@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
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
// src/execution/engine/host/host-bridge.ts
|
|
2
|
+
//
|
|
3
|
+
// HostBridge 契约 + core 侧实现(W6,impl-plan §2.6 / 设计 §3.8 D2 表 + 最小示例)。
|
|
4
|
+
//
|
|
5
|
+
// 归属裁定(设计 §3.8 D2 表逐条):PiEngineService 的 9 成员中——executeAndAwait /
|
|
6
|
+
// getRecordForAction / collectRecords / closeSubagent / cancel / ChatRoundTicket /
|
|
7
|
+
// record 状态回写 / idle+activate lock 定时器——都是「宿主执行链 / 数据所有权在宿主」,
|
|
8
|
+
// 归 HostBridge(core);pi 包(W7)经 host/* 反向请求消费本面。spawnedChildren 归
|
|
9
|
+
// 引擎进程(core 镜像见同目录 spawned-children.ts);sendPromptCommand / EPIPE 兜底 /
|
|
10
|
+
// 冷续轮 resume(stdin-writer)归 pi 包(W7 迁移物)。
|
|
11
|
+
//
|
|
12
|
+
// 本文件只依赖 core 公共类型(types.ts / record-store / stream-sink /
|
|
13
|
+
// lifecycle-manager / orchestration 类型),不 import inproc pi 引擎目录 内部——它是 pi 包
|
|
14
|
+
// 反向请求消费面的契约落点(协议无关,类型闭包经 HostBridgeServiceFace 泛型参数化)。
|
|
15
|
+
// [F-3] cancel 收敛等待面已删(无生产装配点);D3 core 侧收敛语义由引擎面
|
|
16
|
+
// chat-session.cancel 等价承接,偏差登记见 chat-domain impl-plan §5。
|
|
17
|
+
|
|
18
|
+
import { armIdleTimer, disarmIdleTimer } from "../../lifecycle-manager.ts";
|
|
19
|
+
import type { AgentResult as WorkflowAgentResult } from "../../../orchestration/models/types.ts";
|
|
20
|
+
import type { StatusFilter } from "../../record-store.ts";
|
|
21
|
+
import type { SubagentStream } from "../../stream-sink.ts";
|
|
22
|
+
import type {
|
|
23
|
+
AgentEvent,
|
|
24
|
+
AgentResult,
|
|
25
|
+
ExecuteOptions,
|
|
26
|
+
ExecutionRecord,
|
|
27
|
+
SubagentRecord,
|
|
28
|
+
} from "../../types.ts";
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* chat 域轮次交接包的 core 契约基座(设计 §3.8 D2「ChatRoundTicket → HostBridge」)。
|
|
32
|
+
* pi 专有扩展(identity / SessionRunnerContext / SpawnResumeOpts resume)在
|
|
33
|
+
* pi-engine.ChatRoundTicket extends 本接口(W7 随包迁移;过渡期 record/opts/signal/
|
|
34
|
+
* priority/stream 五字段的宿主编排语义在此单一权威)。
|
|
35
|
+
*/
|
|
36
|
+
export interface HostChatRoundTicket {
|
|
37
|
+
record: ExecutionRecord;
|
|
38
|
+
opts: ExecuteOptions;
|
|
39
|
+
signal: AbortSignal | undefined;
|
|
40
|
+
priority: number;
|
|
41
|
+
stream?: SubagentStream;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* HostBridge 的服务实现面(SubagentService 的结构子集,鸭子类型——与原 pi-engine 的
|
|
46
|
+
* PiEngineService 同一形态的协议化泛化:chat 域轮次面泛型参数化,pi 绑定 =
|
|
47
|
+
* HostBridgeServiceFace<ChatRoundTicket>,见 pi-host-binding.ts 的 re-export)。
|
|
48
|
+
* 为什么用结构接口而非 import SubagentService 类型:防 Service 内部演进连锁影响
|
|
49
|
+
* 契约面 + 测试可注入 fake(PiEngineService 的既有先例,语义照搬)。
|
|
50
|
+
*/
|
|
51
|
+
export interface HostBridgeServiceFace<TTicket extends HostChatRoundTicket = HostChatRoundTicket> {
|
|
52
|
+
executeAndAwait(
|
|
53
|
+
opts: ExecuteOptions,
|
|
54
|
+
signal?: AbortSignal,
|
|
55
|
+
onEvent?: (event: AgentEvent) => void,
|
|
56
|
+
stream?: SubagentStream,
|
|
57
|
+
): Promise<WorkflowAgentResult>;
|
|
58
|
+
getRecordForAction(id: string): ExecutionRecord;
|
|
59
|
+
closeSubagent(record: ExecutionRecord, force: boolean): Promise<void>;
|
|
60
|
+
cancel(id: string): boolean;
|
|
61
|
+
collectRecords(limit: number, statusFilter?: StatusFilter): SubagentRecord[];
|
|
62
|
+
/** chat 域轮次交接(run 的 chat 分支入口):按 taskId 取走预备包(一次性消费)。 */
|
|
63
|
+
takeChatRound?(taskId: string): TTicket | undefined;
|
|
64
|
+
/** 执行预备的 chat 轮次(编排归 Service:pool 槽 + runSpawn + 终态迁移)。 */
|
|
65
|
+
runChatRound?(ticket: TTicket): Promise<AgentResult>;
|
|
66
|
+
/** 冷路径续轮(interact message 分支的编排回调:守卫 + record 迁移 + kick-off)。 */
|
|
67
|
+
resumeChatRound?(record: ExecutionRecord, text: string): void;
|
|
68
|
+
/** record 状态迁移上报(热路径投递后让 runtime 派生缓存失效 / GUI 回流)。 */
|
|
69
|
+
reportRecordTransition?(record: ExecutionRecord): void;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* HostBridge 接口(设计 §3.8 最小示例,9 方法)。core 侧实现;pi 包经 host/* 反向
|
|
74
|
+
* 请求消费。签名与最小示例的两处实现级偏差(均按现状语义落地):
|
|
75
|
+
* - getRecordForAction 返回 ExecutionRecord | null(现状实现面的活 record 形态;
|
|
76
|
+
* 不存在 / 不可达 → null,引擎侧 resolveRecord 的 try/catch 语义内聚到本面);
|
|
77
|
+
* - reportRecordTransition 收 record 对象(现状状态回写以 record 为单位整体上报,
|
|
78
|
+
* 无 patch 增量形态——造 patch 形态属凭空造词,W7 反向通道载荷再议)。
|
|
79
|
+
*/
|
|
80
|
+
export interface HostBridge {
|
|
81
|
+
executeAndAwait(
|
|
82
|
+
opts: ExecuteOptions,
|
|
83
|
+
signal?: AbortSignal,
|
|
84
|
+
onEvent?: (event: AgentEvent) => void,
|
|
85
|
+
stream?: SubagentStream,
|
|
86
|
+
): Promise<WorkflowAgentResult>;
|
|
87
|
+
getRecordForAction(id: string): ExecutionRecord | null;
|
|
88
|
+
collectRecords(limit: number, filter?: StatusFilter): SubagentRecord[];
|
|
89
|
+
closeSubagent(record: ExecutionRecord, force: boolean): Promise<void>;
|
|
90
|
+
cancel(id: string): Promise<void>;
|
|
91
|
+
takeChatRound(taskId: string): HostChatRoundTicket | null;
|
|
92
|
+
reportRecordTransition(record: ExecutionRecord): void;
|
|
93
|
+
armIdleTimer(id: string, ms: number): void;
|
|
94
|
+
disarmIdleTimer(id: string): void;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** createHostBridge 依赖(服务面 + idle 超时处置)。 */
|
|
98
|
+
export interface HostBridgeDeps {
|
|
99
|
+
/** HostBridge 服务实现面(生产 = SubagentService 的结构子集)。 */
|
|
100
|
+
service: HostBridgeServiceFace;
|
|
101
|
+
/**
|
|
102
|
+
* idle timer 超时处置(回收层兜底):宿主在 arm 时注入杀链回调(现状语义 =
|
|
103
|
+
* killRecordChildWithEscalation 升级杀,pi-engine.rearmIdleTimerAfterHotPathFailure
|
|
104
|
+
* 同款)。不注入则 arm 时 throw(无处置的 idle timer = 永不回收的泄漏源,宁可显式)。
|
|
105
|
+
*/
|
|
106
|
+
onIdleTimeout: (recordId: string) => void;
|
|
107
|
+
// [F-3 删除登记] 曾有的 waitForRoundTerminal / escalateKill 可选注入(W3 D3 cancel
|
|
108
|
+
// 终态等待面)已删:createHostBridge 全仓无生产调用点,且该面与生产 cancel 链结构
|
|
109
|
+
// 冲突(cancelBackground 同步 unregisterChatRoundRoute 后,waitForRoundTerminal 再
|
|
110
|
+
// race 轮终相位恒等满 3s 超时)。D3 core 侧收敛语义由引擎面等价承接 =
|
|
111
|
+
// chat-session.cancel(waiter 先于 kill 注册 + killChain 有界升级),偏差登记见
|
|
112
|
+
// chat-domain-v1x-liveness-governance.impl-plan.md §5。
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** HostBridge core 实现(SubagentService 编排面的协议化视图)。 */
|
|
116
|
+
export function createHostBridge(deps: HostBridgeDeps): HostBridge {
|
|
117
|
+
const { service } = deps;
|
|
118
|
+
return {
|
|
119
|
+
executeAndAwait: (opts, signal, onEvent, stream) =>
|
|
120
|
+
service.executeAndAwait(opts, signal, onEvent, stream),
|
|
121
|
+
getRecordForAction: (id) => {
|
|
122
|
+
try {
|
|
123
|
+
return service.getRecordForAction(id);
|
|
124
|
+
} catch {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
collectRecords: (limit, filter) => service.collectRecords(limit, filter),
|
|
129
|
+
closeSubagent: (record, force) => service.closeSubagent(record, force),
|
|
130
|
+
/**
|
|
131
|
+
* cancel 语义 = 受理即返回(service.cancel 同步布尔 → 契约 void)。
|
|
132
|
+
* [F-3 删除登记] 终态等待/杀链升级面已删(无生产装配点 + 与 cancelBackground 的
|
|
133
|
+
* 路由注销冲突,见 HostBridgeDeps 尾注);生产收敛语义由引擎面承接 =
|
|
134
|
+
* chat-session.cancel(waiter 先于 kill 注册 → 等 roundLifecycle 终态相位 →
|
|
135
|
+
* CANCEL_SETTLE_GRACE_MS 未收敛走 killChain 有界升级)。resolve 语义归引擎侧
|
|
136
|
+
* 判 notResumable(契约注释,W6 起如此)。
|
|
137
|
+
*/
|
|
138
|
+
cancel: async (id) => {
|
|
139
|
+
service.cancel(id);
|
|
140
|
+
},
|
|
141
|
+
takeChatRound: (taskId) => service.takeChatRound?.(taskId) ?? null,
|
|
142
|
+
reportRecordTransition: (record) => service.reportRecordTransition?.(record),
|
|
143
|
+
armIdleTimer: (id, ms) => {
|
|
144
|
+
armIdleTimer(id, () => deps.onIdleTimeout(id), ms);
|
|
145
|
+
},
|
|
146
|
+
disarmIdleTimer: (id) => {
|
|
147
|
+
disarmIdleTimer(id);
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// src/execution/engine/host/host-ui-endpoint.ts
|
|
2
|
+
//
|
|
3
|
+
// core 壳侧 host/askUser 应答端登记处(W6,R3 MF-A / impl-plan §2.6 末条)。
|
|
4
|
+
//
|
|
5
|
+
// 接线链路:引擎进程经协议帧④ host/askUser 反向请求 → EngineClient reverse-router
|
|
6
|
+
// (W2 已交付,ack 两阶段 R9-2 语义)→ EngineClientOptions.uiRequestHandler 注入点 →
|
|
7
|
+
// 本登记处的 getter(discovery portFactory 构造 EngineClient 时读取)→ SubagentService
|
|
8
|
+
// init/initSession.uiRequestHandler([D4-④] 唯一注入入口,应答处理复用
|
|
9
|
+
// ui-request-handler-factory / dialog-queue 应答链路;[W3] inproc inproc UI 请求队列(已删)
|
|
10
|
+
// 随 inproc pi 引擎目录 删除消亡——chat 域 UI 请求同样经本通道,关联键 = spawn 轮 runId)。
|
|
11
|
+
//
|
|
12
|
+
// 为什么是登记处而非直接传参:EngineClient 在 discovery portFactory 内构造(惰性,
|
|
13
|
+
// 首次 getEngine),构造点拿不到 Service 实例——进程级 endpoint 槽位把「handler 何时
|
|
14
|
+
// 注册」(session_start)与「EngineClient 何时构造」(首次引擎使用,晚于 session_start)
|
|
15
|
+
// 解耦。globalThis[Symbol.for] 持有防 jiti 双路径加载分裂(registry.ts 同款惯例)。
|
|
16
|
+
|
|
17
|
+
import type { UiRequestHandler } from "@zhushanwen/subagent-engine-sdk";
|
|
18
|
+
|
|
19
|
+
const ENDPOINT_SLOT_KEY = Symbol.for(
|
|
20
|
+
"@zhushanwen/pi-subagent-workflow.hostUiRequestEndpoint",
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
function endpointSlot(): { handler: UiRequestHandler | undefined } {
|
|
24
|
+
let slot = Reflect.get(globalThis, ENDPOINT_SLOT_KEY) as
|
|
25
|
+
| { handler: UiRequestHandler | undefined }
|
|
26
|
+
| undefined;
|
|
27
|
+
if (!slot) {
|
|
28
|
+
slot = { handler: undefined };
|
|
29
|
+
Reflect.set(globalThis, ENDPOINT_SLOT_KEY, slot);
|
|
30
|
+
}
|
|
31
|
+
return slot;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** 登记壳侧应答端(SubagentService 在 uiRequestHandler 三态写点同步调用:init / initSession / dispose)。 */
|
|
35
|
+
export function setHostUiRequestEndpoint(handler: UiRequestHandler | undefined): void {
|
|
36
|
+
endpointSlot().handler = handler;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** 读壳侧应答端(discovery portFactory 构造 EngineClient 时取值;undefined → 引擎收 {unsupported:true} 自行降级)。 */
|
|
40
|
+
export function getHostUiRequestEndpoint(): UiRequestHandler | undefined {
|
|
41
|
+
return endpointSlot().handler;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** 测试隔离:清空登记。 */
|
|
45
|
+
export function _resetHostUiRequestEndpointForTest(): void {
|
|
46
|
+
endpointSlot().handler = undefined;
|
|
47
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// src/execution/engine/host/pi-host-binding.ts
|
|
2
|
+
//
|
|
3
|
+
// pi 引擎的宿主侧绑定点(W6 建立;[W3 chat 域收口] 重写为纯协议形态)。
|
|
4
|
+
// 职责 = pi 引擎的 EnginePort 解析与公共常量的宿主侧单一出口——chat 域 inproc 引擎
|
|
5
|
+
// (inproc pi 引擎目录)已随 chat-domain-v1x-liveness-governance W3 删除,chat 轮次与 run
|
|
6
|
+
// 域同样经协议客户端(RemoteEngine,registry 'pi' 由三级发现装载 cli descriptor)
|
|
7
|
+
// 发往 pi-subagent-cli 引擎进程(G1:pi 引擎单一 CLI 形态,core 壳侧零内建引擎)。
|
|
8
|
+
//
|
|
9
|
+
// 两个出口:
|
|
10
|
+
// - PI_POOL_KEY 常量:pi 无隔离池(PI_CODING_AGENT_DIR 全局一份)→ poolKey 恒
|
|
11
|
+
// 'shared'。原 inproc pi-engine(已删) 定义随删件收敛到本公共面(字面量不变,
|
|
12
|
+
// 引擎包内侧等价物在 pi-subagent-cli constants.ts——跨包字面量一致性由协议
|
|
13
|
+
// handle.poolKey 往返锚定);
|
|
14
|
+
// - resolveHostPiEnginePort:宿主侧(SAR / chat 域路由)pi EnginePort 解析——
|
|
15
|
+
// registry 'pi' 返回发现器装载的 cli 形态 port(RemoteEngine);未注册(引擎包
|
|
16
|
+
// 未装/发现失败)→ 不可用 stub:路由层对 pi 恒同步短路(本地 pi 恒可用口径),
|
|
17
|
+
// 真正的拒绝发生在首次 engine.run——stub 抛 EngineNotFoundError(含安装指引),
|
|
18
|
+
// 由 SAR「不 reject」契约收口进 result.error。
|
|
19
|
+
//
|
|
20
|
+
// maxTurnsToWatchdogMs:maxTurns→watchdog 毫秒换算的 barrel 公共出口(U3/U4 / D7,
|
|
21
|
+
// 两宿主预算一致性 S2 的函数级锚点)。原 inproc session-runner(已删) 定义随删件
|
|
22
|
+
// 收敛到本文件——算法(floor 30min + 每轮 5min,均 floor 语义)与运行时真实消费方
|
|
23
|
+
// (pi-subagent-cli spawn-runner 的 spawn watchdog)保持同源常量,漂移由 conformance
|
|
24
|
+
// chat golden(spawn-args 断言)在引擎包侧守护。
|
|
25
|
+
|
|
26
|
+
import type { EnginePort } from "../port.ts";
|
|
27
|
+
import { EngineNotFoundError, getEngine, hasEngine, listEngines } from "../registry.ts";
|
|
28
|
+
|
|
29
|
+
/** pi 无隔离池(PI_CODING_AGENT_DIR 全局一份,协议化设计 §3.3.9),poolKey 恒 'shared'。 */
|
|
30
|
+
export const PI_POOL_KEY = "shared";
|
|
31
|
+
|
|
32
|
+
/** watchdog 换算下限(分钟):与引擎包 spawn-runner 的 floor 同源(30min)。 */
|
|
33
|
+
const WATCHDOG_FLOOR_MINUTES = 30;
|
|
34
|
+
/** watchdog 每轮预算(分钟/turn):同源常量(5min/turn)。 */
|
|
35
|
+
const WATCHDOG_MINUTES_PER_TURN = 5;
|
|
36
|
+
|
|
37
|
+
const MS_PER_SECOND = 1000;
|
|
38
|
+
const SECONDS_PER_MINUTE = 60;
|
|
39
|
+
|
|
40
|
+
/** maxTurns → spawn watchdog 毫秒估算(floor 语义:maxTurns 小时取下限)。 */
|
|
41
|
+
export function maxTurnsToWatchdogMs(maxTurns: number): number {
|
|
42
|
+
return Math.max(
|
|
43
|
+
WATCHDOG_FLOOR_MINUTES * SECONDS_PER_MINUTE * MS_PER_SECOND,
|
|
44
|
+
maxTurns * WATCHDOG_MINUTES_PER_TURN * SECONDS_PER_MINUTE * MS_PER_SECOND,
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* 宿主侧 pi EnginePort 解析(SAR / chat 域路由):registry 的 'pi'(发现器装载的
|
|
50
|
+
* cli descriptor → RemoteEngine)直接返回——chat 轮次与 run 域同路(协议 run(interact)
|
|
51
|
+
* 发往 pi-subagent-cli 引擎进程)。
|
|
52
|
+
* [U-2 一致性修复] pi **未注册**(引擎包未装/发现失败)时返回不可用 stub,不静默
|
|
53
|
+
* 直构任何本地实例——保留设计 D4「全不可用 → 派发期 engine_not_found + 安装指引」
|
|
54
|
+
* 错误契约(zcode 侧 d8-compat 同语义,两引擎对称)。
|
|
55
|
+
*
|
|
56
|
+
* @param getService 未消费(历史签名兼容位——inproc per-session DI 重绑形态随
|
|
57
|
+
* inproc pi 引擎目录 删除消亡;保留形参使 SAR 调用点零改动,W8 收口时随调用面一并清理)。
|
|
58
|
+
*/
|
|
59
|
+
export function resolveHostPiEnginePort(_getService?: () => unknown): EnginePort {
|
|
60
|
+
if (hasEngine("pi")) return getEngine("pi");
|
|
61
|
+
return piUnavailableEnginePort();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** pi 不可用 stub(D4):一切执行面抛 engine_not_found;capabilities 全放行(拒绝点唯一化在 run)。 */
|
|
65
|
+
function piUnavailableEnginePort(): EnginePort {
|
|
66
|
+
const fail = (): never => {
|
|
67
|
+
throw new EngineNotFoundError("pi", listEngines());
|
|
68
|
+
};
|
|
69
|
+
return {
|
|
70
|
+
id: "pi",
|
|
71
|
+
// 与 pi-subagent-cli manifest capabilities 逐位一致(快照权威;stub 的能力位
|
|
72
|
+
// 只被 gate 同步面在 run 前读取,真正的拒绝发生在 stub.run 抛 engine_not_found)。
|
|
73
|
+
capabilities: () => ({
|
|
74
|
+
schemaEnforcement: "native",
|
|
75
|
+
steer: "unsupported",
|
|
76
|
+
conversation: "native",
|
|
77
|
+
personaInjection: "flag",
|
|
78
|
+
eventGranularity: "stream",
|
|
79
|
+
sandbox: "emulated",
|
|
80
|
+
sessionRead: "full",
|
|
81
|
+
resume: "native",
|
|
82
|
+
interrupt: "kill-only",
|
|
83
|
+
permissionMode: "native",
|
|
84
|
+
maxTurns: true,
|
|
85
|
+
}),
|
|
86
|
+
probe: () => fail(),
|
|
87
|
+
run: () => fail(),
|
|
88
|
+
interact: () => fail(),
|
|
89
|
+
read: () => fail(),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
// src/execution/engine/host/spawned-children.ts
|
|
2
|
+
//
|
|
3
|
+
// core 侧 spawnedChildren 状态镜像(W6 建立;[W3 chat 域收口] 去除 inproc 过渡桥,
|
|
4
|
+
// 纯镜像形态——设计 §3.8 D2 归属裁定的终态:spawnedChildren Map + 子进程收割的
|
|
5
|
+
// 持有方 = 引擎进程,core 只持状态投影)。
|
|
6
|
+
//
|
|
7
|
+
// 本文件是 core 侧的公共消费面:
|
|
8
|
+
// - subagent-service / subprocess-agent-runner 的注册与镜像记账调用改经本模块,
|
|
9
|
+
// 不深路径 import 引擎内部(R3 S-C / R1 MF-5 改线落点);
|
|
10
|
+
// - lifecycle-predicates(hasLiveProcessHandle / isResumable)读本模块读点。
|
|
11
|
+
//
|
|
12
|
+
// [W3] 数据源两路(协议化形态):① cli 引擎经 host/childSpawned / childStateChanged
|
|
13
|
+
// 反向通道上报(client/mirror.ts 落本镜像——失效语义同构);② 历史调用点
|
|
14
|
+
// (cancel/close/idle timer/watchdog 的 killRecordChildWithEscalation)写镜像置死位。
|
|
15
|
+
// 实际进程终止**不经本模块**——子进程活在引擎进程内,终止经协议 interact
|
|
16
|
+
// cancel/close / run 域 cancel 帧承载(宿主侧杀链 = EngineClient killAll 进程组收割,
|
|
17
|
+
// 见 remote-engine abort 分级)。inproc 委托(session-runner Map 并读/委托杀)随
|
|
18
|
+
// inproc pi 引擎目录 删除消亡。
|
|
19
|
+
|
|
20
|
+
import type { ChildProcess } from "node:child_process";
|
|
21
|
+
|
|
22
|
+
// 镜像项(recordId 键 + killed 判据,与 client/mirror.ts 载荷契约同构)。
|
|
23
|
+
export interface SpawnedChildMirrorEntry {
|
|
24
|
+
/** 引擎侧一次性子进程 pid(诊断面;recordId 才是镜像 key)。 */
|
|
25
|
+
pid?: number;
|
|
26
|
+
/** 必含判据(`child !== undefined && !child.killed` 同构):true = 已被杀/已终止。 */
|
|
27
|
+
killed: boolean;
|
|
28
|
+
/** 最近一次状态变更的墙钟时间戳(诊断面)。 */
|
|
29
|
+
updatedAt: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* core 侧 spawnedChildren 状态镜像(进程级单例,globalThis[Symbol.for] 持有防 jiti
|
|
34
|
+
* 双路径加载分裂——registry.ts 同款惯例)。镜像只是状态投影:不发信号、不杀进程
|
|
35
|
+
* (收割 = 引擎进程组级,见文件头)。
|
|
36
|
+
*/
|
|
37
|
+
class CoreSpawnedChildrenMirror {
|
|
38
|
+
private readonly entries = new Map<string, SpawnedChildMirrorEntry>();
|
|
39
|
+
|
|
40
|
+
/** 落项 / 覆盖(同 recordId 重 spawn = 覆盖旧句柄,与引擎侧 Map 同语义)。 */
|
|
41
|
+
register(recordId: string, child: { pid?: number; killed: boolean }): void {
|
|
42
|
+
this.entries.set(recordId, {
|
|
43
|
+
pid: child.pid,
|
|
44
|
+
killed: child.killed,
|
|
45
|
+
updatedAt: Date.now(),
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** 单项置死(杀链入口:killRecordChildWithEscalation 途经)。 */
|
|
50
|
+
markKilled(recordId: string): void {
|
|
51
|
+
const entry = this.entries.get(recordId);
|
|
52
|
+
if (entry !== undefined) {
|
|
53
|
+
entry.killed = true;
|
|
54
|
+
entry.updatedAt = Date.now();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** 整体置死 + 清空(失效语义 2+3:引擎 exit / 重建 / dispose / killAll)。 */
|
|
59
|
+
killAll(): void {
|
|
60
|
+
this.entries.clear();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
getChildByRecord(recordId: string): SpawnedChildMirrorEntry | undefined {
|
|
64
|
+
return this.entries.get(recordId);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** 句柄存活谓词(镜像面;判据与引擎侧 `!child.killed` 同构)。 */
|
|
68
|
+
hasLiveProcessHandle(recordId: string): boolean {
|
|
69
|
+
const entry = this.entries.get(recordId);
|
|
70
|
+
return entry !== undefined && !entry.killed;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** 快照(诊断/测试)。 */
|
|
74
|
+
snapshot(): SpawnedChildMirrorEntry[] {
|
|
75
|
+
return [...this.entries.entries()].map(([recordId, entry]) => ({ recordId, ...entry }));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** 测试隔离专用(生产禁用——进程级全局状态)。 */
|
|
79
|
+
clear(): void {
|
|
80
|
+
this.entries.clear();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const MIRROR_SLOT_KEY = Symbol.for(
|
|
85
|
+
"@zhushanwen/pi-subagent-workflow.coreSpawnedChildrenMirror",
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
function coreMirrorSlot(): CoreSpawnedChildrenMirror {
|
|
89
|
+
let slot = Reflect.get(globalThis, MIRROR_SLOT_KEY) as CoreSpawnedChildrenMirror | undefined;
|
|
90
|
+
if (!slot) {
|
|
91
|
+
slot = new CoreSpawnedChildrenMirror();
|
|
92
|
+
Reflect.set(globalThis, MIRROR_SLOT_KEY, slot);
|
|
93
|
+
}
|
|
94
|
+
return slot;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** core 侧镜像访问点(诊断/测试;生产读点走下方公共 API)。 */
|
|
98
|
+
export function coreSpawnedChildrenMirror(): CoreSpawnedChildrenMirror {
|
|
99
|
+
return coreMirrorSlot();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// ── 公共面 API(subagent-service / SAR 消费)─────────────────────────
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* 子进程注册(宿主记账回调 RunContext.onChildSpawned 的落点):写镜像。
|
|
106
|
+
* 引擎经 host/childSpawned 上报的形态经 client/mirror 落同一张镜像(单源)。
|
|
107
|
+
*/
|
|
108
|
+
export function registerSpawnedChildForRecord(recordId: string, child: ChildProcess): void {
|
|
109
|
+
coreMirrorSlot().register(recordId, { pid: child.pid, killed: child.killed });
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* 单 record 终止记账(镜像置死位):实际终止在引擎进程内(协议 interact cancel /
|
|
114
|
+
* close 或 run 域 cancel 帧承载);宿主侧调用点是终止意图的记账面,宿主进程组级
|
|
115
|
+
* 收割兜底 = EngineClient killAll(EnginePort.dispose / abort 杀链,见 remote-engine)。
|
|
116
|
+
*/
|
|
117
|
+
export function killRecordChildWithEscalation(recordId: string, _source: string): void {
|
|
118
|
+
coreMirrorSlot().markKilled(recordId);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** 全量收割记账(dispose / parent-shutdown):镜像整体置死。 */
|
|
122
|
+
export function killAllSpawnedChildren(_signal: NodeJS.Signals = "SIGTERM"): number {
|
|
123
|
+
const before = coreMirrorSlot().snapshot().length;
|
|
124
|
+
coreMirrorSlot().killAll();
|
|
125
|
+
return before;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* 句柄存活读点(lifecycle-predicates 的 hasLiveProcessHandle / isResumable 消费)。
|
|
130
|
+
* 镜像是唯一数据源(host/childSpawned 上报 + 终止意图置死位)。
|
|
131
|
+
*/
|
|
132
|
+
export function hasLiveProcessHandleCore(recordId: string): boolean {
|
|
133
|
+
return coreMirrorSlot().hasLiveProcessHandle(recordId);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** 测试隔离:清镜像。 */
|
|
137
|
+
export function _resetCoreSpawnedChildrenMirrorForTest(): void {
|
|
138
|
+
coreMirrorSlot().clear();
|
|
139
|
+
}
|
|
@@ -15,7 +15,9 @@
|
|
|
15
15
|
//
|
|
16
16
|
// conversation/fork 在调用本 mapper 前已被 capability-gate 预检拒绝([D3-④]
|
|
17
17
|
// capabilities 驱动的调用前拒绝,非 pi 引擎 unsupported),透传仅保持映射完整性——
|
|
18
|
-
// 未来引擎支持时无需改本函数。
|
|
18
|
+
// 未来引擎支持时无需改本函数。forkFromSessionFile 同属预检面(fork 通道族同判据),
|
|
19
|
+
// 透传语义相同:pi 引擎经协议 task.forkSource 消费(--fork 载体,fork-from 断联恢复),
|
|
20
|
+
// zcode 引擎被 gate 拒绝不会到达。
|
|
19
21
|
|
|
20
22
|
import type { AgentCallOpts } from "../../orchestration/models/types.ts";
|
|
21
23
|
import type { ExecuteOptions } from "../types.ts";
|
|
@@ -24,20 +26,45 @@ import type { ExecuteOptions } from "../types.ts";
|
|
|
24
26
|
export function executeOptionsToEngineTaskSpec(opts: ExecuteOptions): AgentCallOpts {
|
|
25
27
|
return {
|
|
26
28
|
prompt: opts.task,
|
|
29
|
+
...identityFields(opts),
|
|
30
|
+
...budgetFields(opts),
|
|
31
|
+
...deliveryFields(opts),
|
|
32
|
+
// 运行期字段(signal/ctxModel)不入声明——归 RunContext(port.ts 删字段去向)。
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** 声明面基础字段(slug/agent/model/thinkingLevel/skillPath/appendSystemPrompt 同名透传)。 */
|
|
37
|
+
function identityFields(opts: ExecuteOptions): Partial<AgentCallOpts> {
|
|
38
|
+
return {
|
|
27
39
|
...(opts.slug !== undefined ? { description: opts.slug } : {}),
|
|
28
40
|
...(opts.agent !== undefined ? { agent: opts.agent } : {}),
|
|
29
41
|
...(opts.model !== undefined ? { model: opts.model } : {}),
|
|
30
42
|
...(opts.thinkingLevel !== undefined ? { thinkingLevel: opts.thinkingLevel } : {}),
|
|
31
43
|
...(opts.skillPath !== undefined ? { skillPath: opts.skillPath } : {}),
|
|
32
44
|
...(opts.appendSystemPrompt !== undefined ? { appendSystemPrompt: opts.appendSystemPrompt } : {}),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** 约束面字段(schema/maxTurns/graceTurns 同名透传)。 */
|
|
49
|
+
function budgetFields(opts: ExecuteOptions): Partial<AgentCallOpts> {
|
|
50
|
+
return {
|
|
33
51
|
...(opts.schema !== undefined ? { schema: opts.schema } : {}),
|
|
34
52
|
...(opts.maxTurns !== undefined ? { maxTurns: opts.maxTurns } : {}),
|
|
35
53
|
...(opts.graceTurns !== undefined ? { graceTurns: opts.graceTurns } : {}),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** 运行载体字段(fork 族 / worktree / cwd / conversation / idleTimeoutMs 同名透传)。 */
|
|
58
|
+
function deliveryFields(opts: ExecuteOptions): Partial<AgentCallOpts> {
|
|
59
|
+
return {
|
|
36
60
|
...(opts.fork !== undefined ? { fork: opts.fork } : {}),
|
|
61
|
+
// fork-from 源 session 文件(W3 断链修复:协议化后唯一 lossless 载体回到本映射)。
|
|
62
|
+
// 唯一改名点:ExecuteOptions.forkFromSessionFile → 中立任务形状 forkSource
|
|
63
|
+
// (与 SDK 协议字段、引擎侧 SpawnRunParams.forkSource 三层同名)。
|
|
64
|
+
...(opts.forkFromSessionFile !== undefined ? { forkSource: opts.forkFromSessionFile } : {}),
|
|
37
65
|
...(opts.worktree !== undefined ? { worktree: opts.worktree } : {}),
|
|
38
66
|
...(opts.cwd !== undefined ? { cwd: opts.cwd } : {}),
|
|
39
67
|
...(opts.conversation !== undefined ? { conversation: opts.conversation } : {}),
|
|
40
68
|
...(opts.idleTimeoutMs !== undefined ? { idleTimeoutMs: opts.idleTimeoutMs } : {}),
|
|
41
|
-
// 运行期字段(signal/ctxModel)不入声明——归 RunContext(port.ts 删字段去向)。
|
|
42
69
|
};
|
|
43
70
|
}
|
|
@@ -9,6 +9,12 @@
|
|
|
9
9
|
// 修复定案:校验源 = 目标引擎 registry(EnginePort.validateModel 可选面),时机 =
|
|
10
10
|
// 路由之后的派发同步期(record 创建前,不产生孤儿 record)。
|
|
11
11
|
//
|
|
12
|
+
// [W3 契约变更②放宽(协议化)] 「record 创建前拒绝」不再绝对:manifest `modelCatalog`
|
|
13
|
+
// 声明 `dynamic:true` 时,未命中 ref 放行(运行期以引擎为权威,失败 = engine_model_mismatch
|
|
14
|
+
// + record 标 failed);仅 `dynamic:false` 的静态目录保持同步拒(engine_model_unknown)。
|
|
15
|
+
// 成员形态映射(cli 形态):manifest 省略 modelCatalog → validateModel 成员不实现
|
|
16
|
+
// (本入口 :63 `typeof !== "function"` 分支 → 跳过校验恒放行)。
|
|
17
|
+
//
|
|
12
18
|
// 两个调用点共享本入口与错误文案(D2-2 调用点双路径覆盖):
|
|
13
19
|
// ① chat 路径 subagent-service.executeViaEngine(非 pi 分支);
|
|
14
20
|
// ② workflow 路径 subprocess-agent-runner.run(route.engine.run 之前,非 pi 分支)。
|
|
@@ -21,6 +27,51 @@ import { toErrorMessage } from "../../core/error-message.ts";
|
|
|
21
27
|
/** 错误消息中列出的目标引擎可用清单上限(防超长错误信息;与 shared/model-ref 同量级口径)。 */
|
|
22
28
|
const ENGINE_MODEL_LIST_LIMIT = 20;
|
|
23
29
|
|
|
30
|
+
// ============================================================
|
|
31
|
+
// canonical ref 拆分(契约变更④:无斜杠 ref 的 core 侧处理)
|
|
32
|
+
// ============================================================
|
|
33
|
+
|
|
34
|
+
/** canonical ref 拆分结果(ModelInfo 构造子集;name = 整串原样)。 */
|
|
35
|
+
export interface SplitModelRef {
|
|
36
|
+
/** provider 段:有斜杠 = 斜杠前段;无斜杠 = ""(契约④——不落 "<ref>/" 畸形)。 */
|
|
37
|
+
provider: string;
|
|
38
|
+
/** id 段:有斜杠 = 斜杠后段;无斜杠 = 整串。 */
|
|
39
|
+
id: string;
|
|
40
|
+
/** 整串原样(留痕/显示名)。 */
|
|
41
|
+
name: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* canonical ref → {provider, id, name} 拆分(单一权威源)。
|
|
46
|
+
*
|
|
47
|
+
* 契约变更④(协议化后):引擎 validateModel 的 canonicalRef 允许**无斜杠**形态
|
|
48
|
+
* (引擎原样返回的 ref)——拆分时按 `provider=""`、`id=ref`、整串进 `name` 处理。
|
|
49
|
+
* 旧实现把无斜杠 ref 整串塞进 provider(id=""),经 record.model "provider/id" 拼接
|
|
50
|
+
* 落成 `"<ref>/"` 畸形、续聊回读还原出错误 provider——本函数消解该畸形。
|
|
51
|
+
*
|
|
52
|
+
* 消费方:resolveIdentityForEngine(chat 域留痕)与续聊回读(record.model → ModelInfo
|
|
53
|
+
* 重建),两处必须同源拆分,否则写入/回读两侧对同一 ref 给出不同 provider/id。
|
|
54
|
+
*
|
|
55
|
+
* 斜杠位置判定用 `> 0`(与既有口径一致):开头斜杠("/x")视为无有效 provider 段,
|
|
56
|
+
* 走无斜杠分支(防御异常形态,不 crash)。
|
|
57
|
+
*/
|
|
58
|
+
export function splitEngineModelRef(modelStr: string): SplitModelRef {
|
|
59
|
+
const slashIdx = modelStr.indexOf("/");
|
|
60
|
+
if (slashIdx > 0) {
|
|
61
|
+
return { provider: modelStr.slice(0, slashIdx), id: modelStr.slice(slashIdx + 1), name: modelStr };
|
|
62
|
+
}
|
|
63
|
+
return { provider: "", id: modelStr, name: modelStr };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* record.model 留痕词形(SplitModelRef 的写入侧配对函数):provider 为空串时只写 id
|
|
68
|
+
* (不拼斜杠——"/ref" 头斜杠与 "ref/" 尾斜杠同属畸形留痕)。续聊回读侧
|
|
69
|
+
* splitEngineModelRef 对无斜杠串给出 provider=""/id=ref,往返自洽。
|
|
70
|
+
*/
|
|
71
|
+
export function joinEngineModelRef(ref: SplitModelRef): string {
|
|
72
|
+
return ref.provider === "" ? ref.id : `${ref.provider}/${ref.id}`;
|
|
73
|
+
}
|
|
74
|
+
|
|
24
75
|
// ============================================================
|
|
25
76
|
// 场景 2:engine+model 不配套的结构化错误(D2-3)
|
|
26
77
|
// ============================================================
|
|
@@ -45,14 +96,16 @@ class EngineModelMismatchError extends Error {
|
|
|
45
96
|
* 非 pi 引擎的派发同步期 model 校验(两路径统一入口)。
|
|
46
97
|
*
|
|
47
98
|
* - 引擎实现 validateModel:同步裁决(含 undefined = 查引擎缺省模型),返回 canonical
|
|
48
|
-
*
|
|
99
|
+
* ref 供 record.model 留痕;失败包装为 EngineModelMismatchError(场景 2 文案:
|
|
49
100
|
* 点破 registry 独立 + 目标引擎可用清单 + 按引擎区分的省略语义修正动作)。
|
|
101
|
+
* canonical ref 允许**无斜杠**形态(引擎原样返回的 ref,契约变更④)——留痕拆分
|
|
102
|
+
* 归 splitEngineModelRef(provider=""/id=ref/整串进 name),不在本入口裁词形。
|
|
50
103
|
* - 引擎未实现 validateModel:返回 modelRef 原样(透传给其 prepare 期校验兜底——
|
|
51
104
|
* 现状语义,未来引擎零强制接入)。
|
|
52
105
|
*
|
|
53
106
|
* @param engine 路由解析出的目标引擎
|
|
54
107
|
* @param modelRef 显式 model(调用参数或 agent .md frontmatter;undefined = 引擎缺省语义)
|
|
55
|
-
* @returns canonical ref
|
|
108
|
+
* @returns canonical ref(引擎裁决后);未实现校验面时 = modelRef 原样
|
|
56
109
|
*/
|
|
57
110
|
export function validateModelForEngine(
|
|
58
111
|
engine: EnginePort,
|
|
@@ -1,42 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
// src/execution/engine/paths.ts
|
|
2
|
+
//
|
|
3
|
+
// 引擎数据目录布局的 re-export shim:实现体单源 @zhushanwen/subagent-engine-sdk
|
|
4
|
+
// (自本文件逐字等价移入 SDK,迁移处置 impl-plan §2.1 登记的「core 侧引用切换」收口)。
|
|
5
|
+
// 设计权威源:subagent-engine-abstraction.md D5/D6(C-ext-15 同源推导要求单源)。
|
|
6
|
+
//
|
|
7
|
+
// 本文件路径是 core package.json exports `./engine/paths` 子入口的解析目标,
|
|
8
|
+
// 不可移动/删除(semver 面无损);core 内消费方(pool-manager / journal-wiring /
|
|
9
|
+
// session-view-service / routing 测试)import 路径保持不变。
|
|
2
10
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
* 布局:`<dataDir>/engines/<engineId>/<pool-key>/journal-<taskId>.jsonl`
|
|
11
|
-
* 隔离池跨任务保留复用;journal 生命周期跟随 record,不随池删除(D5)。
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
/** 路径段安全编码后的最大字符数(防超长段击穿文件名长度上限;runtime 校验侧同源)。 */
|
|
15
|
-
const MAX_SEG_CHARS = 80;
|
|
16
|
-
|
|
17
|
-
/** 路径段进入文件系统前的安全编码:路径穿越、分隔符、空白、超长全部归一。 */
|
|
18
|
-
export function sanitizeSeg(input: string): string {
|
|
19
|
-
const s = input.replace(/[^A-Za-z0-9-]+/g, '-').replace(/^-+|-+$/g, '');
|
|
20
|
-
return s.length > 0 ? s.slice(0, MAX_SEG_CHARS) : 'default';
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function resolveEnginesRoot(dataDir: string): string {
|
|
24
|
-
return join(dataDir, 'engines');
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function resolveEngineDir(dataDir: string, engineId: string): string {
|
|
28
|
-
return join(resolveEnginesRoot(dataDir), sanitizeSeg(engineId));
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export function resolvePoolDir(dataDir: string, engineId: string, poolKey: string): string {
|
|
32
|
-
return join(resolveEngineDir(dataDir, sanitizeSeg(engineId)), sanitizeSeg(poolKey));
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function resolveJournalPath(
|
|
36
|
-
dataDir: string,
|
|
37
|
-
engineId: string,
|
|
38
|
-
poolKey: string,
|
|
39
|
-
taskId: string,
|
|
40
|
-
): string {
|
|
41
|
-
return join(resolvePoolDir(dataDir, engineId, poolKey), `journal-${sanitizeSeg(taskId)}.jsonl`);
|
|
42
|
-
}
|
|
11
|
+
export {
|
|
12
|
+
sanitizeSeg,
|
|
13
|
+
resolveEnginesRoot,
|
|
14
|
+
resolveEngineDir,
|
|
15
|
+
resolvePoolDir,
|
|
16
|
+
resolveJournalPath,
|
|
17
|
+
} from "@zhushanwen/subagent-engine-sdk";
|