@actiondock/core 2.9.1 → 2.11.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 +1 -2
- package/dist/catalog/action-catalog.js +3 -33
- package/dist/catalog/discovery.d.ts +0 -3
- package/dist/catalog/discovery.js +4 -4
- package/dist/catalog/graph.d.ts +0 -4
- package/dist/catalog/graph.js +12 -15
- package/dist/{profile/client-actions.d.ts → client/actions.d.ts} +1 -1
- package/dist/{profile/client-actions.js → client/actions.js} +2 -8
- package/dist/{profile/client-config.d.ts → client/config.d.ts} +1 -1
- package/dist/{profile/client-config.js → client/config.js} +1 -1
- package/dist/client/dispatcher.d.ts +4 -0
- package/dist/client/dispatcher.js +21 -0
- package/dist/client/health.d.ts +38 -0
- package/dist/{profile/client-health.js → client/health.js} +9 -6
- package/dist/client/index.d.ts +16 -0
- package/dist/client/index.js +20 -0
- package/dist/{profile/client-playbooks.d.ts → client/playbooks.d.ts} +1 -1
- package/dist/{profile/client-playbooks.js → client/playbooks.js} +1 -1
- package/dist/{profile/client-runs.d.ts → client/runs.d.ts} +4 -2
- package/dist/{profile/client-runs.js → client/runs.js} +7 -1
- package/dist/{profile/client-state.d.ts → client/state.d.ts} +1 -1
- package/dist/{profile/client-state.js → client/state.js} +1 -1
- package/dist/{profile/client-transport.d.ts → client/transport.d.ts} +29 -10
- package/dist/{profile/client-transport.js → client/transport.js} +125 -35
- package/dist/doctor/checks/index.d.ts +1 -1
- package/dist/doctor/checks/index.js +1 -1
- package/dist/doctor/checks/project.js +24 -92
- package/dist/doctor/checks/registry.js +1 -1
- package/dist/doctor/checks/runtime.d.ts +0 -4
- package/dist/doctor/checks/runtime.js +0 -28
- package/dist/doctor/doctor.js +1 -2
- package/dist/errors.d.ts +85 -4
- package/dist/errors.js +114 -4
- package/dist/execution/service.d.ts +55 -37
- package/dist/execution/service.js +601 -212
- package/dist/execution/types.d.ts +24 -5
- package/dist/host/host.d.ts +42 -22
- package/dist/host/host.js +565 -150
- package/dist/host/routing.js +6 -6
- package/dist/host/types.d.ts +25 -13
- package/dist/index.d.ts +9 -4
- package/dist/index.js +5 -2
- package/dist/input/advice.d.ts +0 -44
- package/dist/input/advice.js +7 -141
- package/dist/input/describe.d.ts +6 -0
- package/dist/input/describe.js +26 -1
- package/dist/input/flat-materializer.js +1 -1
- package/dist/input/flat-parser.js +1 -1
- package/dist/input/index.d.ts +0 -1
- package/dist/input/index.js +0 -1
- package/dist/input/input-resolver.js +2 -2
- package/dist/input/validation-mapper.d.ts +1 -1
- package/dist/invocation/policy.js +2 -0
- package/dist/ipc/diagnostic.d.ts +8 -21
- package/dist/ipc/diagnostic.js +24 -57
- package/dist/ipc/host.js +21 -7
- package/dist/ipc/service.d.ts +14 -0
- package/dist/ipc/service.js +132 -26
- package/dist/ipc/types.d.ts +0 -4
- package/dist/package/index.d.ts +4 -5
- package/dist/package/index.js +1 -2
- package/dist/package/runtime.d.ts +94 -23
- package/dist/package/runtime.js +628 -274
- package/dist/package/static-index.d.ts +3 -6
- package/dist/package/static-index.js +11 -40
- package/dist/package/types.d.ts +19 -4
- package/dist/platform/index.d.ts +2 -1
- package/dist/platform/index.js +2 -1
- package/dist/platform/loader-hook.d.ts +32 -0
- package/dist/platform/loader-hook.js +90 -0
- package/dist/{node → platform}/module-loader.d.ts +13 -0
- package/dist/{node → platform}/module-loader.js +51 -4
- package/dist/platform/node.d.ts +19 -8
- package/dist/platform/node.js +50 -20
- package/dist/platform/types.d.ts +7 -47
- package/dist/process/context-process.d.ts +3 -18
- package/dist/process/context-process.js +3 -44
- package/dist/process/control.d.ts +21 -0
- package/dist/process/control.js +34 -0
- package/dist/process/converters.d.ts +23 -0
- package/dist/process/converters.js +92 -0
- package/dist/process/cursor.js +2 -22
- package/dist/process/{diagnostics-sink.d.ts → diagnostics.d.ts} +0 -7
- package/dist/process/{diagnostics-sink.js → diagnostics.js} +6 -8
- package/dist/process/index.d.ts +1 -3
- package/dist/process/index.js +1 -3
- package/dist/process/input-dispatcher.d.ts +4 -13
- package/dist/process/input-dispatcher.js +48 -69
- package/dist/process/managed-record.d.ts +3 -31
- package/dist/process/metadata-store.d.ts +0 -41
- package/dist/process/metadata-store.js +2 -341
- package/dist/process/process-driver.js +2 -2
- package/dist/process/process-manager.d.ts +8 -50
- package/dist/process/process-manager.js +28 -417
- package/dist/process/quotas.d.ts +14 -0
- package/dist/process/quotas.js +29 -0
- package/dist/process/run-executor.js +0 -1
- package/dist/process/terminal-output-cache.d.ts +20 -34
- package/dist/process/terminal-output-cache.js +43 -64
- package/dist/profile/index.d.ts +1 -2
- package/dist/profile/index.js +1 -2
- package/dist/profile/manager.d.ts +2 -4
- package/dist/profile/manager.js +10 -40
- package/dist/profile/types.d.ts +1 -17
- package/dist/project/digest.d.ts +5 -1
- package/dist/project/digest.js +81 -219
- package/dist/project/index.d.ts +4 -5
- package/dist/project/index.js +4 -5
- package/dist/project/init.js +2 -2
- package/dist/project/loader.d.ts +3 -3
- package/dist/project/loader.js +72 -50
- package/dist/project/lockfile.js +6 -5
- package/dist/project/manifest.js +5 -4
- package/dist/project/transactions.d.ts +4 -42
- package/dist/project/transactions.js +83 -138
- package/dist/project/types-generator.js +2 -1
- package/dist/project/types.d.ts +2 -0
- package/dist/registry/index.d.ts +0 -1
- package/dist/registry/index.js +0 -1
- package/dist/registry/lock.d.ts +2 -11
- package/dist/registry/lock.js +14 -183
- package/dist/registry/registry.d.ts +1 -6
- package/dist/registry/registry.js +5 -17
- package/dist/runtime/action-registry.d.ts +1 -5
- package/dist/runtime/action-registry.js +0 -12
- package/dist/runtime/context.js +2 -2
- package/dist/runtime/events.d.ts +11 -50
- package/dist/runtime/events.js +88 -368
- package/dist/runtime/index.d.ts +0 -4
- package/dist/runtime/index.js +0 -4
- package/dist/runtime/run-persistence.d.ts +2 -0
- package/dist/runtime/run-persistence.js +2 -1
- package/dist/runtime/standalone-commands.d.ts +18 -0
- package/dist/runtime/standalone-commands.js +466 -0
- package/dist/runtime/standalone-help.d.ts +20 -0
- package/dist/runtime/standalone-help.js +72 -0
- package/dist/runtime/standalone.d.ts +1 -44
- package/dist/runtime/standalone.js +31 -526
- package/dist/schema/validator.d.ts +2 -2
- package/dist/schema/validator.js +2 -9
- package/dist/server/index.d.ts +0 -2
- package/dist/server/index.js +0 -2
- package/dist/server/routes/actions.js +1 -1
- package/dist/server/routes/info.js +1 -1
- package/dist/server/routes/playbooks.js +1 -1
- package/dist/server/routes/runs.js +123 -16
- package/dist/server/routes/state.js +43 -18
- package/dist/server/security.d.ts +1 -1
- package/dist/server/security.js +2 -2
- package/dist/server/server.js +3 -7
- package/dist/service/factory.js +4 -3
- package/dist/service/index.d.ts +1 -1
- package/dist/service/index.js +1 -1
- package/dist/service/remote-errors.d.ts +1 -1
- package/dist/service/remote-errors.js +6 -6
- package/dist/service/remote-polling.d.ts +3 -0
- package/dist/service/remote-polling.js +10 -5
- package/dist/service/remote.d.ts +5 -1
- package/dist/service/remote.js +108 -17
- package/dist/service/sse-stream.js +2 -2
- package/dist/service/types.d.ts +22 -19
- package/dist/service/types.js +1 -24
- package/dist/storage/clock.d.ts +1 -1
- package/dist/storage/clock.js +1 -1
- package/dist/storage/data-dir-lock.d.ts +10 -22
- package/dist/storage/data-dir-lock.js +28 -56
- package/dist/storage/file-lock.d.ts +64 -0
- package/dist/storage/file-lock.js +447 -0
- package/dist/storage/index.d.ts +2 -2
- package/dist/storage/index.js +5 -4
- package/dist/storage/run-liveness.d.ts +48 -0
- package/dist/storage/run-liveness.js +44 -0
- package/dist/storage/sqlite-config.d.ts +16 -0
- package/dist/storage/sqlite-config.js +59 -0
- package/dist/storage/sqlite-driver.d.ts +3 -1
- package/dist/storage/sqlite-driver.js +14 -4
- package/dist/storage/sqlite-events.d.ts +13 -0
- package/dist/storage/sqlite-events.js +48 -0
- package/dist/storage/sqlite-runs.d.ts +107 -0
- package/dist/storage/sqlite-runs.js +622 -0
- package/dist/storage/sqlite-schema.d.ts +5 -0
- package/dist/storage/sqlite-schema.js +143 -0
- package/dist/storage/sqlite-state.d.ts +33 -0
- package/dist/storage/sqlite-state.js +270 -0
- package/dist/storage/sqlite.d.ts +30 -57
- package/dist/storage/sqlite.js +84 -741
- package/dist/storage/types.d.ts +35 -2
- package/dist/utils/index.d.ts +18 -14
- package/dist/utils/index.js +37 -29
- package/dist/utils/semver.d.ts +18 -0
- package/dist/utils/semver.js +19 -0
- package/dist/utils/warning.d.ts +1 -0
- package/dist/utils/warning.js +52 -0
- package/dist/{json/value-validator.d.ts → value-validator.d.ts} +9 -0
- package/dist/value-validator.js +330 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +10 -12
- package/dist/execution/index.d.ts +0 -2
- package/dist/execution/index.js +0 -2
- package/dist/filter/index.d.ts +0 -1
- package/dist/filter/index.js +0 -1
- package/dist/graph/index.d.ts +0 -4
- package/dist/graph/index.js +0 -4
- package/dist/input/metadata.d.ts +0 -99
- package/dist/input/metadata.js +0 -99
- package/dist/invocation/index.d.ts +0 -2
- package/dist/invocation/index.js +0 -2
- package/dist/ipc/index.d.ts +0 -4
- package/dist/ipc/index.js +0 -4
- package/dist/json/index.d.ts +0 -1
- package/dist/json/index.js +0 -1
- package/dist/json/value-validator.js +0 -330
- package/dist/node/index.d.ts +0 -1
- package/dist/node/index.js +0 -1
- package/dist/platform/node-fs.d.ts +0 -37
- package/dist/platform/node-fs.js +0 -81
- package/dist/process/control-arbiter.d.ts +0 -108
- package/dist/process/control-arbiter.js +0 -250
- package/dist/process/process-executor.d.ts +0 -47
- package/dist/process/process-executor.js +0 -296
- package/dist/profile/client-health.d.ts +0 -14
- package/dist/profile/client-query.d.ts +0 -30
- package/dist/profile/client-query.js +0 -69
- package/dist/profile/client.d.ts +0 -26
- package/dist/profile/client.js +0 -31
- package/dist/project/closure.d.ts +0 -25
- package/dist/project/closure.js +0 -74
- package/dist/registry/store.d.ts +0 -42
- package/dist/registry/store.js +0 -43
- package/dist/runtime/clock.d.ts +0 -7
- package/dist/runtime/clock.js +0 -7
- package/dist/runtime/module-loader.d.ts +0 -2
- package/dist/runtime/module-loader.js +0 -1
- package/dist/runtime/process.d.ts +0 -8
- package/dist/runtime/process.js +0 -1
- package/dist/runtime/runner.d.ts +0 -234
- package/dist/runtime/runner.js +0 -609
- package/dist/schema/index.d.ts +0 -1
- package/dist/schema/index.js +0 -1
- package/dist/server/dispatcher.d.ts +0 -25
- package/dist/server/dispatcher.js +0 -54
- package/dist/service/local.d.ts +0 -27
- package/dist/service/local.js +0 -141
- package/dist/storage/driver.d.ts +0 -10
- package/dist/storage/driver.js +0 -10
- package/dist/storage/lazy.d.ts +0 -8
- package/dist/storage/lazy.js +0 -45
- package/dist/storage/lock-core.d.ts +0 -158
- package/dist/storage/lock-core.js +0 -872
- package/dist/utils/net.d.ts +0 -10
- package/dist/utils/net.js +0 -16
- package/dist/utils/process.d.ts +0 -10
- package/dist/utils/process.js +0 -21
- /package/dist/{filter → utils}/intent.d.ts +0 -0
- /package/dist/{filter → utils}/intent.js +0 -0
package/README.md
CHANGED
|
@@ -56,7 +56,7 @@ Service -> Resolution -> PackageRuntime -> ExecutionService -> ActionRunner -> A
|
|
|
56
56
|
|
|
57
57
|
- 发现端口 `DiscoveryPort`:负责包与动作的元数据发现、清单检索、全文过滤与规程查询。
|
|
58
58
|
- 执行端口 `ExecutionPort`:负责动作的同步阻塞执行(`run`)与异步启动执行(`start`)。
|
|
59
|
-
- 运行端口 `RunsPort
|
|
59
|
+
- 运行端口 `RunsPort`:负责任务运行历史列表(含幂等请求标识反查)、单次详情查询、读取链路取消信号(`signal`)、协同取消(`cancel`)以及历史记录清理与保留策略淘汰(`clearRuns`、`cleanExpiredRuns`)。
|
|
60
60
|
- 事件端口 `EventsPort`:负责任务执行实时事件流订阅。
|
|
61
61
|
- 配置端口 `ConfigPort`:负责运行时分层配置读取、持久化配置管理与环境变量满足度体检。
|
|
62
62
|
- 状态端口 `StatePort`:负责包级与动作级持久化键值存取、前缀列举与过期清理。
|
|
@@ -83,7 +83,6 @@ ActionDock 2.x 全面贯彻单一事实源设计,彻底杜绝各模块私自
|
|
|
83
83
|
- 受管进程平台驱动 `NodeProcessDriver`:实现完整的受管进程治理体系。基于管道彻底切断子进程与宿主标准流的物理连通;支持跨平台独立进程组管理与信号派发;提供独占控制权租约、逐流增量读取与优雅终止。
|
|
84
84
|
- 原生网络服务容器 `NodeHttpServer`:基于 Node.js 原生 `node:http` 承载 RESTful 微服务与 Server-Sent Events 事件流。
|
|
85
85
|
- 原生模块加载器 `NodeModuleLoader`:基于 Node.js 原生类型擦除机制直接加载 TypeScript 源码,免除前置编译转译开销。
|
|
86
|
-
- 原生文件系统抽象 `NodeFileSystem`:提供跨平台文件读写与原子文件事务保障。
|
|
87
86
|
|
|
88
87
|
---
|
|
89
88
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { parseActionRef } from "./resolve-action.js";
|
|
4
4
|
/**
|
|
@@ -75,7 +75,7 @@ export class DefaultActionCatalog {
|
|
|
75
75
|
for (const node of graph.packages.values()) {
|
|
76
76
|
const packageId = node.identity.id;
|
|
77
77
|
const manifest = node.manifest;
|
|
78
|
-
//
|
|
78
|
+
// - 清单显式 actions 声明优先索引
|
|
79
79
|
if (manifest?.actions && typeof manifest.actions === "object") {
|
|
80
80
|
for (const [actionId, item] of Object.entries(manifest.actions)) {
|
|
81
81
|
const entry = item?.entry || inferActionEntry(node.root, manifest, actionId);
|
|
@@ -98,7 +98,7 @@ export class DefaultActionCatalog {
|
|
|
98
98
|
this.addCandidate(candidate);
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
|
-
//
|
|
101
|
+
// - 内存动态注入动作索引(测试或 Host 注册场景)
|
|
102
102
|
if (actionsProvider) {
|
|
103
103
|
const dynActions = actionsProvider(packageId);
|
|
104
104
|
if (dynActions && typeof dynActions.entries === "function") {
|
|
@@ -119,36 +119,6 @@ export class DefaultActionCatalog {
|
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
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
122
|
}
|
|
153
123
|
}
|
|
154
124
|
find(ref) {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { ActionDockManifest } from "../project/types.js";
|
|
2
|
-
import { type RegistryStore } from "../registry/store.js";
|
|
3
2
|
import type { PackageIdentity } from "../runtime/identity.js";
|
|
4
3
|
/**
|
|
5
4
|
* 发现的包基本信息规范。
|
|
@@ -28,8 +27,6 @@ export interface PackageDiscoveryOptions {
|
|
|
28
27
|
currentProjectRoot?: string;
|
|
29
28
|
/** 自定义 ActionDock 主目录路径(用于定位注册表) */
|
|
30
29
|
customHome?: string;
|
|
31
|
-
/** 显式注入的注册表存储实例(可选,默认使用 DefaultRegistryStore) */
|
|
32
|
-
registryStore?: RegistryStore;
|
|
33
30
|
/** 附加显式包根目录集合 */
|
|
34
31
|
packageRoots?: string[];
|
|
35
32
|
/** 附加显式工作区根目录集合 */
|
|
@@ -2,8 +2,9 @@ import { existsSync, realpathSync } from "node:fs";
|
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
import { loadProjectConfig } from "../project/loader.js";
|
|
4
4
|
import { loadManifest } from "../project/manifest.js";
|
|
5
|
-
import {
|
|
5
|
+
import { loadRegistry } from "../registry/registry.js";
|
|
6
6
|
import { discoverProjectConfigs } from "../registry/scan.js";
|
|
7
|
+
import { ActionDockError, PACKAGE_ID_CONFLICT } from "../errors.js";
|
|
7
8
|
/**
|
|
8
9
|
* 包发现单一事实源 PackageDiscovery。
|
|
9
10
|
* 负责聚合当前工程、用户显式注册包位置与工作区根目录,输出已发现包集合。
|
|
@@ -22,7 +23,6 @@ export class PackageDiscovery {
|
|
|
22
23
|
discoverSync() {
|
|
23
24
|
const packages = new Map();
|
|
24
25
|
this.idRealPaths.clear();
|
|
25
|
-
const registryStore = this.options.registryStore || new DefaultRegistryStore(this.options.customHome);
|
|
26
26
|
const scanLinked = this.options.scanLinkedPackages !== false;
|
|
27
27
|
const registerPackage = (pathOrRoot, flags) => {
|
|
28
28
|
const abs = resolve(pathOrRoot);
|
|
@@ -51,7 +51,7 @@ export class PackageDiscovery {
|
|
|
51
51
|
const idRealPaths = this.idRealPaths;
|
|
52
52
|
const existingReal = idRealPaths.get(manifest.id);
|
|
53
53
|
if (existingReal !== undefined && existingReal !== real) {
|
|
54
|
-
throw new
|
|
54
|
+
throw new ActionDockError(PACKAGE_ID_CONFLICT, `PACKAGE_ID_CONFLICT: Package ID '${manifest.id}' is declared by multiple directories: '${existingReal}' and '${abs}'`);
|
|
55
55
|
}
|
|
56
56
|
idRealPaths.set(manifest.id, real);
|
|
57
57
|
packages.set(real, {
|
|
@@ -74,7 +74,7 @@ export class PackageDiscovery {
|
|
|
74
74
|
// 3. 注册表登记位置
|
|
75
75
|
if (scanLinked) {
|
|
76
76
|
try {
|
|
77
|
-
const regData =
|
|
77
|
+
const regData = loadRegistry(this.options.customHome);
|
|
78
78
|
if (regData.packages) {
|
|
79
79
|
for (const pkg of Object.values(regData.packages)) {
|
|
80
80
|
if (pkg.path) {
|
package/dist/catalog/graph.d.ts
CHANGED
package/dist/catalog/graph.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
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";
|
|
3
|
+
import { ActionDockError, ACTION_PACKAGE_VERSION_CONFLICT, MANIFEST_DIGEST_MISMATCH, MANIFEST_NOT_FOUND, MANIFEST_READ_FAILED, PACKAGE_NOT_FOUND, UNDECLARED_ACTION_DEPENDENCY, } from "../errors.js";
|
|
4
4
|
import { computeManifestDigest, parseJsonWithoutDuplicates } from "../project/digest.js";
|
|
5
5
|
import { loadLockfile } from "../project/lockfile.js";
|
|
6
6
|
import { loadPlaybooks, loadProjectConfig } from "../project/loader.js";
|
|
@@ -42,8 +42,8 @@ export class ActionPackageVersionConflictError extends ActionDockError {
|
|
|
42
42
|
packageId;
|
|
43
43
|
conflicts;
|
|
44
44
|
constructor(packageId, conflicts) {
|
|
45
|
-
const details = conflicts.map((c) => `'${c.requester}'
|
|
46
|
-
super(ACTION_PACKAGE_VERSION_CONFLICT, `ACTION_PACKAGE_VERSION_CONFLICT:
|
|
45
|
+
const details = conflicts.map((c) => `'${c.requester}' requires '${c.rangeOrVersion}'`).join(", ");
|
|
46
|
+
super(ACTION_PACKAGE_VERSION_CONFLICT, `ACTION_PACKAGE_VERSION_CONFLICT: Package '${packageId}' has irreconcilable version conflicts: ${details}`);
|
|
47
47
|
this.name = "ActionPackageVersionConflictError";
|
|
48
48
|
this.packageId = packageId;
|
|
49
49
|
this.conflicts = conflicts;
|
|
@@ -57,10 +57,13 @@ export class UndeclaredActionDependencyError extends ActionDockError {
|
|
|
57
57
|
targetRef;
|
|
58
58
|
caller;
|
|
59
59
|
constructor(targetRef, caller, reason) {
|
|
60
|
+
const hint = caller
|
|
61
|
+
? `Hint: Add '${targetRef}' to the 'uses' array of action '${caller}' in actiondock.json, then run 'ad validate'.`
|
|
62
|
+
: undefined;
|
|
60
63
|
const msg = caller
|
|
61
|
-
? `UNDECLARED_ACTION_DEPENDENCY: Action '${caller}'
|
|
62
|
-
: `UNDECLARED_ACTION_DEPENDENCY:
|
|
63
|
-
super(UNDECLARED_ACTION_DEPENDENCY, msg);
|
|
64
|
+
? `UNDECLARED_ACTION_DEPENDENCY: Action '${caller}' has not declared cross-package dependency on '${targetRef}' in 'uses'${hint ? `\n${hint}` : ""}`
|
|
65
|
+
: `UNDECLARED_ACTION_DEPENDENCY: Root invocation of action '${targetRef}' was rejected: target package is neither a direct dependency in actiondock.json nor delegated by a visible Playbook${reason ? ` (${reason})` : ""}`;
|
|
66
|
+
super(UNDECLARED_ACTION_DEPENDENCY, msg, hint ? { hint } : undefined, undefined, hint);
|
|
64
67
|
this.name = "UndeclaredActionDependencyError";
|
|
65
68
|
this.targetRef = targetRef;
|
|
66
69
|
this.caller = caller;
|
|
@@ -493,19 +496,19 @@ export class PackageGraphBuilder {
|
|
|
493
496
|
}
|
|
494
497
|
const manifestPath = join(pkgDir, MANIFEST_FILE_NAME);
|
|
495
498
|
if (!existsSync(manifestPath)) {
|
|
496
|
-
throw new
|
|
499
|
+
throw new ActionDockError(MANIFEST_NOT_FOUND, `Action package '${item.pkgId}' at '${pkgDir}' misses required manifest 'actiondock.json'`);
|
|
497
500
|
}
|
|
498
501
|
let manifestRaw;
|
|
499
502
|
try {
|
|
500
503
|
manifestRaw = readFileSync(manifestPath, "utf-8");
|
|
501
504
|
}
|
|
502
505
|
catch (err) {
|
|
503
|
-
throw new
|
|
506
|
+
throw new ActionDockError(MANIFEST_READ_FAILED, `Failed to read manifest for '${item.pkgId}': ${err.message}`);
|
|
504
507
|
}
|
|
505
508
|
const depManifest = parseJsonWithoutDuplicates(manifestRaw);
|
|
506
509
|
const actualDigest = computeManifestDigest(depManifest);
|
|
507
510
|
if (locked?.manifestDigest && locked.manifestDigest !== actualDigest) {
|
|
508
|
-
throw new
|
|
511
|
+
throw new ActionDockError(MANIFEST_DIGEST_MISMATCH, `Manifest digest mismatch for package '${item.pkgId}': expected '${locked.manifestDigest}', got '${actualDigest}'. Re-resolution required.`);
|
|
509
512
|
}
|
|
510
513
|
const pkgVersion = depManifest.version || locked?.version || "0.1.0";
|
|
511
514
|
const reqs = versionRequirements.get(item.pkgId) || [];
|
|
@@ -580,10 +583,4 @@ export class PackageGraphBuilder {
|
|
|
580
583
|
// 模式 C:全局包发现构建
|
|
581
584
|
return this.buildFromGlobalDiscovery(nodes, generation);
|
|
582
585
|
}
|
|
583
|
-
/**
|
|
584
|
-
* 异步构建包依赖拓扑图。
|
|
585
|
-
*/
|
|
586
|
-
async build() {
|
|
587
|
-
return this.buildSync();
|
|
588
|
-
}
|
|
589
586
|
}
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { ACTION_CANCELLED, ACTION_TIMEOUT, NETWORK_ERROR } from "../errors.js";
|
|
3
|
-
import { getInsecureDispatcher } from "
|
|
4
|
-
import { normalizeServerUrl } from "./
|
|
5
|
-
import { assertSecureTransport, buildHeaders, fetchRemoteRoute, } from "./client-transport.js";
|
|
6
|
-
import { buildQueryString, fetchRemoteJson } from "./client-query.js";
|
|
3
|
+
import { getInsecureDispatcher } from "./dispatcher.js";
|
|
4
|
+
import { assertSecureTransport, buildHeaders, buildQueryString, fetchRemoteJson, fetchRemoteRoute, normalizeServerUrl, } from "./transport.js";
|
|
7
5
|
/**
|
|
8
6
|
* 执行远端 Action:支持幂等标识、异步触发、外部取消信号与本地超时守卫组合。
|
|
9
7
|
*/
|
|
10
8
|
export async function executeRemoteAction(serverUrl, actionId, input = {}, configOverridesOrOptions, tokenArg) {
|
|
11
|
-
// Parse options / backwards compatibility
|
|
12
9
|
let configOverrides;
|
|
13
10
|
let token = tokenArg;
|
|
14
11
|
let timeoutMs;
|
|
@@ -54,7 +51,6 @@ export async function executeRemoteAction(serverUrl, actionId, input = {}, confi
|
|
|
54
51
|
if (requestId) {
|
|
55
52
|
executionPayload.requestId = requestId;
|
|
56
53
|
}
|
|
57
|
-
// 组合外部取消信号与本地超时守卫:服务端僵死时仍能在 timeoutMs 内本地中断,避免永久挂起
|
|
58
54
|
let timeoutTimer;
|
|
59
55
|
let localTimedOut = false;
|
|
60
56
|
try {
|
|
@@ -116,7 +112,6 @@ export async function executeRemoteAction(serverUrl, actionId, input = {}, confi
|
|
|
116
112
|
return data;
|
|
117
113
|
}
|
|
118
114
|
if (!res.ok) {
|
|
119
|
-
// 错误信封严禁伪造 runId:与任何真实运行无关的标识会让调用方查询永远 not_found
|
|
120
115
|
return {
|
|
121
116
|
ok: false,
|
|
122
117
|
runId: "",
|
|
@@ -134,7 +129,6 @@ export async function executeRemoteAction(serverUrl, actionId, input = {}, confi
|
|
|
134
129
|
};
|
|
135
130
|
}
|
|
136
131
|
catch (err) {
|
|
137
|
-
// 本地超时守卫触发时归类为超时;外部信号中止时归类为取消
|
|
138
132
|
if (localTimedOut) {
|
|
139
133
|
return {
|
|
140
134
|
ok: false,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Agent } from "undici";
|
|
2
|
+
/**
|
|
3
|
+
* 全局单例 Undici Agent(忽略服务端证书校验)。
|
|
4
|
+
* 显式配置 bodyTimeout: 0 以防止 SSE 长连接与流式事件读取出现 UND_ERR_BODY_TIMEOUT 空闲超时断流。
|
|
5
|
+
* Agent 关闭或销毁后自动重建,保证长生命周期进程内的调度器始终可用。
|
|
6
|
+
*/
|
|
7
|
+
let globalInsecureAgent;
|
|
8
|
+
/**
|
|
9
|
+
* 获取用于忽略服务端证书校验的全局单例 Undici Agent 调度器。
|
|
10
|
+
*/
|
|
11
|
+
export function getInsecureDispatcher() {
|
|
12
|
+
if (!globalInsecureAgent || globalInsecureAgent.closed || globalInsecureAgent.destroyed) {
|
|
13
|
+
globalInsecureAgent = new Agent({
|
|
14
|
+
connect: {
|
|
15
|
+
rejectUnauthorized: false,
|
|
16
|
+
},
|
|
17
|
+
bodyTimeout: 0,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
return globalInsecureAgent;
|
|
21
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type RemoteClientRequestOptions } from "./transport.js";
|
|
2
|
+
import { type Clock } from "../storage/clock.js";
|
|
3
|
+
/**
|
|
4
|
+
* 远端服务器健康探测与时延检测结果。
|
|
5
|
+
*/
|
|
6
|
+
export interface RemoteHealthResult {
|
|
7
|
+
/** 服务端是否连通且鉴权成功 */
|
|
8
|
+
ok: boolean;
|
|
9
|
+
/** 服务端状态标识(如 "ok") */
|
|
10
|
+
status?: string;
|
|
11
|
+
/** 远端 ActionDock 版本号 */
|
|
12
|
+
version?: string;
|
|
13
|
+
/** 远端服务运行时间(秒) */
|
|
14
|
+
uptime?: number;
|
|
15
|
+
/** 网络往返延迟(毫秒) */
|
|
16
|
+
latencyMs: number;
|
|
17
|
+
/** 探测失败时的错误信息 */
|
|
18
|
+
error?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* 远端健康探测控制选项。
|
|
22
|
+
*/
|
|
23
|
+
export interface CheckRemoteHealthOptions extends RemoteClientRequestOptions {
|
|
24
|
+
/** 可选注入时钟抽象(缺省使用系统时钟) */
|
|
25
|
+
clock?: Clock;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 远端健康检查域端点。
|
|
29
|
+
*/
|
|
30
|
+
/**
|
|
31
|
+
* 探测指定远端 ActionDock 服务的健康状态与网络延迟。
|
|
32
|
+
*
|
|
33
|
+
* @param serverUrl 目标服务端地址
|
|
34
|
+
* @param token 鉴权 Token(可选)
|
|
35
|
+
* @param timeoutMs 探测超时时间(默认 5000ms)
|
|
36
|
+
* @param options 传输与安全控制选项
|
|
37
|
+
*/
|
|
38
|
+
export declare function checkRemoteHealth(serverUrl: string, token?: string, timeoutMs?: number, options?: CheckRemoteHealthOptions): Promise<RemoteHealthResult>;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { assertSecureTransport, buildHeaders, fetchRemoteRoute, } from "./
|
|
3
|
-
import {
|
|
1
|
+
import { getInsecureDispatcher } from "./dispatcher.js";
|
|
2
|
+
import { assertSecureTransport, buildHeaders, fetchRemoteRoute, normalizeServerUrl, } from "./transport.js";
|
|
3
|
+
import { SystemClock } from "../storage/clock.js";
|
|
4
|
+
/** 模块级默认时钟实例 */
|
|
5
|
+
const defaultClock = new SystemClock();
|
|
4
6
|
/**
|
|
5
7
|
* 远端健康检查域端点。
|
|
6
8
|
*/
|
|
@@ -13,7 +15,8 @@ import { getInsecureDispatcher } from "../server/dispatcher.js";
|
|
|
13
15
|
* @param options 传输与安全控制选项
|
|
14
16
|
*/
|
|
15
17
|
export async function checkRemoteHealth(serverUrl, token, timeoutMs = 5000, options) {
|
|
16
|
-
const
|
|
18
|
+
const clock = options?.clock ?? defaultClock;
|
|
19
|
+
const startTime = clock.monotonic();
|
|
17
20
|
let timer;
|
|
18
21
|
try {
|
|
19
22
|
assertSecureTransport(serverUrl, token, {
|
|
@@ -35,7 +38,7 @@ export async function checkRemoteHealth(serverUrl, token, timeoutMs = 5000, opti
|
|
|
35
38
|
fetchInit.tls = { rejectUnauthorized: false };
|
|
36
39
|
}
|
|
37
40
|
const res = await fetchRemoteRoute(normalizeServerUrl(serverUrl), "/api/v2/health", fetchInit);
|
|
38
|
-
const latencyMs =
|
|
41
|
+
const latencyMs = Math.round(clock.monotonic() - startTime);
|
|
39
42
|
if (!res.ok) {
|
|
40
43
|
const text = await res.text().catch(() => "");
|
|
41
44
|
return {
|
|
@@ -54,7 +57,7 @@ export async function checkRemoteHealth(serverUrl, token, timeoutMs = 5000, opti
|
|
|
54
57
|
};
|
|
55
58
|
}
|
|
56
59
|
catch (err) {
|
|
57
|
-
const latencyMs =
|
|
60
|
+
const latencyMs = Math.round(clock.monotonic() - startTime);
|
|
58
61
|
return {
|
|
59
62
|
ok: false,
|
|
60
63
|
latencyMs,
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ActionDock 核心远程 HTTP 客户端模块。
|
|
3
|
+
*
|
|
4
|
+
* 遵循架构收敛设计规范:按资源域组织,传输层单点。
|
|
5
|
+
* 彻底从 profile 目录解耦移入独立 client 模块。
|
|
6
|
+
*/
|
|
7
|
+
export { assertSecureTransport, buildHeaders, buildQueryString, buildQueryStringPreservingEmpty, createRemoteFetch, fetchRemoteJson, fetchRemoteRoute, normalizeServerUrl, } from "./transport.js";
|
|
8
|
+
export type { RemoteClientRequestOptions, RemoteFetchInit, SecureTransportOptions, } from "./transport.js";
|
|
9
|
+
export { checkRemoteHealth } from "./health.js";
|
|
10
|
+
export type { RemoteHealthResult } from "./health.js";
|
|
11
|
+
export { executeRemoteAction, fetchRemoteActionShow, fetchRemoteActions, fetchRemoteDoctor, fetchRemoteInfo, } from "./actions.js";
|
|
12
|
+
export type { RemoteExecuteOptions, RemoteExecutionResult } from "./actions.js";
|
|
13
|
+
export { fetchRemotePlaybookShow, fetchRemotePlaybooks } from "./playbooks.js";
|
|
14
|
+
export { cancelRemoteRun, cleanExpiredRemoteRuns, clearRemoteRuns, fetchRemoteRun, fetchRemoteRuns, } from "./runs.js";
|
|
15
|
+
export { clearRemoteState, deleteRemoteStateKey, fetchRemoteStateList, getRemoteStateKey, setRemoteStateKey, } from "./state.js";
|
|
16
|
+
export { deleteRemoteConfig, fetchRemoteConfig, fetchRemoteConfigEnv, setRemoteConfig, } from "./config.js";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ActionDock 核心远程 HTTP 客户端模块。
|
|
3
|
+
*
|
|
4
|
+
* 遵循架构收敛设计规范:按资源域组织,传输层单点。
|
|
5
|
+
* 彻底从 profile 目录解耦移入独立 client 模块。
|
|
6
|
+
*/
|
|
7
|
+
// 1. 传输层单点
|
|
8
|
+
export { assertSecureTransport, buildHeaders, buildQueryString, buildQueryStringPreservingEmpty, createRemoteFetch, fetchRemoteJson, fetchRemoteRoute, normalizeServerUrl, } from "./transport.js";
|
|
9
|
+
// 2. 健康检查域
|
|
10
|
+
export { checkRemoteHealth } from "./health.js";
|
|
11
|
+
// 3. Action 执行与查询域
|
|
12
|
+
export { executeRemoteAction, fetchRemoteActionShow, fetchRemoteActions, fetchRemoteDoctor, fetchRemoteInfo, } from "./actions.js";
|
|
13
|
+
// 4. Playbook 规程查询域
|
|
14
|
+
export { fetchRemotePlaybookShow, fetchRemotePlaybooks } from "./playbooks.js";
|
|
15
|
+
// 5. 运行记录管理域
|
|
16
|
+
export { cancelRemoteRun, cleanExpiredRemoteRuns, clearRemoteRuns, fetchRemoteRun, fetchRemoteRuns, } from "./runs.js";
|
|
17
|
+
// 6. 状态存储管理域
|
|
18
|
+
export { clearRemoteState, deleteRemoteStateKey, fetchRemoteStateList, getRemoteStateKey, setRemoteStateKey, } from "./state.js";
|
|
19
|
+
// 7. 配置管理域
|
|
20
|
+
export { deleteRemoteConfig, fetchRemoteConfig, fetchRemoteConfigEnv, setRemoteConfig, } from "./config.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { RunRecord } from "@actiondock/sdk";
|
|
2
|
-
import type { RemoteClientRequestOptions } from "./
|
|
2
|
+
import type { RemoteClientRequestOptions } from "./transport.js";
|
|
3
3
|
/**
|
|
4
4
|
* 远端运行记录域端点。
|
|
5
5
|
*/
|
|
@@ -24,9 +24,11 @@ export declare function fetchRemoteRuns(serverUrl: string, token?: string, optio
|
|
|
24
24
|
packageId?: string;
|
|
25
25
|
intent?: string;
|
|
26
26
|
limit?: number;
|
|
27
|
+
offset?: number;
|
|
28
|
+
requestIds?: string[];
|
|
27
29
|
} & RemoteClientRequestOptions): Promise<{
|
|
28
30
|
ok: boolean;
|
|
29
|
-
total
|
|
31
|
+
total?: number;
|
|
30
32
|
items: RunRecord[];
|
|
31
33
|
}>;
|
|
32
34
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { buildQueryString, fetchRemoteJson } from "./
|
|
1
|
+
import { buildQueryString, fetchRemoteJson } from "./transport.js";
|
|
2
2
|
/**
|
|
3
3
|
* 远端运行记录域端点。
|
|
4
4
|
*/
|
|
@@ -11,6 +11,7 @@ export async function fetchRemoteRun(serverUrl, runId, token, options) {
|
|
|
11
11
|
allowInsecureHttp: options?.allowInsecureHttp,
|
|
12
12
|
insecure: options?.insecure,
|
|
13
13
|
dispatcher: options?.dispatcher,
|
|
14
|
+
signal: options?.signal,
|
|
14
15
|
});
|
|
15
16
|
}
|
|
16
17
|
/**
|
|
@@ -36,11 +37,16 @@ export async function fetchRemoteRuns(serverUrl, token, options) {
|
|
|
36
37
|
packageId: options?.packageId,
|
|
37
38
|
intent: options?.intent,
|
|
38
39
|
limit: options?.limit,
|
|
40
|
+
offset: options?.offset,
|
|
41
|
+
requestIds: options?.requestIds && options.requestIds.length > 0
|
|
42
|
+
? options.requestIds
|
|
43
|
+
: undefined,
|
|
39
44
|
})}`, token, {
|
|
40
45
|
errorPrefix: "Failed to fetch remote runs",
|
|
41
46
|
allowInsecureHttp: options?.allowInsecureHttp,
|
|
42
47
|
insecure: options?.insecure,
|
|
43
48
|
dispatcher: options?.dispatcher,
|
|
49
|
+
signal: options?.signal,
|
|
44
50
|
});
|
|
45
51
|
}
|
|
46
52
|
/**
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* 远端客户端传输层单点。
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* 职责单一聚焦:服务端地址规范化、鉴权头拼装、明文传输安全校验、
|
|
5
|
+
* insecure dispatcher 注入、JSON 响应解析与查询参数序列化,
|
|
6
|
+
* 作为全部远端端点函数的统一传输层单一事实源。
|
|
6
7
|
*/
|
|
7
8
|
/**
|
|
8
9
|
* 传输层安全豁免控制选项。
|
|
@@ -13,12 +14,15 @@ export interface SecureTransportOptions {
|
|
|
13
14
|
/** 是否跳过 TLS 证书合法性校验 */
|
|
14
15
|
insecure?: boolean;
|
|
15
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* 格式化并规范化 Server URL 地址(若未指定协议,本地回环地址默认使用 http://,非本地回环地址默认使用 https://,并移除末尾斜杠)。
|
|
19
|
+
*/
|
|
20
|
+
export declare function normalizeServerUrl(url: string): string;
|
|
16
21
|
/**
|
|
17
22
|
* 校验在携带认证 Token 时传输层协议与目标地址是否安全。
|
|
18
23
|
* 若请求携带认证 Token 且目标为非本地回环的明文 http://,默认报错拒绝。
|
|
19
24
|
* 可通过 allowInsecureHttp 选项、insecure 选项、环境变量或命令行参数豁免明文限制。
|
|
20
|
-
* 目标 URL 无法解析时无论豁免与否均 fail-closed 抛 INVALID_ARGUMENT
|
|
21
|
-
* 杜绝携凭据请求发往不可控的畸形地址。
|
|
25
|
+
* 目标 URL 无法解析时无论豁免与否均 fail-closed 抛 INVALID_ARGUMENT。
|
|
22
26
|
*/
|
|
23
27
|
export declare function assertSecureTransport(serverUrl: string, token?: string, options?: SecureTransportOptions): void;
|
|
24
28
|
/**
|
|
@@ -35,6 +39,8 @@ export interface RemoteClientRequestOptions {
|
|
|
35
39
|
insecure?: boolean;
|
|
36
40
|
/** 自定义底层 HTTP 调度器(平台中立) */
|
|
37
41
|
dispatcher?: unknown;
|
|
42
|
+
/** 取消信号,用于中止 HTTP 请求 */
|
|
43
|
+
signal?: AbortSignal;
|
|
38
44
|
}
|
|
39
45
|
/** 远端请求描述选项。 */
|
|
40
46
|
export interface RemoteFetchInit {
|
|
@@ -49,15 +55,28 @@ export interface RemoteFetchInit {
|
|
|
49
55
|
}
|
|
50
56
|
/**
|
|
51
57
|
* 构建绑定传输上下文(Token、安全选项与调度器)的远端请求函数。
|
|
52
|
-
*
|
|
53
|
-
* 单一事实源收敛所有 fetchRemoteXxx 端点的传输样板:
|
|
54
|
-
* 调用方仅需声明 path 与查询参数,鉴权头拼装、明文传输校验与
|
|
55
|
-
* insecure dispatcher 注入均在此统一处理。
|
|
56
58
|
*/
|
|
57
59
|
export declare function createRemoteFetch(serverUrl: string, token?: string, options?: RemoteClientRequestOptions): (path: string, init?: RemoteFetchInit) => Promise<Response>;
|
|
58
60
|
/**
|
|
59
|
-
*
|
|
61
|
+
* 远端请求底层入口:执行目标协议路由请求。
|
|
60
62
|
*/
|
|
61
63
|
export declare function fetchRemoteRoute(base: string, path: string, init: RequestInit & {
|
|
62
64
|
dispatcher?: any;
|
|
63
65
|
}): Promise<Response>;
|
|
66
|
+
/**
|
|
67
|
+
* 执行远端请求并将响应解析为 JSON,统一处理错误信封透传。
|
|
68
|
+
*/
|
|
69
|
+
export declare function fetchRemoteJson<T = any>(serverUrl: string, path: string, token?: string, options?: {
|
|
70
|
+
method?: string;
|
|
71
|
+
body?: unknown;
|
|
72
|
+
errorPrefix?: string;
|
|
73
|
+
} & RemoteClientRequestOptions): Promise<T>;
|
|
74
|
+
/**
|
|
75
|
+
* 由可选参数字典构造查询串(无参数时返回空串)。
|
|
76
|
+
* 过滤 undefined 与空串。
|
|
77
|
+
*/
|
|
78
|
+
export declare function buildQueryString(params: Record<string, string | number | boolean | readonly (string | number | boolean)[] | undefined>): string;
|
|
79
|
+
/**
|
|
80
|
+
* 构造保留空串语义的查询串:仅跳过 undefined,保留空串。
|
|
81
|
+
*/
|
|
82
|
+
export declare function buildQueryStringPreservingEmpty(params: Record<string, string | number | boolean | readonly (string | number | boolean)[] | undefined>): string;
|