@zhushanwen/subagent-core 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-OL5BK4VN.js → chunk-LZJOEDGQ.js} +455 -203
- package/dist/engine-discovery-scan-Da4Dkzsi.d.cts +818 -0
- package/dist/engine-discovery-scan-Da4Dkzsi.d.ts +818 -0
- package/dist/execution/engine/engine-discovery-scan.cjs +216 -155
- package/dist/execution/engine/engine-discovery-scan.d.cts +1 -2
- package/dist/execution/engine/engine-discovery-scan.d.ts +1 -2
- package/dist/execution/engine/engine-discovery-scan.js +1 -1
- package/dist/execution/relay-env.js +5 -4
- package/dist/index.cjs +7686 -5894
- package/dist/index.d.cts +1876 -1360
- package/dist/index.d.ts +1876 -1360
- package/dist/index.js +7048 -5493
- package/dist.bundle/index.cjs +7747 -5957
- package/package.json +4 -4
- package/src/__tests__/manifest-store.test.ts +16 -15
- package/src/__tests__/robustness-medium-batch1.test.ts +10 -14
- package/src/__tests__/robustness-medium-batch2.test.ts +7 -2
- package/src/execution/__tests__/alive-store.test.ts +117 -1
- package/src/execution/__tests__/batch-finalized.test.ts +206 -0
- package/src/execution/__tests__/chat-engine-routing.test.ts +117 -1
- package/src/execution/__tests__/{cold-resurrect.test.ts → cold-lookup.test.ts} +133 -33
- package/src/execution/__tests__/collect-coordinator-service.test.ts +7 -5
- package/src/execution/__tests__/conversation-continuation.test.ts +1452 -0
- package/src/execution/__tests__/delivery-methods.test.ts +90 -176
- package/src/execution/__tests__/dialog-queue.test.ts +70 -3
- package/src/execution/__tests__/dispose-manifest-recovery.test.ts +475 -0
- package/src/execution/__tests__/execute-and-await-worktree.test.ts +3 -3
- package/src/execution/__tests__/execute-nesting.test.ts +8 -5
- package/src/execution/__tests__/execution-record.test.ts +8 -148
- package/src/execution/__tests__/finalize-record.test.ts +295 -129
- package/src/execution/__tests__/get-record-for-action-restart.test.ts +21 -29
- package/src/execution/__tests__/helpers/fake-engine-port.ts +13 -68
- package/src/execution/__tests__/helpers/legacy-sidecar.ts +33 -0
- package/src/execution/__tests__/helpers/subagent-service-mocks.ts +9 -5
- package/src/execution/__tests__/idle-gc.test.ts +60 -0
- package/src/execution/__tests__/lifecycle-manager.test.ts +3 -254
- package/src/execution/__tests__/manifest-store-tmp-recovery.test.ts +43 -22
- package/src/execution/__tests__/model-config-service.test.ts +111 -0
- package/src/execution/__tests__/nested-visibility-env-propagation.test.ts +10 -6
- package/src/execution/__tests__/notify-ledger.test.ts +42 -1
- package/src/execution/__tests__/rebuild-indexes.test.ts +329 -0
- package/src/execution/__tests__/record-binding.test.ts +613 -0
- package/src/execution/__tests__/record-origin.test.ts +318 -0
- package/src/execution/__tests__/record-store-intent-api.test.ts +600 -0
- package/src/execution/__tests__/record-store-orphan-revive.test.ts +71 -3
- package/src/execution/__tests__/record-store.test.ts +72 -54
- package/src/execution/__tests__/recursive-visibility-baseline.test.ts +8 -5
- package/src/execution/__tests__/round-supervisor-workflow-origin.test.ts +205 -0
- package/src/execution/__tests__/run-orchestration-write-lease.test.ts +293 -0
- package/src/execution/__tests__/run-orchestration.test.ts +199 -0
- package/src/execution/__tests__/session-file-gc.test.ts +35 -4
- package/src/execution/__tests__/session-reconstructor.test.ts +78 -0
- package/src/execution/__tests__/state-marker.test.ts +288 -0
- package/src/execution/__tests__/stream-sink-retirement.test.ts +8 -5
- package/src/execution/__tests__/subagent-actions-core.test.ts +67 -16
- package/src/execution/__tests__/subagent-service-multiproc-guard.test.ts +0 -1
- package/src/execution/__tests__/subagent-service-notify-gate.test.ts +27 -11
- package/src/execution/__tests__/subagent-service-parent-guard.test.ts +17 -11
- package/src/execution/__tests__/subagent-service-recovery-bounds.test.ts +130 -53
- package/src/execution/__tests__/subagent-service.test.ts +17 -215
- package/src/execution/__tests__/subprocess-agent-runner-no-progress-killall.test.ts +138 -0
- package/src/execution/__tests__/subprocess-agent-runner.test.ts +105 -660
- package/src/execution/__tests__/sync-collect-recovery.test.ts +23 -16
- package/src/execution/__tests__/terminal-write-latency.test.ts +79 -0
- package/src/execution/__tests__/workflow-agent-dispatch.test.ts +782 -0
- package/src/execution/alive-store.ts +37 -28
- package/src/execution/{cold-resurrect.ts → cold-lookup.ts} +48 -45
- package/src/execution/config.ts +1 -1
- package/src/execution/conversation-continuation.ts +541 -0
- package/src/execution/dialog-queue.ts +60 -12
- package/src/execution/engine/__tests__/common/capability-gate.test.ts +1 -1
- package/src/execution/engine/__tests__/common/journal-wiring.test.ts +16 -1
- package/src/execution/engine/__tests__/conformance/__fixtures__/engine-protocol/fake-engine-protocol.mjs +17 -51
- package/src/execution/engine/__tests__/conformance/__fixtures__/engine-protocol/smoke-run.fixture.json +0 -5
- package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +1 -1
- package/src/execution/engine/__tests__/conformance/protocol-blackbox.test.ts +5 -9
- package/src/execution/engine/__tests__/engine-discovery-scan.test.ts +0 -3
- package/src/execution/engine/__tests__/engine-discovery.test.ts +0 -3
- package/src/execution/engine/__tests__/model-prompt.test.ts +0 -3
- package/src/execution/engine/__tests__/registry.test.ts +0 -1
- package/src/execution/engine/__tests__/routing.test.ts +0 -1
- package/src/execution/engine/__tests__/run-failure-worktree-cleanup.test.ts +0 -3
- package/src/execution/engine/client/__tests__/__fixtures__/fake-engine.mjs +0 -3
- package/src/execution/engine/client/__tests__/engine-client-reap.test.ts +212 -0
- package/src/execution/engine/client/__tests__/mirror.test.ts +73 -1
- package/src/execution/engine/client/__tests__/protocol-closure.test.ts +2 -9
- package/src/execution/engine/client/__tests__/remote-engine.test.ts +46 -12
- package/src/execution/engine/client/engine-client.ts +81 -25
- package/src/execution/engine/client/mirror.ts +9 -0
- package/src/execution/engine/client/remote-engine.ts +52 -34
- package/src/execution/engine/client/reverse-router.ts +6 -27
- package/src/execution/engine/common/__tests__/run-signals.test.ts +79 -0
- package/src/execution/engine/common/capability-gate.ts +27 -0
- package/src/execution/engine/common/data-dir.ts +3 -2
- package/src/execution/engine/common/errors.ts +1 -1
- package/src/execution/engine/common/journal-wiring.ts +18 -9
- package/src/execution/engine/common/run-signals.ts +83 -0
- package/src/execution/engine/d8-compat.ts +1 -1
- package/src/execution/engine/host/__tests__/host-bridge.test.ts +3 -18
- package/src/execution/engine/host/host-bridge.ts +19 -41
- package/src/execution/engine/host/pi-host-binding.ts +5 -5
- package/src/execution/engine/port.ts +34 -54
- package/src/execution/engine/types.ts +11 -14
- package/src/execution/execution-record.ts +15 -47
- package/src/execution/finalize-record.ts +94 -197
- package/src/execution/idle-gc.ts +9 -3
- package/src/execution/lifecycle-manager.ts +25 -361
- package/src/execution/lifecycle-predicates.ts +22 -19
- package/src/execution/manifest-store.ts +40 -42
- package/src/execution/model-config-service.ts +1 -1
- package/src/execution/notifier.ts +39 -1
- package/src/execution/notify-host.ts +13 -4
- package/src/execution/record-entry.ts +20 -2
- package/src/execution/record-store.ts +925 -160
- package/src/execution/relay-env.ts +8 -3
- package/src/execution/round-supervisor/domain.ts +17 -5
- package/src/execution/round-supervisor/service-binding.test.ts +89 -53
- package/src/execution/round-supervisor/service-binding.ts +71 -21
- package/src/execution/round-supervisor/supervisor.ts +23 -9
- package/src/execution/service/record-access.ts +547 -0
- package/src/execution/service/record-lifecycle.ts +542 -0
- package/src/execution/service/run-orchestration.ts +1647 -0
- package/src/execution/service/service-bootstrap.ts +111 -0
- package/src/execution/service/service-constants.ts +27 -0
- package/src/execution/service/session-baselines.ts +401 -0
- package/src/execution/service/sync-collect-domain.ts +442 -0
- package/src/execution/service/workflow-dispatch.ts +567 -0
- package/src/execution/session-file-gc.ts +11 -8
- package/src/execution/session-reconstructor.ts +44 -1
- package/src/execution/sessions-index.ts +20 -3
- package/src/execution/settled-watchdog.ts +86 -43
- package/src/execution/state-marker.ts +516 -0
- package/src/execution/stream-sink.ts +1 -1
- package/src/execution/subagent-actions-core.ts +53 -31
- package/src/execution/subagent-service.ts +643 -2980
- package/src/execution/subprocess-agent-runner.ts +46 -323
- package/src/execution/types.ts +60 -43
- package/src/execution/ui-request-handler-factory.ts +5 -0
- package/src/execution/worktree-manager.ts +1 -1
- package/src/execution/worktree-registry.ts +1 -1
- package/src/index.ts +6 -5
- package/src/orchestration/__tests__/agent-call-catch-fallback.test.ts +2 -3
- package/src/orchestration/__tests__/agent-call-stream.test.ts +24 -49
- package/src/orchestration/__tests__/error-recovery-terminal-hardening.test.ts +4 -4
- package/src/orchestration/__tests__/file-run-store.test.ts +5 -7
- package/src/orchestration/__tests__/lifecycle-abort-broadcast-signal.test.ts +2 -3
- package/src/orchestration/__tests__/run-snapshot.test.ts +27 -43
- package/src/orchestration/__tests__/worker-message-pump-workflow-dispatch.test.ts +274 -0
- package/src/orchestration/execute-agent-call.ts +1 -1
- package/src/orchestration/file-run-store.ts +1 -1
- package/src/orchestration/models/ports.ts +20 -13
- package/src/orchestration/models/types.ts +11 -13
- package/src/orchestration/run-snapshot.ts +18 -22
- package/src/orchestration/worker-message-pump.ts +33 -57
- package/src/shared/atomic-write.ts +10 -8
- package/dist/chunk-T2SYBW3I.js +0 -24
- package/dist/engine-discovery-scan-BXLA8y-z.d.cts +0 -1624
- package/dist/engine-discovery-scan-BXLA8y-z.d.ts +0 -1624
- package/src/execution/__tests__/chat-round-first-round-watchdog.test.ts +0 -255
- package/src/execution/__tests__/finalized-marker.test.ts +0 -104
- package/src/execution/__tests__/lifecycle-manager-lock.test.ts +0 -211
- package/src/execution/__tests__/subprocess-agent-runner-routing.test.ts +0 -488
- package/src/execution/__tests__/subprocess-agent-runner-timeout.test.ts +0 -75
- package/src/execution/__tests__/tombstone-store.test.ts +0 -73
- package/src/execution/engine/__tests__/conformance/chat-round-protocol.test.ts +0 -230
- package/src/execution/finalized-marker.ts +0 -70
- package/src/execution/tombstone-store.ts +0 -72
package/src/index.ts
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
// 0.4.0 = 首个公开发布的收敛收口面(0.3.0 为 2026-08-30 裁决的跳号占位,永不单独
|
|
25
25
|
// 发布;+ minor changeset 收口面落本号);与 package.json version 的一致性由
|
|
26
26
|
// src/__tests__/smoke.test.ts 动态守护,改版本须两处同步。
|
|
27
|
-
export const CORE_PACKAGE_VERSION = "0.
|
|
27
|
+
export const CORE_PACKAGE_VERSION = "0.9.0";
|
|
28
28
|
|
|
29
29
|
// ── 宿主端口接线面(core/)────────────────────────────────────
|
|
30
30
|
// HostServices:dataRoot / log / discoveryRoots 端口 + configureCore 注入;
|
|
@@ -66,8 +66,6 @@ export type {
|
|
|
66
66
|
EngineCapabilities,
|
|
67
67
|
EngineHandle,
|
|
68
68
|
EngineHandleData,
|
|
69
|
-
InteractAction,
|
|
70
|
-
InteractResult,
|
|
71
69
|
ProbeReport,
|
|
72
70
|
ReplayedTurn,
|
|
73
71
|
SessionView,
|
|
@@ -212,13 +210,16 @@ export {
|
|
|
212
210
|
// globalThis[Symbol.for] slot 防 jiti 多实例分裂,/resume /fork 复用既有实例
|
|
213
211
|
// (SR-3/SR-4 语义)。createSubagentService / SubagentServiceInit 为构造依赖参数
|
|
214
212
|
// 注入形态(modelService 等,无全局查找,@experimental U10 / D6)。
|
|
213
|
+
// [H3/R6] 单例访问器 + Init 接口外移支撑文件 service/service-bootstrap.ts,本
|
|
214
|
+
// barrel 直接改指向该文件(导出符号面不变;壳对 bootstrap 零 re-export——防壳↔
|
|
215
|
+
// bootstrap 值环,设计 v4 import 纪律)。对外消费方零感知。
|
|
216
|
+
export { SubagentService } from "./execution/subagent-service.ts";
|
|
215
217
|
export {
|
|
216
|
-
SubagentService,
|
|
217
218
|
getSubagentService,
|
|
218
219
|
setSubagentService,
|
|
219
220
|
createSubagentService,
|
|
220
221
|
type SubagentServiceInit,
|
|
221
|
-
} from "./execution/
|
|
222
|
+
} from "./execution/service/service-bootstrap.ts";
|
|
222
223
|
// notifyGateAllowsDelivery:closedReason → 投递许可判定(通知门)——
|
|
223
224
|
// 投递内核与壳侧 notify 链的共同语义锚点(execution 生产域消费,A2a)。
|
|
224
225
|
export { notifyGateAllowsDelivery } from "./execution/subagent-service.ts";
|
|
@@ -135,13 +135,12 @@ describe("U7a: catch 分支兜底回发 agent-result(非 Abort 异常)", ()
|
|
|
135
135
|
expect(posted.result.error).toBe("runner exploded");
|
|
136
136
|
expect(posted.result.content).toBe("");
|
|
137
137
|
|
|
138
|
-
// state 一致性三件套(review should_fix
|
|
138
|
+
// state 一致性三件套(review should_fix;[H2 W3] trace.live 字段已删除,
|
|
139
|
+
// 「live 清除」由类型层面收敛——节点无运行期附属对象):
|
|
139
140
|
// trace node 标 failed(不遗留 running 幽灵节点)
|
|
140
141
|
const traceNode = run.state.trace.find(2);
|
|
141
142
|
expect(traceNode?.status).toBe("failed");
|
|
142
143
|
expect(traceNode?.result?.error).toBe("runner exploded");
|
|
143
|
-
// node.live 清除(防内存泄漏)
|
|
144
|
-
expect(traceNode?.live).toBeUndefined();
|
|
145
144
|
// 持久化(catch 是最需留证的场景)
|
|
146
145
|
expect(deps.store.save).toHaveBeenCalled();
|
|
147
146
|
} finally {
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
// src/orchestration/__tests__/agent-call-stream.test.ts
|
|
2
2
|
//
|
|
3
|
-
// U4
|
|
4
|
-
//
|
|
5
|
-
//
|
|
3
|
+
// [H2 W3] 原 U4/U5(dispatchAgentCall 创建 SubagentStream + widgetKey 格式)与
|
|
4
|
+
// U6(streamSink undefined 降级)锁定的是 pump 旁路 streaming 通道——该族随设计
|
|
5
|
+
// subagent-workflow-record-unification.md D2「stream 通道承接」退役:pump 不再
|
|
6
|
+
// 构造 SubagentStream(streaming 由 service 派发路径既有通道承载)。
|
|
6
7
|
//
|
|
7
|
-
//
|
|
8
|
+
// [R2-5] streamSink 注入面已彻底删除(LifecycleDeps 死字段清理):U4' 的运行时
|
|
9
|
+
// 负向断言(「streamSink 已注入 → setWidget 零调用」)前提消失,改为**编译期结构
|
|
10
|
+
// 断言**(下方 HasStreamSink)——字段若被重新引入,keyof LifecycleDeps 重新出现
|
|
11
|
+
// "streamSink",类型断言立即编译红;比运行时负向用例更强的永久护栏。
|
|
12
|
+
//
|
|
13
|
+
// 本文件现锁定:
|
|
14
|
+
// - U4'(编译期):LifecycleDeps 不再有 streamSink 注入面
|
|
15
|
+
// - U6(运行时):最简 deps(无 stream 通道)下 runner.run 仍被调用,无异常
|
|
8
16
|
|
|
9
17
|
import { describe, expect, it, vi } from "vitest";
|
|
10
18
|
|
|
@@ -52,9 +60,8 @@ function makeRunningRun(runId: string): WorkflowRun {
|
|
|
52
60
|
} as unknown as WorkflowRun;
|
|
53
61
|
}
|
|
54
62
|
|
|
55
|
-
/** LifecycleDeps mock
|
|
63
|
+
/** LifecycleDeps mock(runner.run 可控制返回值;streamSink 注入面已随 [R2-5] 删除) */
|
|
56
64
|
function makeDeps(opts: {
|
|
57
|
-
streamSink?: { setWidget: ReturnType<typeof vi.fn> };
|
|
58
65
|
runnerResult?: AgentResult;
|
|
59
66
|
} = {}): LifecycleDeps {
|
|
60
67
|
return {
|
|
@@ -65,7 +72,6 @@ function makeDeps(opts: {
|
|
|
65
72
|
eventBus: { emit: vi.fn() },
|
|
66
73
|
onRunDone: vi.fn(),
|
|
67
74
|
log: vi.fn(),
|
|
68
|
-
streamSink: opts.streamSink,
|
|
69
75
|
} as unknown as LifecycleDeps;
|
|
70
76
|
}
|
|
71
77
|
|
|
@@ -87,50 +93,20 @@ function makeAgentCallMsg(callId: number): unknown {
|
|
|
87
93
|
};
|
|
88
94
|
}
|
|
89
95
|
|
|
90
|
-
// ── U4:
|
|
91
|
-
|
|
92
|
-
describe("U4: dispatchAgentCall stream dispose", () => {
|
|
93
|
-
it("agent call 结束后 stream.dispose 被调用(setWidget 末次 lines=undefined)", async () => {
|
|
94
|
-
const setWidget = vi.fn();
|
|
95
|
-
const deps = makeDeps({ streamSink: { setWidget } });
|
|
96
|
-
const run = makeRunningRun("wf-test-123");
|
|
97
|
-
const handlers = makeHandlers();
|
|
98
|
-
|
|
99
|
-
await handleWorkerMessage(run, makeAgentCallMsg(0), deps, handlers);
|
|
100
|
-
// dispatchAgentCall 内部 void withSlot(...)(fire-and-forget),需等 microtask 完成
|
|
101
|
-
await vi.waitFor(() => {
|
|
102
|
-
expect(setWidget.mock.calls.length).toBeGreaterThanOrEqual(1);
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
const calls = setWidget.mock.calls;
|
|
106
|
-
const lastCall = calls[calls.length - 1];
|
|
107
|
-
expect(lastCall[1]).toBeUndefined();
|
|
108
|
-
});
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
// ── U5: widgetKey 格式 ──
|
|
112
|
-
|
|
113
|
-
describe("U5: widgetKey 格式", () => {
|
|
114
|
-
it("widgetKey = subagent-stream-<runId>-<stepIndex>", async () => {
|
|
115
|
-
const setWidget = vi.fn();
|
|
116
|
-
const deps = makeDeps({ streamSink: { setWidget } });
|
|
117
|
-
const run = makeRunningRun("wf-test-123");
|
|
118
|
-
const handlers = makeHandlers();
|
|
96
|
+
// ── U4': stream 通道退役(编译期结构断言,[R2-5]) ──
|
|
119
97
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
});
|
|
128
|
-
});
|
|
98
|
+
/** "streamSink" ∈ keyof LifecycleDeps 时为 true——与下方显式 false 标注冲突即编译红。 */
|
|
99
|
+
type HasStreamSink = "streamSink" extends keyof LifecycleDeps ? true : false;
|
|
100
|
+
// 结构断言本体:字段已删 = false。若有人重新引入 streamSink 字段,本行类型错误,
|
|
101
|
+
// tsc / vue-tsc 拦截(vitest 转译不做类型检查;类型门由 pre-commit/CI 的 tsc 面
|
|
102
|
+
// 覆盖——比运行时负向用例更强的注入面消失护栏)。
|
|
103
|
+
const assertNoStreamSinkField: HasStreamSink = false;
|
|
104
|
+
void assertNoStreamSinkField;
|
|
129
105
|
|
|
130
|
-
// ── U6:
|
|
106
|
+
// ── U6: 最简 deps 下派发不报错 ──
|
|
131
107
|
|
|
132
|
-
describe("U6:
|
|
133
|
-
it("
|
|
108
|
+
describe("U6: 最简 deps(无 stream 通道)→ runner.run 仍被调用,无异常", () => {
|
|
109
|
+
it("dispatchAgentCall 不依赖 stream 注入面 → runner.run 正常派发", async () => {
|
|
134
110
|
const runnerRun = vi.fn(async () => makeMockResult());
|
|
135
111
|
const deps = {
|
|
136
112
|
store: { save: vi.fn(async () => {}) },
|
|
@@ -140,7 +116,6 @@ describe("U6: streamSink undefined 降级", () => {
|
|
|
140
116
|
eventBus: { emit: vi.fn() },
|
|
141
117
|
onRunDone: vi.fn(),
|
|
142
118
|
log: vi.fn(),
|
|
143
|
-
// streamSink 不设 = undefined
|
|
144
119
|
} as unknown as LifecycleDeps;
|
|
145
120
|
const run = makeRunningRun("wf-test-456");
|
|
146
121
|
const handlers = makeHandlers();
|
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
* - OR-6 主线程半边:{type:"log"} 计入 errorLogs + deps.log debug 留痕(含上限裁剪);
|
|
11
11
|
* 未知 type warn 留痕(协议漂移防线)
|
|
12
12
|
* - OR-8:脚本 return 时残留 fire-and-forget in-flight call 收口为取消终态
|
|
13
|
-
* (call done + trace failed + Cancelled 文案 + completedAt
|
|
14
|
-
*
|
|
13
|
+
* (call done + trace failed + Cancelled 文案 + completedAt;[H2 W3] trace.live
|
|
14
|
+
* 字段已删除——节点无运行期附属对象可滞留),先收口再落盘——done 快照不含
|
|
15
|
+
* running 节点
|
|
15
16
|
*/
|
|
16
17
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
17
18
|
|
|
@@ -320,12 +321,11 @@ describe("[OR-8] run done 时残留 in-flight call 收口 cancelled", () => {
|
|
|
320
321
|
// call 收口为 done + 取消文案(不删除条目——保留调用痕迹)
|
|
321
322
|
expect(call?.status).toBe("done");
|
|
322
323
|
expect(call?.result?.error).toContain("Cancelled");
|
|
323
|
-
// trace 节点 failed + completedAt
|
|
324
|
+
// trace 节点 failed + completedAt(快照/GUI 不再显示 running 步骤)
|
|
324
325
|
const node = run.state.trace.find(1);
|
|
325
326
|
expect(node?.status).toBe("failed");
|
|
326
327
|
expect(node?.error).toContain("Cancelled");
|
|
327
328
|
expect(node?.completedAt).toBeDefined();
|
|
328
|
-
expect(node?.live).toBeUndefined();
|
|
329
329
|
// 持久化快照(收口先于 save)不含 running 形态
|
|
330
330
|
const snap = toRunSnapshot(run);
|
|
331
331
|
expect(snap.state.calls.map((c) => c.status)).toEqual(["done"]);
|
|
@@ -298,13 +298,15 @@ describe("FileRunStore — 版本衔接与 live-strip(U8 / ⛔5,D4 裁决)
|
|
|
298
298
|
expect(JSON.parse(raw).v).toBe("wf-run-v2");
|
|
299
299
|
|
|
300
300
|
// 存量行宽容读 → 再 save:落盘行升级为带 v 当前版本(不做自动迁移的
|
|
301
|
-
// 渐进收敛——D4 裁决②「写入时补 v
|
|
301
|
+
// 渐进收敛——D4 裁决②「写入时补 v」)。[H2 W3] live 字段退役后 codec 不再
|
|
302
|
+
// 承担键清洗(strip 分支随字段删除退役)——存量行的多余键原样透传(类型
|
|
303
|
+
// 层面已无写点,新写行不可能再产生 live 键;真实存量行经旧 codec strip 也不带)。
|
|
302
304
|
writeStateFile("wf-legacy-2.jsonl", LEGACY_LINE + "\n");
|
|
303
305
|
const legacy = (await store.loadAll()).find((r) => r.runId === "wf-legacy-1")!;
|
|
304
306
|
await store.save(legacy);
|
|
305
307
|
const migrated = readFileSync(store.stateFilePath("wf-legacy-1"), "utf8").trim();
|
|
306
308
|
expect(JSON.parse(migrated).v).toBe("wf-run-v2");
|
|
307
|
-
expect(
|
|
309
|
+
expect(JSON.parse(migrated).state.status).toBe("running");
|
|
308
310
|
});
|
|
309
311
|
|
|
310
312
|
it("⛔5 未知更高版本行跳过 + warn(消息含实际版本值,可定位)", async () => {
|
|
@@ -326,7 +328,7 @@ describe("FileRunStore — 版本衔接与 live-strip(U8 / ⛔5,D4 裁决)
|
|
|
326
328
|
expect(warnMessages().some((m) => m.includes("unsupported version") && m.includes("wf-run-v3"))).toBe(true);
|
|
327
329
|
});
|
|
328
330
|
|
|
329
|
-
it("⛔5
|
|
331
|
+
it("⛔5 [H2 W3] live 字段退役:落盘行无 live 键(类型层面收敛的端到端回归)", async () => {
|
|
330
332
|
const run = makeRun("wf-livestrip-1");
|
|
331
333
|
const node: import("../models/types.ts").ExecutionTraceNode = {
|
|
332
334
|
stepIndex: 0,
|
|
@@ -334,20 +336,16 @@ describe("FileRunStore — 版本衔接与 live-strip(U8 / ⛔5,D4 裁决)
|
|
|
334
336
|
task: "do work",
|
|
335
337
|
model: "test-model",
|
|
336
338
|
status: "running",
|
|
337
|
-
live: undefined,
|
|
338
339
|
};
|
|
339
340
|
run.state.trace.append(node);
|
|
340
341
|
const AgentCallMod = await import("../models/agent-call.ts");
|
|
341
342
|
const call = new AgentCallMod.AgentCall(0, { prompt: "do work" }, node);
|
|
342
343
|
run.state.calls.set(0, call);
|
|
343
|
-
node.live = { id: "run-0", turns: [] } as unknown as import("../../execution/types.ts").ExecutionRecord;
|
|
344
344
|
|
|
345
345
|
await store.save(run);
|
|
346
346
|
|
|
347
347
|
const raw = readFileSync(store.stateFilePath("wf-livestrip-1"), "utf8");
|
|
348
348
|
expect(raw.includes('"live"')).toBe(false);
|
|
349
|
-
// strip 产出快照副本:内存中 run 的 live 保留(save 后 run 可继续跑)
|
|
350
|
-
expect(node.live).toBeDefined();
|
|
351
349
|
});
|
|
352
350
|
|
|
353
351
|
it("pi 现网形态行(带 v)经 store 端到端恢复", async () => {
|
|
@@ -160,14 +160,13 @@ describe("[OR-3] abort 广播(abortRun / terminateRunningRuns)", () => {
|
|
|
160
160
|
const deps = makeDeps();
|
|
161
161
|
const runId = await runWorkflow(makeSpec(), deps);
|
|
162
162
|
const run = deps.runs.get(runId)!;
|
|
163
|
-
// 注入 in-flight call(真实 AgentCall 实例:running
|
|
163
|
+
// 注入 in-flight call(真实 AgentCall 实例:running)
|
|
164
164
|
const node: ExecutionTraceNode = {
|
|
165
165
|
stepIndex: 1,
|
|
166
166
|
agent: "a",
|
|
167
167
|
task: "t",
|
|
168
168
|
model: "m",
|
|
169
169
|
status: "running",
|
|
170
|
-
live: { turns: [] } as never,
|
|
171
170
|
};
|
|
172
171
|
run.state.trace.append(node);
|
|
173
172
|
const call = new AgentCall(1, { prompt: "t" }, node);
|
|
@@ -176,7 +175,7 @@ describe("[OR-3] abort 广播(abortRun / terminateRunningRuns)", () => {
|
|
|
176
175
|
|
|
177
176
|
await abortRun(runId, deps, "mid-flight abort");
|
|
178
177
|
|
|
179
|
-
// 收口:call done + trace failed(Cancelled
|
|
178
|
+
// 收口:call done + trace failed(Cancelled 文案;[H2 W3] trace.live 已删除)
|
|
180
179
|
expect(call.status).toBe("done");
|
|
181
180
|
expect(call.result?.error).toContain("Cancelled");
|
|
182
181
|
expect(run.state.trace.find(1)?.status).toBe("failed");
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
// 四视角:
|
|
4
4
|
// ①使用者——toRunSnapshot/fromRunSnapshot 往返等值(含 pi 壳 jsonl-run-store
|
|
5
5
|
// serializeRun 现网形态样本:键序/v 字段/无 live 的快照行,⛔5 往返逐字节一致);
|
|
6
|
-
// ②隔离者——
|
|
6
|
+
// ②隔离者——[H2 W3] ExecutionTraceNode.live 字段退役后节点无运行期附属对象,
|
|
7
|
+
// 序列化直出无 live 键(strip 分支随字段删除退役,防御回归锁定);
|
|
7
8
|
// ③幸存者——版本 guard(D4 裁决③:v 不匹配即拒,字符串无大小序)+ 形状校验
|
|
8
9
|
// 全分支不抛(返回 undefined);
|
|
9
10
|
// ④接线者——「缺 v 宽容」不内聚进 codec(D4 裁决②归属:store 层预处理职责,
|
|
@@ -47,33 +48,10 @@ function makeRun(runId: string, opts: { status?: "running" | "done" } = {}): Wor
|
|
|
47
48
|
);
|
|
48
49
|
}
|
|
49
50
|
|
|
50
|
-
/**
|
|
51
|
-
*
|
|
52
|
-
function
|
|
53
|
-
return {
|
|
54
|
-
id,
|
|
55
|
-
agent: "coder",
|
|
56
|
-
model: "test-model",
|
|
57
|
-
thinkingLevel: undefined,
|
|
58
|
-
mode: "background",
|
|
59
|
-
task: "do work",
|
|
60
|
-
slug: "do-work",
|
|
61
|
-
startedAt: 0,
|
|
62
|
-
rootSessionId: undefined,
|
|
63
|
-
parentRecordId: undefined,
|
|
64
|
-
depth: 0,
|
|
65
|
-
status: "running",
|
|
66
|
-
turns: [],
|
|
67
|
-
turnCount: 0,
|
|
68
|
-
totalTokens: 0,
|
|
69
|
-
lastError: undefined,
|
|
70
|
-
round: 0,
|
|
71
|
-
endedAt: undefined,
|
|
72
|
-
result: undefined,
|
|
73
|
-
error: undefined,
|
|
74
|
-
agentResult: undefined,
|
|
75
|
-
controller: undefined,
|
|
76
|
-
} as ExecutionRecord;
|
|
51
|
+
/** 最小多余键载体([H2 W3] live 字段退役后的防御样本——模拟旧版本运行期对象
|
|
52
|
+
* 残留的多余键,重水合链路的丢弃行为回归用)。 */
|
|
53
|
+
function makeStaleExtraKey(): Record<string, unknown> {
|
|
54
|
+
return { stale: "legacy-key" };
|
|
77
55
|
}
|
|
78
56
|
|
|
79
57
|
/**
|
|
@@ -204,49 +182,55 @@ describe("run-snapshot — toRunSnapshot/fromRunSnapshot 往返等值", () => {
|
|
|
204
182
|
});
|
|
205
183
|
});
|
|
206
184
|
|
|
207
|
-
describe("run-snapshot — live
|
|
208
|
-
it("
|
|
209
|
-
const run = makeRun("wf-
|
|
185
|
+
describe("run-snapshot — [H2 W3] live 字段退役后的序列化行为", () => {
|
|
186
|
+
it("running 节点(类型已无 live 字段)全量直出:序列化无 live 键且往返保真", () => {
|
|
187
|
+
const run = makeRun("wf-nolive-1");
|
|
210
188
|
const node: ExecutionTraceNode = {
|
|
211
189
|
stepIndex: 0,
|
|
212
190
|
agent: "coder",
|
|
213
191
|
task: "do work",
|
|
214
192
|
model: "test-model",
|
|
215
193
|
status: "running",
|
|
216
|
-
live: undefined,
|
|
217
194
|
};
|
|
218
195
|
run.state.trace.append(node);
|
|
219
196
|
const call = new AgentCall(0, { prompt: "do work" }, node);
|
|
220
197
|
run.state.calls.set(0, call);
|
|
221
|
-
// D-10:call.traceNode 与 trace 节点共享引用,live 挂节点上(running 态常态)
|
|
222
|
-
node.live = makeLiveRecord("run-0");
|
|
223
198
|
|
|
224
199
|
const snap = toRunSnapshot(run);
|
|
225
200
|
const serialized = JSON.stringify(snap);
|
|
226
201
|
|
|
202
|
+
// strip 分支随 ExecutionTraceNode.live 字段删除退役——节点不再携带运行期对象,
|
|
203
|
+
// 序列化直出即无 live 键(类型层面收敛的行为回归锁定)
|
|
227
204
|
expect(serialized.includes('"live"')).toBe(false);
|
|
228
205
|
expect(snap.state.trace[0]).not.toHaveProperty("live");
|
|
229
206
|
expect(snap.state.calls[0].traceNode).not.toHaveProperty("live");
|
|
207
|
+
|
|
208
|
+
const back = fromRunSnapshot(JSON.parse(serialized))!;
|
|
209
|
+
expect(back.state.trace.toArray()[0]?.status).toBe("running");
|
|
210
|
+
expect(back.state.trace.toArray()[0]?.task).toBe("do work");
|
|
230
211
|
});
|
|
231
212
|
|
|
232
|
-
it("
|
|
233
|
-
const run = makeRun("wf-
|
|
213
|
+
it("运行期多余键残留不进重水合快照的往返链(防御回归)", () => {
|
|
214
|
+
const run = makeRun("wf-stale-1");
|
|
234
215
|
const node: ExecutionTraceNode = {
|
|
235
216
|
stepIndex: 0,
|
|
236
217
|
agent: "coder",
|
|
237
218
|
task: "do work",
|
|
238
219
|
model: "test-model",
|
|
239
220
|
status: "running",
|
|
240
|
-
live: undefined,
|
|
241
221
|
};
|
|
242
|
-
|
|
243
|
-
|
|
222
|
+
// 模拟旧版本运行期对象残留的多余键(类型外 attach)
|
|
223
|
+
const withStale = Object.assign(node, makeStaleExtraKey()) as ExecutionTraceNode;
|
|
224
|
+
run.state.trace.append(withStale);
|
|
244
225
|
|
|
245
|
-
toRunSnapshot(run);
|
|
226
|
+
const snap = toRunSnapshot(run);
|
|
227
|
+
// trace 直出拷贝会带多余键(codec 不再承担键清洗——多余键是调用方脏数据,
|
|
228
|
+
// 正常路径类型层面已无写点);但 JSON 往返后重水合按 Trace.fromArray 拷贝,
|
|
229
|
+
// 快照行保持可解析、状态保真
|
|
230
|
+
expect(JSON.parse(JSON.stringify(snap)).state.trace[0].status).toBe("running");
|
|
246
231
|
|
|
247
|
-
|
|
248
|
-
expect(
|
|
249
|
-
expect(node.live!.id).toBe("run-0");
|
|
232
|
+
const back = fromRunSnapshot(JSON.parse(JSON.stringify(snap)))!;
|
|
233
|
+
expect(back.state.trace.toArray()[0]?.status).toBe("running");
|
|
250
234
|
});
|
|
251
235
|
});
|
|
252
236
|
|