@actiondock/core 2.7.0 → 2.9.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 (243) hide show
  1. package/README.md +77 -64
  2. package/dist/catalog/action-catalog.d.ts +56 -0
  3. package/dist/catalog/action-catalog.js +202 -0
  4. package/dist/catalog/discovery.d.ts +60 -0
  5. package/dist/catalog/discovery.js +119 -0
  6. package/dist/catalog/graph.d.ts +190 -0
  7. package/dist/catalog/graph.js +589 -0
  8. package/dist/catalog/index.d.ts +5 -5
  9. package/dist/catalog/index.js +5 -5
  10. package/dist/catalog/resolve-action.d.ts +43 -0
  11. package/dist/catalog/resolve-action.js +119 -0
  12. package/dist/catalog/resolve-playbook.d.ts +26 -0
  13. package/dist/catalog/resolve-playbook.js +114 -0
  14. package/dist/doctor/checks/project.js +27 -8
  15. package/dist/doctor/checks/registry.js +2 -2
  16. package/dist/doctor/checks/runtime.js +34 -1
  17. package/dist/errors.d.ts +106 -10
  18. package/dist/errors.js +105 -10
  19. package/dist/execution/service.d.ts +18 -16
  20. package/dist/execution/service.js +183 -252
  21. package/dist/execution/types.d.ts +25 -69
  22. package/dist/execution/types.js +2 -1
  23. package/dist/filter/intent.d.ts +8 -9
  24. package/dist/filter/intent.js +49 -10
  25. package/dist/graph/index.d.ts +4 -0
  26. package/dist/graph/index.js +4 -0
  27. package/dist/host/host.d.ts +74 -32
  28. package/dist/host/host.js +585 -336
  29. package/dist/host/routing.d.ts +15 -48
  30. package/dist/host/routing.js +90 -153
  31. package/dist/host/types.d.ts +50 -17
  32. package/dist/index.d.ts +21 -24
  33. package/dist/index.js +19 -23
  34. package/dist/input/advice.d.ts +5 -1
  35. package/dist/input/advice.js +163 -214
  36. package/dist/input/describe.d.ts +1 -1
  37. package/dist/input/flat-errors.d.ts +5 -6
  38. package/dist/input/flat-errors.js +6 -6
  39. package/dist/input/flat-materializer.js +42 -44
  40. package/dist/invocation/index.d.ts +2 -0
  41. package/dist/invocation/index.js +2 -0
  42. package/dist/invocation/policy.d.ts +157 -0
  43. package/dist/invocation/policy.js +231 -0
  44. package/dist/invocation/types.d.ts +172 -0
  45. package/dist/invocation/types.js +97 -0
  46. package/dist/ipc/diagnostic.d.ts +0 -12
  47. package/dist/ipc/diagnostic.js +0 -21
  48. package/dist/ipc/host.d.ts +4 -4
  49. package/dist/ipc/host.js +44 -47
  50. package/dist/ipc/index.d.ts +1 -1
  51. package/dist/ipc/index.js +1 -1
  52. package/dist/ipc/service.d.ts +40 -0
  53. package/dist/ipc/service.js +349 -0
  54. package/dist/ipc/types.d.ts +21 -15
  55. package/dist/node/index.d.ts +1 -0
  56. package/dist/node/index.js +1 -0
  57. package/dist/node/module-loader.d.ts +63 -0
  58. package/dist/node/module-loader.js +112 -0
  59. package/dist/package/index.d.ts +23 -0
  60. package/dist/package/index.js +18 -0
  61. package/dist/{app/app.d.ts → package/runtime.d.ts} +41 -20
  62. package/dist/{app/app.js → package/runtime.js} +140 -95
  63. package/dist/{app → package}/static-index.js +58 -41
  64. package/dist/package/storage-view.d.ts +13 -0
  65. package/dist/package/storage-view.js +22 -0
  66. package/dist/{app → package}/types.d.ts +76 -57
  67. package/dist/package/types.js +22 -0
  68. package/dist/platform/index.d.ts +1 -1
  69. package/dist/platform/index.js +1 -1
  70. package/dist/platform/node.d.ts +48 -0
  71. package/dist/platform/node.js +96 -0
  72. package/dist/platform/types.d.ts +0 -9
  73. package/dist/process/control-arbiter.d.ts +2 -1
  74. package/dist/process/control-arbiter.js +1 -2
  75. package/dist/process/driver.d.ts +9 -8
  76. package/dist/process/driver.js +11 -22
  77. package/dist/process/index.d.ts +2 -0
  78. package/dist/process/index.js +2 -0
  79. package/dist/process/managed-record.d.ts +2 -2
  80. package/dist/process/process-driver.d.ts +109 -0
  81. package/dist/process/process-driver.js +650 -0
  82. package/dist/process/process-executor.d.ts +47 -0
  83. package/dist/process/process-executor.js +296 -0
  84. package/dist/process/process-manager.js +48 -26
  85. package/dist/process/run-executor.js +12 -12
  86. package/dist/profile/client-actions.js +2 -2
  87. package/dist/profile/client-health.js +2 -2
  88. package/dist/profile/client-query.js +5 -6
  89. package/dist/profile/client-transport.d.ts +19 -17
  90. package/dist/profile/client-transport.js +47 -80
  91. package/dist/profile/client.d.ts +2 -2
  92. package/dist/profile/client.js +1 -1
  93. package/dist/profile/index.d.ts +1 -0
  94. package/dist/profile/index.js +1 -0
  95. package/dist/profile/manager.d.ts +5 -0
  96. package/dist/profile/manager.js +41 -6
  97. package/dist/project/closure.js +2 -2
  98. package/dist/project/index.d.ts +8 -1
  99. package/dist/project/index.js +10 -1
  100. package/dist/project/init.js +2 -2
  101. package/dist/project/loader.d.ts +1 -1
  102. package/dist/project/loader.js +26 -29
  103. package/dist/project/transactions.js +5 -10
  104. package/dist/project/types.d.ts +5 -0
  105. package/dist/registry/index.d.ts +3 -1
  106. package/dist/registry/index.js +2 -1
  107. package/dist/registry/lock.d.ts +28 -7
  108. package/dist/registry/lock.js +136 -16
  109. package/dist/registry/registry.d.ts +1 -5
  110. package/dist/registry/registry.js +1 -53
  111. package/dist/registry/scan.d.ts +0 -15
  112. package/dist/registry/scan.js +0 -59
  113. package/dist/registry/store.d.ts +42 -0
  114. package/dist/registry/store.js +43 -0
  115. package/dist/registry/types.d.ts +0 -24
  116. package/dist/runtime/action-collection.d.ts +1 -1
  117. package/dist/runtime/action-registry.d.ts +0 -4
  118. package/dist/runtime/action-registry.js +0 -7
  119. package/dist/runtime/context.js +5 -11
  120. package/dist/runtime/events.js +3 -6
  121. package/dist/runtime/identity.d.ts +22 -0
  122. package/dist/runtime/identity.js +10 -0
  123. package/dist/runtime/index.d.ts +1 -2
  124. package/dist/runtime/index.js +1 -2
  125. package/dist/runtime/module-loader.d.ts +2 -34
  126. package/dist/runtime/module-loader.js +1 -16
  127. package/dist/runtime/process.d.ts +6 -24
  128. package/dist/runtime/process.js +1 -118
  129. package/dist/runtime/run-persistence.js +2 -5
  130. package/dist/runtime/runner.d.ts +33 -93
  131. package/dist/runtime/runner.js +132 -364
  132. package/dist/runtime/standalone.d.ts +23 -8
  133. package/dist/runtime/standalone.js +100 -147
  134. package/dist/server/body.d.ts +16 -8
  135. package/dist/server/body.js +33 -16
  136. package/dist/server/dispatcher.d.ts +6 -10
  137. package/dist/server/dispatcher.js +24 -32
  138. package/dist/server/http-server.d.ts +87 -0
  139. package/dist/server/http-server.js +304 -0
  140. package/dist/server/index.d.ts +12 -0
  141. package/dist/server/index.js +11 -0
  142. package/dist/server/mcp-endpoint.d.ts +61 -0
  143. package/dist/server/mcp-endpoint.js +118 -0
  144. package/dist/server/policy.d.ts +138 -0
  145. package/dist/server/policy.js +368 -0
  146. package/dist/server/routes/actions.js +114 -64
  147. package/dist/server/routes/common.d.ts +18 -33
  148. package/dist/server/routes/common.js +45 -65
  149. package/dist/server/routes/config.d.ts +1 -1
  150. package/dist/server/routes/config.js +55 -65
  151. package/dist/server/routes/doctor.d.ts +1 -1
  152. package/dist/server/routes/doctor.js +13 -21
  153. package/dist/server/routes/health.d.ts +1 -1
  154. package/dist/server/routes/health.js +4 -5
  155. package/dist/server/routes/info.d.ts +2 -2
  156. package/dist/server/routes/info.js +17 -24
  157. package/dist/server/routes/playbooks.js +23 -36
  158. package/dist/server/routes/runs.js +151 -141
  159. package/dist/server/routes/state.d.ts +1 -1
  160. package/dist/server/routes/state.js +64 -63
  161. package/dist/server/security.d.ts +11 -0
  162. package/dist/server/security.js +36 -19
  163. package/dist/server/server.d.ts +2 -2
  164. package/dist/server/server.js +224 -238
  165. package/dist/server/types.d.ts +68 -21
  166. package/dist/service/factory.d.ts +12 -0
  167. package/dist/service/factory.js +85 -0
  168. package/dist/{target → service}/index.d.ts +1 -1
  169. package/dist/{target → service}/index.js +1 -1
  170. package/dist/service/local.d.ts +27 -0
  171. package/dist/service/local.js +138 -0
  172. package/dist/{target → service}/remote-errors.d.ts +3 -6
  173. package/dist/service/remote-errors.js +38 -0
  174. package/dist/{target → service}/remote-polling.d.ts +2 -2
  175. package/dist/{target → service}/remote-polling.js +8 -8
  176. package/dist/service/remote.d.ts +34 -0
  177. package/dist/service/remote.js +634 -0
  178. package/dist/service/sse-stream.d.ts +24 -0
  179. package/dist/service/sse-stream.js +139 -0
  180. package/dist/service/types.d.ts +272 -0
  181. package/dist/service/types.js +32 -0
  182. package/dist/storage/data-dir-lock.js +10 -5
  183. package/dist/storage/driver.d.ts +2 -1
  184. package/dist/storage/driver.js +3 -52
  185. package/dist/storage/index.d.ts +1 -0
  186. package/dist/storage/index.js +1 -0
  187. package/dist/storage/lock-core.d.ts +2 -6
  188. package/dist/storage/lock-core.js +4 -17
  189. package/dist/storage/params.d.ts +2 -8
  190. package/dist/storage/params.js +2 -8
  191. package/dist/storage/sqlite-driver.d.ts +40 -0
  192. package/dist/storage/sqlite-driver.js +116 -0
  193. package/dist/storage/sqlite.js +21 -6
  194. package/dist/storage/types.d.ts +4 -4
  195. package/dist/storage/types.js +2 -2
  196. package/dist/utils/index.d.ts +53 -0
  197. package/dist/utils/index.js +99 -4
  198. package/dist/utils/process.d.ts +10 -0
  199. package/dist/utils/process.js +21 -0
  200. package/dist/version.d.ts +1 -1
  201. package/dist/version.js +1 -1
  202. package/package.json +41 -3
  203. package/dist/app/index.d.ts +0 -2
  204. package/dist/app/index.js +0 -2
  205. package/dist/app/types.js +0 -1
  206. package/dist/catalog/action-index.d.ts +0 -9
  207. package/dist/catalog/action-index.js +0 -95
  208. package/dist/catalog/action-resolver.d.ts +0 -20
  209. package/dist/catalog/action-resolver.js +0 -95
  210. package/dist/catalog/location-registry.d.ts +0 -15
  211. package/dist/catalog/location-registry.js +0 -138
  212. package/dist/catalog/package-catalog.d.ts +0 -7
  213. package/dist/catalog/package-catalog.js +0 -77
  214. package/dist/catalog/types.d.ts +0 -68
  215. package/dist/catalog/types.js +0 -1
  216. package/dist/export/index.d.ts +0 -1
  217. package/dist/export/index.js +0 -1
  218. package/dist/export/templates.d.ts +0 -71
  219. package/dist/export/templates.js +0 -635
  220. package/dist/ipc/target.d.ts +0 -74
  221. package/dist/ipc/target.js +0 -365
  222. package/dist/platform/default.d.ts +0 -38
  223. package/dist/platform/default.js +0 -78
  224. package/dist/project/resolver.d.ts +0 -116
  225. package/dist/project/resolver.js +0 -376
  226. package/dist/registry/resolve.d.ts +0 -62
  227. package/dist/registry/resolve.js +0 -195
  228. package/dist/runtime/execution-manager.d.ts +0 -48
  229. package/dist/runtime/execution-manager.js +0 -66
  230. package/dist/runtime/package-runner-factory.d.ts +0 -82
  231. package/dist/runtime/package-runner-factory.js +0 -186
  232. package/dist/target/local.d.ts +0 -53
  233. package/dist/target/local.js +0 -349
  234. package/dist/target/remote-errors.js +0 -51
  235. package/dist/target/remote.d.ts +0 -86
  236. package/dist/target/remote.js +0 -818
  237. package/dist/target/target.d.ts +0 -6
  238. package/dist/target/target.js +0 -37
  239. package/dist/target/types.d.ts +0 -261
  240. package/dist/target/types.js +0 -35
  241. /package/dist/{app → package}/static-index.d.ts +0 -0
  242. /package/dist/{target → service}/sse-parser.d.ts +0 -0
  243. /package/dist/{target → service}/sse-parser.js +0 -0
