@actiondock/core 2.0.12 → 2.2.1

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.
Files changed (192) hide show
  1. package/README.md +61 -30
  2. package/dist/app/app.d.ts +73 -0
  3. package/dist/app/app.js +700 -0
  4. package/dist/app/index.d.ts +2 -0
  5. package/dist/app/index.js +2 -0
  6. package/dist/app/types.d.ts +283 -0
  7. package/dist/app/types.js +1 -0
  8. package/dist/catalog/action-index.d.ts +1 -1
  9. package/dist/catalog/action-index.js +93 -0
  10. package/dist/catalog/action-resolver.d.ts +2 -2
  11. package/dist/catalog/action-resolver.js +95 -0
  12. package/dist/catalog/index.d.ts +5 -5
  13. package/dist/catalog/index.js +5 -0
  14. package/dist/catalog/location-registry.d.ts +5 -5
  15. package/dist/catalog/location-registry.js +138 -0
  16. package/dist/catalog/package-catalog.d.ts +2 -2
  17. package/dist/catalog/package-catalog.js +76 -0
  18. package/dist/catalog/types.d.ts +2 -2
  19. package/dist/catalog/types.js +1 -0
  20. package/dist/doctor/doctor.d.ts +2 -1
  21. package/dist/doctor/doctor.js +613 -0
  22. package/dist/doctor/index.d.ts +2 -2
  23. package/dist/doctor/index.js +2 -0
  24. package/dist/doctor/types.js +1 -0
  25. package/dist/errors.d.ts +122 -0
  26. package/dist/errors.js +123 -0
  27. package/dist/execution/index.d.ts +2 -2
  28. package/dist/execution/index.js +2 -0
  29. package/dist/execution/service.d.ts +46 -41
  30. package/dist/execution/service.js +633 -0
  31. package/dist/execution/types.d.ts +59 -2
  32. package/dist/execution/types.js +1 -0
  33. package/dist/export/index.d.ts +1 -1
  34. package/dist/export/index.js +1 -0
  35. package/dist/export/templates.d.ts +45 -7
  36. package/dist/export/templates.js +631 -0
  37. package/dist/filter/index.d.ts +1 -1
  38. package/dist/filter/index.js +1 -0
  39. package/dist/filter/intent.js +123 -0
  40. package/dist/host/host.d.ts +55 -0
  41. package/dist/host/host.js +740 -0
  42. package/dist/host/index.d.ts +2 -0
  43. package/dist/host/index.js +2 -0
  44. package/dist/host/types.d.ts +81 -0
  45. package/dist/host/types.js +1 -0
  46. package/dist/index.d.ts +21 -16
  47. package/dist/index.js +20 -8458
  48. package/dist/ipc/diagnostic.d.ts +65 -0
  49. package/dist/ipc/diagnostic.js +129 -0
  50. package/dist/ipc/host.d.ts +7 -0
  51. package/dist/ipc/host.js +93 -0
  52. package/dist/ipc/index.d.ts +4 -0
  53. package/dist/ipc/index.js +4 -0
  54. package/dist/ipc/target.d.ts +56 -0
  55. package/dist/ipc/target.js +297 -0
  56. package/dist/ipc/types.d.ts +42 -0
  57. package/dist/ipc/types.js +1 -0
  58. package/dist/platform/default.d.ts +32 -0
  59. package/dist/platform/default.js +40 -0
  60. package/dist/platform/index.d.ts +3 -0
  61. package/dist/platform/index.js +3 -0
  62. package/dist/platform/node-fs.d.ts +37 -0
  63. package/dist/platform/node-fs.js +81 -0
  64. package/dist/platform/types.d.ts +104 -0
  65. package/dist/platform/types.js +1 -0
  66. package/dist/profile/client.d.ts +58 -12
  67. package/dist/profile/client.js +467 -0
  68. package/dist/profile/index.d.ts +3 -3
  69. package/dist/profile/index.js +3 -0
  70. package/dist/profile/manager.d.ts +2 -2
  71. package/dist/profile/manager.js +294 -0
  72. package/dist/profile/types.d.ts +1 -1
  73. package/dist/profile/types.js +1 -0
  74. package/dist/project/closure.js +68 -0
  75. package/dist/project/digest.d.ts +29 -0
  76. package/dist/project/digest.js +324 -0
  77. package/dist/project/index.d.ts +10 -5
  78. package/dist/project/index.js +10 -0
  79. package/dist/project/init.d.ts +3 -4
  80. package/dist/project/init.js +175 -0
  81. package/dist/project/loader.d.ts +21 -27
  82. package/dist/project/loader.js +484 -0
  83. package/dist/project/lockfile.d.ts +55 -0
  84. package/dist/project/lockfile.js +175 -0
  85. package/dist/project/manifest.d.ts +6 -28
  86. package/dist/project/manifest.js +220 -0
  87. package/dist/project/resolver.d.ts +116 -0
  88. package/dist/project/resolver.js +376 -0
  89. package/dist/project/transactions.d.ts +103 -0
  90. package/dist/project/transactions.js +1203 -0
  91. package/dist/project/types-generator.d.ts +33 -0
  92. package/dist/project/types-generator.js +168 -0
  93. package/dist/project/types.d.ts +58 -82
  94. package/dist/project/types.js +1 -0
  95. package/dist/registry/index.d.ts +5 -2
  96. package/dist/registry/index.js +5 -0
  97. package/dist/registry/lock.d.ts +27 -0
  98. package/dist/registry/lock.js +93 -0
  99. package/dist/registry/registry.d.ts +32 -11
  100. package/dist/registry/registry.js +611 -0
  101. package/dist/registry/resolve.d.ts +62 -0
  102. package/dist/registry/resolve.js +195 -0
  103. package/dist/registry/scan.d.ts +38 -0
  104. package/dist/registry/scan.js +135 -0
  105. package/dist/registry/types.d.ts +1 -1
  106. package/dist/registry/types.js +1 -0
  107. package/dist/runtime/action-collection.d.ts +27 -0
  108. package/dist/runtime/action-collection.js +57 -0
  109. package/dist/runtime/clock.d.ts +0 -2
  110. package/dist/runtime/clock.js +17 -0
  111. package/dist/runtime/context.d.ts +16 -5
  112. package/dist/runtime/context.js +242 -0
  113. package/dist/runtime/env.d.ts +3 -1
  114. package/dist/runtime/env.js +159 -0
  115. package/dist/runtime/events.d.ts +46 -14
  116. package/dist/runtime/events.js +604 -0
  117. package/dist/runtime/execution-manager.d.ts +1 -1
  118. package/dist/runtime/execution-manager.js +66 -0
  119. package/dist/runtime/index.d.ts +10 -9
  120. package/dist/runtime/index.js +10 -0
  121. package/dist/runtime/module-loader.d.ts +0 -8
  122. package/dist/runtime/module-loader.js +16 -0
  123. package/dist/runtime/process.d.ts +2 -4
  124. package/dist/runtime/process.js +146 -0
  125. package/dist/runtime/runner.d.ts +117 -10
  126. package/dist/runtime/runner.js +984 -0
  127. package/dist/runtime/standalone.d.ts +68 -19
  128. package/dist/runtime/standalone.js +536 -0
  129. package/dist/schema/validator.js +122 -0
  130. package/dist/server/body.js +93 -0
  131. package/dist/server/index.d.ts +5 -6
  132. package/dist/server/index.js +5 -0
  133. package/dist/server/routes/actions.d.ts +2 -2
  134. package/dist/server/routes/actions.js +298 -0
  135. package/dist/server/routes/common.d.ts +28 -17
  136. package/dist/server/routes/common.js +104 -0
  137. package/dist/server/routes/config.d.ts +2 -1
  138. package/dist/server/routes/config.js +173 -0
  139. package/dist/server/routes/doctor.d.ts +2 -2
  140. package/dist/server/routes/doctor.js +63 -0
  141. package/dist/server/routes/health.d.ts +2 -2
  142. package/dist/server/routes/health.js +35 -0
  143. package/dist/server/routes/index.d.ts +9 -9
  144. package/dist/server/routes/index.js +9 -0
  145. package/dist/server/routes/info.d.ts +4 -2
  146. package/dist/server/routes/info.js +158 -0
  147. package/dist/server/routes/playbooks.d.ts +2 -2
  148. package/dist/server/routes/playbooks.js +134 -0
  149. package/dist/server/routes/runs.d.ts +2 -2
  150. package/dist/server/routes/runs.js +343 -0
  151. package/dist/server/routes/state.d.ts +2 -1
  152. package/dist/server/routes/state.js +169 -0
  153. package/dist/server/security.d.ts +11 -4
  154. package/dist/server/security.js +101 -0
  155. package/dist/server/server.d.ts +6 -6
  156. package/dist/server/server.js +355 -0
  157. package/dist/server/types.d.ts +27 -8
  158. package/dist/server/types.js +1 -0
  159. package/dist/storage/data-dir-lock.d.ts +119 -0
  160. package/dist/storage/data-dir-lock.js +1016 -0
  161. package/dist/storage/driver.d.ts +4 -10
  162. package/dist/storage/driver.js +59 -0
  163. package/dist/storage/index.d.ts +30 -10
  164. package/dist/storage/index.js +98 -0
  165. package/dist/storage/lazy.d.ts +8 -0
  166. package/dist/storage/lazy.js +44 -0
  167. package/dist/storage/mask.d.ts +12 -5
  168. package/dist/storage/mask.js +48 -0
  169. package/dist/storage/params.d.ts +13 -0
  170. package/dist/storage/params.js +32 -0
  171. package/dist/storage/sqlite.d.ts +19 -6
  172. package/dist/storage/sqlite.js +689 -0
  173. package/dist/storage/types.d.ts +57 -6
  174. package/dist/storage/types.js +14 -0
  175. package/dist/target/index.d.ts +4 -0
  176. package/dist/target/index.js +4 -0
  177. package/dist/target/local.d.ts +52 -0
  178. package/dist/target/local.js +343 -0
  179. package/dist/target/remote.d.ts +76 -0
  180. package/dist/target/remote.js +839 -0
  181. package/dist/target/target.d.ts +6 -0
  182. package/dist/target/target.js +35 -0
  183. package/dist/target/types.d.ts +246 -0
  184. package/dist/target/types.js +34 -0
  185. package/dist/utils/index.d.ts +22 -2
  186. package/dist/utils/index.js +180 -0
  187. package/dist/version.d.ts +1 -1
  188. package/dist/version.js +4 -0
  189. package/package.json +6 -7
  190. package/dist/build/index.d.ts +0 -1
  191. package/dist/build/templates.d.ts +0 -19
  192. package/dist/server/runtime-registry.d.ts +0 -78
