@actiondock/core 2.7.0 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -68
- package/dist/catalog/action-catalog.d.ts +56 -0
- package/dist/catalog/action-catalog.js +202 -0
- package/dist/catalog/discovery.d.ts +60 -0
- package/dist/catalog/discovery.js +119 -0
- package/dist/catalog/graph.d.ts +190 -0
- package/dist/catalog/graph.js +589 -0
- package/dist/catalog/index.d.ts +5 -5
- package/dist/catalog/index.js +5 -5
- package/dist/catalog/resolve-action.d.ts +43 -0
- package/dist/catalog/resolve-action.js +119 -0
- package/dist/catalog/resolve-playbook.d.ts +26 -0
- package/dist/catalog/resolve-playbook.js +114 -0
- package/dist/doctor/checks/project.js +27 -8
- package/dist/doctor/checks/registry.js +2 -2
- package/dist/doctor/checks/runtime.js +34 -1
- package/dist/errors.d.ts +102 -10
- package/dist/errors.js +103 -10
- package/dist/execution/service.d.ts +18 -16
- package/dist/execution/service.js +183 -252
- package/dist/execution/types.d.ts +25 -69
- package/dist/execution/types.js +2 -1
- package/dist/filter/intent.d.ts +8 -9
- package/dist/filter/intent.js +49 -10
- package/dist/graph/index.d.ts +4 -0
- package/dist/graph/index.js +4 -0
- package/dist/host/host.d.ts +74 -32
- package/dist/host/host.js +585 -336
- package/dist/host/routing.d.ts +15 -48
- package/dist/host/routing.js +90 -153
- package/dist/host/types.d.ts +50 -17
- package/dist/index.d.ts +21 -24
- package/dist/index.js +19 -23
- package/dist/input/advice.d.ts +5 -1
- package/dist/input/advice.js +163 -214
- package/dist/input/describe.d.ts +1 -1
- package/dist/input/flat-errors.d.ts +5 -6
- package/dist/input/flat-errors.js +6 -6
- package/dist/input/flat-materializer.js +42 -44
- package/dist/invocation/index.d.ts +2 -0
- package/dist/invocation/index.js +2 -0
- package/dist/invocation/policy.d.ts +157 -0
- package/dist/invocation/policy.js +231 -0
- package/dist/invocation/types.d.ts +172 -0
- package/dist/invocation/types.js +97 -0
- package/dist/ipc/diagnostic.d.ts +0 -12
- package/dist/ipc/diagnostic.js +0 -21
- package/dist/ipc/host.d.ts +4 -4
- package/dist/ipc/host.js +44 -47
- package/dist/ipc/index.d.ts +1 -1
- package/dist/ipc/index.js +1 -1
- package/dist/ipc/service.d.ts +40 -0
- package/dist/ipc/service.js +349 -0
- package/dist/ipc/types.d.ts +21 -15
- package/dist/node/index.d.ts +1 -0
- package/dist/node/index.js +1 -0
- package/dist/node/module-loader.d.ts +63 -0
- package/dist/node/module-loader.js +112 -0
- package/dist/package/index.d.ts +23 -0
- package/dist/package/index.js +18 -0
- package/dist/{app/app.d.ts → package/runtime.d.ts} +41 -20
- package/dist/{app/app.js → package/runtime.js} +140 -95
- package/dist/{app → package}/static-index.js +58 -41
- package/dist/package/storage-view.d.ts +13 -0
- package/dist/package/storage-view.js +22 -0
- package/dist/{app → package}/types.d.ts +76 -57
- package/dist/package/types.js +22 -0
- package/dist/platform/index.d.ts +1 -1
- package/dist/platform/index.js +1 -1
- package/dist/platform/node.d.ts +48 -0
- package/dist/platform/node.js +96 -0
- package/dist/platform/types.d.ts +0 -9
- package/dist/process/control-arbiter.d.ts +2 -1
- package/dist/process/control-arbiter.js +1 -2
- package/dist/process/driver.d.ts +9 -8
- package/dist/process/driver.js +11 -22
- package/dist/process/index.d.ts +2 -0
- package/dist/process/index.js +2 -0
- package/dist/process/managed-record.d.ts +2 -2
- package/dist/process/process-driver.d.ts +109 -0
- package/dist/process/process-driver.js +650 -0
- package/dist/process/process-executor.d.ts +47 -0
- package/dist/process/process-executor.js +296 -0
- package/dist/process/process-manager.js +48 -26
- package/dist/process/run-executor.js +12 -12
- package/dist/profile/client-actions.js +2 -2
- package/dist/profile/client-health.js +2 -2
- package/dist/profile/client-query.js +5 -6
- package/dist/profile/client-transport.d.ts +19 -17
- package/dist/profile/client-transport.js +47 -80
- package/dist/profile/client.d.ts +2 -2
- package/dist/profile/client.js +1 -1
- package/dist/profile/index.d.ts +1 -0
- package/dist/profile/index.js +1 -0
- package/dist/profile/manager.d.ts +5 -0
- package/dist/profile/manager.js +41 -6
- package/dist/project/closure.js +2 -2
- package/dist/project/index.d.ts +8 -1
- package/dist/project/index.js +10 -1
- package/dist/project/init.js +2 -2
- package/dist/project/loader.d.ts +1 -1
- package/dist/project/loader.js +26 -29
- package/dist/project/transactions.js +5 -10
- package/dist/registry/index.d.ts +3 -1
- package/dist/registry/index.js +2 -1
- package/dist/registry/lock.d.ts +28 -7
- package/dist/registry/lock.js +136 -16
- package/dist/registry/registry.d.ts +1 -5
- package/dist/registry/registry.js +1 -53
- package/dist/registry/scan.d.ts +0 -15
- package/dist/registry/scan.js +0 -59
- package/dist/registry/store.d.ts +42 -0
- package/dist/registry/store.js +43 -0
- package/dist/registry/types.d.ts +0 -24
- package/dist/runtime/action-collection.d.ts +1 -1
- package/dist/runtime/action-registry.d.ts +0 -4
- package/dist/runtime/action-registry.js +0 -7
- package/dist/runtime/context.js +5 -11
- package/dist/runtime/events.js +3 -6
- package/dist/runtime/identity.d.ts +22 -0
- package/dist/runtime/identity.js +10 -0
- package/dist/runtime/index.d.ts +1 -2
- package/dist/runtime/index.js +1 -2
- package/dist/runtime/module-loader.d.ts +2 -34
- package/dist/runtime/module-loader.js +1 -16
- package/dist/runtime/process.d.ts +6 -24
- package/dist/runtime/process.js +1 -118
- package/dist/runtime/run-persistence.js +2 -5
- package/dist/runtime/runner.d.ts +33 -93
- package/dist/runtime/runner.js +132 -364
- package/dist/runtime/standalone.d.ts +23 -8
- package/dist/runtime/standalone.js +100 -147
- package/dist/server/body.d.ts +16 -8
- package/dist/server/body.js +33 -16
- package/dist/server/dispatcher.d.ts +6 -10
- package/dist/server/dispatcher.js +24 -32
- package/dist/server/http-server.d.ts +87 -0
- package/dist/server/http-server.js +304 -0
- package/dist/server/index.d.ts +11 -0
- package/dist/server/index.js +10 -0
- package/dist/server/mcp-endpoint.d.ts +61 -0
- package/dist/server/mcp-endpoint.js +118 -0
- package/dist/server/routes/actions.js +34 -28
- package/dist/server/routes/common.d.ts +10 -14
- package/dist/server/routes/common.js +32 -56
- package/dist/server/routes/config.js +54 -64
- package/dist/server/routes/doctor.d.ts +1 -1
- package/dist/server/routes/doctor.js +10 -18
- package/dist/server/routes/health.d.ts +1 -1
- package/dist/server/routes/health.js +2 -3
- package/dist/server/routes/info.d.ts +2 -2
- package/dist/server/routes/info.js +12 -13
- package/dist/server/routes/playbooks.js +16 -29
- package/dist/server/routes/runs.js +95 -117
- package/dist/server/routes/state.js +63 -62
- package/dist/server/server.d.ts +2 -2
- package/dist/server/server.js +43 -227
- package/dist/server/types.d.ts +8 -19
- package/dist/service/factory.d.ts +12 -0
- package/dist/service/factory.js +85 -0
- package/dist/{target → service}/index.d.ts +1 -1
- package/dist/{target → service}/index.js +1 -1
- package/dist/service/local.d.ts +27 -0
- package/dist/service/local.js +138 -0
- package/dist/{target → service}/remote-errors.d.ts +3 -6
- package/dist/service/remote-errors.js +38 -0
- package/dist/{target → service}/remote-polling.d.ts +2 -2
- package/dist/{target → service}/remote-polling.js +8 -8
- package/dist/service/remote.d.ts +34 -0
- package/dist/service/remote.js +634 -0
- package/dist/service/sse-stream.d.ts +24 -0
- package/dist/service/sse-stream.js +139 -0
- package/dist/service/types.d.ts +272 -0
- package/dist/service/types.js +32 -0
- package/dist/storage/data-dir-lock.js +10 -5
- package/dist/storage/driver.d.ts +2 -1
- package/dist/storage/driver.js +3 -52
- package/dist/storage/index.d.ts +1 -0
- package/dist/storage/index.js +1 -0
- package/dist/storage/lock-core.d.ts +2 -6
- package/dist/storage/lock-core.js +4 -17
- package/dist/storage/params.d.ts +2 -8
- package/dist/storage/params.js +2 -8
- package/dist/storage/sqlite-driver.d.ts +40 -0
- package/dist/storage/sqlite-driver.js +116 -0
- package/dist/storage/sqlite.js +21 -6
- package/dist/storage/types.d.ts +4 -4
- package/dist/storage/types.js +2 -2
- package/dist/utils/index.d.ts +53 -0
- package/dist/utils/index.js +99 -4
- package/dist/utils/process.d.ts +10 -0
- package/dist/utils/process.js +21 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +41 -3
- package/dist/app/index.d.ts +0 -2
- package/dist/app/index.js +0 -2
- package/dist/app/types.js +0 -1
- package/dist/catalog/action-index.d.ts +0 -9
- package/dist/catalog/action-index.js +0 -95
- package/dist/catalog/action-resolver.d.ts +0 -20
- package/dist/catalog/action-resolver.js +0 -95
- package/dist/catalog/location-registry.d.ts +0 -15
- package/dist/catalog/location-registry.js +0 -138
- package/dist/catalog/package-catalog.d.ts +0 -7
- package/dist/catalog/package-catalog.js +0 -77
- package/dist/catalog/types.d.ts +0 -68
- package/dist/catalog/types.js +0 -1
- package/dist/export/index.d.ts +0 -1
- package/dist/export/index.js +0 -1
- package/dist/export/templates.d.ts +0 -71
- package/dist/export/templates.js +0 -635
- package/dist/ipc/target.d.ts +0 -74
- package/dist/ipc/target.js +0 -365
- package/dist/platform/default.d.ts +0 -38
- package/dist/platform/default.js +0 -78
- package/dist/project/resolver.d.ts +0 -116
- package/dist/project/resolver.js +0 -376
- package/dist/registry/resolve.d.ts +0 -62
- package/dist/registry/resolve.js +0 -195
- package/dist/runtime/execution-manager.d.ts +0 -48
- package/dist/runtime/execution-manager.js +0 -66
- package/dist/runtime/package-runner-factory.d.ts +0 -82
- package/dist/runtime/package-runner-factory.js +0 -186
- package/dist/target/local.d.ts +0 -53
- package/dist/target/local.js +0 -349
- package/dist/target/remote-errors.js +0 -51
- package/dist/target/remote.d.ts +0 -86
- package/dist/target/remote.js +0 -818
- package/dist/target/target.d.ts +0 -6
- package/dist/target/target.js +0 -37
- package/dist/target/types.d.ts +0 -261
- package/dist/target/types.js +0 -35
- /package/dist/{app → package}/static-index.d.ts +0 -0
- /package/dist/{target → service}/sse-parser.d.ts +0 -0
- /package/dist/{target → service}/sse-parser.js +0 -0
|
@@ -0,0 +1,589 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
3
|
+
import { ActionDockError, ACTION_PACKAGE_VERSION_CONFLICT, PACKAGE_NOT_FOUND, UNDECLARED_ACTION_DEPENDENCY, } from "../errors.js";
|
|
4
|
+
import { computeManifestDigest, parseJsonWithoutDuplicates } from "../project/digest.js";
|
|
5
|
+
import { loadLockfile } from "../project/lockfile.js";
|
|
6
|
+
import { loadPlaybooks, loadProjectConfig } from "../project/loader.js";
|
|
7
|
+
import { loadManifest, MANIFEST_FILE_NAME } from "../project/manifest.js";
|
|
8
|
+
import { listLinkedPackages } from "../registry/registry.js";
|
|
9
|
+
import { createPackageIdentity } from "../runtime/identity.js";
|
|
10
|
+
import { parseSemVer } from "../utils/index.js";
|
|
11
|
+
import { PackageDiscovery } from "./discovery.js";
|
|
12
|
+
export { parseSemVer };
|
|
13
|
+
/**
|
|
14
|
+
* 校验两个语义化版本范围是否兼容并能收敛为单一解析版本。
|
|
15
|
+
* 遵循设计规范:直接或传递版本范围无法收敛时拒绝并抛出 ACTION_PACKAGE_VERSION_CONFLICT。
|
|
16
|
+
*/
|
|
17
|
+
export function areVersionsCompatible(v1, v2) {
|
|
18
|
+
if (v1 === v2 || v1 === "*" || v2 === "*" || !v1 || !v2) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
const clean1 = v1.trim().replace(/^[\^~=]/, "");
|
|
22
|
+
const clean2 = v2.trim().replace(/^[\^~=]/, "");
|
|
23
|
+
const sem1 = parseSemVer(clean1);
|
|
24
|
+
const sem2 = parseSemVer(clean2);
|
|
25
|
+
if (!sem1 || !sem2) {
|
|
26
|
+
return v1 === v2;
|
|
27
|
+
}
|
|
28
|
+
if (sem1.major !== sem2.major) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
if (v1.startsWith("~") || v2.startsWith("~")) {
|
|
32
|
+
if (sem1.minor !== sem2.minor) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* 版本冲突错误。
|
|
40
|
+
*/
|
|
41
|
+
export class ActionPackageVersionConflictError extends ActionDockError {
|
|
42
|
+
packageId;
|
|
43
|
+
conflicts;
|
|
44
|
+
constructor(packageId, conflicts) {
|
|
45
|
+
const details = conflicts.map((c) => `'${c.requester}' 要求 '${c.rangeOrVersion}'`).join(", ");
|
|
46
|
+
super(ACTION_PACKAGE_VERSION_CONFLICT, `ACTION_PACKAGE_VERSION_CONFLICT: 逻辑包 '${packageId}' 存在不可收敛的版本冲突: ${details}`);
|
|
47
|
+
this.name = "ActionPackageVersionConflictError";
|
|
48
|
+
this.packageId = packageId;
|
|
49
|
+
this.conflicts = conflicts;
|
|
50
|
+
Object.setPrototypeOf(this, ActionPackageVersionConflictError.prototype);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* 未声明依赖调用拦截错误。
|
|
55
|
+
*/
|
|
56
|
+
export class UndeclaredActionDependencyError extends ActionDockError {
|
|
57
|
+
targetRef;
|
|
58
|
+
caller;
|
|
59
|
+
constructor(targetRef, caller, reason) {
|
|
60
|
+
const msg = caller
|
|
61
|
+
? `UNDECLARED_ACTION_DEPENDENCY: Action '${caller}' 未在 'uses' 中声明对 '${targetRef}' 的跨包依赖`
|
|
62
|
+
: `UNDECLARED_ACTION_DEPENDENCY: 根调用 Action '${targetRef}' 被拒绝: 目标包既非 actiondock.json 直接依赖,亦未被可见 Playbook 委托${reason ? ` (${reason})` : ""}`;
|
|
63
|
+
super(UNDECLARED_ACTION_DEPENDENCY, msg);
|
|
64
|
+
this.name = "UndeclaredActionDependencyError";
|
|
65
|
+
this.targetRef = targetRef;
|
|
66
|
+
this.caller = caller;
|
|
67
|
+
Object.setPrototypeOf(this, UndeclaredActionDependencyError.prototype);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* 判定单一 uses 声明项是否命中目标 Action(跨包调用授权单一事实源)。
|
|
72
|
+
*
|
|
73
|
+
* 匹配语义(安全铁律,逐字不变):
|
|
74
|
+
* - 完全限定名:`<targetPackageId>/<targetActionId>`;
|
|
75
|
+
* - 包级通配符:`<targetPackageId>/*`;
|
|
76
|
+
* - 裸包名:`<targetPackageId>`。
|
|
77
|
+
*
|
|
78
|
+
* DefaultPackageGraph.canCascadeCall 与 InvocationPolicy.checkUsesAuthorization
|
|
79
|
+
* 必须统一经由本谓词判定,禁止在调用点另建重复表达式分叉。
|
|
80
|
+
*/
|
|
81
|
+
export function isUsesDeclared(use, targetPackageId, targetActionId) {
|
|
82
|
+
return (use === `${targetPackageId}/${targetActionId}` ||
|
|
83
|
+
use === `${targetPackageId}/*` ||
|
|
84
|
+
use === targetPackageId);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* 默认包依赖图实现。
|
|
88
|
+
*/
|
|
89
|
+
export class DefaultPackageGraph {
|
|
90
|
+
packages;
|
|
91
|
+
root;
|
|
92
|
+
visiblePlaybooks;
|
|
93
|
+
delegatedActions;
|
|
94
|
+
constructor(packages, root, visiblePlaybooks, delegatedActions) {
|
|
95
|
+
this.packages = packages;
|
|
96
|
+
this.root = root;
|
|
97
|
+
this.visiblePlaybooks = visiblePlaybooks ?? new Map();
|
|
98
|
+
this.delegatedActions = delegatedActions ?? new Set();
|
|
99
|
+
}
|
|
100
|
+
get rootPackageId() {
|
|
101
|
+
return this.root?.id;
|
|
102
|
+
}
|
|
103
|
+
get directDependencyIds() {
|
|
104
|
+
if (!this.root)
|
|
105
|
+
return new Set();
|
|
106
|
+
const rootNode = this.packages.get(this.root.id);
|
|
107
|
+
return rootNode ? rootNode.directDependencies : new Set();
|
|
108
|
+
}
|
|
109
|
+
get transitiveDependencyIds() {
|
|
110
|
+
if (!this.root)
|
|
111
|
+
return new Set();
|
|
112
|
+
const rootNode = this.packages.get(this.root.id);
|
|
113
|
+
return rootNode ? rootNode.transitiveDependencies : new Set();
|
|
114
|
+
}
|
|
115
|
+
getPackage(id) {
|
|
116
|
+
return this.packages.get(id);
|
|
117
|
+
}
|
|
118
|
+
getNode(id) {
|
|
119
|
+
return this.packages.get(id);
|
|
120
|
+
}
|
|
121
|
+
hasPackage(id) {
|
|
122
|
+
return this.packages.has(id);
|
|
123
|
+
}
|
|
124
|
+
canRootCall(targetPackageId, targetActionId) {
|
|
125
|
+
if (this.root && targetPackageId === this.root.id) {
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
if (this.directDependencyIds.has(targetPackageId)) {
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
const qualifiedRef = `${targetPackageId}/${targetActionId}`;
|
|
132
|
+
if (this.delegatedActions.has(qualifiedRef)) {
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
assertRootCallAllowed(targetPackageId, targetActionId) {
|
|
138
|
+
if (!this.canRootCall(targetPackageId, targetActionId)) {
|
|
139
|
+
throw new UndeclaredActionDependencyError(`${targetPackageId}/${targetActionId}`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
canCascadeCall(callerPackageId, callerActionId, targetPackageId, targetActionId) {
|
|
143
|
+
if (callerPackageId === targetPackageId) {
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
const callerPkg = this.packages.get(callerPackageId);
|
|
147
|
+
if (!callerPkg) {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
const callerActionEntry = callerPkg.manifest.actions?.[callerActionId];
|
|
151
|
+
const usesList = callerActionEntry?.uses || [];
|
|
152
|
+
return usesList.some((u) => isUsesDeclared(u, targetPackageId, targetActionId));
|
|
153
|
+
}
|
|
154
|
+
assertCascadeCallAllowed(callerPackageId, callerActionId, targetPackageId, targetActionId) {
|
|
155
|
+
if (!this.canCascadeCall(callerPackageId, callerActionId, targetPackageId, targetActionId)) {
|
|
156
|
+
throw new UndeclaredActionDependencyError(`${targetPackageId}/${targetActionId}`, `${callerPackageId}/${callerActionId}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* 构建包节点公共字段(单一事实源:模式 A/B/C 共用,避免节点构造字面量三处拷贝)。
|
|
162
|
+
*/
|
|
163
|
+
function createPackageNodeFields(params) {
|
|
164
|
+
const digest = computeManifestDigest(params.manifest);
|
|
165
|
+
const identity = params.identity ??
|
|
166
|
+
createPackageIdentity({
|
|
167
|
+
id: params.id,
|
|
168
|
+
instanceId: `${params.id}:${params.root}`,
|
|
169
|
+
generation: params.generation ?? "",
|
|
170
|
+
});
|
|
171
|
+
return {
|
|
172
|
+
identity,
|
|
173
|
+
packageId: params.id,
|
|
174
|
+
root: params.root,
|
|
175
|
+
manifest: params.manifest,
|
|
176
|
+
manifestDigest: digest,
|
|
177
|
+
version: params.manifest.version || "0.1.0",
|
|
178
|
+
npmPackage: params.npmPackage,
|
|
179
|
+
directDependencies: new Set(),
|
|
180
|
+
transitiveDependencies: new Set(),
|
|
181
|
+
isDirect: params.isDirect,
|
|
182
|
+
isRoot: params.isRoot,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* 从各包清单的 dependencies 中补全直接依赖边(仅计入图中已存在的包)。
|
|
187
|
+
*/
|
|
188
|
+
function linkDirectDependencies(nodes) {
|
|
189
|
+
for (const node of nodes.values()) {
|
|
190
|
+
if (node.manifest.dependencies && typeof node.manifest.dependencies === "object") {
|
|
191
|
+
for (const depId of Object.keys(node.manifest.dependencies)) {
|
|
192
|
+
if (nodes.has(depId)) {
|
|
193
|
+
node.directDependencies.add(depId);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* 以 BFS 计算每个节点的传递依赖闭包(单一事实源,自带环防护)。
|
|
201
|
+
*/
|
|
202
|
+
function computeTransitiveDependencies(nodes) {
|
|
203
|
+
for (const node of nodes.values()) {
|
|
204
|
+
const q = Array.from(node.directDependencies);
|
|
205
|
+
const visited = new Set(node.directDependencies);
|
|
206
|
+
while (q.length > 0) {
|
|
207
|
+
const curr = q.shift();
|
|
208
|
+
node.transitiveDependencies.add(curr);
|
|
209
|
+
const depNode = nodes.get(curr);
|
|
210
|
+
if (depNode) {
|
|
211
|
+
for (const next of depNode.directDependencies) {
|
|
212
|
+
if (next !== node.identity.id && !visited.has(next)) {
|
|
213
|
+
visited.add(next);
|
|
214
|
+
q.push(next);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* 聚合根包与其直接依赖包的可见 Playbook 及委托点名的 Action(单一事实源)。
|
|
223
|
+
*/
|
|
224
|
+
function collectVisiblePlaybooks(rootNode, nodes) {
|
|
225
|
+
const visiblePlaybooks = new Map();
|
|
226
|
+
const delegatedActions = new Set();
|
|
227
|
+
if (rootNode && rootNode.root && existsSync(rootNode.root)) {
|
|
228
|
+
try {
|
|
229
|
+
const rootPbs = loadPlaybooks(rootNode.root, undefined, rootNode.manifest);
|
|
230
|
+
for (const [id, pb] of rootPbs.entries()) {
|
|
231
|
+
visiblePlaybooks.set(id, pb);
|
|
232
|
+
visiblePlaybooks.set(`${rootNode.packageId}/${id}`, pb);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
catch {
|
|
236
|
+
// 忽略根包 Playbook 加载异常
|
|
237
|
+
}
|
|
238
|
+
for (const depId of rootNode.directDependencies) {
|
|
239
|
+
if (depId === rootNode.packageId)
|
|
240
|
+
continue;
|
|
241
|
+
const depNode = nodes.get(depId);
|
|
242
|
+
if (depNode && depNode.root && existsSync(depNode.root)) {
|
|
243
|
+
try {
|
|
244
|
+
const depPbs = loadPlaybooks(depNode.root, undefined, depNode.manifest);
|
|
245
|
+
for (const [id, pb] of depPbs.entries()) {
|
|
246
|
+
visiblePlaybooks.set(`${depId}/${id}`, pb);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
catch {
|
|
250
|
+
// 忽略依赖包 Playbook 加载异常
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
for (const pb of visiblePlaybooks.values()) {
|
|
256
|
+
if (Array.isArray(pb.actions)) {
|
|
257
|
+
for (const actRef of pb.actions) {
|
|
258
|
+
if (typeof actRef === "string" && actRef.trim()) {
|
|
259
|
+
delegatedActions.add(actRef.trim());
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return { visiblePlaybooks, delegatedActions };
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* 包依赖拓扑图构建器 PackageGraphBuilder。
|
|
268
|
+
* 输入发现的包集合或工程根目录,统一实施版本冲突检测、lockfile 校验与拓扑图构建。
|
|
269
|
+
*/
|
|
270
|
+
export class PackageGraphBuilder {
|
|
271
|
+
options;
|
|
272
|
+
constructor(options = {}) {
|
|
273
|
+
this.options = options;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* 同步构建包依赖拓扑图(模式 A:显式包集合)。
|
|
277
|
+
*/
|
|
278
|
+
buildFromPackages(nodes, generation) {
|
|
279
|
+
for (const pkg of this.options.packages) {
|
|
280
|
+
const fields = createPackageNodeFields({
|
|
281
|
+
id: pkg.id,
|
|
282
|
+
root: pkg.root,
|
|
283
|
+
manifest: pkg.manifest,
|
|
284
|
+
npmPackage: pkg.id,
|
|
285
|
+
isDirect: Boolean(pkg.isCurrentProject),
|
|
286
|
+
isRoot: Boolean(pkg.isCurrentProject),
|
|
287
|
+
identity: pkg.identity,
|
|
288
|
+
generation,
|
|
289
|
+
});
|
|
290
|
+
nodes.set(pkg.id, fields);
|
|
291
|
+
}
|
|
292
|
+
let rootIdentity;
|
|
293
|
+
if (this.options.root) {
|
|
294
|
+
if (nodes.has(this.options.root)) {
|
|
295
|
+
rootIdentity = nodes.get(this.options.root).identity;
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
const absRoot = resolve(this.options.root);
|
|
299
|
+
for (const node of nodes.values()) {
|
|
300
|
+
if (resolve(node.root) === absRoot) {
|
|
301
|
+
rootIdentity = node.identity;
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
if (!rootIdentity) {
|
|
308
|
+
for (const node of nodes.values()) {
|
|
309
|
+
if (node.isRoot) {
|
|
310
|
+
rootIdentity = node.identity;
|
|
311
|
+
break;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
if (rootIdentity) {
|
|
316
|
+
const rootNode = nodes.get(rootIdentity.id);
|
|
317
|
+
if (rootNode) {
|
|
318
|
+
rootNode.isRoot = true;
|
|
319
|
+
rootNode.isDirect = true;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
linkDirectDependencies(nodes);
|
|
323
|
+
computeTransitiveDependencies(nodes);
|
|
324
|
+
const effectiveRootNode = rootIdentity ? nodes.get(rootIdentity.id) : undefined;
|
|
325
|
+
const { visiblePlaybooks, delegatedActions } = collectVisiblePlaybooks(effectiveRootNode, nodes);
|
|
326
|
+
return new DefaultPackageGraph(nodes, rootIdentity, visiblePlaybooks, delegatedActions);
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* 同步构建包依赖拓扑图(模式 C:全局包发现)。
|
|
330
|
+
*/
|
|
331
|
+
buildFromGlobalDiscovery(nodes, generation) {
|
|
332
|
+
const discOpts = {
|
|
333
|
+
...this.options.discoveryOptions,
|
|
334
|
+
customHome: this.options.discoveryOptions?.customHome ?? this.options.customHome,
|
|
335
|
+
scanLinkedPackages: this.options.discoveryOptions?.scanLinkedPackages ?? this.options.allowDevLinks ?? true,
|
|
336
|
+
};
|
|
337
|
+
const discovered = new PackageDiscovery(discOpts).discoverSync();
|
|
338
|
+
for (const pkg of discovered) {
|
|
339
|
+
const fields = createPackageNodeFields({
|
|
340
|
+
id: pkg.id,
|
|
341
|
+
root: pkg.root,
|
|
342
|
+
manifest: pkg.manifest,
|
|
343
|
+
npmPackage: pkg.id,
|
|
344
|
+
isDirect: Boolean(pkg.isCurrentProject),
|
|
345
|
+
isRoot: Boolean(pkg.isCurrentProject),
|
|
346
|
+
generation,
|
|
347
|
+
});
|
|
348
|
+
nodes.set(pkg.id, fields);
|
|
349
|
+
}
|
|
350
|
+
return new DefaultPackageGraph(nodes);
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* 同步构建包依赖拓扑图。
|
|
354
|
+
*/
|
|
355
|
+
buildSync() {
|
|
356
|
+
const projectRoot = this.options.projectRoot || this.options.root;
|
|
357
|
+
const absProjectRoot = projectRoot ? resolve(projectRoot) : undefined;
|
|
358
|
+
const generation = this.options.generationId || crypto.randomUUID();
|
|
359
|
+
const nodes = new Map();
|
|
360
|
+
// 模式 A:显式包集合模式(由 Host.rebuildGraphAndCatalog 或测试直接传入已发现包)
|
|
361
|
+
if (this.options.packages) {
|
|
362
|
+
return this.buildFromPackages(nodes, generation);
|
|
363
|
+
}
|
|
364
|
+
// 模式 B:单工程或根目录依赖解析闭包构建
|
|
365
|
+
if (absProjectRoot) {
|
|
366
|
+
let rootManifest = this.options.manifest;
|
|
367
|
+
if (!rootManifest && existsSync(absProjectRoot)) {
|
|
368
|
+
try {
|
|
369
|
+
rootManifest = loadManifest(absProjectRoot) || loadProjectConfig(absProjectRoot);
|
|
370
|
+
}
|
|
371
|
+
catch {
|
|
372
|
+
// 忽略清单加载异常
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
if (!rootManifest) {
|
|
376
|
+
rootManifest = {
|
|
377
|
+
id: basename(absProjectRoot),
|
|
378
|
+
version: "0.1.0",
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
const rootPackageId = rootManifest.id;
|
|
382
|
+
const rootIdentity = createPackageIdentity({
|
|
383
|
+
id: rootPackageId,
|
|
384
|
+
instanceId: `${rootPackageId}:${absProjectRoot}`,
|
|
385
|
+
generation,
|
|
386
|
+
});
|
|
387
|
+
const rootNode = {
|
|
388
|
+
...createPackageNodeFields({
|
|
389
|
+
id: rootPackageId,
|
|
390
|
+
root: absProjectRoot,
|
|
391
|
+
manifest: rootManifest,
|
|
392
|
+
npmPackage: rootPackageId,
|
|
393
|
+
isDirect: true,
|
|
394
|
+
isRoot: true,
|
|
395
|
+
identity: rootIdentity,
|
|
396
|
+
}),
|
|
397
|
+
};
|
|
398
|
+
nodes.set(rootPackageId, rootNode);
|
|
399
|
+
const lockfile = this.options.lockfile ?? loadLockfile(absProjectRoot);
|
|
400
|
+
const devLinkMap = new Map();
|
|
401
|
+
const scanLinked = Boolean(this.options.discoveryOptions?.scanLinkedPackages ?? this.options.allowDevLinks);
|
|
402
|
+
if (scanLinked) {
|
|
403
|
+
try {
|
|
404
|
+
const linked = listLinkedPackages(this.options.customHome);
|
|
405
|
+
for (const entry of linked) {
|
|
406
|
+
if (existsSync(entry.path)) {
|
|
407
|
+
devLinkMap.set(entry.id, entry.path);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
catch {
|
|
412
|
+
// 忽略扫描外部链接包异常
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
const versionRequirements = new Map();
|
|
416
|
+
function recordRequirement(pkgId, requester, rangeOrVersion) {
|
|
417
|
+
const existing = versionRequirements.get(pkgId) || [];
|
|
418
|
+
for (const req of existing) {
|
|
419
|
+
if (!areVersionsCompatible(req.rangeOrVersion, rangeOrVersion)) {
|
|
420
|
+
throw new ActionPackageVersionConflictError(pkgId, [
|
|
421
|
+
req,
|
|
422
|
+
{ requester, rangeOrVersion },
|
|
423
|
+
]);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
existing.push({ requester, rangeOrVersion });
|
|
427
|
+
versionRequirements.set(pkgId, existing);
|
|
428
|
+
}
|
|
429
|
+
const queue = [];
|
|
430
|
+
for (const [depId, spec] of Object.entries(rootManifest.dependencies || {})) {
|
|
431
|
+
rootNode.directDependencies.add(depId);
|
|
432
|
+
recordRequirement(depId, rootPackageId, spec);
|
|
433
|
+
queue.push({
|
|
434
|
+
pkgId: depId,
|
|
435
|
+
requester: rootPackageId,
|
|
436
|
+
rangeOrSpec: spec,
|
|
437
|
+
isDirect: true,
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
const packageRootsRecord = this.options.packageRoots && !Array.isArray(this.options.packageRoots)
|
|
441
|
+
? this.options.packageRoots
|
|
442
|
+
: undefined;
|
|
443
|
+
while (queue.length > 0) {
|
|
444
|
+
const item = queue.shift();
|
|
445
|
+
if (nodes.has(item.pkgId)) {
|
|
446
|
+
const existingNode = nodes.get(item.pkgId);
|
|
447
|
+
const pkgVer = existingNode.version || existingNode.manifest.version || "0.1.0";
|
|
448
|
+
const reqs = versionRequirements.get(item.pkgId) || [];
|
|
449
|
+
for (const req of reqs) {
|
|
450
|
+
if (!areVersionsCompatible(req.rangeOrVersion, pkgVer)) {
|
|
451
|
+
throw new ActionPackageVersionConflictError(item.pkgId, [
|
|
452
|
+
req,
|
|
453
|
+
{ requester: item.pkgId, rangeOrVersion: pkgVer },
|
|
454
|
+
]);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
continue;
|
|
458
|
+
}
|
|
459
|
+
let pkgDir = null;
|
|
460
|
+
const locked = lockfile?.packages?.[item.pkgId];
|
|
461
|
+
if (packageRootsRecord?.[item.pkgId]) {
|
|
462
|
+
pkgDir = packageRootsRecord[item.pkgId];
|
|
463
|
+
}
|
|
464
|
+
else if (devLinkMap.has(item.pkgId)) {
|
|
465
|
+
pkgDir = devLinkMap.get(item.pkgId);
|
|
466
|
+
}
|
|
467
|
+
else {
|
|
468
|
+
const candidateNames = [];
|
|
469
|
+
if (locked?.npmPackage) {
|
|
470
|
+
candidateNames.push(locked.npmPackage);
|
|
471
|
+
}
|
|
472
|
+
candidateNames.push(item.rangeOrSpec);
|
|
473
|
+
candidateNames.push(item.pkgId);
|
|
474
|
+
let cur = absProjectRoot;
|
|
475
|
+
while (true) {
|
|
476
|
+
for (const candName of candidateNames) {
|
|
477
|
+
const candPath = join(cur, "node_modules", candName);
|
|
478
|
+
if (existsSync(candPath) && existsSync(join(candPath, MANIFEST_FILE_NAME))) {
|
|
479
|
+
pkgDir = candPath;
|
|
480
|
+
break;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
if (pkgDir)
|
|
484
|
+
break;
|
|
485
|
+
const parent = dirname(cur);
|
|
486
|
+
if (parent === cur)
|
|
487
|
+
break;
|
|
488
|
+
cur = parent;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
if (!pkgDir || !existsSync(pkgDir)) {
|
|
492
|
+
throw new ActionDockError(PACKAGE_NOT_FOUND, `PACKAGE_NOT_FOUND: Package '${item.pkgId}' required by '${item.requester}' is not installed in ${absProjectRoot}. Please run 'ad add ${item.rangeOrSpec}'.`);
|
|
493
|
+
}
|
|
494
|
+
const manifestPath = join(pkgDir, MANIFEST_FILE_NAME);
|
|
495
|
+
if (!existsSync(manifestPath)) {
|
|
496
|
+
throw new Error(`Action package '${item.pkgId}' at '${pkgDir}' misses required manifest 'actiondock.json'`);
|
|
497
|
+
}
|
|
498
|
+
let manifestRaw;
|
|
499
|
+
try {
|
|
500
|
+
manifestRaw = readFileSync(manifestPath, "utf-8");
|
|
501
|
+
}
|
|
502
|
+
catch (err) {
|
|
503
|
+
throw new Error(`Failed to read manifest for '${item.pkgId}': ${err.message}`);
|
|
504
|
+
}
|
|
505
|
+
const depManifest = parseJsonWithoutDuplicates(manifestRaw);
|
|
506
|
+
const actualDigest = computeManifestDigest(depManifest);
|
|
507
|
+
if (locked?.manifestDigest && locked.manifestDigest !== actualDigest) {
|
|
508
|
+
throw new Error(`Manifest digest mismatch for package '${item.pkgId}': expected '${locked.manifestDigest}', got '${actualDigest}'. Re-resolution required.`);
|
|
509
|
+
}
|
|
510
|
+
const pkgVersion = depManifest.version || locked?.version || "0.1.0";
|
|
511
|
+
const reqs = versionRequirements.get(item.pkgId) || [];
|
|
512
|
+
for (const req of reqs) {
|
|
513
|
+
if (!areVersionsCompatible(req.rangeOrVersion, pkgVersion)) {
|
|
514
|
+
throw new ActionPackageVersionConflictError(item.pkgId, [
|
|
515
|
+
req,
|
|
516
|
+
{ requester: item.pkgId, rangeOrVersion: pkgVersion },
|
|
517
|
+
]);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
const identity = createPackageIdentity({
|
|
521
|
+
id: item.pkgId,
|
|
522
|
+
instanceId: `${item.pkgId}:${pkgDir}`,
|
|
523
|
+
generation,
|
|
524
|
+
});
|
|
525
|
+
const newNode = {
|
|
526
|
+
...createPackageNodeFields({
|
|
527
|
+
id: item.pkgId,
|
|
528
|
+
root: pkgDir,
|
|
529
|
+
manifest: depManifest,
|
|
530
|
+
npmPackage: locked?.npmPackage || item.rangeOrSpec,
|
|
531
|
+
isDirect: item.isDirect,
|
|
532
|
+
isRoot: false,
|
|
533
|
+
identity,
|
|
534
|
+
}),
|
|
535
|
+
};
|
|
536
|
+
nodes.set(item.pkgId, newNode);
|
|
537
|
+
for (const [subDepId, subSpec] of Object.entries(depManifest.dependencies || {})) {
|
|
538
|
+
recordRequirement(subDepId, item.pkgId, subSpec);
|
|
539
|
+
if (!nodes.has(subDepId)) {
|
|
540
|
+
queue.push({
|
|
541
|
+
pkgId: subDepId,
|
|
542
|
+
requester: item.pkgId,
|
|
543
|
+
rangeOrSpec: subSpec,
|
|
544
|
+
isDirect: false,
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
if (scanLinked) {
|
|
550
|
+
for (const [devPkgId, devPkgDir] of devLinkMap.entries()) {
|
|
551
|
+
if (devPkgId !== rootPackageId && !nodes.has(devPkgId) && existsSync(devPkgDir)) {
|
|
552
|
+
const manifestPath = join(devPkgDir, MANIFEST_FILE_NAME);
|
|
553
|
+
if (!existsSync(manifestPath))
|
|
554
|
+
continue;
|
|
555
|
+
try {
|
|
556
|
+
const manifestRaw = readFileSync(manifestPath, "utf-8");
|
|
557
|
+
const devManifest = parseJsonWithoutDuplicates(manifestRaw);
|
|
558
|
+
nodes.set(devPkgId, createPackageNodeFields({
|
|
559
|
+
id: devPkgId,
|
|
560
|
+
root: devPkgDir,
|
|
561
|
+
manifest: devManifest,
|
|
562
|
+
npmPackage: devPkgId,
|
|
563
|
+
isDirect: true,
|
|
564
|
+
isRoot: false,
|
|
565
|
+
generation,
|
|
566
|
+
}));
|
|
567
|
+
rootNode.directDependencies.add(devPkgId);
|
|
568
|
+
}
|
|
569
|
+
catch {
|
|
570
|
+
// 忽略解析失败的链接包
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
linkDirectDependencies(nodes);
|
|
576
|
+
computeTransitiveDependencies(nodes);
|
|
577
|
+
const { visiblePlaybooks, delegatedActions } = collectVisiblePlaybooks(rootNode, nodes);
|
|
578
|
+
return new DefaultPackageGraph(nodes, rootIdentity, visiblePlaybooks, delegatedActions);
|
|
579
|
+
}
|
|
580
|
+
// 模式 C:全局包发现构建
|
|
581
|
+
return this.buildFromGlobalDiscovery(nodes, generation);
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
* 异步构建包依赖拓扑图。
|
|
585
|
+
*/
|
|
586
|
+
async build() {
|
|
587
|
+
return this.buildSync();
|
|
588
|
+
}
|
|
589
|
+
}
|
package/dist/catalog/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export * from "./action-
|
|
2
|
-
export * from "./
|
|
3
|
-
export * from "./
|
|
4
|
-
export * from "./
|
|
5
|
-
export * from "./
|
|
1
|
+
export * from "./action-catalog.js";
|
|
2
|
+
export * from "./discovery.js";
|
|
3
|
+
export * from "./graph.js";
|
|
4
|
+
export * from "./resolve-action.js";
|
|
5
|
+
export * from "./resolve-playbook.js";
|
package/dist/catalog/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export * from "./action-
|
|
2
|
-
export * from "./
|
|
3
|
-
export * from "./
|
|
4
|
-
export * from "./
|
|
5
|
-
export * from "./
|
|
1
|
+
export * from "./action-catalog.js";
|
|
2
|
+
export * from "./discovery.js";
|
|
3
|
+
export * from "./graph.js";
|
|
4
|
+
export * from "./resolve-action.js";
|
|
5
|
+
export * from "./resolve-playbook.js";
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { ActionContract, ActionRef, ResolvedActionRef } from "@actiondock/sdk";
|
|
2
|
+
import type { PackageIdentity } from "../runtime/identity.js";
|
|
3
|
+
import type { ActionCatalog } from "./action-catalog.js";
|
|
4
|
+
import type { PackageGraph } from "./graph.js";
|
|
5
|
+
/**
|
|
6
|
+
* ActionRef 解析上下文。
|
|
7
|
+
*/
|
|
8
|
+
export interface ResolveActionContext {
|
|
9
|
+
/** 当前调用方包身份或包标识(可选) */
|
|
10
|
+
caller?: PackageIdentity | string;
|
|
11
|
+
/** 包拓扑图单一事实源 */
|
|
12
|
+
graph: PackageGraph;
|
|
13
|
+
/** 动作目录索引单一事实源 */
|
|
14
|
+
catalog: ActionCatalog;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Action 解析最终结果。
|
|
18
|
+
*/
|
|
19
|
+
export interface ResolvedAction {
|
|
20
|
+
/** 规范化解析引用值对象 */
|
|
21
|
+
readonly ref: ResolvedActionRef;
|
|
22
|
+
/** 目标包身份标识值对象 */
|
|
23
|
+
readonly package: PackageIdentity;
|
|
24
|
+
/** 动作入口文件相对路径 */
|
|
25
|
+
readonly entry: string;
|
|
26
|
+
/** 动作契约元数据规范 */
|
|
27
|
+
readonly contract: ActionContract;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* 规范化解析动作引用字符串或对象为 ActionRef。
|
|
31
|
+
* 铁律:ActionRef 解析只有一个事实源。
|
|
32
|
+
*/
|
|
33
|
+
export declare function parseActionRef(ref: ActionRef | string): ActionRef;
|
|
34
|
+
/**
|
|
35
|
+
* 纯领域动作解析函数 resolveAction。
|
|
36
|
+
* 铁律:ActionRef 解析只有一个事实源,禁止各模块各自编写短名匹配或启发式搜索。
|
|
37
|
+
*
|
|
38
|
+
* 解析次序:
|
|
39
|
+
* 1. 显式包限定标识符精确查找目标包与动作
|
|
40
|
+
* 2. 裸标识符优先查找 caller 调用者所在包
|
|
41
|
+
* 3. 裸标识符全局搜索:单命中返回、多命中抛出歧义异常、零命中抛出未找到异常
|
|
42
|
+
*/
|
|
43
|
+
export declare function resolveAction(ref: ActionRef | string, context: ResolveActionContext): ResolvedAction;
|