@actiondock/core 2.19.0 → 2.21.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/dist/client/config.d.ts +17 -14
- package/dist/client/config.js +112 -14
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.js +1 -1
- package/dist/errors.d.ts +13 -1
- package/dist/errors.js +25 -0
- package/dist/execution/service.js +44 -10
- package/dist/execution/types.d.ts +3 -3
- package/dist/host/host.d.ts +20 -1
- package/dist/host/host.js +430 -66
- package/dist/host/types.d.ts +13 -1
- package/dist/index.d.ts +11 -3
- package/dist/index.js +5 -1
- package/dist/input/config-override.d.ts +5 -0
- package/dist/input/config-override.js +23 -0
- package/dist/input/input-resolver.d.ts +24 -7
- package/dist/input/input-resolver.js +73 -5
- package/dist/invocation/bindings.d.ts +53 -0
- package/dist/invocation/bindings.js +248 -0
- package/dist/invocation/policy.d.ts +5 -1
- package/dist/invocation/policy.js +16 -9
- package/dist/invocation/remote.d.ts +40 -0
- package/dist/invocation/remote.js +489 -0
- package/dist/invocation/types.d.ts +33 -0
- package/dist/invocation/types.js +11 -1
- package/dist/package/index.d.ts +2 -2
- package/dist/package/runtime.js +48 -15
- package/dist/platform/node.d.ts +6 -0
- package/dist/platform/node.js +59 -16
- package/dist/platform/types.d.ts +59 -1
- package/dist/process/command-executor.d.ts +35 -0
- package/dist/process/command-executor.js +326 -0
- package/dist/process/index.d.ts +1 -0
- package/dist/process/index.js +1 -0
- package/dist/process/process-driver.d.ts +19 -6
- package/dist/process/process-driver.js +223 -54
- package/dist/process/run-executor.js +101 -47
- package/dist/project/config-declarations.d.ts +61 -0
- package/dist/project/config-declarations.js +297 -0
- package/dist/project/dependencies.d.ts +92 -0
- package/dist/project/dependencies.js +543 -0
- package/dist/project/index.d.ts +8 -2
- package/dist/project/index.js +8 -2
- package/dist/project/init.js +2 -2
- package/dist/project/loader.js +19 -30
- package/dist/project/manifest.js +10 -0
- package/dist/project/package-manager.d.ts +40 -0
- package/dist/project/package-manager.js +224 -0
- package/dist/project/preparation.d.ts +8 -0
- package/dist/project/preparation.js +130 -0
- package/dist/project/transactions.d.ts +5 -1
- package/dist/project/transactions.js +35 -75
- package/dist/project/types.d.ts +30 -0
- package/dist/runtime/context.d.ts +27 -5
- package/dist/runtime/context.js +98 -26
- package/dist/runtime/env.js +15 -1
- package/dist/runtime/run-persistence.d.ts +1 -1
- package/dist/runtime/run-persistence.js +4 -3
- package/dist/runtime/standalone-commands.d.ts +2 -2
- package/dist/runtime/standalone-commands.js +113 -47
- package/dist/runtime/standalone-help.d.ts +1 -0
- package/dist/runtime/standalone-help.js +15 -9
- package/dist/runtime/standalone.js +2 -2
- package/dist/security/config-cipher.d.ts +54 -0
- package/dist/security/config-cipher.js +190 -0
- package/dist/security/config-key.d.ts +35 -0
- package/dist/security/config-key.js +469 -0
- package/dist/server/policy.d.ts +24 -107
- package/dist/server/policy.js +134 -291
- package/dist/server/routes/actions.js +10 -8
- package/dist/server/routes/common.d.ts +5 -20
- package/dist/server/routes/common.js +22 -58
- package/dist/server/routes/config.js +84 -7
- package/dist/server/routes/doctor.d.ts +1 -0
- package/dist/server/routes/doctor.js +4 -3
- package/dist/server/routes/info.js +100 -13
- package/dist/server/routes/playbooks.js +1 -3
- package/dist/server/routes/runs.js +96 -18
- package/dist/server/server.js +25 -53
- package/dist/server/types.d.ts +6 -6
- package/dist/service/factory.js +4 -0
- package/dist/service/remote.js +14 -29
- package/dist/service/types.d.ts +28 -5
- package/dist/service/types.js +8 -0
- package/dist/storage/config-value.d.ts +33 -0
- package/dist/storage/config-value.js +102 -0
- package/dist/storage/file-lock.js +35 -21
- package/dist/storage/index.d.ts +24 -2
- package/dist/storage/index.js +65 -2
- package/dist/storage/mask.d.ts +33 -6
- package/dist/storage/mask.js +298 -16
- package/dist/storage/migrations/index.d.ts +40 -0
- package/dist/storage/migrations/index.js +96 -0
- package/dist/storage/migrations/v2-to-v3.d.ts +16 -0
- package/dist/storage/migrations/v2-to-v3.js +116 -0
- package/dist/storage/sqlite-config.d.ts +62 -3
- package/dist/storage/sqlite-config.js +163 -9
- package/dist/storage/sqlite-driver.d.ts +5 -2
- package/dist/storage/sqlite-driver.js +24 -3
- package/dist/storage/sqlite-schema.d.ts +20 -2
- package/dist/storage/sqlite-schema.js +129 -132
- package/dist/storage/sqlite.d.ts +7 -2
- package/dist/storage/sqlite.js +64 -13
- package/dist/storage/types.d.ts +72 -4
- package/dist/storage/types.js +7 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
package/dist/invocation/types.js
CHANGED
|
@@ -31,9 +31,12 @@ export function createInvocationContext(options) {
|
|
|
31
31
|
parentRunId: options.parentRunId,
|
|
32
32
|
caller: options.caller,
|
|
33
33
|
callStack: options.callStack ? [...options.callStack] : [],
|
|
34
|
+
targetScope: options.targetScope,
|
|
34
35
|
package: pkg,
|
|
35
36
|
signal: options.signal ?? new AbortController().signal,
|
|
36
37
|
timeoutMs: options.timeoutMs,
|
|
38
|
+
initialTimeoutMs: options.initialTimeoutMs,
|
|
39
|
+
deadline: options.deadline,
|
|
37
40
|
config: options.config,
|
|
38
41
|
requestId: options.requestId,
|
|
39
42
|
tenantId: options.tenantId,
|
|
@@ -63,11 +66,16 @@ export function createInvocationContext(options) {
|
|
|
63
66
|
* parentRunId 与 caller 为 undefined,并按根调用契约挑选字段,保持无血缘血缘字段的键序不变。
|
|
64
67
|
*/
|
|
65
68
|
export function createRootInvocationContext(options) {
|
|
69
|
+
const initialTimeoutMs = options.initialTimeoutMs ?? (typeof options.timeoutMs === "number" && options.timeoutMs > 0 ? options.timeoutMs : undefined);
|
|
70
|
+
const deadline = options.deadline ?? (initialTimeoutMs !== undefined ? Date.now() + initialTimeoutMs : undefined);
|
|
71
|
+
const remainingBudget = deadline !== undefined ? Math.max(0, deadline - Date.now()) : options.timeoutMs;
|
|
66
72
|
const base = createInvocationContext({
|
|
67
73
|
package: options.targetPackage,
|
|
68
74
|
callStack: options.callStack,
|
|
69
75
|
signal: options.signal,
|
|
70
|
-
timeoutMs:
|
|
76
|
+
timeoutMs: remainingBudget,
|
|
77
|
+
initialTimeoutMs,
|
|
78
|
+
deadline,
|
|
71
79
|
config: options.config,
|
|
72
80
|
requestId: options.requestId,
|
|
73
81
|
hostSessionId: options.hostSessionId,
|
|
@@ -89,6 +97,8 @@ export function createRootInvocationContext(options) {
|
|
|
89
97
|
package: base.package,
|
|
90
98
|
signal: base.signal,
|
|
91
99
|
timeoutMs: base.timeoutMs,
|
|
100
|
+
initialTimeoutMs: base.initialTimeoutMs,
|
|
101
|
+
deadline: base.deadline,
|
|
92
102
|
config: base.config,
|
|
93
103
|
requestId: base.requestId,
|
|
94
104
|
hostSessionId: base.hostSessionId,
|
package/dist/package/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export { createPackageRuntime, DefaultPackageRuntime, } from "./runtime.js";
|
|
|
10
10
|
export { createNonClosingStorageView } from "./storage-view.js";
|
|
11
11
|
export { findExecutable } from "../utils/index.js";
|
|
12
12
|
export type { PackageRuntime, PackageRuntimeOptions, PackageInfo, ActionSpec, ActionSummary, PlaybookSpec, PlaybookSummary, } from "./types.js";
|
|
13
|
-
export type { RuntimePlatform, StorageFactory, StorageFactoryOptions, GlobalStorageFactoryOptions, } from "../platform/types.js";
|
|
13
|
+
export type { RuntimePlatform, StorageFactory, StorageFactoryOptions, GlobalStorageFactoryOptions, InvocationTargetResolution, InvocationCallerInfo, InvocationTargetResolver, } from "../platform/types.js";
|
|
14
14
|
export { type Clock, SystemClock, } from "../storage/clock.js";
|
|
15
15
|
export type { ModuleLoader } from "../platform/module-loader.js";
|
|
16
16
|
export { InMemoryEventSink, type EventSink, } from "../runtime/events.js";
|
|
@@ -19,4 +19,4 @@ export type { ProcessAPI as ProcessExecutor } from "@actiondock/sdk";
|
|
|
19
19
|
export type { ProcessDriver, ProcessDriverCallbacks, ProcessDriverHandle, ProcessHandle, ProcessObserver, } from "../process/driver.js";
|
|
20
20
|
export { createStorage, resolveDatabasePath, } from "../storage/index.js";
|
|
21
21
|
export { SqliteRuntimeStorage } from "../storage/sqlite.js";
|
|
22
|
-
export type { RuntimeStorage, SqliteDriver, StateEntry, } from "../storage/types.js";
|
|
22
|
+
export type { RuntimeStorage, SqliteDriver, StateEntry, ConfigWriteOptions, ConfigSnapshot, } from "../storage/types.js";
|
package/dist/package/runtime.js
CHANGED
|
@@ -5,7 +5,9 @@ import { createNodePlatform } from "../platform/index.js";
|
|
|
5
5
|
import { findProjectRoot, loadProjectConfig } from "../project/loader.js";
|
|
6
6
|
import { RuntimeConfig } from "../runtime/context.js";
|
|
7
7
|
import { normalizeActionCollection } from "../runtime/action-collection.js";
|
|
8
|
-
import {
|
|
8
|
+
import { redactConfigValue, sanitizeConfigDefinitions } from "../storage/mask.js";
|
|
9
|
+
import { redactConfigValueWithProtection } from "../storage/index.js";
|
|
10
|
+
import { assertConcreteConfigKey, assertValidConfigDeclarations, isConfigTemplate, resolveConfigDeclaration, validateConfigValue, } from "../project/config-declarations.js";
|
|
9
11
|
import { decodeStateKey, SqliteRuntimeStorage } from "../storage/sqlite.js";
|
|
10
12
|
import { createPackageIdentity } from "../runtime/identity.js";
|
|
11
13
|
import { ACTION_NOT_FOUND, ActionDockError, CAPABILITY_UNAVAILABLE, INVALID_ARGUMENT, INVOCATION_UNSUPPORTED, NOT_FOUND, SERVICE_CLOSED, } from "../errors.js";
|
|
@@ -127,6 +129,9 @@ export class DefaultPackageRuntime {
|
|
|
127
129
|
};
|
|
128
130
|
}
|
|
129
131
|
this.packageRoot = packageRoot;
|
|
132
|
+
if (projectConfig.config !== undefined) {
|
|
133
|
+
assertValidConfigDeclarations(projectConfig.config);
|
|
134
|
+
}
|
|
130
135
|
this.projectConfig = projectConfig;
|
|
131
136
|
// 兼容未在公开选项契约中显式声明的包实例标识与代系标识内部参数透传
|
|
132
137
|
this.identity = options.identity || createPackageIdentity({
|
|
@@ -235,6 +240,7 @@ export class DefaultPackageRuntime {
|
|
|
235
240
|
}
|
|
236
241
|
/** 构造包存储工厂选项(单一事实源,异步与同步打开路径共用) */
|
|
237
242
|
buildStorageOptions() {
|
|
243
|
+
const config = this.projectConfig?.config;
|
|
238
244
|
return {
|
|
239
245
|
projectRoot: this.packageRoot,
|
|
240
246
|
dataDir: this.options.dataDir,
|
|
@@ -243,6 +249,9 @@ export class DefaultPackageRuntime {
|
|
|
243
249
|
// 默认持有者语义:App 主路径打开时收割死亡会话遗留非终态运行记录;
|
|
244
250
|
// CLI 查询旁观视图显式置 recoverOrphans: false 跳过收割
|
|
245
251
|
recoverOrphans: this.options.recoverOrphans !== false,
|
|
252
|
+
// 供旧版本库自动迁移判定敏感性(各字典内具体键优先于模板);
|
|
253
|
+
// 仅在库需要迁移时被读取,不引入新的生命周期
|
|
254
|
+
...(config && Object.keys(config).length > 0 ? { configDeclarations: [config] } : {}),
|
|
246
255
|
};
|
|
247
256
|
}
|
|
248
257
|
/**
|
|
@@ -296,12 +305,15 @@ export class DefaultPackageRuntime {
|
|
|
296
305
|
this.globalStorageRes = { kind: "own", storage };
|
|
297
306
|
return storage;
|
|
298
307
|
}
|
|
308
|
+
const config = this.projectConfig?.config;
|
|
299
309
|
const globalOpts = {
|
|
300
310
|
customHome: this.options.customHome,
|
|
301
311
|
dataDir: this.options.dataDir,
|
|
302
312
|
inMemory: this.options.inMemory,
|
|
303
313
|
// 与主存储保持同侧收割语义(全局库 runs 表为空集,收割无实际副作用)
|
|
304
314
|
recoverOrphans: this.options.recoverOrphans !== false,
|
|
315
|
+
// 独立全局库迁移以当前包声明为并集口径;Host 共享路径由 Host 汇集全部已加载包声明
|
|
316
|
+
...(config && Object.keys(config).length > 0 ? { configDeclarations: [config] } : {}),
|
|
305
317
|
};
|
|
306
318
|
const storage = this.platform.storage.createGlobalStorage(globalOpts);
|
|
307
319
|
this.globalStorageRes = { kind: "own", storage };
|
|
@@ -679,9 +691,18 @@ export class DefaultPackageRuntime {
|
|
|
679
691
|
}
|
|
680
692
|
async listConfig() {
|
|
681
693
|
this.assertOpen();
|
|
682
|
-
const
|
|
683
|
-
const
|
|
684
|
-
const
|
|
694
|
+
const packageStorage = await this.prepareStorageAsync();
|
|
695
|
+
const globalStorage = await this.ensureGlobalStorage();
|
|
696
|
+
const declaredKeys = Object.keys(this.projectConfig.config || {}).filter((k) => !isConfigTemplate(k));
|
|
697
|
+
const packageStoredKeys = Object.keys(packageStorage.listConfig());
|
|
698
|
+
const globalStoredKeys = Object.keys(globalStorage.listConfig());
|
|
699
|
+
const overrideKeys = Object.keys(this.options.configOverrides || {});
|
|
700
|
+
const allKeys = Array.from(new Set([
|
|
701
|
+
...declaredKeys,
|
|
702
|
+
...packageStoredKeys,
|
|
703
|
+
...globalStoredKeys,
|
|
704
|
+
...overrideKeys,
|
|
705
|
+
])).filter((k) => !isConfigTemplate(k));
|
|
685
706
|
const views = [];
|
|
686
707
|
for (const key of allKeys) {
|
|
687
708
|
const item = await this.getConfig(key);
|
|
@@ -693,27 +714,39 @@ export class DefaultPackageRuntime {
|
|
|
693
714
|
}
|
|
694
715
|
async getConfig(key) {
|
|
695
716
|
this.assertOpen();
|
|
696
|
-
|
|
697
|
-
const
|
|
698
|
-
// 委托 RuntimeConfig
|
|
699
|
-
const resolved = this.ensureRuntimeConfig().
|
|
700
|
-
//
|
|
701
|
-
|
|
702
|
-
const configured = resolved.source !== "default";
|
|
717
|
+
assertConcreteConfigKey(key);
|
|
718
|
+
const decl = resolveConfigDeclaration(this.projectConfig.config, key);
|
|
719
|
+
// 委托 RuntimeConfig 五层优先级链单一事实源,取值与历史保护声明同链原子解析
|
|
720
|
+
const resolved = this.ensureRuntimeConfig().describeWithProtection(key);
|
|
721
|
+
// configured 显式判定:仅真实显式来源(override/package/global/env)为 true,
|
|
722
|
+
// default 与整链未命中(source null)均为 false,不得依赖与 "default" 的不等比较
|
|
723
|
+
const configured = resolved.source !== null && resolved.source !== "default";
|
|
724
|
+
// 当前声明与存储持久化的历史保护声明合并脱敏:删除或弱化声明后仍保持既有保护;
|
|
725
|
+
// 无历史保护时沿用单声明脱敏原语,保持既有视图行为不变
|
|
726
|
+
const redacted = resolved.protection !== undefined
|
|
727
|
+
? redactConfigValueWithProtection(resolved.value, decl?.item ? [decl.item] : [], resolved.protection)
|
|
728
|
+
: redactConfigValue(resolved.value, decl?.item);
|
|
703
729
|
return {
|
|
704
730
|
key,
|
|
705
731
|
configured,
|
|
706
|
-
secret:
|
|
707
|
-
source,
|
|
708
|
-
value:
|
|
732
|
+
secret: redacted.secret,
|
|
733
|
+
source: resolved.source,
|
|
734
|
+
value: redacted.value,
|
|
735
|
+
redactedPaths: redacted.redactedPaths,
|
|
709
736
|
};
|
|
710
737
|
}
|
|
711
738
|
async setConfig(key, value) {
|
|
712
739
|
this.assertOpen();
|
|
713
|
-
|
|
740
|
+
assertConcreteConfigKey(key);
|
|
741
|
+
const decl = resolveConfigDeclaration(this.projectConfig.config, key);
|
|
742
|
+
validateConfigValue(key, value, decl?.item);
|
|
743
|
+
// 传递当前有效声明(具体键优先于模板解析结果),
|
|
744
|
+
// 由存储统一判定整键加密并合并历史保护,禁止保护弱化
|
|
745
|
+
await (await this.prepareStorageAsync()).setConfig(key, value, decl?.item ? { declarations: [decl.item] } : undefined);
|
|
714
746
|
}
|
|
715
747
|
async deleteConfig(key) {
|
|
716
748
|
this.assertOpen();
|
|
749
|
+
assertConcreteConfigKey(key);
|
|
717
750
|
return await (await this.prepareStorageAsync()).deleteConfig(key);
|
|
718
751
|
}
|
|
719
752
|
/**
|
package/dist/platform/node.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { type ModuleLoader } from "./module-loader.js";
|
|
|
4
4
|
import { ProcessManager } from "../process/process-manager.js";
|
|
5
5
|
import type { ProcessDriver } from "../process/driver.js";
|
|
6
6
|
import { type SqliteDriver } from "../storage/index.js";
|
|
7
|
+
import type { ConfigKeyProvider } from "../security/config-cipher.js";
|
|
7
8
|
import type { EventSink } from "../runtime/events.js";
|
|
8
9
|
import type { RuntimePlatform, StorageFactory } from "./types.js";
|
|
9
10
|
/**
|
|
@@ -35,6 +36,11 @@ export interface NodePlatformOptions {
|
|
|
35
36
|
clock?: Clock;
|
|
36
37
|
/** 自定义存储工厂(默认基于 NodeSqliteDriver 构造) */
|
|
37
38
|
storage?: StorageFactory;
|
|
39
|
+
/**
|
|
40
|
+
* 显式注入的配置加密密钥提供器:优先于由有效 customHome/dataDir 派生的默认提供器,
|
|
41
|
+
* 显式注入时对内存库同样生效(供测试注入固定密钥)。
|
|
42
|
+
*/
|
|
43
|
+
configKeyProvider?: ConfigKeyProvider;
|
|
38
44
|
/** 可选注入的执行事件接收器 */
|
|
39
45
|
eventSink?: EventSink;
|
|
40
46
|
/** 可选注入的统一日志记录器 */
|
package/dist/platform/node.js
CHANGED
|
@@ -7,6 +7,7 @@ import { NodeProcessDriver } from "../process/process-driver.js";
|
|
|
7
7
|
import { ProcessManager } from "../process/process-manager.js";
|
|
8
8
|
import { NodeSqliteDriver } from "../storage/sqlite-driver.js";
|
|
9
9
|
import { resolveDatabasePath, resolveGlobalDatabasePath, SqliteRuntimeStorage, } from "../storage/index.js";
|
|
10
|
+
import { createConfigKeyProvider } from "../security/config-key.js";
|
|
10
11
|
function ensureDirectoryForDb(dbPath) {
|
|
11
12
|
if (dbPath !== ":memory:") {
|
|
12
13
|
const dir = dirname(dbPath);
|
|
@@ -72,43 +73,85 @@ export function createNodePlatform(options = {}) {
|
|
|
72
73
|
return cachedModules;
|
|
73
74
|
};
|
|
74
75
|
const createDriver = options.driverFactory ?? ((dbPath) => new NodeSqliteDriver(dbPath));
|
|
76
|
+
// - 配置加密密钥提供器按每次建库时的有效路径派生:密钥必须与数据库共享同一
|
|
77
|
+
// dataDir/customHome 域,禁止密钥落真实 home 而数据库在别处(或反向)。
|
|
78
|
+
// 提供器懒加载:仅构造平台或读取普通配置不创建 keys 目录;
|
|
79
|
+
// 内存库不注入派生提供器,由存储使用随机内存密钥,即使环境提供密钥也不触真实密钥源;
|
|
80
|
+
// 显式注入的测试提供器对内存库保留生效。
|
|
81
|
+
const resolveConfigKeyProvider = (dbPath, effectiveCustomHome, effectiveDataDir) => {
|
|
82
|
+
if (options.configKeyProvider) {
|
|
83
|
+
return options.configKeyProvider;
|
|
84
|
+
}
|
|
85
|
+
if (dbPath === ":memory:") {
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
return createConfigKeyProvider({
|
|
89
|
+
customHome: effectiveCustomHome,
|
|
90
|
+
dataDir: effectiveDataDir,
|
|
91
|
+
});
|
|
92
|
+
};
|
|
93
|
+
// - 自建驱动构造失败时释放句柄:SqliteRuntimeStorage 将注入 driver 视为外部资源,
|
|
94
|
+
// 构造抛出不会代为关闭,此处回收驱动,避免锁泄漏后原样透传错误
|
|
95
|
+
const createStorageWithDriverCleanup = (build, dbPath) => {
|
|
96
|
+
const driver = createDriver(dbPath);
|
|
97
|
+
try {
|
|
98
|
+
return build(driver);
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
try {
|
|
102
|
+
driver.close();
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
// 忽略清理阶段副异常,确保原始错误优先透传
|
|
106
|
+
}
|
|
107
|
+
throw err;
|
|
108
|
+
}
|
|
109
|
+
};
|
|
75
110
|
const storage = options.storage ?? {
|
|
76
111
|
createStorage(packageId, opts) {
|
|
112
|
+
// 显式 opts 中的 undefined 不得覆盖平台级路径:密钥与数据库必须解析同一有效路径
|
|
113
|
+
const effectiveCustomHome = opts?.customHome ?? options.customHome;
|
|
114
|
+
const effectiveDataDir = opts?.dataDir ?? options.dataDir;
|
|
77
115
|
const mergedOpts = {
|
|
78
|
-
customHome:
|
|
79
|
-
dataDir:
|
|
80
|
-
|
|
116
|
+
customHome: effectiveCustomHome,
|
|
117
|
+
dataDir: effectiveDataDir,
|
|
118
|
+
inMemory: opts?.inMemory,
|
|
119
|
+
projectRoot: opts?.projectRoot,
|
|
81
120
|
};
|
|
82
121
|
const dbPath = resolveDatabasePath(packageId, mergedOpts);
|
|
83
122
|
ensureDirectoryForDb(dbPath);
|
|
84
|
-
|
|
123
|
+
const configKeyProvider = resolveConfigKeyProvider(dbPath, effectiveCustomHome, effectiveDataDir);
|
|
124
|
+
return createStorageWithDriverCleanup((driver) => new SqliteRuntimeStorage({
|
|
85
125
|
dbPath,
|
|
86
126
|
packageId,
|
|
87
127
|
clock,
|
|
88
|
-
driver
|
|
128
|
+
driver,
|
|
89
129
|
recoverOrphans: opts?.recoverOrphans === true,
|
|
90
130
|
retentionPolicy: opts?.retentionPolicy,
|
|
91
131
|
logger: options.logger,
|
|
92
|
-
|
|
132
|
+
...(configKeyProvider ? { configKeyProvider } : {}),
|
|
133
|
+
...(opts?.configDeclarations?.length ? { configDeclarations: opts.configDeclarations } : {}),
|
|
134
|
+
}), dbPath);
|
|
93
135
|
},
|
|
94
136
|
createGlobalStorage(opts) {
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
};
|
|
100
|
-
const dbPath = mergedOpts.inMemory
|
|
137
|
+
const effectiveCustomHome = opts?.customHome ?? options.customHome;
|
|
138
|
+
const effectiveDataDir = opts?.dataDir ?? options.dataDir;
|
|
139
|
+
const inMemory = Boolean(opts?.inMemory);
|
|
140
|
+
const dbPath = inMemory
|
|
101
141
|
? ":memory:"
|
|
102
|
-
: resolveGlobalDatabasePath({ dataDir:
|
|
142
|
+
: resolveGlobalDatabasePath({ dataDir: effectiveDataDir, customHome: effectiveCustomHome });
|
|
103
143
|
ensureDirectoryForDb(dbPath);
|
|
104
|
-
|
|
144
|
+
const configKeyProvider = resolveConfigKeyProvider(dbPath, effectiveCustomHome, effectiveDataDir);
|
|
145
|
+
return createStorageWithDriverCleanup((driver) => new SqliteRuntimeStorage({
|
|
105
146
|
dbPath,
|
|
106
147
|
packageId: "__global__",
|
|
107
148
|
clock,
|
|
108
|
-
driver
|
|
149
|
+
driver,
|
|
109
150
|
recoverOrphans: opts?.recoverOrphans === true,
|
|
110
151
|
logger: options.logger,
|
|
111
|
-
|
|
152
|
+
...(configKeyProvider ? { configKeyProvider } : {}),
|
|
153
|
+
...(opts?.configDeclarations?.length ? { configDeclarations: opts.configDeclarations } : {}),
|
|
154
|
+
}), dbPath);
|
|
112
155
|
},
|
|
113
156
|
};
|
|
114
157
|
const platform = {
|
package/dist/platform/types.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import type { ProcessAPI } from "@actiondock/sdk";
|
|
1
|
+
import type { ActionInvokeOptions, ProcessAPI } from "@actiondock/sdk";
|
|
2
2
|
import type { Clock } from "../storage/clock.js";
|
|
3
3
|
import type { ModuleLoader } from "./module-loader.js";
|
|
4
4
|
import type { RunsRetentionPolicy, RuntimeStorage } from "../storage/types.js";
|
|
5
5
|
import type { EventSink } from "../runtime/events.js";
|
|
6
|
+
import type { PackageRuntime } from "../package/types.js";
|
|
7
|
+
import type { ConfigItemDefinition } from "../project/types.js";
|
|
6
8
|
/**
|
|
7
9
|
* 跨运行时持久化存储工厂配置选项。
|
|
8
10
|
*/
|
|
@@ -18,6 +20,11 @@ export interface StorageFactoryOptions {
|
|
|
18
20
|
recoverOrphans?: boolean;
|
|
19
21
|
/** 运行记录保留策略配置 */
|
|
20
22
|
retentionPolicy?: RunsRetentionPolicy;
|
|
23
|
+
/**
|
|
24
|
+
* 供旧版本数据库迁移判定的配置声明字典集合(包级存储传当前包声明)。
|
|
25
|
+
* 仅在库需要迁移时被读取;版本迁移只在首次打开执行。
|
|
26
|
+
*/
|
|
27
|
+
configDeclarations?: readonly Record<string, ConfigItemDefinition>[];
|
|
21
28
|
}
|
|
22
29
|
/**
|
|
23
30
|
* 跨运行时全局存储工厂配置选项。
|
|
@@ -28,6 +35,11 @@ export interface GlobalStorageFactoryOptions {
|
|
|
28
35
|
customHome?: string;
|
|
29
36
|
/** 是否以持有者身份打开并收割遗留非终态运行记录(默认 false,旁观语义) */
|
|
30
37
|
recoverOrphans?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* 供旧版本全局库迁移判定的配置声明字典集合(通常为所有已加载包的声明并集)。
|
|
40
|
+
* 仅在库需要迁移时被读取;版本迁移只在首次打开执行。
|
|
41
|
+
*/
|
|
42
|
+
configDeclarations?: readonly Record<string, ConfigItemDefinition>[];
|
|
31
43
|
}
|
|
32
44
|
/**
|
|
33
45
|
* 跨运行时持久化存储工厂契约。
|
|
@@ -42,6 +54,48 @@ export interface StorageFactory {
|
|
|
42
54
|
*/
|
|
43
55
|
createGlobalStorage(options?: GlobalStorageFactoryOptions): RuntimeStorage;
|
|
44
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* 动作调用目标解析结果。
|
|
59
|
+
*/
|
|
60
|
+
export interface InvocationTargetResolution {
|
|
61
|
+
/** 目标 PackageRuntime 实例 */
|
|
62
|
+
readonly runtime: PackageRuntime;
|
|
63
|
+
/** 可选调用作用域,用于区分调用目标与环路死锁检测身份 */
|
|
64
|
+
readonly scope?: string;
|
|
65
|
+
/** 是否强制要求调用方显式声明 uses 依赖 */
|
|
66
|
+
readonly requiresExplicitUses?: boolean;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* 动作调用发起方元数据信息。
|
|
70
|
+
*/
|
|
71
|
+
export interface InvocationCallerInfo {
|
|
72
|
+
/** 调用发起方包标识 */
|
|
73
|
+
readonly packageId: string;
|
|
74
|
+
/** 调用发起方 Action 动作标识 */
|
|
75
|
+
readonly actionId?: string;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* 运行时平台调用目标解析器端口契约。
|
|
79
|
+
* 允许底层运行时平台在 Host 选择执行目标阶段介入目标解析,提供自定义 PackageRuntime。
|
|
80
|
+
*/
|
|
81
|
+
export interface InvocationTargetResolver {
|
|
82
|
+
/**
|
|
83
|
+
* 解析指定 Action 引用与调用选项对应的目标 PackageRuntime。
|
|
84
|
+
*
|
|
85
|
+
* @param action 规范化 Action 引用元数据
|
|
86
|
+
* @param options 动作调用选项(包含命名 binding 等)
|
|
87
|
+
* @param caller 发起调用的调用方元数据
|
|
88
|
+
* @returns 目标解析结果;返回的 Runtime 由 Host 接管生命周期;未命中返回 undefined 交由默认主链处理
|
|
89
|
+
*/
|
|
90
|
+
resolve(action: {
|
|
91
|
+
packageId: string;
|
|
92
|
+
actionId: string;
|
|
93
|
+
}, options: ActionInvokeOptions | undefined, caller: InvocationCallerInfo): InvocationTargetResolution | undefined;
|
|
94
|
+
/**
|
|
95
|
+
* 清理端口缓存和附属资源,不重复关闭已移交 Host 的 Runtime。
|
|
96
|
+
*/
|
|
97
|
+
close?(): Promise<void>;
|
|
98
|
+
}
|
|
45
99
|
/**
|
|
46
100
|
* 运行时底层环境核心标准契约。
|
|
47
101
|
* 提供统一的运行时契约,屏蔽宿主平台与测试沙箱环境的实现差异。
|
|
@@ -61,4 +115,8 @@ export interface RuntimePlatform {
|
|
|
61
115
|
* 可选执行事件接收器,宿主可注入,缺省由上层默认构造。
|
|
62
116
|
*/
|
|
63
117
|
readonly eventSink?: EventSink;
|
|
118
|
+
/**
|
|
119
|
+
* 可选动作调用目标解析器端口,用于宿主环境自定义动作调用路由(例如测试具名 Mock 模拟目标)。
|
|
120
|
+
*/
|
|
121
|
+
readonly invocationTargets?: InvocationTargetResolver;
|
|
64
122
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ProcessDriver } from "./driver.js";
|
|
2
|
+
/**
|
|
3
|
+
* 工程工具命令执行配置选项。
|
|
4
|
+
*/
|
|
5
|
+
export interface ExecuteCommandOptions {
|
|
6
|
+
cwd?: string;
|
|
7
|
+
env?: Record<string, string | undefined>;
|
|
8
|
+
signal?: AbortSignal;
|
|
9
|
+
timeoutMs?: number;
|
|
10
|
+
maxOutputBytes?: number;
|
|
11
|
+
onOutput?: (stream: "stdout" | "stderr", text: string) => void;
|
|
12
|
+
driver?: ProcessDriver;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* 工程工具命令执行结果。
|
|
16
|
+
*/
|
|
17
|
+
export interface CommandExecutionResult {
|
|
18
|
+
status: number | null;
|
|
19
|
+
signal: string | null;
|
|
20
|
+
stdout: string;
|
|
21
|
+
stderr: string;
|
|
22
|
+
truncated: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* 面向工程工具的一次性命令适配执行器。
|
|
26
|
+
*
|
|
27
|
+
* 核心设计契约:
|
|
28
|
+
* - 复用底层 ProcessDriver 平台驱动,严格保持进程组隔离与进程树收敛能力;
|
|
29
|
+
* - 绝不启用系统 Shell,参数列表原样透传,杜绝命令注入与参数转义漏洞;
|
|
30
|
+
* - 默认每流上限 512KiB 字节有界捕获,超出上限继续排空或转发并置 truncated 标志;
|
|
31
|
+
* - 捕获字节独立深拷贝,脱离原始底层缓冲区以防内存滞留与复用篡改;
|
|
32
|
+
* - 仅当显式指定 onOutput 时流式转发,严格保证跨分块 UTF-8 字符解码完整性;
|
|
33
|
+
* - 规范化取消、超时与异常收敛:等待 driver.terminate 与 outputClosed 终态后抛出结构化 ProcessError。
|
|
34
|
+
*/
|
|
35
|
+
export declare function executeCommand(executable: string, args: readonly string[], options?: ExecuteCommandOptions): Promise<CommandExecutionResult>;
|