@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
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
// reader.test.ts —— PiEngine reader(P5):readPiSessionView 对 session-reconstructor
|
|
2
|
-
// 的投影包装。断言三件事:①合法 JSONL → SessionView(turns/toolCalls strip 内部态/
|
|
3
|
-
// usage 聚合/source='native');②reconstructor 降级条件(文件缺失/缺 identity/无
|
|
4
|
-
// assistant)→ undefined 不 throw;③不泄漏 InternalToolCall 内部态(_status/startedTs)。
|
|
5
|
-
|
|
6
|
-
import * as fs from "node:fs";
|
|
7
|
-
import * as os from "node:os";
|
|
8
|
-
import * as path from "node:path";
|
|
9
|
-
|
|
10
|
-
import { beforeAll, describe, expect, it } from "vitest";
|
|
11
|
-
|
|
12
|
-
import { readPiSessionView } from "../reader.ts";
|
|
13
|
-
|
|
14
|
-
let tmpDir: string;
|
|
15
|
-
|
|
16
|
-
beforeAll(() => {
|
|
17
|
-
tmpDir = fs.mkdtempSync(join(os.tmpdir(), "pi-reader-"));
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
// node:path 的 join 在 ESM 测试里直接用(避免顶部 import 与 beforeAll 顺序问题)
|
|
21
|
-
function join(...segs: string[]): string {
|
|
22
|
-
return path.join(...segs);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/** 最小合法 subagent JSONL:header + identity + 一轮 assistant(text/thinking/toolCall)+ toolResult。 */
|
|
26
|
-
function writeValidSession(file: string): void {
|
|
27
|
-
const lines = [
|
|
28
|
-
JSON.stringify({ type: "session", id: "pi-sess-1", cwd: "/proj", timestamp: "2026-08-25T10:00:00Z" }),
|
|
29
|
-
JSON.stringify({
|
|
30
|
-
type: "custom",
|
|
31
|
-
customType: "subagent-identity",
|
|
32
|
-
data: { id: "bg-1-abc", agent: "reviewer", mode: "background", task: "review code", slug: "rev", startedAt: 1756000000000 },
|
|
33
|
-
}),
|
|
34
|
-
JSON.stringify({
|
|
35
|
-
type: "message",
|
|
36
|
-
timestamp: "2026-08-25T10:00:01Z",
|
|
37
|
-
message: {
|
|
38
|
-
role: "assistant",
|
|
39
|
-
timestamp: 1756000001000,
|
|
40
|
-
content: [
|
|
41
|
-
{ type: "thinking", thinking: "let me look" },
|
|
42
|
-
{ type: "toolCall", id: "tc-1", name: "bash", arguments: { command: "ls" } },
|
|
43
|
-
],
|
|
44
|
-
usage: { input: 10, output: 5, cacheRead: 1, cacheWrite: 2, cost: { total: 0.1 } },
|
|
45
|
-
stopReason: "toolUse",
|
|
46
|
-
},
|
|
47
|
-
}),
|
|
48
|
-
JSON.stringify({
|
|
49
|
-
type: "message",
|
|
50
|
-
timestamp: "2026-08-25T10:00:02Z",
|
|
51
|
-
message: { role: "toolResult", toolCallId: "tc-1", toolName: "bash", content: [{ type: "text", text: "file-a" }], timestamp: 1756000002000 },
|
|
52
|
-
}),
|
|
53
|
-
JSON.stringify({
|
|
54
|
-
type: "message",
|
|
55
|
-
timestamp: "2026-08-25T10:00:03Z",
|
|
56
|
-
message: {
|
|
57
|
-
role: "assistant",
|
|
58
|
-
timestamp: 1756000003000,
|
|
59
|
-
content: [{ type: "text", text: "all good" }],
|
|
60
|
-
usage: { input: 20, output: 8, cacheRead: 0, cacheWrite: 0, cost: { total: 0.05 } },
|
|
61
|
-
stopReason: "stop",
|
|
62
|
-
},
|
|
63
|
-
}),
|
|
64
|
-
];
|
|
65
|
-
fs.writeFileSync(file, `${lines.join("\n")}\n`, "utf8");
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
describe("readPiSessionView", () => {
|
|
69
|
-
it("projects a valid subagent JSONL to a native SessionView", async () => {
|
|
70
|
-
const file = join(tmpDir, "valid.jsonl");
|
|
71
|
-
writeValidSession(file);
|
|
72
|
-
|
|
73
|
-
const view = await readPiSessionView(file);
|
|
74
|
-
|
|
75
|
-
expect(view).toBeDefined();
|
|
76
|
-
expect(view?.engineId).toBe("pi");
|
|
77
|
-
expect(view?.source).toBe("native");
|
|
78
|
-
// 两轮 assistant message → 两个 turn(toolResult 不产 turn)
|
|
79
|
-
expect(view?.turns).toHaveLength(2);
|
|
80
|
-
|
|
81
|
-
const [turn1, turn2] = view?.turns ?? [];
|
|
82
|
-
expect(turn1?.text).toBe("");
|
|
83
|
-
expect(turn1?.thinking).toBe("let me look");
|
|
84
|
-
expect(turn1?.toolCalls).toHaveLength(1);
|
|
85
|
-
const tc = turn1?.toolCalls[0];
|
|
86
|
-
expect(tc?.toolName).toBe("bash");
|
|
87
|
-
expect(tc?.args).toEqual({ command: "ls" });
|
|
88
|
-
expect(tc?.result).toEqual({ content: [{ type: "text", text: "file-a" }] });
|
|
89
|
-
// InternalToolCall 内部态不泄漏(导出纯净形状)
|
|
90
|
-
expect(tc).not.toHaveProperty("_status");
|
|
91
|
-
expect(tc).not.toHaveProperty("startedTs");
|
|
92
|
-
expect(turn1?.closed).toBe(true);
|
|
93
|
-
|
|
94
|
-
expect(turn2?.text).toBe("all good");
|
|
95
|
-
expect(turn2?.closed).toBe(true);
|
|
96
|
-
|
|
97
|
-
// usage 聚合:两轮 usageDelta 之和(cost 浮点累加有精度噪声,用 toBeCloseTo)
|
|
98
|
-
expect(view?.usage?.input).toBe(30)
|
|
99
|
-
expect(view?.usage?.output).toBe(13)
|
|
100
|
-
expect(view?.usage?.cacheRead).toBe(1)
|
|
101
|
-
expect(view?.usage?.cacheWrite).toBe(2)
|
|
102
|
-
expect(view?.usage?.cost).toBeCloseTo(0.15, 10)
|
|
103
|
-
expect(view?.usage?.total).toBe(46);
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
it("returns undefined (no throw) when file is missing", async () => {
|
|
107
|
-
await expect(readPiSessionView(join(tmpDir, "nope.jsonl"))).resolves.toBeUndefined();
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it("returns undefined when identity entry is missing", async () => {
|
|
111
|
-
const file = join(tmpDir, "no-identity.jsonl");
|
|
112
|
-
fs.writeFileSync(
|
|
113
|
-
file,
|
|
114
|
-
`${JSON.stringify({ type: "session", id: "s" })}\n${JSON.stringify({
|
|
115
|
-
type: "message",
|
|
116
|
-
message: { role: "assistant", content: [{ type: "text", text: "hi" }], timestamp: 1 },
|
|
117
|
-
})}\n`,
|
|
118
|
-
"utf8",
|
|
119
|
-
);
|
|
120
|
-
await expect(readPiSessionView(file)).resolves.toBeUndefined();
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
it("returns undefined when no assistant message exists", async () => {
|
|
124
|
-
const file = join(tmpDir, "no-assistant.jsonl");
|
|
125
|
-
fs.writeFileSync(
|
|
126
|
-
file,
|
|
127
|
-
`${JSON.stringify({ type: "session", id: "s" })}\n${JSON.stringify({
|
|
128
|
-
type: "custom",
|
|
129
|
-
customType: "subagent-identity",
|
|
130
|
-
data: { id: "bg-2", agent: "w", mode: "background", task: "t", startedAt: 1 },
|
|
131
|
-
})}\n`,
|
|
132
|
-
"utf8",
|
|
133
|
-
);
|
|
134
|
-
await expect(readPiSessionView(file)).resolves.toBeUndefined();
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
it("omits usage when no message carries it", async () => {
|
|
138
|
-
const file = join(tmpDir, "no-usage.jsonl");
|
|
139
|
-
fs.writeFileSync(
|
|
140
|
-
file,
|
|
141
|
-
`${JSON.stringify({ type: "session", id: "s" })}\n${JSON.stringify({
|
|
142
|
-
type: "custom",
|
|
143
|
-
customType: "subagent-identity",
|
|
144
|
-
data: { id: "bg-3", agent: "w", mode: "background", task: "t", startedAt: 1 },
|
|
145
|
-
})}\n${JSON.stringify({
|
|
146
|
-
type: "message",
|
|
147
|
-
message: { role: "assistant", content: [{ type: "text", text: "hi" }], stopReason: "stop", timestamp: 1 },
|
|
148
|
-
})}\n`,
|
|
149
|
-
"utf8",
|
|
150
|
-
);
|
|
151
|
-
const view = await readPiSessionView(file);
|
|
152
|
-
expect(view?.turns).toHaveLength(1);
|
|
153
|
-
expect(view?.usage).toBeUndefined();
|
|
154
|
-
});
|
|
155
|
-
});
|
|
@@ -1,257 +0,0 @@
|
|
|
1
|
-
// src/execution/engine/engines/pi/__tests__/spawn-opts-direct.test.ts
|
|
2
|
-
//
|
|
3
|
-
// [D6 任务形状合流 / 实施期门⑤ ⛔ 硬门产物] pi 边界一次直出映射
|
|
4
|
-
// (agentCallToExecuteOptions:AgentCallOpts → ExecuteOptions)的字段完整性对照表
|
|
5
|
-
// 与逐字段断言。本文件取代已删除的两个往返保真测试:
|
|
6
|
-
// - execution/__tests__/execute-options-mapper.test.ts(mapToExecuteOptions,18 用例)
|
|
7
|
-
// - engines/pi/__tests__/task-spec-mapper.test.ts(spec 往返保真,12 用例)
|
|
8
|
-
//
|
|
9
|
-
// ════════════════════════════════════════════════════════════════════════
|
|
10
|
-
// 字段完整性对照表(从两个被删 mapper 的现有测试提取字段全集,逐字段核对)
|
|
11
|
-
// ════════════════════════════════════════════════════════════════════════
|
|
12
|
-
//
|
|
13
|
-
// 合流前链路(三形态两映射):
|
|
14
|
-
// AgentCallOpts --mapToExecuteOptions--> ExecuteOptions
|
|
15
|
-
// --executeOptionsToTaskSpec--> AgentTaskSpec --taskSpecToExecuteOptions--> ExecuteOptions
|
|
16
|
-
// 合流后(单一形状一次直出):
|
|
17
|
-
// AgentCallOpts --agentCallToExecuteOptions--> ExecuteOptions
|
|
18
|
-
//
|
|
19
|
-
// ┌────────────────────┬──────────────────────────────────────┬────────────────────────────────────┬──────────────┐
|
|
20
|
-
// │ ExecuteOptions 字段 │ 合流前(两级链的合成语义) │ 合流后(一次直出) │ 断言用例 │
|
|
21
|
-
// ├────────────────────┼──────────────────────────────────────┼────────────────────────────────────┼──────────────┤
|
|
22
|
-
// │ task │ prompt→opts.task→spec.task(恒等往返)│ prompt 直取 │ D-01 │
|
|
23
|
-
// │ slug │ description??agent??"workflow-agent" │ 同规则内联(截断 SLUG_MAX_LENGTH=35)│ D-02..D-05 │
|
|
24
|
-
// │ │ 截断(mapToExecuteOptions) │ │ │
|
|
25
|
-
// │ agent │ spec.agent ?? persona.agentRef │ agent 直取(agentRef 无写入方,裁撤) │ D-06 │
|
|
26
|
-
// │ model │ 透传(显式 override,不与 ctxModel 混)│ 同 │ D-07 │
|
|
27
|
-
// │ thinkingLevel │ spec.effort 恒等映射回 │ thinkingLevel 直取(恒等层删除) │ D-08 │
|
|
28
|
-
// │ skillPath │ persona.skillPath 收拢/还原(恒等) │ skillPath 直取(平铺保留) │ D-09 │
|
|
29
|
-
// │ appendSystemPrompt │ persona.appendSystemPrompt 收拢/还原 │ appendSystemPrompt 直取 │ D-10 │
|
|
30
|
-
// │ schema │ 透传 │ 同 │ D-11 │
|
|
31
|
-
// │ schemaEnv │ spec.schema 派生优先(stringifyCached │ schema 派生优先;无 schema 时 │ D-12..D-14 │
|
|
32
|
-
// │ │ compact,与 resolver 同函数同缓存)+ │ schemaEnv 兜底(原 ctx.schemaEnv │ │
|
|
33
|
-
// │ │ ctx.schemaEnv 兜底(源 = opts.schemaEnv)│ 通道的合流等价);均无 → undefined │ │
|
|
34
|
-
// │ maxTurns │ 透传(预算语义:undefined = 不限) │ 同 │ D-15 │
|
|
35
|
-
// │ graceTurns │ 透传(spec 字段) │ 同(合流形状可选字段) │ D-16 │
|
|
36
|
-
// │ ctxModel │ RunContext.ctxModel 回填 │ 第 2 参直取(运行期件,不入声明) │ D-17 │
|
|
37
|
-
// │ fork │ 透传 │ 同 │ D-18 │
|
|
38
|
-
// │ worktree │ 透传(boolean | WorktreeHandle 三态) │ 同 │ D-19 │
|
|
39
|
-
// │ cwd │ 透传 │ 同 │ D-20 │
|
|
40
|
-
// │ conversation │ 透传(interact 控制面 task 标志) │ 同 │ D-21 │
|
|
41
|
-
// │ idleTimeoutMs │ 透传(同上) │ 同 │ D-22 │
|
|
42
|
-
// │ engine/engineFallback│ PiEngine.run 调用方追加(D9① 留痕) │ 同(不在本函数,pi-engine.test 覆盖) │ pi-engine.test│
|
|
43
|
-
// │ signal/onComplete │ 不入 opts(port 设计删字段去向) │ 同(RunContext/编排侧各归其位) │ D-23 │
|
|
44
|
-
// └────────────────────┴──────────────────────────────────────┴────────────────────────────────────┴──────────────┘
|
|
45
|
-
//
|
|
46
|
-
// 调用方扩展字段(引擎不消费,不入 spawn 参数):scene / timeoutMs(SAR mergeTimeoutSignal
|
|
47
|
-
// 合并进 signal)/ skill(resolver 解析为 skillPath)/ engine(SAR 路由层)/ returnMeta
|
|
48
|
-
// (worker 层)——不入本映射即正确(D-24 断言不泄漏)。
|
|
49
|
-
// 已裁撤字段(D6 登记于 AgentCallOpts 类型注释):persona.agentRef、requires。
|
|
50
|
-
//
|
|
51
|
-
// 全字段直出快照断言(D-00)+ 逐字段用例双保险:快照锁全集、用例锁语义边界。
|
|
52
|
-
|
|
53
|
-
import { describe, expect, it } from "vitest";
|
|
54
|
-
|
|
55
|
-
import type { AgentCallOpts } from "../../../../../orchestration/models/types.ts";
|
|
56
|
-
import { SLUG_MAX_LENGTH } from "../../../../../orchestration/models/types.ts";
|
|
57
|
-
import type { ModelInfo } from "../../../../model-resolver.ts";
|
|
58
|
-
import type { ExecuteOptions } from "../../../../types.ts";
|
|
59
|
-
import { agentCallToExecuteOptions } from "../pi-engine.ts";
|
|
60
|
-
|
|
61
|
-
/** 全字段样例(覆盖对照表全部直出映射点)。 */
|
|
62
|
-
function makeFullCall(): AgentCallOpts {
|
|
63
|
-
return {
|
|
64
|
-
prompt: "review the diff",
|
|
65
|
-
description: "review-diff",
|
|
66
|
-
agent: "/agents/reviewer.md",
|
|
67
|
-
model: "zai-coding-cn/glm-5.2",
|
|
68
|
-
thinkingLevel: "high",
|
|
69
|
-
skillPath: "/skills/code-review/SKILL.md",
|
|
70
|
-
appendSystemPrompt: ["extra system prompt line"],
|
|
71
|
-
schema: { type: "object", properties: { verdict: { type: "string" } }, required: ["verdict"] },
|
|
72
|
-
maxTurns: 20,
|
|
73
|
-
graceTurns: 3,
|
|
74
|
-
fork: true,
|
|
75
|
-
worktree: true,
|
|
76
|
-
cwd: "/repo/worktree-x",
|
|
77
|
-
conversation: true,
|
|
78
|
-
idleTimeoutMs: 600_000,
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
describe("agentCallToExecuteOptions(D6 一次直出:AgentCallOpts → pi spawn 编排参数)", () => {
|
|
83
|
-
it("D-00 全字段直出快照(与合流前两级链的合成结果逐字段一致——原往返保真测试的直出等价物)", () => {
|
|
84
|
-
const result = agentCallToExecuteOptions(makeFullCall());
|
|
85
|
-
const expected: ExecuteOptions = {
|
|
86
|
-
task: "review the diff",
|
|
87
|
-
slug: "review-diff",
|
|
88
|
-
agent: "/agents/reviewer.md",
|
|
89
|
-
model: "zai-coding-cn/glm-5.2",
|
|
90
|
-
thinkingLevel: "high",
|
|
91
|
-
skillPath: "/skills/code-review/SKILL.md",
|
|
92
|
-
appendSystemPrompt: ["extra system prompt line"],
|
|
93
|
-
schema: { type: "object", properties: { verdict: { type: "string" } }, required: ["verdict"] },
|
|
94
|
-
schemaEnv: JSON.stringify({ type: "object", properties: { verdict: { type: "string" } }, required: ["verdict"] }),
|
|
95
|
-
maxTurns: 20,
|
|
96
|
-
graceTurns: 3,
|
|
97
|
-
ctxModel: undefined,
|
|
98
|
-
fork: true,
|
|
99
|
-
worktree: true,
|
|
100
|
-
cwd: "/repo/worktree-x",
|
|
101
|
-
conversation: true,
|
|
102
|
-
idleTimeoutMs: 600_000,
|
|
103
|
-
};
|
|
104
|
-
expect(result).toEqual(expected);
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
// ── task / slug(D-01..D-05)──
|
|
108
|
-
|
|
109
|
-
it("D-01 prompt → task", () => {
|
|
110
|
-
expect(agentCallToExecuteOptions({ prompt: "do the thing" }).task).toBe("do the thing");
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
it("D-02 description → slug", () => {
|
|
114
|
-
expect(agentCallToExecuteOptions({ prompt: "t", description: "fix-login" }).slug).toBe("fix-login");
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
it("D-03 description 缺失 → 回落 agent 名(保证 slug 非空)", () => {
|
|
118
|
-
expect(agentCallToExecuteOptions({ prompt: "t", agent: "worker" }).slug).toBe("worker");
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
it("D-04 description 与 agent 均缺失 → 回落 'workflow-agent'", () => {
|
|
122
|
-
expect(agentCallToExecuteOptions({ prompt: "t" }).slug).toBe("workflow-agent");
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
it("D-05 slug 截断:description > SLUG_MAX_LENGTH(35) 截到 35;= 35 不截(边界)", () => {
|
|
126
|
-
expect(agentCallToExecuteOptions({ prompt: "t", description: "a".repeat(36) }).slug).toBe("a".repeat(35));
|
|
127
|
-
expect(agentCallToExecuteOptions({ prompt: "t", description: "a".repeat(35) }).slug).toBe("a".repeat(35));
|
|
128
|
-
expect(SLUG_MAX_LENGTH).toBe(35);
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
// ── 身份 / 模型 / 推理档位(D-06..D-08)──
|
|
132
|
-
|
|
133
|
-
it("D-06 agent 直取(原 persona.agentRef 兜底随 PersonaSpec 裁撤——无生产写入方)", () => {
|
|
134
|
-
expect(agentCallToExecuteOptions({ prompt: "t", agent: "/a.md" }).agent).toBe("/a.md");
|
|
135
|
-
expect(agentCallToExecuteOptions({ prompt: "t" }).agent).toBeUndefined();
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
it("D-07 model:显式 override 透传;缺省 undefined(不与 ctxModel 混合)", () => {
|
|
139
|
-
const ctxModel: ModelInfo = { id: "ctx-model", name: "Ctx", provider: "test", reasoning: false };
|
|
140
|
-
expect(agentCallToExecuteOptions({ prompt: "t", model: "explicit-model" }, ctxModel).model).toBe("explicit-model");
|
|
141
|
-
expect(agentCallToExecuteOptions({ prompt: "t" }, ctxModel).model).toBeUndefined();
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
it("D-08 thinkingLevel 直取(原 effort 恒等映射层删除,含 7 档外的缺省)", () => {
|
|
145
|
-
for (const level of ["off", "low", "medium", "high", "max", undefined]) {
|
|
146
|
-
expect(agentCallToExecuteOptions({ prompt: "t", thinkingLevel: level }).thinkingLevel).toBe(level);
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
// ── persona 平铺字段(D-09..D-10)──
|
|
151
|
-
|
|
152
|
-
it("D-09 skillPath 直取(原 persona 收拢/还原恒等)", () => {
|
|
153
|
-
expect(agentCallToExecuteOptions({ prompt: "t", skillPath: "/s" }).skillPath).toBe("/s");
|
|
154
|
-
expect(agentCallToExecuteOptions({ prompt: "t" }).skillPath).toBeUndefined();
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
it("D-10 appendSystemPrompt 直取(含空数组归一语义:空数组保持空数组——下游 spread no-op 等价)", () => {
|
|
158
|
-
expect(agentCallToExecuteOptions({ prompt: "t", appendSystemPrompt: ["l1", "l2"] }).appendSystemPrompt).toEqual(["l1", "l2"]);
|
|
159
|
-
expect(agentCallToExecuteOptions({ prompt: "t", appendSystemPrompt: [] }).appendSystemPrompt).toEqual([]);
|
|
160
|
-
expect(agentCallToExecuteOptions({ prompt: "t" }).appendSystemPrompt).toBeUndefined();
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
// ── schema / schemaEnv(D-11..D-14)──
|
|
164
|
-
|
|
165
|
-
it("D-11 schema 透传为原始对象引用", () => {
|
|
166
|
-
const schema = { type: "object" };
|
|
167
|
-
expect(agentCallToExecuteOptions({ prompt: "t", schema }).schema).toBe(schema);
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
it("D-12 schemaEnv 派生:与 agent-opts-resolver 同函数(stringifySchemaCached compact),逐字节等值", () => {
|
|
171
|
-
const schema = { type: "object", properties: { a: { type: "number" } } };
|
|
172
|
-
expect(agentCallToExecuteOptions({ prompt: "t", schema }).schemaEnv).toBe(JSON.stringify(schema));
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
it("D-13 派生优先:schema 存在时 opts.schemaEnv(stale 值)被忽略", () => {
|
|
176
|
-
const schema = { type: "object" };
|
|
177
|
-
expect(agentCallToExecuteOptions({ prompt: "t", schema, schemaEnv: "STALE" }).schemaEnv).toBe(JSON.stringify(schema));
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
it("D-14 schemaEnv 兜底/缺省:无 schema 时用 opts.schemaEnv(解耦形态,原 ctx 兜底通道等价);均无 → undefined(BC-6:childEnv 不注入)", () => {
|
|
181
|
-
expect(agentCallToExecuteOptions({ prompt: "t", schemaEnv: '{"type":"object"}' }).schemaEnv).toBe('{"type":"object"}');
|
|
182
|
-
expect(agentCallToExecuteOptions({ prompt: "t" }).schemaEnv).toBeUndefined();
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
// ── 轮数 / 运行期 / 隔离(D-15..D-20)──
|
|
186
|
-
|
|
187
|
-
it("D-15 maxTurns 透传(undefined = 不限,不挂 turns 估算 watchdog)", () => {
|
|
188
|
-
expect(agentCallToExecuteOptions({ prompt: "t", maxTurns: 20 }).maxTurns).toBe(20);
|
|
189
|
-
expect(agentCallToExecuteOptions({ prompt: "t" }).maxTurns).toBeUndefined();
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
it("D-16 graceTurns 透传(合流形状可选字段,chat 域经 host-task-spec 填充)", () => {
|
|
193
|
-
expect(agentCallToExecuteOptions({ prompt: "t", graceTurns: 3 }).graceTurns).toBe(3);
|
|
194
|
-
expect(agentCallToExecuteOptions({ prompt: "t" }).graceTurns).toBeUndefined();
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
it("D-17 ctxModel 从第 2 参回填(运行期件不入任务声明——D-008 兼底链路)", () => {
|
|
198
|
-
const ctxModel: ModelInfo = { id: "mimo-v2.5-pro", name: "MiMo", provider: "router-openai", reasoning: false };
|
|
199
|
-
expect(agentCallToExecuteOptions({ prompt: "t" }, ctxModel).ctxModel).toBe(ctxModel);
|
|
200
|
-
expect(agentCallToExecuteOptions({ prompt: "t" }).ctxModel).toBeUndefined();
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
it("D-18 fork 透传", () => {
|
|
204
|
-
expect(agentCallToExecuteOptions({ prompt: "t", fork: true }).fork).toBe(true);
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
it("D-19 worktree 三态(true/false/WorktreeHandle)直出保持", () => {
|
|
208
|
-
const handle = { path: "/wt", branch: "b", baseCommit: "c", mainCwd: "/repo" };
|
|
209
|
-
for (const wt of [true, false, handle] as const) {
|
|
210
|
-
expect(agentCallToExecuteOptions({ prompt: "t", worktree: wt }).worktree).toBe(wt);
|
|
211
|
-
}
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
it("D-20 cwd 透传", () => {
|
|
215
|
-
expect(agentCallToExecuteOptions({ prompt: "t", cwd: "/work" }).cwd).toBe("/work");
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
// ── 交互控制面(D-21..D-22)──
|
|
219
|
-
|
|
220
|
-
it("D-21 conversation 透传(interact 控制面的 task 标志)", () => {
|
|
221
|
-
expect(agentCallToExecuteOptions({ prompt: "t", conversation: true }).conversation).toBe(true);
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
it("D-22 idleTimeoutMs 透传", () => {
|
|
225
|
-
expect(agentCallToExecuteOptions({ prompt: "t", idleTimeoutMs: 12345 }).idleTimeoutMs).toBe(12345);
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
// ── 声明边界(D-23..D-24)──
|
|
229
|
-
|
|
230
|
-
it("D-23 运行期字段不入直出产物:signal/onComplete/engine/engineFallback 不由本函数产出(engine 由 run 调用方追加)", () => {
|
|
231
|
-
const result = agentCallToExecuteOptions(makeFullCall()) as unknown as Record<string, unknown>;
|
|
232
|
-
expect("signal" in result).toBe(false);
|
|
233
|
-
expect("onComplete" in result).toBe(false);
|
|
234
|
-
expect("engine" in result).toBe(false);
|
|
235
|
-
expect("engineFallback" in result).toBe(false);
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
it("D-24 调用方扩展字段不泄漏进 spawn 参数:scene/timeoutMs/skill/engine/returnMeta/denyTools/permissionMode", () => {
|
|
239
|
-
const result = agentCallToExecuteOptions({
|
|
240
|
-
prompt: "t",
|
|
241
|
-
scene: "coding",
|
|
242
|
-
timeoutMs: 5000,
|
|
243
|
-
skill: "code-review",
|
|
244
|
-
engine: "pi",
|
|
245
|
-
returnMeta: true,
|
|
246
|
-
denyTools: ["bash"],
|
|
247
|
-
permissionMode: "yolo",
|
|
248
|
-
}) as unknown as Record<string, unknown>;
|
|
249
|
-
expect("scene" in result).toBe(false);
|
|
250
|
-
expect("timeoutMs" in result).toBe(false);
|
|
251
|
-
expect("skill" in result).toBe(false);
|
|
252
|
-
expect("engine" in result).toBe(false);
|
|
253
|
-
expect("returnMeta" in result).toBe(false);
|
|
254
|
-
expect("denyTools" in result).toBe(false);
|
|
255
|
-
expect("permissionMode" in result).toBe(false);
|
|
256
|
-
});
|
|
257
|
-
});
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 从主进程 argv 解析可镜像给子进程的 flag。
|
|
3
|
-
*
|
|
4
|
-
* 独立模块:argv 解析是独立职责,从 session-runner.ts 拆出避免该文件超行数上限。
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* 镜像 flag 集合:从主进程 argv 解析出的可透传给子进程的 flag。
|
|
9
|
-
* 面向 buildSpawnArgs 的入参形态(解析后)。undefined 字段语义与解析为空一致。
|
|
10
|
-
*/
|
|
11
|
-
export interface MirrorFlags {
|
|
12
|
-
noExtensions: boolean;
|
|
13
|
-
approve: boolean;
|
|
14
|
-
extensionPaths: string[];
|
|
15
|
-
noContextFiles: boolean;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* 有值 flag 的解析规则表:成员是「后跟一个值」的 flag 名(含长短形式)。
|
|
20
|
-
* 用于 parseMirrorFlagArgs 跳过其他 flag 的值时不误吃。
|
|
21
|
-
*/
|
|
22
|
-
const VALUED_FLAGS = new Set<string>([
|
|
23
|
-
"--extension", "-e",
|
|
24
|
-
"--skill",
|
|
25
|
-
"--model", "--system-prompt", "--append-system-prompt",
|
|
26
|
-
"--tools", "-t", "--exclude-tools", "-xt",
|
|
27
|
-
"--fork", "--session-dir", "--mode",
|
|
28
|
-
"--thinking", "--models",
|
|
29
|
-
]);
|
|
30
|
-
|
|
31
|
-
/** MirrorFlags 的布尔字段名(extensionPaths 数组字段单列,不进此表)。 */
|
|
32
|
-
type MirrorBooleanKey = "noExtensions" | "approve" | "noContextFiles";
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* 布尔镜像 flag 表:token(长/短形式)→ MirrorFlags 布尔字段。
|
|
36
|
-
* 用 Map 而非对象字面量查表——对象查表对 "__proto__"/"constructor" 等 token
|
|
37
|
-
* 会命中原型链返回非 undefined,Map.get 无此陷阱。
|
|
38
|
-
*/
|
|
39
|
-
const BOOLEAN_FLAGS = new Map<string, MirrorBooleanKey>([
|
|
40
|
-
["--no-extensions", "noExtensions"],
|
|
41
|
-
["-ne", "noExtensions"],
|
|
42
|
-
["--approve", "approve"],
|
|
43
|
-
["-a", "approve"],
|
|
44
|
-
["--no-context-files", "noContextFiles"],
|
|
45
|
-
["-nc", "noContextFiles"],
|
|
46
|
-
]);
|
|
47
|
-
|
|
48
|
-
/** argv 中 flag 的起始索引:argv[0]=runtime, argv[1]=binary 路径。 */
|
|
49
|
-
const ARGV_FLAG_START = 2;
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* 从主进程 argv 解析可镜像的 flag(--no-extensions/--approve/--extension/--no-context-files)。
|
|
53
|
-
*
|
|
54
|
-
* 数据源是主 pi 进程的 process.argv:子进程 spawn 的父就是主进程,
|
|
55
|
-
* 主进程 argv 完整保留启动时收到的全部 flag(已运行时验证)。这让子进程
|
|
56
|
-
* extension/approve 加载行为与主进程一致,且对任意 pi 宿主通用(不止 xyz-agent)。
|
|
57
|
-
*
|
|
58
|
-
* 解析规则:
|
|
59
|
-
* - --no-extensions / -ne、--approve / -a:布尔 flag(查 BOOLEAN_FLAGS 表)
|
|
60
|
-
* - --no-context-files / -nc:布尔 flag(镜像理由:--extension 镜像会把
|
|
61
|
-
* @zhushanwen/pi-system-prompt 带进每个 subagent,该扩展靠子进程自己的
|
|
62
|
-
* argv 检测此 flag 决定是否注入全局 AGENTS.md——不镜像则用户 opt-out
|
|
63
|
-
* 在 subagent 路径失效)
|
|
64
|
-
* - --extension / -e:支持 `--extension <path>`(空格)与 `--extension=<path>`(等号)
|
|
65
|
-
* - 其他 flag(在 VALUED_FLAGS 中)的值不被误当 extension 路径
|
|
66
|
-
* - positional 参数被忽略
|
|
67
|
-
* - argv[0]/argv[1] 是 bun/pi binary 路径,从 argv[2:] 开始扫
|
|
68
|
-
*/
|
|
69
|
-
// [perf] 进程内 process.argv 引用恒定(唯一调用点 session-runner 每次 spawn 传同一引用),
|
|
70
|
-
// 解析结果按 argv 引用相等 memo——每次 spawn 免重复扫描/正则。测试传新数组引用不命中。
|
|
71
|
-
let memoArgv: readonly string[] | undefined;
|
|
72
|
-
let memoResult: MirrorFlags | undefined;
|
|
73
|
-
|
|
74
|
-
export function mirrorMainProcessFlags(argv: readonly string[]): MirrorFlags {
|
|
75
|
-
if (memoResult !== undefined && memoArgv === argv) return memoResult;
|
|
76
|
-
const result = parseMirrorFlagArgs(
|
|
77
|
-
argv.length > ARGV_FLAG_START ? argv.slice(ARGV_FLAG_START) : [],
|
|
78
|
-
);
|
|
79
|
-
memoArgv = argv;
|
|
80
|
-
memoResult = result;
|
|
81
|
-
return result;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/** 纯解析:扫描 flag 区段(argv[2:])构造 MirrorFlags,不做 memo。 */
|
|
85
|
-
function parseMirrorFlagArgs(flagArgs: readonly string[]): MirrorFlags {
|
|
86
|
-
const flags: Record<MirrorBooleanKey, boolean> = {
|
|
87
|
-
noExtensions: false,
|
|
88
|
-
approve: false,
|
|
89
|
-
noContextFiles: false,
|
|
90
|
-
};
|
|
91
|
-
const extensionPaths: string[] = [];
|
|
92
|
-
|
|
93
|
-
// argv[0]=runtime(bun), argv[1]=pi binary 路径;flag 从 argv[2] 起
|
|
94
|
-
for (let i = 0; i < flagArgs.length; i++) {
|
|
95
|
-
const tok = flagArgs[i];
|
|
96
|
-
const booleanKey = BOOLEAN_FLAGS.get(tok);
|
|
97
|
-
if (booleanKey !== undefined) {
|
|
98
|
-
flags[booleanKey] = true;
|
|
99
|
-
continue;
|
|
100
|
-
}
|
|
101
|
-
// 等号形式 --extension=path / -e=path
|
|
102
|
-
const eqMatch = /^(--extension|-e)=(.*)$/.exec(tok);
|
|
103
|
-
if (eqMatch) {
|
|
104
|
-
const val = eqMatch[2];
|
|
105
|
-
if (val) extensionPaths.push(val);
|
|
106
|
-
continue;
|
|
107
|
-
}
|
|
108
|
-
// 空格形式 --extension <path> / -e <path>:值在下一个 token
|
|
109
|
-
// [MF-7a] flag 判定收窄为 startsWith("--"):守卫原为 !startsWith("-"),把以单个
|
|
110
|
-
// - 开头的合法路径(如相对路径 -weird-dir/x.md)误判为 flag 跳过——extension 路径
|
|
111
|
-
// 静默丢失。pi CLI 的多字符长 flag 一律 -- 前缀,单 - 只接单字符短 flag(-e 本身),
|
|
112
|
-
// 故「-- 开头才算 flag」不误吃真 flag 且放行 - 开头路径。
|
|
113
|
-
if (tok === "--extension" || tok === "-e") {
|
|
114
|
-
const next = flagArgs[i + 1];
|
|
115
|
-
if (next !== undefined && !next.startsWith("--") && next.length > 0) {
|
|
116
|
-
extensionPaths.push(next);
|
|
117
|
-
i++; // 跳过值
|
|
118
|
-
}
|
|
119
|
-
continue;
|
|
120
|
-
}
|
|
121
|
-
// 其他有值 flag:跳过其值,避免误吃(如 --skill /a 的 /a)
|
|
122
|
-
if (VALUED_FLAGS.has(tok)) {
|
|
123
|
-
i++;
|
|
124
|
-
continue;
|
|
125
|
-
}
|
|
126
|
-
// 其他情况(未知 flag、--flag=val 形式、positional)忽略
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
return {
|
|
130
|
-
noExtensions: flags.noExtensions,
|
|
131
|
-
approve: flags.approve,
|
|
132
|
-
extensionPaths,
|
|
133
|
-
noContextFiles: flags.noContextFiles,
|
|
134
|
-
};
|
|
135
|
-
}
|