@@ -0,0 +1,119 @@
1
+ import { ActionDockError, ACTION_NOT_FOUND, INVALID_ACTION_REF, PACKAGE_NOT_FOUND, } from "../errors.js";
2
+ /**
3
+ * 规范化解析动作引用字符串或对象为 ActionRef。
4
+ * 铁律:ActionRef 解析只有一个事实源。
5
+ */
6
+ export function parseActionRef(ref) {
7
+ if (typeof ref === "object" && ref !== null) {
8
+ if (!ref.actionId) {
9
+ throw new ActionDockError(INVALID_ACTION_REF, "INVALID_ACTION_REF: Invalid action identifier: actionId is required");
10
+ }
11
+ return ref;
12
+ }
13
+ const str = String(ref).trim();
14
+ if (!str) {
15
+ throw new ActionDockError(INVALID_ACTION_REF, "INVALID_ACTION_REF: Invalid action identifier: cannot be empty");
16
+ }
17
+ if (str.includes("/")) {
18
+ const lastSlashIndex = str.lastIndexOf("/");
19
+ const packageId = str.slice(0, lastSlashIndex);
20
+ const actionId = str.slice(lastSlashIndex + 1);
21
+ if (!packageId || !actionId || actionId.includes(":") || actionId.includes("/") || actionId.includes("..")) {
22
+ throw new ActionDockError(INVALID_ACTION_REF, `INVALID_ACTION_REF: Invalid action identifier: '${str}'`);
23
+ }
24
+ return { packageId, actionId };
25
+ }
26
+ if (str.includes(":")) {
27
+ throw new ActionDockError(INVALID_ACTION_REF, `INVALID_ACTION_REF: Invalid action identifier: '${str}'`);
28
+ }
29
+ return { actionId: str };
30
+ }
31
+ /**
32
+ * 纯领域动作解析函数 resolveAction。
33
+ * 铁律:ActionRef 解析只有一个事实源,禁止各模块各自编写短名匹配或启发式搜索。
34
+ *
35
+ * 解析次序:
36
+ * 1. 显式包限定标识符精确查找目标包与动作
37
+ * 2. 裸标识符优先查找 caller 调用者所在包
38
+ * 3. 裸标识符全局搜索:单命中返回、多命中抛出歧义异常、零命中抛出未找到异常
39
+ */
40
+ export function resolveAction(ref, context) {
41
+ const parsed = parseActionRef(ref);
42
+ // 1. 显式指定 packageId
43
+ if (parsed.packageId) {
44
+ const node = context.graph.packages.get(parsed.packageId);
45
+ if (!node) {
46
+ throw new ActionDockError(PACKAGE_NOT_FOUND, `PACKAGE_NOT_FOUND: Package '${parsed.packageId}' not found`);
47
+ }
48
+ const matches = context.catalog.find({
49
+ packageId: parsed.packageId,
50
+ actionId: parsed.actionId,
51
+ });
52
+ if (matches.length === 0) {
53
+ throw new ActionDockError(ACTION_NOT_FOUND, `ACTION_NOT_FOUND: Action '${parsed.actionId}' not found in package '${parsed.packageId}'`);
54
+ }
55
+ const candidate = matches[0];
56
+ return {
57
+ ref: {
58
+ packageId: node.identity.id,
59
+ packageInstanceId: node.identity.instanceId,
60
+ actionId: parsed.actionId,
61
+ generationId: node.identity.generation,
62
+ },
63
+ package: node.identity,
64
+ entry: candidate.entry,
65
+ contract: candidate.contract,
66
+ };
67
+ }
68
+ // 2. 裸标识符优先匹配 caller 当前包
69
+ if (context.caller) {
70
+ const callerId = typeof context.caller === "string" ? context.caller : context.caller.id;
71
+ const inCaller = context.catalog.find({
72
+ packageId: callerId,
73
+ actionId: parsed.actionId,
74
+ });
75
+ if (inCaller.length > 0) {
76
+ const candidate = inCaller[0];
77
+ const node = context.graph.packages.get(callerId);
78
+ return {
79
+ ref: {
80
+ packageId: node.identity.id,
81
+ packageInstanceId: node.identity.instanceId,
82
+ actionId: parsed.actionId,
83
+ generationId: node.identity.generation,
84
+ },
85
+ package: node.identity,
86
+ entry: candidate.entry,
87
+ contract: candidate.contract,
88
+ };
89
+ }
90
+ }
91
+ // 3. 全局唯一匹配检查
92
+ const allMatches = context.catalog.find(parsed.actionId);
93
+ if (allMatches.length === 0) {
94
+ const message = context.caller
95
+ ? `ACTION_NOT_FOUND: Action '${parsed.actionId}' not found in current project or any registered package`
96
+ : `ACTION_NOT_FOUND: Action '${parsed.actionId}' not found in any registered package`;
97
+ throw new ActionDockError(ACTION_NOT_FOUND, message);
98
+ }
99
+ if (allMatches.length > 1) {
100
+ const candidates = allMatches.map((m) => `${m.packageId}/${m.actionId}`).join(", ");
101
+ throw new ActionDockError(INVALID_ACTION_REF, `INVALID_ACTION_REF: Action '${parsed.actionId}' is ambiguous and provided by multiple packages: ${candidates}. Please specify '<package-id>/${parsed.actionId}'. (AMBIGUOUS_ACTION_REF)`, {
102
+ alias: "AMBIGUOUS_ACTION_REF",
103
+ candidates: allMatches.map((m) => m.packageId),
104
+ });
105
+ }
106
+ const candidate = allMatches[0];
107
+ const node = context.graph.packages.get(candidate.packageId);
108
+ return {
109
+ ref: {
110
+ packageId: node.identity.id,
111
+ packageInstanceId: node.identity.instanceId,
112
+ actionId: parsed.actionId,
113
+ generationId: node.identity.generation,
114
+ },
115
+ package: node.identity,
116
+ entry: candidate.entry,
117
+ contract: candidate.contract,
118
+ };
119
+ }
@@ -0,0 +1,26 @@
1
+ import type { PlaybookDefinition } from "../project/types.js";
2
+ import type { PackageGraph } from "./graph.js";
3
+ /**
4
+ * Playbook 解析结果。
5
+ */
6
+ export interface ResolvedPlaybook {
7
+ /** 所属包标识 */
8
+ readonly packageId: string;
9
+ /** 项目物理根目录绝对路径 */
10
+ readonly projectRoot: string;
11
+ /** 规程标识 */
12
+ readonly playbookId: string;
13
+ /** 规程定义实体 */
14
+ readonly playbook: PlaybookDefinition;
15
+ }
16
+ export interface ResolvePlaybookContext {
17
+ /** 包拓扑图单一事实源 */
18
+ readonly graph: PackageGraph;
19
+ /** 调用方所在包标识(可选) */
20
+ readonly caller?: string;
21
+ }
22
+ /**
23
+ * 纯领域规程解析函数 resolvePlaybook。
24
+ * 基于 PackageGraph 替代原 registry 内部的 resolvePlaybookProject 启发式搜索。
25
+ */
26
+ export declare function resolvePlaybook(identifier: string, context: ResolvePlaybookContext): ResolvedPlaybook;
@@ -0,0 +1,114 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { resolve } from "node:path";
3
+ import { loadPlaybooks } from "../project/loader.js";
4
+ import { getPackageSlug } from "../utils/index.js";
5
+ import { ActionDockError, INVALID_ACTION_REF, NOT_FOUND, PACKAGE_NOT_FOUND } from "../errors.js";
6
+ function getNodePlaybooks(node) {
7
+ const map = new Map();
8
+ if (node.root && existsSync(node.root)) {
9
+ try {
10
+ const diskPlaybooks = loadPlaybooks(node.root, node.manifest?.playbooksDir);
11
+ for (const [k, v] of diskPlaybooks) {
12
+ map.set(k, v);
13
+ }
14
+ }
15
+ catch {
16
+ // 忽略磁盘规程目录扫描异常
17
+ }
18
+ }
19
+ if (node.manifest?.playbooks && typeof node.manifest.playbooks === "object") {
20
+ for (const [id, item] of Object.entries(node.manifest.playbooks)) {
21
+ const existing = map.get(id);
22
+ let content = item.content ?? existing?.content ?? "";
23
+ let filePath = item.entry && node.root
24
+ ? resolve(node.root, item.entry)
25
+ : existing?.filePath;
26
+ if (!content && filePath && existsSync(filePath)) {
27
+ try {
28
+ content = readFileSync(filePath, "utf-8");
29
+ }
30
+ catch { }
31
+ }
32
+ map.set(id, {
33
+ id,
34
+ description: item.description ?? existing?.description,
35
+ actions: item.actions ?? existing?.actions ?? [],
36
+ content,
37
+ filePath: filePath || "",
38
+ });
39
+ }
40
+ }
41
+ return map;
42
+ }
43
+ /**
44
+ * 纯领域规程解析函数 resolvePlaybook。
45
+ * 基于 PackageGraph 替代原 registry 内部的 resolvePlaybookProject 启发式搜索。
46
+ */
47
+ export function resolvePlaybook(identifier, context) {
48
+ const str = identifier.trim();
49
+ // 1. scoped 形式解析:<package-id>/<playbook-id>
50
+ if (str.includes("/")) {
51
+ const lastSlashIndex = str.lastIndexOf("/");
52
+ const targetPackage = str.slice(0, lastSlashIndex);
53
+ const playbookId = str.slice(lastSlashIndex + 1);
54
+ const node = context.graph.packages.get(targetPackage) ||
55
+ Array.from(context.graph.packages.values()).find((n) => getPackageSlug(n.identity.id) === targetPackage);
56
+ if (!node) {
57
+ throw new ActionDockError(PACKAGE_NOT_FOUND, `Package '${targetPackage}' not found`);
58
+ }
59
+ const playbooks = getNodePlaybooks(node);
60
+ const playbook = playbooks.get(playbookId);
61
+ if (!playbook) {
62
+ throw new ActionDockError(NOT_FOUND, `Playbook '${playbookId}' not found in package '${node.identity.id}' (${node.root})`);
63
+ }
64
+ return {
65
+ packageId: node.identity.id,
66
+ projectRoot: node.root,
67
+ playbookId,
68
+ playbook,
69
+ };
70
+ }
71
+ // 2. 优先在 caller 调用方包中匹配
72
+ if (context.caller) {
73
+ const callerNode = context.graph.packages.get(context.caller);
74
+ if (callerNode) {
75
+ const playbooks = getNodePlaybooks(callerNode);
76
+ const pb = playbooks.get(str);
77
+ if (pb) {
78
+ return {
79
+ packageId: callerNode.identity.id,
80
+ projectRoot: callerNode.root,
81
+ playbookId: str,
82
+ playbook: pb,
83
+ };
84
+ }
85
+ }
86
+ }
87
+ // 3. 全局搜索
88
+ const matches = [];
89
+ for (const node of context.graph.packages.values()) {
90
+ try {
91
+ const playbooks = getNodePlaybooks(node);
92
+ const pb = playbooks.get(str);
93
+ if (pb) {
94
+ matches.push({
95
+ packageId: node.identity.id,
96
+ projectRoot: node.root,
97
+ playbookId: str,
98
+ playbook: pb,
99
+ });
100
+ }
101
+ }
102
+ catch {
103
+ // 忽略单个包加载异常
104
+ }
105
+ }
106
+ if (matches.length === 1) {
107
+ return matches[0];
108
+ }
109
+ if (matches.length > 1) {
110
+ const pkgList = matches.map((m) => `'${m.packageId}'`).join(", ");
111
+ throw new ActionDockError(INVALID_ACTION_REF, `Playbook '${str}' is provided by multiple linked packages: ${pkgList}. Please specify using '<package-id>/${str}'.`);
112
+ }
113
+ throw new ActionDockError(NOT_FOUND, `Playbook '${str}' not found in any registered package`);
114
+ }
@@ -1,4 +1,4 @@
1
- import { existsSync, readFileSync, statSync } from "node:fs";
1
+ import { existsSync, readFileSync, rmSync, statSync } from "node:fs";
2
2
  import { dirname, join, relative } from "node:path";
