@zhushanwen/subagent-core 0.6.0 → 0.7.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 -1
- package/dist/chunk-KXVBIVOU.js +16 -0
- package/dist/chunk-T2SYBW3I.js +24 -0
- package/dist/chunk-VURUAGMM.js +2305 -0
- package/dist/{types-C3fE3R9x.d.cts → engine-discovery-scan-ocpM8FmI.d.cts} +770 -668
- package/dist/{types-C3fE3R9x.d.ts → engine-discovery-scan-ocpM8FmI.d.ts} +770 -668
- package/dist/execution/engine/engine-discovery-scan.cjs +2210 -0
- package/dist/execution/engine/engine-discovery-scan.d.cts +4 -0
- package/dist/execution/engine/engine-discovery-scan.d.ts +4 -0
- package/dist/execution/engine/engine-discovery-scan.js +20 -0
- package/dist/execution/engine/paths.cjs +6 -23
- package/dist/execution/engine/paths.d.cts +1 -8
- package/dist/execution/engine/paths.d.ts +1 -8
- package/dist/execution/engine/paths.js +1 -1
- package/dist/execution/relay-env.cjs +12 -28
- package/dist/execution/relay-env.d.cts +1 -33
- package/dist/execution/relay-env.d.ts +1 -33
- package/dist/execution/relay-env.js +5 -3
- package/dist/index.cjs +14045 -16059
- package/dist/index.d.cts +1035 -1579
- package/dist/index.d.ts +1035 -1579
- package/dist/index.js +9838 -13800
- package/dist.bundle/index.cjs +28875 -30323
- package/package.json +20 -26
- package/src/__tests__/record-store-last-line.test.ts +16 -7
- package/src/core/error-message.ts +7 -6
- package/src/core/host-services.ts +8 -2
- package/src/core/notify-ports.ts +17 -2
- package/src/execution/__tests__/chat-engine-routing.test.ts +62 -28
- package/src/execution/__tests__/chat-round-first-round-watchdog.test.ts +255 -0
- package/src/execution/__tests__/collect-coordinator-service.test.ts +36 -47
- package/src/execution/__tests__/collect-mixed-dispatch.test.ts +20 -53
- package/src/execution/__tests__/delivery-methods.test.ts +179 -237
- package/src/execution/__tests__/execute-and-await-worktree.test.ts +0 -2
- package/src/execution/__tests__/execute-nesting.test.ts +20 -13
- package/src/execution/__tests__/explicit-agent-ref-guard.test.ts +20 -33
- package/src/execution/__tests__/gc-timer.test.ts +7 -22
- package/src/execution/__tests__/get-record-for-action-restart.test.ts +20 -10
- package/src/execution/__tests__/helpers/fake-engine-port.ts +187 -0
- package/src/execution/__tests__/helpers/spawn-mock.ts +36 -9
- package/src/execution/__tests__/helpers/subagent-service-mocks.ts +1 -1
- package/src/execution/__tests__/idle-gc.test.ts +200 -0
- package/src/execution/__tests__/lifecycle-predicates.test.ts +26 -21
- package/src/execution/__tests__/nested-visibility-env-propagation.test.ts +5 -2
- package/src/execution/__tests__/reconcile-sweep.test.ts +200 -0
- package/src/execution/__tests__/record-store.test.ts +60 -6
- package/src/execution/__tests__/recursive-visibility-baseline.test.ts +20 -13
- package/src/execution/__tests__/round-supervisor.test.ts +293 -0
- package/src/execution/__tests__/session-pending.test.ts +119 -17
- package/src/execution/__tests__/stream-sink-retirement.test.ts +10 -10
- package/src/execution/__tests__/subagent-service-multiproc-guard.test.ts +1 -11
- package/src/execution/__tests__/subagent-service-notify-gate.test.ts +33 -30
- package/src/execution/__tests__/subagent-service-parent-guard.test.ts +2 -9
- package/src/execution/__tests__/subagent-service-recovery-bounds.test.ts +59 -129
- package/src/execution/__tests__/subagent-service.test.ts +2 -2
- package/src/execution/__tests__/subprocess-agent-runner-routing.test.ts +109 -7
- package/src/execution/__tests__/subprocess-agent-runner.test.ts +108 -36
- package/src/execution/__tests__/sync-collect-recovery.test.ts +21 -36
- package/src/execution/__tests__/workflow-state-root.test.ts +232 -0
- package/src/execution/agent-registry.ts +6 -2
- package/src/execution/dialog-queue.ts +6 -73
- package/src/execution/engine/__tests__/common/capability-gate.test.ts +115 -15
- package/src/execution/engine/__tests__/common/errors.test.ts +11 -18
- package/src/execution/engine/__tests__/common/kill-chain.test.ts +7 -0
- package/src/execution/engine/__tests__/common/nesting-guard.test.ts +9 -3
- package/src/execution/engine/__tests__/common/session-view-service.test.ts +90 -3
- package/src/execution/engine/__tests__/conformance/H9-test-disposition.md +116 -0
- package/src/execution/engine/__tests__/conformance/__fixtures__/engine-protocol/fake-engine-protocol.mjs +377 -0
- package/src/execution/engine/__tests__/conformance/__fixtures__/engine-protocol/recorded.fixture.json +331 -0
- package/src/execution/engine/__tests__/conformance/__fixtures__/engine-protocol/smoke-run.fixture.json +213 -0
- package/src/execution/engine/__tests__/conformance/chat-round-protocol.test.ts +230 -0
- package/src/execution/engine/__tests__/conformance/contract.abort.test.ts +69 -42
- package/src/execution/engine/__tests__/conformance/contract.agent-events.test.ts +4 -81
- package/src/execution/engine/__tests__/conformance/contract.probe.test.ts +67 -44
- package/src/execution/engine/__tests__/conformance/contract.read-degradation.test.ts +81 -54
- package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +133 -70
- package/src/execution/engine/__tests__/conformance/engine-crash.test.ts +143 -0
- package/src/execution/engine/__tests__/conformance/fake-engine-capabilities.ts +19 -0
- package/src/execution/engine/__tests__/conformance/golden-replay.pi.test.ts +7 -2
- package/src/execution/engine/__tests__/conformance/golden-replay.zcode.test.ts +6 -5
- package/src/execution/engine/__tests__/conformance/protocol-blackbox.test.ts +398 -0
- package/src/execution/engine/__tests__/conformance/registry-fork-filter.test.ts +221 -0
- package/src/execution/engine/__tests__/conformance/round-liveness-supervisor.test.ts +302 -0
- package/src/execution/engine/__tests__/conformance/static-spawn-guard.test.ts +58 -0
- package/src/execution/engine/__tests__/engine-discovery-scan.test.ts +558 -0
- package/src/execution/engine/__tests__/host-task-spec.test.ts +45 -0
- package/src/execution/engine/__tests__/model-ref-split.test.ts +74 -0
- package/src/execution/engine/__tests__/registry.test.ts +206 -1
- package/src/execution/engine/__tests__/routing.test.ts +97 -0
- package/src/execution/engine/__tests__/run-failure-worktree-cleanup.test.ts +97 -0
- package/src/execution/engine/client/__tests__/__fixtures__/fake-engine.mjs +294 -0
- package/src/execution/engine/client/__tests__/engine-client.test.ts +516 -0
- package/src/execution/engine/client/__tests__/mirror.test.ts +67 -0
- package/src/execution/engine/client/__tests__/pid-file.test.ts +257 -0
- package/src/execution/engine/client/__tests__/protocol-closure.test.ts +95 -0
- package/src/execution/engine/client/__tests__/remote-engine.test.ts +457 -0
- package/src/execution/engine/client/client-options.ts +103 -0
- package/src/execution/engine/client/engine-client.ts +687 -0
- package/src/execution/engine/client/mirror.ts +167 -0
- package/src/execution/engine/client/pid-file.ts +392 -0
- package/src/execution/engine/client/reaper.ts +95 -0
- package/src/execution/engine/client/remote-engine.ts +441 -0
- package/src/execution/engine/client/reverse-router.ts +255 -0
- package/src/execution/engine/common/capability-gate.ts +109 -22
- package/src/execution/engine/common/errors.ts +9 -25
- package/src/execution/engine/common/event-journal.ts +4 -50
- package/src/execution/engine/common/journal-replay.ts +3 -1
- package/src/execution/engine/common/kill-chain.ts +18 -251
- package/src/execution/engine/common/nesting-guard.ts +18 -114
- package/src/execution/engine/common/pool-manager.ts +4 -0
- package/src/execution/engine/common/session-view-service.ts +56 -84
- package/src/execution/engine/config.ts +151 -0
- package/src/execution/engine/d8-compat.ts +346 -0
- package/src/execution/engine/engine-discovery-roots.ts +107 -0
- package/src/execution/engine/engine-discovery-scan.ts +269 -0
- package/src/execution/engine/engine-discovery.ts +30 -7
- package/src/execution/engine/engine-inspect-package.ts +282 -0
- package/src/execution/engine/engine-manifest.ts +244 -0
- package/src/execution/engine/host/__tests__/host-askuser-endpoint.test.ts +123 -0
- package/src/execution/engine/host/__tests__/host-bridge.test.ts +135 -0
- package/src/execution/engine/host/__tests__/spawned-children.test.ts +73 -0
- package/src/execution/engine/host/host-bridge.ts +150 -0
- package/src/execution/engine/host/host-ui-endpoint.ts +47 -0
- package/src/execution/engine/host/pi-host-binding.ts +91 -0
- package/src/execution/engine/host/spawned-children.ts +139 -0
- package/src/execution/engine/host-task-spec.ts +29 -2
- package/src/execution/engine/model-validation.ts +55 -2
- package/src/execution/engine/paths.ts +16 -41
- package/src/execution/engine/port.ts +48 -2
- package/src/execution/engine/registry.ts +153 -34
- package/src/execution/engine/routing.ts +225 -52
- package/src/execution/engine/types.ts +25 -200
- package/src/execution/finalize-record.ts +25 -0
- package/src/execution/idle-gc.ts +89 -14
- package/src/execution/lifecycle-manager.ts +10 -7
- package/src/execution/lifecycle-predicates.ts +10 -8
- package/src/execution/record-store.ts +29 -2
- package/src/execution/relay-env.ts +19 -36
- package/src/execution/round-supervisor/domain.ts +89 -0
- package/src/execution/round-supervisor/index.ts +33 -0
- package/src/execution/round-supervisor/notify-accounting.ts +87 -0
- package/src/execution/round-supervisor/reconcile-sweep.ts +235 -0
- package/src/execution/round-supervisor/service-binding.test.ts +661 -0
- package/src/execution/round-supervisor/service-binding.ts +273 -0
- package/src/execution/round-supervisor/supervisor.ts +426 -0
- package/src/execution/session-pending.ts +68 -74
- package/src/execution/settled-watchdog.ts +39 -0
- package/src/execution/subagent-service.ts +746 -400
- package/src/execution/subprocess-agent-runner.ts +16 -8
- package/src/execution/types.ts +41 -117
- package/src/execution/ui-channels.ts +13 -214
- package/src/execution/ui-request-handler-factory.ts +7 -4
- package/src/execution/ui-request-observability.ts +2 -2
- package/src/execution/workflow-state-root.ts +67 -0
- package/src/execution/worktree-git-ops.ts +5 -0
- package/src/execution/worktree-manager.ts +11 -1
- package/src/index.ts +55 -26
- package/src/orchestration/__tests__/execute-agent-call.test.ts +1 -1
- package/src/orchestration/execute-agent-call.ts +1 -1
- package/src/orchestration/file-run-store.ts +144 -59
- package/src/orchestration/models/types.ts +43 -42
- package/src/shared/zcode-model-ref.ts +31 -0
- package/dist/chunk-43ONBFZX.js +0 -240
- package/dist/chunk-A4IVZWVX.js +0 -31
- package/dist/chunk-APZY4IME.js +0 -27
- package/dist/chunk-V3VHZ2VX.js +0 -59
- package/dist/execution/engine/engines/zcode/constants.cjs +0 -107
- package/dist/execution/engine/engines/zcode/constants.d.cts +0 -135
- package/dist/execution/engine/engines/zcode/constants.d.ts +0 -135
- package/dist/execution/engine/engines/zcode/constants.js +0 -54
- package/dist/execution/engine/engines/zcode/reader.cjs +0 -276
- package/dist/execution/engine/engines/zcode/reader.d.cts +0 -21
- package/dist/execution/engine/engines/zcode/reader.d.ts +0 -21
- package/dist/execution/engine/engines/zcode/reader.js +0 -9
- package/src/__tests__/append-system-prompt-assembly.test.ts +0 -243
- package/src/__tests__/fr4-get-state-handshake.test.ts +0 -125
- package/src/__tests__/session-runner.test.ts +0 -69
- package/src/execution/__tests__/ask-user-transit-e2e.test.ts +0 -490
- package/src/execution/__tests__/chatmode-first-round-closure-spawn.test.ts +0 -191
- package/src/execution/__tests__/descendant-sweep-guards.test.ts +0 -220
- package/src/execution/__tests__/descendant-sweep.test.ts +0 -269
- package/src/execution/__tests__/engine-model-validation.test.ts +0 -741
- package/src/execution/__tests__/epipe-fallback.test.ts +0 -248
- package/src/execution/__tests__/execution-runtime-face.test.ts +0 -272
- package/src/execution/__tests__/get-state-handshake.test.ts +0 -127
- package/src/execution/__tests__/helpers/session-runner-mocks.ts +0 -113
- package/src/execution/__tests__/keep-alive-no-progress.test.ts +0 -280
- package/src/execution/__tests__/kill-all-escalation.test.ts +0 -196
- package/src/execution/__tests__/max-turns-to-watchdog-ms.test.ts +0 -113
- package/src/execution/__tests__/output-collector.test.ts +0 -469
- package/src/execution/__tests__/pi-invocation.test.ts +0 -166
- package/src/execution/__tests__/recursive-visibility-env.test.ts +0 -149
- package/src/execution/__tests__/rpc-mode.test.ts +0 -89
- package/src/execution/__tests__/run-and-finalize-anchoring.test.ts +0 -387
- package/src/execution/__tests__/run-and-finalize-chatmode.test.ts +0 -277
- package/src/execution/__tests__/run-spawn-chatmode-settled.test.ts +0 -254
- package/src/execution/__tests__/run-spawn-edges.test.ts +0 -1079
- package/src/execution/__tests__/run-spawn-integration.test.ts +0 -933
- package/src/execution/__tests__/run-spawn-resume.test.ts +0 -322
- package/src/execution/__tests__/run-spawn-rpc-mode.test.ts +0 -196
- package/src/execution/__tests__/run-spawn-stdout-callback-throw.test.ts +0 -207
- package/src/execution/__tests__/service-kill-escalation.test.ts +0 -91
- package/src/execution/__tests__/session-runner-branch-cache-lru.test.ts +0 -110
- package/src/execution/__tests__/session-runner-close-prune.test.ts +0 -181
- package/src/execution/__tests__/session-runner-dispatch.test.ts +0 -489
- package/src/execution/__tests__/session-runner-epipe.test.ts +0 -179
- package/src/execution/__tests__/session-runner-heartbeat-idle-fallback.test.ts +0 -227
- package/src/execution/__tests__/session-runner-lifecycle-helpers.test.ts +0 -290
- package/src/execution/__tests__/session-runner-schema-env.test.ts +0 -352
- package/src/execution/__tests__/settled-watchdog.test.ts +0 -524
- package/src/execution/__tests__/spawn-args.test.ts +0 -446
- package/src/execution/__tests__/spawn-event-adapter-rpc.test.ts +0 -192
- package/src/execution/__tests__/spawn-event-adapter.test.ts +0 -167
- package/src/execution/__tests__/spawn-worktree-guidance.test.ts +0 -208
- package/src/execution/__tests__/spawned-children.test.ts +0 -236
- package/src/execution/__tests__/start-sync-model-guard.test.ts +0 -150
- package/src/execution/__tests__/stdin-writer.test.ts +0 -464
- package/src/execution/__tests__/subagent-service-message-close.test.ts +0 -693
- package/src/execution/__tests__/temp-prompt.test.ts +0 -53
- package/src/execution/__tests__/timeout-integration.test.ts +0 -616
- package/src/execution/__tests__/turn-limiter-semantics.test.ts +0 -194
- package/src/execution/__tests__/turn-limiter.test.ts +0 -65
- package/src/execution/__tests__/ui-request-handler.test.ts +0 -205
- package/src/execution/__tests__/ui-request-queue.test.ts +0 -298
- package/src/execution/__tests__/worktree-pid-registration.integration.test.ts +0 -230
- package/src/execution/engine/__tests__/common/schema-emulation.test.ts +0 -128
- package/src/execution/engine/__tests__/common/session-view-service-zcode-dbpath.test.ts +0 -149
- package/src/execution/engine/__tests__/conformance/__fixtures__/pi-golden-events.json +0 -28
- package/src/execution/engine/__tests__/conformance/zcode-appserver-harness.ts +0 -128
- package/src/execution/engine/__tests__/paths.test.ts +0 -39
- package/src/execution/engine/common/schema-emulation.ts +0 -189
- package/src/execution/engine/common/session-view-projection.ts +0 -51
- package/src/execution/engine/engines/pi/__tests__/pi-engine.test.ts +0 -615
- package/src/execution/engine/engines/pi/__tests__/reader.test.ts +0 -155
- package/src/execution/engine/engines/pi/__tests__/spawn-opts-direct.test.ts +0 -257
- package/src/execution/engine/engines/pi/argv-mirror.ts +0 -135
- package/src/execution/engine/engines/pi/get-state-handshake.ts +0 -179
- package/src/execution/engine/engines/pi/output-collector.ts +0 -317
- package/src/execution/engine/engines/pi/pi-engine.ts +0 -811
- package/src/execution/engine/engines/pi/pi-invocation.ts +0 -120
- package/src/execution/engine/engines/pi/reader.ts +0 -59
- package/src/execution/engine/engines/pi/registration.ts +0 -37
- package/src/execution/engine/engines/pi/session-runner.ts +0 -2840
- package/src/execution/engine/engines/pi/spawn-event-adapter.ts +0 -404
- package/src/execution/engine/engines/pi/stdin-writer.ts +0 -199
- package/src/execution/engine/engines/pi/temp-prompt.ts +0 -62
- package/src/execution/engine/engines/pi/turn-limiter.ts +0 -102
- package/src/execution/engine/engines/zcode/__tests__/__fixtures__/fake-appserver.mjs +0 -301
- package/src/execution/engine/engines/zcode/__tests__/__fixtures__/zcode-golden-appserver.json +0 -36
- package/src/execution/engine/engines/zcode/__tests__/appserver-launcher.test.ts +0 -321
- package/src/execution/engine/engines/zcode/__tests__/connection.test.ts +0 -473
- package/src/execution/engine/engines/zcode/__tests__/parser.test.ts +0 -43
- package/src/execution/engine/engines/zcode/__tests__/preparer.test.ts +0 -124
- package/src/execution/engine/engines/zcode/__tests__/reader.test.ts +0 -210
- package/src/execution/engine/engines/zcode/__tests__/registration.test.ts +0 -71
- package/src/execution/engine/engines/zcode/__tests__/session-channel-dispose-harvest.test.ts +0 -247
- package/src/execution/engine/engines/zcode/__tests__/session-channel-turn-timers.test.ts +0 -451
- package/src/execution/engine/engines/zcode/__tests__/session-channel.test.ts +0 -792
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine-appserver.test.ts +0 -782
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine-degrade.test.ts +0 -168
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine-dispose.test.ts +0 -210
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine-retry.test.ts +0 -353
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine-status.test.ts +0 -282
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine-timeout.test.ts +0 -372
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine.live.test.ts +0 -145
- package/src/execution/engine/engines/zcode/appserver-launcher.ts +0 -167
- package/src/execution/engine/engines/zcode/connection.ts +0 -598
- package/src/execution/engine/engines/zcode/constants.ts +0 -176
- package/src/execution/engine/engines/zcode/golden-sample.ts +0 -47
- package/src/execution/engine/engines/zcode/parser.ts +0 -102
- package/src/execution/engine/engines/zcode/preparer.ts +0 -235
- package/src/execution/engine/engines/zcode/reader.ts +0 -381
- package/src/execution/engine/engines/zcode/registration.ts +0 -37
- package/src/execution/engine/engines/zcode/session-channel.ts +0 -968
- package/src/execution/engine/engines/zcode/zcode-engine.ts +0 -1431
- package/src/execution/round-settlement.ts +0 -93
- package/src/execution/ui-request-queue.ts +0 -215
- package/src/shared/schema-env.ts +0 -44
|
@@ -43,6 +43,16 @@ export interface FinalizeDeps {
|
|
|
43
43
|
pi: { appendEntry?: (type: string, data: unknown) => void } | null;
|
|
44
44
|
/** pending-notifications 终态注销(绑定 pi.events.emit,由调用方闭包提供)。 */
|
|
45
45
|
emitUnregister(id: string, status: string): void;
|
|
46
|
+
/**
|
|
47
|
+
* [F-5 修复] record 终态化的宿主侧收口钩子(recordId;best-effort,抛错由调用方
|
|
48
|
+
* 在闭包内自行兜底)。单一汇聚点:doFinalizeRecord 是全部 closed 终态的必经路径
|
|
49
|
+
* (finalizeRecord / closeChatIdle / closeAfterRoundSettled / finalizeFailed /
|
|
50
|
+
* finalizeAborted / consumeCloseAfterRound),chat 轮路由注销(chatRoundRoutes)
|
|
51
|
+
* 由 SubagentService 经此钩子统一执行——此前仅 cancelBackground 注销,chat record
|
|
52
|
+
* 经 finalize 链终态化后路由闭包(持 record/stream/守护引用)泄漏。finalizeRoundToIdle
|
|
53
|
+
* 不经本钩子(回 idle 非终态,续聊仍需路由)。
|
|
54
|
+
*/
|
|
55
|
+
onFinalized?: (recordId: string) => void;
|
|
46
56
|
/**
|
|
47
57
|
* [T1/PS-9] subagent sessionDir(getSubagentSessionDir(agentDir, rootCwd),调用方注入)。
|
|
48
58
|
*
|
|
@@ -254,8 +264,23 @@ export async function doFinalizeRecord(
|
|
|
254
264
|
removeAliveMarkerIfPresent(record);
|
|
255
265
|
|
|
256
266
|
// pending-notifications:终态注销(只记 registry 状态,通知由 BgNotifier 发)
|
|
267
|
+
// [W4 发射点枚举归属①] 注销合法发射点枚举(设计 D2)第 ① 处:subagent record
|
|
268
|
+
// 终态化(finalizeRecord 路径,含监督器放弃)。其余合法发射点:② chatMode 轮末
|
|
269
|
+
// idle(doFinalizeRoundToIdle,本文件下方);③ workflow run 终态迁移
|
|
270
|
+
// (transition("done") 路径);④ 监督器显式放弃(走本路径,终态化+注销同批);
|
|
271
|
+
// ⑤ 注册对账 sweep 补发(round-supervisor/reconcile-sweep.ts)。进程退出本身
|
|
272
|
+
// 永远不是注销理由(subagent-service disposeAllRecords 的 emit 属①——其同批
|
|
273
|
+
// completeRecord+archive 终态化)。
|
|
257
274
|
deps.emitUnregister(record.id, status);
|
|
258
275
|
|
|
276
|
+
// [F-5 修复] 宿主侧终态收口钩子(chat 轮路由注销的单一汇聚点,见 FinalizeDeps
|
|
277
|
+
// .onFinalized 注释)。fire-and-forget:钩子失败不阻断 manifest 收尾(闭包内自查)。
|
|
278
|
+
try {
|
|
279
|
+
deps.onFinalized?.(record.id);
|
|
280
|
+
} catch (err) {
|
|
281
|
+
bestEffort(err, "onFinalized hook (finalizeRecord)");
|
|
282
|
+
}
|
|
283
|
+
|
|
259
284
|
// ── Step 4 (last): manifest 持久化(best-effort,不阻断、不 throw)──
|
|
260
285
|
await writeManifestBestEffort(deps, record);
|
|
261
286
|
}
|
package/src/execution/idle-gc.ts
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
* SP-4 idle record GC:30 天 TTL 定时归档,防 idle record 永久驻留内存。
|
|
3
3
|
* 从 subagent-service.ts 抽出(文件超 max-lines;逻辑自包含:interval + TTL 扫描)。
|
|
4
4
|
* 启动幂等由调用方(service.startGcTimer)守卫;返回 stop 函数供 dispose 清理。
|
|
5
|
+
*
|
|
6
|
+
* [W4 idle-gc 扩展 · 设计 chat-domain-v1x-liveness-governance D4 连带面 2③]
|
|
7
|
+
* 注册翻 process 档后的兜底通道扩展(与翻档同批生效,先行期 = 无兜底挂账窗口):
|
|
8
|
+
* 1. 锚扩展:无 idleSince 的 resumable record 以 startedAt(创建时确定,
|
|
9
|
+
* types.ts ExecutionRecord.startedAt)为锚——兜底定位 30 天量级终态归档,
|
|
10
|
+
* 创建时锚的精度损失在该量级可接受(同设计对 record startedAt 的 rationale)。
|
|
11
|
+
* 2. **只归档不补注销**:被归档 record 的注册注销统一交 core 注册对账 sweep
|
|
12
|
+
* (判据含「已归档 = 视同终态」)——归档跨 session record 时 appendEntry 只达
|
|
13
|
+
* 当前 session entries(写达域无效),且 archive 不走 finalizeRecord、无注销
|
|
14
|
+
* 发射枚举身份(发射点枚举 D2 的 5 处不含 GC)。
|
|
15
|
+
* 3. WorkflowRun store 同批纳入:running 且 meta.startedAt 超 IDLE_TTL_MS 的 run
|
|
16
|
+
* 终态化归档(transition("done","time_limited") + save 持久化终态)。时间锚选择
|
|
17
|
+
* = WorkflowRunMeta.startedAt(run 创建时刻,ISO string)——run 状态无 idleSince
|
|
18
|
+
* 等价物,meta.completedAt 仅终态存在,startedAt 是唯一创建时确定的锚(与
|
|
19
|
+
* record startedAt 同 rationale)。**只终态化不补注销**同上:run 的注销发射
|
|
20
|
+
* 身份在 transition("done") 路径(发射点③)与其宿主收口链,GC 不越权补发。
|
|
5
21
|
*/
|
|
6
22
|
import { getLogger } from "../core/logger.ts";
|
|
7
23
|
import { getEngineDataDir } from "./engine/common/data-dir.ts";
|
|
@@ -16,17 +32,32 @@ const logger = getLogger("subagents");
|
|
|
16
32
|
/** GC 扫描间隔:1 小时。 */
|
|
17
33
|
// eslint-disable-next-line no-magic-numbers -- 60*60*1000 = 1h 的毫秒换算常数
|
|
18
34
|
const GC_INTERVAL_MS = 60 * 60 * 1000;
|
|
19
|
-
/** idle record TTL:30 天(超龄归档)。 */
|
|
35
|
+
/** idle record TTL:30 天(超龄归档)。record 锚窗与 workflow run 锚窗共用。 */
|
|
20
36
|
// eslint-disable-next-line no-magic-numbers -- 30*24*60*60*1000 = 30d 的毫秒换算常数
|
|
21
37
|
const IDLE_TTL_MS = 30 * 24 * 60 * 60 * 1000;
|
|
22
38
|
/** 毫秒/天(GC 日志的 d 换算)。 */
|
|
23
39
|
// eslint-disable-next-line no-magic-numbers -- 24*60*60*1000 = 1d 的毫秒换算常数
|
|
24
40
|
const MS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
25
41
|
|
|
42
|
+
/**
|
|
43
|
+
* WorkflowRun GC 窄口(idle-gc 对 WorkflowRun store 的最小依赖面,结构类型——
|
|
44
|
+
* 调用方传 FileRunStore 实例即可,不 import orchestration 具体类,保持本模块
|
|
45
|
+
* 可独立编译 + 单测)。loadAll 失败(宿主未 configureCore / IO 错)由实现侧
|
|
46
|
+
* 或本模块 catch 吞掉,单轮跳过下轮重试。
|
|
47
|
+
*/
|
|
48
|
+
export interface WorkflowRunGcStore {
|
|
49
|
+
loadAll(): Promise<Array<{ runId: string; state: { status: string }; meta: { startedAt: string }; transition(target: "done", reason?: string): void }>>;
|
|
50
|
+
save(run: unknown): Promise<void>;
|
|
51
|
+
}
|
|
52
|
+
|
|
26
53
|
/**
|
|
27
54
|
* 启动 idle record GC 定时器,返回 stop 函数(清理 interval;幂等)。
|
|
28
|
-
*
|
|
29
|
-
*
|
|
55
|
+
* 每个扫描周期:
|
|
56
|
+
* - record 面:对 store 内全部 active record 中 resumable 的,锚点(idleSince
|
|
57
|
+
* 优先,缺失回退 startedAt——[W4 锚扩展])超过 IDLE_TTL_MS 的归档。archive
|
|
58
|
+
* 单条失败不阻断其余(bestEffort 留痕)。**只归档不补注销**(见文件头注)。
|
|
59
|
+
* - workflow 面(注入 workflowRuns 时):running 且 meta.startedAt 超
|
|
60
|
+
* IDLE_TTL_MS 的 run 终态化归档(transition + save),单 run 失败不阻断。
|
|
30
61
|
*
|
|
31
62
|
* [D8 池引用计数接线] 归档时同步释放该 record 的引擎池引用(releasePoolRef:
|
|
32
63
|
* journal 跟随 record 删除 + refs 移除 + 归零删池内原生状态)。锚点选在 30 天 TTL
|
|
@@ -37,28 +68,72 @@ const MS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
|
37
68
|
* 不能删——那是 record 主数据死亡(主 session 文件被 pi 侧删除,core 无触发点)才有
|
|
38
69
|
* 的处置,由 cleanupExpiredPoolRefs 的 TTL 兜底覆盖。
|
|
39
70
|
*/
|
|
40
|
-
export function startIdleGc(store: RecordStore): () => void {
|
|
71
|
+
export function startIdleGc(store: RecordStore, workflowRuns?: WorkflowRunGcStore): () => void {
|
|
41
72
|
const timer = setInterval(() => {
|
|
42
73
|
const now = Date.now();
|
|
43
74
|
for (const record of store.listAllActive()) {
|
|
44
|
-
if (isResumable(record)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
|
|
75
|
+
if (!isResumable(record)) continue;
|
|
76
|
+
// [W4 锚扩展] idleSince(轮终写点)优先;缺失(resumable 但无轮终信号的
|
|
77
|
+
// 存量/异常形态)回退 startedAt(创建时确定)——两锚同为「最晚活性证据」,
|
|
78
|
+
// 30 天量级下 created 锚的精度损失可接受。
|
|
79
|
+
const anchorMs = record.idleSince ?? record.startedAt;
|
|
80
|
+
const age = now - anchorMs;
|
|
81
|
+
if (age > IDLE_TTL_MS) {
|
|
82
|
+
logger.warn(
|
|
83
|
+
`[subagents] GC: archiving idle record ${record.id} (idle for ${Math.round(age / MS_PER_DAY)}d)`,
|
|
84
|
+
);
|
|
85
|
+
try {
|
|
86
|
+
store.archive(record);
|
|
87
|
+
} catch (err) {
|
|
88
|
+
bestEffort(err, `GC archive record ${record.id}`);
|
|
54
89
|
}
|
|
90
|
+
releaseEnginePoolRef(record);
|
|
55
91
|
}
|
|
56
92
|
}
|
|
93
|
+
if (workflowRuns !== undefined) {
|
|
94
|
+
void gcWorkflowRuns(workflowRuns, now);
|
|
95
|
+
}
|
|
57
96
|
}, GC_INTERVAL_MS);
|
|
58
97
|
timer.unref?.();
|
|
59
98
|
return () => clearInterval(timer);
|
|
60
99
|
}
|
|
61
100
|
|
|
101
|
+
/**
|
|
102
|
+
* [W4 WorkflowRun store 纳入] running 且 startedAt 超锚窗的 run 终态化归档。
|
|
103
|
+
* reason = "time_limited"(超龄归档语义的 DoneReason,对主 agent 的语义是
|
|
104
|
+
* 「run 因超时被收口」而非 completed)。失败吞错留痕(清理是旁路维护,不能
|
|
105
|
+
* 拖垮 GC interval;下轮重试)。
|
|
106
|
+
*/
|
|
107
|
+
async function gcWorkflowRuns(workflowRuns: WorkflowRunGcStore, now: number): Promise<void> {
|
|
108
|
+
let runs: Awaited<ReturnType<WorkflowRunGcStore["loadAll"]>>;
|
|
109
|
+
try {
|
|
110
|
+
runs = await workflowRuns.loadAll();
|
|
111
|
+
} catch (err) {
|
|
112
|
+
// 宿主未 configureCore(core_host_not_configured)/ IO 失败:本轮跳过,
|
|
113
|
+
// 下轮重试。debug 留痕——这是「workflow 域未启用」的正常形态,warn 会噪声。
|
|
114
|
+
logger.debug(`[subagents] GC: workflow run store loadAll failed (skipped this cycle): ${
|
|
115
|
+
err instanceof Error ? err.message : String(err)
|
|
116
|
+
}`);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
for (const run of runs) {
|
|
120
|
+
if (run.state.status !== "running") continue;
|
|
121
|
+
const startedMs = Date.parse(run.meta.startedAt);
|
|
122
|
+
if (!Number.isFinite(startedMs)) continue; // 畸形锚不过判(宁挂账不失明)
|
|
123
|
+
const age = now - startedMs;
|
|
124
|
+
if (age <= IDLE_TTL_MS) continue;
|
|
125
|
+
logger.warn(
|
|
126
|
+
`[subagents] GC: terminating stale running workflow run ${run.runId} (started ${Math.round(age / MS_PER_DAY)}d ago)`,
|
|
127
|
+
);
|
|
128
|
+
try {
|
|
129
|
+
run.transition("done", "time_limited");
|
|
130
|
+
await workflowRuns.save(run);
|
|
131
|
+
} catch (err) {
|
|
132
|
+
bestEffort(err, `GC terminate workflow run ${run.runId}`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
62
137
|
/**
|
|
63
138
|
* 释放 record 的引擎池引用(best-effort)。无 engineHandle(存量 record / 非引擎
|
|
64
139
|
* 路径)时 no-op;engine 缺省投影 'pi'(与读侧存量 entry 零迁移口径一致)。
|
|
@@ -13,7 +13,10 @@
|
|
|
13
13
|
// 【已接线:session-runner.ts agent_settled arm / subagent-service 新 turn disarm】
|
|
14
14
|
// 2. 全局 ceiling —— 活进程上限,超限时按 LRU 挤出最久空闲(决策 4)【未接线,deferred】
|
|
15
15
|
// 3. shutdown 收割 —— 父进程 shutdown 时显式 SIGTERM 全部 activation(决策 7 防线 i)
|
|
16
|
-
// 【未接线:
|
|
16
|
+
// 【未接线:[F-7 纠偏] 旧注「reapSpawnedChildrenOnShutdown 已等价覆盖」失实——
|
|
17
|
+
// 该 hook 调 killAllSpawnedChildren,后者协议化后仅镜像置死 no-op(见
|
|
18
|
+
// engine/host/spawned-children.ts 与 src/index.ts 导出注释);引擎进程实际回收 =
|
|
19
|
+
// stdin-EOF 自灭链,本职责仍无显式收割接线】
|
|
17
20
|
// 4. 孤儿扫描 —— 父进程启动时按持久化 PID 扫收上次崩溃遗留的孤儿(决策 7 防线 ii)【deferred】
|
|
18
21
|
// 5. activate 互斥 —— 同 recordId 的并发 activate 串行化(决策 7 防线 iii,防双写者)
|
|
19
22
|
// 【已接线:subagent-service.ts 冷路径 resume 前 acquireActivateLock】
|
|
@@ -295,12 +298,12 @@ export function getActiveProcessCount(): number {
|
|
|
295
298
|
// ============================================================
|
|
296
299
|
// 职责 3:shutdown 收割(防线 i)
|
|
297
300
|
//
|
|
298
|
-
// [
|
|
299
|
-
//
|
|
300
|
-
//
|
|
301
|
-
//
|
|
302
|
-
//
|
|
303
|
-
//
|
|
301
|
+
// [状态:未接线,无等价实现([F-7 纠偏])] reapAllAliveProcesses 无生产调用方。旧注
|
|
302
|
+
// 「shutdown 收割已由 reapSpawnedChildrenOnShutdown 等价覆盖」失实:该 hook 调
|
|
303
|
+
// killAllSpawnedChildren,而后者协议化后(engines/pi inproc 删除、子进程活在引擎
|
|
304
|
+
// 进程内)仅做 core 侧镜像置死,不发任何 SIGTERM(_signal 参数被忽略)——引擎进程
|
|
305
|
+
// 实际回收走 stdin-EOF 自灭链,本职责的显式收割仍无接线。本函数保留作未来接入面;
|
|
306
|
+
// 若未来接入须先保证 register/unregister 记账完整,否则收割列表不全。
|
|
304
307
|
// ============================================================
|
|
305
308
|
|
|
306
309
|
/**
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
//
|
|
5
5
|
// 旧三态(running/idle/cancelled)折为两态(running/closed)后,「对话模式等待续聊」
|
|
6
6
|
//(旧 idle)和「正在执行」都是 status="running",需派生谓词区分。谓词复用已有
|
|
7
|
-
// lifecycle-manager.hasIdleTimer(idle timer 是否 armed)与
|
|
8
|
-
|
|
7
|
+
// lifecycle-manager.hasIdleTimer(idle timer 是否 armed)与 core 侧 spawnedChildren
|
|
8
|
+
// 状态镜像读点(engine/host/spawned-children.ts,活进程句柄是否存在),不新增状态记账。
|
|
9
9
|
//
|
|
10
10
|
// 两种 running 子态(v4 B-1):
|
|
11
11
|
// - 等待续聊(旧 idle):isIdle=true(timer armed)。又分两路:
|
|
@@ -20,19 +20,21 @@
|
|
|
20
20
|
// 故 isIdle 在这两个检查点恒为 true——notify 守卫与 early-return 判据可靠。
|
|
21
21
|
|
|
22
22
|
import { hasIdleTimer } from "./lifecycle-manager.ts";
|
|
23
|
-
|
|
23
|
+
// [W6 拆依赖] 活进程句柄读点改经 core 侧 spawnedChildren 状态镜像公共面
|
|
24
|
+
// (engine/host/spawned-children.ts),不再深路径 import inproc pi 引擎目录 内部——
|
|
25
|
+
// 行为不变(镜像 ∪ inproc 权威 map 并读,见该文件头注释的过渡桥语义)。
|
|
26
|
+
import { hasLiveProcessHandleCore } from "./engine/host/spawned-children.ts";
|
|
24
27
|
import type { ExecutionRecord } from "./types.ts";
|
|
25
28
|
|
|
26
29
|
/**
|
|
27
30
|
* 活进程句柄是否存在(isResumable 子判据)。
|
|
28
31
|
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
+
* [W6] 改读 core 侧状态镜像(engine/host/spawned-children.ts 的 hasLiveProcessHandleCore:
|
|
33
|
+
* 镜像项存在且未 killed = 有活进程句柄;迁移期内建 pi 的 inproc 权威 map 并读兜底)。
|
|
34
|
+
* 进程 close / 被杀后镜像项置死或移除 = 无活进程(Path B / 跨重启)。
|
|
32
35
|
*/
|
|
33
36
|
export function hasLiveProcessHandle(recordId: string): boolean {
|
|
34
|
-
|
|
35
|
-
return child !== undefined && !child.killed;
|
|
37
|
+
return hasLiveProcessHandleCore(recordId);
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
/**
|
|
@@ -744,7 +744,13 @@ export class RecordStore {
|
|
|
744
744
|
// 的修补对 async/chat 成员同样生效——拉齐 light 重建丢 result/model 与 full 重建的
|
|
745
745
|
// 既有形态不一致(v2 D3 影响面诚实口径),不触碰任何通知文案(golden 不锁 entry 字节)。
|
|
746
746
|
const rec0 = lastEntry === undefined ? rec : RecordStore.mergeOrphanLastEntry(rec, lastEntry);
|
|
747
|
-
|
|
747
|
+
// [W4 boot 分区 · 裁决表行 3] 重认领保留分支的判据 = resumable 且**无完成产出**:
|
|
748
|
+
// 非 chatMode 的 resumable=true 且 result 有值是 SP-5 one-shot 完成态(任务已完成,
|
|
749
|
+
// 直断 closed/gc 无损);resumable=true 且 result 缺失是「监督器死亡纳管态」(W4:
|
|
750
|
+
// 引擎死亡接管后宿主重启)——保留 running 交 round-supervisor boot 重认领继续
|
|
751
|
+
// 管辖(注册存续 process 档),误判 closed 会制造「指向已终态 record 的残留注册」
|
|
752
|
+
// 并损失 resume 可能。
|
|
753
|
+
if (rec0.chatMode === true || (rec0.resumable === true && rec0.result === undefined)) {
|
|
748
754
|
// chat 会话跨重启等续聊:保留 running(可续聊),仅落执行态信号。
|
|
749
755
|
this.reportSubagentRecord({ ...rec0, resumable: true });
|
|
750
756
|
return;
|
|
@@ -769,12 +775,29 @@ export class RecordStore {
|
|
|
769
775
|
// 真实 reason 同层——否则无 reason sidecar 在磁盘重建时被兜底为 disconnected,
|
|
770
776
|
// 把正常完成的记录误标成断联。
|
|
771
777
|
writeFinalized(sessionFile, "gc");
|
|
778
|
+
// [F3 boot 直断语义,设计表 3 行 2] 走到本分支的 record 分两类:
|
|
779
|
+
// - resumable=true(上方分流保证此时 result 有值)= SP-5 one-shot 完成态——任务
|
|
780
|
+
// 真实完成,直断 closed/gc 无 error,投影 completed 不变;
|
|
781
|
+
// - 其余 = in-flight(重启前在途、无 resumable 信号)——宿主重启中断了在途任务,
|
|
782
|
+
// 投影不得是 completed(事故环 3:异常中断被谎报完成,违反 G3)。error 载体经
|
|
783
|
+
// deriveOutcome("gc", error) = "failed"(execution-record.ts 唯一权威派生)
|
|
784
|
+
// 投影 failed,文案供 GUI/主 agent 明确「任务因宿主重启中断」;ClosedReason
|
|
785
|
+
// 枚举不扩展(sidecar/entry 面最小改动,"gc" 由 error 载体补足失败语义)。
|
|
786
|
+
const inFlightAbortedError =
|
|
787
|
+
rec0.resumable === true
|
|
788
|
+
? undefined
|
|
789
|
+
: "orphan recovery: task aborted by host restart (in-flight at shutdown; session context lost" +
|
|
790
|
+
(parseOk ? "" : "; truncated last line") + ")";
|
|
772
791
|
this.reportSubagentRecord({
|
|
773
792
|
...rec0,
|
|
774
793
|
status: "closed",
|
|
775
794
|
closedReason: "gc",
|
|
776
795
|
endedAt: Date.now(),
|
|
777
|
-
...(
|
|
796
|
+
...(inFlightAbortedError !== undefined
|
|
797
|
+
? { error: inFlightAbortedError }
|
|
798
|
+
: parseOk
|
|
799
|
+
? {}
|
|
800
|
+
: { error: "orphan recovery: subagent session ended abnormally (truncated last line)" }),
|
|
778
801
|
});
|
|
779
802
|
}
|
|
780
803
|
|
|
@@ -794,6 +817,10 @@ export class RecordStore {
|
|
|
794
817
|
// `?? ""`),pickStr 签名宽返回 string|undefined —— `?? ""` 运行时不可达,
|
|
795
818
|
// 仅满足 model 非可选类型,空串回退语义不变(cur 空 → src,src 也空 → "")。
|
|
796
819
|
model: pickStr(rec.model, last.model) ?? "",
|
|
820
|
+
// [W4 boot 分区] 轮终执行态信号(resumable)随末条 entry 保留:子文件侧重建
|
|
821
|
+
// (reconstructAll)不带该信号,boot 分区的「already-resumable-idle 重认领 vs
|
|
822
|
+
// in-flight 直断」分流(finalizeOrphanRecord)只能从主 session 末条 entry 取证。
|
|
823
|
+
resumable: rec.resumable ?? last.resumable,
|
|
797
824
|
};
|
|
798
825
|
}
|
|
799
826
|
|
|
@@ -1,37 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
* env 语义:SOCKET/NODE/SCRIPT 三者同时非空 = relay 激活(全有或全无,无中间态);
|
|
10
|
-
* SESSION_ID/RECORD_ID 是 tee 帧归属键(缺失由代理握手前自检拒绝,退出码 13)。
|
|
11
|
-
*/
|
|
1
|
+
// src/execution/relay-env.ts
|
|
2
|
+
//
|
|
3
|
+
// relay 通道 env 名与协议常量的 re-export shim——单源在
|
|
4
|
+
// @zhushanwen/subagent-engine-sdk(round1-reuse R9 跨进程契约副本收编;core → SDK
|
|
5
|
+
// 边界正向合法)。本文件保持路径不变以保住 package.json exports 的 ./relay-env
|
|
6
|
+
// 子入口(semver 面:runtime/extension 消费方 import specifier 不变)。
|
|
7
|
+
// 代理脚本 relay.mjs 仍为内嵌镜像(零依赖脚本不能 import workspace 包),
|
|
8
|
+
// 镜像一致性由 conformance relay 变体断言锁定。
|
|
12
9
|
|
|
13
|
-
export
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
/** 握手被拒:协议版本不匹配(安装损坏,重装应用)。 */
|
|
25
|
-
VERSION_MISMATCH: 10,
|
|
26
|
-
/** relay socket 不可达(runtime 未运行或已重启)。 */
|
|
27
|
-
SOCKET_UNREACHABLE: 11,
|
|
28
|
-
/** socket 中途断开(runtime 崩溃等)——代理生命线断即退。 */
|
|
29
|
-
SOCKET_CLOSED: 12,
|
|
30
|
-
/** 归属 env(SESSION_ID/RECORD_ID)缺失——防无归属帧污染广播。 */
|
|
31
|
-
MISSING_IDENTITY: 13,
|
|
32
|
-
} as const;
|
|
33
|
-
|
|
34
|
-
/** 激活判定:三 env 同时非空才走 relay,任一缺失回落直连 spawn 真实 pi(TUI/独立 pi 零回归)。 */
|
|
35
|
-
export function isRelayActive(env: NodeJS.ProcessEnv | Record<string, string | undefined>): boolean {
|
|
36
|
-
return Boolean(env[RELAY_ENV_SOCKET] && env[RELAY_ENV_NODE] && env[RELAY_ENV_SCRIPT]);
|
|
37
|
-
}
|
|
10
|
+
export {
|
|
11
|
+
RELAY_ENV_SOCKET,
|
|
12
|
+
RELAY_ENV_NODE,
|
|
13
|
+
RELAY_ENV_SCRIPT,
|
|
14
|
+
RELAY_ENV_SESSION_ID,
|
|
15
|
+
RELAY_ENV_RECORD_ID,
|
|
16
|
+
RELAY_PROTOCOL_VERSION,
|
|
17
|
+
RELAY_EXIT_CODES,
|
|
18
|
+
isRelayActive,
|
|
19
|
+
readRelayForwardEnv,
|
|
20
|
+
} from "@zhushanwen/subagent-engine-sdk";
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// src/execution/round-supervisor/domain.ts
|
|
2
|
+
//
|
|
3
|
+
// [W4] 轮次活性监督器——域分类与 record 级判据谓词(单一权威源)。
|
|
4
|
+
//
|
|
5
|
+
// 设计权威源:docs/design/chat-domain-v1x-liveness-governance.md §3.2 D2 前置 1
|
|
6
|
+
// (轮次域分类)+ 前置 2(record 去向单一裁决表)+ 三态判定表。
|
|
7
|
+
//
|
|
8
|
+
// 判定域 = run 域一次性任务(resumable 且无进程驱动)+ workflow 域 resumable run。
|
|
9
|
+
// chat/conversation 形态(record.chatMode)**豁免**出 no-progress 判定域:轮终 idle
|
|
10
|
+
// 现状(doFinalizeRoundToIdle + idle timer / idle-gc)+ settled-watchdog 两段守护
|
|
11
|
+
// 管辖——豁免只意味着「监督器不重复管」,不意味着无界(D2 R2 精确化)。
|
|
12
|
+
//
|
|
13
|
+
// 判据状态源钉死为 record 级(R3 核正):pi 引擎 poolKey 恒 'shared' 单进程、
|
|
14
|
+
// ensureConnected 被动重建会重填「镜像整体置死」——镜像不能作持续判据;run 终态
|
|
15
|
+
// failed 即「驱动死亡」的证据,不随引擎进程重建翻转。镜像置死仅作死亡事件的
|
|
16
|
+
// 触发信号(supervisor 的死亡事件纳管入口),不作持续判据。
|
|
17
|
+
//
|
|
18
|
+
// 纳管模型(R3 显式化):死亡事件纳管(run failed / 引擎 exited 事件把 record 纳入
|
|
19
|
+
// 监督域),**重建不解管**(引擎进程重建不解除已纳管 record 的监督,监督器按
|
|
20
|
+
// record 级状态持续判定直至终态或放弃)。本文件的谓词全部只读 record 级状态,
|
|
21
|
+
// 不读引擎镜像——结构性保证「重建不解管」(模拟引擎重建后监督器仍按 record 级判)。
|
|
22
|
+
|
|
23
|
+
import type { ExecutionRecord } from "../types.ts";
|
|
24
|
+
|
|
25
|
+
/** 监督器域分类(判定域先收窄,再谈三态)。 */
|
|
26
|
+
export type SupervisorDomain =
|
|
27
|
+
/** run 域一次性任务(非 chatMode record)——监督域主体。 */
|
|
28
|
+
| "run"
|
|
29
|
+
/** conversation/chat 形态(record.chatMode)——豁免,现状机制管辖。 */
|
|
30
|
+
| "conversation";
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* 域分类(裁决表 conversation 行「任何触发不入监督域」的判定锚)。
|
|
34
|
+
* record.chatMode === true → conversation(豁免);否则 → run 域。
|
|
35
|
+
* (workflow 域 resumable run 的活性收口 = kill-9 恢复链 + idle-gc startedAt 锚
|
|
36
|
+
* 归档 + sweep 对账——workflow run 不在 RecordStore,其注册对账按 type=workflow
|
|
37
|
+
* 保守跳过,见 reconcile-sweep.ts。)
|
|
38
|
+
*/
|
|
39
|
+
export function classifySupervisorDomain(record: Pick<ExecutionRecord, "chatMode">): SupervisorDomain {
|
|
40
|
+
return record.chatMode === true ? "conversation" : "run";
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* 三态判定「该唤醒」的 record 级判据(设计三态表逐字实现):
|
|
45
|
+
* **resumable 未终态 且 无在途 run / 无进程驱动**。
|
|
46
|
+
*
|
|
47
|
+
* 入参解耦说明:谓词只消费 record 级状态与两个布尔(在途 run / 活进程句柄),
|
|
48
|
+
* 由调用方(supervisor)供给——「有在途 run」来自 supervisor 的在途记账
|
|
49
|
+
* (subagent-service 报告),「有进程驱动」来自生命周期镜像谓词。本函数不读
|
|
50
|
+
* 镜像/引擎状态,结构性满足「镜像置死只作触发信号不作持续判据」。
|
|
51
|
+
*
|
|
52
|
+
* 「已有完成产出」(SP-5 upgrade 等待态)不在本谓词域——由调用方以 hasResult
|
|
53
|
+
* 单独判定(视图投影面分离,supervisor.evaluate 消费)。
|
|
54
|
+
*/
|
|
55
|
+
export function isAwakeWarrantedShape(
|
|
56
|
+
record: { status: string; resumable: boolean; chatMode: boolean },
|
|
57
|
+
hasInFlightRun: boolean,
|
|
58
|
+
hasLiveProcess: boolean,
|
|
59
|
+
): boolean {
|
|
60
|
+
if (record.chatMode === true) return false; // conversation 豁免
|
|
61
|
+
if (record.status !== "running") return false; // 终态 = 已收口
|
|
62
|
+
if (hasInFlightRun || hasLiveProcess) return false; // 该等(有驱动)→ 不干预
|
|
63
|
+
return record.resumable === true;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* boot 分区「already-resumable-idle」重认领谓词(与裁决表同源——设计 D4 连带面 2
|
|
68
|
+
* ②「启动扫描 resumable 且无进程驱动且非 conversation 形态」的单一权威实现;
|
|
69
|
+
* cold-resurrect.ts 的 message 冷查链不承载启动扫描,本谓词即其「cold-resurrect
|
|
70
|
+
* 扩展」落点,record-store 孤儿恢复的保留分支与 supervisor.bootPartition 共同消费
|
|
71
|
+
* 同一判据形态)。
|
|
72
|
+
*
|
|
73
|
+
* 判据:非 conversation 形态 + status=running + resumable 信号(轮终写点 set true;
|
|
74
|
+
* 冷路径续轮清除——重启前已在途的 record resumable=undefined,走 boot 直断分支
|
|
75
|
+
* 而非重认领)+ **无完成产出**(resumable=true 且 result 有值是 SP-5 one-shot
|
|
76
|
+
* 完成态——任务已完成,直断 closed/gc 无损,不属重认领域;result 缺失才是 W4
|
|
77
|
+
* 死亡纳管态跨重启的形态)。
|
|
78
|
+
*/
|
|
79
|
+
export function isBootReadoptable(record: {
|
|
80
|
+
status: string;
|
|
81
|
+
resumable: boolean;
|
|
82
|
+
chatMode: boolean;
|
|
83
|
+
hasResult: boolean;
|
|
84
|
+
}): boolean {
|
|
85
|
+
if (record.chatMode) return false;
|
|
86
|
+
if (record.status !== "running") return false;
|
|
87
|
+
if (!record.resumable) return false;
|
|
88
|
+
return !record.hasResult;
|
|
89
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// src/execution/round-supervisor/index.ts
|
|
2
|
+
//
|
|
3
|
+
// [W4] 轮次活性监督器公共出口(SubagentService 与测试的消费面)。
|
|
4
|
+
|
|
5
|
+
export {
|
|
6
|
+
classifySupervisorDomain,
|
|
7
|
+
isAwakeWarrantedShape,
|
|
8
|
+
isBootReadoptable,
|
|
9
|
+
type SupervisorDomain,
|
|
10
|
+
} from "./domain.ts";
|
|
11
|
+
export {
|
|
12
|
+
classifyReplacement,
|
|
13
|
+
type ReplacementCandidate,
|
|
14
|
+
type ReplacementProbeSubject,
|
|
15
|
+
type ReplacementVerdict,
|
|
16
|
+
} from "./notify-accounting.ts";
|
|
17
|
+
export {
|
|
18
|
+
runReconcileSweep,
|
|
19
|
+
type ReconcileSweepDeps,
|
|
20
|
+
type ReconcileSweepResult,
|
|
21
|
+
type SupervisedRecordState,
|
|
22
|
+
} from "./reconcile-sweep.ts";
|
|
23
|
+
export {
|
|
24
|
+
ROUND_SUPERVISOR_WATCHDOG_DEFAULT_MS,
|
|
25
|
+
ROUND_SUPERVISOR_WATCHDOG_ENV,
|
|
26
|
+
RoundSupervisor,
|
|
27
|
+
getSupervisorWatchdogMs,
|
|
28
|
+
isSupervisorGiveUpDisabled,
|
|
29
|
+
type GiveUpKind,
|
|
30
|
+
type RoundSupervisorDeps,
|
|
31
|
+
type SupervisorCandidateRecord,
|
|
32
|
+
type SupervisorRecordView,
|
|
33
|
+
} from "./supervisor.ts";
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// src/execution/round-supervisor/notify-accounting.ts
|
|
2
|
+
//
|
|
3
|
+
// [W4] 通知对账——送决策指引前查替代的两级启发式(纯函数)。
|
|
4
|
+
//
|
|
5
|
+
// 设计权威源:docs/design/chat-domain-v1x-liveness-governance.md §3.2 D2「通知对账」
|
|
6
|
+
// (R3 增补、R4 钉死判定语义)。
|
|
7
|
+
//
|
|
8
|
+
// 背景:主 agent 是唯一决策者,重派不被禁止——即使合并单条通知,它仍可能在收到
|
|
9
|
+
// 指引前合法地重派了新任务。record 数据模型不存在重派关联字段(parentRecordId 是
|
|
10
|
+
// 层级语义、rootSessionId 是 session 隔离语义、task 是完整 prompt 非关联键),
|
|
11
|
+
// 对账判定为显式定义的两级启发式:
|
|
12
|
+
// - 高置信替代:同 rootSessionId + 同 agent 名 + 同 slug(≤35 字符短标签,重派
|
|
13
|
+
// 同任务大概率同 slug)+ 决策指引看门狗窗内新建 → 撤销指引,改送「原任务已被
|
|
14
|
+
// 新任务替代」终止通知 + 对原 record 走该放弃路径(终态化 + 注销);
|
|
15
|
+
// - 低置信(仅 agent 同名):不撤销指引,但指引内容自带豁免声明(「若你已重新
|
|
16
|
+
// 派发或不再需要此任务,忽略本指引;原任务将在看门狗到期后自动终止」)。
|
|
17
|
+
//
|
|
18
|
+
// 两失败方向登记(设计四要素):
|
|
19
|
+
// - 漏判(重派改写 slug/task 致高置信不命中)→ 残余双执行;重审触发 = 实测双执行
|
|
20
|
+
// 反馈 ≥1 例 → 升级「supersedes 显式引用」方案;
|
|
21
|
+
// - 误判(无关任务撞 slug)→ 原任务被错误终态化——危害轻(原任务本已无进程驱动,
|
|
22
|
+
// 仅损失 resume 可能)。
|
|
23
|
+
|
|
24
|
+
/** 对账候选(重派承接任务的 record 投影面)。 */
|
|
25
|
+
export interface ReplacementCandidate {
|
|
26
|
+
id: string;
|
|
27
|
+
rootSessionId: string | undefined;
|
|
28
|
+
/** agent 类型名(record.agent)。 */
|
|
29
|
+
agentName: string;
|
|
30
|
+
/** 人类短标签(record.slug,≤35 字符)。 */
|
|
31
|
+
slug: string;
|
|
32
|
+
/** 创建时刻(record.startedAt,ms)。 */
|
|
33
|
+
startedAt: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** 被接管 record 的对账基准面。 */
|
|
37
|
+
export interface ReplacementProbeSubject {
|
|
38
|
+
id: string;
|
|
39
|
+
rootSessionId: string | undefined;
|
|
40
|
+
agentName: string;
|
|
41
|
+
slug: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** 对账结论(两级 + 无命中)。 */
|
|
45
|
+
export type ReplacementVerdict =
|
|
46
|
+
| { kind: "high-confidence"; replacementId: string }
|
|
47
|
+
| { kind: "low-confidence" }
|
|
48
|
+
| { kind: "none" };
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* 高置信判定窗口:候选的 startedAt 必须落在「决策指引看门狗窗」内(接管时刻起
|
|
52
|
+
* 算——窗内新建才有「承接了同一任务」的置信;窗外的同名任务与本接管无时序关联)。
|
|
53
|
+
* 窗值由调用方传(= 监督器决策看门狗窗,同源常量)。
|
|
54
|
+
*/
|
|
55
|
+
export function classifyReplacement(
|
|
56
|
+
subject: ReplacementProbeSubject,
|
|
57
|
+
candidates: readonly ReplacementCandidate[],
|
|
58
|
+
windowMs: number,
|
|
59
|
+
now: number,
|
|
60
|
+
): ReplacementVerdict {
|
|
61
|
+
let sameAgentOnly = false;
|
|
62
|
+
for (const candidate of candidates) {
|
|
63
|
+
if (candidate.id === subject.id) continue;
|
|
64
|
+
if (candidate.agentName !== subject.agentName) continue;
|
|
65
|
+
// 时序窗(高/低置信共同的门):窗内新建才参与对账——窗外的同名任务与本接管
|
|
66
|
+
// 无时序关联(预先存在的同名任务不是替代者)。
|
|
67
|
+
if (now - candidate.startedAt > windowMs) continue;
|
|
68
|
+
// [契约锚] sameRoot 在生产装配下恒真——此检查是对供给侧不变量的防御性复认,
|
|
69
|
+
// 不是独立生效的第四要素。生产候选源 = supervisor.deps.listCandidateRecords
|
|
70
|
+
// (service-binding.ts supervisorCandidates 已按 getSessionRootId() 预过滤,
|
|
71
|
+
// 循环内候选恒同 root)。约束力悄悄依赖该供给不变量:若换候选源为未按 root
|
|
72
|
+
// 预过滤的全量集,sameRoot 从恒真退化为真实约束——跨 root 命中会从
|
|
73
|
+
// high-confidence 降为 low-confidence(替代收口弱化:原任务改由看门狗到期才
|
|
74
|
+
// 放弃),行为静默漂移。换候选源必须保「root 预过滤」或显式重审本判定语义。
|
|
75
|
+
const sameRoot =
|
|
76
|
+
candidate.rootSessionId !== undefined &&
|
|
77
|
+
candidate.rootSessionId === subject.rootSessionId;
|
|
78
|
+
const sameSlug =
|
|
79
|
+
subject.slug !== "" &&
|
|
80
|
+
candidate.slug === subject.slug;
|
|
81
|
+
if (sameRoot && sameSlug) {
|
|
82
|
+
return { kind: "high-confidence", replacementId: candidate.id };
|
|
83
|
+
}
|
|
84
|
+
sameAgentOnly = true;
|
|
85
|
+
}
|
|
86
|
+
return sameAgentOnly ? { kind: "low-confidence" } : { kind: "none" };
|
|
87
|
+
}
|