@@ -1,40 +1,89 @@
1
1
  import type { ActionDefinition } from "@actiondock/sdk";
2
- import type { ConfigItemDefinition } from "../project/types";
2
+ import type { ActionSpec } from "../app/types.js";
3
+ import type { ConfigItemDefinition } from "../project/types.js";
4
+ import type { ActionDockTarget } from "../target/types.js";
3
5
  /**
4
- * 独立编译可执行文件运行时的初始化选项。
6
+ * 退出状态码常量。
5
7
  */
6
- export interface StandaloneRuntimeOptions {
8
+ export declare const ExitCode: {
9
+ readonly SUCCESS: 0;
10
+ readonly FAILURE: 1;
11
+ readonly INVALID_ARGUMENT: 2;
12
+ readonly SIGINT: 130;
13
+ };
14
+ /**
15
+ * 独立二进制运行分发器配置选项。
16
+ */
17
+ export interface StandaloneDispatcherOptions {
7
18
  /** 所属 Package ID */
8
19
  packageId: string;
9
20
  /** 版本号 */
10
21
  version: string;
11
22
  /** 描述信息 */
12
23
  description?: string;
13
- /** 声明的配置依赖定义 */
24
+ /** 已构造的 ActionDockTarget 门面(若未传入则依据 actions/config 自动创建) */
25
+ target?: ActionDockTarget;
26
+ /** 声明的配置依赖定义(兼容选项) */
27
+ configDefs?: Record<string, ConfigItemDefinition>;
14
28
  config?: Record<string, ConfigItemDefinition>;
15
- /** 打包内置的 Action 动作定义列表 */
16
- actions: ActionDefinition[];
29
+ /** 打包内置的 Action 动作定义列表(兼容选项) */
30
+ actions?: Map<string, ActionDefinition> | Array<({
31
+ id: string;
32
+ action: ActionDefinition;
33
+ } & Partial<ActionSpec>) | (ActionDefinition & {
34
+ id: string;
35
+ })> | Record<string, ActionDefinition>;
36
+ /** 标准输出自定义拦截器 */
37
+ stdout?: (msg: string) => void;
38
+ /** 标准错误自定义拦截器 */
39
+ stderr?: (msg: string) => void;
40
+ /** 持久化数据库目录 */
41
+ dataDir?: string;
42
+ /** 自定义主目录 */
43
+ customHome?: string;
44
+ /** 是否使用纯内存存储 */
45
+ inMemory?: boolean;
17
46
  }
18
47
  /**
19
- * 独立二进制可执行文件运行时(Standalone Runtime)。
48
+ * 统一独立入口轻量参数解析分发器(StandaloneDispatcher)。
20
49
  *
21
50
  * 职责:
22
- * 1. 作为由 `ad build` 编译生成的单文件独立可执行文件(Standalone Binary)的运行时入口。
23
- * 2. 保证与开发态(`ad run` / `ad action`)在输出信封、配置优先级、状态存储等方面的 100% 行为一致性。
24
- * 3. 自带轻量 CLI 分发器,支持 `list`, `describe`, `run`, `config`, `state`, `version`, `help` 子命令。
51
+ * 1. 负责轻量参数解析、诊断输出渲染与统一退出码管理。
52
+ * 2. 统一面向 ActionDockTarget 门面调用能力(支持本地 LocalTarget IPC 监督隔离 Target)。
53
+ * 3. 严格遵循 ActionDock 2.0 输出协议约定:结果数据专走 stdout,日志与错误专走 stderr。
54
+ * 4. 独立入口拒绝异步启动语义,显式拦截并返回 STANDALONE_ASYNC_UNSUPPORTED。
25
55
  */
26
- export declare class StandaloneRuntime {
27
- private packageId;
28
- private version;
29
- private description?;
30
- private configDefs?;
31
- private actionsMap;
32
- constructor(options: StandaloneRuntimeOptions);
56
+ export declare class StandaloneDispatcher {
57
+ private options;
58
+ constructor(options: StandaloneDispatcherOptions);
59
+ private writeOut;
60
+ private writeErr;
61
+ private createLocalTarget;
33
62
  /**
34
- * 解析命令行参数并执行对应的独立二进制子命令。
63
+ * 解析命令行参数并分发执行对应子命令。
35
64
  *
36
- * @param argv 命令行参数数组(通常为 process.argv.slice(2))
65
+ * @param argv 命令行参数数组(如 process.argv.slice(2))
66
+ * @returns 退出状态码(0: 成功, 1: 失败, 2: 参数错误, 130: 中断)
37
67
  */
68
+ dispatch(argv: string[]): Promise<number>;
69
+ private handleList;
70
+ private handleDescribe;
71
+ private handleRun;
72
+ private handleConfig;
73
+ private handleState;
74
+ private printHelp;
75
+ }
76
+ /**
77
+ * 独立二进制可执行文件运行时(兼容门面包装)。
78
+ */
79
+ export interface StandaloneRuntimeOptions extends StandaloneDispatcherOptions {
80
+ }
81
+ export declare class StandaloneRuntime {
82
+ private dispatcher;
83
+ constructor(options: StandaloneRuntimeOptions);
38
84
  run(argv: string[]): Promise<void>;
39
85
  }
86
+ /**
87
+ * 工厂函数:创建独立运行时实例。
88
+ */
40
89
  export declare function createStandaloneRuntime(options: StandaloneRuntimeOptions): StandaloneRuntime;
@@ -0,0 +1,536 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { filterWithFallbackInfo } from "../filter/index.js";
3
+ import { createActionDockTarget } from "../target/target.js";
4
+ import { STANDALONE_ASYNC_UNSUPPORTED } from "../errors.js";
5
+ import { normalizeActionCollection } from "./action-collection.js";
6
+ import { parseDuration } from "../utils/index.js";
7
+ /**
8
+ * 退出状态码常量。
9
+ */
10
+ export const ExitCode = {
11
+ SUCCESS: 0,
12
+ FAILURE: 1,
13
+ INVALID_ARGUMENT: 2,
14
+ SIGINT: 130,
15
+ };
16
+ /**
17
+ * 统一独立入口轻量参数解析分发器(StandaloneDispatcher)。
18
+ *
19
+ * 职责:
20
+ * 1. 负责轻量参数解析、诊断输出渲染与统一退出码管理。
21
+ * 2. 统一面向 ActionDockTarget 门面调用能力(支持本地 LocalTarget 与 IPC 监督隔离 Target)。
22
+ * 3. 严格遵循 ActionDock 2.0 输出协议约定:结果数据专走 stdout,日志与错误专走 stderr。
23
+ * 4. 独立入口拒绝异步启动语义,显式拦截并返回 STANDALONE_ASYNC_UNSUPPORTED。
24
+ */
25
+ export class StandaloneDispatcher {
26
+ options;
27
+ constructor(options) {
28
+ this.options = options;
29
+ }
30
+ writeOut(msg) {
31
+ if (this.options.stdout) {
32
+ this.options.stdout(msg);
33
+ }
34
+ else {
35
+ console.log(msg);
36
+ }
37
+ }
38
+ writeErr(msg) {
39
+ if (this.options.stderr) {
40
+ this.options.stderr(msg);
41
+ }
42
+ else {
43
+ console.error(msg);
44
+ }
45
+ }
46
+ async createLocalTarget(dataDir, configOverrides = {}) {
47
+ if (this.options.target) {
48
+ return { target: this.options.target, ownsTarget: false };
49
+ }
50
+ if (this.options.inMemory && this.options._sharedTarget) {
51
+ return { target: this.options._sharedTarget, ownsTarget: false };
52
+ }
53
+ // 归一化 Action 集合:单一入口统一三形态输入
54
+ const { actionsMap, actionSpecs } = normalizeActionCollection(this.options.actions);
55
+ // projectConfig.actions 要求 manifest 形态,字段语义兼容,此处显式收敛类型
56
+ const manifestActions = actionSpecs;
57
+ const appOptions = {
58
+ projectConfig: {
59
+ id: this.options.packageId,
60
+ name: this.options.packageId,
61
+ version: this.options.version,
62
+ description: this.options.description,
63
+ config: this.options.config || this.options.configDefs,
64
+ actions: manifestActions,
65
+ },
66
+ actions: actionsMap,
67
+ dataDir: dataDir || this.options.dataDir,
68
+ configOverrides,
69
+ customHome: this.options.customHome,
70
+ inMemory: this.options.inMemory,
71
+ };
72
+ const target = await createActionDockTarget({
73
+ type: "local",
74
+ appOptions,
75
+ });
76
+ if (this.options.inMemory) {
77
+ this.options._sharedTarget = target;
78
+ return { target, ownsTarget: false };
79
+ }
80
+ return { target, ownsTarget: true };
81
+ }
82
+ /**
83
+ * 解析命令行参数并分发执行对应子命令。
84
+ *
85
+ * @param argv 命令行参数数组(如 process.argv.slice(2))
86
+ * @returns 退出状态码(0: 成功, 1: 失败, 2: 参数错误, 130: 中断)
87
+ */
88
+ async dispatch(argv) {
89
+ const args = [...argv];
90
+ let dataDir;
91
+ const configOverrides = {};
92
+ // 1. 提取全局参数(--data-dir, --config)
93
+ const filteredArgs = [];
94
+ for (let i = 0; i < args.length; i++) {
95
+ const arg = args[i];
96
+ if (arg === "--data-dir" && i + 1 < args.length) {
97
+ dataDir = args[++i];
98
+ }
99
+ else if (arg.startsWith("--data-dir=")) {
100
+ dataDir = arg.slice(11);
101
+ }
102
+ else if (arg === "--config" && i + 1 < args.length) {
103
+ const pair = args[++i];
104
+ const [k, ...v] = pair.split("=");
105
+ if (k)
106
+ configOverrides[k] = v.join("=");
107
+ }
108
+ else if (arg.startsWith("--config=")) {
109
+ const pair = arg.slice(9);
110
+ const [k, ...v] = pair.split("=");
111
+ if (k)
112
+ configOverrides[k] = v.join("=");
113
+ }
114
+ else {
115
+ filteredArgs.push(arg);
116
+ }
117
+ }
118
+ const command = filteredArgs[0] || "help";
119
+ const subArgs = filteredArgs.slice(1);
120
+ // 2. 独立入口拒绝异步启动语义
121
+ if (args.includes("--async")) {
122
+ const isJson = args.includes("--json") || args.includes("--envelope");
123
+ if (isJson) {
124
+ this.writeOut(JSON.stringify({
125
+ ok: false,
126
+ error: {
127
+ code: STANDALONE_ASYNC_UNSUPPORTED,
128
+ message: "Async execution is not supported in standalone single-execution binaries. Use 'ad serve' or remote target.",
129
+ },
130
+ }, null, 2));
131
+ }
132
+ else {
133
+ this.writeErr(`Error [${STANDALONE_ASYNC_UNSUPPORTED}]: Async execution is not supported in standalone single-execution binaries.`);
134
+ }
135
+ return ExitCode.FAILURE;
136
+ }
137
+ // 3. 版本与帮助快速处理(无需初始化 Host / Storage)
138
+ if (command === "-v" || command === "-V" || command === "--version" || command === "version") {
139
+ this.writeOut(`${this.options.packageId} v${this.options.version}`);
140
+ return ExitCode.SUCCESS;
141
+ }
142
+ if (command === "-h" || command === "--help" || command === "help") {
143
+ this.printHelp();
144
+ return ExitCode.SUCCESS;
145
+ }
146
+ let target;
147
+ let ownsTarget = false;
148
+ try {
149
+ const targetRes = await this.createLocalTarget(dataDir, configOverrides);
150
+ target = targetRes.target;
151
+ ownsTarget = targetRes.ownsTarget;
152
+ }
153
+ catch (err) {
154
+ this.writeErr(`Error initializing standalone target: ${err?.message || err}`);
155
+ return ExitCode.FAILURE;
156
+ }
157
+ const controller = new AbortController();
158
+ const sigintHandler = () => {
159
+ controller.abort(new Error("Interrupted by SIGINT"));
160
+ };
161
+ process.once("SIGINT", sigintHandler);
162
+ try {
163
+ switch (command) {
164
+ case "list":
165
+ return await this.handleList(target, subArgs);
166
+ case "describe":
167
+ case "show":
168
+ return await this.handleDescribe(target, subArgs);
169
+ case "run":
170
+ return await this.handleRun(target, subArgs, controller.signal);
171
+ case "config":
172
+ return await this.handleConfig(target, subArgs);
173
+ case "state":
174
+ return await this.handleState(target, subArgs);
175
+ default:
176
+ this.writeErr(`Unknown command: '${command}'`);
177
+ this.printHelp();
178
+ return ExitCode.INVALID_ARGUMENT;
179
+ }
180
+ }
181
+ catch (err) {
182
+ if (err?.name === "AbortError" || controller.signal.aborted) {
183
+ return ExitCode.SIGINT;
184
+ }
185
+ this.writeErr(`Error: ${err?.message || err}`);
186
+ return ExitCode.FAILURE;
187
+ }
188
+ finally {
189
+ process.removeListener("SIGINT", sigintHandler);
190
+ if (ownsTarget) {
191
+ await target.close();
192
+ }
193
+ }
194
+ }
195
+ async handleList(target, subArgs) {
196
+ const isJson = subArgs.includes("--json") || subArgs.includes("--envelope");
197
+ const useEnvelope = subArgs.includes("--envelope");
198
+ const noFallback = subArgs.includes("--no-fallback");
199
+ let intent;
200
+ const positionalPatterns = [];
201
+ for (let i = 0; i < subArgs.length; i++) {
202
+ const arg = subArgs[i];
203
+ if (arg === "--intent" || arg === "-i") {
204
+ if (i + 1 < subArgs.length)
205
+ intent = subArgs[++i];
206
+ }
207
+ else if (arg.startsWith("--intent=")) {
208
+ intent = arg.slice(9);
209
+ }
210
+ else if (arg.startsWith("-i=")) {
211
+ intent = arg.slice(3);
212
+ }
213
+ else if (!arg.startsWith("-")) {
214
+ positionalPatterns.push(arg);
215
+ }
216
+ }
217
+ const effectiveIntent = intent || (positionalPatterns.length > 0 ? positionalPatterns.join("|") : undefined);
218
+ const actions = await target.listActions();
219
+ const list = actions.map((a) => ({
220
+ id: a.id,
221
+ description: a.description || "",
222
+ }));
223
+ const filterRes = filterWithFallbackInfo(list, effectiveIntent, [(a) => a.id, (a) => a.description], !noFallback);
224
+ if (isJson) {
225
+ const payload = useEnvelope
226
+ ? { ok: true, data: filterRes.items }
227
+ : filterRes.items;
228
+ this.writeOut(JSON.stringify(payload, null, 2));
229
+ }
230
+ else {
231
+ let text = `Actions in ${this.options.packageId} (v${this.options.version}):\n\n`;
232
+ for (const a of filterRes.items) {
233
+ text += ` ${a.id.padEnd(28)} ${a.description}\n`;
234
+ }
235
+ this.writeOut(text.trimEnd());
236
+ }
237
+ return ExitCode.SUCCESS;
238
+ }
239
+ async handleDescribe(target, subArgs) {
240
+ const id = subArgs.find((a) => !a.startsWith("-"));
241
+ const isJson = subArgs.includes("--json") || subArgs.includes("--envelope");
242
+ const useEnvelope = subArgs.includes("--envelope");
243
+ if (!id) {
244
+ this.writeErr("Error: Action ID is required for describe");
245
+ return ExitCode.INVALID_ARGUMENT;
246
+ }
247
+ let action;
248
+ try {
249
+ action = await target.describeAction(id);
250
+ }
251
+ catch {
252
+ this.writeErr(`Error: Action '${id}' not found`);
253
+ return ExitCode.INVALID_ARGUMENT;
254
+ }
255
+ const detail = {
256
+ id: action.id,
257
+ packageId: this.options.packageId,
258
+ description: action.description,
259
+ inputSchema: action.inputSchema,
260
+ outputSchema: action.outputSchema,
261
+ };
262
+ if (isJson) {
263
+ const payload = useEnvelope ? { ok: true, data: detail } : detail;
264
+ this.writeOut(JSON.stringify(payload, null, 2));
265
+ }
266
+ else {
267
+ let text = `Action: ${action.id}\n`;
268
+ if (action.description)
269
+ text += `Description: ${action.description}\n`;
270
+ if (action.inputSchema) {
271
+ text += `\nInput Schema:\n${JSON.stringify(action.inputSchema, null, 2)}\n`;
272
+ }
273
+ if (action.outputSchema) {
274
+ text += `\nOutput Schema:\n${JSON.stringify(action.outputSchema, null, 2)}\n`;
275
+ }
276
+ this.writeOut(text.trimEnd());
277
+ }
278
+ return ExitCode.SUCCESS;
279
+ }
280
+ async handleRun(target, subArgs, signal) {
281
+ const id = subArgs.find((a) => !a.startsWith("-"));
282
+ if (!id) {
283
+ this.writeErr("Error: Action ID is required for run");
284
+ return ExitCode.INVALID_ARGUMENT;
285
+ }
286
+ let input = {};
287
+ let timeoutMs;
288
+ for (let i = 0; i < subArgs.length; i++) {
289
+ const arg = subArgs[i];
290
+ if (arg === "--timeout" && i + 1 < subArgs.length) {
291
+ timeoutMs = parseDuration(subArgs[++i]);
292
+ }
293
+ else if (arg.startsWith("--timeout=")) {
294
+ timeoutMs = parseDuration(arg.slice(10));
295
+ }
296
+ else if (arg === "--input" && i + 1 < subArgs.length) {
297
+ try {
298
+ input = JSON.parse(subArgs[++i]);
299
+ }
300
+ catch (e) {
301
+ this.writeErr(`Error parsing --input JSON: ${e.message}`);
302
+ return ExitCode.INVALID_ARGUMENT;
303
+ }
304
+ }
305
+ else if (arg.startsWith("--input=")) {
306
+ try {
307
+ input = JSON.parse(arg.slice(8));
308
+ }
309
+ catch (e) {
310
+ this.writeErr(`Error parsing --input JSON: ${e.message}`);
311
+ return ExitCode.INVALID_ARGUMENT;
312
+ }
313
+ }
314
+ else if (arg === "--input-file" && i + 1 < subArgs.length) {
315
+ try {
316
+ input = JSON.parse(readFileSync(subArgs[++i], "utf-8"));
317
+ }
318
+ catch (e) {
319
+ this.writeErr(`Error reading --input-file: ${e.message}`);
320
+ return ExitCode.INVALID_ARGUMENT;
321
+ }
322
+ }
323
+ }
324
+ const result = await target.runAction(id, input, {
325
+ signal,
326
+ timeoutMs,
327
+ });
328
+ this.writeOut(JSON.stringify(result, null, 2));
329
+ return result.ok ? ExitCode.SUCCESS : ExitCode.FAILURE;
330
+ }
331
+ async handleConfig(target, subArgs) {
332
+ const sub = subArgs[0] || "list";
333
+ if (sub === "list") {
334
+ const views = await target.listConfig(this.options.packageId);
335
+ const dict = {};
336
+ for (const v of views) {
337
+ if (v.configured && v.value !== undefined) {
338
+ dict[v.key] = v.value;
339
+ }
340
+ }
341
+ this.writeOut(JSON.stringify(dict, null, 2));
342
+ return ExitCode.SUCCESS;
343
+ }
344
+ if (sub === "get") {
345
+ const key = subArgs[1];
346
+ if (!key) {
347
+ this.writeErr("Error: config key required");
348
+ return ExitCode.INVALID_ARGUMENT;
349
+ }
350
+ try {
351
+ const item = await target.getConfig(this.options.packageId, key);
352
+ this.writeOut(item.configured ? JSON.stringify(item.value) : "undefined");
353
+ return ExitCode.SUCCESS;
354
+ }
355
+ catch {
356
+ this.writeOut("undefined");
357
+ return ExitCode.SUCCESS;
358
+ }
359
+ }
360
+ if (sub === "set") {
361
+ const key = subArgs[1];
362
+ const rawVal = subArgs[2];
363
+ if (!key || rawVal === undefined) {
364
+ this.writeErr("Error: key and value required");
365
+ return ExitCode.INVALID_ARGUMENT;
366
+ }
367
+ let parsed = rawVal;
368
+ try {
369
+ parsed = JSON.parse(rawVal);
370
+ }
371
+ catch {
372
+ parsed = rawVal;
373
+ }
374
+ await target.setConfig(this.options.packageId, key, parsed);
375
+ this.writeOut(`Config '${key}' updated`);
376
+ return ExitCode.SUCCESS;
377
+ }
378
+ if (sub === "delete") {
379
+ const key = subArgs[1];
380
+ if (!key) {
381
+ this.writeErr("Error: config key required");
382
+ return ExitCode.INVALID_ARGUMENT;
383
+ }
384
+ await target.deleteConfig(this.options.packageId, key);
385
+ this.writeOut(`Config '${key}' deleted`);
386
+ return ExitCode.SUCCESS;
387
+ }
388
+ this.writeErr(`Unknown config subcommand: '${sub}'`);
389
+ return ExitCode.INVALID_ARGUMENT;
390
+ }
391
+ async handleState(target, subArgs) {
392
+ const sub = subArgs[0] || "list";
393
+ let namespace;
394
+ let isAll = false;
395
+ let isJson = false;
396
+ for (let i = 1; i < subArgs.length; i++) {
397
+ if ((subArgs[i] === "-n" || subArgs[i] === "--namespace") && i + 1 < subArgs.length) {
398
+ namespace = subArgs[++i];
399
+ }
400
+ else if (subArgs[i].startsWith("--namespace=")) {
401
+ namespace = subArgs[i].slice(12);
402
+ }
403
+ else if (subArgs[i] === "-a" || subArgs[i] === "--all") {
404
+ isAll = true;
405
+ }
406
+ else if (subArgs[i] === "--json") {
407
+ isJson = true;
408
+ }
409
+ }
410
+ if (sub === "list") {
411
+ const prefix = subArgs[1] && !subArgs[1].startsWith("-") ? subArgs[1] : "";
412
+ const keys = await target.listStateKeys(this.options.packageId, "", {
413
+ namespace,
414
+ prefix: prefix || undefined,
415
+ all: isAll,
416
+ });
417
+ this.writeOut(JSON.stringify(keys, null, 2));
418
+ return ExitCode.SUCCESS;
419
+ }
420
+ if (sub === "get") {
421
+ const key = subArgs[1] && !subArgs[1].startsWith("-") ? subArgs[1] : subArgs[2];
422
+ if (!key) {
423
+ this.writeErr("Error: state key required");
424
+ return ExitCode.INVALID_ARGUMENT;
425
+ }
426
+ let ns = namespace;
427
+ let actualKey = key;
428
+ if (ns === undefined && key.includes(":")) {
429
+ const colonIdx = key.indexOf(":");
430
+ ns = key.slice(0, colonIdx);
431
+ actualKey = key.slice(colonIdx + 1);
432
+ }
433
+ const val = await target.getState(this.options.packageId, "", actualKey, { namespace: ns });
434
+ if (isJson) {
435
+ this.writeOut(JSON.stringify({ key, value: val }, null, 2));
436
+ }
437
+ else {
438
+ this.writeOut(val !== undefined ? JSON.stringify(val) : "undefined");
439
+ }
440
+ return ExitCode.SUCCESS;
441
+ }
442
+ if (sub === "set") {
443
+ const key = subArgs[1];
444
+ const rawVal = subArgs[2];
445
+ if (!key || rawVal === undefined) {
446
+ this.writeErr("Error: key and value required");
447
+ return ExitCode.INVALID_ARGUMENT;
448
+ }
449
+ let ns = namespace || "";
450
+ let actualKey = key;
451
+ if (namespace === undefined && key.includes(":")) {
452
+ const colonIdx = key.indexOf(":");
453
+ ns = key.slice(0, colonIdx);
454
+ actualKey = key.slice(colonIdx + 1);
455
+ }
456
+ let parsed = rawVal;
457
+ try {
458
+ parsed = JSON.parse(rawVal);
459
+ }
460
+ catch {
461
+ parsed = rawVal;
462
+ }
463
+ let ttl;
464
+ for (let i = 3; i < subArgs.length; i++) {
465
+ if (subArgs[i] === "--ttl" && i + 1 < subArgs.length) {
466
+ ttl = parseInt(subArgs[++i], 10);
467
+ }
468
+ else if (subArgs[i].startsWith("--ttl=")) {
469
+ ttl = parseInt(subArgs[i].slice(6), 10);
470
+ }
471
+ }
472
+ await target.setState(this.options.packageId, "", actualKey, parsed, { namespace: ns, ttl });
473
+ const displayKey = ns ? `${ns}:${actualKey}` : actualKey;
474
+ this.writeOut(`State '${displayKey}' updated`);
475
+ return ExitCode.SUCCESS;
476
+ }
477
+ if (sub === "delete" || sub === "rm") {
478
+ const key = subArgs[1] && !subArgs[1].startsWith("-") ? subArgs[1] : subArgs[2];
479
+ if (!key) {
480
+ this.writeErr("Error: state key required");
481
+ return ExitCode.INVALID_ARGUMENT;
482
+ }
483
+ const deleted = await target.deleteState(this.options.packageId, "", key, { namespace });
484
+ if (deleted) {
485
+ this.writeOut(`State '${key}' deleted`);
486
+ return ExitCode.SUCCESS;
487
+ }
488
+ this.writeErr(`Error: State key '${key}' not found`);
489
+ return ExitCode.FAILURE;
490
+ }
491
+ if (sub === "clear" || sub === "clean") {
492
+ const prefix = subArgs[1] && !subArgs[1].startsWith("-") ? subArgs[1] : "";
493
+ const count = await target.clearState(this.options.packageId, "", {
494
+ namespace,
495
+ all: isAll,
496
+ prefix: prefix || undefined,
497
+ });
498
+ this.writeOut(`Cleared ${count} state entry(s)`);
499
+ return ExitCode.SUCCESS;
500
+ }
501
+ this.writeErr(`Unknown state subcommand: '${sub}'`);
502
+ return ExitCode.INVALID_ARGUMENT;
503
+ }
504
+ printHelp() {
505
+ this.writeOut(`${this.options.packageId} (v${this.options.version})`);
506
+ if (this.options.description)
507
+ this.writeOut(`${this.options.description}\n`);
508
+ this.writeOut("Usage:");
509
+ this.writeOut(" <cmd> list [--json] List available actions");
510
+ this.writeOut(" <cmd> describe <id> [--json] Show action details and schemas");
511
+ this.writeOut(" <cmd> run <id> [--input '<json>'] Execute action with JSON input");
512
+ this.writeOut(" <cmd> config list/get/set/delete Manage package configuration");
513
+ this.writeOut(" <cmd> state list/get/set/delete Manage shared state store");
514
+ this.writeOut("\nGlobal options:");
515
+ this.writeOut(" --data-dir <path> Custom runtime database directory");
516
+ this.writeOut(" --config <KEY=val> Temporary config override");
517
+ }
518
+ }
519
+ export class StandaloneRuntime {
520
+ dispatcher;
521
+ constructor(options) {
522
+ this.dispatcher = new StandaloneDispatcher(options);
523
+ }
524
+ async run(argv) {
525
+ const code = await this.dispatcher.dispatch(argv);
526
+ if (code !== ExitCode.SUCCESS && code !== ExitCode.FAILURE) {
527
+ process.exit(code);
528
+ }
529
+ }
530
+ }
531
+ /**
532
+ * 工厂函数:创建独立运行时实例。
533
+ */
534
+ export function createStandaloneRuntime(options) {
535
+ return new StandaloneRuntime(options);
536
+ }