Skip to content

Commit 7c4d75f

Browse files
authored
Merge pull request #256 from Integration-Automation/feat/assets-batch
Add environment-scoped typed asset store
2 parents c98fe41 + d1ace35 commit 7c4d75f

18 files changed

Lines changed: 550 additions & 20 deletions

File tree

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
## Table of Contents
1515

16+
- [What's new (2026-06-20) — Environment-Scoped Typed Asset Store](#whats-new-2026-06-20--environment-scoped-typed-asset-store)
1617
- [What's new (2026-06-20) — Task / Process Mining (Automation-Candidate Discovery)](#whats-new-2026-06-20--task--process-mining-automation-candidate-discovery)
1718
- [What's new (2026-06-20) — Stuck-Loop Guard (Agent Loop Progress Detection)](#whats-new-2026-06-20--stuck-loop-guard-agent-loop-progress-detection)
1819
- [What's new (2026-06-20) — Coordinate-Space Mapping (Model Grid ⇄ Physical Pixels)](#whats-new-2026-06-20--coordinate-space-mapping-model-grid--physical-pixels)
@@ -100,6 +101,12 @@
100101

101102
---
102103

104+
## What's new (2026-06-20) — Environment-Scoped Typed Asset Store
105+
106+
Per-environment typed config + credential refs. Full reference: [`docs/source/Eng/doc/new_features/v48_features_doc.rst`](docs/source/Eng/doc/new_features/v48_features_doc.rst).
107+
108+
- **`AssetStore` / `active_environment`** (`AC_set_asset` / `AC_get_asset` / `AC_list_assets`, `ac_*`): the orchestrator "Assets/lockers" pillar — centrally-managed config values that differ by environment (dev/staging/prod) and carry a type (`text`/`int`/`bool`/`credential`). `get` coerces to the declared type and falls back to the default env; `credential` assets hold a secret *reference* that `resolve` turns into the real value via an injected resolver (Python-only, so secrets never enter `get`/executor records). Fills the gap the secret vault (secret-only) and config-sync (whole-blob) left.
109+
103110
## What's new (2026-06-20) — Task / Process Mining (Automation-Candidate Discovery)
104111

105112
Discover what to automate from recorded action logs. Full reference: [`docs/source/Eng/doc/new_features/v47_features_doc.rst`](docs/source/Eng/doc/new_features/v47_features_doc.rst).

README/README_zh-CN.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
## 目录
1414

15+
- [本次更新 (2026-06-20) — 环境范围的带类型资产存储](#本次更新-2026-06-20--环境范围的带类型资产存储)
1516
- [本次更新 (2026-06-20) — 任务 / 流程挖掘(自动化候选发现)](#本次更新-2026-06-20--任务--流程挖掘自动化候选发现)
1617
- [本次更新 (2026-06-20) — 卡循环守卫(Agent Loop 进度检测)](#本次更新-2026-06-20--卡循环守卫agent-loop-进度检测)
1718
- [本次更新 (2026-06-20) — 坐标空间映射(模型网格 ⇄ 物理像素)](#本次更新-2026-06-20--坐标空间映射模型网格--物理像素)
@@ -99,6 +100,12 @@
99100

100101
---
101102

103+
## 本次更新 (2026-06-20) — 环境范围的带类型资产存储
104+
105+
依环境的带类型配置 + credential 引用。完整参考:[`docs/source/Zh/doc/new_features/v48_features_doc.rst`](../docs/source/Zh/doc/new_features/v48_features_doc.rst)
106+
107+
- **`AssetStore` / `active_environment`**(`AC_set_asset` / `AC_get_asset` / `AC_list_assets``ac_*`):orchestrator 的「Assets/lockers」支柱 —— 集中管理、依环境(dev/staging/prod)而异且带类型(`text`/`int`/`bool`/`credential`)的配置值。`get` 转成声明类型并退回 default 环境;`credential` 资产持有密钥*引用*,由 `resolve` 通过注入解析器转成真实值(仅限 Python,因此密钥永不进入 `get`/executor 记录)。补足密钥保险库(仅密钥)与 config-sync(整块)的缺口。
108+
102109
## 本次更新 (2026-06-20) — 任务 / 流程挖掘(自动化候选发现)
103110

104111
从录制的动作日志发现该自动化什么。完整参考:[`docs/source/Zh/doc/new_features/v47_features_doc.rst`](../docs/source/Zh/doc/new_features/v47_features_doc.rst)

README/README_zh-TW.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
## 目錄
1414

15+
- [本次更新 (2026-06-20) — 環境範圍的具型別資產儲存](#本次更新-2026-06-20--環境範圍的具型別資產儲存)
1516
- [本次更新 (2026-06-20) — 任務 / 流程探勘(自動化候選發現)](#本次更新-2026-06-20--任務--流程探勘自動化候選發現)
1617
- [本次更新 (2026-06-20) — 卡迴圈守衛(Agent Loop 進度偵測)](#本次更新-2026-06-20--卡迴圈守衛agent-loop-進度偵測)
1718
- [本次更新 (2026-06-20) — 座標空間對映(模型網格 ⇄ 實體像素)](#本次更新-2026-06-20--座標空間對映模型網格--實體像素)
@@ -99,6 +100,12 @@
99100

100101
---
101102

103+
## 本次更新 (2026-06-20) — 環境範圍的具型別資產儲存
104+
105+
依環境的具型別設定 + credential 參照。完整參考:[`docs/source/Zh/doc/new_features/v48_features_doc.rst`](../docs/source/Zh/doc/new_features/v48_features_doc.rst)
106+
107+
- **`AssetStore` / `active_environment`**(`AC_set_asset` / `AC_get_asset` / `AC_list_assets``ac_*`):orchestrator 的「Assets/lockers」支柱 —— 集中管理、依環境(dev/staging/prod)而異且帶型別(`text`/`int`/`bool`/`credential`)的設定值。`get` 轉成宣告型別並退回 default 環境;`credential` 資產持有密鑰*參照*,由 `resolve` 透過注入解析器轉成真實值(僅限 Python,因此密鑰永不進入 `get`/executor 紀錄)。補足密鑰保險庫(僅密鑰)與 config-sync(整塊)的缺口。
108+
102109
## 本次更新 (2026-06-20) — 任務 / 流程探勘(自動化候選發現)
103110

104111
從錄製的動作日誌發現該自動化什麼。完整參考:[`docs/source/Zh/doc/new_features/v47_features_doc.rst`](../docs/source/Zh/doc/new_features/v47_features_doc.rst)
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
Environment-Scoped Typed Asset Store
2+
====================================
3+
4+
Flows need centrally-managed config values that differ by environment
5+
(dev/staging/prod) and carry a type — the orchestrator "Assets / lockers"
6+
pillar. The secret vault covers secrets only and config-sync moves whole blobs;
7+
neither offers a typed, per-environment named lookup. ``AssetStore`` fills that:
8+
values are stored under an environment, read back with type coercion, and
9+
``credential`` assets hold a *reference* (a secret name) that :meth:`resolve`
10+
turns into the real value through an injected resolver — so the secret never
11+
lands in a plain ``get`` or an executor record.
12+
13+
JSON-backed (or in-memory); pure standard library; imports no ``PySide6``.
14+
15+
Headless API
16+
------------
17+
18+
.. code-block:: python
19+
20+
from je_auto_control import AssetStore, active_environment
21+
22+
store = AssetStore("assets.json")
23+
store.set("max_retries", 3, asset_type="int", environment="prod")
24+
store.set("api_base", "https://prod.example.com", environment="prod")
25+
store.set("db_password", "vault_db_pw", asset_type="credential") # value = a ref
26+
27+
store.get("max_retries", environment="prod").value # -> 3 (typed)
28+
store.get("api_base", environment="staging").value # -> falls back to default
29+
store.get("db_password").value # -> "vault_db_pw" (reference, safe)
30+
31+
# resolve a credential through an injected secret resolver (Python-only):
32+
store = AssetStore("assets.json", secret_resolver=secret_manager.get)
33+
store.resolve("db_password") # -> the real secret
34+
35+
Types are ``text`` / ``int`` / ``bool`` / ``credential``; ``get`` coerces to the
36+
declared type and falls back to the ``default`` environment unless disabled.
37+
``active_environment()`` reads ``JE_AUTOCONTROL_ENV``. ``list`` / ``delete`` round
38+
out the store.
39+
40+
Executor commands
41+
-----------------
42+
43+
================================ ===================================================
44+
Command Effect
45+
================================ ===================================================
46+
``AC_set_asset`` Store a typed, environment-scoped asset.
47+
``AC_get_asset`` Read an asset (credential stays a reference).
48+
``AC_list_assets`` List ``{name, type, environment}`` (no values).
49+
================================ ===================================================
50+
51+
Credential **resolution** is intentionally Python-API-only (so secrets never
52+
enter run records). The same lifecycle operations are exposed as MCP tools
53+
(``ac_set_asset`` / ``ac_get_asset`` / ``ac_list_assets``) and as Script Builder
54+
commands under **Data**.

docs/source/Eng/eng_index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ Comprehensive guides for all AutoControl features.
7070
doc/new_features/v45_features_doc
7171
doc/new_features/v46_features_doc
7272
doc/new_features/v47_features_doc
73+
doc/new_features/v48_features_doc
7374
doc/ocr_backends/ocr_backends_doc
7475
doc/observability/observability_doc
7576
doc/operations_layer/operations_layer_doc
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
環境範圍的具型別資產儲存
2+
========================
3+
4+
流程需要集中管理、依環境(dev/staging/prod)而異且帶有型別的設定值 —— 這是 orchestrator
5+
的「Assets / lockers」支柱。密鑰保險庫只處理密鑰,config-sync 搬移整塊設定;兩者皆無具
6+
型別、依環境的具名查詢。``AssetStore`` 補足此處:值依環境儲存、讀回時做型別轉換,而
7+
``credential`` 資產持有一個*參照*(密鑰名稱),由 :meth:`resolve` 透過注入的解析器轉成
8+
真實值 —— 因此密鑰永不出現在純 ``get`` 或 executor 紀錄中。
9+
10+
JSON 後端(或記憶體內);純標準函式庫;不匯入 ``PySide6``。
11+
12+
無頭 API
13+
--------
14+
15+
.. code-block:: python
16+
17+
from je_auto_control import AssetStore, active_environment
18+
19+
store = AssetStore("assets.json")
20+
store.set("max_retries", 3, asset_type="int", environment="prod")
21+
store.set("api_base", "https://prod.example.com", environment="prod")
22+
store.set("db_password", "vault_db_pw", asset_type="credential") # value = 參照
23+
24+
store.get("max_retries", environment="prod").value # -> 3(具型別)
25+
store.get("api_base", environment="staging").value # -> 退回 default
26+
store.get("db_password").value # -> "vault_db_pw"(參照,安全)
27+
28+
# 透過注入的密鑰解析器解析 credential(僅限 Python):
29+
store = AssetStore("assets.json", secret_resolver=secret_manager.get)
30+
store.resolve("db_password") # -> 真實密鑰
31+
32+
型別為 ``text`` / ``int`` / ``bool`` / ``credential``;``get`` 會轉成宣告型別,並在未停用
33+
時退回 ``default`` 環境。``active_environment()`` 讀取 ``JE_AUTOCONTROL_ENV``。``list`` /
34+
``delete`` 補齊整個儲存體。
35+
36+
執行器指令
37+
----------
38+
39+
================================ ===================================================
40+
指令 效果
41+
================================ ===================================================
42+
``AC_set_asset`` 儲存具型別、依環境的資產。
43+
``AC_get_asset`` 讀取資產(credential 維持參照)。
44+
``AC_list_assets`` 列出 ``{name, type, environment}``(不含值)。
45+
================================ ===================================================
46+
47+
credential 的**解析**刻意僅限 Python API(因此密鑰永不進入執行紀錄)。相同的生命週期操
48+
作亦提供為 MCP 工具(``ac_set_asset`` / ``ac_get_asset`` / ``ac_list_assets``),以及
49+
Script Builder 中 **Data** 分類下的指令。

docs/source/Zh/zh_index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ AutoControl 所有功能的完整使用指南。
7070
doc/new_features/v45_features_doc
7171
doc/new_features/v46_features_doc
7272
doc/new_features/v47_features_doc
73+
doc/new_features/v48_features_doc
7374
doc/ocr_backends/ocr_backends_doc
7475
doc/observability/observability_doc
7576
doc/operations_layer/operations_layer_doc

je_auto_control/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,10 @@
264264
Candidate, MiningReport, SequencePattern, directly_follows,
265265
find_repeated_sequences, mine_action_log, rank_automation_candidates,
266266
)
267+
# Environment-scoped typed asset/config store
268+
from je_auto_control.utils.assets import (
269+
Asset, AssetStore, AssetValue, active_environment,
270+
)
267271
# Background popup/interrupt watchdog (unattended automation)
268272
from je_auto_control.utils.watchdog import (
269273
PopupWatchdog, WatchdogRule, default_popup_watchdog,
@@ -723,6 +727,7 @@ def start_autocontrol_gui(*args, **kwargs):
723727
"Candidate", "MiningReport", "SequencePattern", "directly_follows",
724728
"find_repeated_sequences", "mine_action_log",
725729
"rank_automation_candidates",
730+
"Asset", "AssetStore", "AssetValue", "active_environment",
726731
# MCP server
727732
"AuditLogger", "HttpMCPServer", "MCPContent", "MCPPrompt",
728733
"MCPPromptArgument", "MCPResource", "MCPServer", "MCPTool",

je_auto_control/gui/script_builder/command_schema.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,6 +1067,38 @@ def _add_misc_specs(specs: List[CommandSpec]) -> None:
10671067
),
10681068
description="Find repeated sequences + rank automation candidates.",
10691069
))
1070+
specs.append(CommandSpec(
1071+
"AC_set_asset", "Data", "Asset: Set",
1072+
fields=(
1073+
FieldSpec("name", FieldType.STRING),
1074+
FieldSpec("value", FieldType.STRING),
1075+
FieldSpec("asset_type", FieldType.ENUM, optional=True,
1076+
default="text",
1077+
choices=("text", "int", "bool", "credential")),
1078+
FieldSpec("environment", FieldType.STRING, optional=True,
1079+
default="default"),
1080+
FieldSpec("db", FieldType.STRING, optional=True),
1081+
),
1082+
description="Store a typed, environment-scoped asset.",
1083+
))
1084+
specs.append(CommandSpec(
1085+
"AC_get_asset", "Data", "Asset: Get",
1086+
fields=(
1087+
FieldSpec("name", FieldType.STRING),
1088+
FieldSpec("environment", FieldType.STRING, optional=True,
1089+
default="default"),
1090+
FieldSpec("db", FieldType.STRING, optional=True),
1091+
),
1092+
description="Read a typed asset (credential stays a reference).",
1093+
))
1094+
specs.append(CommandSpec(
1095+
"AC_list_assets", "Data", "Asset: List",
1096+
fields=(
1097+
FieldSpec("environment", FieldType.STRING, optional=True),
1098+
FieldSpec("db", FieldType.STRING, optional=True),
1099+
),
1100+
description="List assets (name/type/environment, no values).",
1101+
))
10701102
specs.append(CommandSpec(
10711103
"AC_generate_sop", "Report", "Generate SOP Document",
10721104
fields=(
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
"""Environment-scoped typed asset/config store (UiPath-Assets style)."""
2+
from je_auto_control.utils.assets.assets import (
3+
Asset, AssetStore, AssetValue, active_environment,
4+
)
5+
6+
__all__ = ["Asset", "AssetStore", "AssetValue", "active_environment"]

0 commit comments

Comments
 (0)