@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.
Files changed (278) hide show
  1. package/README.md +1 -1
  2. package/dist/chunk-KXVBIVOU.js +16 -0
  3. package/dist/chunk-T2SYBW3I.js +24 -0
  4. package/dist/chunk-VURUAGMM.js +2305 -0
  5. package/dist/{types-C3fE3R9x.d.cts → engine-discovery-scan-ocpM8FmI.d.cts} +770 -668
  6. package/dist/{types-C3fE3R9x.d.ts → engine-discovery-scan-ocpM8FmI.d.ts} +770 -668
  7. package/dist/execution/engine/engine-discovery-scan.cjs +2210 -0
  8. package/dist/execution/engine/engine-discovery-scan.d.cts +4 -0
  9. package/dist/execution/engine/engine-discovery-scan.d.ts +4 -0
  10. package/dist/execution/engine/engine-discovery-scan.js +20 -0
  11. package/dist/execution/engine/paths.cjs +6 -23
  12. package/dist/execution/engine/paths.d.cts +1 -8
  13. package/dist/execution/engine/paths.d.ts +1 -8
  14. package/dist/execution/engine/paths.js +1 -1
  15. package/dist/execution/relay-env.cjs +12 -28
  16. package/dist/execution/relay-env.d.cts +1 -33
  17. package/dist/execution/relay-env.d.ts +1 -33
  18. package/dist/execution/relay-env.js +5 -3
  19. package/dist/index.cjs +14045 -16059
  20. package/dist/index.d.cts +1035 -1579
  21. package/dist/index.d.ts +1035 -1579
  22. package/dist/index.js +9838 -13800
  23. package/dist.bundle/index.cjs +28875 -30323
  24. package/package.json +20 -26
  25. package/src/__tests__/record-store-last-line.test.ts +16 -7
  26. package/src/core/error-message.ts +7 -6
  27. package/src/core/host-services.ts +8 -2
  28. package/src/core/notify-ports.ts +17 -2
  29. package/src/execution/__tests__/chat-engine-routing.test.ts +62 -28
  30. package/src/execution/__tests__/chat-round-first-round-watchdog.test.ts +255 -0
  31. package/src/execution/__tests__/collect-coordinator-service.test.ts +36 -47
  32. package/src/execution/__tests__/collect-mixed-dispatch.test.ts +20 -53
  33. package/src/execution/__tests__/delivery-methods.test.ts +179 -237
  34. package/src/execution/__tests__/execute-and-await-worktree.test.ts +0 -2
  35. package/src/execution/__tests__/execute-nesting.test.ts +20 -13
  36. package/src/execution/__tests__/explicit-agent-ref-guard.test.ts +20 -33
  37. package/src/execution/__tests__/gc-timer.test.ts +7 -22
  38. package/src/execution/__tests__/get-record-for-action-restart.test.ts +20 -10
  39. package/src/execution/__tests__/helpers/fake-engine-port.ts +187 -0
  40. package/src/execution/__tests__/helpers/spawn-mock.ts +36 -9
  41. package/src/execution/__tests__/helpers/subagent-service-mocks.ts +1 -1
  42. package/src/execution/__tests__/idle-gc.test.ts +200 -0
  43. package/src/execution/__tests__/lifecycle-predicates.test.ts +26 -21
  44. package/src/execution/__tests__/nested-visibility-env-propagation.test.ts +5 -2
  45. package/src/execution/__tests__/reconcile-sweep.test.ts +200 -0
  46. package/src/execution/__tests__/record-store.test.ts +60 -6
  47. package/src/execution/__tests__/recursive-visibility-baseline.test.ts +20 -13
  48. package/src/execution/__tests__/round-supervisor.test.ts +293 -0
  49. package/src/execution/__tests__/session-pending.test.ts +119 -17
  50. package/src/execution/__tests__/stream-sink-retirement.test.ts +10 -10
  51. package/src/execution/__tests__/subagent-service-multiproc-guard.test.ts +1 -11
  52. package/src/execution/__tests__/subagent-service-notify-gate.test.ts +33 -30
  53. package/src/execution/__tests__/subagent-service-parent-guard.test.ts +2 -9
  54. package/src/execution/__tests__/subagent-service-recovery-bounds.test.ts +59 -129
  55. package/src/execution/__tests__/subagent-service.test.ts +2 -2
  56. package/src/execution/__tests__/subprocess-agent-runner-routing.test.ts +109 -7
  57. package/src/execution/__tests__/subprocess-agent-runner.test.ts +108 -36
  58. package/src/execution/__tests__/sync-collect-recovery.test.ts +21 -36
  59. package/src/execution/__tests__/workflow-state-root.test.ts +232 -0
  60. package/src/execution/agent-registry.ts +6 -2
  61. package/src/execution/dialog-queue.ts +6 -73
  62. package/src/execution/engine/__tests__/common/capability-gate.test.ts +115 -15
  63. package/src/execution/engine/__tests__/common/errors.test.ts +11 -18
  64. package/src/execution/engine/__tests__/common/kill-chain.test.ts +7 -0
  65. package/src/execution/engine/__tests__/common/nesting-guard.test.ts +9 -3
  66. package/src/execution/engine/__tests__/common/session-view-service.test.ts +90 -3
  67. package/src/execution/engine/__tests__/conformance/H9-test-disposition.md +116 -0
  68. package/src/execution/engine/__tests__/conformance/__fixtures__/engine-protocol/fake-engine-protocol.mjs +377 -0
  69. package/src/execution/engine/__tests__/conformance/__fixtures__/engine-protocol/recorded.fixture.json +331 -0
  70. package/src/execution/engine/__tests__/conformance/__fixtures__/engine-protocol/smoke-run.fixture.json +213 -0
  71. package/src/execution/engine/__tests__/conformance/chat-round-protocol.test.ts +230 -0
  72. package/src/execution/engine/__tests__/conformance/contract.abort.test.ts +69 -42
  73. package/src/execution/engine/__tests__/conformance/contract.agent-events.test.ts +4 -81
  74. package/src/execution/engine/__tests__/conformance/contract.probe.test.ts +67 -44
  75. package/src/execution/engine/__tests__/conformance/contract.read-degradation.test.ts +81 -54
  76. package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +133 -70
  77. package/src/execution/engine/__tests__/conformance/engine-crash.test.ts +143 -0
  78. package/src/execution/engine/__tests__/conformance/fake-engine-capabilities.ts +19 -0
  79. package/src/execution/engine/__tests__/conformance/golden-replay.pi.test.ts +7 -2
  80. package/src/execution/engine/__tests__/conformance/golden-replay.zcode.test.ts +6 -5
  81. package/src/execution/engine/__tests__/conformance/protocol-blackbox.test.ts +398 -0
  82. package/src/execution/engine/__tests__/conformance/registry-fork-filter.test.ts +221 -0
  83. package/src/execution/engine/__tests__/conformance/round-liveness-supervisor.test.ts +302 -0
  84. package/src/execution/engine/__tests__/conformance/static-spawn-guard.test.ts +58 -0
  85. package/src/execution/engine/__tests__/engine-discovery-scan.test.ts +558 -0
  86. package/src/execution/engine/__tests__/host-task-spec.test.ts +45 -0
  87. package/src/execution/engine/__tests__/model-ref-split.test.ts +74 -0
  88. package/src/execution/engine/__tests__/registry.test.ts +206 -1
  89. package/src/execution/engine/__tests__/routing.test.ts +97 -0
  90. package/src/execution/engine/__tests__/run-failure-worktree-cleanup.test.ts +97 -0
  91. package/src/execution/engine/client/__tests__/__fixtures__/fake-engine.mjs +294 -0
  92. package/src/execution/engine/client/__tests__/engine-client.test.ts +516 -0
  93. package/src/execution/engine/client/__tests__/mirror.test.ts +67 -0
  94. package/src/execution/engine/client/__tests__/pid-file.test.ts +257 -0
  95. package/src/execution/engine/client/__tests__/protocol-closure.test.ts +95 -0
  96. package/src/execution/engine/client/__tests__/remote-engine.test.ts +457 -0
  97. package/src/execution/engine/client/client-options.ts +103 -0
  98. package/src/execution/engine/client/engine-client.ts +687 -0
  99. package/src/execution/engine/client/mirror.ts +167 -0
  100. package/src/execution/engine/client/pid-file.ts +392 -0
  101. package/src/execution/engine/client/reaper.ts +95 -0
  102. package/src/execution/engine/client/remote-engine.ts +441 -0
  103. package/src/execution/engine/client/reverse-router.ts +255 -0
  104. package/src/execution/engine/common/capability-gate.ts +109 -22
  105. package/src/execution/engine/common/errors.ts +9 -25
  106. package/src/execution/engine/common/event-journal.ts +4 -50
  107. package/src/execution/engine/common/journal-replay.ts +3 -1
  108. package/src/execution/engine/common/kill-chain.ts +18 -251
  109. package/src/execution/engine/common/nesting-guard.ts +18 -114
  110. package/src/execution/engine/common/pool-manager.ts +4 -0
  111. package/src/execution/engine/common/session-view-service.ts +56 -84
  112. package/src/execution/engine/config.ts +151 -0
  113. package/src/execution/engine/d8-compat.ts +346 -0
  114. package/src/execution/engine/engine-discovery-roots.ts +107 -0
  115. package/src/execution/engine/engine-discovery-scan.ts +269 -0
  116. package/src/execution/engine/engine-discovery.ts +30 -7
  117. package/src/execution/engine/engine-inspect-package.ts +282 -0
  118. package/src/execution/engine/engine-manifest.ts +244 -0
  119. package/src/execution/engine/host/__tests__/host-askuser-endpoint.test.ts +123 -0
  120. package/src/execution/engine/host/__tests__/host-bridge.test.ts +135 -0
  121. package/src/execution/engine/host/__tests__/spawned-children.test.ts +73 -0
  122. package/src/execution/engine/host/host-bridge.ts +150 -0
  123. package/src/execution/engine/host/host-ui-endpoint.ts +47 -0
  124. package/src/execution/engine/host/pi-host-binding.ts +91 -0
  125. package/src/execution/engine/host/spawned-children.ts +139 -0
  126. package/src/execution/engine/host-task-spec.ts +29 -2
  127. package/src/execution/engine/model-validation.ts +55 -2
  128. package/src/execution/engine/paths.ts +16 -41
  129. package/src/execution/engine/port.ts +48 -2
  130. package/src/execution/engine/registry.ts +153 -34
  131. package/src/execution/engine/routing.ts +225 -52
  132. package/src/execution/engine/types.ts +25 -200
  133. package/src/execution/finalize-record.ts +25 -0
  134. package/src/execution/idle-gc.ts +89 -14
  135. package/src/execution/lifecycle-manager.ts +10 -7
  136. package/src/execution/lifecycle-predicates.ts +10 -8
  137. package/src/execution/record-store.ts +29 -2
  138. package/src/execution/relay-env.ts +19 -36
  139. package/src/execution/round-supervisor/domain.ts +89 -0
  140. package/src/execution/round-supervisor/index.ts +33 -0
  141. package/src/execution/round-supervisor/notify-accounting.ts +87 -0
  142. package/src/execution/round-supervisor/reconcile-sweep.ts +235 -0
  143. package/src/execution/round-supervisor/service-binding.test.ts +661 -0
  144. package/src/execution/round-supervisor/service-binding.ts +273 -0
  145. package/src/execution/round-supervisor/supervisor.ts +426 -0
  146. package/src/execution/session-pending.ts +68 -74
  147. package/src/execution/settled-watchdog.ts +39 -0
  148. package/src/execution/subagent-service.ts +746 -400
  149. package/src/execution/subprocess-agent-runner.ts +16 -8
  150. package/src/execution/types.ts +41 -117
  151. package/src/execution/ui-channels.ts +13 -214
  152. package/src/execution/ui-request-handler-factory.ts +7 -4
  153. package/src/execution/ui-request-observability.ts +2 -2
  154. package/src/execution/workflow-state-root.ts +67 -0
  155. package/src/execution/worktree-git-ops.ts +5 -0
  156. package/src/execution/worktree-manager.ts +11 -1
  157. package/src/index.ts +55 -26
  158. package/src/orchestration/__tests__/execute-agent-call.test.ts +1 -1
  159. package/src/orchestration/execute-agent-call.ts +1 -1
  160. package/src/orchestration/file-run-store.ts +144 -59
  161. package/src/orchestration/models/types.ts +43 -42
  162. package/src/shared/zcode-model-ref.ts +31 -0
  163. package/dist/chunk-43ONBFZX.js +0 -240
  164. package/dist/chunk-A4IVZWVX.js +0 -31
  165. package/dist/chunk-APZY4IME.js +0 -27
  166. package/dist/chunk-V3VHZ2VX.js +0 -59
  167. package/dist/execution/engine/engines/zcode/constants.cjs +0 -107
  168. package/dist/execution/engine/engines/zcode/constants.d.cts +0 -135
  169. package/dist/execution/engine/engines/zcode/constants.d.ts +0 -135
  170. package/dist/execution/engine/engines/zcode/constants.js +0 -54
  171. package/dist/execution/engine/engines/zcode/reader.cjs +0 -276
  172. package/dist/execution/engine/engines/zcode/reader.d.cts +0 -21
  173. package/dist/execution/engine/engines/zcode/reader.d.ts +0 -21
  174. package/dist/execution/engine/engines/zcode/reader.js +0 -9
  175. package/src/__tests__/append-system-prompt-assembly.test.ts +0 -243
  176. package/src/__tests__/fr4-get-state-handshake.test.ts +0 -125
  177. package/src/__tests__/session-runner.test.ts +0 -69
  178. package/src/execution/__tests__/ask-user-transit-e2e.test.ts +0 -490
  179. package/src/execution/__tests__/chatmode-first-round-closure-spawn.test.ts +0 -191
  180. package/src/execution/__tests__/descendant-sweep-guards.test.ts +0 -220
  181. package/src/execution/__tests__/descendant-sweep.test.ts +0 -269
  182. package/src/execution/__tests__/engine-model-validation.test.ts +0 -741
  183. package/src/execution/__tests__/epipe-fallback.test.ts +0 -248
  184. package/src/execution/__tests__/execution-runtime-face.test.ts +0 -272
  185. package/src/execution/__tests__/get-state-handshake.test.ts +0 -127
  186. package/src/execution/__tests__/helpers/session-runner-mocks.ts +0 -113
  187. package/src/execution/__tests__/keep-alive-no-progress.test.ts +0 -280
  188. package/src/execution/__tests__/kill-all-escalation.test.ts +0 -196
  189. package/src/execution/__tests__/max-turns-to-watchdog-ms.test.ts +0 -113
  190. package/src/execution/__tests__/output-collector.test.ts +0 -469
  191. package/src/execution/__tests__/pi-invocation.test.ts +0 -166
  192. package/src/execution/__tests__/recursive-visibility-env.test.ts +0 -149
  193. package/src/execution/__tests__/rpc-mode.test.ts +0 -89
  194. package/src/execution/__tests__/run-and-finalize-anchoring.test.ts +0 -387
  195. package/src/execution/__tests__/run-and-finalize-chatmode.test.ts +0 -277
  196. package/src/execution/__tests__/run-spawn-chatmode-settled.test.ts +0 -254
  197. package/src/execution/__tests__/run-spawn-edges.test.ts +0 -1079
  198. package/src/execution/__tests__/run-spawn-integration.test.ts +0 -933
  199. package/src/execution/__tests__/run-spawn-resume.test.ts +0 -322
  200. package/src/execution/__tests__/run-spawn-rpc-mode.test.ts +0 -196
  201. package/src/execution/__tests__/run-spawn-stdout-callback-throw.test.ts +0 -207
  202. package/src/execution/__tests__/service-kill-escalation.test.ts +0 -91
  203. package/src/execution/__tests__/session-runner-branch-cache-lru.test.ts +0 -110
  204. package/src/execution/__tests__/session-runner-close-prune.test.ts +0 -181
  205. package/src/execution/__tests__/session-runner-dispatch.test.ts +0 -489
  206. package/src/execution/__tests__/session-runner-epipe.test.ts +0 -179
  207. package/src/execution/__tests__/session-runner-heartbeat-idle-fallback.test.ts +0 -227
  208. package/src/execution/__tests__/session-runner-lifecycle-helpers.test.ts +0 -290
  209. package/src/execution/__tests__/session-runner-schema-env.test.ts +0 -352
  210. package/src/execution/__tests__/settled-watchdog.test.ts +0 -524
  211. package/src/execution/__tests__/spawn-args.test.ts +0 -446
  212. package/src/execution/__tests__/spawn-event-adapter-rpc.test.ts +0 -192
  213. package/src/execution/__tests__/spawn-event-adapter.test.ts +0 -167
  214. package/src/execution/__tests__/spawn-worktree-guidance.test.ts +0 -208
  215. package/src/execution/__tests__/spawned-children.test.ts +0 -236
  216. package/src/execution/__tests__/start-sync-model-guard.test.ts +0 -150
  217. package/src/execution/__tests__/stdin-writer.test.ts +0 -464
  218. package/src/execution/__tests__/subagent-service-message-close.test.ts +0 -693
  219. package/src/execution/__tests__/temp-prompt.test.ts +0 -53
  220. package/src/execution/__tests__/timeout-integration.test.ts +0 -616
  221. package/src/execution/__tests__/turn-limiter-semantics.test.ts +0 -194
  222. package/src/execution/__tests__/turn-limiter.test.ts +0 -65
  223. package/src/execution/__tests__/ui-request-handler.test.ts +0 -205
  224. package/src/execution/__tests__/ui-request-queue.test.ts +0 -298
  225. package/src/execution/__tests__/worktree-pid-registration.integration.test.ts +0 -230
  226. package/src/execution/engine/__tests__/common/schema-emulation.test.ts +0 -128
  227. package/src/execution/engine/__tests__/common/session-view-service-zcode-dbpath.test.ts +0 -149
  228. package/src/execution/engine/__tests__/conformance/__fixtures__/pi-golden-events.json +0 -28
  229. package/src/execution/engine/__tests__/conformance/zcode-appserver-harness.ts +0 -128
  230. package/src/execution/engine/__tests__/paths.test.ts +0 -39
  231. package/src/execution/engine/common/schema-emulation.ts +0 -189
  232. package/src/execution/engine/common/session-view-projection.ts +0 -51
  233. package/src/execution/engine/engines/pi/__tests__/pi-engine.test.ts +0 -615
  234. package/src/execution/engine/engines/pi/__tests__/reader.test.ts +0 -155
  235. package/src/execution/engine/engines/pi/__tests__/spawn-opts-direct.test.ts +0 -257
  236. package/src/execution/engine/engines/pi/argv-mirror.ts +0 -135
  237. package/src/execution/engine/engines/pi/get-state-handshake.ts +0 -179
  238. package/src/execution/engine/engines/pi/output-collector.ts +0 -317
  239. package/src/execution/engine/engines/pi/pi-engine.ts +0 -811
  240. package/src/execution/engine/engines/pi/pi-invocation.ts +0 -120
  241. package/src/execution/engine/engines/pi/reader.ts +0 -59
  242. package/src/execution/engine/engines/pi/registration.ts +0 -37
  243. package/src/execution/engine/engines/pi/session-runner.ts +0 -2840
  244. package/src/execution/engine/engines/pi/spawn-event-adapter.ts +0 -404
  245. package/src/execution/engine/engines/pi/stdin-writer.ts +0 -199
  246. package/src/execution/engine/engines/pi/temp-prompt.ts +0 -62
  247. package/src/execution/engine/engines/pi/turn-limiter.ts +0 -102
  248. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/fake-appserver.mjs +0 -301
  249. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/zcode-golden-appserver.json +0 -36
  250. package/src/execution/engine/engines/zcode/__tests__/appserver-launcher.test.ts +0 -321
  251. package/src/execution/engine/engines/zcode/__tests__/connection.test.ts +0 -473
  252. package/src/execution/engine/engines/zcode/__tests__/parser.test.ts +0 -43
  253. package/src/execution/engine/engines/zcode/__tests__/preparer.test.ts +0 -124
  254. package/src/execution/engine/engines/zcode/__tests__/reader.test.ts +0 -210
  255. package/src/execution/engine/engines/zcode/__tests__/registration.test.ts +0 -71
  256. package/src/execution/engine/engines/zcode/__tests__/session-channel-dispose-harvest.test.ts +0 -247
  257. package/src/execution/engine/engines/zcode/__tests__/session-channel-turn-timers.test.ts +0 -451
  258. package/src/execution/engine/engines/zcode/__tests__/session-channel.test.ts +0 -792
  259. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-appserver.test.ts +0 -782
  260. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-degrade.test.ts +0 -168
  261. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-dispose.test.ts +0 -210
  262. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-retry.test.ts +0 -353
  263. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-status.test.ts +0 -282
  264. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-timeout.test.ts +0 -372
  265. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.live.test.ts +0 -145
  266. package/src/execution/engine/engines/zcode/appserver-launcher.ts +0 -167
  267. package/src/execution/engine/engines/zcode/connection.ts +0 -598
  268. package/src/execution/engine/engines/zcode/constants.ts +0 -176
  269. package/src/execution/engine/engines/zcode/golden-sample.ts +0 -47
  270. package/src/execution/engine/engines/zcode/parser.ts +0 -102
  271. package/src/execution/engine/engines/zcode/preparer.ts +0 -235
  272. package/src/execution/engine/engines/zcode/reader.ts +0 -381
  273. package/src/execution/engine/engines/zcode/registration.ts +0 -37
  274. package/src/execution/engine/engines/zcode/session-channel.ts +0 -968
  275. package/src/execution/engine/engines/zcode/zcode-engine.ts +0 -1431
  276. package/src/execution/round-settlement.ts +0 -93
  277. package/src/execution/ui-request-queue.ts +0 -215
  278. package/src/shared/schema-env.ts +0 -44
