@actiondock/core 2.19.0 → 2.20.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 +3 -1
- package/dist/errors.js +2 -0
- package/dist/execution/service.js +8 -5
- package/dist/execution/types.d.ts +3 -3
- package/dist/host/host.d.ts +9 -1
- package/dist/host/host.js +183 -38
- package/dist/host/types.d.ts +3 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.js +1 -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 +2 -0
- package/dist/invocation/types.js +1 -0
- package/dist/package/index.d.ts +1 -1
- package/dist/package/runtime.js +31 -12
- package/dist/platform/types.d.ts +48 -1
- package/dist/project/config-declarations.d.ts +61 -0
- package/dist/project/config-declarations.js +297 -0
- package/dist/project/index.d.ts +5 -2
- package/dist/project/index.js +5 -2
- package/dist/project/init.js +2 -2
- package/dist/project/loader.js +4 -0
- package/dist/project/manifest.js +10 -0
- package/dist/project/types.d.ts +30 -0
- package/dist/runtime/context.d.ts +6 -3
- package/dist/runtime/context.js +60 -13
- package/dist/runtime/env.js +15 -1
- 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/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 +65 -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 +1 -0
- package/dist/service/remote.js +14 -29
- package/dist/service/types.d.ts +20 -5
- package/dist/service/types.js +8 -0
- package/dist/storage/mask.d.ts +33 -6
- package/dist/storage/mask.js +298 -16
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
package/dist/host/host.js
CHANGED
|
@@ -8,16 +8,20 @@ import { hasPendingTransactions, isProjectLockHeld, recoverPendingTransactions }
|
|
|
8
8
|
import { listLinkedPackages } from "../registry/registry.js";
|
|
9
9
|
import { InMemoryEventSink } from "../runtime/events.js";
|
|
10
10
|
import { snapshotRunOrigin } from "../runtime/run-origin.js";
|
|
11
|
-
import { ActionDockError, ACTION_NOT_FOUND, ACTION_PACKAGE_VERSION_CONFLICT, ACTION_SUBRUN_LIMIT, EXECUTION_FAILED, INVALID_ACTION_REF, PACKAGE_ID_CONFLICT, PACKAGE_NOT_FOUND, PROJECT_BUSY, PROJECT_RECOVERY_REQUIRED, SERVICE_CLOSED, UNDECLARED_ACTION_DEPENDENCY, } from "../errors.js";
|
|
11
|
+
import { ActionDockError, ACTION_CANCELLED, ACTION_NOT_FOUND, ACTION_PACKAGE_VERSION_CONFLICT, ACTION_SUBRUN_LIMIT, EXECUTION_FAILED, INVALID_ACTION_REF, PACKAGE_ID_CONFLICT, PACKAGE_NOT_FOUND, PROJECT_BUSY, PROJECT_RECOVERY_REQUIRED, SERVICE_CLOSED, UNDECLARED_ACTION_DEPENDENCY, } from "../errors.js";
|
|
12
12
|
import { InvocationPolicy } from "../invocation/policy.js";
|
|
13
|
+
import { loadActionBindings, resolveActionBinding, validateActionBindings, } from "../invocation/bindings.js";
|
|
14
|
+
import { RemoteInvocationExecutor } from "../invocation/remote.js";
|
|
15
|
+
import { resolveTarget } from "../profile/manager.js";
|
|
13
16
|
import { createAbortError } from "../ipc/service.js";
|
|
14
17
|
import { DataDirLock } from "../storage/data-dir-lock.js";
|
|
15
18
|
import { DefaultActionCatalog, DefaultPackageGraph, PackageGraphBuilder, resolveAction, } from "../catalog/index.js";
|
|
16
19
|
import { parseActionRef } from "../catalog/resolve-action.js";
|
|
17
20
|
import { buildRuntimeError, collectPackageInfos, describeActionAcrossRuntimes, describeVisiblePlaybook, isRootCallVisible, listVisiblePlaybooks, packageNotFoundMessage, parseRefLoose, resolveProjectRoot, } from "./routing.js";
|
|
18
21
|
import { CAPABILITY_UNAVAILABLE } from "../errors.js";
|
|
19
|
-
import { createGlobalStorage,
|
|
22
|
+
import { createGlobalStorage, redactConfigValueAtPaths, redactConfigValueForDeclarations } from "../storage/index.js";
|
|
20
23
|
import { filterByIntent } from "../utils/intent.js";
|
|
24
|
+
import { assertConcreteConfigKey, isConfigTemplate, resolveConfigDeclaration, validateConfigValue, } from "../project/config-declarations.js";
|
|
21
25
|
function isPackageRuntime(item) {
|
|
22
26
|
return (typeof item === "object" &&
|
|
23
27
|
item !== null &&
|
|
@@ -60,6 +64,8 @@ export class DefaultActionDockHost {
|
|
|
60
64
|
hostSessionId;
|
|
61
65
|
options;
|
|
62
66
|
runtimes = new Map();
|
|
67
|
+
extraRuntimes = new Set();
|
|
68
|
+
extraRuntimeScopes = new Map();
|
|
63
69
|
policy;
|
|
64
70
|
hostPublicPackageIds = new Set();
|
|
65
71
|
maxCallDepth;
|
|
@@ -76,6 +82,9 @@ export class DefaultActionDockHost {
|
|
|
76
82
|
globalStorage;
|
|
77
83
|
initPromise;
|
|
78
84
|
isInitialized = false;
|
|
85
|
+
actionBindings = new Map();
|
|
86
|
+
remoteTargets = new Map();
|
|
87
|
+
remoteInvoker;
|
|
79
88
|
discovery;
|
|
80
89
|
execution;
|
|
81
90
|
runs;
|
|
@@ -100,6 +109,7 @@ export class DefaultActionDockHost {
|
|
|
100
109
|
}
|
|
101
110
|
this.hostSessionId = randomUUID();
|
|
102
111
|
this.options = options;
|
|
112
|
+
this.remoteInvoker = new RemoteInvocationExecutor({ logger: options.logger });
|
|
103
113
|
this.maxCallDepth = options.maxCallDepth ?? 16;
|
|
104
114
|
this.maxSubRuns = options.maxSubRuns ?? 64;
|
|
105
115
|
this.policy = new InvocationPolicy({
|
|
@@ -348,6 +358,21 @@ export class DefaultActionDockHost {
|
|
|
348
358
|
// 持有者在返回前打开共享全局存储,保留对全局库存储错误的提前发现能力
|
|
349
359
|
this.getGlobalStorage();
|
|
350
360
|
}
|
|
361
|
+
/** 返回的 Runtime 由 Host 统一接管,端口只清理自身缓存和附属资源。 */
|
|
362
|
+
async closeInvocationTargets() {
|
|
363
|
+
const extras = Array.from(this.extraRuntimes).filter((runtime) => this.runtimes.get(runtime.packageId) !== runtime);
|
|
364
|
+
this.extraRuntimes.clear();
|
|
365
|
+
this.extraRuntimeScopes.clear();
|
|
366
|
+
const results = await Promise.allSettled(extras.map((runtime) => runtime.close()));
|
|
367
|
+
const errors = results.flatMap((result) => result.status === "rejected" ? [result.reason] : []);
|
|
368
|
+
try {
|
|
369
|
+
await this.options.platform?.invocationTargets?.close?.();
|
|
370
|
+
}
|
|
371
|
+
catch (error) {
|
|
372
|
+
errors.push(error);
|
|
373
|
+
}
|
|
374
|
+
return errors;
|
|
375
|
+
}
|
|
351
376
|
/**
|
|
352
377
|
* 异步安全回滚初始化失败时所占用的资源。
|
|
353
378
|
*/
|
|
@@ -363,7 +388,11 @@ export class DefaultActionDockHost {
|
|
|
363
388
|
// 忽略 Runtime 关闭异常
|
|
364
389
|
}
|
|
365
390
|
}));
|
|
391
|
+
const invocationCloseErrors = await this.closeInvocationTargets();
|
|
366
392
|
this.runtimes.clear();
|
|
393
|
+
this.actionBindings.clear();
|
|
394
|
+
this.remoteTargets.clear();
|
|
395
|
+
await this.remoteInvoker.close();
|
|
367
396
|
try {
|
|
368
397
|
this.globalStorage?.close();
|
|
369
398
|
}
|
|
@@ -379,6 +408,8 @@ export class DefaultActionDockHost {
|
|
|
379
408
|
}
|
|
380
409
|
this.dataDirLock = undefined;
|
|
381
410
|
this.isClosed = true;
|
|
411
|
+
if (invocationCloseErrors.length)
|
|
412
|
+
throw new AggregateError(invocationCloseErrors, "Invocation target cleanup failed");
|
|
382
413
|
}
|
|
383
414
|
/**
|
|
384
415
|
* 阶段函数:注册显式传入的 packages 列表(PackageRuntimeOptions 配置或包目录物理路径)。
|
|
@@ -551,21 +582,75 @@ export class DefaultActionDockHost {
|
|
|
551
582
|
* 铁律 2:跨包调用改走 ActionInvoker 回到 Host 执行主链,经由唯一的 InvocationPolicy 授权后调用目标 Package 的 ExecutionService。
|
|
552
583
|
*/
|
|
553
584
|
createActionInvoker(callerRuntime) {
|
|
554
|
-
return async (childAction, childInput, context) => {
|
|
555
|
-
|
|
585
|
+
return async (childAction, childInput, context, options) => {
|
|
586
|
+
if (this.isClosed)
|
|
587
|
+
throw new ActionDockError(SERVICE_CLOSED, "ActionDockHost is closed");
|
|
588
|
+
if (context.signal.aborted)
|
|
589
|
+
throw new ActionDockError(ACTION_CANCELLED, "Caller invocation is cancelled");
|
|
590
|
+
const parsed = parseActionRef(childAction);
|
|
591
|
+
// 裸引用仍由既有解析器消歧;远端专属依赖须使用完全限定引用。
|
|
592
|
+
const localResolved = parsed.packageId ? undefined : resolveAction(childAction, {
|
|
556
593
|
caller: callerRuntime.packageId,
|
|
557
594
|
graph: this.graph,
|
|
558
595
|
catalog: this.catalog,
|
|
559
596
|
});
|
|
560
|
-
const targetPackageId =
|
|
561
|
-
const targetActionId =
|
|
562
|
-
const
|
|
563
|
-
const
|
|
564
|
-
|
|
565
|
-
|
|
597
|
+
const targetPackageId = parsed.packageId ?? localResolved.package.id;
|
|
598
|
+
const targetActionId = parsed.actionId;
|
|
599
|
+
const canonicalRef = `${targetPackageId}/${targetActionId}`;
|
|
600
|
+
const canonicalActionRef = { packageId: targetPackageId, actionId: targetActionId };
|
|
601
|
+
const callerBindings = this.actionBindings.get(callerRuntime.packageId) ?? {};
|
|
602
|
+
const isNamedTarget = Boolean(options?.binding && options.binding !== "default");
|
|
603
|
+
// 目标装配是同步解析,不在此引入另一条执行或网络调用链。
|
|
604
|
+
const targetOverride = this.options.platform?.invocationTargets?.resolve(canonicalActionRef, options, {
|
|
605
|
+
packageId: callerRuntime.packageId,
|
|
606
|
+
actionId: context.caller?.actionId,
|
|
607
|
+
});
|
|
608
|
+
let targetRuntime;
|
|
609
|
+
let targetScope;
|
|
610
|
+
let isRemote = false;
|
|
611
|
+
let remoteProfile;
|
|
612
|
+
if (targetOverride) {
|
|
613
|
+
if (targetOverride.runtime.packageId !== targetPackageId) {
|
|
614
|
+
throw new ActionDockError(INVALID_ACTION_REF, `Invocation target packageId mismatch: expected '${targetPackageId}', got '${targetOverride.runtime.packageId}'`);
|
|
615
|
+
}
|
|
616
|
+
targetRuntime = targetOverride.runtime;
|
|
617
|
+
this.extraRuntimes.add(targetRuntime);
|
|
618
|
+
this.bindRuntime(targetRuntime);
|
|
619
|
+
targetScope = targetOverride.scope ?? (isNamedTarget ? `binding:${options?.binding}` : undefined);
|
|
620
|
+
if (targetScope)
|
|
621
|
+
this.extraRuntimeScopes.set(targetRuntime, targetScope);
|
|
622
|
+
}
|
|
623
|
+
else {
|
|
624
|
+
// 没有绑定的旧调用不引入额外的清单命名约束,保持编程式 Runtime 兼容。
|
|
625
|
+
const binding = options?.binding !== undefined || Object.hasOwn(callerBindings, canonicalRef)
|
|
626
|
+
? resolveActionBinding(callerBindings, canonicalRef, options?.binding)
|
|
627
|
+
: undefined;
|
|
628
|
+
if (binding?.type === "remote") {
|
|
629
|
+
isRemote = true;
|
|
630
|
+
remoteProfile = binding.profile;
|
|
631
|
+
targetScope = `profile:${binding.profile}`;
|
|
632
|
+
}
|
|
633
|
+
else {
|
|
634
|
+
isRemote = false;
|
|
635
|
+
if (!localResolved) {
|
|
636
|
+
resolveAction(childAction, { caller: callerRuntime.packageId, graph: this.graph, catalog: this.catalog });
|
|
637
|
+
}
|
|
638
|
+
const isLogicalSamePackage = targetPackageId === callerRuntime.packageId;
|
|
639
|
+
targetRuntime = isLogicalSamePackage ? callerRuntime : this.getRuntime(targetPackageId);
|
|
640
|
+
if (targetRuntime)
|
|
641
|
+
targetScope = this.extraRuntimeScopes.get(targetRuntime);
|
|
642
|
+
if (!targetRuntime) {
|
|
643
|
+
throw new ActionDockError(PACKAGE_NOT_FOUND, packageNotFoundMessage(targetPackageId, this.failedLinkedPackages));
|
|
644
|
+
}
|
|
645
|
+
}
|
|
566
646
|
}
|
|
647
|
+
const isLogicalSamePackage = targetPackageId === callerRuntime.packageId;
|
|
648
|
+
const isPhysicalSameRuntime = Boolean(targetRuntime && targetRuntime === callerRuntime);
|
|
649
|
+
const requiresExplicitUses = Boolean(isRemote ||
|
|
650
|
+
targetOverride?.requiresExplicitUses ||
|
|
651
|
+
(isNamedTarget && targetOverride !== undefined));
|
|
567
652
|
// 跨包 uses 依赖声明校验(统一委托 InvocationPolicy 单一事实源)
|
|
568
|
-
if (!
|
|
653
|
+
if (!isLogicalSamePackage || requiresExplicitUses) {
|
|
569
654
|
let declaredUses = context.caller?.declaredUses;
|
|
570
655
|
if (!declaredUses) {
|
|
571
656
|
try {
|
|
@@ -580,7 +665,11 @@ export class DefaultActionDockHost {
|
|
|
580
665
|
packageId: callerRuntime.packageId,
|
|
581
666
|
actionId: context.caller?.actionId || "",
|
|
582
667
|
declaredUses,
|
|
583
|
-
}, {
|
|
668
|
+
}, {
|
|
669
|
+
packageId: targetPackageId,
|
|
670
|
+
actionId: targetActionId,
|
|
671
|
+
requiresExplicitUses,
|
|
672
|
+
}, this.graph);
|
|
584
673
|
if (authErr) {
|
|
585
674
|
const hint = authErr.details?.hint;
|
|
586
675
|
const msg = hint ? `${authErr.message}\n${hint}` : authErr.message;
|
|
@@ -593,7 +682,7 @@ export class DefaultActionDockHost {
|
|
|
593
682
|
throw new ActionDockError(depthErr.code, depthErr.message, depthErr.details);
|
|
594
683
|
}
|
|
595
684
|
// 调用链环路死锁检测
|
|
596
|
-
const cycle = this.policy.checkCycle(context.callStack, targetActionId, targetPackageId, callerRuntime.packageId);
|
|
685
|
+
const cycle = this.policy.checkCycle(context.callStack, targetActionId, targetPackageId, callerRuntime.packageId, targetScope);
|
|
597
686
|
if (cycle.error) {
|
|
598
687
|
throw new ActionDockError(cycle.error.code, cycle.error.message, cycle.error.details);
|
|
599
688
|
}
|
|
@@ -608,14 +697,18 @@ export class DefaultActionDockHost {
|
|
|
608
697
|
}
|
|
609
698
|
try {
|
|
610
699
|
const nextCallStack = [...context.callStack, cycle.callKey];
|
|
700
|
+
if (isRemote) {
|
|
701
|
+
const candidate = this.catalog.find({ packageId: targetPackageId, actionId: targetActionId })[0];
|
|
702
|
+
return await this.remoteInvoker.invoke(this.remoteTargets.get(remoteProfile), { packageId: targetPackageId, actionId: targetActionId }, childInput, { ...context, callStack: nextCallStack }, { binding: options?.binding ?? "default", profile: remoteProfile }, candidate?.contract);
|
|
703
|
+
}
|
|
611
704
|
const targetOwner = context.owner
|
|
612
705
|
? {
|
|
613
706
|
tenantId: context.owner.tenantId,
|
|
614
707
|
principalId: context.owner.principalId,
|
|
615
|
-
packageInstanceId:
|
|
708
|
+
packageInstanceId: isPhysicalSameRuntime
|
|
616
709
|
? (context.owner.packageInstanceId || callerRuntime.identity.instanceId)
|
|
617
710
|
: targetRuntime.identity.instanceId,
|
|
618
|
-
generationId:
|
|
711
|
+
generationId: isPhysicalSameRuntime
|
|
619
712
|
? (context.owner.generationId || callerRuntime.identity.generation)
|
|
620
713
|
: targetRuntime.identity.generation,
|
|
621
714
|
}
|
|
@@ -626,6 +719,7 @@ export class DefaultActionDockHost {
|
|
|
626
719
|
parentRunId: context.parentRunId,
|
|
627
720
|
caller: context.caller,
|
|
628
721
|
callStack: nextCallStack,
|
|
722
|
+
targetScope,
|
|
629
723
|
package: targetRuntime.identity,
|
|
630
724
|
signal: context.signal,
|
|
631
725
|
timeoutMs: context.timeoutMs,
|
|
@@ -699,6 +793,27 @@ export class DefaultActionDockHost {
|
|
|
699
793
|
}
|
|
700
794
|
throw new ActionDockError(PACKAGE_ID_CONFLICT, `Package ID conflict: package '${runtime.packageId}' is already registered in host`);
|
|
701
795
|
}
|
|
796
|
+
const explicitBindings = this.options.actionBindings;
|
|
797
|
+
const bindings = explicitBindings && Object.hasOwn(explicitBindings, runtime.packageId)
|
|
798
|
+
? validateActionBindings(explicitBindings[runtime.packageId])
|
|
799
|
+
: runtime.packageRoot ? loadActionBindings(runtime.packageRoot) : validateActionBindings({});
|
|
800
|
+
for (const group of Object.values(bindings)) {
|
|
801
|
+
for (const target of Object.values(group)) {
|
|
802
|
+
if (target.type !== "remote" || this.remoteTargets.has(target.profile))
|
|
803
|
+
continue;
|
|
804
|
+
const resolved = resolveTarget({ profile: target.profile }, this.options.customHome);
|
|
805
|
+
if (resolved.type !== "remote" || !resolved.serverUrl) {
|
|
806
|
+
throw new ActionDockError(INVALID_ACTION_REF, `Binding profile '${target.profile}' must identify a remote service`);
|
|
807
|
+
}
|
|
808
|
+
this.remoteTargets.set(target.profile, Object.freeze({
|
|
809
|
+
serverUrl: resolved.serverUrl,
|
|
810
|
+
token: resolved.token,
|
|
811
|
+
insecure: resolved.insecure,
|
|
812
|
+
allowInsecureHttp: resolved.allowInsecureHttp,
|
|
813
|
+
}));
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
this.actionBindings.set(runtime.packageId, bindings);
|
|
702
817
|
this.runtimes.set(runtime.packageId, runtime);
|
|
703
818
|
if (isPublic) {
|
|
704
819
|
this.hostPublicPackageIds.add(runtime.packageId);
|
|
@@ -1241,17 +1356,26 @@ export class DefaultActionDockHost {
|
|
|
1241
1356
|
}
|
|
1242
1357
|
return this.globalStorage;
|
|
1243
1358
|
}
|
|
1244
|
-
|
|
1245
|
-
|
|
1359
|
+
findAllDeclaredConfigItems(key) {
|
|
1360
|
+
const items = [];
|
|
1246
1361
|
for (const runtime of this.listRuntimes()) {
|
|
1247
|
-
const
|
|
1248
|
-
if (item) {
|
|
1249
|
-
|
|
1250
|
-
return item;
|
|
1251
|
-
foundItem = item;
|
|
1362
|
+
const decl = resolveConfigDeclaration(runtime.projectConfig?.config, key);
|
|
1363
|
+
if (decl?.item) {
|
|
1364
|
+
items.push(decl.item);
|
|
1252
1365
|
}
|
|
1253
1366
|
}
|
|
1254
|
-
return
|
|
1367
|
+
return items;
|
|
1368
|
+
}
|
|
1369
|
+
protectGlobalConfigView(view) {
|
|
1370
|
+
if (view.source !== "global")
|
|
1371
|
+
return view;
|
|
1372
|
+
const items = this.findAllDeclaredConfigItems(view.key);
|
|
1373
|
+
if (items.length === 0)
|
|
1374
|
+
return view;
|
|
1375
|
+
// 外部注入的运行时可能持有独立全局库;只能加强它返回的安全值,不能换读 Host 的库。
|
|
1376
|
+
const merged = redactConfigValueForDeclarations(view.value, items);
|
|
1377
|
+
const safe = redactConfigValueAtPaths(merged.value, [...view.redactedPaths, ...merged.redactedPaths]);
|
|
1378
|
+
return { ...view, ...safe, secret: view.secret || merged.secret };
|
|
1255
1379
|
}
|
|
1256
1380
|
resolveRuntime(packageId) {
|
|
1257
1381
|
if (packageId) {
|
|
@@ -1272,25 +1396,32 @@ export class DefaultActionDockHost {
|
|
|
1272
1396
|
}
|
|
1273
1397
|
async getConfig(packageId, key) {
|
|
1274
1398
|
await this.ensureInitialized();
|
|
1399
|
+
assertConcreteConfigKey(key);
|
|
1275
1400
|
if (packageId === "global") {
|
|
1276
1401
|
const globalStorage = this.getGlobalStorage();
|
|
1277
1402
|
const val = globalStorage.getConfig(key);
|
|
1278
1403
|
const configured = val !== undefined;
|
|
1279
|
-
const
|
|
1280
|
-
const
|
|
1404
|
+
const items = this.findAllDeclaredConfigItems(key);
|
|
1405
|
+
const redacted = redactConfigValueForDeclarations(val, items);
|
|
1281
1406
|
return {
|
|
1282
1407
|
key,
|
|
1283
1408
|
configured,
|
|
1284
|
-
secret:
|
|
1285
|
-
source: configured ? "global" :
|
|
1286
|
-
value:
|
|
1409
|
+
secret: redacted.secret,
|
|
1410
|
+
source: configured ? "global" : null,
|
|
1411
|
+
value: redacted.value,
|
|
1412
|
+
redactedPaths: redacted.redactedPaths,
|
|
1287
1413
|
};
|
|
1288
1414
|
}
|
|
1289
|
-
return this.requireRuntime(packageId).getConfig(key);
|
|
1415
|
+
return this.protectGlobalConfigView(await this.requireRuntime(packageId).getConfig(key));
|
|
1290
1416
|
}
|
|
1291
1417
|
async setConfig(packageId, key, value) {
|
|
1292
1418
|
await this.ensureInitialized();
|
|
1419
|
+
assertConcreteConfigKey(key);
|
|
1293
1420
|
if (packageId === "global") {
|
|
1421
|
+
const items = this.findAllDeclaredConfigItems(key);
|
|
1422
|
+
for (const item of items) {
|
|
1423
|
+
validateConfigValue(key, value, item);
|
|
1424
|
+
}
|
|
1294
1425
|
await this.getGlobalStorage().setConfig(key, value);
|
|
1295
1426
|
return;
|
|
1296
1427
|
}
|
|
@@ -1298,6 +1429,7 @@ export class DefaultActionDockHost {
|
|
|
1298
1429
|
}
|
|
1299
1430
|
async deleteConfig(packageId, key) {
|
|
1300
1431
|
await this.ensureInitialized();
|
|
1432
|
+
assertConcreteConfigKey(key);
|
|
1301
1433
|
if (packageId === "global") {
|
|
1302
1434
|
return await this.getGlobalStorage().deleteConfig(key);
|
|
1303
1435
|
}
|
|
@@ -1308,19 +1440,26 @@ export class DefaultActionDockHost {
|
|
|
1308
1440
|
if (packageId === "global") {
|
|
1309
1441
|
const globalStorage = this.getGlobalStorage();
|
|
1310
1442
|
const all = globalStorage.listConfig();
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1443
|
+
const views = [];
|
|
1444
|
+
for (const [key, val] of Object.entries(all)) {
|
|
1445
|
+
if (isConfigTemplate(key)) {
|
|
1446
|
+
continue;
|
|
1447
|
+
}
|
|
1448
|
+
const items = this.findAllDeclaredConfigItems(key);
|
|
1449
|
+
const redacted = redactConfigValueForDeclarations(val, items);
|
|
1450
|
+
views.push({
|
|
1315
1451
|
key,
|
|
1316
1452
|
configured: true,
|
|
1317
|
-
secret:
|
|
1453
|
+
secret: redacted.secret,
|
|
1318
1454
|
source: "global",
|
|
1319
|
-
value:
|
|
1320
|
-
|
|
1321
|
-
|
|
1455
|
+
value: redacted.value,
|
|
1456
|
+
redactedPaths: redacted.redactedPaths,
|
|
1457
|
+
});
|
|
1458
|
+
}
|
|
1459
|
+
return views;
|
|
1322
1460
|
}
|
|
1323
|
-
|
|
1461
|
+
const views = await this.requireRuntime(packageId).listConfig();
|
|
1462
|
+
return views.map((view) => this.protectGlobalConfigView(view));
|
|
1324
1463
|
}
|
|
1325
1464
|
async getState(packageId, actionId, key, options) {
|
|
1326
1465
|
await this.ensureInitialized();
|
|
@@ -1377,7 +1516,11 @@ export class DefaultActionDockHost {
|
|
|
1377
1516
|
// 忽略 Runtime 关闭异常,确保全部安全释放
|
|
1378
1517
|
}
|
|
1379
1518
|
}));
|
|
1519
|
+
const invocationCloseErrors = await this.closeInvocationTargets();
|
|
1380
1520
|
this.runtimes.clear();
|
|
1521
|
+
this.actionBindings.clear();
|
|
1522
|
+
this.remoteTargets.clear();
|
|
1523
|
+
await this.remoteInvoker.close();
|
|
1381
1524
|
try {
|
|
1382
1525
|
this.globalStorage?.close();
|
|
1383
1526
|
}
|
|
@@ -1392,6 +1535,8 @@ export class DefaultActionDockHost {
|
|
|
1392
1535
|
// 忽略目录排他锁释放异常
|
|
1393
1536
|
}
|
|
1394
1537
|
this.dataDirLock = undefined;
|
|
1538
|
+
if (invocationCloseErrors.length)
|
|
1539
|
+
throw new AggregateError(invocationCloseErrors, "Invocation target cleanup failed");
|
|
1395
1540
|
}
|
|
1396
1541
|
}
|
|
1397
1542
|
/**
|
package/dist/host/types.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ import type { EventSink } from "../runtime/events.js";
|
|
|
7
7
|
import type { RuntimePlatform } from "../platform/types.js";
|
|
8
8
|
import type { ActionDockService, ConfigValueView, EventsPort, ListRunsOptions, StateScopeOptions } from "../service/types.js";
|
|
9
9
|
import type { StateEntry } from "../storage/types.js";
|
|
10
|
+
import type { ActionBindings } from "../invocation/bindings.js";
|
|
10
11
|
/**
|
|
11
12
|
* 宿主事件服务端口(既作为独立方法调用,又满足 EventsPort 规范)。
|
|
12
13
|
*/
|
|
@@ -21,6 +22,8 @@ export interface HostEventsPort extends EventsPort {
|
|
|
21
22
|
* ActionDock 宿主容器初始化配置选项。
|
|
22
23
|
*/
|
|
23
24
|
export interface ActionDockHostOptions {
|
|
25
|
+
/** 按调用方包覆盖运行时命名绑定;未覆盖的包读取其 .actiondock/bindings.json。 */
|
|
26
|
+
actionBindings?: Readonly<Record<string, ActionBindings>>;
|
|
24
27
|
/** 显式预注册的包列表(PackageRuntime 实例、PackageRuntimeOptions 配置或包目录物理路径)。Host 统一管理其生命周期,关闭时统一释放。 */
|
|
25
28
|
packages?: Array<PackageRuntime | PackageRuntimeOptions | string>;
|
|
26
29
|
/** 当前工程根目录绝对物理路径 */
|
package/dist/index.d.ts
CHANGED
|
@@ -7,15 +7,16 @@
|
|
|
7
7
|
*/
|
|
8
8
|
export { ACTIONDOCK_VERSION } from "./version.js";
|
|
9
9
|
export { createActionDock, connectActionDock, } from "./service/factory.js";
|
|
10
|
-
export type { ActionDockService, ActionDockService as ActionDock, DiscoveryPort, ExecutionPort, RunsPort, EventsPort, RunEventSubscriptionOptions, ConfigPort, StatePort, CreateActionDockOptions, ConnectActionDockOptions, RemoteServiceOptions, ConfigValueView, ListRunsOptions, RunReadOptions, StateScopeOptions, } from "./service/types.js";
|
|
10
|
+
export type { ActionDockService, ActionDockService as ActionDock, DiscoveryPort, ExecutionPort, RunsPort, EventsPort, RunEventSubscriptionOptions, ConfigPort, StatePort, CreateActionDockOptions, ConnectActionDockOptions, RemoteServiceOptions, ConfigValueView, ConfigSource, ListRunsOptions, RunReadOptions, StateScopeOptions, } from "./service/types.js";
|
|
11
11
|
export { isTerminalRunStatus, DEFAULT_RUNS_RETENTION_MS, DEFAULT_MAX_RUNS_PER_PACKAGE, DEFAULT_MIN_RETAIN_RUNS, } from "./storage/types.js";
|
|
12
12
|
export { isRunHostDead } from "./storage/run-liveness.js";
|
|
13
13
|
export type { TerminalRunStatus } from "./storage/types.js";
|
|
14
14
|
export { parseDuration } from "./utils/index.js";
|
|
15
15
|
export { toSnakeUpperCase, resolveEnvValue } from "./runtime/env.js";
|
|
16
16
|
export type { ResolvedEnv } from "./runtime/env.js";
|
|
17
|
-
export type { ActionRef, ResolvedActionRef, ExecutionResult, RunRecord, RunOrigin, ExecutionEvent, } from "@actiondock/sdk";
|
|
17
|
+
export type { ActionInvokeOptions, ActionRef, ResolvedActionRef, ExecutionResult, RunRecord, RunOrigin, ExecutionEvent, } from "@actiondock/sdk";
|
|
18
18
|
export type { RunOptions, ExecutionTicket, CancelResult, } from "./execution/types.js";
|
|
19
|
+
export type { ActionBindings, ActionBindingTarget } from "./invocation/bindings.js";
|
|
19
20
|
export type { ActionSpec, ActionSummary, PlaybookSpec, PlaybookSummary, PackageInfo, ListActionsOptions, } from "./package/types.js";
|
|
20
21
|
export { createNodePlatform, } from "./platform/node.js";
|
|
21
22
|
export { startActionDockServer, } from "./server/server.js";
|
|
@@ -24,4 +25,4 @@ export { initProject } from "./project/init.js";
|
|
|
24
25
|
export { loadProjectConfig, findProjectRoot, } from "./project/loader.js";
|
|
25
26
|
export type { ProjectConfig, } from "./project/types.js";
|
|
26
27
|
export type { PackageGraph, } from "./catalog/graph.js";
|
|
27
|
-
export { ActionDockError, ProcessError, PACKAGE_NOT_FOUND, ACTION_PACKAGE_VERSION_CONFLICT, ACTION_NOT_FOUND, ACTION_LOAD_FAILED, ACTION_FAILED, ACTION_TIMEOUT, ACTION_CANCELLED, INPUT_VALIDATION_FAILED, OUTPUT_VALIDATION_FAILED, INPUT_NOT_JSON, OUTPUT_NOT_JSON, ACTION_SUBRUN_LIMIT, ACTION_CALL_CYCLE, UNDECLARED_ACTION_DEPENDENCY, INVALID_ACTION_REF, IDEMPOTENCY_CONFLICT, EXECUTION_FAILED, UNHANDLED_EXECUTION_ERROR, RUN_REPOSITORY_UNAVAILABLE, RUN_PERSISTENCE_FAILED, STANDALONE_ASYNC_UNSUPPORTED, HOST_PROCESS_EXITED, EXECUTION_ABORTED, TIMEOUT, NETWORK_ERROR, CAPABILITY_UNAVAILABLE, STATE_KEY_NOT_FOUND, STORAGE_BUSY, PROJECT_BUSY, PROJECT_RECOVERY_REQUIRED, EVENT_BACKPRESSURE_LIMIT, EVENT_CURSOR_EXPIRED, PROCESS_OUTPUT_LIMIT, PROCESS_SPAWN_ERROR, PROCESS_CANCELLED, PROCESS_TIMEOUT, UNAUTHORIZED, NOT_FOUND, SERVER_ERROR, PACKAGE_FORBIDDEN, ACTION_FORBIDDEN, PLAYBOOK_NOT_FOUND, REQUEST_TOO_LARGE, ACTION_START_FAILED, ACTION_EXECUTION_ERROR, DATA_DIR_IN_USE, DATA_DIR_RECOVERY_REQUIRED, PROCESS_FAILED, MCP_TOOL_NAME_COLLISION, ACCESS_DENIED, INVALID_FLAT_ARGUMENT, INVALID_JSON, INVALID_JSON_LITERAL, INPUT_PATH_CONFLICT, FLAT_INPUT_LIMIT_EXCEEDED, INPUT_LIMIT_EXCEEDED, INPUT_POLICY_VIOLATION, INPUT_CONFLICT, INPUT_FILE_NOT_FOUND, INPUT_FILE_READ_FAILED, INVALID_ARGUMENT, PACKAGE_NOT_ALLOWED, INVALID_PACKAGE_ID, PATH_TRAVERSAL, AMBIGUOUS_STATE_KEY, RUN_NOT_FOUND, RUN_ALREADY_FINISHED, PROJECT_ROOT_NOT_FOUND, describeActionLoadFailure, createErrorEnvelope, resolveExecutionHint, } from "./errors.js";
|
|
28
|
+
export { ActionDockError, ProcessError, PACKAGE_NOT_FOUND, ACTION_PACKAGE_VERSION_CONFLICT, ACTION_NOT_FOUND, ACTION_LOAD_FAILED, ACTION_FAILED, ACTION_TIMEOUT, ACTION_CANCELLED, CONFIG_VALUE_INVALID, INPUT_VALIDATION_FAILED, OUTPUT_VALIDATION_FAILED, INPUT_NOT_JSON, OUTPUT_NOT_JSON, ACTION_SUBRUN_LIMIT, ACTION_CALL_CYCLE, UNDECLARED_ACTION_DEPENDENCY, INVALID_ACTION_REF, IDEMPOTENCY_CONFLICT, EXECUTION_FAILED, UNHANDLED_EXECUTION_ERROR, RUN_REPOSITORY_UNAVAILABLE, RUN_PERSISTENCE_FAILED, STANDALONE_ASYNC_UNSUPPORTED, HOST_PROCESS_EXITED, EXECUTION_ABORTED, TIMEOUT, NETWORK_ERROR, CAPABILITY_UNAVAILABLE, STATE_KEY_NOT_FOUND, STORAGE_BUSY, PROJECT_BUSY, PROJECT_RECOVERY_REQUIRED, EVENT_BACKPRESSURE_LIMIT, EVENT_CURSOR_EXPIRED, PROCESS_OUTPUT_LIMIT, PROCESS_SPAWN_ERROR, PROCESS_CANCELLED, PROCESS_TIMEOUT, UNAUTHORIZED, NOT_FOUND, SERVER_ERROR, PACKAGE_FORBIDDEN, ACTION_FORBIDDEN, PLAYBOOK_NOT_FOUND, REQUEST_TOO_LARGE, ACTION_START_FAILED, ACTION_EXECUTION_ERROR, DATA_DIR_IN_USE, DATA_DIR_RECOVERY_REQUIRED, PROCESS_FAILED, MCP_TOOL_NAME_COLLISION, ACCESS_DENIED, INVALID_FLAT_ARGUMENT, INVALID_JSON, INVALID_JSON_LITERAL, INPUT_PATH_CONFLICT, FLAT_INPUT_LIMIT_EXCEEDED, INPUT_LIMIT_EXCEEDED, INPUT_POLICY_VIOLATION, INPUT_CONFLICT, INPUT_FILE_NOT_FOUND, INPUT_FILE_READ_FAILED, INVALID_ARGUMENT, PACKAGE_NOT_ALLOWED, INVALID_PACKAGE_ID, PATH_TRAVERSAL, AMBIGUOUS_STATE_KEY, RUN_NOT_FOUND, RUN_ALREADY_FINISHED, PROJECT_ROOT_NOT_FOUND, describeActionLoadFailure, createErrorEnvelope, resolveExecutionHint, } from "./errors.js";
|
package/dist/index.js
CHANGED
|
@@ -20,4 +20,4 @@ export { startActionDockServer, } from "./server/server.js";
|
|
|
20
20
|
export { initProject } from "./project/init.js";
|
|
21
21
|
export { loadProjectConfig, findProjectRoot, } from "./project/loader.js";
|
|
22
22
|
// 8. 统一错误模型与核心标准错误码常量
|
|
23
|
-
export { ActionDockError, ProcessError, PACKAGE_NOT_FOUND, ACTION_PACKAGE_VERSION_CONFLICT, ACTION_NOT_FOUND, ACTION_LOAD_FAILED, ACTION_FAILED, ACTION_TIMEOUT, ACTION_CANCELLED, INPUT_VALIDATION_FAILED, OUTPUT_VALIDATION_FAILED, INPUT_NOT_JSON, OUTPUT_NOT_JSON, ACTION_SUBRUN_LIMIT, ACTION_CALL_CYCLE, UNDECLARED_ACTION_DEPENDENCY, INVALID_ACTION_REF, IDEMPOTENCY_CONFLICT, EXECUTION_FAILED, UNHANDLED_EXECUTION_ERROR, RUN_REPOSITORY_UNAVAILABLE, RUN_PERSISTENCE_FAILED, STANDALONE_ASYNC_UNSUPPORTED, HOST_PROCESS_EXITED, EXECUTION_ABORTED, TIMEOUT, NETWORK_ERROR, CAPABILITY_UNAVAILABLE, STATE_KEY_NOT_FOUND, STORAGE_BUSY, PROJECT_BUSY, PROJECT_RECOVERY_REQUIRED, EVENT_BACKPRESSURE_LIMIT, EVENT_CURSOR_EXPIRED, PROCESS_OUTPUT_LIMIT, PROCESS_SPAWN_ERROR, PROCESS_CANCELLED, PROCESS_TIMEOUT, UNAUTHORIZED, NOT_FOUND, SERVER_ERROR, PACKAGE_FORBIDDEN, ACTION_FORBIDDEN, PLAYBOOK_NOT_FOUND, REQUEST_TOO_LARGE, ACTION_START_FAILED, ACTION_EXECUTION_ERROR, DATA_DIR_IN_USE, DATA_DIR_RECOVERY_REQUIRED, PROCESS_FAILED, MCP_TOOL_NAME_COLLISION, ACCESS_DENIED, INVALID_FLAT_ARGUMENT, INVALID_JSON, INVALID_JSON_LITERAL, INPUT_PATH_CONFLICT, FLAT_INPUT_LIMIT_EXCEEDED, INPUT_LIMIT_EXCEEDED, INPUT_POLICY_VIOLATION, INPUT_CONFLICT, INPUT_FILE_NOT_FOUND, INPUT_FILE_READ_FAILED, INVALID_ARGUMENT, PACKAGE_NOT_ALLOWED, INVALID_PACKAGE_ID, PATH_TRAVERSAL, AMBIGUOUS_STATE_KEY, RUN_NOT_FOUND, RUN_ALREADY_FINISHED, PROJECT_ROOT_NOT_FOUND, describeActionLoadFailure, createErrorEnvelope, resolveExecutionHint, } from "./errors.js";
|
|
23
|
+
export { ActionDockError, ProcessError, PACKAGE_NOT_FOUND, ACTION_PACKAGE_VERSION_CONFLICT, ACTION_NOT_FOUND, ACTION_LOAD_FAILED, ACTION_FAILED, ACTION_TIMEOUT, ACTION_CANCELLED, CONFIG_VALUE_INVALID, INPUT_VALIDATION_FAILED, OUTPUT_VALIDATION_FAILED, INPUT_NOT_JSON, OUTPUT_NOT_JSON, ACTION_SUBRUN_LIMIT, ACTION_CALL_CYCLE, UNDECLARED_ACTION_DEPENDENCY, INVALID_ACTION_REF, IDEMPOTENCY_CONFLICT, EXECUTION_FAILED, UNHANDLED_EXECUTION_ERROR, RUN_REPOSITORY_UNAVAILABLE, RUN_PERSISTENCE_FAILED, STANDALONE_ASYNC_UNSUPPORTED, HOST_PROCESS_EXITED, EXECUTION_ABORTED, TIMEOUT, NETWORK_ERROR, CAPABILITY_UNAVAILABLE, STATE_KEY_NOT_FOUND, STORAGE_BUSY, PROJECT_BUSY, PROJECT_RECOVERY_REQUIRED, EVENT_BACKPRESSURE_LIMIT, EVENT_CURSOR_EXPIRED, PROCESS_OUTPUT_LIMIT, PROCESS_SPAWN_ERROR, PROCESS_CANCELLED, PROCESS_TIMEOUT, UNAUTHORIZED, NOT_FOUND, SERVER_ERROR, PACKAGE_FORBIDDEN, ACTION_FORBIDDEN, PLAYBOOK_NOT_FOUND, REQUEST_TOO_LARGE, ACTION_START_FAILED, ACTION_EXECUTION_ERROR, DATA_DIR_IN_USE, DATA_DIR_RECOVERY_REQUIRED, PROCESS_FAILED, MCP_TOOL_NAME_COLLISION, ACCESS_DENIED, INVALID_FLAT_ARGUMENT, INVALID_JSON, INVALID_JSON_LITERAL, INPUT_PATH_CONFLICT, FLAT_INPUT_LIMIT_EXCEEDED, INPUT_LIMIT_EXCEEDED, INPUT_POLICY_VIOLATION, INPUT_CONFLICT, INPUT_FILE_NOT_FOUND, INPUT_FILE_READ_FAILED, INVALID_ARGUMENT, PACKAGE_NOT_ALLOWED, INVALID_PACKAGE_ID, PATH_TRAVERSAL, AMBIGUOUS_STATE_KEY, RUN_NOT_FOUND, RUN_ALREADY_FINISHED, PROJECT_ROOT_NOT_FOUND, describeActionLoadFailure, createErrorEnvelope, resolveExecutionHint, } from "./errors.js";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ActionDockError, INVALID_ARGUMENT } from "../errors.js";
|
|
2
|
+
import { assertConcreteConfigKey } from "../project/config-declarations.js";
|
|
3
|
+
import { parseJson } from "./input-resolver.js";
|
|
4
|
+
/** 配置赋值只识别等号左侧的 :=,不物化路径,也不把解析失败回退为字符串。 */
|
|
5
|
+
export function parseConfigOverrideAssignment(pair) {
|
|
6
|
+
const equals = pair.indexOf("=");
|
|
7
|
+
if (equals < 0) {
|
|
8
|
+
throw new ActionDockError(INVALID_ARGUMENT, "Expected configuration assignment 'KEY=value' or 'KEY:=json'");
|
|
9
|
+
}
|
|
10
|
+
const json = equals > 0 && pair[equals - 1] === ":";
|
|
11
|
+
const key = pair.slice(0, json ? equals - 1 : equals);
|
|
12
|
+
assertConcreteConfigKey(key);
|
|
13
|
+
const rawValue = pair.slice(equals + 1);
|
|
14
|
+
if (!json)
|
|
15
|
+
return { key, value: rawValue };
|
|
16
|
+
try {
|
|
17
|
+
return { key, value: parseJson(rawValue, "configuration override") };
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
// JSON.parse 和通用输入校验的诊断可能含输入片段,不能直接回显或挂载 cause。
|
|
21
|
+
throw new ActionDockError(INVALID_ARGUMENT, `Invalid JSON configuration override for '${key}'`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -16,7 +16,7 @@ export interface InputResolutionPolicy {
|
|
|
16
16
|
sanitizeInputErrors?: boolean;
|
|
17
17
|
/** 是否仅允许字节流输入(默认 false) */
|
|
18
18
|
byteStreamOnly?: boolean;
|
|
19
|
-
/** 原始 stdin 文本模式:保留开头 BOM,UTF-8
|
|
19
|
+
/** 原始 stdin 文本模式:保留开头 BOM,UTF-8 编码失败视为读取失败(stdinField 默认启用) */
|
|
20
20
|
stdinRawText?: boolean;
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
@@ -26,19 +26,21 @@ export interface InputResolutionPolicy {
|
|
|
26
26
|
*/
|
|
27
27
|
export declare function readStdin(stream?: NodeJS.ReadableStream): Promise<string>;
|
|
28
28
|
/**
|
|
29
|
-
*
|
|
29
|
+
* 通用 JSON 值输入解析选项;扁平参数与字段绑定产生对象,完整 JSON 可以是任意合法值。
|
|
30
30
|
*/
|
|
31
|
-
export interface
|
|
31
|
+
export interface ResolveInputOptions {
|
|
32
32
|
input?: string;
|
|
33
33
|
inputFile?: string;
|
|
34
34
|
flatArgs?: string[];
|
|
35
|
-
/** 将 stdin
|
|
35
|
+
/** 将 stdin 完整原始文本绑定为指定顶层字段的字符串值(与 input / inputFile 互斥,可与 flatArgs 组合) */
|
|
36
36
|
stdinField?: string;
|
|
37
37
|
stdin?: NodeJS.ReadableStream;
|
|
38
38
|
flatOptions?: FlatParserOptions & FlatMaterializerOptions;
|
|
39
39
|
policy?: InputResolutionPolicy;
|
|
40
40
|
signal?: AbortSignal;
|
|
41
41
|
}
|
|
42
|
+
/** Action 输入沿用通用解码选项,Action 专属契约校验由执行边界负责。 */
|
|
43
|
+
export type ResolveActionInputOptions = ResolveInputOptions;
|
|
42
44
|
/**
|
|
43
45
|
* 解析完整 JSON 文档字符串。
|
|
44
46
|
* 若解析失败抛出 INVALID_JSON 异常。
|
|
@@ -49,7 +51,12 @@ export interface ResolveActionInputOptions {
|
|
|
49
51
|
*/
|
|
50
52
|
export declare function parseJson(text: string, source: string, policy?: InputResolutionPolicy): JsonValue;
|
|
51
53
|
/**
|
|
52
|
-
*
|
|
54
|
+
* 解析一个完整值:合法 JSON 解码为对应类型,非 JSON 文本保留为字符串。
|
|
55
|
+
* 只有语法错误允许回退;大小、深度、有限数和危险属性校验失败必须透传。
|
|
56
|
+
*/
|
|
57
|
+
export declare function parseValueLiteral(text: string, policy?: InputResolutionPolicy): JsonValue;
|
|
58
|
+
/**
|
|
59
|
+
* 统一解析 JSON 值及结构化输入,不承担 Action、配置或状态的业务校验。
|
|
53
60
|
*
|
|
54
61
|
* 输入模式仲裁规则(Input Mode Arbitration):
|
|
55
62
|
* - effectiveFlat: flatArgs 存在且 length > 0
|
|
@@ -66,6 +73,16 @@ export declare function parseJson(text: string, source: string, policy?: InputRe
|
|
|
66
73
|
* - stdinField 的 stdin 读取为原始文本绑定:不做 JSON 解析、不剥 BOM、保留首尾空白,空 stdin 得到空字符串。
|
|
67
74
|
*
|
|
68
75
|
* @param options 输入解析选项
|
|
69
|
-
* @returns 解析后的 JSON
|
|
76
|
+
* @returns 解析后的 JSON 值
|
|
70
77
|
*/
|
|
71
|
-
export declare function
|
|
78
|
+
export declare function resolveInput(options: ResolveInputOptions): Promise<JsonValue>;
|
|
79
|
+
/** Action 入参复用同一解码器,避免各命令的扁平路径与 stdin 绑定语义漂移。 */
|
|
80
|
+
export declare const resolveActionInput: typeof resolveInput;
|
|
81
|
+
/** 完整值写入的输入选项;业务层仍负责声明校验与整键替换。 */
|
|
82
|
+
export interface ResolveValueInputOptions extends Pick<ResolveInputOptions, "flatArgs" | "stdinField" | "stdin" | "signal" | "policy" | "flatOptions"> {
|
|
83
|
+
value?: string;
|
|
84
|
+
fromStdin?: boolean;
|
|
85
|
+
}
|
|
86
|
+
export declare function hasValueInput(input: ResolveValueInputOptions): boolean;
|
|
87
|
+
/** 先仲裁来源再读流,配置、状态及独立运行入口使用同一完整值解码规则。 */
|
|
88
|
+
export declare function resolveValueInput(options: ResolveValueInputOptions): Promise<JsonValue>;
|