@actiondock/core 2.10.0 → 2.12.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 +8 -14
- 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 +20 -88
- 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 +53 -3
- package/dist/errors.js +53 -3
- 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 +562 -149
- 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/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 +1 -1
- package/dist/input/validation-mapper.d.ts +1 -1
- 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 +32 -573
- 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/dist/platform/types.d.ts
CHANGED
|
@@ -1,50 +1,8 @@
|
|
|
1
1
|
import type { ProcessAPI } from "@actiondock/sdk";
|
|
2
|
-
import type { Clock } from "../
|
|
3
|
-
import type { ModuleLoader } from "
|
|
2
|
+
import type { Clock } from "../storage/clock.js";
|
|
3
|
+
import type { ModuleLoader } from "./module-loader.js";
|
|
4
4
|
import type { RunsRetentionPolicy, RuntimeStorage } from "../storage/types.js";
|
|
5
|
-
|
|
6
|
-
* 文件元数据信息契约。
|
|
7
|
-
*/
|
|
8
|
-
export interface FileStat {
|
|
9
|
-
/** 是否为目录 */
|
|
10
|
-
isDirectory(): boolean;
|
|
11
|
-
/** 是否为普通文件 */
|
|
12
|
-
isFile(): boolean;
|
|
13
|
-
/** 文件字节大小 */
|
|
14
|
-
size: number;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* 跨运行时统一文件系统抽象契约。
|
|
18
|
-
*/
|
|
19
|
-
export interface FileSystem {
|
|
20
|
-
/** 读取文件内容 */
|
|
21
|
-
readFile(path: string, encoding?: string): Promise<string> | string;
|
|
22
|
-
/** 写入文件内容 */
|
|
23
|
-
writeFile(path: string, content: string | Uint8Array): Promise<void> | void;
|
|
24
|
-
/** 读取目录下的所有条目名称 */
|
|
25
|
-
readdir(dir: string): Promise<string[]> | string[];
|
|
26
|
-
/** 获取路径对应条目的元数据状态 */
|
|
27
|
-
stat(path: string): Promise<{
|
|
28
|
-
isDirectory(): boolean;
|
|
29
|
-
isFile(): boolean;
|
|
30
|
-
size: number;
|
|
31
|
-
}>;
|
|
32
|
-
/** 检查路径是否存在 */
|
|
33
|
-
exists(path: string): Promise<boolean> | boolean;
|
|
34
|
-
/** 创建目录 */
|
|
35
|
-
mkdir(dir: string, options?: {
|
|
36
|
-
recursive?: boolean;
|
|
37
|
-
}): Promise<void> | void;
|
|
38
|
-
/** 删除文件或目录 */
|
|
39
|
-
rm(path: string, options?: {
|
|
40
|
-
recursive?: boolean;
|
|
41
|
-
force?: boolean;
|
|
42
|
-
}): Promise<void> | void;
|
|
43
|
-
/** 拷贝文件或目录 */
|
|
44
|
-
copy(src: string, dest: string, options?: {
|
|
45
|
-
recursive?: boolean;
|
|
46
|
-
}): Promise<void> | void;
|
|
47
|
-
}
|
|
5
|
+
import type { EventSink } from "../runtime/events.js";
|
|
48
6
|
/**
|
|
49
7
|
* 跨运行时持久化存储工厂配置选项。
|
|
50
8
|
*/
|
|
@@ -93,12 +51,14 @@ export interface RuntimePlatform {
|
|
|
93
51
|
readonly name: "node" | "test";
|
|
94
52
|
/** 统一时间与时钟驱动 */
|
|
95
53
|
readonly clock: Clock;
|
|
96
|
-
/** 统一文件系统操作驱动 */
|
|
97
|
-
readonly files: FileSystem;
|
|
98
54
|
/** 动态源码模块加载驱动 */
|
|
99
55
|
readonly modules: ModuleLoader;
|
|
100
56
|
/** 子进程衍生与执行驱动 */
|
|
101
57
|
readonly process: ProcessAPI;
|
|
102
58
|
/** 持久化数据库存储驱动工厂 */
|
|
103
59
|
readonly storage: StorageFactory;
|
|
60
|
+
/**
|
|
61
|
+
* 可选执行事件接收器,宿主可注入,缺省由上层默认构造。
|
|
62
|
+
*/
|
|
63
|
+
readonly eventSink?: EventSink;
|
|
104
64
|
}
|
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
import type { CallOptions,
|
|
1
|
+
import type { CallOptions, OperationReceipt, ProcessAPI, ProcessControlInput, ProcessInfo, ProcessListInput, ProcessListResult, ProcessReadInput, ProcessRunInput, ProcessRunResult, ProcessStartInput, ProcessStartResult, ProcessStopInput, ProcessWriteInput, ReadResult } from "@actiondock/sdk";
|
|
2
2
|
import type { ProcessManager, ProcessOwner } from "./process-manager.js";
|
|
3
3
|
/**
|
|
4
4
|
* 绑定当前 ActionContext 上下文凭据与运行标识的 ProcessAPI 适配器实现。
|
|
5
5
|
*
|
|
6
6
|
* 核心保证:
|
|
7
7
|
* - 自动注入当前运行上下文的归属所有者与运行标识。
|
|
8
|
-
* -
|
|
9
|
-
* - 拦截 Run 退出或异常生命周期:若当前 Run 未显式 release 释放控制权,自动撤销 grant 并将目标进程置入隔离状态 quarantined。
|
|
8
|
+
* - 跟踪 Run 生命周期终结时的资源清理。
|
|
10
9
|
*/
|
|
11
10
|
export declare class ContextProcessAPI implements ProcessAPI {
|
|
12
|
-
private readonly heldProcesses;
|
|
13
11
|
private isDisposed;
|
|
14
12
|
private onAbortHandler?;
|
|
15
13
|
readonly processManager: ProcessManager;
|
|
@@ -39,18 +37,6 @@ export declare class ContextProcessAPI implements ProcessAPI {
|
|
|
39
37
|
* 分页列出当前所有者可见的受管进程列表。
|
|
40
38
|
*/
|
|
41
39
|
list(input: ProcessListInput, call?: CallOptions): Promise<ProcessListResult>;
|
|
42
|
-
/**
|
|
43
|
-
* 申请指定受管进程的独占控制令牌。
|
|
44
|
-
*/
|
|
45
|
-
acquire(id: string, input: ProcessAcquireInput, call?: CallOptions): Promise<ControlGrant>;
|
|
46
|
-
/**
|
|
47
|
-
* 延长当前有效控制令牌的存活时间。
|
|
48
|
-
*/
|
|
49
|
-
renew(id: string, token: string, ttlMs: number, call?: CallOptions): Promise<ControlGrant>;
|
|
50
|
-
/**
|
|
51
|
-
* 显式释放控制令牌。
|
|
52
|
-
*/
|
|
53
|
-
release(id: string, token: string, call?: CallOptions): Promise<void>;
|
|
54
40
|
/**
|
|
55
41
|
* 向受管进程输入流写入原始字节数据。
|
|
56
42
|
*/
|
|
@@ -72,8 +58,7 @@ export declare class ContextProcessAPI implements ProcessAPI {
|
|
|
72
58
|
*/
|
|
73
59
|
stop(id: string, input: ProcessStopInput, call?: CallOptions): Promise<ProcessInfo>;
|
|
74
60
|
/**
|
|
75
|
-
* 拦截 Action Run
|
|
76
|
-
* 若当前 Run 持有进程控制权且未显式 release,自动撤销 grant 并将目标进程置入隔离状态。
|
|
61
|
+
* 拦截 Action Run 生命周期终结,执行资源清理。
|
|
77
62
|
*/
|
|
78
63
|
dispose(): Promise<void>;
|
|
79
64
|
/**
|
|
@@ -3,11 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 核心保证:
|
|
5
5
|
* - 自动注入当前运行上下文的归属所有者与运行标识。
|
|
6
|
-
* -
|
|
7
|
-
* - 拦截 Run 退出或异常生命周期:若当前 Run 未显式 release 释放控制权,自动撤销 grant 并将目标进程置入隔离状态 quarantined。
|
|
6
|
+
* - 跟踪 Run 生命周期终结时的资源清理。
|
|
8
7
|
*/
|
|
9
8
|
export class ContextProcessAPI {
|
|
10
|
-
heldProcesses = new Map();
|
|
11
9
|
isDisposed = false;
|
|
12
10
|
onAbortHandler;
|
|
13
11
|
processManager;
|
|
@@ -64,29 +62,6 @@ export class ContextProcessAPI {
|
|
|
64
62
|
async list(input, call) {
|
|
65
63
|
return this.processManager.list(this.owner, input, this.mergeCallOptions(call));
|
|
66
64
|
}
|
|
67
|
-
/**
|
|
68
|
-
* 申请指定受管进程的独占控制令牌。
|
|
69
|
-
*/
|
|
70
|
-
async acquire(id, input, call) {
|
|
71
|
-
const grant = await this.processManager.acquire(this.owner, id, input, this.mergeCallOptions(call), this.runId);
|
|
72
|
-
this.heldProcesses.set(id, grant.token);
|
|
73
|
-
return grant;
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* 延长当前有效控制令牌的存活时间。
|
|
77
|
-
*/
|
|
78
|
-
async renew(id, token, ttlMs, call) {
|
|
79
|
-
const renewed = await this.processManager.renew(this.owner, id, token, ttlMs, this.mergeCallOptions(call));
|
|
80
|
-
this.heldProcesses.set(id, renewed.token);
|
|
81
|
-
return renewed;
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* 显式释放控制令牌。
|
|
85
|
-
*/
|
|
86
|
-
async release(id, token, call) {
|
|
87
|
-
await this.processManager.release(this.owner, id, token, this.mergeCallOptions(call));
|
|
88
|
-
this.heldProcesses.delete(id);
|
|
89
|
-
}
|
|
90
65
|
/**
|
|
91
66
|
* 向受管进程输入流写入原始字节数据。
|
|
92
67
|
*/
|
|
@@ -115,13 +90,10 @@ export class ContextProcessAPI {
|
|
|
115
90
|
* 终止指定的受管进程资源。
|
|
116
91
|
*/
|
|
117
92
|
async stop(id, input, call) {
|
|
118
|
-
|
|
119
|
-
this.heldProcesses.delete(id);
|
|
120
|
-
return info;
|
|
93
|
+
return await this.processManager.stop(this.owner, id, input, this.mergeCallOptions(call));
|
|
121
94
|
}
|
|
122
95
|
/**
|
|
123
|
-
* 拦截 Action Run
|
|
124
|
-
* 若当前 Run 持有进程控制权且未显式 release,自动撤销 grant 并将目标进程置入隔离状态。
|
|
96
|
+
* 拦截 Action Run 生命周期终结,执行资源清理。
|
|
125
97
|
*/
|
|
126
98
|
async dispose() {
|
|
127
99
|
if (this.isDisposed) {
|
|
@@ -132,19 +104,6 @@ export class ContextProcessAPI {
|
|
|
132
104
|
this.signal.removeEventListener("abort", this.onAbortHandler);
|
|
133
105
|
this.onAbortHandler = undefined;
|
|
134
106
|
}
|
|
135
|
-
if (this.heldProcesses.size === 0) {
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
const pendingEntries = Array.from(this.heldProcesses.entries());
|
|
139
|
-
this.heldProcesses.clear();
|
|
140
|
-
for (const [processId, token] of pendingEntries) {
|
|
141
|
-
try {
|
|
142
|
-
await this.processManager.quarantineProcess(this.owner, processId, token, "Run terminated without explicitly releasing control");
|
|
143
|
-
}
|
|
144
|
-
catch {
|
|
145
|
-
// 忽略终结清理阶段次级异常
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
107
|
}
|
|
149
108
|
/**
|
|
150
109
|
* 合并上下文取消信号与单次调用选项中的取消信号。
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ManagedProcessRecord, ProcessOwner } from "./managed-record.js";
|
|
2
|
+
export interface ControlManagerOptions {
|
|
3
|
+
persistState: (processId: string, patch: any) => Promise<void>;
|
|
4
|
+
takeoverQueue: (proc: ManagedProcessRecord, reason: string) => void;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* 受管进程控制权状态管理器。
|
|
8
|
+
* 聚焦于 free、quarantined 与 closed 三态流转与输入队列安全接管。
|
|
9
|
+
*/
|
|
10
|
+
export declare class ProcessControlManager {
|
|
11
|
+
private readonly options;
|
|
12
|
+
constructor(options: ControlManagerOptions);
|
|
13
|
+
/**
|
|
14
|
+
* 将进程控制状态原子收敛为已关闭(终态)。
|
|
15
|
+
*/
|
|
16
|
+
close(proc: ManagedProcessRecord): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* 将进程转入检疫隔离状态,接管待处理输入队列并透传隔离原因。
|
|
19
|
+
*/
|
|
20
|
+
quarantine(proc: ManagedProcessRecord, owner: ProcessOwner, reason?: string): Promise<void>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { CONTROL_REVOKED } from "../errors.js";
|
|
2
|
+
import { checkOwnerAuthorized } from "./converters.js";
|
|
3
|
+
/**
|
|
4
|
+
* 受管进程控制权状态管理器。
|
|
5
|
+
* 聚焦于 free、quarantined 与 closed 三态流转与输入队列安全接管。
|
|
6
|
+
*/
|
|
7
|
+
export class ProcessControlManager {
|
|
8
|
+
options;
|
|
9
|
+
constructor(options) {
|
|
10
|
+
this.options = options;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* 将进程控制状态原子收敛为已关闭(终态)。
|
|
14
|
+
*/
|
|
15
|
+
async close(proc) {
|
|
16
|
+
if (proc.info.control === "closed") {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
proc.info.control = "closed";
|
|
20
|
+
await this.options.persistState(proc.info.id, { control: "closed", controlState: "closed" });
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* 将进程转入检疫隔离状态,接管待处理输入队列并透传隔离原因。
|
|
24
|
+
*/
|
|
25
|
+
async quarantine(proc, owner, reason) {
|
|
26
|
+
checkOwnerAuthorized(owner, proc.owner);
|
|
27
|
+
if (proc.info.control === "quarantined" || proc.info.control === "closed") {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
proc.info.control = "quarantined";
|
|
31
|
+
this.options.takeoverQueue(proc, reason ?? CONTROL_REVOKED);
|
|
32
|
+
await this.options.persistState(proc.info.id, { control: "quarantined", controlState: "quarantined" });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ProcessInfo } from "@actiondock/sdk";
|
|
2
|
+
import type { ProcessOwnerFilter, StoredProcessRecord } from "./metadata-store.js";
|
|
3
|
+
import type { ProcessOwner } from "./managed-record.js";
|
|
4
|
+
/**
|
|
5
|
+
* 格式化生成作用域唯一隔离字符串。
|
|
6
|
+
*/
|
|
7
|
+
export declare function formatProcessScope(owner: ProcessOwner): string;
|
|
8
|
+
/**
|
|
9
|
+
* 校验调用方所有者凭据与目标记录是否完全匹配。
|
|
10
|
+
*/
|
|
11
|
+
export declare function checkOwnerAuthorized(owner: ProcessOwner, target: ProcessOwnerFilter | StoredProcessRecord): void;
|
|
12
|
+
/**
|
|
13
|
+
* 计算任意 JSON 负载对象的 SHA-256 哈希值。
|
|
14
|
+
*/
|
|
15
|
+
export declare function hashRequestPayload(payload: unknown): string;
|
|
16
|
+
/**
|
|
17
|
+
* 将持久化记录转换为 SDK 标准 ProcessInfo 快照。
|
|
18
|
+
*/
|
|
19
|
+
export declare function toSdkProcessInfo(record: StoredProcessRecord): ProcessInfo;
|
|
20
|
+
/**
|
|
21
|
+
* 将内部模型转换为持久化记录。
|
|
22
|
+
*/
|
|
23
|
+
export declare function toStoredProcessRecord(owner: ProcessOwner, info: ProcessInfo, startRequestId?: string): StoredProcessRecord;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { ACCESS_DENIED, ProcessError } from "../errors.js";
|
|
3
|
+
/**
|
|
4
|
+
* 格式化生成作用域唯一隔离字符串。
|
|
5
|
+
*/
|
|
6
|
+
export function formatProcessScope(owner) {
|
|
7
|
+
return `${owner.tenantId}:${owner.principalId}:${owner.packageInstanceId}:${owner.generationId}`;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* 校验调用方所有者凭据与目标记录是否完全匹配。
|
|
11
|
+
*/
|
|
12
|
+
export function checkOwnerAuthorized(owner, target) {
|
|
13
|
+
if (!owner ||
|
|
14
|
+
!owner.tenantId ||
|
|
15
|
+
!owner.principalId ||
|
|
16
|
+
!owner.packageInstanceId ||
|
|
17
|
+
!owner.generationId) {
|
|
18
|
+
throw new ProcessError(ACCESS_DENIED, "Missing required owner identity fields");
|
|
19
|
+
}
|
|
20
|
+
if (owner.tenantId !== target.tenantId ||
|
|
21
|
+
owner.principalId !== target.principalId ||
|
|
22
|
+
owner.packageInstanceId !== target.packageInstanceId ||
|
|
23
|
+
owner.generationId !== target.generationId) {
|
|
24
|
+
throw new ProcessError(ACCESS_DENIED, "Access denied: owner identity mismatch");
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 计算任意 JSON 负载对象的 SHA-256 哈希值。
|
|
29
|
+
*/
|
|
30
|
+
export function hashRequestPayload(payload) {
|
|
31
|
+
return createHash("sha256").update(JSON.stringify(payload)).digest("hex");
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* 将持久化记录转换为 SDK 标准 ProcessInfo 快照。
|
|
35
|
+
*/
|
|
36
|
+
export function toSdkProcessInfo(record) {
|
|
37
|
+
const ctrl = (record.control ?? record.controlState ?? "free");
|
|
38
|
+
const exitDetails = record.exitCode !== undefined || record.exitSignal !== undefined
|
|
39
|
+
? { code: record.exitCode ?? null, signal: record.exitSignal ?? null }
|
|
40
|
+
: undefined;
|
|
41
|
+
return {
|
|
42
|
+
id: record.processId,
|
|
43
|
+
hostEpoch: record.hostEpoch,
|
|
44
|
+
state: record.state,
|
|
45
|
+
control: ctrl,
|
|
46
|
+
io: (record.ioConfig ?? { mode: "pipe" }),
|
|
47
|
+
capabilities: (record.capabilities ?? {
|
|
48
|
+
pty: false,
|
|
49
|
+
resize: false,
|
|
50
|
+
inputEOF: false,
|
|
51
|
+
interruptForeground: false,
|
|
52
|
+
terminationScope: "process",
|
|
53
|
+
}),
|
|
54
|
+
createdAt: record.createdAt ?? new Date().toISOString(),
|
|
55
|
+
exit: exitDetails,
|
|
56
|
+
endReason: record.endReason,
|
|
57
|
+
outputClosed: Boolean(record.outputClosed),
|
|
58
|
+
outputEndReason: record.outputEndReason,
|
|
59
|
+
effectiveLimits: (record.effectiveLimits ?? {
|
|
60
|
+
idleMs: 60000,
|
|
61
|
+
lifetimeMs: 3600000,
|
|
62
|
+
outputBufferBytes: 4 * 1024 * 1024,
|
|
63
|
+
}),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* 将内部模型转换为持久化记录。
|
|
68
|
+
*/
|
|
69
|
+
export function toStoredProcessRecord(owner, info, startRequestId) {
|
|
70
|
+
return {
|
|
71
|
+
processId: info.id,
|
|
72
|
+
tenantId: owner.tenantId,
|
|
73
|
+
principalId: owner.principalId,
|
|
74
|
+
packageInstanceId: owner.packageInstanceId,
|
|
75
|
+
generationId: owner.generationId,
|
|
76
|
+
hostEpoch: info.hostEpoch,
|
|
77
|
+
state: info.state,
|
|
78
|
+
controlState: info.control,
|
|
79
|
+
control: info.control,
|
|
80
|
+
ioConfig: info.io,
|
|
81
|
+
capabilities: info.capabilities,
|
|
82
|
+
createdAt: info.createdAt,
|
|
83
|
+
exitCode: info.exit ? info.exit.code : null,
|
|
84
|
+
exitSignal: info.exit ? info.exit.signal : null,
|
|
85
|
+
endReason: info.endReason ?? null,
|
|
86
|
+
outputClosed: info.outputClosed,
|
|
87
|
+
outputEndReason: info.outputEndReason ?? null,
|
|
88
|
+
inputClosed: false,
|
|
89
|
+
effectiveLimits: info.effectiveLimits,
|
|
90
|
+
startRequestId,
|
|
91
|
+
};
|
|
92
|
+
}
|
package/dist/process/cursor.js
CHANGED
|
@@ -1,29 +1,9 @@
|
|
|
1
1
|
import { INVALID_CURSOR, ProcessError } from "../errors.js";
|
|
2
2
|
function toBase64Url(str) {
|
|
3
|
-
|
|
4
|
-
return Buffer.from(str, "utf8").toString("base64url");
|
|
5
|
-
}
|
|
6
|
-
const bytes = new TextEncoder().encode(str);
|
|
7
|
-
let binary = "";
|
|
8
|
-
for (let i = 0; i < bytes.byteLength; i++) {
|
|
9
|
-
binary += String.fromCharCode(bytes[i]);
|
|
10
|
-
}
|
|
11
|
-
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
3
|
+
return Buffer.from(str, "utf8").toString("base64url");
|
|
12
4
|
}
|
|
13
5
|
function fromBase64Url(base64url) {
|
|
14
|
-
|
|
15
|
-
return Buffer.from(base64url, "base64url").toString("utf8");
|
|
16
|
-
}
|
|
17
|
-
let base64 = base64url.replace(/-/g, "+").replace(/_/g, "/");
|
|
18
|
-
while (base64.length % 4) {
|
|
19
|
-
base64 += "=";
|
|
20
|
-
}
|
|
21
|
-
const binary = atob(base64);
|
|
22
|
-
const bytes = new Uint8Array(binary.length);
|
|
23
|
-
for (let i = 0; i < binary.length; i++) {
|
|
24
|
-
bytes[i] = binary.charCodeAt(i);
|
|
25
|
-
}
|
|
26
|
-
return new TextDecoder("utf-8").decode(bytes);
|
|
6
|
+
return Buffer.from(base64url, "base64url").toString("utf8");
|
|
27
7
|
}
|
|
28
8
|
/**
|
|
29
9
|
* 将内部字段编码为外部不透明游标字符串。
|
|
@@ -6,7 +6,6 @@ import type { Logger } from "@actiondock/sdk";
|
|
|
6
6
|
* 缺失时保留在内存环形缓冲区,避免静默吞没异常。
|
|
7
7
|
*/
|
|
8
8
|
export declare class DiagnosticsSink {
|
|
9
|
-
/** 注入的 logger 缺失时保留最近诊断条目的环形缓冲容量,默认 100 */
|
|
10
9
|
static readonly DEFAULT_BUFFER_LIMIT = 100;
|
|
11
10
|
private readonly logger?;
|
|
12
11
|
private readonly bufferLimit;
|
|
@@ -15,12 +14,6 @@ export declare class DiagnosticsSink {
|
|
|
15
14
|
logger?: Logger;
|
|
16
15
|
bufferLimit?: number;
|
|
17
16
|
});
|
|
18
|
-
/**
|
|
19
|
-
* 记录内部诊断信息:优先写入注入的 logger,缺失时保留在内存环形缓冲区。
|
|
20
|
-
*/
|
|
21
17
|
record(message: string, err?: unknown): void;
|
|
22
|
-
/**
|
|
23
|
-
* 获取最近的内部诊断日志快照(最近条目在前)。
|
|
24
|
-
*/
|
|
25
18
|
recent(): string[];
|
|
26
19
|
}
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
* 缺失时保留在内存环形缓冲区,避免静默吞没异常。
|
|
6
6
|
*/
|
|
7
7
|
export class DiagnosticsSink {
|
|
8
|
-
/** 注入的 logger 缺失时保留最近诊断条目的环形缓冲容量,默认 100 */
|
|
9
8
|
static DEFAULT_BUFFER_LIMIT = 100;
|
|
10
9
|
logger;
|
|
11
10
|
bufferLimit;
|
|
@@ -14,9 +13,6 @@ export class DiagnosticsSink {
|
|
|
14
13
|
this.logger = options?.logger;
|
|
15
14
|
this.bufferLimit = options?.bufferLimit ?? DiagnosticsSink.DEFAULT_BUFFER_LIMIT;
|
|
16
15
|
}
|
|
17
|
-
/**
|
|
18
|
-
* 记录内部诊断信息:优先写入注入的 logger,缺失时保留在内存环形缓冲区。
|
|
19
|
-
*/
|
|
20
16
|
record(message, err) {
|
|
21
17
|
const detail = err instanceof Error ? `${err.name}: ${err.message}` : err !== undefined ? String(err) : "";
|
|
22
18
|
const line = detail ? `${message} (${detail})` : message;
|
|
@@ -24,11 +20,13 @@ export class DiagnosticsSink {
|
|
|
24
20
|
if (this.diagnostics.length > this.bufferLimit) {
|
|
25
21
|
this.diagnostics.shift();
|
|
26
22
|
}
|
|
27
|
-
|
|
23
|
+
try {
|
|
24
|
+
this.logger?.warn("[ProcessManager] " + line);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// 防御与透明:避免外部 Logger 故障反向干扰核心生命周期流程
|
|
28
|
+
}
|
|
28
29
|
}
|
|
29
|
-
/**
|
|
30
|
-
* 获取最近的内部诊断日志快照(最近条目在前)。
|
|
31
|
-
*/
|
|
32
30
|
recent() {
|
|
33
31
|
return [...this.diagnostics].reverse();
|
|
34
32
|
}
|
package/dist/process/index.d.ts
CHANGED
|
@@ -2,14 +2,12 @@ export * from "./cursor.js";
|
|
|
2
2
|
export * from "./output-log.js";
|
|
3
3
|
export * from "./metadata-store.js";
|
|
4
4
|
export * from "./driver.js";
|
|
5
|
-
export * from "./diagnostics-sink.js";
|
|
6
5
|
export * from "./reservation-table.js";
|
|
7
6
|
export * from "./terminal-output-cache.js";
|
|
8
7
|
export * from "./run-executor.js";
|
|
9
8
|
export * from "./managed-record.js";
|
|
10
|
-
export * from "./control-arbiter.js";
|
|
11
9
|
export * from "./input-dispatcher.js";
|
|
12
10
|
export * from "./process-manager.js";
|
|
13
11
|
export * from "./context-process.js";
|
|
14
12
|
export * from "./process-driver.js";
|
|
15
|
-
export * from "./
|
|
13
|
+
export * from "./converters.js";
|
package/dist/process/index.js
CHANGED
|
@@ -2,14 +2,12 @@ export * from "./cursor.js";
|
|
|
2
2
|
export * from "./output-log.js";
|
|
3
3
|
export * from "./metadata-store.js";
|
|
4
4
|
export * from "./driver.js";
|
|
5
|
-
export * from "./diagnostics-sink.js";
|
|
6
5
|
export * from "./reservation-table.js";
|
|
7
6
|
export * from "./terminal-output-cache.js";
|
|
8
7
|
export * from "./run-executor.js";
|
|
9
8
|
export * from "./managed-record.js";
|
|
10
|
-
export * from "./control-arbiter.js";
|
|
11
9
|
export * from "./input-dispatcher.js";
|
|
12
10
|
export * from "./process-manager.js";
|
|
13
11
|
export * from "./context-process.js";
|
|
14
12
|
export * from "./process-driver.js";
|
|
15
|
-
export * from "./
|
|
13
|
+
export * from "./converters.js";
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { OperationReceipt } from "@actiondock/sdk";
|
|
2
2
|
import type { ManagedProcessRecord, ProcessOwner, QueuedOperation } from "./managed-record.js";
|
|
3
|
-
import type { ControlArbiter } from "./control-arbiter.js";
|
|
4
3
|
import type { ProcessRequestKey, StoredProcessRecord } from "./metadata-store.js";
|
|
5
4
|
/**
|
|
6
5
|
* 输入调度器宿主协作回调集合。
|
|
@@ -12,23 +11,17 @@ export interface InputDispatcherHost {
|
|
|
12
11
|
persistReceipt(key: ProcessRequestKey, receipt: OperationReceipt, payloadHash?: string): Promise<void>;
|
|
13
12
|
persistState(processId: string, patch: Partial<StoredProcessRecord>): Promise<void>;
|
|
14
13
|
/** 写入不确定失败后的隔离处置 */
|
|
15
|
-
quarantineProcess(owner: ProcessOwner, processId: string,
|
|
14
|
+
quarantineProcess(owner: ProcessOwner, processId: string, reason?: string): Promise<void> | unknown;
|
|
16
15
|
/** 成功输入后的空闲定时器刷新 */
|
|
17
16
|
refreshIdleTimer(proc: ManagedProcessRecord): void;
|
|
18
17
|
/** 内部诊断记录 */
|
|
19
18
|
recordDiagnostic(message: string, err?: unknown): void;
|
|
20
|
-
/** 宿主级输入队列待写字节统计 */
|
|
21
|
-
countHostPendingInputBytes(): number;
|
|
22
|
-
/** 输入队列容量配额 */
|
|
23
|
-
readonly maxPendingQueueBytesPerProcess: number;
|
|
24
|
-
readonly maxPendingQueueBytesPerHost: number;
|
|
25
19
|
}
|
|
26
20
|
/**
|
|
27
21
|
* write 入队请求参数。
|
|
28
22
|
*/
|
|
29
23
|
export interface EnqueueWriteInput {
|
|
30
24
|
requestId: string;
|
|
31
|
-
token: string;
|
|
32
25
|
data: Uint8Array;
|
|
33
26
|
key: ProcessRequestKey;
|
|
34
27
|
payloadHash: string;
|
|
@@ -38,7 +31,6 @@ export interface EnqueueWriteInput {
|
|
|
38
31
|
*/
|
|
39
32
|
export interface EnqueueControlInput {
|
|
40
33
|
requestId: string;
|
|
41
|
-
token: string;
|
|
42
34
|
action: QueuedOperation["action"];
|
|
43
35
|
key: ProcessRequestKey;
|
|
44
36
|
payloadHash: string;
|
|
@@ -55,14 +47,13 @@ export interface EnqueueControlInput {
|
|
|
55
47
|
*/
|
|
56
48
|
export declare class InputDispatcher {
|
|
57
49
|
private readonly host;
|
|
58
|
-
|
|
59
|
-
constructor(host: InputDispatcherHost, arbiter: ControlArbiter);
|
|
50
|
+
constructor(host: InputDispatcherHost);
|
|
60
51
|
/**
|
|
61
|
-
*
|
|
52
|
+
* 入队写入操作:同步阶段完成授权校验与输入通道校验;
|
|
62
53
|
* 异步阶段落盘排队收据并推送队列,随后触发串行调度。
|
|
63
54
|
*
|
|
64
55
|
* 返回的 Promise 在收据成功入队后 resolve(state 为 queued);
|
|
65
|
-
*
|
|
56
|
+
* 落盘或推送失败时原样抛出。
|
|
66
57
|
*/
|
|
67
58
|
enqueueWrite(proc: ManagedProcessRecord, input: EnqueueWriteInput): Promise<OperationReceipt>;
|
|
68
59
|
/**
|