3
3
  import { discoverActionFiles, loadActions, loadPlaybooks, loadProjectConfig } from "../../project/loader.js";
4
4
  import { loadManifest, MANIFEST_FILE_NAME } from "../../project/manifest.js";
@@ -46,33 +46,52 @@ function checkProjectSdk(scope) {
46
46
  }
47
47
  /**
48
48
  * 检查工程运行时数据库可写性。
49
+ *
50
+ * 探测写入独立临时数据库文件,避免对生产运行库产生写副作用:
51
+ * 体检是诊断行为,不得在真实库上执行写加删事务引入额外写竞争。
49
52
  */
50
53
  async function checkProjectStorage(scope) {
51
54
  const { ctx, config } = scope;
52
55
  const dbPath = resolveDatabasePath(config.id, { customHome: ctx.customHome });
56
+ const probeDir = dirname(dbPath);
57
+ // 探测库:与生产库同目录但独立命名,结束后整体删除,不留探测残留
58
+ const probeId = `doctor.probe.${Date.now()}`;
59
+ const probePkgDir = dirname(resolveDatabasePath(probeId, { customHome: ctx.customHome }));
60
+ const probeStorage = createStorage(probeId, { customHome: ctx.customHome });
53
61
  try {
54
- const projectStorage = createStorage(config.id, { customHome: ctx.customHome });
55
- await projectStorage.setConfig("_doctor_probe_", "ok");
56
- await projectStorage.deleteConfig("_doctor_probe_");
57
- projectStorage.close();
62
+ await probeStorage.setConfig("probe", "ok");
63
+ probeStorage.close();
58
64
  ctx.checks.push({
59
65
  id: "project.storage",
60
66
  category: "project",
61
67
  name: "Project Database",
62
68
  status: "ok",
63
- message: `Database writable at ${dbPath}`,
69
+ message: `Database directory writable at ${probeDir}`,
64
70
  });
65
71
  }
66
72
  catch (err) {
73
+ try {
74
+ probeStorage.close();
75
+ }
76
+ catch { }
67
77
  ctx.checks.push({
68
78
  id: "project.storage",
69
79
  category: "project",
70
80
  name: "Project Database",
71
81
  status: "error",
72
- message: `Failed to write project runtime database: ${err.message}`,
73
- fix: `Check write permissions for '${dirname(dbPath)}'`,
82
+ message: `Failed to write project runtime database directory: ${err.message}`,
83
+ fix: `Check write permissions for '${probeDir}'`,
74
84
  });
75
85
  }
86
+ finally {
87
+ // 清理探测库目录(含 WAL/SHM 侧车文件)
88
+ try {
89
+ if (existsSync(probePkgDir)) {
90
+ rmSync(probePkgDir, { recursive: true, force: true });
91
+ }
92
+ }
93
+ catch { }
94
+ }
76
95
  }