@@ -1,321 +0,0 @@
1
- // appserver-launcher.test.ts —— wrapper fs 拦截语义 + 落盘幂等/覆盖 + exit 面。
2
- //
3
- // 防线背景:wrapper 的失效模式是静默的(曾出过首调走未赋值 __origReadFileSync
4
- // 导致拦截整体失效的 bug——56a49ad4c),本文件用「落盘产物 + 探针 fake CLI」的
5
- // 真进程集成形态锚定核心语义:v2 注入优先合并、existsSync 拦截(GUI-only 宿主)、
6
- // encoding 归一、no-patch 分支、透传不受影响。
7
-
8
- import * as childProcess from "node:child_process";
9
- import * as fs from "node:fs";
10
- import * as os from "node:os";
11
- import * as path from "node:path";
12
-
13
- import { afterEach, beforeEach, describe, expect, it } from "vitest";
14
-
15
- import {
16
- APPSERVER_LAUNCHER_SOURCE,
17
- ZCODE_APPSERVER_LAUNCHER_NAME,
18
- ensureAppServerLauncher,
19
- } from "../appserver-launcher.ts";
20
-
21
- // 探针 fake CLI:以 wrapper 注入后的 fs 形态读取 CONFIG_PATH 的各种调用形态并
22
- // 落盘 state(wrapper 对它 import() 启动——与真实 zcode.cjs 同入口形态)
23
- const PROBE_SOURCE = `'use strict';
24
- const fs = require('node:fs');
25
- const path = require('node:path');
26
- const os = require('node:os');
27
- const CONFIG = path.join(os.homedir(), '.zcode', 'cli', 'config.json');
28
- const OTHER = path.join(os.homedir(), '.probe-other.txt');
29
- const STATE = process.env.ZCODE_PROBE_STATE;
30
- function grab(v) {
31
- if (Buffer.isBuffer(v)) return { kind: 'buffer', text: v.toString('utf8') };
32
- return { kind: typeof v, text: String(v) };
33
- }
34
- async function main() {
35
- const out = {};
36
- out.existsConfig = fs.existsSync(CONFIG);
37
- out.existsMissing = fs.existsSync(path.join(os.homedir(), '.no-such-file'));
38
- out.existsOther = fs.existsSync(OTHER);
39
- const tries = (label, fn) => {
40
- try { out[label] = grab(fn()); } catch (err) { out[label] = { kind: 'error', code: err && err.code }; }
41
- };
42
- tries('syncUtf8', () => fs.readFileSync(CONFIG, 'utf8'));
43
- tries('syncUtf8Dash', () => fs.readFileSync(CONFIG, 'utf-8'));
44
- tries('syncUtf8Obj', () => fs.readFileSync(CONFIG, { encoding: 'utf-8' }));
45
- tries('syncNoEnc', () => fs.readFileSync(CONFIG));
46
- tries('syncOther', () => fs.readFileSync(OTHER, 'utf8'));
47
- out.promiseUtf8Dash = await fs.promises.readFile(CONFIG, 'utf-8').then(
48
- (v) => grab(v), (err) => ({ kind: 'error', code: err && err.code }));
49
- fs.writeFileSync(STATE, JSON.stringify(out));
50
- }
51
- main().then(() => process.exit(0), (err) => {
52
- process.stderr.write('probe failed: ' + (err && err.stack || err));
53
- process.exit(9);
54
- });
55
- `;
56
-
57
- interface ProbeState {
58
- existsConfig: boolean;
59
- existsMissing: boolean;
60
- existsOther: boolean;
61
- syncUtf8: { kind: string; text?: string; code?: string };
62
- syncUtf8Dash: { kind: string; text?: string; code?: string };
63
- syncUtf8Obj: { kind: string; text?: string; code?: string };
64
- syncNoEnc: { kind: string; text?: string; code?: string };
65
- syncOther: { kind: string; text?: string; code?: string };
66
- promiseUtf8Dash: { kind: string; text?: string; code?: string };
67
- [k: string]: unknown;
68
- }
69
-
70
- let tmpRoot: string;
71
-
72
- interface HomeSpec {
73
- /** v2 config 原文(与 v2 字段互斥,用于损坏/缺失场景) */
74
- v2Raw?: string;
75
- /** v2 config 对象形态 */
76
- v2?: unknown;
77
- /** cli config 原文(与 real 字段互斥) */
78
- realRaw?: string;
79
- /** cli config 对象形态;undefined = 不布置该文件(GUI-only 宿主) */
80
- real?: unknown;
81
- }
82
-
83
- function setupHome(spec: HomeSpec): { run: () => childProcess.SpawnSyncReturns<string>; state: () => ProbeState } {
84
- const home = fs.mkdtempSync(path.join(tmpRoot, "home-"));
85
- const engineDataDir = fs.mkdtempSync(path.join(tmpRoot, "eng-"));
86
- const cliDir = path.join(home, ".zcode", "cli");
87
- fs.mkdirSync(cliDir, { recursive: true });
88
- fs.writeFileSync(path.join(home, ".probe-other.txt"), "OTHER-CONTENT");
89
- const v2Path = path.join(home, ".zcode", "v2", "config.json");
90
- fs.mkdirSync(path.dirname(v2Path), { recursive: true });
91
- if (spec.v2Raw !== undefined) fs.writeFileSync(v2Path, spec.v2Raw);
92
- else if (spec.v2 !== undefined) fs.writeFileSync(v2Path, JSON.stringify(spec.v2, null, 2));
93
- const cliConfig = path.join(cliDir, "config.json");
94
- if (spec.realRaw !== undefined) fs.writeFileSync(cliConfig, spec.realRaw);
95
- else if (spec.real !== undefined) fs.writeFileSync(cliConfig, JSON.stringify(spec.real, null, 2));
96
-
97
- const probePath = path.join(tmpRoot, `probe-${path.basename(home)}.cjs`);
98
- fs.writeFileSync(probePath, PROBE_SOURCE);
99
- const launcher = ensureAppServerLauncher(engineDataDir);
100
- const statePath = path.join(tmpRoot, `state-${path.basename(home)}.json`);
101
-
102
- return {
103
- run: () =>
104
- childProcess.spawnSync(process.execPath, [launcher], {
105
- env: {
106
- ...process.env,
107
- HOME: home,
108
- ZCODE_ENG_CLI_PATH: probePath,
109
- ZCODE_ENG_V2_CONFIG: v2Path,
110
- ZCODE_PROBE_STATE: statePath,
111
- } as NodeJS.ProcessEnv,
112
- encoding: "utf8",
113
- timeout: 15_000,
114
- }),
115
- state: () => JSON.parse(fs.readFileSync(statePath, "utf8")) as ProbeState,
116
- };
117
- }
118
-
119
- const providerEntry = (apiKey: string) => ({ options: { apiKey, baseURL: "https://example.test/v1" } });
120
-
121
- beforeEach(() => {
122
- tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), "zcode-launcher-test-"));
123
- });
124
-
125
- afterEach(() => {
126
- fs.rmSync(tmpRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
127
- });
128
-
129
- describe("wrapper 合并语义(v2 注入优先)", () => {
130
- it("同 id 时 v2 条目整条优先于真实文件(等价复刻 GUI 直传:v2 权威),real 独有条目保留", () => {
131
- const h = setupHome({
132
- v2: { provider: { shared: providerEntry("v2-new-key") } },
133
- real: {
134
- provider: { shared: providerEntry("real-stale-key"), realOnly: providerEntry("real-key") },
135
- model: { main: "shared/model-a" },
136
- },
137
- });
138
- const res = h.run();
139
- expect(res.status).toBe(0);
140
- const cfg = JSON.parse(h.state().syncUtf8.text as string);
141
- expect(cfg.provider.shared.options.apiKey).toBe("v2-new-key");
142
- expect(cfg.provider.realOnly.options.apiKey).toBe("real-key");
143
- expect(cfg.model.main).toBe("shared/model-a");
144
- });
145
-
146
- it("real 无 model.main 时以 v2.model.main / FALLBACK 兜底注入", () => {
147
- const h = setupHome({
148
- v2: { provider: { p1: providerEntry("k1") } },
149
- real: { provider: { p2: providerEntry("k2") } },
150
- });
151
- const res = h.run();
152
- expect(res.status).toBe(0);
153
- const cfg = JSON.parse(h.state().syncUtf8.text as string);
154
- expect(cfg.model.main).toBe("builtin:bigmodel-coding-plan/GLM-5.3");
155
- });
156
-
157
- it("v2.model.main 存在时优先于 FALLBACK", () => {
158
- const h = setupHome({
159
- v2: { provider: { p1: providerEntry("k1") }, model: { main: "p1/model-x" } },
160
- real: {},
161
- });
162
- const res = h.run();
163
- expect(res.status).toBe(0);
164
- const cfg = JSON.parse(h.state().syncUtf8.text as string);
165
- expect(cfg.model.main).toBe("p1/model-x");
166
- });
167
- });
168
-
169
- describe("existsSync 拦截(GUI-only 宿主:cli config 不存在)", () => {
170
- it("真实文件缺失时 existsSync 返回 true 且读取拿到注入配置(短路门不复 exist = 注入不可见)", () => {
171
- const h = setupHome({
172
- v2: { provider: { p1: providerEntry("k1") } },
173
- // real 不布置 → cli/config.json 不存在
174
- });
175
- const res = h.run();
176
- expect(res.status).toBe(0);
177
- const st = h.state();
178
- expect(st.existsConfig).toBe(true);
179
- const cfg = JSON.parse(st.syncUtf8.text as string);
180
- expect(cfg.provider.p1.options.apiKey).toBe("k1");
181
- });
182
- });
183
-
184
- describe("no-patch 分支(无凭据可注入 → 原生行为透出)", () => {
185
- it("v2 无带 apiKey 的 provider:不 patch,读原始内容、existsSync 原生", () => {
186
- const h = setupHome({
187
- v2: { provider: { p1: { options: { apiKey: "" } } } },
188
- realRaw: '{"provider":{"r1":{"options":{"apiKey":"real"}}}}',
189
- });
190
- const res = h.run();
191
- expect(res.status).toBe(0);
192
- const st = h.state();
193
- expect(st.syncUtf8.text).toBe('{"provider":{"r1":{"options":{"apiKey":"real"}}}}');
194
- expect(st.existsConfig).toBe(true);
195
- });
196
-
197
- it("v2 文件缺失(ENOENT,未登录):静默 no-patch,stderr 无 v2 读取失败", () => {
198
- const h = setupHome({ realRaw: '{"provider":{}}' });
199
- const res = h.run();
200
- expect(res.status).toBe(0);
201
- expect(res.stderr).not.toContain("v2 config 读取失败");
202
- const st = h.state();
203
- expect(st.syncUtf8.text).toBe('{"provider":{}}');
204
- });
205
-
206
- it("v2 损坏(非 ENOENT):no-patch 且 stderr 出声(与「未登录」区分)", () => {
207
- const h = setupHome({ v2Raw: "{broken-json", realRaw: '{"provider":{}}' });
208
- const res = h.run();
209
- expect(res.status).toBe(0);
210
- expect(res.stderr).toContain("v2 config 读取失败");
211
- expect(h.state().syncUtf8.text).toBe('{"provider":{}}');
212
- });
213
-
214
- it("no-patch 且真实文件不存在:existsSync 原生 false、读取 ENOENT(原生报错透出)", () => {
215
- const h = setupHome({ v2Raw: "{broken" });
216
- const res = h.run();
217
- expect(res.status).toBe(0);
218
- const st = h.state();
219
- expect(st.existsConfig).toBe(false);
220
- expect(st.syncUtf8.code).toBe("ENOENT");
221
- });
222
- });
223
-
224
- describe("调用形态(encoding 归一与透传)", () => {
225
- const base = { v2: { provider: { p1: providerEntry("k1") } }, real: {} };
226
-
227
- it("'utf8' / 'utf-8' / {encoding:'utf-8'} 均返回 string;无 encoding 返回 Buffer(内容一致)", () => {
228
- const h = setupHome(base);
229
- const res = h.run();
230
- expect(res.status).toBe(0);
231
- const st = h.state();
232
- for (const key of ["syncUtf8", "syncUtf8Dash", "syncUtf8Obj", "promiseUtf8Dash"] as const) {
233
- expect(st[key].kind, key).toBe("string");
234
- }
235
- expect(st.syncNoEnc.kind).toBe("buffer");
236
- const merged = JSON.parse(st.syncUtf8.text as string);
237
- expect(JSON.parse(st.syncNoEnc.text as string)).toEqual(merged);
238
- });
239
-
240
- it("非 CONFIG_PATH 读取与 existsSync 穿透不受影响", () => {
241
- const h = setupHome(base);
242
- const res = h.run();
243
- expect(res.status).toBe(0);
244
- const st = h.state();
245
- expect(st.syncOther.text).toBe("OTHER-CONTENT");
246
- expect(st.existsOther).toBe(true);
247
- expect(st.existsMissing).toBe(false);
248
- });
249
- });
250
-
251
- describe("exit 面", () => {
252
- it("ZCODE_ENG_CLI_PATH 缺失:exit 2 + stderr 含恢复指引", () => {
253
- const home = fs.mkdtempSync(path.join(tmpRoot, "home-"));
254
- const engineDataDir = fs.mkdtempSync(path.join(tmpRoot, "eng-"));
255
- const launcher = ensureAppServerLauncher(engineDataDir);
256
- // 密封性:本测试自身可能跑在 app-server 宿主链路下(env 带 ZCODE_ENG_CLI_PATH),
257
- // 不剥掉则「缺失」前置不成立,launcher 会拿到真 CLI 走正常启动路径(exit 1)而非配置错误 exit 2
258
- const { ZCODE_ENG_CLI_PATH: _ambient, ...hermeticEnv } = process.env;
259
- const res = childProcess.spawnSync(process.execPath, [launcher], {
260
- env: { ...hermeticEnv, HOME: home, ZCODE_ENG_V2_CONFIG: path.join(home, "v2.json") },
261
- encoding: "utf8",
262
- timeout: 15_000,
263
- });
264
- expect(res.status).toBe(2);
265
- expect(res.stderr).toContain("ZCODE_ENG_CLI_PATH");
266
- });
267
-
268
- it("CLI_PATH 指向不存在文件:exit 3 + stderr 加载失败", () => {
269
- const home = fs.mkdtempSync(path.join(tmpRoot, "home-"));
270
- const engineDataDir = fs.mkdtempSync(path.join(tmpRoot, "eng-"));
271
- const launcher = ensureAppServerLauncher(engineDataDir);
272
- const res = childProcess.spawnSync(process.execPath, [launcher], {
273
- env: {
274
- ...process.env,
275
- HOME: home,
276
- ZCODE_ENG_CLI_PATH: path.join(tmpRoot, "no-such-cli.cjs"),
277
- ZCODE_ENG_V2_CONFIG: path.join(home, "v2.json"),
278
- },
279
- encoding: "utf8",
280
- timeout: 15_000,
281
- });
282
- expect(res.status).toBe(3);
283
- expect(res.stderr).toContain("加载失败");
284
- });
285
- });
286
-
287
- describe("落盘端(ensureAppServerLauncher)", () => {
288
- it("首调落盘产物内容与 APPSERVER_LAUNCHER_SOURCE 一致,路径含 engines/zcode/", () => {
289
- const engineDataDir = fs.mkdtempSync(path.join(tmpRoot, "eng-"));
290
- const file = ensureAppServerLauncher(engineDataDir);
291
- expect(path.basename(file)).toBe(ZCODE_APPSERVER_LAUNCHER_NAME);
292
- expect(file).toContain(path.join("engines", "zcode"));
293
- expect(fs.readFileSync(file, "utf8")).toBe(APPSERVER_LAUNCHER_SOURCE);
294
- });
295
-
296
- it("重复调用幂等:返回同一路径,内容不变", () => {
297
- const engineDataDir = fs.mkdtempSync(path.join(tmpRoot, "eng-"));
298
- const a = ensureAppServerLauncher(engineDataDir);
299
- const b = ensureAppServerLauncher(engineDataDir);
300
- expect(b).toBe(a);
301
- expect(fs.readFileSync(b, "utf8")).toBe(APPSERVER_LAUNCHER_SOURCE);
302
- });
303
-
304
- it("陈旧内容(升级后旧 wrapper)被覆盖刷新", () => {
305
- const engineDataDir = fs.mkdtempSync(path.join(tmpRoot, "eng-"));
306
- const dir = path.join(engineDataDir, "engines", "zcode");
307
- fs.mkdirSync(dir, { recursive: true });
308
- fs.writeFileSync(path.join(dir, ZCODE_APPSERVER_LAUNCHER_NAME), "// stale old wrapper");
309
- const file = ensureAppServerLauncher(engineDataDir);
310
- expect(fs.readFileSync(file, "utf8")).toBe(APPSERVER_LAUNCHER_SOURCE);
311
- });
312
-
313
- it("落盘失败包装为含恢复动作的错误(目录只读)", () => {
314
- const engineDataDir = fs.mkdtempSync(path.join(tmpRoot, "eng-"));
315
- // 预置同名目录占位目标文件路径,使 renameSync 前的 writeFileSync 落在
316
- // 目录形态上失败(EISDIR)——覆盖 recovery 文案分支
317
- const dir = path.join(engineDataDir, "engines", "zcode");
318
- fs.mkdirSync(path.join(dir, ZCODE_APPSERVER_LAUNCHER_NAME), { recursive: true });
319
- expect(() => ensureAppServerLauncher(engineDataDir)).toThrow(/落盘失败[\s\S]*恢复/);
320
- });
321
- });