@zhushanwen/subagent-core 0.2.0 → 0.4.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 +45 -2
- package/agents/analyst.md +60 -0
- package/agents/coder.md +69 -0
- package/agents/debugger.md +66 -0
- package/agents/doc-reviewer.md +49 -0
- package/agents/explorer.md +63 -0
- package/agents/general-purpose.md +32 -0
- package/agents/orchestrator.md +61 -0
- package/agents/planner.md +53 -0
- package/agents/researcher.md +67 -0
- package/agents/reviewer.md +73 -0
- package/dist/chunk-4KN4TTG7.js +240 -0
- package/dist/chunk-APZY4IME.js +27 -0
- package/dist/chunk-X7SZ5HLQ.js +66 -0
- package/dist/execution/engine/engines/zcode/constants.cjs +65 -0
- package/dist/execution/engine/engines/zcode/constants.d.cts +93 -1
- package/dist/execution/engine/engines/zcode/constants.d.ts +93 -1
- package/dist/execution/engine/engines/zcode/constants.js +43 -1
- package/dist/execution/engine/engines/zcode/reader.d.cts +1 -1
- package/dist/execution/engine/engines/zcode/reader.d.ts +1 -1
- package/dist/execution/engine/engines/zcode/reader.js +4 -234
- package/dist/execution/engine/paths.js +7 -19
- package/dist/index.cjs +14709 -100
- package/dist/index.d.cts +4053 -200
- package/dist/index.d.ts +4053 -200
- package/dist/index.js +14358 -102
- package/dist/{types-BxyAidGf.d.cts → types-DpUO16pj.d.cts} +464 -1
- package/dist/{types-BxyAidGf.d.ts → types-DpUO16pj.d.ts} +464 -1
- package/package.json +6 -3
- package/src/__tests__/review-fix-loop-script.test.ts +90 -2
- package/src/__tests__/review-fix-loop-utils.test.ts +21 -0
- package/src/__tests__/smoke.test.ts +9 -2
- package/src/execution/__tests__/agent-profile.test.ts +232 -0
- package/src/execution/__tests__/agents-assembly.test.ts +219 -0
- package/src/execution/__tests__/chat-engine-routing.test.ts +71 -0
- package/src/execution/__tests__/chatmode-first-round-closure-spawn.test.ts +1 -0
- package/src/execution/__tests__/create-concurrency-pool.test.ts +194 -0
- package/src/execution/__tests__/delivery-methods.test.ts +2 -0
- package/src/execution/__tests__/descendant-sweep.test.ts +269 -0
- package/src/execution/__tests__/dialog-queue.test.ts +199 -1
- package/src/execution/__tests__/epipe-fallback.test.ts +2 -0
- package/src/execution/__tests__/execution-runtime-face.test.ts +272 -0
- package/src/execution/__tests__/finalize-record.test.ts +106 -0
- package/src/execution/__tests__/gc-timer.test.ts +2 -0
- package/src/execution/__tests__/get-record-for-action-restart.test.ts +2 -0
- package/src/execution/__tests__/get-state-handshake.test.ts +127 -0
- package/src/execution/__tests__/keep-alive-no-progress.test.ts +378 -0
- package/src/execution/__tests__/kill-all-escalation.test.ts +196 -0
- package/src/execution/__tests__/lifecycle-manager-idle-timer-identity.test.ts +117 -0
- package/src/execution/__tests__/lifecycle-manager.test.ts +39 -0
- package/src/execution/__tests__/manifest-store-tmp-recovery.test.ts +99 -0
- package/src/execution/__tests__/max-turns-to-watchdog-ms.test.ts +113 -0
- package/src/execution/__tests__/notify-ledger.test.ts +294 -0
- package/src/execution/__tests__/record-store-orphan-revive.test.ts +159 -0
- package/src/execution/__tests__/record-store.test.ts +83 -0
- package/src/execution/__tests__/run-and-finalize-chatmode.test.ts +4 -0
- package/src/execution/__tests__/run-spawn-chatmode-settled.test.ts +1 -0
- package/src/execution/__tests__/run-spawn-edges.test.ts +407 -17
- package/src/execution/__tests__/run-spawn-integration.test.ts +1 -1
- package/src/execution/__tests__/run-spawn-stdout-callback-throw.test.ts +12 -4
- package/src/execution/__tests__/service-kill-escalation.test.ts +89 -0
- package/src/execution/__tests__/session-pending.test.ts +228 -0
- package/src/execution/__tests__/session-runner-branch-cache-lru.test.ts +110 -0
- package/src/execution/__tests__/session-runner-close-prune.test.ts +181 -0
- package/src/execution/__tests__/session-runner-epipe.test.ts +1 -0
- package/src/execution/__tests__/session-runner-heartbeat-idle-fallback.test.ts +226 -0
- package/src/execution/__tests__/settled-watchdog.test.ts +289 -0
- package/src/execution/__tests__/spawned-children.test.ts +153 -10
- package/src/execution/__tests__/subagent-actions-core.test.ts +997 -0
- package/src/execution/__tests__/subagent-service-message-close.test.ts +71 -10
- package/src/execution/__tests__/subagent-service-multiproc-guard.test.ts +174 -0
- package/src/execution/__tests__/subagent-service-notify-gate.test.ts +266 -0
- package/src/execution/__tests__/subagent-service-parent-guard.test.ts +3 -0
- package/src/execution/__tests__/subagent-service-recovery-bounds.test.ts +316 -0
- package/src/execution/__tests__/timeout-integration.test.ts +7 -7
- package/src/execution/__tests__/ui-request-handler-factory.test.ts +95 -1
- package/src/execution/__tests__/ui-request-queue.test.ts +25 -0
- package/src/execution/__tests__/worktree-git-ops.test.ts +571 -0
- package/src/execution/__tests__/worktree-reconcile-aging.test.ts +204 -0
- package/src/execution/agent-registry.ts +225 -1
- package/src/execution/agents-assembly.ts +88 -0
- package/src/execution/concurrency-pool.ts +71 -9
- package/src/execution/dialog-queue.ts +101 -3
- package/src/execution/engine/__tests__/conformance/contract.abort.test.ts +49 -2
- package/src/execution/engine/__tests__/conformance/contract.agent-events.test.ts +87 -1
- package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +26 -0
- package/src/execution/engine/__tests__/conformance/golden-replay.zcode.test.ts +83 -1
- package/src/execution/engine/__tests__/conformance/zcode-appserver-harness.ts +131 -0
- package/src/execution/engine/__tests__/registry.test.ts +90 -1
- package/src/execution/engine/engine-discovery.ts +12 -16
- package/src/execution/engine/engines/pi/task-spec-mapper.ts +3 -3
- package/src/execution/engine/engines/zcode/__tests__/__fixtures__/fake-appserver.mjs +274 -0
- package/src/execution/engine/engines/zcode/__tests__/__fixtures__/zcode-golden-appserver.json +36 -0
- package/src/execution/engine/engines/zcode/__tests__/connection.test.ts +472 -0
- package/src/execution/engine/engines/zcode/__tests__/preparer-appserver.test.ts +387 -0
- package/src/execution/engine/engines/zcode/__tests__/session-channel.test.ts +780 -0
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine-appserver.test.ts +815 -0
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine-degrade.test.ts +462 -0
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine.live.test.ts +119 -1
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine.test.ts +136 -6
- package/src/execution/engine/engines/zcode/appserver-home.ts +442 -0
- package/src/execution/engine/engines/zcode/appserver-probe.ts +141 -0
- package/src/execution/engine/engines/zcode/connection.ts +585 -0
- package/src/execution/engine/engines/zcode/constants.ts +129 -0
- package/src/execution/engine/engines/zcode/golden-sample.ts +54 -8
- package/src/execution/engine/engines/zcode/preparer.ts +25 -22
- package/src/execution/engine/engines/zcode/session-channel.ts +656 -0
- package/src/execution/engine/engines/zcode/zcode-engine.ts +909 -41
- package/src/execution/engine/host-task-spec.ts +3 -3
- package/src/execution/engine/port.ts +41 -1
- package/src/execution/engine/registry.ts +53 -0
- package/src/execution/finalize-record.ts +63 -5
- package/src/execution/get-state-handshake.ts +85 -10
- package/src/execution/lifecycle-manager.ts +27 -3
- package/src/execution/manifest-store.ts +53 -62
- package/src/execution/notifier.ts +10 -10
- package/src/execution/notify-ledger.ts +117 -16
- package/src/execution/record-entry.ts +8 -2
- package/src/execution/record-store.ts +29 -15
- package/src/execution/session-pending.ts +213 -62
- package/src/execution/session-runner.ts +974 -128
- package/src/execution/sessions-index.ts +10 -55
- package/src/execution/settled-watchdog.ts +99 -0
- package/src/execution/subagent-actions-core.ts +686 -0
- package/src/execution/subagent-service.ts +396 -49
- package/src/execution/ui-request-handler-factory.ts +27 -4
- package/src/execution/worktree-git-ops.ts +397 -0
- package/src/execution/worktree-manager.ts +72 -10
- package/src/execution/worktree-registry.ts +6 -12
- package/src/index.ts +413 -6
- package/src/orchestration/__tests__/__fixtures__/worker-template.snapshot.txt +42 -3
- package/src/orchestration/__tests__/agent-call-catch-fallback.test.ts +2 -4
- package/src/orchestration/__tests__/args-meta.test.ts +358 -0
- package/src/orchestration/__tests__/error-recovery-handlers.test.ts +1 -8
- package/src/orchestration/__tests__/error-recovery-rebuild-failure.test.ts +312 -0
- package/src/orchestration/__tests__/error-recovery-terminal-hardening.test.ts +382 -0
- package/src/orchestration/__tests__/file-run-store-prune.test.ts +168 -0
- package/src/orchestration/__tests__/file-run-store-throttle.test.ts +168 -0
- package/src/orchestration/__tests__/file-run-store.test.ts +389 -0
- package/src/orchestration/__tests__/helpers/flush-microtasks.ts +13 -0
- package/src/orchestration/__tests__/launcher-nested-workflow.test.ts +34 -0
- package/src/orchestration/__tests__/lifecycle-abort-broadcast-signal.test.ts +357 -0
- package/src/orchestration/__tests__/lifecycle-recover-crashed.test.ts +289 -0
- package/src/orchestration/__tests__/lifecycle.test.ts +77 -0
- package/src/orchestration/__tests__/run-snapshot.test.ts +353 -0
- package/src/orchestration/__tests__/script-generate.test.ts +314 -0
- package/src/orchestration/__tests__/worker-pending-timeout-abort.test.ts +275 -0
- package/src/orchestration/__tests__/worker-script-builder-runtime.test.ts +78 -1
- package/src/orchestration/__tests__/workflow-files.test.ts +186 -0
- package/src/orchestration/__tests__/workflow-run-summary.test.ts +119 -0
- package/src/orchestration/__tests__/workflow-script-registry-impl.test.ts +124 -0
- package/src/orchestration/agent-opts-resolver.ts +7 -7
- package/src/orchestration/args-meta.ts +198 -0
- package/src/orchestration/error-recovery.ts +416 -146
- package/src/orchestration/execute-agent-call.ts +9 -9
- package/src/orchestration/file-run-store.ts +327 -0
- package/src/orchestration/launcher.ts +35 -26
- package/src/orchestration/lifecycle.ts +355 -79
- package/src/orchestration/models/agent-call.ts +7 -7
- package/src/orchestration/models/budget.ts +5 -5
- package/src/orchestration/models/run-runtime.ts +13 -13
- package/src/orchestration/models/trace.ts +8 -8
- package/src/orchestration/models/workflow-run.ts +27 -27
- package/src/orchestration/models/workflow-script.ts +4 -4
- package/src/orchestration/run-snapshot.ts +266 -0
- package/src/orchestration/script-generate.ts +154 -0
- package/src/orchestration/script-lint.ts +33 -33
- package/src/orchestration/worker-handle.ts +10 -10
- package/src/orchestration/worker-host.ts +10 -10
- package/src/orchestration/worker-script-builder.ts +401 -346
- package/src/orchestration/workflow-files.ts +37 -11
- package/src/orchestration/workflow-run-summary.ts +69 -0
- package/src/orchestration/workflow-script-registry-impl.ts +31 -9
- package/src/shared/__tests__/agent-ref.test.ts +209 -2
- package/src/shared/__tests__/atomic-write.test.ts +267 -0
- package/src/shared/__tests__/bounded-serialize.test.ts +236 -0
- package/src/shared/__tests__/injection-render.test.ts +518 -0
- package/src/shared/__tests__/resource-discovery-host-roots.test.ts +474 -0
- package/src/shared/__tests__/resource-discovery.test.ts +3 -2
- package/src/shared/agent-ref.ts +143 -2
- package/src/shared/atomic-write.ts +320 -0
- package/src/shared/bounded-serialize.ts +154 -0
- package/src/shared/injection-render.ts +279 -0
- package/src/shared/meta-parser.ts +41 -1
- package/src/shared/resource-discovery.ts +104 -37
- package/src/shared/resource-meta.ts +14 -0
- package/src/shared/xml-injection.ts +9 -9
- package/workflows/README.md +9 -9
- package/workflows/chain.js +4 -2
- package/workflows/map-reduce.js +5 -3
- package/workflows/parallel.js +5 -3
- package/workflows/review-fix-loop-utils.cjs +14 -3
- package/workflows/review-fix-loop.js +18 -7
- package/workflows/scatter-gather.js +4 -2
- package/dist/chunk-3VOERJPJ.js +0 -22
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
//
|
|
3
3
|
// registry 专属测试(P1 验收 4):注册/获取/listEngines/hasEngine/
|
|
4
4
|
// 未注册 id 报 engine_not_found(错误文案含已注册清单——错误规格表第 1 行契约)。
|
|
5
|
+
// [R1 D6] 追加:重注册先 dispose 旧单例(D6②)+ disposeEngines 收割遍历(D6③)。
|
|
5
6
|
|
|
6
|
-
import { beforeEach, describe, expect, it } from "vitest";
|
|
7
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
7
8
|
|
|
8
9
|
import type { EnginePort, RunContext } from "../port.ts";
|
|
9
10
|
import {
|
|
10
11
|
clearEngines,
|
|
11
12
|
DEFAULT_ENGINE_ID,
|
|
13
|
+
disposeEngines,
|
|
12
14
|
EngineNotFoundError,
|
|
13
15
|
getEngine,
|
|
14
16
|
hasEngine,
|
|
@@ -117,4 +119,91 @@ describe("engine registry", () => {
|
|
|
117
119
|
it("DEFAULT_ENGINE_ID 缺省为 'pi'(D9:回填期零风险默认)", () => {
|
|
118
120
|
expect(DEFAULT_ENGINE_ID).toBe("pi");
|
|
119
121
|
});
|
|
122
|
+
|
|
123
|
+
// ── [R1 D6②] 重注册同名:先 dispose 已实例化的旧单例(防常驻资源泄漏)──
|
|
124
|
+
|
|
125
|
+
it("重注册同名:已实例化的旧单例 dispose 被调用一次,新工厂实例生效", () => {
|
|
126
|
+
const dispose = vi.fn(() => Promise.resolve());
|
|
127
|
+
registerEngine("fake", () => ({ ...makeFakeEngine("fake"), dispose }));
|
|
128
|
+
getEngine("fake"); // 实例化旧引擎(未实例化 = 无常驻资源可回收)
|
|
129
|
+
registerEngine("fake", () => makeFakeEngine("fake-v2"));
|
|
130
|
+
expect(dispose).toHaveBeenCalledTimes(1);
|
|
131
|
+
expect(getEngine("fake").id).toBe("fake-v2");
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it("重注册同名:旧实例 dispose 同步 throw 不阻断替换(best-effort)", () => {
|
|
135
|
+
const dispose = vi.fn(() => {
|
|
136
|
+
throw new Error("dispose boom");
|
|
137
|
+
});
|
|
138
|
+
registerEngine("fake", () => ({ ...makeFakeEngine("fake"), dispose }));
|
|
139
|
+
getEngine("fake");
|
|
140
|
+
expect(() => registerEngine("fake", () => makeFakeEngine("fake-v2"))).not.toThrow();
|
|
141
|
+
expect(dispose).toHaveBeenCalledTimes(1);
|
|
142
|
+
expect(getEngine("fake").id).toBe("fake-v2");
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it("重注册同名:旧实例 dispose 异步 reject 不阻断替换、不产生 unhandledRejection", async () => {
|
|
146
|
+
const dispose = vi.fn(() => Promise.reject(new Error("dispose async boom")));
|
|
147
|
+
registerEngine("fake", () => ({ ...makeFakeEngine("fake"), dispose }));
|
|
148
|
+
getEngine("fake");
|
|
149
|
+
expect(() => registerEngine("fake", () => makeFakeEngine("fake-v2"))).not.toThrow();
|
|
150
|
+
expect(getEngine("fake").id).toBe("fake-v2");
|
|
151
|
+
// flush macrotask:reject 必须已被 registry 侧 catch 吞掉——否则 vitest 以
|
|
152
|
+
// unhandledRejection 判本文件失败,用例即失效
|
|
153
|
+
await new Promise<void>((resolve) => setImmediate(resolve));
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it("重注册同名:旧引擎仅注册工厂未实例化时不触发 dispose(惰性单例无资源)", () => {
|
|
157
|
+
const dispose = vi.fn(() => Promise.resolve());
|
|
158
|
+
registerEngine("fake", () => ({ ...makeFakeEngine("fake"), dispose }));
|
|
159
|
+
// 不 getEngine——singletons 无记录
|
|
160
|
+
registerEngine("fake", () => makeFakeEngine("fake-v2"));
|
|
161
|
+
expect(dispose).not.toHaveBeenCalled();
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it("重注册同名:旧实例未实现 dispose(可选成员)时直接替换不抛", () => {
|
|
165
|
+
registerEngine("fake", () => makeFakeEngine("fake"));
|
|
166
|
+
getEngine("fake");
|
|
167
|
+
expect(() => registerEngine("fake", () => makeFakeEngine("fake-v2"))).not.toThrow();
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
// ── [R1 D6③] disposeEngines:宿主收割(killAllSpawnedChildren)前的触发遍历 ──
|
|
171
|
+
|
|
172
|
+
describe("disposeEngines(D6③)", () => {
|
|
173
|
+
it("只对已实例化的引擎触发 dispose(绝不实例化未用引擎)", () => {
|
|
174
|
+
const instantiated = vi.fn(() => Promise.resolve());
|
|
175
|
+
const neverInstantiated = vi.fn(() => Promise.resolve());
|
|
176
|
+
registerEngine("used", () => ({ ...makeFakeEngine("used"), dispose: instantiated }));
|
|
177
|
+
registerEngine("unused", () => ({ ...makeFakeEngine("unused"), dispose: neverInstantiated }));
|
|
178
|
+
getEngine("used");
|
|
179
|
+
disposeEngines();
|
|
180
|
+
expect(instantiated).toHaveBeenCalledTimes(1);
|
|
181
|
+
expect(neverInstantiated).not.toHaveBeenCalled();
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it("未实现 dispose 的引擎(可选面)跳过不抛", () => {
|
|
185
|
+
registerEngine("plain", () => makeFakeEngine("plain"));
|
|
186
|
+
getEngine("plain");
|
|
187
|
+
expect(() => disposeEngines()).not.toThrow();
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it("dispose 幂等(实现承诺):disposeEngines 重复调用不抛、逐次触发", async () => {
|
|
191
|
+
const dispose = vi.fn(() => Promise.resolve());
|
|
192
|
+
registerEngine("fake", () => ({ ...makeFakeEngine("fake"), dispose }));
|
|
193
|
+
getEngine("fake");
|
|
194
|
+
expect(() => disposeEngines()).not.toThrow();
|
|
195
|
+
expect(() => disposeEngines()).not.toThrow();
|
|
196
|
+
// 幂等语义由引擎实现承诺(不变量 4),本断言只验证 registry 重复触发不抛
|
|
197
|
+
expect(dispose).toHaveBeenCalledTimes(2);
|
|
198
|
+
await new Promise<void>((resolve) => setImmediate(resolve));
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it("dispose 后单例保留(run 自动重建归引擎承诺,registry 不删——不变量 4 边界)", () => {
|
|
202
|
+
const dispose = vi.fn(() => Promise.resolve());
|
|
203
|
+
registerEngine("fake", () => ({ ...makeFakeEngine("fake"), dispose }));
|
|
204
|
+
const engine = getEngine("fake");
|
|
205
|
+
disposeEngines();
|
|
206
|
+
expect(getEngine("fake")).toBe(engine);
|
|
207
|
+
});
|
|
208
|
+
});
|
|
120
209
|
});
|
|
@@ -15,6 +15,10 @@ import * as path from "node:path";
|
|
|
15
15
|
import { SUBAGENTS_ENGINES_FILENAME, type SubagentEnginesFile } from "@xyz-agent/extension-protocol";
|
|
16
16
|
|
|
17
17
|
import { listEngines } from "./registry.ts";
|
|
18
|
+
import { writeAtomicFileSync } from "../../shared/atomic-write.ts";
|
|
19
|
+
|
|
20
|
+
/** engines.json 落盘缩进(与 subagent-core 其他 JSON store 的 JSON_INDENT 约定一致)。 */
|
|
21
|
+
const JSON_INDENT = 2;
|
|
18
22
|
|
|
19
23
|
/** engines.json 绝对路径(与 config.json 同目录;config.ts 的 getGlobalConfigPath 同构)。 */
|
|
20
24
|
export function getEnginesFilePath(agentDir: string): string {
|
|
@@ -25,14 +29,15 @@ export function getEnginesFilePath(agentDir: string): string {
|
|
|
25
29
|
* 把注册表引擎列表同步到 engines.json(session_start 时调用)。
|
|
26
30
|
*
|
|
27
31
|
* 幂等:内容与现文件一致时零写入(mtime 不动——读侧无谓失效);写入走 tmp+rename
|
|
28
|
-
*
|
|
32
|
+
* 原子替换(shared/atomic-write 统一原语,U6b 迁移——与池 config 同防线)。
|
|
33
|
+
* fail-safe:任何 IO 异常吞掉(可发现性降级不阻塞
|
|
29
34
|
* session 启动——GUI 兜底显示 ['pi'])。
|
|
30
35
|
*/
|
|
31
36
|
export function syncEnginesFile(agentDir: string): void {
|
|
32
37
|
try {
|
|
33
38
|
const filePath = getEnginesFilePath(agentDir);
|
|
34
39
|
const payload: SubagentEnginesFile = { v: 1, engines: listEngines(), updatedAt: Date.now() };
|
|
35
|
-
const serialized = JSON.stringify(payload, null,
|
|
40
|
+
const serialized = JSON.stringify(payload, null, JSON_INDENT);
|
|
36
41
|
try {
|
|
37
42
|
const existing = fs.readFileSync(filePath, "utf8");
|
|
38
43
|
const parsed = JSON.parse(existing) as Partial<SubagentEnginesFile>;
|
|
@@ -44,22 +49,13 @@ export function syncEnginesFile(agentDir: string): void {
|
|
|
44
49
|
) {
|
|
45
50
|
return;
|
|
46
51
|
}
|
|
47
|
-
} catch {
|
|
52
|
+
} catch (err) {
|
|
48
53
|
// 现文件缺失/损坏 → 走写入
|
|
54
|
+
void err;
|
|
49
55
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
try {
|
|
53
|
-
fs.writeFileSync(tmp, serialized, "utf8");
|
|
54
|
-
fs.renameSync(tmp, filePath);
|
|
55
|
-
} finally {
|
|
56
|
-
try {
|
|
57
|
-
if (fs.existsSync(tmp)) fs.unlinkSync(tmp);
|
|
58
|
-
} catch {
|
|
59
|
-
// rename 失败路径的残留清理 best-effort
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
} catch {
|
|
56
|
+
writeAtomicFileSync(filePath, serialized);
|
|
57
|
+
} catch (err) {
|
|
63
58
|
// 吞掉:见文件头 fail-safe 说明
|
|
59
|
+
void err;
|
|
64
60
|
}
|
|
65
61
|
}
|
|
@@ -29,9 +29,9 @@ export function executeOptionsToTaskSpec(opts: ExecuteOptions): AgentTaskSpec {
|
|
|
29
29
|
const persona: PersonaSpec | undefined =
|
|
30
30
|
opts.skillPath !== undefined || opts.appendSystemPrompt !== undefined
|
|
31
31
|
? {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
...(opts.skillPath !== undefined ? { skillPath: opts.skillPath } : {}),
|
|
33
|
+
...(opts.appendSystemPrompt !== undefined ? { appendSystemPrompt: opts.appendSystemPrompt } : {}),
|
|
34
|
+
}
|
|
35
35
|
: undefined;
|
|
36
36
|
return {
|
|
37
37
|
task: opts.task,
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fake app-server(R2 连接层测试专用,绝不 spawn 真 zcode.cjs)。
|
|
3
|
+
*
|
|
4
|
+
* 移植改造自 zsw 仓 84b63a0^ z-subagent-workflow/fixtures/fake-appserver.js 的测试
|
|
5
|
+
* 模式(该仓只读参照),vitest 子进程形态(ESM——本仓 eslint 禁 require,CJS 形态
|
|
6
|
+
* 被 no-require-imports 拦截):启动方式与真协议对齐——由被测 AppServerConnection
|
|
7
|
+
* 以 `node <本文件> app-server --cwd <dir>` spawn(argv 解析后记录进流水,不消费)。
|
|
8
|
+
* stdio NDJSON,帧形态对齐设计附录 A.1(无 jsonrpc 字段)。
|
|
9
|
+
*
|
|
10
|
+
* 测试断言面 = FAKE_STATE_FILE 事件流水(append JSONL):
|
|
11
|
+
* boot / env / recv(收到的每个客户端帧)/ reverse-answer(反向请求收到的我方应答)
|
|
12
|
+
* / unparseable-from-client。env 开关随 spawn env 固化:
|
|
13
|
+
* FAKE_STATE_FILE 流水文件路径(未设则不记流水)
|
|
14
|
+
* FAKE_STDERR=1 启动时往 stderr 写两行(tee 落盘断言取证)
|
|
15
|
+
* FAKE_EXTRA_KEYS=1 我方应答/推送帧携带未知键(客户端宽容解析断言)
|
|
16
|
+
* FAKE_PROTOCOL_PUSH=1 协议自报走 {method:'protocol'} 推送形态(缺省走 A.1 首帧
|
|
17
|
+
* {protocol:{...}} 形态)
|
|
18
|
+
*
|
|
19
|
+
* 内置方法(可编程注入四帧型的全部形态):
|
|
20
|
+
* test/echo 应答 {id, result: params}(原样回显——并发 id 关联断言依据)
|
|
21
|
+
* test/delay-echo delayMs 后应答回显(制造在途请求)
|
|
22
|
+
* test/fail 应答 {id, error:{code,message,data}}(params 指定)
|
|
23
|
+
* test/push 先推一帧 {method: pushMethod, params: pushParams} 再应答
|
|
24
|
+
* test/reverse 发一个反向请求(method=params.reverseMethod)并等客户端
|
|
25
|
+
* 应答,流水记录后回 {id, result:{answered:true}}
|
|
26
|
+
* test/malformed-first 先写一行非 JSON 再正常应答(坏行跳过不断流断言)
|
|
27
|
+
* test/suicide stderr 写 600 字符噪声 + 标记后 exit(1)(崩溃收割断言)
|
|
28
|
+
* session/create 真实协议语义(A.2):先发反向请求 session/requestRuntime
|
|
29
|
+
* Preferences 并等客户端应答(D9 常量表断言依据),流水记录
|
|
30
|
+
* 后回 {session:{sessionId}}
|
|
31
|
+
* session/subscribe 应答 {subscribed:true}(R3;真实应答形状未知——会话层不校验)
|
|
32
|
+
* session/send 按 FAKE_SESSION_SCENARIO 推送帧序列后应答(缺省 {accepted:true})
|
|
33
|
+
* session/read 按 FAKE_SESSION_SCENARIO 应答(缺省 {messages:[]})
|
|
34
|
+
* session/close 应答 {closed:true}
|
|
35
|
+
* 其余方法 应答 -32601(method not found)
|
|
36
|
+
*
|
|
37
|
+
* 会话场景注入(R3 会话层测试;不设 = 各方法走缺省行为,R2 连接层测试不受影响):
|
|
38
|
+
* FAKE_SESSION_SCENARIO=<path> 启动时读取一次的 JSON 文件:
|
|
39
|
+
* {
|
|
40
|
+
* createResult?: object 覆盖 create 应答(golden create 应答注入)
|
|
41
|
+
* createError?: {code,message,data} create 应答 error 帧(-32602/-32601 注入)
|
|
42
|
+
* sendError?: {code,message,data} send 应答 error 帧(-32010/-32602 注入)
|
|
43
|
+
* sendPushes?: [frame, ...] send 应答前逐帧推送(推送流 + 终态帧全显式
|
|
44
|
+
* 逐字回放,不经 withExtra 改写)
|
|
45
|
+
* sendResult?: object 缺省 {accepted:true}
|
|
46
|
+
* readError?: {code,message,data} read 应答 error 帧(read 兜底降级链断言)
|
|
47
|
+
* readResult?: object 覆盖 read 应答
|
|
48
|
+
* stopBehavior?: 'terminal'|'none' session/stop 的行为(R4 abort 链断言面):
|
|
49
|
+
* 'terminal'(缺省)= stop 时推送该会话的
|
|
50
|
+
* turn.terminal 终态帧(stop 优雅生效——不杀
|
|
51
|
+
* 进程的 abort 路径);'none' = 只应答不推终态
|
|
52
|
+
* (grace 窗口耗尽 → killChain 兜底路径)
|
|
53
|
+
* }
|
|
54
|
+
*
|
|
55
|
+
* 多会话支持(R4 引擎接线 / RA3 双会话地基):
|
|
56
|
+
* FAKE_STAMP_SESSION=1 session/send 的推送帧回放时把 params.sessionId 统一改写
|
|
57
|
+
* 为「当前 send 的目标会话」,telemetry 帧(无 sid)补记
|
|
58
|
+
* sessionId——并发两会话各自收到归因正确的推送流,不串线。
|
|
59
|
+
* (缺省关:R2/R3 单会话用例的字节级行为不变。)
|
|
60
|
+
* session/stop 应答 {stopped:true};按 scenario.stopBehavior 决定是否
|
|
61
|
+
* 推送终态帧(见上)。stopTerminal 推送同样受 STAMP 改写。
|
|
62
|
+
*
|
|
63
|
+
* 探针连接支持(R5 降级链——D8 冒烟探针 / D2 门控断言面):
|
|
64
|
+
* ZCODE_APPSERVER_PROBE_CONN=1 本进程是探针连接(引擎 runAppServerSmokeProbe 叠加
|
|
65
|
+
* 的 env 标记):scenario 只读 FAKE_PROBE_SCENARIO(常驻
|
|
66
|
+
* 主连接的 FAKE_SESSION_SCENARIO 不作用于探针——故障注入可
|
|
67
|
+
* 只命中主连接或只命中探针);env 快照记 probe 标志。
|
|
68
|
+
* FAKE_PROBE_SCENARIO=<path> 仅探针进程消费的 JSON:
|
|
69
|
+
* { createError?: {code,message,data} } 探针 create 应答 error 帧(探针失败注入)
|
|
70
|
+
* { hangCreate?: true } create 永不应答(预算超时注入)
|
|
71
|
+
*/
|
|
72
|
+
import fs from 'node:fs';
|
|
73
|
+
import readline from 'node:readline';
|
|
74
|
+
|
|
75
|
+
const STATE_FILE = process.env.FAKE_STATE_FILE;
|
|
76
|
+
const EXTRA_KEYS = process.env.FAKE_EXTRA_KEYS === '1';
|
|
77
|
+
const PROTOCOL_AS_PUSH = process.env.FAKE_PROTOCOL_PUSH === '1';
|
|
78
|
+
// [R4] 多会话推送改写开关(见文件头注释)
|
|
79
|
+
const STAMP_SESSION = process.env.FAKE_STAMP_SESSION === '1';
|
|
80
|
+
// [R5] 探针连接判定(引擎探针在 env 叠 ZCODE_APPSERVER_PROBE_CONN=1——见 appserver-probe.ts)
|
|
81
|
+
const IS_PROBE = process.env.ZCODE_APPSERVER_PROBE_CONN === '1';
|
|
82
|
+
|
|
83
|
+
// 会话场景(R3/R5):启动时读取一次(env 固化语义与其他 FAKE_ 开关一致)。探针进程
|
|
84
|
+
// 只读 FAKE_PROBE_SCENARIO(与主连接的故障注入互不串扰)
|
|
85
|
+
let SCENARIO = null;
|
|
86
|
+
if (process.env.FAKE_SESSION_SCENARIO && !IS_PROBE) {
|
|
87
|
+
try {
|
|
88
|
+
SCENARIO = JSON.parse(fs.readFileSync(process.env.FAKE_SESSION_SCENARIO, 'utf8'));
|
|
89
|
+
} catch (err) {
|
|
90
|
+
log('scenario-load-failed', { message: String(err && err.message) });
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (process.env.FAKE_PROBE_SCENARIO && IS_PROBE) {
|
|
94
|
+
try {
|
|
95
|
+
SCENARIO = JSON.parse(fs.readFileSync(process.env.FAKE_PROBE_SCENARIO, 'utf8'));
|
|
96
|
+
} catch (err) {
|
|
97
|
+
log('scenario-load-failed', { message: String(err && err.message) });
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
let seq = 0;
|
|
102
|
+
function log(ev, data = {}) {
|
|
103
|
+
if (!STATE_FILE) return;
|
|
104
|
+
try {
|
|
105
|
+
fs.appendFileSync(STATE_FILE, JSON.stringify({ seq: ++seq, ev, ...data }) + '\n');
|
|
106
|
+
} catch { /* 流水写失败不影响协议行为 */ }
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const out = (frame) => process.stdout.write(`${JSON.stringify(frame)}\n`);
|
|
110
|
+
const withExtra = (frame) => (EXTRA_KEYS ? { ...frame, unknownServerKey: 'lenient' } : frame);
|
|
111
|
+
const reply = (id, result) => out(withExtra({ id, result }));
|
|
112
|
+
const replyErr = (id, code, message, data) =>
|
|
113
|
+
out({ id, error: { code, message, ...(data !== undefined ? { data } : {}) } });
|
|
114
|
+
|
|
115
|
+
// 协议自报(A.1:首帧 {protocol:{...}};推送形态显式开关——两种到达形态都要被忽略)
|
|
116
|
+
if (PROTOCOL_AS_PUSH) out({ method: 'protocol', params: { name: 'ZCode Protocol', version: 1 } });
|
|
117
|
+
else out({ protocol: { name: 'ZCode Protocol', version: 1 } });
|
|
118
|
+
|
|
119
|
+
// SIGTERM 优雅窗口:默认终止会丢弃「已写入管道但尚未读到」的帧——延迟退出让
|
|
120
|
+
// stdin 排空后收尾(dispose 的 close-帧-先于-SIGTERM 顺序在本侧可观测:
|
|
121
|
+
// killChain 的 grace 远大于本窗口,不会升级 SIGKILL)
|
|
122
|
+
process.on('SIGTERM', () => {
|
|
123
|
+
setTimeout(() => process.exit(0), 100);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// env 快照 + boot 流水(惰性启动 / argv 形态 / env 惯例断言的数据源)
|
|
127
|
+
log('env', {
|
|
128
|
+
pid: process.pid,
|
|
129
|
+
home: process.env.HOME,
|
|
130
|
+
telemetry: process.env.ZCODE_MODEL_TELEMETRY_ENABLED,
|
|
131
|
+
nested: process.env.ZSW_NESTED,
|
|
132
|
+
unifiedNested: process.env.XYZ_AGENT_SUBAGENT,
|
|
133
|
+
probe: process.env.ZCODE_APPSERVER_PROBE_CONN,
|
|
134
|
+
});
|
|
135
|
+
log('boot', { pid: process.pid, argv: process.argv.slice(2) });
|
|
136
|
+
if (process.env.FAKE_STDERR === '1') {
|
|
137
|
+
process.stderr.write('fake-appserver stderr line A\nfake-appserver stderr line B\n');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// 反向请求记账:id -> 客户端应答到达时 resolve
|
|
141
|
+
let reqSeq = 0;
|
|
142
|
+
const pendingReverse = new Map();
|
|
143
|
+
|
|
144
|
+
function sendReverse(method, params) {
|
|
145
|
+
return new Promise((resolve) => {
|
|
146
|
+
const id = `srv-${++reqSeq}`;
|
|
147
|
+
pendingReverse.set(id, resolve);
|
|
148
|
+
out({ id, method, ...(params !== undefined ? { params } : {}) });
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function onClientAnswer(frame) {
|
|
153
|
+
const settle = pendingReverse.get(frame.id);
|
|
154
|
+
if (settle) {
|
|
155
|
+
pendingReverse.delete(frame.id);
|
|
156
|
+
settle({ id: frame.id, result: frame.result, error: frame.error });
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// 推送帧回放(scenario 帧即 golden 语料/注入形态本身,不走 withExtra)。STAMP_SESSION
|
|
161
|
+
// 开启时统一改写/补记 params.sessionId 为目标会话(RA3 双会话地基:并发两会话各自
|
|
162
|
+
// 收到归因正确的推送流——真服务端推送本就按会话归因,telemetry 帧不带 sid 属协议
|
|
163
|
+
// 实测形态,stamp 是 fake 侧的确定性等价物)。
|
|
164
|
+
function pushFrames(frames, targetSessionId) {
|
|
165
|
+
for (const frame of frames || []) {
|
|
166
|
+
if (!STAMP_SESSION || !targetSessionId) {
|
|
167
|
+
out(frame);
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
const stamped = JSON.parse(JSON.stringify(frame));
|
|
171
|
+
if (stamped && typeof stamped.params === 'object' && stamped.params !== null) {
|
|
172
|
+
stamped.params.sessionId = targetSessionId;
|
|
173
|
+
}
|
|
174
|
+
out(stamped);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// [R4] stop 触发的终态推送(stopBehavior 缺省 'terminal'——abort 优雅生效路径)
|
|
179
|
+
const TURN_TERMINAL_FRAME = {
|
|
180
|
+
method: 'v4/telemetry/event',
|
|
181
|
+
params: { kind: 'turn.terminal', status: 'success' },
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
async function handleRequest(f) {
|
|
185
|
+
const { id, method } = f;
|
|
186
|
+
const params = f.params ?? {};
|
|
187
|
+
switch (method) {
|
|
188
|
+
case 'test/echo':
|
|
189
|
+
return reply(id, params);
|
|
190
|
+
case 'test/delay-echo': {
|
|
191
|
+
const delay = Number(params.delayMs) || 50;
|
|
192
|
+
setTimeout(() => reply(id, params), delay);
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
case 'test/fail':
|
|
196
|
+
return replyErr(id, Number(params.code) || -32603, String(params.message || 'fake failure'), params.data);
|
|
197
|
+
case 'test/push': {
|
|
198
|
+
const pushMethod = String(params.pushMethod || 'test/notification');
|
|
199
|
+
out(withExtra({ method: pushMethod, ...(params.pushParams !== undefined ? { params: params.pushParams } : {}) }));
|
|
200
|
+
return reply(id, { pushed: true });
|
|
201
|
+
}
|
|
202
|
+
case 'test/reverse': {
|
|
203
|
+
const answer = await sendReverse(String(params.reverseMethod || 'permission/request'), params.reverseParams);
|
|
204
|
+
log('reverse-answer', { requested: params.reverseMethod, answer });
|
|
205
|
+
return reply(id, { answered: true });
|
|
206
|
+
}
|
|
207
|
+
case 'test/malformed-first':
|
|
208
|
+
process.stdout.write('this is not json {{{\n');
|
|
209
|
+
return reply(id, { survived: true });
|
|
210
|
+
case 'test/suicide':
|
|
211
|
+
process.stderr.write('A'.repeat(600) + 'CRASH-MARK-TAIL');
|
|
212
|
+
process.exit(1);
|
|
213
|
+
return; // 不可达(exit 先行),保持 switch 完整
|
|
214
|
+
case 'session/create': {
|
|
215
|
+
// [R5] 探针预算超时注入:hangCreate 时永不应答(探针 deadline 收割判据)
|
|
216
|
+
if (SCENARIO && SCENARIO.hangCreate) return;
|
|
217
|
+
if (SCENARIO && SCENARIO.createError) {
|
|
218
|
+
return replyErr(id, SCENARIO.createError.code, SCENARIO.createError.message, SCENARIO.createError.data);
|
|
219
|
+
}
|
|
220
|
+
const answer = await sendReverse('session/requestRuntimePreferences');
|
|
221
|
+
log('reverse-answer', { requested: 'session/requestRuntimePreferences', answer });
|
|
222
|
+
if (SCENARIO && SCENARIO.createResult) return reply(id, SCENARIO.createResult);
|
|
223
|
+
return reply(id, { session: { sessionId: `sess_${id}` } });
|
|
224
|
+
}
|
|
225
|
+
case 'session/subscribe':
|
|
226
|
+
return reply(id, (SCENARIO && SCENARIO.subscribeResult) || { subscribed: true });
|
|
227
|
+
case 'session/send': {
|
|
228
|
+
if (SCENARIO && SCENARIO.sendError) {
|
|
229
|
+
return replyErr(id, SCENARIO.sendError.code, SCENARIO.sendError.message, SCENARIO.sendError.data);
|
|
230
|
+
}
|
|
231
|
+
// 推送帧逐字回放(STAMP_SESSION 时按目标会话归因改写)
|
|
232
|
+
pushFrames(SCENARIO && SCENARIO.sendPushes, String(params.sessionId || ''));
|
|
233
|
+
return reply(id, (SCENARIO && SCENARIO.sendResult) || { accepted: true });
|
|
234
|
+
}
|
|
235
|
+
case 'session/stop': {
|
|
236
|
+
// [R4] abort 链断言面:缺省推终态(stop 优雅生效);stopBehavior:'none' 只应答
|
|
237
|
+
const behavior = (SCENARIO && SCENARIO.stopBehavior) || 'terminal';
|
|
238
|
+
if (behavior === 'terminal') {
|
|
239
|
+
pushFrames([TURN_TERMINAL_FRAME], String(params.sessionId || ''));
|
|
240
|
+
}
|
|
241
|
+
return reply(id, { stopped: true });
|
|
242
|
+
}
|
|
243
|
+
case 'session/read': {
|
|
244
|
+
if (SCENARIO && SCENARIO.readError) {
|
|
245
|
+
return replyErr(id, SCENARIO.readError.code, SCENARIO.readError.message, SCENARIO.readError.data);
|
|
246
|
+
}
|
|
247
|
+
return reply(id, (SCENARIO && SCENARIO.readResult) || { messages: [] });
|
|
248
|
+
}
|
|
249
|
+
case 'session/close':
|
|
250
|
+
return reply(id, { closed: true });
|
|
251
|
+
default:
|
|
252
|
+
return replyErr(id, -32601, `method not found: ${method}`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const rl = readline.createInterface({ input: process.stdin });
|
|
257
|
+
rl.on('line', (line) => {
|
|
258
|
+
const text = String(line).trim();
|
|
259
|
+
if (!text) return;
|
|
260
|
+
let f;
|
|
261
|
+
try {
|
|
262
|
+
f = JSON.parse(text);
|
|
263
|
+
} catch {
|
|
264
|
+
log('unparseable-from-client', { line: text.slice(0, 100) });
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
log('recv', { frame: f });
|
|
268
|
+
if (f && f.id != null && typeof f.method === 'string') {
|
|
269
|
+
void handleRequest(f);
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
if (f && f.id != null) onClientAnswer(f); // 我方反向请求的客户端应答
|
|
273
|
+
});
|
|
274
|
+
rl.on('close', () => process.exit(0));
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_meta": {
|
|
3
|
+
"description": "zcode app-server 常驻通道 golden 帧序列语料(R3)。四类样本:create 应答 / 推送流 / 终态帧 / read 应答(NDJSON 逐行,附录 A.2 任务生命周期帧序)",
|
|
4
|
+
"source": "synthesized-from-A2-protocol-authority",
|
|
5
|
+
"synthesisNote": "非真机实录——按设计附录 A.2(协议权威,zcode.cjs 0.16.5 二进制字符串级验证命中)+ 旧 zsw 实现真机抓包形态(zsw 仓 84b63a0^ runner-appserver.js 实测注释)合成。真机冒烟(RA 跨仓段)后应替换为实录并同步双副本。telemetry 帧不带 sessionId(A.2 未标)——归因走唯一在途兜底;session/event 帧带 sessionId",
|
|
6
|
+
"engineVersion": "0.16.5 (app-server)",
|
|
7
|
+
"protocolVersion": 1,
|
|
8
|
+
"recordedAt": "2026-08-30",
|
|
9
|
+
"invariants": {
|
|
10
|
+
"textIdentity": "pushStream 中 payload.delta 拼接 === terminal 收尾帧 payload.response === readResponse 最后 assistant 消息 text parts 拼接('你好,任务完成')——不变量 1 双来源",
|
|
11
|
+
"usage": "收尾帧 usage {inputTokens:12599, outputTokens:17} 与 spawn golden(zcode-golden-spawn.json)同值——漂移对照锚点"
|
|
12
|
+
},
|
|
13
|
+
"frames": {
|
|
14
|
+
"createResponse": "session/create 应答帧(NDJSON 单行)。projection.sessionId 恒 \"unknown\"(勿用),权威位置 session.sessionId",
|
|
15
|
+
"pushStream": "推送流帧(A.2 ④ 逐行):state.updated 进入 running / v4 telemetry stream.chunk(无文本,chunkLength 遥测)/ session/event payload.delta(实时文本增量)",
|
|
16
|
+
"terminal": "终态帧(A.2 ⑤ 逐行):v4 telemetry turn.terminal(终态权威,status 枚举)+ session/event 收尾帧(全文 + usage)",
|
|
17
|
+
"readResponse": "session/read 应答帧(NDJSON 单行,A.2 ⑥):messages[].info.role + parts[](text 全文 / step-finish tokens——tokens 结构属 A.5 未确认项,宽容解析)"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"frames": {
|
|
21
|
+
"createResponse": "{\"session\":{\"sessionId\":\"sess_golden_r3_01\"},\"projection\":{\"sessionId\":\"unknown\",\"status\":\"idle\",\"turnCount\":0,\"totalTokenCount\":0,\"contextUsed\":0,\"contextWindow\":1000000}}",
|
|
22
|
+
"pushStream": [
|
|
23
|
+
"{\"method\":\"state.updated\",\"params\":{\"sessionId\":\"sess_golden_r3_01\",\"patch\":{\"status\":\"running\"},\"reason\":\"prompt_started\"}}",
|
|
24
|
+
"{\"method\":\"v4/telemetry/event\",\"params\":{\"kind\":\"stream.chunk\",\"channel\":\"text\",\"chunkLength\":6,\"firstChunk\":true,\"assistantMessageId\":\"msg_golden_r3_01\"}}",
|
|
25
|
+
"{\"method\":\"session/event\",\"params\":{\"sessionId\":\"sess_golden_r3_01\",\"payload\":{\"delta\":\"你好\",\"assistantMessageId\":\"msg_golden_r3_01\"}}}",
|
|
26
|
+
"{\"method\":\"v4/telemetry/event\",\"params\":{\"kind\":\"stream.chunk\",\"channel\":\"text\",\"chunkLength\":1,\"firstChunk\":false,\"assistantMessageId\":\"msg_golden_r3_01\"}}",
|
|
27
|
+
"{\"method\":\"session/event\",\"params\":{\"sessionId\":\"sess_golden_r3_01\",\"payload\":{\"delta\":\",\",\"assistantMessageId\":\"msg_golden_r3_01\"}}}",
|
|
28
|
+
"{\"method\":\"session/event\",\"params\":{\"sessionId\":\"sess_golden_r3_01\",\"payload\":{\"delta\":\"任务完成\",\"assistantMessageId\":\"msg_golden_r3_01\"}}}"
|
|
29
|
+
],
|
|
30
|
+
"terminal": [
|
|
31
|
+
"{\"method\":\"v4/telemetry/event\",\"params\":{\"kind\":\"turn.terminal\",\"status\":\"success\"}}",
|
|
32
|
+
"{\"method\":\"session/event\",\"params\":{\"sessionId\":\"sess_golden_r3_01\",\"payload\":{\"response\":\"你好,任务完成\",\"usage\":{\"inputTokens\":12599,\"outputTokens\":17}}}}"
|
|
33
|
+
],
|
|
34
|
+
"readResponse": "{\"messages\":[{\"info\":{\"role\":\"user\"},\"parts\":[{\"type\":\"text\",\"text\":\"做点什么\"}]},{\"info\":{\"role\":\"assistant\"},\"parts\":[{\"type\":\"text\",\"text\":\"你好\"},{\"type\":\"text\",\"text\":\",任务完成\"},{\"type\":\"step-finish\",\"tokens\":{\"input\":12599,\"output\":17,\"reasoning\":0,\"cache\":512,\"total\":12616}}]}]}"
|
|
35
|
+
}
|
|
36
|
+
}
|