@actiondock/core 2.0.12 → 2.2.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.
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 +621 -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 +116 -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
@@ -0,0 +1,2 @@
1
+ export * from "./types.js";
2
+ export * from "./app.js";
@@ -0,0 +1,283 @@
1
+ import type { ActionDefinition, ActionRef, ExecutionEvent, ExecutionResult, JsonValue, Logger, ProcessAPI, RunRecord } from "@actiondock/sdk";
2
+ import type { CancelResult, ExecuteOptions, ExecutionService, ExecutionTicket } from "../execution/types.js";
3
+ import type { ConfigItemDefinition, ProjectConfig } from "../project/types.js";
4
+ import type { Clock } from "../runtime/clock.js";
5
+ import type { EventSink } from "../runtime/events.js";
6
+ import type { RuntimePlatform, StorageFactory, StorageFactoryOptions } from "../platform/types.js";
7
+ import type { RuntimeStorage } from "../storage/types.js";
8
+ import type { ConfigValueView, StateScopeOptions } from "../target/types.js";
9
+ export type { ConfigValueView, RuntimePlatform, StateScopeOptions, StorageFactory, StorageFactoryOptions };
10
+ /**
11
+ * 宏包信息契约。
12
+ */
13
+ export interface PackageInfo {
14
+ /** 包唯一标识 */
15
+ id: string;
16
+ /** 包名称 */
17
+ name: string;
18
+ /** 包语义化版本号 */
19
+ version: string;
20
+ /** 包描述信息 */
21
+ description?: string;
22
+ /** 包根目录绝对物理路径 */
23
+ packageRoot?: string;
24
+ /** Action 脚本文件目录 */
25
+ actionsDir?: string;
26
+ /** Playbook SOP 文档目录 */
27
+ playbooksDir?: string;
28
+ /** 声明的项目依赖配置项清单 */
29
+ config?: Record<string, ConfigItemDefinition>;
30
+ /** 动作总数统计 */
31
+ actionsCount?: number;
32
+ /** 规程总数统计 */
33
+ playbooksCount?: number;
34
+ /** 动作标识符列表 */
35
+ actions?: string[];
36
+ /** 规程标识符列表 */
37
+ playbooks?: string[];
38
+ }
39
+ /**
40
+ * Action 简要摘要条目。
41
+ */
42
+ export interface ActionSummary {
43
+ /** Action 唯一标识 */
44
+ id: string;
45
+ /** 所属包唯一标识 */
46
+ packageId?: string;
47
+ /** Action 描述信息 */
48
+ description?: string;
49
+ /** 标签列表 */
50
+ tags?: string[];
51
+ /** 入口文件相对路径 */
52
+ entry?: string;
53
+ /** 协议注解元数据 */
54
+ annotations?: Record<string, unknown>;
55
+ /** 静态依赖的 Action 列表 */
56
+ uses?: string[];
57
+ /** 输入模式规范 */
58
+ inputSchema?: Record<string, unknown> | boolean;
59
+ /** 输出模式规范 */
60
+ outputSchema?: Record<string, unknown> | boolean;
61
+ }
62
+ /**
63
+ * Action 完整规范说明契约。
64
+ */
65
+ export interface ActionSpec {
66
+ /** Action 唯一标识 */
67
+ id: string;
68
+ /** 所属包唯一标识 */
69
+ packageId?: string;
70
+ /** Action 描述信息 */
71
+ description?: string;
72
+ /** 输入模式规范 */
73
+ inputSchema?: Record<string, unknown> | boolean;
74
+ /** 输出模式规范 */
75
+ outputSchema?: Record<string, unknown> | boolean;
76
+ /** 标签列表 */
77
+ tags?: string[];
78
+ /** 协议注解元数据 */
79
+ annotations?: Record<string, unknown>;
80
+ /** 静态依赖的 Action 列表 */
81
+ uses?: string[];
82
+ /** 入口文件相对路径 */
83
+ entry?: string;
84
+ /** 入口文件物理绝对路径 */
85
+ filePath?: string;
86
+ }
87
+ /**
88
+ * Action 列表检索查询选项。
89
+ */
90
+ export interface ListActionsOptions {
91
+ /** 标签筛选过滤列表 */
92
+ tags?: string[];
93
+ /** 模糊检索关键词(匹配标识或描述) */
94
+ query?: string;
95
+ /** 标识前缀过滤 */
96
+ prefix?: string;
97
+ }
98
+ /**
99
+ * Playbook 规程简要摘要条目。
100
+ */
101
+ export interface PlaybookSummary {
102
+ /** Playbook 唯一标识 */
103
+ id: string;
104
+ /** 所属包唯一标识 */
105
+ packageId?: string;
106
+ /** Playbook 描述信息 */
107
+ description?: string;
108
+ /** 规程所依赖或调用的 Action 列表 */
109
+ actions?: string[];
110
+ /** 物理源文件路径 */
111
+ filePath?: string;
112
+ }
113
+ /**
114
+ * Playbook 规程完整规范说明契约。
115
+ */
116
+ export interface PlaybookSpec {
117
+ /** Playbook 唯一标识 */
118
+ id: string;
119
+ /** 所属包唯一标识 */
120
+ packageId?: string;
121
+ /** Playbook 描述信息 */
122
+ description?: string;
123
+ /** 规程所依赖或调用的 Action 列表 */
124
+ actions?: string[];
125
+ /** Markdown 正文规程操作指南内容 */
126
+ content: string;
127
+ /** 物理源文件路径 */
128
+ filePath?: string;
129
+ }
130
+ /**
131
+ * 持久化状态读写操作选项。
132
+ */
133
+ export interface StateOptions {
134
+ /** 状态隔离命名空间 */
135
+ namespace?: string;
136
+ /** 存活有效期(秒),仅在设置状态时生效 */
137
+ ttl?: number;
138
+ }
139
+ /**
140
+ * ActionDockApp 初始化配置选项。
141
+ */
142
+ export interface ActionDockAppOptions {
143
+ /** 项目根目录绝对物理路径 */
144
+ packageRoot?: string;
145
+ /** 项目配置文件 (actiondock.json) 对象 */
146
+ projectConfig?: ProjectConfig;
147
+ /** 显式注入的运行时平台适配 */
148
+ platform?: RuntimePlatform;
149
+ /** 显式注入的项目级运行时存储实例 */
150
+ storage?: RuntimeStorage;
151
+ /** 显式注入的全局运行时存储实例 */
152
+ globalStorage?: RuntimeStorage;
153
+ /** 显式注入的事件接收器 */
154
+ eventSink?: EventSink;
155
+ /** 数据持久化存储目录 */
156
+ dataDir?: string;
157
+ /** 自定义家目录绝对路径 */
158
+ customHome?: string;
159
+ /** 是否采用纯内存运行模式 */
160
+ inMemory?: boolean;
161
+ /** 显式注入或预注册的 Action 集合 */
162
+ actions?: Map<string, ActionDefinition> | Array<{
163
+ id: string;
164
+ action: ActionDefinition;
165
+ } | (ActionDefinition & {
166
+ id: string;
167
+ })> | Record<string, ActionDefinition>;
168
+ /** 跨包或动态 Action 解析器 */
169
+ actionResolver?: (ref: ActionRef | string) => ActionDefinition | undefined | Promise<ActionDefinition | undefined>;
170
+ /** 跨包运行上下文解析委托函数 */
171
+ packageContextResolver?: (packageId: string) => Promise<{
172
+ projectRoot?: string;
173
+ projectConfig?: ProjectConfig;
174
+ storage: RuntimeStorage;
175
+ actions?: Map<string, ActionDefinition>;
176
+ } | undefined> | {
177
+ projectRoot?: string;
178
+ projectConfig?: ProjectConfig;
179
+ storage: RuntimeStorage;
180
+ actions?: Map<string, ActionDefinition>;
181
+ } | undefined;
182
+ /** 临时配置覆写字典 */
183
+ configOverrides?: Record<string, unknown>;
184
+ /** 宿主所有者标识 */
185
+ ownerId?: string;
186
+ /** 最大并发活跃运行数 */
187
+ maxActiveRuns?: number;
188
+ /** 最大调用嵌套深度 */
189
+ maxCallDepth?: number;
190
+ /** 最大子任务数限制 */
191
+ maxSubRuns?: number;
192
+ /** 执行宿主会话标识 */
193
+ hostSessionId?: string;
194
+ /** 日志记录器 */
195
+ logger?: Logger;
196
+ /** 时钟源 */
197
+ clock?: Clock;
198
+ /** 进程执行器 */
199
+ process?: ProcessAPI;
200
+ /** 是否暴露调试与物理路径信息 */
201
+ exposeDebugInfo?: boolean;
202
+ }
203
+ /**
204
+ * ActionDock 统一应用领域契约。
205
+ * 作为单个 Action Package 的唯一运行单元与对外门面。
206
+ */
207
+ export interface ActionDockApp {
208
+ /** 包唯一标识 */
209
+ readonly packageId: string;
210
+ /** 包根目录绝对物理路径 */
211
+ readonly packageRoot?: string;
212
+ /** 项目配置对象(actiondock.json 解析结果) */
213
+ readonly projectConfig: ProjectConfig;
214
+ /** 底层运行平台驱动适配契约 */
215
+ readonly platform: RuntimePlatform;
216
+ /** 当前包持久化存储实例 */
217
+ readonly storage: RuntimeStorage;
218
+ /** 全局持久化存储实例 */
219
+ readonly globalStorage?: RuntimeStorage;
220
+ /** 统一执行协调服务实例 */
221
+ readonly executionService: ExecutionService;
222
+ /** 预加载的 Action 定义映射表(短标识至定义) */
223
+ readonly actionsMap: Map<string, ActionDefinition>;
224
+ /** 获取当前包元数据信息 */
225
+ info(options?: {
226
+ exposeDebugInfo?: boolean;
227
+ }): Promise<PackageInfo>;
228
+ /** 静态列出当前包中所有可用的 Action 摘要 */
229
+ listActions(options?: ListActionsOptions): Promise<ActionSummary[]>;
230
+ /** 静态查询并返回指定 Action 的规范结构与模式定义 */
231
+ describeAction(id: string): Promise<ActionSpec>;
232
+ /** 静态列出当前包中所有可用的 Playbook 摘要 */
233
+ listPlaybooks(): Promise<PlaybookSummary[]>;
234
+ /** 静态查询并返回指定 Playbook 的规范内容与操作指南 */
235
+ describePlaybook(id: string): Promise<PlaybookSpec>;
236
+ /** 同步执行指定 Action 并等待终态结果(仅接受本包短标识) */
237
+ runAction(id: string, input: JsonValue, options?: ExecuteOptions): Promise<ExecutionResult>;
238
+ /** 异步启动指定 Action 并立即返回任务执行票据(仅接受本包短标识) */
239
+ startAction(id: string, input: JsonValue, options?: ExecuteOptions): Promise<ExecutionTicket>;
240
+ /** 查询指定运行标识的记录详情 */
241
+ getRun(runId: string): Promise<RunRecord | undefined>;
242
+ /** 取消指定在运行的任务 */
243
+ cancelRun(runId: string, reason?: string): Promise<CancelResult>;
244
+ /** 订阅指定运行的事件流 */
245
+ events(runId: string, options?: {
246
+ after?: number | string;
247
+ signal?: AbortSignal;
248
+ maxQueueSize?: number;
249
+ }): AsyncIterable<ExecutionEvent>;
250
+ /** 列出当前包的所有配置安全视图 */
251
+ listConfig(): Promise<ConfigValueView[]>;
252
+ /** 获取指定配置项的安全视图(按五层优先级链解析) */
253
+ getConfig(key: string): Promise<ConfigValueView>;
254
+ /** 写入持久化配置项 */
255
+ setConfig(key: string, value: JsonValue): Promise<void>;
256
+ /** 删除持久化配置项 */
257
+ deleteConfig(key: string): Promise<boolean>;
258
+ /** 获取指定持久化状态值 */
259
+ getState<T extends JsonValue = JsonValue>(key: string, options?: StateScopeOptions): Promise<T | undefined>;
260
+ getState<T extends JsonValue = JsonValue>(actionId: string, key: string, options?: StateScopeOptions): Promise<T | undefined>;
261
+ /** 写入指定持久化状态值 */
262
+ setState<T extends JsonValue = JsonValue>(key: string, value: T, options?: StateScopeOptions): Promise<void>;
263
+ setState<T extends JsonValue = JsonValue>(actionId: string, key: string, value: T, options: StateScopeOptions): Promise<void>;
264
+ /** 删除指定持久化状态项 */
265
+ deleteState(key: string, options?: StateScopeOptions): Promise<boolean>;
266
+ deleteState(actionId: string, key: string, options?: StateScopeOptions): Promise<boolean>;
267
+ /** 显式获取指定 Action 命名空间的状态值 */
268
+ getActionState<T extends JsonValue = JsonValue>(actionId: string, key: string, options?: StateScopeOptions): Promise<T | undefined>;
269
+ /** 显式写入指定 Action 命名空间的状态值 */
270
+ setActionState<T extends JsonValue = JsonValue>(actionId: string, key: string, value: T, options?: StateScopeOptions): Promise<void>;
271
+ /** 显式删除指定 Action 命名空间的状态项 */
272
+ deleteActionState(actionId: string, key: string, options?: StateScopeOptions): Promise<boolean>;
273
+ /** 列出所有状态键 */
274
+ listStateKeys(options?: StateScopeOptions): Promise<string[]>;
275
+ listStateKeys(actionId: string, options?: StateScopeOptions): Promise<string[]>;
276
+ /** 清空指定持久化状态项 */
277
+ clearState(options?: StateScopeOptions): Promise<number>;
278
+ clearState(actionId: string, options?: StateScopeOptions): Promise<number>;
279
+ /** 优雅关闭应用并收尾清理所有底层资源 */
280
+ close(options?: {
281
+ graceMs?: number;
282
+ }): Promise<void>;
283
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,4 +1,4 @@
1
- import type { CatalogSnapshot, IndexedAction } from "./types";
1
+ import type { CatalogSnapshot, IndexedAction } from "./types.js";
2
2
  export declare class ActionIndex {
3
3
  private actions;
4
4
  constructor(snapshot: CatalogSnapshot);
@@ -0,0 +1,93 @@
1
+ import { existsSync, readdirSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { loadManifest } from "../project/manifest.js";
4
+ export class ActionIndex {
5
+ actions = new Map(); // actionId -> IndexedAction[]
6
+ constructor(snapshot) {
7
+ this.indexSnapshot(snapshot);
8
+ }
9
+ indexSnapshot(snapshot) {
10
+ for (const [packageId, pkg] of snapshot.packages) {
11
+ let manifest = null;
12
+ try {
13
+ manifest = loadManifest(pkg.projectRoot);
14
+ }
15
+ catch {
16
+ // Skip invalid manifest during catalog indexing
17
+ }
18
+ if (manifest && manifest.actions) {
19
+ for (const [actionId, item] of Object.entries(manifest.actions)) {
20
+ const indexed = {
21
+ packageId,
22
+ actionId,
23
+ contract: {
24
+ id: actionId,
25
+ description: item.description,
26
+ inputSchema: item.inputSchema,
27
+ outputSchema: item.outputSchema,
28
+ uses: item.uses,
29
+ tags: item.tags,
30
+ annotations: item.annotations,
31
+ },
32
+ entry: item.entry,
33
+ projectRoot: pkg.projectRoot,
34
+ };
35
+ this.add(indexed);
36
+ }
37
+ }
38
+ else {
39
+ // 向后兼容回退:若未提供清单,扫描 actions 目录生成基础索引
40
+ const actionsDir = join(pkg.projectRoot, pkg.config.actionsDir || "actions");
41
+ if (existsSync(actionsDir)) {
42
+ try {
43
+ const files = readdirSync(actionsDir);
44
+ for (const file of files) {
45
+ if (file.endsWith(".ts") || file.endsWith(".js")) {
46
+ const actionId = file.replace(/\.(ts|js)$/, "");
47
+ const indexed = {
48
+ packageId,
49
+ actionId,
50
+ contract: {
51
+ id: actionId,
52
+ },
53
+ entry: join(pkg.config.actionsDir || "actions", file),
54
+ projectRoot: pkg.projectRoot,
55
+ };
56
+ this.add(indexed);
57
+ }
58
+ }
59
+ }
60
+ catch {
61
+ // 忽略读取目录异常
62
+ }
63
+ }
64
+ }
65
+ }
66
+ }
67
+ add(action) {
68
+ let list = this.actions.get(action.actionId);
69
+ if (!list) {
70
+ list = [];
71
+ this.actions.set(action.actionId, list);
72
+ }
73
+ list.push(action);
74
+ }
75
+ list(packageId) {
76
+ const all = [];
77
+ for (const [_, list] of this.actions) {
78
+ for (const action of list) {
79
+ if (!packageId || action.packageId === packageId) {
80
+ all.push(action);
81
+ }
82
+ }
83
+ }
84
+ return all;
85
+ }
86
+ find(actionId, packageId) {
87
+ const matches = this.actions.get(actionId) || [];
88
+ if (packageId) {
89
+ return matches.filter((a) => a.packageId === packageId);
90
+ }
91
+ return matches;
92
+ }
93
+ }
@@ -1,6 +1,6 @@
1
1
  import type { ActionRef, ResolvedActionRef } from "@actiondock/sdk";
2
- import { ActionIndex } from "./action-index";
3
- import type { CatalogSnapshot, IndexedAction } from "./types";
2
+ import { ActionIndex } from "./action-index.js";
3
+ import type { CatalogSnapshot, IndexedAction } from "./types.js";
4
4
  export interface ResolveOptions {
5
5
  currentPackageId?: string;
6
6
  }
@@ -0,0 +1,95 @@
1
+ import { ActionIndex } from "./action-index.js";
2
+ export class ActionResolver {
3
+ snapshot;
4
+ index;
5
+ constructor(snapshot, index) {
6
+ this.snapshot = snapshot;
7
+ this.index = index || new ActionIndex(snapshot);
8
+ }
9
+ /**
10
+ * 解析字符串或 ActionRef 为规范化的 ActionRef。
11
+ * 支持 greet、my-tools/greet、@team/github/issues.list。
12
+ */
13
+ static parseRef(refStringOrObj) {
14
+ if (typeof refStringOrObj === "object") {
15
+ return refStringOrObj;
16
+ }
17
+ const str = refStringOrObj.trim();
18
+ if (str.includes("/")) {
19
+ const lastSlashIndex = str.lastIndexOf("/");
20
+ const packageId = str.slice(0, lastSlashIndex);
21
+ const actionId = str.slice(lastSlashIndex + 1);
22
+ if (actionId.includes(":") || actionId.includes("/") || actionId.includes("..")) {
23
+ throw new Error(`Invalid action identifier: '${actionId}'`);
24
+ }
25
+ return { packageId, actionId };
26
+ }
27
+ // 处理旧语法 package:action 的兼容提醒
28
+ if (str.includes(":")) {
29
+ const parts = str.split(":");
30
+ throw new Error(`Legacy syntax '${str}' is deprecated. Please use '${parts.join("/")}' instead.`);
31
+ }
32
+ return { actionId: str };
33
+ }
34
+ resolve(refStringOrObj, options = {}) {
35
+ const ref = ActionResolver.parseRef(refStringOrObj);
36
+ // 1. 若指定了 packageId,直接精确匹配
37
+ if (ref.packageId) {
38
+ const matches = this.index.find(ref.actionId, ref.packageId);
39
+ if (matches.length === 0) {
40
+ throw new Error(`ACTION_NOT_FOUND: Action '${ref.actionId}' not found in package '${ref.packageId}'`);
41
+ }
42
+ const matched = matches[0];
43
+ const pkg = this.snapshot.packages.get(matched.packageId);
44
+ return {
45
+ resolved: {
46
+ packageId: matched.packageId,
47
+ packageInstanceId: pkg?.packageInstanceId || matched.packageId,
48
+ actionId: matched.actionId,
49
+ generationId: this.snapshot.generationId,
50
+ },
51
+ action: matched,
52
+ };
53
+ }
54
+ // 2. 未指定 packageId:优先查找当前调用者包
55
+ if (options.currentPackageId) {
56
+ const inCurrent = this.index.find(ref.actionId, options.currentPackageId);
57
+ if (inCurrent.length > 0) {
58
+ const matched = inCurrent[0];
59
+ const pkg = this.snapshot.packages.get(matched.packageId);
60
+ return {
61
+ resolved: {
62
+ packageId: matched.packageId,
63
+ packageInstanceId: pkg?.packageInstanceId || matched.packageId,
64
+ actionId: matched.actionId,
65
+ generationId: this.snapshot.generationId,
66
+ },
67
+ action: matched,
68
+ };
69
+ }
70
+ }
71
+ // 3. 全局唯一匹配检查
72
+ const allMatches = this.index.find(ref.actionId);
73
+ if (allMatches.length === 0) {
74
+ throw new Error(`ACTION_NOT_FOUND: Action '${ref.actionId}' not found in any linked package`);
75
+ }
76
+ if (allMatches.length > 1) {
77
+ const candidates = allMatches.map((m) => `${m.packageId}/${m.actionId}`).join(", ");
78
+ const err = new Error(`INVALID_ACTION_REF: Action '${ref.actionId}' is ambiguous and provided by multiple packages: ${candidates}. Please specify the package name. (AMBIGUOUS_ACTION_REF)`);
79
+ err.code = "INVALID_ACTION_REF";
80
+ err.details = { alias: "AMBIGUOUS_ACTION_REF" };
81
+ throw err;
82
+ }
83
+ const matched = allMatches[0];
84
+ const pkg = this.snapshot.packages.get(matched.packageId);
85
+ return {
86
+ resolved: {
87
+ packageId: matched.packageId,
88
+ packageInstanceId: pkg?.packageInstanceId || matched.packageId,
89
+ actionId: matched.actionId,
90
+ generationId: this.snapshot.generationId,
91
+ },
92
+ action: matched,
93
+ };
94
+ }
95
+ }
@@ -1,5 +1,5 @@
1
- export * from "./action-index";
2
- export * from "./action-resolver";
3
- export * from "./location-registry";
4
- export * from "./package-catalog";
5
- export * from "./types";
1
+ export * from "./action-index.js";
2
+ export * from "./action-resolver.js";
3
+ export * from "./location-registry.js";
4
+ export * from "./package-catalog.js";
5
+ export * from "./types.js";
@@ -0,0 +1,5 @@
1
+ export * from "./action-index.js";
2
+ export * from "./action-resolver.js";
3
+ export * from "./location-registry.js";
4
+ export * from "./package-catalog.js";
5
+ export * from "./types.js";
@@ -1,15 +1,15 @@
1
- import type { LocationLink, LocationRegistryData } from "./types";
1
+ import type { LocationLink, LocationRegistryData } from "./types.js";
2
2
  export declare class LocationRegistry {
3
3
  private customHome?;
4
4
  private filePath;
5
5
  constructor(customHome?: string);
6
6
  getFilePath(): string;
7
7
  load(): LocationRegistryData;
8
- save(data: LocationRegistryData): void;
8
+ save(data: LocationRegistryData): Promise<void>;
9
9
  addLink(path: string, options?: {
10
10
  type?: "package" | "workspace";
11
11
  depth?: number;
12
- }): LocationLink;
13
- removeLink(targetPathOrId: string): LocationLink | null;
14
- prune(): LocationLink[];
12
+ }): Promise<LocationLink>;
13
+ removeLink(targetPathOrId: string): Promise<LocationLink | null>;
14
+ prune(): Promise<LocationLink[]>;
15
15
  }
@@ -0,0 +1,138 @@
1
+ import { existsSync } from "node:fs";
2
+ import { resolve } from "node:path";
3
+ import { getRegistryFilePath, linkPackage, loadRegistry, loadRegistryAsync, pruneRegistry, unlinkPackage, } from "../registry/registry.js";
4
+ import { withRegistryLock } from "../registry/lock.js";
5
+ import { writeRegistryLocked } from "../registry/registry.js";
6
+ import { loadProjectConfig } from "../project/loader.js";
7
+ import { ACTIONDOCK_VERSION } from "../version.js";
8
+ export class LocationRegistry {
9
+ customHome;
10
+ filePath;
11
+ constructor(customHome) {
12
+ this.customHome = customHome;
13
+ this.filePath = getRegistryFilePath(customHome);
14
+ }
15
+ getFilePath() {
16
+ return this.filePath;
17
+ }
18
+ load() {
19
+ const reg = loadRegistry(this.customHome);
20
+ const links = [];
21
+ if (reg.workspaces) {
22
+ for (const [wsPath, ws] of Object.entries(reg.workspaces)) {
23
+ links.push({
24
+ type: "workspace",
25
+ path: resolve(ws.path || wsPath),
26
+ linkedAt: ws.linkedAt || new Date().toISOString(),
27
+ depth: 3,
28
+ });
29
+ }
30
+ }
31
+ if (reg.packages) {
32
+ for (const pkg of Object.values(reg.packages)) {
33
+ if (!pkg.workspaceRoot && pkg.path) {
34
+ links.push({
35
+ type: "package",
36
+ path: resolve(pkg.path),
37
+ linkedAt: pkg.linkedAt || new Date().toISOString(),
38
+ });
39
+ }
40
+ }
41
+ }
42
+ return { schemaVersion: 1, links };
43
+ }
44
+ async save(data) {
45
+ // 读改写整体收敛在注册表锁内完成,写入直接走锁内原子落盘,
46
+ // 避免嵌套调用 saveRegistry 造成的同路径锁重入死等
47
+ await withRegistryLock(this.filePath, async () => {
48
+ const current = await loadRegistryAsync(this.customHome);
49
+ const newPackages = {};
50
+ const newWorkspaces = {};
51
+ for (const link of data.links) {
52
+ const absPath = resolve(link.path);
53
+ if (link.type === "workspace") {
54
+ newWorkspaces[absPath] = {
55
+ path: absPath,
56
+ linkedAt: link.linkedAt || new Date().toISOString(),
57
+ };
58
+ }
59
+ else {
60
+ const existing = Object.values(current.packages || {}).find((p) => resolve(p.path) === absPath);
61
+ if (existing) {
62
+ newPackages[existing.id] = existing;
63
+ }
64
+ else if (existsSync(absPath)) {
65
+ try {
66
+ const config = loadProjectConfig(absPath);
67
+ newPackages[config.id] = {
68
+ id: config.id,
69
+ name: config.name || config.id,
70
+ version: config.version || "0.0.0",
71
+ path: absPath,
72
+ linkedAt: link.linkedAt || new Date().toISOString(),
73
+ };
74
+ }
75
+ catch {
76
+ // 项目损坏或配置非法:跳过该链接条目,避免保存整体失败
77
+ }
78
+ }
79
+ }
80
+ }
81
+ await writeRegistryLocked({
82
+ version: ACTIONDOCK_VERSION,
83
+ packages: newPackages,
84
+ workspaces: newWorkspaces,
85
+ }, this.customHome);
86
+ });
87
+ }
88
+ async addLink(path, options = {}) {
89
+ const type = options.type || "package";
90
+ if (type === "workspace") {
91
+ const res = await linkPackage(path, this.customHome, { recursive: true });
92
+ return {
93
+ type: "workspace",
94
+ path: resolve(path),
95
+ linkedAt: res.linkedAt,
96
+ depth: options.depth ?? 3,
97
+ };
98
+ }
99
+ else {
100
+ const res = await linkPackage(path, this.customHome, { recursive: false });
101
+ return {
102
+ type: "package",
103
+ path: resolve(path),
104
+ linkedAt: res.linkedAt,
105
+ };
106
+ }
107
+ }
108
+ async removeLink(targetPathOrId) {
109
+ const unres = await unlinkPackage(targetPathOrId, this.customHome);
110
+ if (!unres || (!unres.removedPackage && !unres.packagesCount)) {
111
+ return null;
112
+ }
113
+ return {
114
+ type: unres.type,
115
+ path: unres.path,
116
+ linkedAt: new Date().toISOString(),
117
+ };
118
+ }
119
+ async prune() {
120
+ const pruneRes = await pruneRegistry(this.customHome);
121
+ const removed = [];
122
+ for (const pkg of pruneRes.prunedPackages) {
123
+ removed.push({
124
+ type: "package",
125
+ path: pkg.path,
126
+ linkedAt: pkg.linkedAt,
127
+ });
128
+ }
129
+ for (const ws of pruneRes.prunedWorkspaces) {
130
+ removed.push({
131
+ type: "workspace",
132
+ path: ws.path,
133
+ linkedAt: ws.linkedAt,
134
+ });
135
+ }
136
+ return removed;
137
+ }
138
+ }
@@ -1,5 +1,5 @@
1
- import { LocationRegistry } from "./location-registry";
2
- import type { CatalogSnapshot } from "./types";
1
+ import { LocationRegistry } from "./location-registry.js";
2
+ import type { CatalogSnapshot } from "./types.js";
3
3
  export declare class PackageCatalog {
4
4
  private registry;
5
5
  constructor(registry?: LocationRegistry);