@actiondock/core 2.5.1 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/app.d.ts +14 -1
- package/dist/app/app.js +88 -222
- package/dist/app/static-index.d.ts +39 -0
- package/dist/app/static-index.js +164 -0
- package/dist/app/types.d.ts +5 -0
- package/dist/catalog/action-index.js +6 -4
- package/dist/catalog/package-catalog.js +2 -1
- package/dist/doctor/checks/index.d.ts +5 -0
- package/dist/doctor/checks/index.js +5 -0
- package/dist/doctor/checks/project-locate.d.ts +6 -0
- package/dist/doctor/checks/project-locate.js +36 -0
- package/dist/doctor/checks/project.d.ts +6 -0
- package/dist/doctor/checks/project.js +383 -0
- package/dist/doctor/checks/registry.d.ts +13 -0
- package/dist/doctor/checks/registry.js +207 -0
- package/dist/doctor/checks/runtime.d.ts +13 -0
- package/dist/doctor/checks/runtime.js +90 -0
- package/dist/doctor/checks/storage.d.ts +5 -0
- package/dist/doctor/checks/storage.js +34 -0
- package/dist/doctor/context.d.ts +35 -0
- package/dist/doctor/context.js +11 -0
- package/dist/doctor/doctor.d.ts +5 -0
- package/dist/doctor/doctor.js +33 -602
- package/dist/errors.d.ts +22 -0
- package/dist/errors.js +22 -0
- package/dist/execution/service.js +14 -9
- package/dist/export/templates.js +42 -30
- package/dist/host/host.d.ts +33 -0
- package/dist/host/host.js +222 -362
- package/dist/host/routing.d.ts +92 -0
- package/dist/host/routing.js +238 -0
- package/dist/host/types.d.ts +8 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -1
- package/dist/input/advice.d.ts +100 -0
- package/dist/input/advice.js +767 -0
- package/dist/input/describe.d.ts +106 -0
- package/dist/input/describe.js +176 -0
- package/dist/input/file-input.d.ts +54 -0
- package/dist/input/file-input.js +124 -0
- package/dist/input/flat-decode.d.ts +11 -0
- package/dist/input/flat-decode.js +13 -0
- package/dist/input/flat-errors.d.ts +72 -0
- package/dist/input/flat-errors.js +87 -0
- package/dist/input/flat-materializer.d.ts +29 -0
- package/dist/input/flat-materializer.js +179 -0
- package/dist/input/flat-parser.d.ts +50 -0
- package/dist/input/flat-parser.js +169 -0
- package/dist/input/flat-predicates.d.ts +34 -0
- package/dist/input/flat-predicates.js +50 -0
- package/dist/input/index.d.ts +14 -0
- package/dist/input/index.js +14 -0
- package/dist/input/input-resolver.d.ts +63 -0
- package/dist/input/input-resolver.js +254 -0
- package/dist/input/json-depth-scanner.d.ts +17 -0
- package/dist/input/json-depth-scanner.js +49 -0
- package/dist/input/metadata.d.ts +99 -0
- package/dist/input/metadata.js +99 -0
- package/dist/input/stdin-input.d.ts +26 -0
- package/dist/input/stdin-input.js +125 -0
- package/dist/input/utf8.d.ts +19 -0
- package/dist/input/utf8.js +36 -0
- package/dist/input/validation-mapper.d.ts +27 -0
- package/dist/input/validation-mapper.js +144 -0
- package/dist/ipc/host.js +38 -0
- package/dist/json/index.d.ts +1 -0
- package/dist/json/index.js +1 -0
- package/dist/json/value-validator.d.ts +88 -0
- package/dist/json/value-validator.js +330 -0
- package/dist/platform/types.d.ts +7 -0
- package/dist/process/control-arbiter.d.ts +107 -0
- package/dist/process/control-arbiter.js +251 -0
- package/dist/process/diagnostics-sink.d.ts +26 -0
- package/dist/process/diagnostics-sink.js +35 -0
- package/dist/process/index.d.ts +7 -0
- package/dist/process/index.js +7 -0
- package/dist/process/input-dispatcher.d.ts +88 -0
- package/dist/process/input-dispatcher.js +240 -0
- package/dist/process/managed-record.d.ts +78 -0
- package/dist/process/managed-record.js +1 -0
- package/dist/process/process-manager.d.ts +15 -56
- package/dist/process/process-manager.js +119 -707
- package/dist/process/reservation-table.d.ts +39 -0
- package/dist/process/reservation-table.js +80 -0
- package/dist/process/run-executor.d.ts +16 -0
- package/dist/process/run-executor.js +155 -0
- package/dist/process/terminal-output-cache.d.ts +66 -0
- package/dist/process/terminal-output-cache.js +132 -0
- package/dist/profile/client-actions.d.ts +56 -0
- package/dist/profile/client-actions.js +215 -0
- package/dist/profile/client-config.d.ts +20 -0
- package/dist/profile/client-config.js +51 -0
- package/dist/profile/client-health.d.ts +14 -0
- package/dist/profile/client-health.js +69 -0
- package/dist/profile/client-playbooks.d.ts +19 -0
- package/dist/profile/client-playbooks.js +36 -0
- package/dist/profile/client-query.d.ts +30 -0
- package/dist/profile/client-query.js +70 -0
- package/dist/profile/client-runs.d.ts +42 -0
- package/dist/profile/client-runs.js +58 -0
- package/dist/profile/client-state.d.ts +56 -0
- package/dist/profile/client-state.js +83 -0
- package/dist/profile/client-transport.d.ts +61 -0
- package/dist/profile/client-transport.js +156 -0
- package/dist/profile/client.d.ts +23 -142
- package/dist/profile/client.js +28 -588
- package/dist/profile/manager.js +1 -1
- package/dist/project/closure.d.ts +4 -4
- package/dist/project/closure.js +11 -5
- package/dist/project/init.js +2 -2
- package/dist/project/loader.d.ts +0 -25
- package/dist/project/loader.js +1 -154
- package/dist/project/transactions.d.ts +12 -14
- package/dist/project/transactions.js +60 -836
- package/dist/registry/registry.js +6 -4
- package/dist/registry/resolve.js +1 -1
- package/dist/runtime/action-registry.d.ts +45 -0
- package/dist/runtime/action-registry.js +108 -0
- package/dist/runtime/clock.d.ts +5 -17
- package/dist/runtime/clock.js +5 -15
- package/dist/runtime/context.d.ts +3 -0
- package/dist/runtime/context.js +17 -56
- package/dist/runtime/index.d.ts +3 -0
- package/dist/runtime/index.js +3 -0
- package/dist/runtime/package-runner-factory.d.ts +82 -0
- package/dist/runtime/package-runner-factory.js +186 -0
- package/dist/runtime/run-persistence.d.ts +85 -0
- package/dist/runtime/run-persistence.js +111 -0
- package/dist/runtime/runner.d.ts +25 -45
- package/dist/runtime/runner.js +130 -354
- package/dist/runtime/standalone.d.ts +25 -2
- package/dist/runtime/standalone.js +305 -87
- package/dist/schema/index.d.ts +1 -0
- package/dist/schema/index.js +1 -0
- package/dist/schema/validator.d.ts +10 -0
- package/dist/schema/validator.js +48 -54
- package/dist/server/dispatcher.d.ts +8 -3
- package/dist/server/dispatcher.js +16 -40
- package/dist/server/routes/runs.js +6 -4
- package/dist/server/security.d.ts +1 -7
- package/dist/server/security.js +2 -13
- package/dist/storage/clock.d.ts +25 -0
- package/dist/storage/clock.js +23 -0
- package/dist/storage/data-dir-lock.d.ts +3 -36
- package/dist/storage/data-dir-lock.js +48 -881
- package/dist/storage/index.d.ts +8 -1
- package/dist/storage/index.js +8 -2
- package/dist/storage/lazy.js +1 -0
- package/dist/storage/lock-core.d.ts +162 -0
- package/dist/storage/lock-core.js +885 -0
- package/dist/storage/sqlite.d.ts +19 -6
- package/dist/storage/sqlite.js +81 -89
- package/dist/storage/types.d.ts +27 -5
- package/dist/storage/types.js +21 -0
- package/dist/storage/utils.d.ts +22 -0
- package/dist/storage/utils.js +34 -0
- package/dist/target/local.d.ts +1 -0
- package/dist/target/local.js +23 -17
- package/dist/target/remote-errors.d.ts +21 -0
- package/dist/target/remote-errors.js +51 -0
- package/dist/target/remote-polling.d.ts +35 -0
- package/dist/target/remote-polling.js +104 -0
- package/dist/target/remote.d.ts +4 -0
- package/dist/target/remote.js +108 -301
- package/dist/target/sse-parser.d.ts +35 -0
- package/dist/target/sse-parser.js +163 -0
- package/dist/target/target.js +2 -0
- package/dist/target/types.d.ts +6 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/net.d.ts +10 -0
- package/dist/utils/net.js +16 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
package/dist/app/app.d.ts
CHANGED
|
@@ -22,14 +22,19 @@ export declare class DefaultActionDockApp implements ActionDockApp {
|
|
|
22
22
|
private readonly options;
|
|
23
23
|
private runtimeConfig;
|
|
24
24
|
private isClosed;
|
|
25
|
+
/** 静态清单索引缓存:包静态事实(根目录、配置、内存注入集合)在实例生命周期内不变,解析结果同实例内复用 */
|
|
26
|
+
private staticActionIndex?;
|
|
27
|
+
private staticPlaybookIndex?;
|
|
25
28
|
constructor(options?: ActionDockAppOptions);
|
|
26
29
|
/**
|
|
27
30
|
* 静态读取并聚合当前包的 Action 规范索引。
|
|
28
|
-
*
|
|
31
|
+
* 聚合逻辑委托 static-index 单一事实源;同实例内复用首次解析结果,
|
|
32
|
+
* 消除重复查询单次调用内的重复读盘(磁盘清单在实例生命周期内视为静态事实)。
|
|
29
33
|
*/
|
|
30
34
|
private getStaticActionMap;
|
|
31
35
|
/**
|
|
32
36
|
* 静态读取并聚合当前包的 Playbook 规范索引。
|
|
37
|
+
* 聚合逻辑委托 static-index 单一事实源;同实例内复用首次解析结果。
|
|
33
38
|
*/
|
|
34
39
|
private getStaticPlaybookMap;
|
|
35
40
|
info(options?: {
|
|
@@ -52,6 +57,14 @@ export declare class DefaultActionDockApp implements ActionDockApp {
|
|
|
52
57
|
getConfig(key: string): Promise<ConfigValueView>;
|
|
53
58
|
setConfig(key: string, value: JsonValue): Promise<void>;
|
|
54
59
|
deleteConfig(key: string): Promise<boolean>;
|
|
60
|
+
/**
|
|
61
|
+
* 状态作用域统一解析辅助函数(单一事实源)。
|
|
62
|
+
*
|
|
63
|
+
* 完成重载消歧与 actionId 冲突校验,返回最终生效的命名空间:
|
|
64
|
+
* - actionId 存在时拼 接 `${actionId}:${namespace}` 或直接 actionId;
|
|
65
|
+
* - 无 actionId 时返回显式 namespace 或空字符串(包级扁平状态)。
|
|
66
|
+
*/
|
|
67
|
+
private resolveStateScope;
|
|
55
68
|
getState<T extends JsonValue = JsonValue>(key: string, options?: StateScopeOptions): Promise<T | undefined>;
|
|
56
69
|
getState<T extends JsonValue = JsonValue>(actionId: string, key: string, options?: StateScopeOptions): Promise<T | undefined>;
|
|
57
70
|
setState<T extends JsonValue = JsonValue>(key: string, value: T, options?: StateScopeOptions): Promise<void>;
|
package/dist/app/app.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { existsSync
|
|
2
|
-
import { join
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
3
|
import { DefaultExecutionService } from "../execution/service.js";
|
|
4
4
|
import { createDefaultPlatform } from "../platform/index.js";
|
|
5
|
-
import { findProjectRoot,
|
|
6
|
-
import { loadManifest } from "../project/manifest.js";
|
|
5
|
+
import { findProjectRoot, loadProjectConfig } from "../project/loader.js";
|
|
7
6
|
import { RuntimeConfig } from "../runtime/context.js";
|
|
8
7
|
import { normalizeActionCollection } from "../runtime/action-collection.js";
|
|
9
8
|
import { createGlobalStorage, createLazyStorage, createStorage } from "../storage/index.js";
|
|
10
9
|
import { isSecretConfigKey, sanitizeConfigDefinitions } from "../storage/mask.js";
|
|
11
10
|
import { decodeStateKey, SqliteRuntimeStorage } from "../storage/sqlite.js";
|
|
11
|
+
import { buildStaticActionMap, buildStaticPlaybookMap } from "./static-index.js";
|
|
12
12
|
/**
|
|
13
13
|
* ActionDock 统一应用默认实现。
|
|
14
14
|
* 封装并管理单个 Action Package 的执行引擎、静态元数据索引、配置与状态存储生命周期。
|
|
@@ -27,6 +27,9 @@ export class DefaultActionDockApp {
|
|
|
27
27
|
options;
|
|
28
28
|
runtimeConfig;
|
|
29
29
|
isClosed = false;
|
|
30
|
+
/** 静态清单索引缓存:包静态事实(根目录、配置、内存注入集合)在实例生命周期内不变,解析结果同实例内复用 */
|
|
31
|
+
staticActionIndex;
|
|
32
|
+
staticPlaybookIndex;
|
|
30
33
|
constructor(options = {}) {
|
|
31
34
|
this.options = options;
|
|
32
35
|
// 1. 确定项目根路径与配置对象
|
|
@@ -41,12 +44,9 @@ export class DefaultActionDockApp {
|
|
|
41
44
|
if (!projectConfig && packageRoot) {
|
|
42
45
|
const configPath = join(packageRoot, "actiondock.json");
|
|
43
46
|
if (existsSync(configPath)) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
catch {
|
|
48
|
-
// 忽略解析失败,使用回退配置
|
|
49
|
-
}
|
|
47
|
+
// 文件存在但解析失败(损坏 JSON、校验失败)时直接向上抛出:
|
|
48
|
+
// 仅当确实不存在 actiondock.json 文件时才允许回退默认配置,杜绝幽灵包配置
|
|
49
|
+
projectConfig = loadProjectConfig(packageRoot);
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
if (!projectConfig) {
|
|
@@ -75,6 +75,9 @@ export class DefaultActionDockApp {
|
|
|
75
75
|
dataDir: options.dataDir,
|
|
76
76
|
customHome: options.customHome,
|
|
77
77
|
inMemory: options.inMemory,
|
|
78
|
+
// 默认持有者语义:App 主路径打开时收割死亡会话遗留非终态运行记录;
|
|
79
|
+
// CLI 查询旁观视图显式置 recoverOrphans: false 跳过收割
|
|
80
|
+
recoverOrphans: options.recoverOrphans !== false,
|
|
78
81
|
};
|
|
79
82
|
const storageFactory = this.platform.storage;
|
|
80
83
|
const initStorage = () => {
|
|
@@ -113,6 +116,8 @@ export class DefaultActionDockApp {
|
|
|
113
116
|
customHome: options.customHome,
|
|
114
117
|
dataDir: options.dataDir,
|
|
115
118
|
inMemory: options.inMemory,
|
|
119
|
+
// 与主存储保持同侧收割语义(全局库 runs 表为空集,收割无实际副作用)
|
|
120
|
+
recoverOrphans: options.recoverOrphans !== false,
|
|
116
121
|
};
|
|
117
122
|
const storageFactory = this.platform.storage;
|
|
118
123
|
const initGlobalStorage = () => {
|
|
@@ -153,142 +158,33 @@ export class DefaultActionDockApp {
|
|
|
153
158
|
}
|
|
154
159
|
/**
|
|
155
160
|
* 静态读取并聚合当前包的 Action 规范索引。
|
|
156
|
-
*
|
|
161
|
+
* 聚合逻辑委托 static-index 单一事实源;同实例内复用首次解析结果,
|
|
162
|
+
* 消除重复查询单次调用内的重复读盘(磁盘清单在实例生命周期内视为静态事实)。
|
|
157
163
|
*/
|
|
158
164
|
getStaticActionMap() {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
try {
|
|
163
|
-
const manifest = loadManifest(this.packageRoot);
|
|
164
|
-
if (manifest?.actions) {
|
|
165
|
-
for (const [id, item] of Object.entries(manifest.actions)) {
|
|
166
|
-
map.set(id, {
|
|
167
|
-
id,
|
|
168
|
-
packageId: this.packageId,
|
|
169
|
-
description: item.description,
|
|
170
|
-
inputSchema: item.inputSchema,
|
|
171
|
-
outputSchema: item.outputSchema,
|
|
172
|
-
tags: item.tags ? [...item.tags] : [],
|
|
173
|
-
annotations: item.annotations,
|
|
174
|
-
uses: item.uses ? [...item.uses] : [],
|
|
175
|
-
entry: item.entry,
|
|
176
|
-
filePath: item.entry ? resolve(this.packageRoot, item.entry) : undefined,
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
catch {
|
|
182
|
-
// 忽略清单缺失或解析异常
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
// 2. 读取项目配置文件中声明的 actions (Manifest v2 格式)
|
|
186
|
-
if (this.projectConfig && this.projectConfig.actions) {
|
|
187
|
-
const rawActions = this.projectConfig.actions;
|
|
188
|
-
if (typeof rawActions === "object" && rawActions !== null) {
|
|
189
|
-
for (const [id, item] of Object.entries(rawActions)) {
|
|
190
|
-
const existing = map.get(id);
|
|
191
|
-
map.set(id, {
|
|
192
|
-
id,
|
|
193
|
-
packageId: this.packageId,
|
|
194
|
-
description: item.description ?? existing?.description,
|
|
195
|
-
inputSchema: item.inputSchema ?? existing?.inputSchema,
|
|
196
|
-
outputSchema: item.outputSchema ?? existing?.outputSchema,
|
|
197
|
-
tags: item.tags ?? existing?.tags,
|
|
198
|
-
annotations: item.annotations ?? existing?.annotations,
|
|
199
|
-
uses: item.uses ?? existing?.uses,
|
|
200
|
-
entry: item.entry ?? existing?.entry,
|
|
201
|
-
filePath: item.entry && this.packageRoot
|
|
202
|
-
? resolve(this.packageRoot, item.entry)
|
|
203
|
-
: existing?.filePath,
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
// 3. 读取内存显式注入的 Action 定义
|
|
209
|
-
for (const [id, act] of this.actionsMap) {
|
|
210
|
-
// 若为当前包完全限定名别名(例如 "pkgId/actionId"),跳过以防与短名 action 重复
|
|
211
|
-
if (id.startsWith(`${this.packageId}/`)) {
|
|
212
|
-
const shortId = id.slice(this.packageId.length + 1);
|
|
213
|
-
if (this.actionsMap.has(shortId) || map.has(shortId)) {
|
|
214
|
-
continue;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
const existing = map.get(id);
|
|
218
|
-
const actObj = act;
|
|
219
|
-
map.set(id, {
|
|
220
|
-
id,
|
|
165
|
+
if (!this.staticActionIndex) {
|
|
166
|
+
this.staticActionIndex = buildStaticActionMap({
|
|
167
|
+
packageRoot: this.packageRoot,
|
|
221
168
|
packageId: this.packageId,
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
outputSchema: actObj.outputSchema ?? existing?.outputSchema,
|
|
225
|
-
tags: actObj.tags ? [...actObj.tags] : existing?.tags,
|
|
226
|
-
annotations: actObj.annotations ?? existing?.annotations,
|
|
227
|
-
uses: actObj.uses ? [...actObj.uses] : existing?.uses,
|
|
228
|
-
entry: existing?.entry,
|
|
229
|
-
filePath: existing?.filePath,
|
|
169
|
+
projectConfig: this.projectConfig,
|
|
170
|
+
actionsMap: this.actionsMap,
|
|
230
171
|
});
|
|
231
172
|
}
|
|
232
|
-
return
|
|
173
|
+
return this.staticActionIndex;
|
|
233
174
|
}
|
|
234
175
|
/**
|
|
235
176
|
* 静态读取并聚合当前包的 Playbook 规范索引。
|
|
177
|
+
* 聚合逻辑委托 static-index 单一事实源;同实例内复用首次解析结果。
|
|
236
178
|
*/
|
|
237
179
|
getStaticPlaybookMap() {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
try {
|
|
245
|
-
const loaded = loadPlaybooks(this.packageRoot, playbooksDir);
|
|
246
|
-
for (const [id, def] of loaded) {
|
|
247
|
-
map.set(id, {
|
|
248
|
-
id: def.id,
|
|
249
|
-
packageId: this.packageId,
|
|
250
|
-
description: def.description,
|
|
251
|
-
actions: def.actions,
|
|
252
|
-
content: def.content,
|
|
253
|
-
filePath: def.filePath,
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
catch {
|
|
258
|
-
// 忽略规程加载异常
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
// 2. 读取项目配置文件中的 playbooks
|
|
263
|
-
if (this.projectConfig && this.projectConfig.playbooks) {
|
|
264
|
-
const rawPlaybooks = this.projectConfig.playbooks;
|
|
265
|
-
if (typeof rawPlaybooks === "object" && rawPlaybooks !== null) {
|
|
266
|
-
for (const [id, item] of Object.entries(rawPlaybooks)) {
|
|
267
|
-
const existing = map.get(id);
|
|
268
|
-
let content = item.content ?? existing?.content ?? "";
|
|
269
|
-
let filePath = item.entry && this.packageRoot
|
|
270
|
-
? resolve(this.packageRoot, item.entry)
|
|
271
|
-
: existing?.filePath;
|
|
272
|
-
if (!content && filePath && existsSync(filePath)) {
|
|
273
|
-
try {
|
|
274
|
-
content = readFileSync(filePath, "utf-8");
|
|
275
|
-
}
|
|
276
|
-
catch {
|
|
277
|
-
// 忽略读取异常
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
map.set(id, {
|
|
281
|
-
id,
|
|
282
|
-
packageId: this.packageId,
|
|
283
|
-
description: item.description ?? existing?.description,
|
|
284
|
-
actions: item.actions ?? existing?.actions,
|
|
285
|
-
content,
|
|
286
|
-
filePath,
|
|
287
|
-
});
|
|
288
|
-
}
|
|
289
|
-
}
|
|
180
|
+
if (!this.staticPlaybookIndex) {
|
|
181
|
+
this.staticPlaybookIndex = buildStaticPlaybookMap({
|
|
182
|
+
packageRoot: this.packageRoot,
|
|
183
|
+
packageId: this.packageId,
|
|
184
|
+
projectConfig: this.projectConfig,
|
|
185
|
+
});
|
|
290
186
|
}
|
|
291
|
-
return
|
|
187
|
+
return this.staticPlaybookIndex;
|
|
292
188
|
}
|
|
293
189
|
async info(options) {
|
|
294
190
|
const actionsMap = this.getStaticActionMap();
|
|
@@ -484,36 +380,47 @@ export class DefaultActionDockApp {
|
|
|
484
380
|
async deleteConfig(key) {
|
|
485
381
|
return await this.storage.deleteConfig(key);
|
|
486
382
|
}
|
|
487
|
-
|
|
383
|
+
/**
|
|
384
|
+
* 状态作用域统一解析辅助函数(单一事实源)。
|
|
385
|
+
*
|
|
386
|
+
* 完成重载消歧与 actionId 冲突校验,返回最终生效的命名空间:
|
|
387
|
+
* - actionId 存在时拼 接 `${actionId}:${namespace}` 或直接 actionId;
|
|
388
|
+
* - 无 actionId 时返回显式 namespace 或空字符串(包级扁平状态)。
|
|
389
|
+
*/
|
|
390
|
+
resolveStateScope(actionIdOrKey, keyOrOptions, options) {
|
|
488
391
|
let actionId;
|
|
489
|
-
let
|
|
490
|
-
|
|
392
|
+
let resolvedOpts;
|
|
393
|
+
// 消歧规则(与原始重载语义严格一致):仅当第二参为字符串时认定为
|
|
394
|
+
// (actionId, key, options) 形态;否则(undefined 或选项对象)认定为
|
|
395
|
+
// (key, options) 扁平调用形态,首参是状态键而非 actionId
|
|
491
396
|
if (typeof keyOrOptions === "string") {
|
|
492
397
|
actionId = actionIdOrKey;
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
throw new Error(`Conflicting actionId specified: positional '${actionId}' vs options.actionId '${opts.actionId}'`);
|
|
398
|
+
resolvedOpts = options;
|
|
399
|
+
if (resolvedOpts?.actionId && resolvedOpts.actionId !== actionId) {
|
|
400
|
+
throw new Error(`Conflicting actionId specified: positional '${actionId}' vs options.actionId '${resolvedOpts.actionId}'`);
|
|
497
401
|
}
|
|
498
402
|
}
|
|
499
403
|
else {
|
|
404
|
+
// (key, options) 扁平调用:首参是状态键,无位置 actionId;
|
|
405
|
+
// options.actionId 属于合法的显式指定,直接采纳而非判为冲突
|
|
500
406
|
actionId = "";
|
|
501
|
-
|
|
502
|
-
opts = keyOrOptions;
|
|
407
|
+
resolvedOpts = keyOrOptions;
|
|
503
408
|
}
|
|
504
|
-
if (!actionId &&
|
|
505
|
-
actionId =
|
|
409
|
+
if (!actionId && resolvedOpts?.actionId) {
|
|
410
|
+
actionId = resolvedOpts.actionId;
|
|
506
411
|
}
|
|
507
412
|
const ns = actionId
|
|
508
|
-
? (
|
|
509
|
-
: (
|
|
413
|
+
? (resolvedOpts?.namespace ? `${actionId}:${resolvedOpts.namespace}` : actionId)
|
|
414
|
+
: (resolvedOpts?.namespace ?? "");
|
|
415
|
+
return { ns, opts: resolvedOpts };
|
|
416
|
+
}
|
|
417
|
+
async getState(actionIdOrKey, keyOrOptions, options) {
|
|
418
|
+
const { ns, opts } = this.resolveStateScope(actionIdOrKey, keyOrOptions, options);
|
|
419
|
+
const key = typeof keyOrOptions === "string" ? keyOrOptions : actionIdOrKey;
|
|
510
420
|
if (opts?.detail) {
|
|
511
421
|
const entry = await this.storage.findState(key, ns || undefined);
|
|
512
422
|
return entry;
|
|
513
423
|
}
|
|
514
|
-
if (actionId) {
|
|
515
|
-
return await this.storage.getState(ns, key);
|
|
516
|
-
}
|
|
517
424
|
if (ns) {
|
|
518
425
|
return await this.storage.getState(ns, key);
|
|
519
426
|
}
|
|
@@ -521,10 +428,10 @@ export class DefaultActionDockApp {
|
|
|
521
428
|
return entry?.value;
|
|
522
429
|
}
|
|
523
430
|
async setState(actionIdOrKey, keyOrValue, valueOrOptions, options) {
|
|
524
|
-
let actionId;
|
|
525
431
|
let key;
|
|
526
432
|
let value;
|
|
527
433
|
let opts;
|
|
434
|
+
let actionId;
|
|
528
435
|
if (arguments.length >= 4) {
|
|
529
436
|
if (options?.actionId && options.actionId !== actionIdOrKey) {
|
|
530
437
|
throw new Error(`Conflicting actionId specified: positional '${actionIdOrKey}' vs options.actionId '${options.actionId}'`);
|
|
@@ -570,28 +477,8 @@ export class DefaultActionDockApp {
|
|
|
570
477
|
await this.storage.setState(targetNs, targetKey, value, opts?.ttl);
|
|
571
478
|
}
|
|
572
479
|
async deleteState(actionIdOrKey, keyOrOptions, options) {
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
let opts;
|
|
576
|
-
if (typeof keyOrOptions === "string") {
|
|
577
|
-
actionId = actionIdOrKey;
|
|
578
|
-
key = keyOrOptions;
|
|
579
|
-
opts = options;
|
|
580
|
-
if (opts?.actionId && opts.actionId !== actionId) {
|
|
581
|
-
throw new Error(`Conflicting actionId specified: positional '${actionId}' vs options.actionId '${opts.actionId}'`);
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
else {
|
|
585
|
-
actionId = "";
|
|
586
|
-
key = actionIdOrKey;
|
|
587
|
-
opts = keyOrOptions;
|
|
588
|
-
}
|
|
589
|
-
if (!actionId && opts?.actionId) {
|
|
590
|
-
actionId = opts.actionId;
|
|
591
|
-
}
|
|
592
|
-
const ns = actionId
|
|
593
|
-
? (opts?.namespace ? `${actionId}:${opts.namespace}` : actionId)
|
|
594
|
-
: (opts?.namespace ?? "");
|
|
480
|
+
const { ns } = this.resolveStateScope(actionIdOrKey, keyOrOptions, options);
|
|
481
|
+
const key = typeof keyOrOptions === "string" ? keyOrOptions : actionIdOrKey;
|
|
595
482
|
if (ns) {
|
|
596
483
|
return await this.storage.deleteState(ns, key);
|
|
597
484
|
}
|
|
@@ -608,74 +495,53 @@ export class DefaultActionDockApp {
|
|
|
608
495
|
return await this.storage.deleteState(targetNs, targetKey);
|
|
609
496
|
}
|
|
610
497
|
async getActionState(actionId, key, options) {
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
}
|
|
614
|
-
const ns = options?.namespace ? `${actionId}:${options.namespace}` : actionId;
|
|
615
|
-
if (options?.detail) {
|
|
498
|
+
const { ns, opts } = this.resolveStateScope(actionId, key, options);
|
|
499
|
+
if (opts?.detail) {
|
|
616
500
|
const entry = await this.storage.findState(key, ns || undefined);
|
|
617
501
|
return entry;
|
|
618
502
|
}
|
|
619
503
|
return await this.storage.getState(ns, key);
|
|
620
504
|
}
|
|
621
505
|
async setActionState(actionId, key, value, options) {
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
}
|
|
625
|
-
const ns = options?.namespace ? `${actionId}:${options.namespace}` : actionId;
|
|
626
|
-
await this.storage.setState(ns, key, value, options?.ttl);
|
|
506
|
+
const { ns, opts } = this.resolveStateScope(actionId, key, options);
|
|
507
|
+
await this.storage.setState(ns, key, value, opts?.ttl);
|
|
627
508
|
}
|
|
628
509
|
async deleteActionState(actionId, key, options) {
|
|
629
|
-
|
|
630
|
-
throw new Error(`Conflicting actionId specified: positional '${actionId}' vs options.actionId '${options.actionId}'`);
|
|
631
|
-
}
|
|
632
|
-
const ns = options?.namespace ? `${actionId}:${options.namespace}` : actionId;
|
|
510
|
+
const { ns } = this.resolveStateScope(actionId, key, options);
|
|
633
511
|
return await this.storage.deleteState(ns, key);
|
|
634
512
|
}
|
|
635
513
|
async listStateKeys(actionIdOrOptions, options) {
|
|
636
|
-
|
|
637
|
-
|
|
514
|
+
// 重载消歧:首参为字符串时是 (actionId, options) 调用(完成冲突校验后取其域);
|
|
515
|
+
// 否则首参本身就是选项对象(或未传),取 options.actionId 或 namespace 扁平域
|
|
516
|
+
let ns;
|
|
638
517
|
if (typeof actionIdOrOptions === "string") {
|
|
639
|
-
|
|
640
|
-
opts = options;
|
|
641
|
-
if (opts?.actionId && opts.actionId !== actionId) {
|
|
642
|
-
throw new Error(`Conflicting actionId specified: positional '${actionId}' vs options.actionId '${opts.actionId}'`);
|
|
643
|
-
}
|
|
518
|
+
ns = this.resolveStateScope(actionIdOrOptions, "", options).ns;
|
|
644
519
|
}
|
|
645
520
|
else {
|
|
646
|
-
|
|
647
|
-
|
|
521
|
+
const opts = actionIdOrOptions;
|
|
522
|
+
ns = opts?.actionId
|
|
523
|
+
? (opts.namespace ? `${opts.actionId}:${opts.namespace}` : opts.actionId)
|
|
524
|
+
: (opts?.namespace ?? "");
|
|
648
525
|
}
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
}
|
|
652
|
-
const ns = actionId
|
|
653
|
-
? (opts?.namespace ? `${actionId}:${opts.namespace}` : actionId)
|
|
654
|
-
: (opts?.namespace ?? null);
|
|
655
|
-
return this.storage.listStateKeys(ns, opts?.prefix);
|
|
526
|
+
const opts = typeof actionIdOrOptions === "string" ? options : actionIdOrOptions;
|
|
527
|
+
return this.storage.listStateKeys(ns ? ns : null, opts?.prefix);
|
|
656
528
|
}
|
|
657
529
|
async clearState(actionIdOrOptions, options) {
|
|
658
|
-
|
|
659
|
-
|
|
530
|
+
// 首参为字符串时是 (actionId, options) 调用:以伪 key 消费冲突校验后取其 actionId 域;
|
|
531
|
+
// 否则首参本身就是选项对象(或未传),直接走扁平分支
|
|
660
532
|
if (typeof actionIdOrOptions === "string") {
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
actionId = "";
|
|
669
|
-
opts = actionIdOrOptions;
|
|
670
|
-
}
|
|
671
|
-
if (!actionId && opts?.actionId) {
|
|
672
|
-
actionId = opts.actionId;
|
|
533
|
+
const { ns } = this.resolveStateScope(actionIdOrOptions, "", options);
|
|
534
|
+
const finalNs = ns || (options?.namespace ?? "");
|
|
535
|
+
return this.storage.clearState({
|
|
536
|
+
namespace: finalNs ? finalNs : undefined,
|
|
537
|
+
prefix: options?.prefix,
|
|
538
|
+
all: options?.all,
|
|
539
|
+
});
|
|
673
540
|
}
|
|
674
|
-
const
|
|
675
|
-
|
|
676
|
-
: (opts?.namespace ?? undefined);
|
|
541
|
+
const opts = actionIdOrOptions;
|
|
542
|
+
const ns = opts?.namespace;
|
|
677
543
|
return this.storage.clearState({
|
|
678
|
-
namespace: ns,
|
|
544
|
+
namespace: ns ? ns : undefined,
|
|
679
545
|
prefix: opts?.prefix,
|
|
680
546
|
all: opts?.all,
|
|
681
547
|
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { ActionDefinition } from "@actiondock/sdk";
|
|
2
|
+
import type { ProjectConfig } from "../project/types.js";
|
|
3
|
+
import type { ActionSpec, PlaybookSpec } from "./types.js";
|
|
4
|
+
/**
|
|
5
|
+
* 静态清单索引构建入参:同一包的全部静态事实来源。
|
|
6
|
+
* 入参不可变(同实例内复用解析结果的前提),字段与 App 实例的运行时只读状态一一对应。
|
|
7
|
+
*/
|
|
8
|
+
export interface StaticIndexInput {
|
|
9
|
+
/** 包根目录(磁盘清单来源;缺省时仅聚合配置与内存注入来源) */
|
|
10
|
+
packageRoot?: string;
|
|
11
|
+
/** 包唯一标识 */
|
|
12
|
+
packageId: string;
|
|
13
|
+
/** 项目配置(Manifest v2 声明来源) */
|
|
14
|
+
projectConfig: ProjectConfig;
|
|
15
|
+
}
|
|
16
|
+
/** Action 索引构建入参:静态事实来源之上叠加内存注入的 Action 定义集合 */
|
|
17
|
+
export interface StaticActionIndexInput extends StaticIndexInput {
|
|
18
|
+
/** 内存显式注入的 Action 定义集合 */
|
|
19
|
+
actionsMap: ReadonlyMap<string, ActionDefinition>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* 静态读取并聚合指定包的 Action 规范索引。
|
|
23
|
+
* 不产生全量模块导入与执行副作用。
|
|
24
|
+
*
|
|
25
|
+
* 聚合优先级(后者覆盖前者同名字段,缺省字段回退前者):
|
|
26
|
+
* - 磁盘声明式清单文件(actiondock.json);
|
|
27
|
+
* - 项目配置中声明的 actions(Manifest v2 格式);
|
|
28
|
+
* - 内存显式注入的 Action 定义。
|
|
29
|
+
*
|
|
30
|
+
* 清单文件不存在属于合法空态;解析失败(损坏 JSON 等)输出告警并跳过清单部分。
|
|
31
|
+
*/
|
|
32
|
+
export declare function buildStaticActionMap(input: StaticActionIndexInput): Map<string, ActionSpec>;
|
|
33
|
+
/**
|
|
34
|
+
* 静态读取并聚合指定包的 Playbook 规范索引。
|
|
35
|
+
*
|
|
36
|
+
* 聚合来源:磁盘规程目录扫描(以 actiondock.json 声明为事实源)与
|
|
37
|
+
* 项目配置中声明的 playbooks;同键时配置声明覆盖磁盘扫描结果。
|
|
38
|
+
*/
|
|
39
|
+
export declare function buildStaticPlaybookMap(input: StaticIndexInput): Map<string, PlaybookSpec>;
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
import { loadPlaybooks } from "../project/loader.js";
|
|
4
|
+
import { loadManifest, MANIFEST_FILE_NAME } from "../project/manifest.js";
|
|
5
|
+
/**
|
|
6
|
+
* 静态读取并聚合指定包的 Action 规范索引。
|
|
7
|
+
* 不产生全量模块导入与执行副作用。
|
|
8
|
+
*
|
|
9
|
+
* 聚合优先级(后者覆盖前者同名字段,缺省字段回退前者):
|
|
10
|
+
* - 磁盘声明式清单文件(actiondock.json);
|
|
11
|
+
* - 项目配置中声明的 actions(Manifest v2 格式);
|
|
12
|
+
* - 内存显式注入的 Action 定义。
|
|
13
|
+
*
|
|
14
|
+
* 清单文件不存在属于合法空态;解析失败(损坏 JSON 等)输出告警并跳过清单部分。
|
|
15
|
+
*/
|
|
16
|
+
export function buildStaticActionMap(input) {
|
|
17
|
+
const { packageRoot, packageId, projectConfig, actionsMap } = input;
|
|
18
|
+
const map = new Map();
|
|
19
|
+
// 读取声明式清单文件 (actiondock.json)
|
|
20
|
+
if (packageRoot) {
|
|
21
|
+
const manifestPath = join(packageRoot, MANIFEST_FILE_NAME);
|
|
22
|
+
// 文件不存在属于合法空态(无清单包);解析失败(损坏 JSON 等)则输出告警并跳过清单部分
|
|
23
|
+
if (!existsSync(manifestPath)) {
|
|
24
|
+
// 合法空态:无清单文件,仅依赖后续配置与内存注入来源
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
try {
|
|
28
|
+
const manifest = loadManifest(packageRoot);
|
|
29
|
+
if (manifest?.actions) {
|
|
30
|
+
for (const [id, item] of Object.entries(manifest.actions)) {
|
|
31
|
+
map.set(id, {
|
|
32
|
+
id,
|
|
33
|
+
packageId,
|
|
34
|
+
description: item.description,
|
|
35
|
+
inputSchema: item.inputSchema,
|
|
36
|
+
outputSchema: item.outputSchema,
|
|
37
|
+
tags: item.tags ? [...item.tags] : [],
|
|
38
|
+
annotations: item.annotations,
|
|
39
|
+
uses: item.uses ? [...item.uses] : [],
|
|
40
|
+
entry: item.entry,
|
|
41
|
+
filePath: item.entry ? resolve(packageRoot, item.entry) : undefined,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
console.warn(`[App] Failed to load manifest for package '${packageId}' from '${manifestPath}': ${err?.message || String(err)}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// 读取项目配置文件中声明的 actions (Manifest v2 格式)
|
|
52
|
+
if (projectConfig && projectConfig.actions) {
|
|
53
|
+
const rawActions = projectConfig.actions;
|
|
54
|
+
if (typeof rawActions === "object" && rawActions !== null) {
|
|
55
|
+
for (const [id, item] of Object.entries(rawActions)) {
|
|
56
|
+
const existing = map.get(id);
|
|
57
|
+
map.set(id, {
|
|
58
|
+
id,
|
|
59
|
+
packageId,
|
|
60
|
+
description: item.description ?? existing?.description,
|
|
61
|
+
inputSchema: item.inputSchema ?? existing?.inputSchema,
|
|
62
|
+
outputSchema: item.outputSchema ?? existing?.outputSchema,
|
|
63
|
+
tags: item.tags ?? existing?.tags,
|
|
64
|
+
annotations: item.annotations ?? existing?.annotations,
|
|
65
|
+
uses: item.uses ?? existing?.uses,
|
|
66
|
+
entry: item.entry ?? existing?.entry,
|
|
67
|
+
filePath: item.entry && packageRoot
|
|
68
|
+
? resolve(packageRoot, item.entry)
|
|
69
|
+
: existing?.filePath,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// 读取内存显式注入的 Action 定义
|
|
75
|
+
for (const [id, act] of actionsMap) {
|
|
76
|
+
// 若为当前包完全限定名别名(例如 "pkgId/actionId"),跳过以防与短名 action 重复
|
|
77
|
+
if (id.startsWith(`${packageId}/`)) {
|
|
78
|
+
const shortId = id.slice(packageId.length + 1);
|
|
79
|
+
if (actionsMap.has(shortId) || map.has(shortId)) {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const existing = map.get(id);
|
|
84
|
+
const actObj = act;
|
|
85
|
+
map.set(id, {
|
|
86
|
+
id,
|
|
87
|
+
packageId,
|
|
88
|
+
description: actObj.description ?? existing?.description,
|
|
89
|
+
inputSchema: actObj.inputSchema ?? existing?.inputSchema,
|
|
90
|
+
outputSchema: actObj.outputSchema ?? existing?.outputSchema,
|
|
91
|
+
tags: actObj.tags ? [...actObj.tags] : existing?.tags,
|
|
92
|
+
annotations: actObj.annotations ?? existing?.annotations,
|
|
93
|
+
uses: actObj.uses ? [...actObj.uses] : existing?.uses,
|
|
94
|
+
entry: existing?.entry,
|
|
95
|
+
filePath: existing?.filePath,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
return map;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* 静态读取并聚合指定包的 Playbook 规范索引。
|
|
102
|
+
*
|
|
103
|
+
* 聚合来源:磁盘规程目录扫描(以 actiondock.json 声明为事实源)与
|
|
104
|
+
* 项目配置中声明的 playbooks;同键时配置声明覆盖磁盘扫描结果。
|
|
105
|
+
*/
|
|
106
|
+
export function buildStaticPlaybookMap(input) {
|
|
107
|
+
const { packageRoot, packageId, projectConfig } = input;
|
|
108
|
+
const map = new Map();
|
|
109
|
+
// 扫描磁盘规程文件
|
|
110
|
+
if (packageRoot) {
|
|
111
|
+
const playbooksDir = projectConfig?.playbooksDir || "playbooks";
|
|
112
|
+
const dirPath = join(packageRoot, playbooksDir);
|
|
113
|
+
if (existsSync(dirPath)) {
|
|
114
|
+
try {
|
|
115
|
+
const loaded = loadPlaybooks(packageRoot, playbooksDir);
|
|
116
|
+
for (const [id, def] of loaded) {
|
|
117
|
+
map.set(id, {
|
|
118
|
+
id: def.id,
|
|
119
|
+
packageId,
|
|
120
|
+
description: def.description,
|
|
121
|
+
actions: def.actions,
|
|
122
|
+
content: def.content,
|
|
123
|
+
filePath: def.filePath,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
// 规程加载失败(清单声明非法、规程文件损坏等)输出告警并跳过磁盘部分,保持返回可用列表
|
|
129
|
+
console.warn(`[App] Failed to load playbooks for package '${packageId}' from '${dirPath}': ${err?.message || String(err)}`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// 读取项目配置文件中的 playbooks
|
|
134
|
+
if (projectConfig && projectConfig.playbooks) {
|
|
135
|
+
const rawPlaybooks = projectConfig.playbooks;
|
|
136
|
+
if (typeof rawPlaybooks === "object" && rawPlaybooks !== null) {
|
|
137
|
+
for (const [id, item] of Object.entries(rawPlaybooks)) {
|
|
138
|
+
const existing = map.get(id);
|
|
139
|
+
let content = item.content ?? existing?.content ?? "";
|
|
140
|
+
let filePath = item.entry && packageRoot
|
|
141
|
+
? resolve(packageRoot, item.entry)
|
|
142
|
+
: existing?.filePath;
|
|
143
|
+
if (!content && filePath && existsSync(filePath)) {
|
|
144
|
+
try {
|
|
145
|
+
content = readFileSync(filePath, "utf-8");
|
|
146
|
+
}
|
|
147
|
+
catch (err) {
|
|
148
|
+
// 读取失败(权限、IO 错误等)输出告警并保持空正文,不再无声吞没
|
|
149
|
+
console.warn(`[App] Failed to read playbook '${id}' content from '${filePath}' in package '${packageId}': ${err?.message || String(err)}`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
map.set(id, {
|
|
153
|
+
id,
|
|
154
|
+
packageId,
|
|
155
|
+
description: item.description ?? existing?.description,
|
|
156
|
+
actions: item.actions ?? existing?.actions,
|
|
157
|
+
content,
|
|
158
|
+
filePath,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return map;
|
|
164
|
+
}
|