Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

## Table of Contents

- [What's new (2026-06-19) — Memory & Determinism](#whats-new-2026-06-19--memory--determinism)
- [What's new (2026-06-19) — Office I/O](#whats-new-2026-06-19--office-io)
- [What's new (2026-06-19) — Agent Toolkit](#whats-new-2026-06-19--agent-toolkit)
- [What's new (2026-06-19) — Authoring & Debugging](#whats-new-2026-06-19--authoring--debugging)
Expand Down Expand Up @@ -67,6 +68,13 @@

---

## What's new (2026-06-19) — Memory & Determinism

Two pure-stdlib tools from the agent/QA research round, full stack (facade, `AC_*`, MCP, Script Builder). Full reference: [`docs/source/Eng/doc/new_features/v15_features_doc.rst`](docs/source/Eng/doc/new_features/v15_features_doc.rst).

- **Agent episodic memory** — `AgentMemory` (`AC_memory_remember` / `AC_memory_recall` / `AC_memory_recent` / `AC_memory_forget` / `AC_memory_stats`, `ac_memory_*`): SQLite store of `(goal → trajectory → outcome)` episodes with keyword recall to inject past experience into the planner's context — cross-run learning, no embedding dependency.
- **Deterministic run** — `DeterministicRun` / `seed_everything` (`AC_seed_everything`, `ac_seed_everything`): pin the RNG seed and freeze `time.time` for a `with` block (recording the choices for replay) to kill time/randomness flakiness; `time.monotonic` left intact so timeouts still work.

## What's new (2026-06-19) — Office I/O

Headless read/write for Excel/Word/PowerPoint, full stack (facade, `AC_*`, MCP, Script Builder). Optional extra: `pip install je_auto_control[office]`. Full reference: [`docs/source/Eng/doc/new_features/v14_features_doc.rst`](docs/source/Eng/doc/new_features/v14_features_doc.rst).
Expand Down
8 changes: 8 additions & 0 deletions README/README_zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

## 目录

- [本次更新 (2026-06-19) — 记忆与确定性](#本次更新-2026-06-19--记忆与确定性)
- [本次更新 (2026-06-19) — Office 读写](#本次更新-2026-06-19--office-读写)
- [本次更新 (2026-06-19) — Agent 工具组](#本次更新-2026-06-19--agent-工具组)
- [本次更新 (2026-06-19) — 编写与调试](#本次更新-2026-06-19--编写与调试)
Expand Down Expand Up @@ -66,6 +67,13 @@

---

## 本次更新 (2026-06-19) — 记忆与确定性

由 agent/QA 研究轮找出的两项纯标准库工具,走完整五层(facade、`AC_*`、MCP、Script Builder)。完整参考:[`docs/source/Zh/doc/new_features/v15_features_doc.rst`](../docs/source/Zh/doc/new_features/v15_features_doc.rst)。

- **Agent 情节记忆** — `AgentMemory`(`AC_memory_remember` / `AC_memory_recall` / `AC_memory_recent` / `AC_memory_forget` / `AC_memory_stats`、`ac_memory_*`):以 SQLite 存储 `(目标 → 轨迹 → 结果)` 情节,依关键字召回过往经验注入规划器上下文——跨执行学习,免向量依赖。
- **确定性执行** — `DeterministicRun` / `seed_everything`(`AC_seed_everything`、`ac_seed_everything`):在 `with` 块内固定 RNG 种子并冻结 `time.time`(记录选择以便重现),消除时间/随机造成的不稳定;`time.monotonic` 保持不变,超时仍正常。

## 本次更新 (2026-06-19) — Office 读写

Excel/Word/PowerPoint 的 headless 读写,走完整五层(facade、`AC_*`、MCP、Script Builder)。可选 extra:`pip install je_auto_control[office]`。完整参考:[`docs/source/Zh/doc/new_features/v14_features_doc.rst`](../docs/source/Zh/doc/new_features/v14_features_doc.rst)。
Expand Down
8 changes: 8 additions & 0 deletions README/README_zh-TW.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

## 目錄

- [本次更新 (2026-06-19) — 記憶與決定性](#本次更新-2026-06-19--記憶與決定性)
- [本次更新 (2026-06-19) — Office 讀寫](#本次更新-2026-06-19--office-讀寫)
- [本次更新 (2026-06-19) — Agent 工具組](#本次更新-2026-06-19--agent-工具組)
- [本次更新 (2026-06-19) — 編寫與除錯](#本次更新-2026-06-19--編寫與除錯)
Expand Down Expand Up @@ -66,6 +67,13 @@

---

## 本次更新 (2026-06-19) — 記憶與決定性

由 agent/QA 研究輪找出的兩項純標準庫工具,走完整五層(facade、`AC_*`、MCP、Script Builder)。完整參考:[`docs/source/Zh/doc/new_features/v15_features_doc.rst`](../docs/source/Zh/doc/new_features/v15_features_doc.rst)。

- **Agent 情節記憶** — `AgentMemory`(`AC_memory_remember` / `AC_memory_recall` / `AC_memory_recent` / `AC_memory_forget` / `AC_memory_stats`、`ac_memory_*`):以 SQLite 儲存 `(目標 → 軌跡 → 結果)` 情節,依關鍵字召回過往經驗注入規劃器脈絡——跨執行學習,免向量相依。
- **決定性執行** — `DeterministicRun` / `seed_everything`(`AC_seed_everything`、`ac_seed_everything`):在 `with` 區塊內固定 RNG 種子並凍結 `time.time`(記錄選擇以便重現),消除時間/隨機造成的不穩定;`time.monotonic` 保持不變,逾時仍正常。

## 本次更新 (2026-06-19) — Office 讀寫

Excel/Word/PowerPoint 的 headless 讀寫,走完整五層(facade、`AC_*`、MCP、Script Builder)。可選 extra:`pip install je_auto_control[office]`。完整參考:[`docs/source/Zh/doc/new_features/v14_features_doc.rst`](../docs/source/Zh/doc/new_features/v14_features_doc.rst)。
Expand Down
61 changes: 61 additions & 0 deletions docs/source/Eng/doc/new_features/v15_features_doc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
==================================================
New Features (2026-06-19) — Memory & Determinism
==================================================

Two pure-standard-library tools surfaced by the agent / QA research round,
wired through the full stack (facade, ``AC_*`` executor commands, MCP
tools, Script Builder): a persistent **agent episodic memory** store and a
**deterministic run** harness.

.. contents::
:local:
:depth: 2


Agent episodic memory
====================

An agent that re-derives "how do I log in to this app" every run wastes
tokens and repeats mistakes. :class:`AgentMemory` records each episode —
the goal, the trajectory (steps / tool-calls), and the outcome — to a
SQLite file, and recalls the most relevant past episodes by keyword so they
can be injected into the planner's context::

from je_auto_control import AgentMemory

mem = AgentMemory("agent.memory.db")
mem.remember("log in to the billing portal",
steps=recorded_actions, outcome="success", tags=["auth"])

for episode in mem.recall("portal login", limit=3):
... # feed episode.goal / episode.steps back to the planner

Recall scores each episode by term frequency over its goal + tags +
outcome (a dependency-free BM25 stand-in); a vector tier can be added later
without changing the API. Commands: ``AC_memory_remember`` /
``AC_memory_recall`` / ``AC_memory_recent`` / ``AC_memory_forget`` /
``AC_memory_stats`` (and the matching ``ac_memory_*`` MCP tools).


Deterministic run
================

Time and randomness are two of the top causes of flaky automation.
:class:`DeterministicRun` pins both for a ``with`` block and records the
choices so a run can be reproduced exactly::

from je_auto_control import DeterministicRun

with DeterministicRun(seed=42, freeze_time=1_750_000_000.0) as run:
... # random.* reproducible; time.time() frozen
manifest = run.manifest() # {"seed": 42, "freeze_time": 1750000000.0}

Scope (pure standard library — no ``freezegun`` dependency): it seeds the
global :mod:`random` generator (and numpy if present) and restores its
state on exit, and patches ``time.time`` / ``time.time_ns`` to a fixed
instant. ``time.monotonic`` is deliberately left alone so duration
measurements and timeouts keep working.

``seed_everything(seed)`` is the standalone seeding helper, also exposed as
``AC_seed_everything`` / ``ac_seed_everything`` for run-wide reproducibility
from a flow.
1 change: 1 addition & 0 deletions docs/source/Eng/eng_index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Comprehensive guides for all AutoControl features.
doc/new_features/v12_features_doc
doc/new_features/v13_features_doc
doc/new_features/v14_features_doc
doc/new_features/v15_features_doc
doc/ocr_backends/ocr_backends_doc
doc/observability/observability_doc
doc/operations_layer/operations_layer_doc
Expand Down
54 changes: 54 additions & 0 deletions docs/source/Zh/doc/new_features/v15_features_doc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
========================================
新功能 (2026-06-19) — 記憶與決定性
========================================

由 agent / QA 研究輪找出的兩項純標準庫工具,走完整五層(facade、
``AC_*`` 執行器指令、MCP 工具、Script Builder):持久化的 **agent
情節記憶**,以及**決定性執行**工具。

.. contents::
:local:
:depth: 2


Agent 情節記憶
==============

每次執行都重新推導「這個 app 怎麼登入」很浪費 token,也會重複犯錯。
:class:`AgentMemory` 把每段情節——目標、軌跡(步驟 / 工具呼叫)、結果
——寫入 SQLite 檔,並依關鍵字召回最相關的過往情節,注入規劃器的脈絡::

from je_auto_control import AgentMemory

mem = AgentMemory("agent.memory.db")
mem.remember("登入帳務入口", steps=recorded_actions,
outcome="success", tags=["auth"])

for episode in mem.recall("入口 登入", limit=3):
... # 把 episode.goal / episode.steps 回饋給規劃器

召回時以目標 + 標籤 + 結果上的詞頻為每段情節評分(免相依的 BM25 替代);
日後可在不改 API 的情況下加上向量層。指令:``AC_memory_remember`` /
``AC_memory_recall`` / ``AC_memory_recent`` / ``AC_memory_forget`` /
``AC_memory_stats``(以及對應的 ``ac_memory_*`` MCP 工具)。


決定性執行
==========

時間與隨機是自動化不穩定(flaky)的兩大主因。:class:`DeterministicRun`
在 ``with`` 區塊內把兩者都固定下來,並記錄選擇以便完全重現::

from je_auto_control import DeterministicRun

with DeterministicRun(seed=42, freeze_time=1_750_000_000.0) as run:
... # random.* 可重現;time.time() 被凍結
manifest = run.manifest() # {"seed": 42, "freeze_time": 1750000000.0}

範圍(純標準庫——不需 ``freezegun``):為全域 :mod:`random` 產生器(若有
numpy 也一併)設種子並於離開時還原狀態,並把 ``time.time`` /
``time.time_ns`` 修補為固定時刻。``time.monotonic`` 刻意保持不變,讓
時間長度量測與逾時仍正常運作。

``seed_everything(seed)`` 是獨立的設種子輔助函式,亦以 ``AC_seed_everything``
/ ``ac_seed_everything`` 形式提供,供流程做全執行重現。
1 change: 1 addition & 0 deletions docs/source/Zh/zh_index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ AutoControl 所有功能的完整使用指南。
doc/new_features/v12_features_doc
doc/new_features/v13_features_doc
doc/new_features/v14_features_doc
doc/new_features/v15_features_doc
doc/ocr_backends/ocr_backends_doc
doc/observability/observability_doc
doc/operations_layer/operations_layer_doc
Expand Down
8 changes: 8 additions & 0 deletions je_auto_control/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,12 @@
read_document, read_presentation, read_workbook,
write_document, write_presentation, write_workbook,
)
# Persistent episodic memory for agents (goal -> trajectory -> outcome)
from je_auto_control.utils.agent_memory import AgentMemory, Episode
# Deterministic run controls (seeded RNG + frozen wall clock)
from je_auto_control.utils.deterministic import (
DeterministicRun, seed_everything,
)
# Background popup/interrupt watchdog (unattended automation)
from je_auto_control.utils.watchdog import (
PopupWatchdog, WatchdogRule, default_popup_watchdog,
Expand Down Expand Up @@ -550,6 +556,8 @@ def start_autocontrol_gui(*args, **kwargs):
"read_workbook", "write_workbook",
"read_document", "write_document",
"read_presentation", "write_presentation",
"AgentMemory", "Episode",
"DeterministicRun", "seed_everything",
# MCP server
"AuditLogger", "HttpMCPServer", "MCPContent", "MCPPrompt",
"MCPPromptArgument", "MCPResource", "MCPServer", "MCPTool",
Expand Down
39 changes: 39 additions & 0 deletions je_auto_control/gui/script_builder/command_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,45 @@ def _add_misc_specs(specs: List[CommandSpec]) -> None:
_add_authoring_specs(specs)
_add_agent_specs(specs)
_add_office_specs(specs)
_add_memory_specs(specs)


def _add_memory_specs(specs: List[CommandSpec]) -> None:
db = FieldSpec("db", FieldType.FILE_PATH)
specs.append(CommandSpec(
"AC_memory_remember", "Agent", "Memory: Remember Episode",
fields=(db, FieldSpec("goal", FieldType.STRING),
FieldSpec("outcome", FieldType.STRING, optional=True)),
description="Store an episode (goal -> 'steps' via JSON view -> "
"outcome).",
))
specs.append(CommandSpec(
"AC_memory_recall", "Agent", "Memory: Recall",
fields=(db, FieldSpec("query", FieldType.STRING),
FieldSpec("limit", FieldType.INT, optional=True, default=5)),
description="Recall episodes most relevant to a query.",
))
specs.append(CommandSpec(
"AC_memory_recent", "Agent", "Memory: Recent",
fields=(db, FieldSpec("limit", FieldType.INT, optional=True,
default=10)),
description="List the most recent episodes.",
))
specs.append(CommandSpec(
"AC_memory_forget", "Agent", "Memory: Forget",
fields=(db, FieldSpec("episode_id", FieldType.INT)),
description="Delete an episode by id.",
))
specs.append(CommandSpec(
"AC_memory_stats", "Agent", "Memory: Stats",
fields=(db,),
description="Episode count for a memory store.",
))
specs.append(CommandSpec(
"AC_seed_everything", "Flow", "Seed RNG (deterministic)",
fields=(FieldSpec("seed", FieldType.INT, optional=True, default=0),),
description="Seed all RNG run-wide for reproducible runs.",
))


def _add_office_specs(specs: List[CommandSpec]) -> None:
Expand Down
6 changes: 6 additions & 0 deletions je_auto_control/utils/agent_memory/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"""Persistent episodic memory for agents (goal -> trajectory -> outcome)."""
from je_auto_control.utils.agent_memory.agent_memory import (
AgentMemory, Episode,
)

__all__ = ["AgentMemory", "Episode"]
Loading
Loading