77
96
  /**
78
97
  * 检查工程 Actions 可加载性与数量。
@@ -1,6 +1,6 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
- import { ActionResolver } from "../../catalog/action-resolver.js";
3
+ import { parseActionRef } from "../../catalog/resolve-action.js";
4
4
  import { findProjectRoot, loadProjectConfig } from "../../project/loader.js";
5
5
  import { loadManifest } from "../../project/manifest.js";
6
6
  import { getRegistryStatus, listLinkedPackages, resolvePackageRoot } from "../../registry/registry.js";
@@ -158,7 +158,7 @@ export const checkUsesClosure = {
158
158
  continue;
159
159
  let parsed;
160
160
  try {
161
- parsed = ActionResolver.parseRef(rawRef);
161
+ parsed = parseActionRef(rawRef);
162
162
  }
163
163
  catch {
164
164
  unresolvableUses.push(`${pkg.id}/${actionId} -> '${rawRef}'`);
@@ -1,5 +1,38 @@
1
- import { findExecutable } from "../../utils/index.js";
1
+ import { findExecutable, parseSemVer } from "../../utils/index.js";
2
+ /**
3
+ * 比较两个版本字符串(基于 utils.parseSemVer 单一事实源)。
4
+ *
5
+ * 行为契约(与历史手写实现逐字节对齐):
6
+ * - 双方均为严格三段式语义化版本且无预发布后缀时,按 major/minor/patch 逐段数值比较;
7
+ * - 其余形态(两段式、带 v 前缀的四段式、携带预发布后缀等)回退到历史宽松语义:
8
+ * 去 v 前缀后按点分段数值比较,缺段补零、非数值段作零。
9
+ * 宽松回退保留历史行为的尾段数值比较(预发布后缀的数字段参与比较),
10
+ * 与 parseSemVer 的严格语义存在刻意差异,不得合并。
11
+ */
2
12
  function compareSemver(v1, v2) {
13
+ // 预检:parseSemVer 会剥离 = 前缀而历史宽松语义不会(NaN 段作零),
14
+ // 携带 = 前缀的输入必须回退宽松分支以保持历史行为完全一致。
15
+ if (v1[0] === "=" || v2[0] === "=") {
16
+ return compareLooseVersion(v1, v2);
17
+ }
18
+ const s1 = parseSemVer(v1);
19
+ const s2 = parseSemVer(v2);
20
+ if (s1 && s2 && !s1.prerelease && !s2.prerelease) {
21
+ if (s1.major !== s2.major)
22
+ return s1.major > s2.major ? 1 : -1;
23
+ if (s1.minor !== s2.minor)
24
+ return s1.minor > s2.minor ? 1 : -1;
25
+ if (s1.patch !== s2.patch)
26
+ return s1.patch > s2.patch ? 1 : -1;
27
+ return 0;
28
+ }
29
+ return compareLooseVersion(v1, v2);
30
+ }
31
+ /**
32
+ * 历史宽松版本比较(去 v 前缀后按点分段数值比较,缺段补零、非数值段作零)。
33
+ * 仅供 compareSemver 的非严格形态回退分支使用,禁止断开对外直接引用。
34
+ */
35
+ function compareLooseVersion(v1, v2) {
3
36
  const p1 = v1.replace(/^v/, "").split(".").map(Number);
4
37
  const p2 = v2.replace(/^v/, "").split(".").map(Number);
5
38
  for (let i = 0; i < Math.max(p1.length, p2.length); i++) {
package/dist/errors.d.ts CHANGED
@@ -29,14 +29,8 @@ export declare const INPUT_NOT_JSON = "INPUT_NOT_JSON";
29
29
  export declare const OUTPUT_NOT_JSON = "OUTPUT_NOT_JSON";
30
30
  /** 根运行并发子任务数达到上限 */
31
31
  export declare const ACTION_SUBRUN_LIMIT = "ACTION_SUBRUN_LIMIT";
32
- /** 子任务数达限错误的别名标记(details.alias 专用,非独立错误码) */
33
- export declare const MAX_SUBRUNS_REACHED = "MAX_SUBRUNS_REACHED";
34
32
  /** Action 调用链出现环路 */
35
33
  export declare const ACTION_CALL_CYCLE = "ACTION_CALL_CYCLE";
36
- /** 调用链环路检测的别名标记(details.alias 专用,非独立错误码) */
37
- export declare const ACTION_CYCLE_DETECTED = "ACTION_CYCLE_DETECTED";
38
- /** 调用链深度超限的别名标记(details.alias 专用,非独立错误码) */
39
- export declare const ACTION_MAX_DEPTH_EXCEEDED = "ACTION_MAX_DEPTH_EXCEEDED";
40
34
  /** 跨包调用未在 uses 中声明依赖 */
41
35
  export declare const UNDECLARED_ACTION_DEPENDENCY = "UNDECLARED_ACTION_DEPENDENCY";
42
36
  /** Action 引用存在多包歧义 */
@@ -53,14 +47,22 @@ export declare const RUN_REPOSITORY_UNAVAILABLE = "RUN_REPOSITORY_UNAVAILABLE";
53
47
  export declare const RUN_PERSISTENCE_FAILED = "RUN_PERSISTENCE_FAILED";
54
48
  /** 独立单执行二进制拒绝异步启动语义 */
55
49
  export declare const STANDALONE_ASYNC_UNSUPPORTED = "STANDALONE_ASYNC_UNSUPPORTED";
50
+ /** 独立运行模式不支持级联调用 */
51
+ export declare const INVOCATION_UNSUPPORTED = "INVOCATION_UNSUPPORTED";
56
52
  /** 宿主子进程已退出,调用无法送达 */
57
53
  export declare const HOST_PROCESS_EXITED = "HOST_PROCESS_EXITED";
58
54
  /** 调用在启动前已被取消 */
59
55
  export declare const EXECUTION_ABORTED = "EXECUTION_ABORTED";
60
56
  /** 远程运行等待超时 */
61
57
  export declare const TIMEOUT = "TIMEOUT";
58
+ /** 服务已关闭拒绝继续调用 */
59
+ export declare const SERVICE_CLOSED = "SERVICE_CLOSED";
62
60
  /** 远程服务器网络连接失败 */
63
61
  export declare const NETWORK_ERROR = "NETWORK_ERROR";
62
+ /** 非本地明文 HTTP 传输违规 */
63
+ export declare const INSECURE_TRANSPORT = "INSECURE_TRANSPORT";
64
+ /** 远程 HTTP 请求失败 */
65
+ export declare const REMOTE_REQUEST_FAILED = "REMOTE_REQUEST_FAILED";
64
66
  /** 远程事件流全部候选路由均不可用 */
65
67
  export declare const REMOTE_STREAM_UNAVAILABLE = "REMOTE_STREAM_UNAVAILABLE";
66
68
  /** 远程目标未启用管理接口能力 */
@@ -92,6 +94,72 @@ export declare const UNAUTHORIZED = "UNAUTHORIZED";
92
94
  export declare const NOT_FOUND = "NOT_FOUND";
93
95
  /** HTTP 服务内部错误 */
94
96
  export declare const SERVER_ERROR = "SERVER_ERROR";
97
+ /** HTTP 服务请求非法 */
98
+ export declare const BAD_REQUEST = "BAD_REQUEST";
99
+ /** 目标包未列入允许白名单(403 禁止访问) */
100
+ export declare const PACKAGE_FORBIDDEN = "PACKAGE_FORBIDDEN";
101
+ /** 目标动作未列入允许白名单(403 禁止访问) */
102
+ export declare const ACTION_FORBIDDEN = "ACTION_FORBIDDEN";
103
+ /** 目标规程未找到 */
104
+ export declare const PLAYBOOK_NOT_FOUND = "PLAYBOOK_NOT_FOUND";
105
+ /** 请求体体积超出安全限制 */
106
+ export declare const REQUEST_TOO_LARGE = "REQUEST_TOO_LARGE";
107
+ /** 动作异步启动失败 */
108
+ export declare const ACTION_START_FAILED = "ACTION_START_FAILED";
109
+ /** 动作执行发生内部错误 */
110
+ export declare const ACTION_EXECUTION_ERROR = "ACTION_EXECUTION_ERROR";
111
+ /** 动作列表检索失败 */
112
+ export declare const ACTIONS_LIST_ERROR = "ACTIONS_LIST_ERROR";
113
+ /** 规程列表检索失败 */
114
+ export declare const PLAYBOOKS_LIST_ERROR = "PLAYBOOKS_LIST_ERROR";
115
+ /** 运行记录列表检索失败 */
116
+ export declare const RUNS_LIST_ERROR = "RUNS_LIST_ERROR";
117
+ /** 运行记录清空操作失败 */
118
+ export declare const RUNS_CLEAR_ERROR = "RUNS_CLEAR_ERROR";
119
+ /** 服务大纲信息自省失败 */
120
+ export declare const INFO_ERROR = "INFO_ERROR";
121
+ /** 包信息检索失败 */
122
+ export declare const PACKAGES_INFO_ERROR = "PACKAGES_INFO_ERROR";
123
+ /** 环境诊断体检执行失败 */
124
+ export declare const DOCTOR_ERROR = "DOCTOR_ERROR";
125
+ /** 运行由于服务中断或异常退出被置为中断态 */
126
+ export declare const RUN_INTERRUPTED = "RUN_INTERRUPTED";
127
+ /** 配置项环境变量生成失败 */
128
+ export declare const CONFIG_ENV_ERROR = "CONFIG_ENV_ERROR";
129
+ /** 配置项列表检索失败 */
130
+ export declare const CONFIG_LIST_ERROR = "CONFIG_LIST_ERROR";
131
+ /** 配置项写入失败 */
132
+ export declare const CONFIG_SET_ERROR = "CONFIG_SET_ERROR";
133
+ /** 配置项删除失败 */
134
+ export declare const CONFIG_DELETE_ERROR = "CONFIG_DELETE_ERROR";
135
+ /** 状态条目列表检索失败 */
136
+ export declare const STATE_LIST_ERROR = "STATE_LIST_ERROR";
137
+ /** 状态清空操作失败 */
138
+ export declare const STATE_CLEAR_ERROR = "STATE_CLEAR_ERROR";
139
+ /** 状态键操作异常 */
140
+ export declare const STATE_KEY_ERROR = "STATE_KEY_ERROR";
141
+ /** 数据目录已被其他活跃会话持有 */
142
+ export declare const DATA_DIR_IN_USE = "DATA_DIR_IN_USE";
143
+ /** 数据目录存在未完成的事务,需执行恢复 */
144
+ export declare const DATA_DIR_RECOVERY_REQUIRED = "DATA_DIR_RECOVERY_REQUIRED";
145
+ /** 存储底层 Schema 版本不受支持 */
146
+ export declare const UNSUPPORTED_STORAGE_SCHEMA = "UNSUPPORTED_STORAGE_SCHEMA";
147
+ /** 持久化运行错误对象反序列化解码失败 */
148
+ export declare const STORED_ERROR_DECODE_FAILED = "STORED_ERROR_DECODE_FAILED";
149
+ /** 子进程执行失败终结 */
150
+ export declare const PROCESS_FAILED = "PROCESS_FAILED";
151
+ /** 生成的类型定义已过期 */
152
+ export declare const GENERATED_TYPES_OUTDATED = "GENERATED_TYPES_OUTDATED";
153
+ /** 通信协议版本或格式不受支持 */
154
+ export declare const PROTOCOL_UNSUPPORTED = "PROTOCOL_UNSUPPORTED";
155
+ /** 服务调用结果未知 */
156
+ export declare const SERVICE_RESULT_UNKNOWN = "SERVICE_RESULT_UNKNOWN";
157
+ /** MCP 工具命名发生冲突 */
158
+ export declare const MCP_TOOL_NAME_COLLISION = "MCP_TOOL_NAME_COLLISION";
159
+ /** 跨进程 IPC 通信或调用异常 */
160
+ export declare const IPC_ERROR = "IPC_ERROR";
161
+ /** 服务调用层内部异常回退错误码 */
162
+ export declare const SERVICE_ERROR = "SERVICE_ERROR";
95
163
  /**
96
164
  * 判定错误消息根因是否为依赖模块缺失。
97
165
  * 兼容 Node.js 与打包器(Bun 等)两类加载器的报错文案。
@@ -172,11 +240,39 @@ export declare const INPUT_CONFLICT = "INPUT_CONFLICT";
172
240
  export declare const INPUT_FILE_NOT_FOUND = "INPUT_FILE_NOT_FOUND";
173
241
  /** 输入文件或流读取失败 */
174
242
  export declare const INPUT_FILE_READ_FAILED = "INPUT_FILE_READ_FAILED";
243
+ /** 命令参数或选项非法 */
244
+ export declare const INVALID_ARGUMENT = "INVALID_ARGUMENT";
245
+ /** 目标包未列入白名单 */
246
+ export declare const PACKAGE_NOT_ALLOWED = "PACKAGE_NOT_ALLOWED";
247
+ /** 包标识符格式非法或包含越界字符 */
248
+ export declare const INVALID_PACKAGE_ID = "INVALID_PACKAGE_ID";
249
+ /** 路径越界违规访问 */
250
+ export declare const PATH_TRAVERSAL = "PATH_TRAVERSAL";
251
+ /** 状态键存在多命名空间歧义 */
252
+ export declare const AMBIGUOUS_STATE_KEY = "AMBIGUOUS_STATE_KEY";
253
+ /** 目标运行记录未找到 */
254
+ export declare const RUN_NOT_FOUND = "RUN_NOT_FOUND";
255
+ /** 目标运行已进入终态不可操作 */
256
+ export declare const RUN_ALREADY_FINISHED = "RUN_ALREADY_FINISHED";
257
+ /**
258
+ * ActionDock 统一基础结构化异常类。
259
+ * 全仓各领域异常与跨层透传异常的统一事实源基类。
260
+ */
261
+ export declare class ActionDockError<T = any> extends Error {
262
+ readonly code: ErrorCode;
263
+ readonly details?: T;
264
+ readonly status?: number;
265
+ constructor(code: ErrorCode, message: string, details?: T, status?: number);
266
+ }
267
+ /**
268
+ * 集中定义的标准结构化错误码联合类型。
269
+ */
270
+ export type ErrorCode = typeof PACKAGE_NOT_FOUND | typeof ACTION_PACKAGE_VERSION_CONFLICT | typeof ACTION_NOT_FOUND | typeof ACTION_LOAD_FAILED | typeof ACTION_FAILED | typeof ACTION_TIMEOUT | typeof ACTION_CANCELLED | typeof INPUT_VALIDATION_FAILED | typeof OUTPUT_VALIDATION_FAILED | typeof INPUT_NOT_JSON | typeof OUTPUT_NOT_JSON | typeof ACTION_SUBRUN_LIMIT | typeof ACTION_CALL_CYCLE | typeof UNDECLARED_ACTION_DEPENDENCY | typeof INVALID_ACTION_REF | typeof IDEMPOTENCY_CONFLICT | typeof EXECUTION_FAILED | typeof UNHANDLED_EXECUTION_ERROR | typeof RUN_REPOSITORY_UNAVAILABLE | typeof RUN_PERSISTENCE_FAILED | typeof STANDALONE_ASYNC_UNSUPPORTED | typeof INVOCATION_UNSUPPORTED | typeof HOST_PROCESS_EXITED | typeof EXECUTION_ABORTED | typeof TIMEOUT | typeof SERVICE_CLOSED | typeof NETWORK_ERROR | typeof INSECURE_TRANSPORT | typeof REMOTE_REQUEST_FAILED | typeof REMOTE_STREAM_UNAVAILABLE | typeof CAPABILITY_UNAVAILABLE | typeof STATE_KEY_NOT_FOUND | typeof STORAGE_BUSY | typeof PROJECT_BUSY | typeof PROJECT_RECOVERY_REQUIRED | typeof STORAGE_WORKER_EXITED | typeof EVENT_BACKPRESSURE_LIMIT | typeof EVENT_CURSOR_EXPIRED | typeof PROCESS_OUTPUT_LIMIT | typeof PROCESS_SPAWN_ERROR | typeof PROCESS_CANCELLED | typeof PROCESS_TIMEOUT | typeof UNAUTHORIZED | typeof NOT_FOUND | typeof SERVER_ERROR | typeof BAD_REQUEST | typeof PACKAGE_FORBIDDEN | typeof ACTION_FORBIDDEN | typeof PLAYBOOK_NOT_FOUND | typeof REQUEST_TOO_LARGE | typeof ACTION_START_FAILED | typeof ACTION_EXECUTION_ERROR | typeof ACTIONS_LIST_ERROR | typeof PLAYBOOKS_LIST_ERROR | typeof RUNS_LIST_ERROR | typeof RUNS_CLEAR_ERROR | typeof INFO_ERROR | typeof PACKAGES_INFO_ERROR | typeof DOCTOR_ERROR | typeof RUN_INTERRUPTED | typeof CONFIG_ENV_ERROR | typeof CONFIG_LIST_ERROR | typeof CONFIG_SET_ERROR | typeof CONFIG_DELETE_ERROR | typeof STATE_LIST_ERROR | typeof STATE_CLEAR_ERROR | typeof STATE_KEY_ERROR | typeof DATA_DIR_IN_USE | typeof DATA_DIR_RECOVERY_REQUIRED | typeof UNSUPPORTED_STORAGE_SCHEMA | typeof STORED_ERROR_DECODE_FAILED | typeof PROCESS_FAILED | typeof GENERATED_TYPES_OUTDATED | typeof PROTOCOL_UNSUPPORTED | typeof SERVICE_RESULT_UNKNOWN | typeof MCP_TOOL_NAME_COLLISION | typeof ACCESS_DENIED | typeof UNSUPPORTED_CAPABILITY | typeof CONTROL_BUSY | typeof CONTROL_EXPIRED | typeof CONTROL_REVOKED | typeof PROCESS_QUARANTINED | typeof PROCESS_LOST | typeof REQUEST_CONFLICT | typeof INPUT_OUTCOME_UNKNOWN | typeof OUTPUT_GAP | typeof OUTPUT_UNAVAILABLE | typeof INVALID_CURSOR | typeof QUEUE_FULL | typeof QUOTA_EXCEEDED | typeof INPUT_CLOSED | typeof INVALID_FLAT_ARGUMENT | typeof INVALID_JSON | typeof INVALID_JSON_LITERAL | typeof INPUT_PATH_CONFLICT | typeof FLAT_INPUT_LIMIT_EXCEEDED | typeof INPUT_LIMIT_EXCEEDED | typeof INPUT_POLICY_VIOLATION | typeof INPUT_CONFLICT | typeof INPUT_FILE_NOT_FOUND | typeof INPUT_FILE_READ_FAILED | typeof INVALID_ARGUMENT | typeof PACKAGE_NOT_ALLOWED | typeof INVALID_PACKAGE_ID | typeof PATH_TRAVERSAL | typeof AMBIGUOUS_STATE_KEY | typeof RUN_NOT_FOUND | typeof RUN_ALREADY_FINISHED | typeof IPC_ERROR | typeof SERVICE_ERROR;
271
+ /** 全仓统一错误码类型别名 */
272
+ export type ActionDockErrorCode = ErrorCode;
175
273
  /**
176
274
  * 进程领域结构化异常类。
177
275
  */
178
- export declare class ProcessError extends Error {
179
- readonly code: string;
180
- readonly details?: Record<string, unknown>;
181
- constructor(code: string, message: string, details?: Record<string, unknown>);
276
+ export declare class ProcessError extends ActionDockError {
277
+ constructor(code: ErrorCode, message: string, details?: Record<string, unknown>);
182
278
  }