@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.
- package/README.md +77 -64
- 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 +106 -10
- package/dist/errors.js +105 -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/project/types.d.ts +5 -0
- 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 +12 -0
- package/dist/server/index.js +11 -0
- package/dist/server/mcp-endpoint.d.ts +61 -0
- package/dist/server/mcp-endpoint.js +118 -0
- package/dist/server/policy.d.ts +138 -0
- package/dist/server/policy.js +368 -0
- package/dist/server/routes/actions.js +114 -64
- package/dist/server/routes/common.d.ts +18 -33
- package/dist/server/routes/common.js +45 -65
- package/dist/server/routes/config.d.ts +1 -1
- package/dist/server/routes/config.js +55 -65
- package/dist/server/routes/doctor.d.ts +1 -1
- package/dist/server/routes/doctor.js +13 -21
- package/dist/server/routes/health.d.ts +1 -1
- package/dist/server/routes/health.js +4 -5
- package/dist/server/routes/info.d.ts +2 -2
- package/dist/server/routes/info.js +17 -24
- package/dist/server/routes/playbooks.js +23 -36
- package/dist/server/routes/runs.js +151 -141
- package/dist/server/routes/state.d.ts +1 -1
- package/dist/server/routes/state.js +64 -63
- package/dist/server/security.d.ts +11 -0
- package/dist/server/security.js +36 -19
- package/dist/server/server.d.ts +2 -2
- package/dist/server/server.js +224 -238
- package/dist/server/types.d.ts +68 -21
- 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
package/README.md
CHANGED
|
@@ -1,115 +1,128 @@
|
|
|
1
1
|
# @actiondock/core
|
|
2
2
|
|
|
3
|
-
ActionDock 2.
|
|
3
|
+
ActionDock 2.x Node-first 原生运行时与核心领域。
|
|
4
4
|
|
|
5
5
|
[](https://nodejs.org/)
|
|
6
6
|
[](https://www.typescriptlang.org/)
|
|
7
7
|
[](https://opensource.org/licenses/Apache-2.0)
|
|
8
8
|
|
|
9
|
-
`@actiondock/core`
|
|
9
|
+
`@actiondock/core` 是 ActionDock 2.x 的核心领域内核与 Node-first 原生运行时。统一暴露最小化核心服务门面(`createActionDock`、`connectActionDock`)、标准服务端口体系(`DiscoveryPort`、`ExecutionPort`、`RunsPort`、`EventsPort`、`ConfigPort`、`StatePort`)、统一错误模型(`ActionDockError`)、原生平台装配(`createNodePlatform`)、服务启动(`startActionDockServer`)与包图依赖契约(`PackageGraph`),内部驱动存储引擎、受管进程与 HTTP 网络服务。
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
-
##
|
|
13
|
+
## 子路径导出规范
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
为保障边界清晰与根入口极简,`@actiondock/core` 提供精细化子路径导出:
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
[TargetError](./src/target/types.ts) 继承标准 Error,提供机器可读的结构化错误码与附加详情:
|
|
26
|
-
|
|
27
|
-
- `TARGET_PROTOCOL_UNSUPPORTED`:协议版本或特性不受支持。
|
|
28
|
-
- `TARGET_CAPABILITY_UNAVAILABLE`:目标端未启用或缺失所需能力。
|
|
29
|
-
- `TARGET_RESULT_UNKNOWN`:连接超时或中断导致执行结果状态未知。
|
|
17
|
+
- `.`:核心公共根入口,仅暴露 minimal 服务门面、服务端口、平台工厂与核心契约。
|
|
18
|
+
- `./server`:HTTP 服务容器、路由分发、TLS 安全与服务端守护进程。
|
|
19
|
+
- `./project`:项目元数据、清单与依赖管理、依赖闭包及原子事务。
|
|
20
|
+
- `./registry`:包注册表、软链接治理与包根目录寻址。
|
|
21
|
+
- `./profile`:远程连接配置与管理客户端。
|
|
22
|
+
- `./graph`:包图模型与动作目录解析。
|
|
23
|
+
- `./package`:包级运行时、存储驱动与参数解析工具。
|
|
30
24
|
|
|
31
25
|
---
|
|
32
26
|
|
|
33
|
-
##
|
|
27
|
+
## 统一执行主链
|
|
28
|
+
|
|
29
|
+
ActionDock 2.x 将所有调用形态(命令行、协议服务、微服务与测试沙箱)收敛至统一的确定性执行主链:
|
|
34
30
|
|
|
35
|
-
|
|
31
|
+
```text
|
|
32
|
+
Service -> Resolution -> PackageRuntime -> ExecutionService -> ActionRunner -> Action
|
|
33
|
+
```
|
|
36
34
|
|
|
37
|
-
-
|
|
38
|
-
- `
|
|
39
|
-
-
|
|
35
|
+
- 服务接入:通过统一服务门面或标准服务端口接收外部调用请求与入参数据。
|
|
36
|
+
- 解析定位:通过 `resolveAction` 依赖单一事实源完成动作寻址与跨包引用消歧。
|
|
37
|
+
- 运行时装配:基于包图节点构建隔离的包级执行上下文与依赖环境。
|
|
38
|
+
- 执行协调:统筹并发配额、追踪根调用与协同取消信号。
|
|
39
|
+
- 动作执行:驱动单一终态状态机,执行入参出参模式校验、循环依赖拦截与状态持久化。
|
|
40
|
+
- 业务执行:执行开发者编写的纯粹业务逻辑并产出强类型结果。
|
|
40
41
|
|
|
41
42
|
---
|
|
42
43
|
|
|
43
|
-
##
|
|
44
|
+
## 统一服务门面与标准服务端口
|
|
44
45
|
|
|
45
|
-
|
|
46
|
+
### 统一服务门面
|
|
46
47
|
|
|
47
|
-
|
|
48
|
-
- 原子事务:[beginTransaction](./src/project/transactions.ts) 在执行依赖增删(如 `ad add` 与 `ad remove`)前为 `package.json`、`actiondock.json` 与 `actiondock.lock.json` 创建磁盘快照。若安装或校验流程失败,自动执行原子回滚并恢复原始状态。
|
|
48
|
+
通过顶层工厂函数提供无缝屏蔽本地与远程拓扑差异的服务门面:
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
- 本地服务门面 `createActionDock`:创建本地 `ActionDockService` 服务端口实例,在当前 Node.js 进程内装配原生运行时驱动并高效执行。
|
|
51
|
+
- 远端服务门面 `connectActionDock`:创建远端 `ActionDockService` 服务端口实例,通过 HTTP 协议与远端 ActionDock 服务通信,支持鉴权令牌、请求超时控制与证书安全校验。
|
|
52
|
+
|
|
53
|
+
### 标准服务端口体系
|
|
51
54
|
|
|
52
|
-
|
|
55
|
+
系统将所有对外能力解耦并收敛为六大标准服务端口契约:
|
|
53
56
|
|
|
54
|
-
-
|
|
55
|
-
-
|
|
56
|
-
-
|
|
57
|
+
- 发现端口 `DiscoveryPort`:负责包与动作的元数据发现、清单检索、全文过滤与规程查询。
|
|
58
|
+
- 执行端口 `ExecutionPort`:负责动作的同步阻塞执行(`run`)与异步启动执行(`start`)。
|
|
59
|
+
- 运行端口 `RunsPort`:负责任务运行历史列表、单次详情查询与协同取消(`cancel`)。
|
|
60
|
+
- 事件端口 `EventsPort`:负责任务执行实时事件流订阅。
|
|
61
|
+
- 配置端口 `ConfigPort`:负责运行时分层配置读取、持久化配置管理与环境变量满足度体检。
|
|
62
|
+
- 状态端口 `StatePort`:负责包级与动作级持久化键值存取、前缀列举与过期清理。
|
|
57
63
|
|
|
58
64
|
---
|
|
59
65
|
|
|
60
|
-
##
|
|
66
|
+
## 单一事实源架构原则
|
|
61
67
|
|
|
62
|
-
|
|
68
|
+
ActionDock 2.x 全面贯彻单一事实源设计,彻底杜绝各模块私自实现短名搜索或启发式猜测:
|
|
63
69
|
|
|
64
|
-
|
|
70
|
+
- 包图发现单一事实源 `PackageDiscovery`:自顶向下扫描工作区与全局注册表,建立包目录索引。
|
|
71
|
+
- 包拓扑图单一事实源 `PackageGraph`:维护包节点身份标识、实例版本与拓扑依赖关系。
|
|
72
|
+
- 动作目录单一事实源 `ActionCatalog`:统一聚合索引所有已加载包的动作元数据,提供确定性的多维检索能力。
|
|
73
|
+
- 动作解析单一事实源 `resolveAction`:作为全系统动作引用的唯一解析函数。优先支持包限定斜杠语法(`<package-id>/<action-id>`)与当前调用方所属包优先匹配;严格禁止冒号历史语法(`pkg:action`)。
|
|
74
|
+
- 调用治理策略单一事实源 `InvocationPolicy`:统筹管理根任务最大并发配额(默认 32)、子任务并发上限(默认 64)与最大调用嵌套深度(默认 16)。
|
|
65
75
|
|
|
66
|
-
|
|
67
|
-
- `prepare(sql: string): SqliteStatement`:编译 SQL 模板,生成预编译语句对象。
|
|
68
|
-
- `transaction<T>(fn: () => T): T`:同步事务执行器,在出现异常时自动回滚,并在驱动层严格拦截异步 Promise 以避免事务泄漏。
|
|
69
|
-
- `close(): void`:释放数据库连接与文件句柄。
|
|
76
|
+
---
|
|
70
77
|
|
|
71
|
-
|
|
78
|
+
## 原生运行时驱动
|
|
72
79
|
|
|
73
|
-
|
|
80
|
+
`@actiondock/core` 深度集成 Node.js 24 原生能力,无需编译外部二进制扩展:
|
|
74
81
|
|
|
75
|
-
-
|
|
76
|
-
-
|
|
77
|
-
-
|
|
78
|
-
-
|
|
79
|
-
-
|
|
80
|
-
- ProcessExecutor 进程执行器接口:抽象跨平台的子进程操作,向后兼容一次性命令执行。
|
|
82
|
+
- 原生存储驱动 `NodeSqliteDriver`:基于 Node.js 原生 `node:sqlite`(`DatabaseSync`)构建同步存储驱动。默认启用预写日志模式(WAL)、外键约束检查与忙等待超时。
|
|
83
|
+
- 受管进程平台驱动 `NodeProcessDriver`:实现完整的受管进程治理体系。基于管道彻底切断子进程与宿主标准流的物理连通;支持跨平台独立进程组管理与信号派发;提供独占控制权租约、逐流增量读取与优雅终止。
|
|
84
|
+
- 原生网络服务容器 `NodeHttpServer`:基于 Node.js 原生 `node:http` 承载 RESTful 微服务与 Server-Sent Events 事件流。
|
|
85
|
+
- 原生模块加载器 `NodeModuleLoader`:基于 Node.js 原生类型擦除机制直接加载 TypeScript 源码,免除前置编译转译开销。
|
|
86
|
+
- 原生文件系统抽象 `NodeFileSystem`:提供跨平台文件读写与原子文件事务保障。
|
|
81
87
|
|
|
82
88
|
---
|
|
83
89
|
|
|
84
|
-
##
|
|
90
|
+
## 微服务启动与访问控制
|
|
85
91
|
|
|
86
|
-
|
|
92
|
+
通过 `startActionDockServer` 启动 Node.js 原生 HTTP/HTTPS 微服务,提供标准 RESTful API 与统一内嵌 `/mcp` 端点:
|
|
87
93
|
|
|
88
|
-
|
|
94
|
+
- 服务配置参数(`ServerOptions`):
|
|
95
|
+
- `port`:监听端口(默认 5177)。
|
|
96
|
+
- `host`:监听地址(默认 127.0.0.1,监听非回环地址时强制要求配置 token)。
|
|
97
|
+
- `token`:服务访问鉴权令牌。
|
|
98
|
+
- `packageAllowlist`:允许访问执行的包标识白名单列表(为空允许全部)。
|
|
99
|
+
- `actionAllowlist`:允许访问执行的动作标识白名单列表(为空允许全部,支持短名 actionId 与全限定名 packageId/actionId)。
|
|
100
|
+
- `tls`:HTTPS 证书与私钥配置。
|
|
101
|
+
- `corsOrigins`:允许的跨域来源白名单。
|
|
102
|
+
- 权限交集与安全拦截:
|
|
103
|
+
- 同时配置 `packageAllowlist` 与 `actionAllowlist` 时取两者交集。
|
|
104
|
+
- 未在白名单中的动作详情调阅与执行请求均被严格拦截,返回 HTTP 403 状态码与 `ACTION_FORBIDDEN` 结构化错误。
|
|
105
|
+
- 历史运行记录查询、单次详情与取消操作同步实施白名单校验。
|
|
106
|
+
- 统一内嵌的 MCP 协议端点工具注册与任务扩展同样受白名单联动过滤。
|
|
89
107
|
|
|
90
|
-
|
|
91
|
-
- 模式严格校验:在 Action 执行前校验输入数据是否满足模式规范,校验失败时直接阻断并生成结构化诊断信息。
|
|
92
|
-
- 运行记录持久化:在 SQLite 中写入 `running` 状态记录,并在结束时流转至对应终态。
|
|
93
|
-
- 生命周期状态转换:涵盖 `running`、`success`、`failed`、`timed_out`、`cancelled`、`interrupted` 状态。
|
|
94
|
-
- 上下文环境合成:动态构建 ActionContext,集成配置优先级解析器、状态存储器与标准错误流日志记录器。
|
|
108
|
+
---
|
|
95
109
|
|
|
96
|
-
|
|
110
|
+
## 数据目录锁与故障自愈
|
|
97
111
|
|
|
98
|
-
|
|
112
|
+
通过 `DataDirLock` 在数据目录下维护 `.actiondock.data.lock` 排他文件锁,记录宿主进程与受管子进程状态:
|
|
99
113
|
|
|
100
|
-
-
|
|
101
|
-
-
|
|
102
|
-
-
|
|
103
|
-
- 事件汇聚分发:将执行过程中的状态变更事件统一推送到事件接收器中。
|
|
114
|
+
- 活跃进程冲突防护:检测到已有活跃宿主主进程正在持有该数据目录时,抛出 `DATA_DIR_IN_USE` 错误拒绝并发启动。
|
|
115
|
+
- 孤儿进程保护:检测到前序宿主主进程异常退出但仍有关联受管子进程处于运行状态时,抛出 `DATA_DIR_RECOVERY_REQUIRED` 错误,阻止脏写并等待子进程回收。
|
|
116
|
+
- 故障自动恢复:前序宿主进程与关联子进程均已死亡时,当前宿主自动接管排他锁并安全清理残留会话。
|
|
104
117
|
|
|
105
118
|
---
|
|
106
119
|
|
|
107
|
-
##
|
|
120
|
+
## 依赖管理与原子事务
|
|
108
121
|
|
|
109
|
-
|
|
122
|
+
基于 `actiondock.lock.json`(规范版本 `lockfileVersion: 1`)提供严格的依赖版本锁定与原子事务保护:
|
|
110
123
|
|
|
111
|
-
-
|
|
112
|
-
-
|
|
124
|
+
- 依赖图构建:`PackageGraphBuilder` 递归解析本地包依赖与符号链接,统一建立拓扑图并检测版本冲突。
|
|
125
|
+
- 原子事务:`beginTransaction` 在执行依赖增删(如 `ad add` 与 `ad remove`)前为 `package.json`、`actiondock.json` 与 `actiondock.lock.json` 创建快照。若安装或校验流程失败,自动执行原子回滚并恢复原始状态。
|
|
113
126
|
|
|
114
127
|
---
|
|
115
128
|
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { ActionContract, ActionRef } from "@actiondock/sdk";
|
|
2
|
+
import type { PackageIdentity } from "../runtime/identity.js";
|
|
3
|
+
import type { PackageGraph } from "./graph.js";
|
|
4
|
+
/**
|
|
5
|
+
* 动作目录候选条目规范。
|
|
6
|
+
*/
|
|
7
|
+
export interface ActionCandidate {
|
|
8
|
+
/** 所属包唯一逻辑标识 */
|
|
9
|
+
readonly packageId: string;
|
|
10
|
+
/** 所属包唯一身份标识值对象 */
|
|
11
|
+
readonly packageIdentity: PackageIdentity;
|
|
12
|
+
/** 动作唯一标识符 */
|
|
13
|
+
readonly actionId: string;
|
|
14
|
+
/** 动作契约元数据定义 */
|
|
15
|
+
readonly contract: ActionContract;
|
|
16
|
+
/** 动作执行入口相对文件路径 */
|
|
17
|
+
readonly entry: string;
|
|
18
|
+
/** 所属包根目录绝对物理路径 */
|
|
19
|
+
readonly packageRoot: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* 动作目录索引 ActionCatalog 契约。
|
|
23
|
+
*/
|
|
24
|
+
export interface ActionCatalog {
|
|
25
|
+
/**
|
|
26
|
+
* 按动作引用查找候选动作列表。
|
|
27
|
+
* 若指定了 packageId,仅匹配对应包;若未指定 packageId,返回全部同名候选。
|
|
28
|
+
*/
|
|
29
|
+
find(ref: ActionRef | string): ActionCandidate[];
|
|
30
|
+
/**
|
|
31
|
+
* 获取已索引候选动作集合(可选限定指定包)。
|
|
32
|
+
*/
|
|
33
|
+
list(packageId?: string): ActionCandidate[];
|
|
34
|
+
/**
|
|
35
|
+
* 精确获取特定包内的特定动作候选。
|
|
36
|
+
*/
|
|
37
|
+
get(packageId: string, actionId: string): ActionCandidate | undefined;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* 动作目录默认实现 DefaultActionCatalog。
|
|
41
|
+
* 基于 PackageGraph 与包内 manifest/actions 构建 Action 索引。
|
|
42
|
+
*/
|
|
43
|
+
export declare class DefaultActionCatalog implements ActionCatalog {
|
|
44
|
+
private readonly byPackageAndAction;
|
|
45
|
+
private readonly byActionId;
|
|
46
|
+
private readonly byPackageId;
|
|
47
|
+
private readonly graph;
|
|
48
|
+
private readonly actionsProvider?;
|
|
49
|
+
constructor(graph: PackageGraph, actionsProvider?: (packageId: string) => Map<string, any> | undefined);
|
|
50
|
+
private checkDynamicAction;
|
|
51
|
+
private addCandidate;
|
|
52
|
+
private indexGraph;
|
|
53
|
+
find(ref: ActionRef | string): ActionCandidate[];
|
|
54
|
+
list(packageId?: string): ActionCandidate[];
|
|
55
|
+
get(packageId: string, actionId: string): ActionCandidate | undefined;
|
|
56
|
+
}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { existsSync, readdirSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { parseActionRef } from "./resolve-action.js";
|
|
4
|
+
/**
|
|
5
|
+
* 推断清单声明的 Action 入口相对路径:优先 .ts,不存在时回退 .js,兼容纯 JS 包。
|
|
6
|
+
*/
|
|
7
|
+
function inferActionEntry(packageRoot, manifest, actionId) {
|
|
8
|
+
const actionsDir = manifest?.actionsDir || "actions";
|
|
9
|
+
const tsEntry = join(actionsDir, `${actionId}.ts`);
|
|
10
|
+
return existsSync(join(packageRoot, tsEntry)) ? tsEntry : join(actionsDir, `${actionId}.js`);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* 动作目录默认实现 DefaultActionCatalog。
|
|
14
|
+
* 基于 PackageGraph 与包内 manifest/actions 构建 Action 索引。
|
|
15
|
+
*/
|
|
16
|
+
export class DefaultActionCatalog {
|
|
17
|
+
byPackageAndAction = new Map();
|
|
18
|
+
byActionId = new Map();
|
|
19
|
+
byPackageId = new Map();
|
|
20
|
+
graph;
|
|
21
|
+
actionsProvider;
|
|
22
|
+
constructor(graph, actionsProvider) {
|
|
23
|
+
this.graph = graph;
|
|
24
|
+
this.actionsProvider = actionsProvider;
|
|
25
|
+
this.indexGraph(graph, actionsProvider);
|
|
26
|
+
}
|
|
27
|
+
checkDynamicAction(packageId, actionId) {
|
|
28
|
+
if (!this.actionsProvider)
|
|
29
|
+
return undefined;
|
|
30
|
+
const provided = this.actionsProvider(packageId);
|
|
31
|
+
if (!provided)
|
|
32
|
+
return undefined;
|
|
33
|
+
const act = provided.get(actionId);
|
|
34
|
+
if (!act)
|
|
35
|
+
return undefined;
|
|
36
|
+
const node = this.graph.packages.get(packageId);
|
|
37
|
+
if (!node)
|
|
38
|
+
return undefined;
|
|
39
|
+
const candidate = {
|
|
40
|
+
packageId,
|
|
41
|
+
packageIdentity: node.identity,
|
|
42
|
+
actionId,
|
|
43
|
+
contract: {
|
|
44
|
+
id: actionId,
|
|
45
|
+
description: act?.description,
|
|
46
|
+
inputSchema: act?.inputSchema,
|
|
47
|
+
outputSchema: act?.outputSchema,
|
|
48
|
+
uses: act?.uses,
|
|
49
|
+
tags: act?.tags,
|
|
50
|
+
annotations: act?.annotations,
|
|
51
|
+
},
|
|
52
|
+
entry: act?.entry || "",
|
|
53
|
+
packageRoot: node.root || "",
|
|
54
|
+
};
|
|
55
|
+
this.addCandidate(candidate);
|
|
56
|
+
return candidate;
|
|
57
|
+
}
|
|
58
|
+
addCandidate(candidate) {
|
|
59
|
+
const qualifiedKey = `${candidate.packageId}/${candidate.actionId}`;
|
|
60
|
+
this.byPackageAndAction.set(qualifiedKey, candidate);
|
|
61
|
+
let forAction = this.byActionId.get(candidate.actionId);
|
|
62
|
+
if (!forAction) {
|
|
63
|
+
forAction = [];
|
|
64
|
+
this.byActionId.set(candidate.actionId, forAction);
|
|
65
|
+
}
|
|
66
|
+
forAction.push(candidate);
|
|
67
|
+
let forPackage = this.byPackageId.get(candidate.packageId);
|
|
68
|
+
if (!forPackage) {
|
|
69
|
+
forPackage = [];
|
|
70
|
+
this.byPackageId.set(candidate.packageId, forPackage);
|
|
71
|
+
}
|
|
72
|
+
forPackage.push(candidate);
|
|
73
|
+
}
|
|
74
|
+
indexGraph(graph, actionsProvider) {
|
|
75
|
+
for (const node of graph.packages.values()) {
|
|
76
|
+
const packageId = node.identity.id;
|
|
77
|
+
const manifest = node.manifest;
|
|
78
|
+
// 1. 清单显式 actions 声明优先索引
|
|
79
|
+
if (manifest?.actions && typeof manifest.actions === "object") {
|
|
80
|
+
for (const [actionId, item] of Object.entries(manifest.actions)) {
|
|
81
|
+
const entry = item?.entry || inferActionEntry(node.root, manifest, actionId);
|
|
82
|
+
const candidate = {
|
|
83
|
+
packageId,
|
|
84
|
+
packageIdentity: node.identity,
|
|
85
|
+
actionId,
|
|
86
|
+
contract: {
|
|
87
|
+
id: actionId,
|
|
88
|
+
description: item?.description,
|
|
89
|
+
inputSchema: item?.inputSchema,
|
|
90
|
+
outputSchema: item?.outputSchema,
|
|
91
|
+
uses: item?.uses,
|
|
92
|
+
tags: item?.tags,
|
|
93
|
+
annotations: item?.annotations,
|
|
94
|
+
},
|
|
95
|
+
entry,
|
|
96
|
+
packageRoot: node.root,
|
|
97
|
+
};
|
|
98
|
+
this.addCandidate(candidate);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// 2. 内存动态注入动作索引(测试或 Host 注册场景)
|
|
102
|
+
if (actionsProvider) {
|
|
103
|
+
const dynActions = actionsProvider(packageId);
|
|
104
|
+
if (dynActions && typeof dynActions.entries === "function") {
|
|
105
|
+
for (const [actionId, act] of dynActions.entries()) {
|
|
106
|
+
const qualifiedKey = `${packageId}/${actionId}`;
|
|
107
|
+
if (!this.byPackageAndAction.has(qualifiedKey)) {
|
|
108
|
+
const contract = act?.contract || { id: actionId };
|
|
109
|
+
const candidate = {
|
|
110
|
+
packageId,
|
|
111
|
+
packageIdentity: node.identity,
|
|
112
|
+
actionId,
|
|
113
|
+
contract,
|
|
114
|
+
entry: "",
|
|
115
|
+
packageRoot: node.root,
|
|
116
|
+
};
|
|
117
|
+
this.addCandidate(candidate);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// 3. actions 目录回退扫描
|
|
123
|
+
const actionsDir = join(node.root, manifest?.actionsDir || "actions");
|
|
124
|
+
if (existsSync(actionsDir)) {
|
|
125
|
+
try {
|
|
126
|
+
const files = readdirSync(actionsDir);
|
|
127
|
+
for (const file of files) {
|
|
128
|
+
if (file.endsWith(".ts") || file.endsWith(".js")) {
|
|
129
|
+
if (file.endsWith(".d.ts") || file.endsWith(".test.ts") || file.endsWith(".spec.ts")) {
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
const actionId = file.replace(/\.(ts|js)$/, "");
|
|
133
|
+
const qualifiedKey = `${packageId}/${actionId}`;
|
|
134
|
+
if (!this.byPackageAndAction.has(qualifiedKey)) {
|
|
135
|
+
const candidate = {
|
|
136
|
+
packageId,
|
|
137
|
+
packageIdentity: node.identity,
|
|
138
|
+
actionId,
|
|
139
|
+
contract: { id: actionId },
|
|
140
|
+
entry: join(manifest?.actionsDir || "actions", file),
|
|
141
|
+
packageRoot: node.root,
|
|
142
|
+
};
|
|
143
|
+
this.addCandidate(candidate);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
// 忽略扫描目录异常
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
find(ref) {
|
|
155
|
+
const parsed = parseActionRef(ref);
|
|
156
|
+
if (parsed.packageId) {
|
|
157
|
+
const item = this.get(parsed.packageId, parsed.actionId);
|
|
158
|
+
return item ? [item] : [];
|
|
159
|
+
}
|
|
160
|
+
if (this.actionsProvider) {
|
|
161
|
+
for (const node of this.graph.packages.values()) {
|
|
162
|
+
const key = `${node.identity.id}/${parsed.actionId}`;
|
|
163
|
+
if (!this.byPackageAndAction.has(key)) {
|
|
164
|
+
this.checkDynamicAction(node.identity.id, parsed.actionId);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return this.byActionId.get(parsed.actionId) || [];
|
|
169
|
+
}
|
|
170
|
+
list(packageId) {
|
|
171
|
+
if (packageId) {
|
|
172
|
+
if (this.actionsProvider) {
|
|
173
|
+
const provided = this.actionsProvider(packageId);
|
|
174
|
+
if (provided) {
|
|
175
|
+
for (const actionId of provided.keys()) {
|
|
176
|
+
if (!this.byPackageAndAction.has(`${packageId}/${actionId}`)) {
|
|
177
|
+
this.checkDynamicAction(packageId, actionId);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return this.byPackageId.get(packageId) || [];
|
|
183
|
+
}
|
|
184
|
+
if (this.actionsProvider) {
|
|
185
|
+
for (const node of this.graph.packages.values()) {
|
|
186
|
+
const provided = this.actionsProvider(node.identity.id);
|
|
187
|
+
if (provided) {
|
|
188
|
+
for (const actionId of provided.keys()) {
|
|
189
|
+
if (!this.byPackageAndAction.has(`${node.identity.id}/${actionId}`)) {
|
|
190
|
+
this.checkDynamicAction(node.identity.id, actionId);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return Array.from(this.byPackageAndAction.values());
|
|
197
|
+
}
|
|
198
|
+
get(packageId, actionId) {
|
|
199
|
+
return (this.byPackageAndAction.get(`${packageId}/${actionId}`) ||
|
|
200
|
+
this.checkDynamicAction(packageId, actionId));
|
|
201
|
+
}
|
|
202
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { ActionDockManifest } from "../project/types.js";
|
|
2
|
+
import { type RegistryStore } from "../registry/store.js";
|
|
3
|
+
import type { PackageIdentity } from "../runtime/identity.js";
|
|
4
|
+
/**
|
|
5
|
+
* 发现的包基本信息规范。
|
|
6
|
+
*/
|
|
7
|
+
export interface DiscoveredPackage {
|
|
8
|
+
/** 逻辑包唯一标识符 */
|
|
9
|
+
readonly id: string;
|
|
10
|
+
/** 包物理根目录绝对路径 */
|
|
11
|
+
readonly root: string;
|
|
12
|
+
/** 包清单定义 */
|
|
13
|
+
readonly manifest: ActionDockManifest;
|
|
14
|
+
/** 包物理与快照身份凭证(可选,由已有运行时传入) */
|
|
15
|
+
readonly identity?: PackageIdentity;
|
|
16
|
+
/** 是否来自工作区目录扫描发现 */
|
|
17
|
+
readonly isWorkspaceChild?: boolean;
|
|
18
|
+
/** 是否为当前工作目录工程 */
|
|
19
|
+
readonly isCurrentProject?: boolean;
|
|
20
|
+
/** 是否来自显式链接的外部包 */
|
|
21
|
+
readonly isLinked?: boolean;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* 包发现配置选项。
|
|
25
|
+
*/
|
|
26
|
+
export interface PackageDiscoveryOptions {
|
|
27
|
+
/** 当前项目根路径(可选) */
|
|
28
|
+
currentProjectRoot?: string;
|
|
29
|
+
/** 自定义 ActionDock 主目录路径(用于定位注册表) */
|
|
30
|
+
customHome?: string;
|
|
31
|
+
/** 显式注入的注册表存储实例(可选,默认使用 DefaultRegistryStore) */
|
|
32
|
+
registryStore?: RegistryStore;
|
|
33
|
+
/** 附加显式包根目录集合 */
|
|
34
|
+
packageRoots?: string[];
|
|
35
|
+
/** 附加显式工作区根目录集合 */
|
|
36
|
+
workspaceRoots?: string[];
|
|
37
|
+
/** 工作区目录扫描最大深度(默认 3) */
|
|
38
|
+
workspaceScanDepth?: number;
|
|
39
|
+
/** 是否扫描已注册链接包(默认为 true) */
|
|
40
|
+
scanLinkedPackages?: boolean;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* 包发现单一事实源 PackageDiscovery。
|
|
44
|
+
* 负责聚合当前工程、用户显式注册包位置与工作区根目录,输出已发现包集合。
|
|
45
|
+
* 纯粹负责发现物理位置并去重冲突检测,严禁进行依赖鉴权或动作调用拦截。
|
|
46
|
+
*/
|
|
47
|
+
export declare class PackageDiscovery {
|
|
48
|
+
private readonly options;
|
|
49
|
+
/** 包标识到物理根路径(realpath 归一)的查重映射,避免注册路径的线性全表扫描 */
|
|
50
|
+
private readonly idRealPaths;
|
|
51
|
+
constructor(options?: PackageDiscoveryOptions);
|
|
52
|
+
/**
|
|
53
|
+
* 同步发现所有可用包基本信息集合。
|
|
54
|
+
*/
|
|
55
|
+
discoverSync(): DiscoveredPackage[];
|
|
56
|
+
/**
|
|
57
|
+
* 异步发现所有可用包基本信息集合。
|
|
58
|
+
*/
|
|
59
|
+
discover(): Promise<DiscoveredPackage[]>;
|
|
60
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { existsSync, realpathSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { loadProjectConfig } from "../project/loader.js";
|
|
4
|
+
import { loadManifest } from "../project/manifest.js";
|
|
5
|
+
import { DefaultRegistryStore } from "../registry/store.js";
|
|
6
|
+
import { discoverProjectConfigs } from "../registry/scan.js";
|
|
7
|
+
/**
|
|
8
|
+
* 包发现单一事实源 PackageDiscovery。
|
|
9
|
+
* 负责聚合当前工程、用户显式注册包位置与工作区根目录,输出已发现包集合。
|
|
10
|
+
* 纯粹负责发现物理位置并去重冲突检测,严禁进行依赖鉴权或动作调用拦截。
|
|
11
|
+
*/
|
|
12
|
+
export class PackageDiscovery {
|
|
13
|
+
options;
|
|
14
|
+
/** 包标识到物理根路径(realpath 归一)的查重映射,避免注册路径的线性全表扫描 */
|
|
15
|
+
idRealPaths = new Map();
|
|
16
|
+
constructor(options = {}) {
|
|
17
|
+
this.options = options;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* 同步发现所有可用包基本信息集合。
|
|
21
|
+
*/
|
|
22
|
+
discoverSync() {
|
|
23
|
+
const packages = new Map();
|
|
24
|
+
this.idRealPaths.clear();
|
|
25
|
+
const registryStore = this.options.registryStore || new DefaultRegistryStore(this.options.customHome);
|
|
26
|
+
const scanLinked = this.options.scanLinkedPackages !== false;
|
|
27
|
+
const registerPackage = (pathOrRoot, flags) => {
|
|
28
|
+
const abs = resolve(pathOrRoot);
|
|
29
|
+
if (!existsSync(abs))
|
|
30
|
+
return;
|
|
31
|
+
const real = realpathSync(abs);
|
|
32
|
+
if (packages.has(real)) {
|
|
33
|
+
const existing = packages.get(real);
|
|
34
|
+
if (flags.isCurrentProject && !existing.isCurrentProject) {
|
|
35
|
+
packages.set(real, { ...existing, isCurrentProject: true });
|
|
36
|
+
}
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
let manifest;
|
|
40
|
+
try {
|
|
41
|
+
manifest = loadManifest(abs) || loadProjectConfig(abs);
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
if (flags.isCurrentProject) {
|
|
45
|
+
throw err;
|
|
46
|
+
}
|
|
47
|
+
console.warn(`[PackageDiscovery] Skipping invalid package at '${abs}': ${err?.message || String(err)}`);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
// 以 id 到物理路径的映射做常数查重,替代全表线性扫描;同物理路径重复注册静默去重
|
|
51
|
+
const idRealPaths = this.idRealPaths;
|
|
52
|
+
const existingReal = idRealPaths.get(manifest.id);
|
|
53
|
+
if (existingReal !== undefined && existingReal !== real) {
|
|
54
|
+
throw new Error(`PACKAGE_ID_CONFLICT: Package ID '${manifest.id}' is declared by multiple directories: '${existingReal}' and '${abs}'`);
|
|
55
|
+
}
|
|
56
|
+
idRealPaths.set(manifest.id, real);
|
|
57
|
+
packages.set(real, {
|
|
58
|
+
id: manifest.id,
|
|
59
|
+
root: abs,
|
|
60
|
+
manifest,
|
|
61
|
+
...flags,
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
// 1. 当前工程根路径
|
|
65
|
+
if (this.options.currentProjectRoot) {
|
|
66
|
+
registerPackage(this.options.currentProjectRoot, { isCurrentProject: true });
|
|
67
|
+
}
|
|
68
|
+
// 2. 显式包路径
|
|
69
|
+
if (this.options.packageRoots) {
|
|
70
|
+
for (const p of this.options.packageRoots) {
|
|
71
|
+
registerPackage(p, { isLinked: true });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// 3. 注册表登记位置
|
|
75
|
+
if (scanLinked) {
|
|
76
|
+
try {
|
|
77
|
+
const regData = registryStore.load();
|
|
78
|
+
if (regData.packages) {
|
|
79
|
+
for (const pkg of Object.values(regData.packages)) {
|
|
80
|
+
if (pkg.path) {
|
|
81
|
+
registerPackage(pkg.path, { isLinked: true });
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (regData.workspaces) {
|
|
86
|
+
for (const wsPath of Object.keys(regData.workspaces)) {
|
|
87
|
+
if (existsSync(wsPath)) {
|
|
88
|
+
const configs = discoverProjectConfigs(wsPath, this.options.workspaceScanDepth ?? 3);
|
|
89
|
+
for (const item of configs) {
|
|
90
|
+
registerPackage(item.root, { isWorkspaceChild: true });
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
console.warn(`[PackageDiscovery] Failed to load registry locations: ${err?.message || String(err)}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// 4. 显式附加工作区根目录
|
|
101
|
+
if (this.options.workspaceRoots) {
|
|
102
|
+
for (const wsPath of this.options.workspaceRoots) {
|
|
103
|
+
if (existsSync(wsPath)) {
|
|
104
|
+
const configs = discoverProjectConfigs(wsPath, this.options.workspaceScanDepth ?? 3);
|
|
105
|
+
for (const item of configs) {
|
|
106
|
+
registerPackage(item.root, { isWorkspaceChild: true });
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return Array.from(packages.values());
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* 异步发现所有可用包基本信息集合。
|
|
115
|
+
*/
|
|
116
|
+
async discover() {
|
|
117
|
+
return this.discoverSync();
|
|
118
|
+
}
|
|
119
|
+
}
|