shennian 0.5.0 → 0.5.2

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 (342) hide show
  1. package/README.md +2 -2
  2. package/dist/publish-build-manifest.json +165 -125
  3. package/dist/src/agents/acp/adapter.js +2 -2
  4. package/dist/src/agents/acp/capability-cache.js +2 -2
  5. package/dist/src/agents/acp/catalog.js +2 -2
  6. package/dist/src/agents/acp/manifests.js +2 -2
  7. package/dist/src/agents/claude.js +8 -6
  8. package/dist/src/agents/codex.js +2 -2
  9. package/dist/src/agents/command-spec.js +4 -4
  10. package/dist/src/agents/cursor.js +1 -1
  11. package/dist/src/agents/custom-recovery-conformance.js +2 -2
  12. package/dist/src/agents/gemini.js +1 -1
  13. package/dist/src/agents/model-registry/discovery.js +3 -3
  14. package/dist/src/agents/model-registry/service.js +1 -1
  15. package/dist/src/agents/model-registry.js +1 -1
  16. package/dist/src/agents/openclaw.js +2 -2
  17. package/dist/src/agents/opencode.js +1 -1
  18. package/dist/src/agents/pi-coding-agent.js +3 -4
  19. package/dist/src/agents/pi-session-ownership.js +2 -2
  20. package/dist/src/agents/spawn-errors.js +1 -0
  21. package/dist/src/agents/windows-agent-paths.js +1 -0
  22. package/dist/src/commands/agent-readiness.js +2 -2
  23. package/dist/src/commands/daemon-service-spec.js +1 -1
  24. package/dist/src/commands/daemon.js +6 -6
  25. package/dist/src/commands/queue.js +1 -0
  26. package/dist/src/commands/room.js +3 -3
  27. package/dist/src/config/index.js +2 -2
  28. package/dist/src/fs/atomic-rename.js +1 -0
  29. package/dist/src/index.js +3 -3
  30. package/dist/src/native-fusion/claude-entry-parser.js +7 -0
  31. package/dist/src/native-fusion/local-repository.js +2 -2
  32. package/dist/src/native-fusion/native-source-deletions.js +2 -2
  33. package/dist/src/native-fusion/parsers.js +1 -3
  34. package/dist/src/native-fusion/state.js +2 -2
  35. package/dist/src/personal-sync/epoch.js +2 -2
  36. package/dist/src/personal-sync/identity.js +2 -2
  37. package/dist/src/relay/client.js +1 -1
  38. package/dist/src/room/activation-service.js +6 -6
  39. package/dist/src/room/attachment-cache.js +2 -2
  40. package/dist/src/room/host-session-observations.js +2 -2
  41. package/dist/src/room/managed-context.js +1 -1
  42. package/dist/src/room/managed-room-ipc.js +2 -2
  43. package/dist/src/room/mirror-sync-service.js +1 -1
  44. package/dist/src/room/public-attachment-cache.js +2 -2
  45. package/dist/src/room/room-error-guidance.js +1 -0
  46. package/dist/src/room/session-registry.js +2 -2
  47. package/dist/src/security/managed-agent-policy.js +1 -1
  48. package/dist/src/security/managed-agent-runtime.js +1 -1
  49. package/dist/src/session/attachment-transfer-store.js +2 -2
  50. package/dist/src/session/canonical-store.js +5 -5
  51. package/dist/src/session/deletion-sync-state.js +2 -2
  52. package/dist/src/session/handlers/agent-workspace-validation.js +1 -1
  53. package/dist/src/session/handlers/chat-adapter-config.js +1 -1
  54. package/dist/src/session/handlers/chat-events.js +2 -2
  55. package/dist/src/session/handlers/chat-recovery.js +1 -1
  56. package/dist/src/session/handlers/chat.js +1 -1
  57. package/dist/src/session/manager.js +1 -1
  58. package/dist/src/session/native-cleanup-outbox.js +2 -2
  59. package/dist/src/session/queue-diagnostics.js +1 -0
  60. package/dist/src/session/queue-dispatch-failure.js +1 -0
  61. package/dist/src/session/queue-helpers.js +5 -5
  62. package/dist/src/session/queue-retry.js +1 -1
  63. package/dist/src/session/queue-storage.js +2 -2
  64. package/dist/src/session/queue.js +1 -1
  65. package/dist/src/session/room-reply-notice.js +1 -0
  66. package/dist/src/session/run-recovery/journal.js +2 -2
  67. package/dist/src/session/run-stall.js +1 -0
  68. package/dist/src/session/store.js +2 -2
  69. package/dist/src/session/tool-detail-store.js +2 -2
  70. package/node_modules/@shennian/wire/dist/agent-capabilities.js +1 -1
  71. package/node_modules/@shennian/wire/dist/agent-workspace.js +1 -144
  72. package/node_modules/@shennian/wire/dist/envelope.js +1 -1
  73. package/node_modules/@shennian/wire/dist/events.js +1 -1
  74. package/node_modules/@shennian/wire/dist/external-message-format.js +3 -70
  75. package/node_modules/@shennian/wire/dist/frames.js +1 -1
  76. package/node_modules/@shennian/wire/dist/fs.js +2 -7
  77. package/node_modules/@shennian/wire/dist/index.js +1 -21
  78. package/node_modules/@shennian/wire/dist/machine.js +1 -1
  79. package/node_modules/@shennian/wire/dist/message-payload.js +8 -307
  80. package/node_modules/@shennian/wire/dist/methods.js +1 -3
  81. package/node_modules/@shennian/wire/dist/native-session.js +1 -1
  82. package/node_modules/@shennian/wire/dist/project-fs.js +1 -462
  83. package/node_modules/@shennian/wire/dist/project-path.js +1 -25
  84. package/node_modules/@shennian/wire/dist/project.js +1 -3
  85. package/node_modules/@shennian/wire/dist/relay-connectivity.js +1 -29
  86. package/node_modules/@shennian/wire/dist/room.js +1 -20
  87. package/node_modules/@shennian/wire/dist/schedule.js +1 -1
  88. package/node_modules/@shennian/wire/dist/session-sync.js +1 -123
  89. package/node_modules/@shennian/wire/dist/session.js +1 -60
  90. package/node_modules/@shennian/wire/dist/tool-detail.js +1 -9
  91. package/node_modules/@shennian/wire/dist/voice-chief.js +1 -3
  92. package/package.json +3 -8
  93. package/dist/bin/shennian.d.ts +0 -2
  94. package/dist/src/agent-env.d.ts +0 -44
  95. package/dist/src/agents/acp/adapter.d.ts +0 -82
  96. package/dist/src/agents/acp/auth-state.d.ts +0 -3
  97. package/dist/src/agents/acp/auth.d.ts +0 -7
  98. package/dist/src/agents/acp/capability-cache.d.ts +0 -14
  99. package/dist/src/agents/acp/catalog.d.ts +0 -11
  100. package/dist/src/agents/acp/client-services.d.ts +0 -37
  101. package/dist/src/agents/acp/discovery.d.ts +0 -10
  102. package/dist/src/agents/acp/events.d.ts +0 -4
  103. package/dist/src/agents/acp/manifests.d.ts +0 -63
  104. package/dist/src/agents/acp/metrics.d.ts +0 -24
  105. package/dist/src/agents/acp/package-commands.d.ts +0 -4
  106. package/dist/src/agents/acp/process-client.d.ts +0 -41
  107. package/dist/src/agents/acp/process-tree.d.ts +0 -2
  108. package/dist/src/agents/acp/types.d.ts +0 -31
  109. package/dist/src/agents/acp/watcher.d.ts +0 -22
  110. package/dist/src/agents/adapter.d.ts +0 -180
  111. package/dist/src/agents/auth-status.d.ts +0 -4
  112. package/dist/src/agents/claude-managed-permissions.d.ts +0 -33
  113. package/dist/src/agents/claude.d.ts +0 -69
  114. package/dist/src/agents/codex-managed-permissions.d.ts +0 -32
  115. package/dist/src/agents/codex-managed-room-tools.d.ts +0 -41
  116. package/dist/src/agents/codex-protocol.d.ts +0 -103
  117. package/dist/src/agents/codex-runtime.d.ts +0 -91
  118. package/dist/src/agents/codex-utils.d.ts +0 -29
  119. package/dist/src/agents/codex.d.ts +0 -59
  120. package/dist/src/agents/command-spec.d.ts +0 -55
  121. package/dist/src/agents/config-status.d.ts +0 -18
  122. package/dist/src/agents/cursor-managed-permissions.d.ts +0 -28
  123. package/dist/src/agents/cursor.d.ts +0 -44
  124. package/dist/src/agents/custom-managed-runtime.d.ts +0 -37
  125. package/dist/src/agents/custom-recovery-conformance.d.ts +0 -2
  126. package/dist/src/agents/custom.d.ts +0 -62
  127. package/dist/src/agents/detect.d.ts +0 -23
  128. package/dist/src/agents/event-terminal-gate.d.ts +0 -16
  129. package/dist/src/agents/external-channel-instructions.d.ts +0 -4
  130. package/dist/src/agents/gemini.d.ts +0 -32
  131. package/dist/src/agents/manager.d.ts +0 -57
  132. package/dist/src/agents/model-registry/cache.d.ts +0 -4
  133. package/dist/src/agents/model-registry/discovery.d.ts +0 -4
  134. package/dist/src/agents/model-registry/opencode-api.d.ts +0 -2
  135. package/dist/src/agents/model-registry/parsers.d.ts +0 -20
  136. package/dist/src/agents/model-registry/runner.d.ts +0 -6
  137. package/dist/src/agents/model-registry/service.d.ts +0 -10
  138. package/dist/src/agents/model-registry/types.d.ts +0 -39
  139. package/dist/src/agents/model-registry.d.ts +0 -17
  140. package/dist/src/agents/native-capabilities.d.ts +0 -10
  141. package/dist/src/agents/openclaw.d.ts +0 -29
  142. package/dist/src/agents/opencode-managed-permissions.d.ts +0 -25
  143. package/dist/src/agents/opencode.d.ts +0 -46
  144. package/dist/src/agents/pi-coding-agent-managed-permissions.d.ts +0 -7
  145. package/dist/src/agents/pi-coding-agent.d.ts +0 -63
  146. package/dist/src/agents/pi-managed-extension.d.ts +0 -12
  147. package/dist/src/agents/pi-managed-model-broker.d.ts +0 -27
  148. package/dist/src/agents/pi-managed-model-broker.js +0 -1
  149. package/dist/src/agents/pi-rpc-client.d.ts +0 -31
  150. package/dist/src/agents/pi-session-ownership.d.ts +0 -2
  151. package/dist/src/agents/platform-instructions.d.ts +0 -5
  152. package/dist/src/agents/runtime-compatibility.d.ts +0 -11
  153. package/dist/src/agents/workbuddy-managed-permissions.d.ts +0 -37
  154. package/dist/src/agents/workbuddy.d.ts +0 -63
  155. package/dist/src/commands/agent-readiness.d.ts +0 -17
  156. package/dist/src/commands/agent.d.ts +0 -2
  157. package/dist/src/commands/daemon-instance-lock.d.ts +0 -21
  158. package/dist/src/commands/daemon-process.d.ts +0 -6
  159. package/dist/src/commands/daemon-service-spec.d.ts +0 -26
  160. package/dist/src/commands/daemon-start-wait.d.ts +0 -9
  161. package/dist/src/commands/daemon-state.d.ts +0 -57
  162. package/dist/src/commands/daemon-windows.d.ts +0 -33
  163. package/dist/src/commands/daemon.d.ts +0 -67
  164. package/dist/src/commands/integration.d.ts +0 -3
  165. package/dist/src/commands/logout.d.ts +0 -3
  166. package/dist/src/commands/manager.d.ts +0 -2
  167. package/dist/src/commands/pair-authorization.d.ts +0 -3
  168. package/dist/src/commands/pair-browser.d.ts +0 -44
  169. package/dist/src/commands/pair-qr.d.ts +0 -4
  170. package/dist/src/commands/pair.d.ts +0 -19
  171. package/dist/src/commands/room.d.ts +0 -16
  172. package/dist/src/commands/runtime.d.ts +0 -2
  173. package/dist/src/commands/schedule.d.ts +0 -2
  174. package/dist/src/commands/tools.d.ts +0 -2
  175. package/dist/src/commands/upgrade.d.ts +0 -31
  176. package/dist/src/commands/worker.d.ts +0 -11
  177. package/dist/src/config/index.d.ts +0 -58
  178. package/dist/src/daemon-ipc/agent-readiness.d.ts +0 -15
  179. package/dist/src/daemon-ipc/client.d.ts +0 -8
  180. package/dist/src/daemon-ipc/control.d.ts +0 -16
  181. package/dist/src/daemon-ipc/json.d.ts +0 -3
  182. package/dist/src/daemon-ipc/paths.d.ts +0 -15
  183. package/dist/src/daemon-ipc/protocol.d.ts +0 -31
  184. package/dist/src/daemon-ipc/secret.d.ts +0 -3
  185. package/dist/src/daemon-ipc/server.d.ts +0 -20
  186. package/dist/src/daemon-log.d.ts +0 -9
  187. package/dist/src/env-path.d.ts +0 -15
  188. package/dist/src/fs/boundary.d.ts +0 -23
  189. package/dist/src/fs/handler.d.ts +0 -26
  190. package/dist/src/fs/security.d.ts +0 -2
  191. package/dist/src/fs/text-decoder.d.ts +0 -10
  192. package/dist/src/index.d.ts +0 -1
  193. package/dist/src/log-redaction.d.ts +0 -4
  194. package/dist/src/log-reporter.d.ts +0 -41
  195. package/dist/src/manager/prompt.d.ts +0 -2
  196. package/dist/src/manager/registry.d.ts +0 -184
  197. package/dist/src/manager/retired-external-channel-compat.d.ts +0 -78
  198. package/dist/src/manager/runtime.d.ts +0 -90
  199. package/dist/src/manager/worker-ipc.d.ts +0 -28
  200. package/dist/src/manager/worker-markdown.d.ts +0 -10
  201. package/dist/src/native-fusion/codex-files.d.ts +0 -10
  202. package/dist/src/native-fusion/codex-message-parser.d.ts +0 -9
  203. package/dist/src/native-fusion/codex-parser.d.ts +0 -8
  204. package/dist/src/native-fusion/codex-user-input.d.ts +0 -11
  205. package/dist/src/native-fusion/config.d.ts +0 -1
  206. package/dist/src/native-fusion/file-identity.d.ts +0 -9
  207. package/dist/src/native-fusion/file-watcher.d.ts +0 -26
  208. package/dist/src/native-fusion/local-repository.d.ts +0 -90
  209. package/dist/src/native-fusion/native-source-deletions.d.ts +0 -47
  210. package/dist/src/native-fusion/opencode-parser.d.ts +0 -29
  211. package/dist/src/native-fusion/parser-common.d.ts +0 -35
  212. package/dist/src/native-fusion/parsers.d.ts +0 -13
  213. package/dist/src/native-fusion/service.d.ts +0 -64
  214. package/dist/src/native-fusion/session-header.d.ts +0 -13
  215. package/dist/src/native-fusion/session-native-sources.d.ts +0 -24
  216. package/dist/src/native-fusion/source-visibility-audit.d.ts +0 -16
  217. package/dist/src/native-fusion/source-visibility.d.ts +0 -25
  218. package/dist/src/native-fusion/state.d.ts +0 -4
  219. package/dist/src/native-fusion/types.d.ts +0 -82
  220. package/dist/src/personal-sync/epoch.d.ts +0 -17
  221. package/dist/src/personal-sync/identity.d.ts +0 -1
  222. package/dist/src/personal-sync/machine-authority.d.ts +0 -12
  223. package/dist/src/personal-sync/metrics.d.ts +0 -25
  224. package/dist/src/personal-sync/paths.d.ts +0 -5
  225. package/dist/src/region.d.ts +0 -15
  226. package/dist/src/relay/client.d.ts +0 -81
  227. package/dist/src/room/activation-audit.d.ts +0 -15
  228. package/dist/src/room/activation-policy.d.ts +0 -8
  229. package/dist/src/room/activation-service.d.ts +0 -77
  230. package/dist/src/room/attachment-cache.d.ts +0 -44
  231. package/dist/src/room/attachment-upload.d.ts +0 -20
  232. package/dist/src/room/device-authorization-client.d.ts +0 -91
  233. package/dist/src/room/host-session-observations.d.ts +0 -54
  234. package/dist/src/room/invite-bootstrap.d.ts +0 -49
  235. package/dist/src/room/invite-qr.d.ts +0 -6
  236. package/dist/src/room/live-delivery.d.ts +0 -5
  237. package/dist/src/room/managed-context.d.ts +0 -49
  238. package/dist/src/room/managed-prompt-composer.d.ts +0 -47
  239. package/dist/src/room/managed-room-binding.d.ts +0 -69
  240. package/dist/src/room/managed-room-ipc.d.ts +0 -65
  241. package/dist/src/room/mirror-sync-service.d.ts +0 -49
  242. package/dist/src/room/public-attachment-cache.d.ts +0 -34
  243. package/dist/src/room/public-room-client.d.ts +0 -37
  244. package/dist/src/room/registration-authority.d.ts +0 -4
  245. package/dist/src/room/room-action-client-types.d.ts +0 -137
  246. package/dist/src/room/room-action-client.d.ts +0 -116
  247. package/dist/src/room/room-binding-client.d.ts +0 -62
  248. package/dist/src/room/session-registry.d.ts +0 -158
  249. package/dist/src/runtime-distribution.d.ts +0 -7
  250. package/dist/src/schedules/personal-context.d.ts +0 -2
  251. package/dist/src/schedules/server-client.d.ts +0 -19
  252. package/dist/src/security/managed-agent-credential-paths.d.ts +0 -6
  253. package/dist/src/security/managed-agent-executable.d.ts +0 -19
  254. package/dist/src/security/managed-agent-policy.d.ts +0 -66
  255. package/dist/src/security/managed-agent-runtime.d.ts +0 -44
  256. package/dist/src/session/archive-zip.d.ts +0 -10
  257. package/dist/src/session/attachment-reference.d.ts +0 -2
  258. package/dist/src/session/attachment-transfer-store.d.ts +0 -45
  259. package/dist/src/session/canonical-store.d.ts +0 -104
  260. package/dist/src/session/deletion-sync-state.d.ts +0 -20
  261. package/dist/src/session/deletion-sync-validation.d.ts +0 -2
  262. package/dist/src/session/deletion-synchronizer.d.ts +0 -9
  263. package/dist/src/session/handlers/agent-capabilities.d.ts +0 -3
  264. package/dist/src/session/handlers/agent-config.d.ts +0 -7
  265. package/dist/src/session/handlers/agent-control.d.ts +0 -4
  266. package/dist/src/session/handlers/agent-workspace-validation.d.ts +0 -28
  267. package/dist/src/session/handlers/agents.d.ts +0 -11
  268. package/dist/src/session/handlers/chat-adapter-config.d.ts +0 -11
  269. package/dist/src/session/handlers/chat-context.d.ts +0 -31
  270. package/dist/src/session/handlers/chat-events.d.ts +0 -5
  271. package/dist/src/session/handlers/chat-recovery.d.ts +0 -4
  272. package/dist/src/session/handlers/chat-session-lifecycle.d.ts +0 -9
  273. package/dist/src/session/handlers/chat.d.ts +0 -6
  274. package/dist/src/session/handlers/control.d.ts +0 -5
  275. package/dist/src/session/handlers/fs.d.ts +0 -14
  276. package/dist/src/session/handlers/message-status.d.ts +0 -3
  277. package/dist/src/session/handlers/pi-validation-session.d.ts +0 -7
  278. package/dist/src/session/handlers/pi-validation-session.js +0 -1
  279. package/dist/src/session/handlers/project-fs.d.ts +0 -11
  280. package/dist/src/session/handlers/remote-access.d.ts +0 -4
  281. package/dist/src/session/handlers/room-managed.d.ts +0 -6
  282. package/dist/src/session/handlers/session-refresh.d.ts +0 -3
  283. package/dist/src/session/handlers/title.d.ts +0 -3
  284. package/dist/src/session/handlers/tool-detail.d.ts +0 -3
  285. package/dist/src/session/handlers/voice-window.d.ts +0 -3
  286. package/dist/src/session/history-subscriptions.d.ts +0 -29
  287. package/dist/src/session/index-publisher.d.ts +0 -3
  288. package/dist/src/session/manager-event-authority.d.ts +0 -3
  289. package/dist/src/session/manager.d.ts +0 -95
  290. package/dist/src/session/native-cleanup-outbox.d.ts +0 -64
  291. package/dist/src/session/native-session-lifecycle.d.ts +0 -56
  292. package/dist/src/session/project-fs-store.d.ts +0 -43
  293. package/dist/src/session/projection.d.ts +0 -3
  294. package/dist/src/session/queue-control.d.ts +0 -27
  295. package/dist/src/session/queue-helpers.d.ts +0 -20
  296. package/dist/src/session/queue-message.d.ts +0 -35
  297. package/dist/src/session/queue-retry.d.ts +0 -11
  298. package/dist/src/session/queue-storage.d.ts +0 -8
  299. package/dist/src/session/queue-types.d.ts +0 -31
  300. package/dist/src/session/queue.d.ts +0 -73
  301. package/dist/src/session/queued-chat-dispatch.d.ts +0 -12
  302. package/dist/src/session/run-recovery/barrier.d.ts +0 -12
  303. package/dist/src/session/run-recovery/coordinator.d.ts +0 -32
  304. package/dist/src/session/run-recovery/journal.d.ts +0 -30
  305. package/dist/src/session/run-recovery/schema.d.ts +0 -48
  306. package/dist/src/session/store.d.ts +0 -128
  307. package/dist/src/session/tool-detail-store.d.ts +0 -17
  308. package/dist/src/session/turn-trigger.d.ts +0 -43
  309. package/dist/src/session/types.d.ts +0 -93
  310. package/dist/src/tools/markdown-to-pdf.d.ts +0 -42
  311. package/dist/src/upgrade/channel.d.ts +0 -5
  312. package/dist/src/upgrade/distribution.d.ts +0 -21
  313. package/dist/src/upgrade/engine.d.ts +0 -104
  314. package/dist/src/upgrade/scheduler.d.ts +0 -60
  315. package/dist/src/upgrade/updater-bootstrap.d.ts +0 -12
  316. package/dist/src/upgrade/updater-launcher.d.ts +0 -37
  317. package/dist/src/upgrade/updater-protocol.d.ts +0 -40
  318. package/dist/src/upgrade/updater-service-entry.d.ts +0 -7
  319. package/dist/src/upgrade/updater-worker.d.ts +0 -57
  320. package/dist/src/windows-shell.d.ts +0 -6
  321. package/node_modules/@shennian/wire/dist/agent-capabilities.d.ts +0 -16
  322. package/node_modules/@shennian/wire/dist/agent-workspace.d.ts +0 -133
  323. package/node_modules/@shennian/wire/dist/envelope.d.ts +0 -7
  324. package/node_modules/@shennian/wire/dist/events.d.ts +0 -125
  325. package/node_modules/@shennian/wire/dist/external-message-format.d.ts +0 -37
  326. package/node_modules/@shennian/wire/dist/frames.d.ts +0 -33
  327. package/node_modules/@shennian/wire/dist/fs.d.ts +0 -107
  328. package/node_modules/@shennian/wire/dist/index.d.ts +0 -21
  329. package/node_modules/@shennian/wire/dist/machine.d.ts +0 -160
  330. package/node_modules/@shennian/wire/dist/message-payload.d.ts +0 -71
  331. package/node_modules/@shennian/wire/dist/methods.d.ts +0 -5
  332. package/node_modules/@shennian/wire/dist/native-session.d.ts +0 -20
  333. package/node_modules/@shennian/wire/dist/project-fs.d.ts +0 -146
  334. package/node_modules/@shennian/wire/dist/project-path.d.ts +0 -4
  335. package/node_modules/@shennian/wire/dist/project.d.ts +0 -16
  336. package/node_modules/@shennian/wire/dist/relay-connectivity.d.ts +0 -30
  337. package/node_modules/@shennian/wire/dist/room.d.ts +0 -190
  338. package/node_modules/@shennian/wire/dist/schedule.d.ts +0 -37
  339. package/node_modules/@shennian/wire/dist/session-sync.d.ts +0 -406
  340. package/node_modules/@shennian/wire/dist/session.d.ts +0 -465
  341. package/node_modules/@shennian/wire/dist/tool-detail.d.ts +0 -38
  342. package/node_modules/@shennian/wire/dist/voice-chief.d.ts +0 -116
@@ -1,3 +1,3 @@
1
- import{randomUUID as p}from"node:crypto";import{createHash as m}from"node:crypto";import{realpathSync as g}from"node:fs";import{pathToFileURL as I}from"node:url";import*as l from"@agentclientprotocol/sdk";import{RequestError as w}from"@agentclientprotocol/sdk";import{AgentAdapter as C,registerAgent as v}from"../adapter.js";import{mapAcpSessionUpdate as A}from"./events.js";import{AcpProcessClient as P}from"./process-client.js";import{acpAgentType as f}from"./types.js";import{runAcpTerminalAuthentication as q}from"./auth.js";import{setAcpRuntimeAuthState as d}from"./auth-state.js";import{recordAcpAuthFailure as E,recordAcpImportResult as y}from"./metrics.js";import{isManagedAgentNativeFull as S}from"../../security/managed-agent-policy.js";import{buildManagedNativeFullProcessEnv as b}from"../../agent-env.js";class x extends C{manifest;options;type;get recoveryCapabilities(){const e=this.client?.capabilities;return{inspectTerminal:!1,reattachRun:!1,resumeRun:!1,resumeSession:!!(e?.sessionCapabilities?.resume||e?.loadSession)}}client=null;workDir="";shennianSessionId="";requestedSessionId=null;agentSessionId=null;runId="";seq=0;active=!1;extraEnv={};pendingPermissions=new Map;configOptions=[];modes=null;importCapture=null;emittedToolStates=new Map;pendingAuthRetry=null;retryingAfterAuth=!1;managedAgentPolicy=null;configurationSignature="";startedConfigurationSignature="";constructor(e,t={}){super(),this.manifest=e,this.options=t,this.type=f(e.id)}configure(e){this.extraEnv=e.env??{},this.managedAgentPolicy=e.managedAgentPolicy??null,this.configurationSignature=m("sha256").update(JSON.stringify({env:Object.entries(this.extraEnv).sort(([t],[s])=>t.localeCompare(s)),managedAgentPolicy:this.managedAgentPolicy})).digest("hex")}async start(e,t,s){this.shennianSessionId=e;try{this.workDir=g.native(t)}catch{this.workDir=t}this.requestedSessionId=s??null,this.agentSessionId=null,this.client=this.createProcessClient(),await this.client.start(this.workDir),this.startedConfigurationSignature=this.configurationSignature}async send(e,t,s,i,n){await this.refreshProcessConfiguration();const o=this.requireClient();this.runId=p(),this.seq=0,this.emittedToolStates.clear();try{await this.ensureSession(),await this.applyDynamicConfig(t,s),this.active=!0,this.emitEvent({state:"start",runPhase:"thinking",agentSessionId:this.agentSessionId??void 0});const r=[],a=[];n?.trim()&&a.push(n.trim()),a.push(e),r.push({type:"text",text:a.join(`
1
+ import{randomUUID as g}from"node:crypto";import{createHash as f}from"node:crypto";import{realpathSync as y}from"node:fs";import{pathToFileURL as v}from"node:url";import*as l from"@agentclientprotocol/sdk";import{RequestError as C}from"@agentclientprotocol/sdk";import{AgentAdapter as A,registerAgent as P}from"../adapter.js";import{mapAcpSessionUpdate as q}from"./events.js";import{AcpProcessClient as E}from"./process-client.js";import{acpAgentType as S}from"./types.js";import{runAcpTerminalAuthentication as b}from"./auth.js";import{setAcpRuntimeAuthState as d}from"./auth-state.js";import{recordAcpAuthFailure as x,recordAcpImportResult as I}from"./metrics.js";import{isManagedAgentNativeFull as w}from"../../security/managed-agent-policy.js";import{buildManagedNativeFullProcessEnv as O}from"../../agent-env.js";function p(c,e){return c.find(t=>t.category===e&&t.type==="select")}function m(c){return(c?.options??[]).flatMap(e=>"options"in e?e.options:[e])}class T extends A{manifest;options;type;get recoveryCapabilities(){const e=this.client?.capabilities;return{inspectTerminal:!1,reattachRun:!1,resumeRun:!1,resumeSession:!!(e?.sessionCapabilities?.resume||e?.loadSession)}}client=null;workDir="";shennianSessionId="";requestedSessionId=null;agentSessionId=null;runId="";seq=0;active=!1;extraEnv={};pendingPermissions=new Map;configOptions=[];modes=null;importCapture=null;emittedToolStates=new Map;pendingAuthRetry=null;retryingAfterAuth=!1;managedAgentPolicy=null;configurationSignature="";startedConfigurationSignature="";constructor(e,t={}){super(),this.manifest=e,this.options=t,this.type=S(e.id)}configure(e){this.extraEnv=e.env??{},this.managedAgentPolicy=e.managedAgentPolicy??null,this.configurationSignature=f("sha256").update(JSON.stringify({env:Object.entries(this.extraEnv).sort(([t],[n])=>t.localeCompare(n)),managedAgentPolicy:this.managedAgentPolicy})).digest("hex")}async start(e,t,n){this.shennianSessionId=e;try{this.workDir=y.native(t)}catch{this.workDir=t}this.requestedSessionId=n??null,this.agentSessionId=null,this.client=this.createProcessClient(),await this.client.start(this.workDir),this.startedConfigurationSignature=this.configurationSignature}async send(e,t,n,i,s){await this.refreshProcessConfiguration();const a=this.requireClient();this.runId=g(),this.seq=0,this.emittedToolStates.clear();try{await this.ensureSession(),await this.applyDynamicConfig(t,n),this.active=!0,this.emitEvent({state:"start",runPhase:"thinking",agentSessionId:this.agentSessionId??void 0});const o=[],r=[];s?.trim()&&r.push(s.trim()),r.push(e),o.push({type:"text",text:r.join(`
2
2
 
3
- `)});for(const h of i??[])r.push({type:"resource_link",uri:I(h.path).href,name:h.name,mimeType:h.mimeType,size:h.byteSize});const c=await this.promptWithTimeout(o,r);this.active=!1,c.stopReason==="cancelled"?this.emitEvent({state:"aborted",agentSessionId:this.agentSessionId??void 0}):this.emitEvent({state:"final",agentSessionId:this.agentSessionId??void 0})}catch(r){this.active=!1,this.cancelPendingPermissions();const a=r instanceof Error?r.message:String(r),c=r instanceof w&&r.code===-32e3;throw c&&(d(this.type,"required"),this.retryingAfterAuth||(this.pendingAuthRetry={text:e,...t?{modelId:t}:{},...s?{reasoningEffort:s}:{},...i?{attachments:[...i]}:{},...n!==void 0?{systemPrompt:n}:{}})),this.emitEvent({state:"error",message:a,...c?{errorCode:"acp_auth_required"}:{},agentSessionId:this.agentSessionId??void 0}),r}}async resume(e){this.requestedSessionId=e,this.agentSessionId=null,await this.ensureSession()}async stop(){this.active&&this.agentSessionId&&this.client&&await this.client.agent.notify(l.methods.agent.session.cancel,{sessionId:this.agentSessionId}),this.cancelPendingPermissions(),this.active=!1,await this.client?.close(),this.client=null,this.startedConfigurationSignature=""}async getStatus(){return{active:this.active,runId:this.active?this.runId:null,canStop:this.active}}async respondToPermission(e,t){const s=this.pendingPermissions.get(e);if(!s)throw new Error("ACP permission request is no longer pending");if(!s.optionIds.has(t))throw new Error("Invalid ACP permission option");this.pendingPermissions.delete(e),clearTimeout(s.timer),s.resolve({outcome:{outcome:"selected",optionId:t}})}getAuthMethods(){return[...this.requireClient().initializeResponse?.authMethods??[]]}hasPendingAuthenticationRetry(){return this.pendingAuthRetry!==null}getSessionOptions(){const e=this.configOptions.find(o=>o.category==="model"&&o.type==="select"),t=this.configOptions.find(o=>o.category==="thought_level"&&o.type==="select"),s=this.modes?.availableModes.map(o=>({id:o.id,name:o.name,...o.description?{description:o.description}:{}}))??[],i=o=>(o?.options??[]).flatMap(r=>"options"in r?r.options:[r]),n=(t?i(t):s).map(o=>({id:"value"in o?o.value:o.id,name:o.name,...o.description?{description:o.description}:{}}));return{models:i(e).map(o=>({id:o.value,name:o.name,...o.description?{description:o.description}:{},...o.value===e?.currentValue?{isDefault:!0}:{},...n.length?{supportedReasoningEfforts:n}:{}})),modes:s}}async authenticate(e,t={}){const s=this.requireClient(),i=s.initializeResponse?.authMethods?.find(n=>n.id===e);if(!i)throw new Error("ACP authentication method is unavailable");try{if("type"in i&&i.type==="terminal"){if(!t.interactiveTerminal)throw new Error("ACP terminal authentication must be completed on the target machine with `shennian agent auth`");await s.close(),await q({...this.manifest.authLaunch??this.manifest.launch,env:Object.fromEntries(Object.entries({...this.extraEnv,...this.manifest.authLaunch?.env??this.manifest.launch.env}).filter(n=>typeof n[1]=="string"))},i,this.workDir)}else await s.authenticate(e);await this.resumeAfterExternalAuthentication()}catch(n){throw E(),n}}async logout(){await this.requireClient().logout(),d(this.type,"required")}async resumeAfterExternalAuthentication(){await this.client?.close(),this.client=this.createProcessClient(),await this.client.start(this.workDir),this.startedConfigurationSignature=this.configurationSignature,d(this.type,"ready");const e=this.pendingAuthRetry;this.pendingAuthRetry=null,e&&this.retryAfterAuthentication(e)}async listExternalSessions(e={}){const t=this.requireClient();if(!t.capabilities.sessionCapabilities?.list)return[];const s=[];let i;for(let n=0;n<10&&s.length<500;n+=1){let o=e.cwd;if(o)try{o=g.native(o)}catch{}const r=await t.listSessions(o,i);if(s.push(...r.sessions.slice(0,500-s.length).map(a=>({agentSessionId:a.sessionId,cwd:a.cwd,...a.title?{title:a.title.slice(0,200)}:{},...a.updatedAt?{updatedAt:a.updatedAt}:{}}))),i=r.nextCursor,!i)break}return s}async loadExternalSession(e){const t=this.requireClient();if(!t.capabilities.loadSession)throw new Error("ACP session history import is unsupported");this.requestedSessionId=e,this.agentSessionId=e;const s=[];this.importCapture=s;try{const i=await t.agent.request(l.methods.agent.session.load,{sessionId:e,cwd:this.workDir,mcpServers:[]});this.configOptions=i.configOptions??[],this.modes=i.modes??null,y(!0)}catch(i){throw y(!1),i}finally{this.importCapture=null}return s.map((i,n)=>({sourceId:i.sourceHint??m("sha256").update(`${e}\0${n}\0${i.role}\0${i.payload}`).digest("hex"),role:i.role,payload:i.payload}))}async closeExternalSession(e){if(!this.requireClient().capabilities.sessionCapabilities?.close)throw new Error("ACP session close is unsupported");await this.requireClient().closeSession(e)}async deleteExternalSession(e){if(!this.requireClient().capabilities.sessionCapabilities?.delete)throw new Error("ACP session delete is unsupported");await this.requireClient().deleteSession(e)}async ensureSession(){if(this.agentSessionId)return;const e=this.requireClient();if(this.requestedSessionId){const s=e.capabilities;if(s.sessionCapabilities?.resume){const i=await e.agent.request(l.methods.agent.session.resume,{sessionId:this.requestedSessionId,cwd:this.workDir,mcpServers:[]});this.configOptions=i.configOptions??[],this.modes=i.modes??null}else if(s.loadSession){this.agentSessionId=this.requestedSessionId;const i=await e.agent.request(l.methods.agent.session.load,{sessionId:this.requestedSessionId,cwd:this.workDir,mcpServers:[]});this.configOptions=i.configOptions??[],this.modes=i.modes??null}else throw new Error(`${this.manifest.name} cannot resume ACP sessions`);this.agentSessionId=this.requestedSessionId;return}const t=await e.agent.request(l.methods.agent.session.new,{cwd:this.workDir,mcpServers:[]});this.agentSessionId=t.sessionId,this.configOptions=t.configOptions??[],this.modes=t.modes??null}async applyDynamicConfig(e,t){if(!this.agentSessionId)return;t&&this.modes?.availableModes.some(i=>i.id===t)&&(this.modes.currentModeId!==t&&(await this.requireClient().agent.request(l.methods.agent.session.setMode,{sessionId:this.agentSessionId,modeId:t}),this.modes.currentModeId=t),t=void 0);const s=[{category:"model",value:e},{category:"thought_level",value:t}];for(const i of s){if(!i.value)continue;const n=this.configOptions.find(o=>o.category===i.category&&o.type==="select");!n||n.currentValue===i.value||(await this.requireClient().agent.request(l.methods.agent.session.setConfigOption,{sessionId:this.agentSessionId,configId:n.id,value:i.value}),n.currentValue=i.value)}}handleSessionUpdate(e){if(e.sessionId===this.agentSessionId){if(this.importCapture){this.captureImportedUpdate(e.update);return}if(this.active){if(e.update.sessionUpdate==="tool_call"||e.update.sessionUpdate==="tool_call_update"){const t=JSON.stringify(e.update);if(this.emittedToolStates.get(e.update.toolCallId)===t)return;this.emittedToolStates.set(e.update.toolCallId,t)}for(const t of A(e.update,s=>this.makeEvent(s)))this.emit("agentEvent",t)}}}captureImportedUpdate(e){if(this.importCapture){if(e.sessionUpdate==="user_message_chunk"||e.sessionUpdate==="agent_message_chunk"){const t=e.content.type==="text"?e.content.text:e.content.type==="resource_link"?e.content.name||e.content.uri:`[${e.content.type}]`,s=e.sessionUpdate==="user_message_chunk"?"user":"agent",i=e.messageId?`message:${e.messageId}`:void 0,n=i?this.importCapture.find(o=>o.sourceHint===i):this.importCapture.at(-1);n?.role===s&&n.sourceHint===i?n.payload+=t:this.importCapture.push({role:s,payload:t,...i?{sourceHint:i}:{}});return}if(e.sessionUpdate==="tool_call"){const t=`tool:${e.toolCallId}`,s=this.importCapture.find(n=>n.sourceHint===t),i={role:"agent",sourceHint:t,payload:JSON.stringify({v:1,type:"tool_use",name:e.title,toolCallId:e.toolCallId,status:e.status??"running"})};s?s.payload=i.payload:this.importCapture.push(i);return}if(e.sessionUpdate==="tool_call_update"&&(e.status==="completed"||e.status==="failed")){const t=this.importCapture.find(i=>i.sourceHint===`tool:${e.toolCallId}`),s=JSON.stringify({v:1,type:"tool_result",name:e.title??"tool",toolCallId:e.toolCallId,status:e.status});t?t.payload=s:this.importCapture.push({role:"agent",sourceHint:`tool:${e.toolCallId}`,payload:s})}}}handlePermission(e){if(!this.active||e.sessionId!==this.agentSessionId)return Promise.resolve({outcome:{outcome:"cancelled"}});const t=p();return new Promise(s=>{const i=setTimeout(()=>{this.pendingPermissions.delete(t),s({outcome:{outcome:"cancelled"}})},this.options.permissionTimeoutMs??3e5);i.unref?.(),this.pendingPermissions.set(t,{optionIds:new Set(e.options.map(n=>n.optionId)),resolve:s,timer:i}),this.emitEvent({state:"approval-pending",runPhase:"waiting_approval",approval:{title:e.toolCall.title??void 0,source:this.manifest.name},permission:{id:t,sessionId:this.shennianSessionId,agentSessionId:this.agentSessionId??void 0,runId:this.runId,toolCallId:e.toolCall.toolCallId,options:e.options.map(n=>({id:n.optionId,name:n.name,kind:n.kind}))}})})}requireClient(){if(!this.client)throw new Error("ACP adapter has not started");return this.client}createProcessClient(){return new P(this.manifest.launch,{onSessionUpdate:e=>this.handleSessionUpdate(e),onPermission:e=>this.handlePermission(e)},this.buildEnvironment(),{...this.buildClientCapabilities(),terminalAuth:!0})}async refreshProcessConfiguration(){if(!this.client||this.startedConfigurationSignature===this.configurationSignature)return;const e=this.agentSessionId??this.requestedSessionId;await this.client.close(),this.requestedSessionId=e,this.agentSessionId=null,this.configOptions=[],this.modes=null,this.client=this.createProcessClient(),await this.client.start(this.workDir),this.startedConfigurationSignature=this.configurationSignature}buildEnvironment(){return this.managedAgentPolicy?S(this.managedAgentPolicy)?b(this.extraEnv):{...this.extraEnv}:{...process.env,...this.extraEnv}}buildClientCapabilities(){const e=this.manifest.clientCapabilities??{},t=this.managedAgentPolicy?.adapterPolicy;return t?S(this.managedAgentPolicy)?{...e,terminal:!0,terminalPolicy:"managed-room-only"}:{readTextFile:!!e.readTextFile,writeTextFile:!!(e.writeTextFile&&t.fileAccess!=="workspace-read"),terminal:!0,terminalPolicy:"managed-room-only"}:e}async retryAfterAuthentication(e){this.retryingAfterAuth=!0;try{await this.send(e.text,e.modelId,e.reasoningEffort,e.attachments,e.systemPrompt)}catch{}finally{this.retryingAfterAuth=!1}}async promptWithTimeout(e,t){let s;try{return await Promise.race([e.agent.request(l.methods.agent.session.prompt,{sessionId:this.agentSessionId,prompt:t}),new Promise((i,n)=>{s=setTimeout(()=>n(new Error("ACP prompt timed out")),this.options.promptTimeoutMs??720*6e4),s.unref?.()})])}catch(i){throw i instanceof Error&&i.message==="ACP prompt timed out"&&(await e.close(),this.client===e&&(this.client=null)),i}finally{s&&clearTimeout(s)}}cancelPendingPermissions(){for(const e of this.pendingPermissions.values())clearTimeout(e.timer),e.resolve({outcome:{outcome:"cancelled"}});this.pendingPermissions.clear()}makeEvent(e){return{...e,runId:this.runId,seq:this.seq++}}emitEvent(e){this.emit("agentEvent",this.makeEvent(e))}}function J(u){v(f(u.id),()=>new x(u))}export{x as AcpAgentAdapter,J as registerAcpAgent};
3
+ `)});for(const h of i??[])o.push({type:"resource_link",uri:v(h.path).href,name:h.name,mimeType:h.mimeType,size:h.byteSize});const u=await this.promptWithTimeout(a,o);this.active=!1,u.stopReason==="cancelled"?this.emitEvent({state:"aborted",agentSessionId:this.agentSessionId??void 0}):this.emitEvent({state:"final",agentSessionId:this.agentSessionId??void 0})}catch(o){this.active=!1,this.cancelPendingPermissions();const r=o instanceof Error?o.message:String(o),u=o instanceof C&&o.code===-32e3;throw u&&(d(this.type,"required"),this.retryingAfterAuth||(this.pendingAuthRetry={text:e,...t?{modelId:t}:{},...n?{reasoningEffort:n}:{},...i?{attachments:[...i]}:{},...s!==void 0?{systemPrompt:s}:{}})),this.emitEvent({state:"error",message:r,...u?{errorCode:"acp_auth_required"}:{},agentSessionId:this.agentSessionId??void 0}),o}}async resume(e){this.requestedSessionId=e,this.agentSessionId=null,await this.ensureSession()}async stop(){this.active&&this.agentSessionId&&this.client&&await this.client.agent.notify(l.methods.agent.session.cancel,{sessionId:this.agentSessionId}),this.cancelPendingPermissions(),this.active=!1,await this.client?.close(),this.client=null,this.startedConfigurationSignature=""}async getStatus(){return{active:this.active,runId:this.active?this.runId:null,canStop:this.active}}async respondToPermission(e,t){const n=this.pendingPermissions.get(e);if(!n)throw new Error("ACP permission request is no longer pending");if(!n.optionIds.has(t))throw new Error("Invalid ACP permission option");this.pendingPermissions.delete(e),clearTimeout(n.timer),n.resolve({outcome:{outcome:"selected",optionId:t}})}getAuthMethods(){return[...this.requireClient().initializeResponse?.authMethods??[]]}hasPendingAuthenticationRetry(){return this.pendingAuthRetry!==null}getSessionOptions(){const e=p(this.configOptions,"model"),t=p(this.configOptions,"thought_level"),n=this.modes?.availableModes.map(s=>({id:s.id,name:s.name,...s.description?{description:s.description}:{}}))??[],i=(t?m(t):n).map(s=>({id:"value"in s?s.value:s.id,name:s.name,...s.description?{description:s.description}:{}}));return{models:m(e).map(s=>({id:s.value,name:s.name,...s.description?{description:s.description}:{},...s.value===e?.currentValue?{isDefault:!0}:{},...i.length?{supportedReasoningEfforts:i}:{}})),modes:n}}async authenticate(e,t={}){const n=this.requireClient(),i=n.initializeResponse?.authMethods?.find(s=>s.id===e);if(!i)throw new Error("ACP authentication method is unavailable");try{if("type"in i&&i.type==="terminal"){if(!t.interactiveTerminal)throw new Error("ACP terminal authentication must be completed on the target machine with `shennian agent auth`");await n.close(),await b({...this.manifest.authLaunch??this.manifest.launch,env:Object.fromEntries(Object.entries({...this.extraEnv,...this.manifest.authLaunch?.env??this.manifest.launch.env}).filter(s=>typeof s[1]=="string"))},i,this.workDir)}else await n.authenticate(e);await this.resumeAfterExternalAuthentication()}catch(s){throw x(),s}}async logout(){await this.requireClient().logout(),d(this.type,"required")}async resumeAfterExternalAuthentication(){await this.client?.close(),this.client=this.createProcessClient(),await this.client.start(this.workDir),this.startedConfigurationSignature=this.configurationSignature,d(this.type,"ready");const e=this.pendingAuthRetry;this.pendingAuthRetry=null,e&&this.retryAfterAuthentication(e)}async listExternalSessions(e={}){const t=this.requireClient();if(!t.capabilities.sessionCapabilities?.list)return[];const n=[];let i;for(let s=0;s<10&&n.length<500;s+=1){let a=e.cwd;if(a)try{a=y.native(a)}catch{}const o=await t.listSessions(a,i);if(n.push(...o.sessions.slice(0,500-n.length).map(r=>({agentSessionId:r.sessionId,cwd:r.cwd,...r.title?{title:r.title.slice(0,200)}:{},...r.updatedAt?{updatedAt:r.updatedAt}:{}}))),i=o.nextCursor,!i)break}return n}async loadExternalSession(e){const t=this.requireClient();if(!t.capabilities.loadSession)throw new Error("ACP session history import is unsupported");this.requestedSessionId=e,this.agentSessionId=e;const n=[];this.importCapture=n;try{const i=await t.agent.request(l.methods.agent.session.load,{sessionId:e,cwd:this.workDir,mcpServers:[]});this.configOptions=i.configOptions??[],this.modes=i.modes??null,I(!0)}catch(i){throw I(!1),i}finally{this.importCapture=null}return n.map((i,s)=>({sourceId:i.sourceHint??f("sha256").update(`${e}\0${s}\0${i.role}\0${i.payload}`).digest("hex"),role:i.role,payload:i.payload}))}async closeExternalSession(e){if(!this.requireClient().capabilities.sessionCapabilities?.close)throw new Error("ACP session close is unsupported");await this.requireClient().closeSession(e)}async deleteExternalSession(e){if(!this.requireClient().capabilities.sessionCapabilities?.delete)throw new Error("ACP session delete is unsupported");await this.requireClient().deleteSession(e)}async ensureSession(){if(this.agentSessionId)return;const e=this.requireClient();if(this.requestedSessionId){const n=e.capabilities;if(n.sessionCapabilities?.resume){const i=await e.agent.request(l.methods.agent.session.resume,{sessionId:this.requestedSessionId,cwd:this.workDir,mcpServers:[]});this.configOptions=i.configOptions??[],this.modes=i.modes??null}else if(n.loadSession){this.agentSessionId=this.requestedSessionId;const i=await e.agent.request(l.methods.agent.session.load,{sessionId:this.requestedSessionId,cwd:this.workDir,mcpServers:[]});this.configOptions=i.configOptions??[],this.modes=i.modes??null}else throw new Error(`${this.manifest.name} cannot resume ACP sessions`);this.agentSessionId=this.requestedSessionId,this.emit("sessionOptions");return}const t=await e.agent.request(l.methods.agent.session.new,{cwd:this.workDir,mcpServers:[]});this.agentSessionId=t.sessionId,this.configOptions=t.configOptions??[],this.modes=t.modes??null,this.emit("sessionOptions")}async applyDynamicConfig(e,t){if(!this.agentSessionId)return;t&&this.modes?.availableModes.some(i=>i.id===t)&&(this.modes.currentModeId!==t&&(await this.requireClient().agent.request(l.methods.agent.session.setMode,{sessionId:this.agentSessionId,modeId:t}),this.modes.currentModeId=t),t=void 0);const n=[{category:"model",value:e},{category:"thought_level",value:t}];for(const i of n){if(!i.value)continue;const s=p(this.configOptions,i.category);!s||s.currentValue===i.value||m(s).some(a=>a.value===i.value)&&(await this.requireClient().agent.request(l.methods.agent.session.setConfigOption,{sessionId:this.agentSessionId,configId:s.id,value:i.value}),s.currentValue=i.value)}}handleSessionUpdate(e){if(e.sessionId===this.agentSessionId){if(this.importCapture){this.captureImportedUpdate(e.update);return}if(this.active){if(e.update.sessionUpdate==="tool_call"||e.update.sessionUpdate==="tool_call_update"){const t=JSON.stringify(e.update);if(this.emittedToolStates.get(e.update.toolCallId)===t)return;this.emittedToolStates.set(e.update.toolCallId,t)}for(const t of q(e.update,n=>this.makeEvent(n)))this.emit("agentEvent",t)}}}captureImportedUpdate(e){if(this.importCapture){if(e.sessionUpdate==="user_message_chunk"||e.sessionUpdate==="agent_message_chunk"){const t=e.content.type==="text"?e.content.text:e.content.type==="resource_link"?e.content.name||e.content.uri:`[${e.content.type}]`,n=e.sessionUpdate==="user_message_chunk"?"user":"agent",i=e.messageId?`message:${e.messageId}`:void 0,s=i?this.importCapture.find(a=>a.sourceHint===i):this.importCapture.at(-1);s?.role===n&&s.sourceHint===i?s.payload+=t:this.importCapture.push({role:n,payload:t,...i?{sourceHint:i}:{}});return}if(e.sessionUpdate==="tool_call"){const t=`tool:${e.toolCallId}`,n=this.importCapture.find(s=>s.sourceHint===t),i={role:"agent",sourceHint:t,payload:JSON.stringify({v:1,type:"tool_use",name:e.title,toolCallId:e.toolCallId,status:e.status??"running"})};n?n.payload=i.payload:this.importCapture.push(i);return}if(e.sessionUpdate==="tool_call_update"&&(e.status==="completed"||e.status==="failed")){const t=this.importCapture.find(i=>i.sourceHint===`tool:${e.toolCallId}`),n=JSON.stringify({v:1,type:"tool_result",name:e.title??"tool",toolCallId:e.toolCallId,status:e.status});t?t.payload=n:this.importCapture.push({role:"agent",sourceHint:`tool:${e.toolCallId}`,payload:n})}}}handlePermission(e){if(!this.active||e.sessionId!==this.agentSessionId)return Promise.resolve({outcome:{outcome:"cancelled"}});const t=g();return new Promise(n=>{const i=setTimeout(()=>{this.pendingPermissions.delete(t),n({outcome:{outcome:"cancelled"}})},this.options.permissionTimeoutMs??3e5);i.unref?.(),this.pendingPermissions.set(t,{optionIds:new Set(e.options.map(s=>s.optionId)),resolve:n,timer:i}),this.emitEvent({state:"approval-pending",runPhase:"waiting_approval",approval:{title:e.toolCall.title??void 0,source:this.manifest.name},permission:{id:t,sessionId:this.shennianSessionId,agentSessionId:this.agentSessionId??void 0,runId:this.runId,toolCallId:e.toolCall.toolCallId,options:e.options.map(s=>({id:s.optionId,name:s.name,kind:s.kind}))}})})}requireClient(){if(!this.client)throw new Error("ACP adapter has not started");return this.client}createProcessClient(){return new E(this.manifest.launch,{onSessionUpdate:e=>this.handleSessionUpdate(e),onPermission:e=>this.handlePermission(e)},this.buildEnvironment(),{...this.buildClientCapabilities(),terminalAuth:!0})}async refreshProcessConfiguration(){if(!this.client||this.startedConfigurationSignature===this.configurationSignature)return;const e=this.agentSessionId??this.requestedSessionId;await this.client.close(),this.requestedSessionId=e,this.agentSessionId=null,this.configOptions=[],this.modes=null,this.client=this.createProcessClient(),await this.client.start(this.workDir),this.startedConfigurationSignature=this.configurationSignature}buildEnvironment(){return this.managedAgentPolicy?w(this.managedAgentPolicy)?O(this.extraEnv):{...this.extraEnv}:{...process.env,...this.extraEnv}}buildClientCapabilities(){const e=this.manifest.clientCapabilities??{},t=this.managedAgentPolicy?.adapterPolicy;return t?w(this.managedAgentPolicy)?{...e,terminal:!0,terminalPolicy:"managed-room-only"}:{readTextFile:!!e.readTextFile,writeTextFile:!!(e.writeTextFile&&t.fileAccess!=="workspace-read"),terminal:!0,terminalPolicy:"managed-room-only"}:e}async retryAfterAuthentication(e){this.retryingAfterAuth=!0;try{await this.send(e.text,e.modelId,e.reasoningEffort,e.attachments,e.systemPrompt)}catch{}finally{this.retryingAfterAuth=!1}}async promptWithTimeout(e,t){let n;try{return await Promise.race([e.agent.request(l.methods.agent.session.prompt,{sessionId:this.agentSessionId,prompt:t}),new Promise((i,s)=>{n=setTimeout(()=>s(new Error("ACP prompt timed out")),this.options.promptTimeoutMs??720*6e4),n.unref?.()})])}catch(i){throw i instanceof Error&&i.message==="ACP prompt timed out"&&(await e.close(),this.client===e&&(this.client=null)),i}finally{n&&clearTimeout(n)}}cancelPendingPermissions(){for(const e of this.pendingPermissions.values())clearTimeout(e.timer),e.resolve({outcome:{outcome:"cancelled"}});this.pendingPermissions.clear()}makeEvent(e){return{...e,runId:this.runId,seq:this.seq++}}emitEvent(e){this.emit("agentEvent",this.makeEvent(e))}}function L(c){P(S(c.id),()=>new T(c))}export{T as AcpAgentAdapter,L as registerAcpAgent};
@@ -1,2 +1,2 @@
1
- import c from"node:crypto";import n from"node:fs";import l from"node:path";import{resolveShennianPath as r}from"../../config/index.js";const a="acp-capabilities-v1.json",m=2*1024*1024;function h(e){return e.executableIdentity?c.createHash("sha256").update(JSON.stringify({id:e.manifest.id,command:e.manifest.launch.command,args:e.manifest.launch.args??[],env:e.manifest.launch.env??{},clientCapabilities:e.manifest.clientCapabilities??{},platform:e.platform,catalogRevision:e.catalogRevision??"local",executable:e.executableIdentity})).digest("hex"):null}function b(e){return o().entries[e]??null}function C(e,t){const i=o();i.entries[e]=t;const s=Object.entries(i.entries).slice(-256);f({version:1,entries:Object.fromEntries(s)})}function v(){try{n.unlinkSync(r(a))}catch{}}function o(){try{const e=r(a);if(n.statSync(e).size>m)return{version:1,entries:{}};const t=JSON.parse(n.readFileSync(e,"utf8"));if(t.version!==1||!t.entries||typeof t.entries!="object")throw new Error("invalid");return t}catch{return{version:1,entries:{}}}}function f(e){const t=r(a);n.mkdirSync(l.dirname(t),{recursive:!0,mode:448});const i=`${t}.tmp-${process.pid}-${c.randomUUID()}`;try{n.writeFileSync(i,`${JSON.stringify(e)}
2
- `,{mode:384,flag:"wx"}),n.renameSync(i,t)}finally{try{n.unlinkSync(i)}catch{}}}export{h as buildAcpCapabilityCacheKey,v as clearAcpCapabilityCache,b as readAcpCapabilityCache,C as writeAcpCapabilityCache};
1
+ import c from"node:crypto";import r from"node:fs";import{renameSyncWithRetry as l}from"../../fs/atomic-rename.js";import m from"node:path";import{resolveShennianPath as i}from"../../config/index.js";const a="acp-capabilities-v1.json",f=2*1024*1024;function C(e){return e.executableIdentity?c.createHash("sha256").update(JSON.stringify({id:e.manifest.id,command:e.manifest.launch.command,args:e.manifest.launch.args??[],env:e.manifest.launch.env??{},clientCapabilities:e.manifest.clientCapabilities??{},platform:e.platform,catalogRevision:e.catalogRevision??"local",executable:e.executableIdentity})).digest("hex"):null}function v(e){return o().entries[e]??null}function S(e,t){const n=o();n.entries[e]=t;const s=Object.entries(n.entries).slice(-256);y({version:1,entries:Object.fromEntries(s)})}function g(){try{r.unlinkSync(i(a))}catch{}}function o(){try{const e=i(a);if(r.statSync(e).size>f)return{version:1,entries:{}};const t=JSON.parse(r.readFileSync(e,"utf8"));if(t.version!==1||!t.entries||typeof t.entries!="object")throw new Error("invalid");return t}catch{return{version:1,entries:{}}}}function y(e){const t=i(a);r.mkdirSync(m.dirname(t),{recursive:!0,mode:448});const n=`${t}.tmp-${process.pid}-${c.randomUUID()}`;try{r.writeFileSync(n,`${JSON.stringify(e)}
2
+ `,{mode:384,flag:"wx"}),l(n,t)}finally{try{r.unlinkSync(n)}catch{}}}export{C as buildAcpCapabilityCacheKey,g as clearAcpCapabilityCache,v as readAcpCapabilityCache,S as writeAcpCapabilityCache};
@@ -1,2 +1,2 @@
1
- import n from"node:fs";import u from"node:path";import{resolveShennianPath as f}from"../../config/index.js";import{deriveInstalledPackageCommands as g}from"./package-commands.js";const p="acp-registry-v1.json",s=2*1024*1024;async function S(a={}){const r=i();let e=null;return a.serverUrl&&a.authToken&&(e=await w(a).catch(()=>null),e&&(!r||Date.parse(e.fetchedAt)>=Date.parse(r.fetchedAt))?y(e):e&&r&&(e=r)),e??=r,!e||e.platform!==c()?{candidates:[]}:{revision:e.revision,candidates:e.candidates.flatMap(t=>t.duplicateOf?[]:[...new Set([...t.commands,...g({npm:t.npmPackage,uv:t.uvPackage})])].map(l=>({id:t.id,name:t.name,source:"registry",...t.website?{homepage:t.website}:{},...t.npmPackage||t.uvPackage?{packageHints:{...t.npmPackage?{npm:t.npmPackage}:{},...t.uvPackage?{uv:t.uvPackage}:{}}}:{},launch:{command:l,args:t.args}})))}}function c(){const a=process.platform==="win32"?"windows":process.platform==="darwin"?"darwin":"linux",r=process.arch==="arm64"?"aarch64":"x86_64";return`${a}-${r}`}async function w(a){const r=new AbortController,e=setTimeout(()=>r.abort(),5e3);try{const t=new URL("/api/acp/registry",a.serverUrl);t.searchParams.set("platform",c());const o=await(a.fetchImpl??fetch)(t,{headers:{authorization:`Bearer ${a.authToken}`,...i()?.revision?{"x-shennian-acp-revision":i().revision}:{}},signal:r.signal});if(!o.ok)throw new Error(`ACP catalog request failed (${o.status})`);if(Number(o.headers.get("content-length")??0)>s)throw new Error("ACP catalog exceeds size limit");const m=new Uint8Array(await o.arrayBuffer());if(m.byteLength>s)throw new Error("ACP catalog exceeds size limit");return h(JSON.parse(new TextDecoder().decode(m)))}finally{clearTimeout(e)}}function h(a){if(!a||typeof a!="object")throw new Error("Invalid ACP catalog");const r=a;if(!/^[a-z0-9]+-[a-f0-9]{16}$/.test(r.revision)||!/^[a-f0-9]{64}$/.test(r.digest)||Number.isNaN(Date.parse(r.fetchedAt))||r.platform!==c()||!Array.isArray(r.candidates))throw new Error("Invalid ACP catalog");for(const e of r.candidates)if(!/^[a-z][a-z0-9-]{0,63}$/.test(e.id)||!e.name||e.name.length>80||!Array.isArray(e.commands)||e.commands.some(t=>!/^[a-zA-Z0-9._-]{1,128}$/.test(t))||!Array.isArray(e.args))throw new Error("Invalid ACP catalog candidate");return r}function i(){try{const a=f(p);return n.statSync(a).size>s?null:h(JSON.parse(n.readFileSync(a,"utf8")))}catch{return null}}function y(a){const r=f(p);n.mkdirSync(u.dirname(r),{recursive:!0,mode:448});const e=`${r}.tmp-${process.pid}`;try{n.writeFileSync(e,`${JSON.stringify(a)}
2
- `,{mode:384,flag:"wx"}),n.renameSync(e,r)}finally{try{n.unlinkSync(e)}catch{}}}export{c as currentAcpPlatform,S as loadAcpCatalog};
1
+ import o from"node:fs";import{renameSyncWithRetry as u}from"../../fs/atomic-rename.js";import g from"node:path";import{resolveShennianPath as f}from"../../config/index.js";import{deriveInstalledPackageCommands as y}from"./package-commands.js";const p="acp-registry-v1.json",s=2*1024*1024;async function C(a={}){const r=i();let e=null;return a.serverUrl&&a.authToken&&(e=await w(a).catch(()=>null),e&&(!r||Date.parse(e.fetchedAt)>=Date.parse(r.fetchedAt))?d(e):e&&r&&(e=r)),e??=r,!e||e.platform!==c()?{candidates:[]}:{revision:e.revision,candidates:e.candidates.flatMap(t=>t.duplicateOf?[]:[...new Set([...t.commands,...y({npm:t.npmPackage,uv:t.uvPackage})])].map(l=>({id:t.id,name:t.name,source:"registry",...t.website?{homepage:t.website}:{},...t.npmPackage||t.uvPackage?{packageHints:{...t.npmPackage?{npm:t.npmPackage}:{},...t.uvPackage?{uv:t.uvPackage}:{}}}:{},launch:{command:l,args:t.args}})))}}function c(){const a=process.platform==="win32"?"windows":process.platform==="darwin"?"darwin":"linux",r=process.arch==="arm64"?"aarch64":"x86_64";return`${a}-${r}`}async function w(a){const r=new AbortController,e=setTimeout(()=>r.abort(),5e3);try{const t=new URL("/api/acp/registry",a.serverUrl);t.searchParams.set("platform",c());const n=await(a.fetchImpl??fetch)(t,{headers:{authorization:`Bearer ${a.authToken}`,...i()?.revision?{"x-shennian-acp-revision":i().revision}:{}},signal:r.signal});if(!n.ok)throw new Error(`ACP catalog request failed (${n.status})`);if(Number(n.headers.get("content-length")??0)>s)throw new Error("ACP catalog exceeds size limit");const m=new Uint8Array(await n.arrayBuffer());if(m.byteLength>s)throw new Error("ACP catalog exceeds size limit");return h(JSON.parse(new TextDecoder().decode(m)))}finally{clearTimeout(e)}}function h(a){if(!a||typeof a!="object")throw new Error("Invalid ACP catalog");const r=a;if(!/^[a-z0-9]+-[a-f0-9]{16}$/.test(r.revision)||!/^[a-f0-9]{64}$/.test(r.digest)||Number.isNaN(Date.parse(r.fetchedAt))||r.platform!==c()||!Array.isArray(r.candidates))throw new Error("Invalid ACP catalog");for(const e of r.candidates)if(!/^[a-z][a-z0-9-]{0,63}$/.test(e.id)||!e.name||e.name.length>80||!Array.isArray(e.commands)||e.commands.some(t=>!/^[a-zA-Z0-9._-]{1,128}$/.test(t))||!Array.isArray(e.args))throw new Error("Invalid ACP catalog candidate");return r}function i(){try{const a=f(p);return o.statSync(a).size>s?null:h(JSON.parse(o.readFileSync(a,"utf8")))}catch{return null}}function d(a){const r=f(p);o.mkdirSync(g.dirname(r),{recursive:!0,mode:448});const e=`${r}.tmp-${process.pid}`;try{o.writeFileSync(e,`${JSON.stringify(a)}
2
+ `,{mode:384,flag:"wx"}),u(e,r)}finally{try{o.unlinkSync(e)}catch{}}}export{c as currentAcpPlatform,C as loadAcpCatalog};
@@ -1,2 +1,2 @@
1
- import o from"node:fs";import c from"node:path";import{z as n}from"zod";import{resolveShennianPath as u}from"../../config/index.js";const w="https://shennian.net/schemas/acp-agent-manifest-v1.json",h="acp-agents.d",S=64*1024,f=n.object({schemaVersion:n.literal(1),id:n.string().regex(/^[a-z0-9][a-z0-9._-]{0,63}$/),name:n.string().trim().min(1).max(80),protocol:n.literal("acp"),command:n.string().trim().min(1).max(4096),args:n.array(n.string().max(4096)).max(64).default([]),enabled:n.boolean().default(!0),homepage:n.string().url().refine(t=>new URL(t).protocol==="https:").optional(),clientCapabilities:n.object({readTextFile:n.boolean().default(!1),writeTextFile:n.boolean().default(!1),terminal:n.boolean().default(!1)}).strict().optional()}).strict();function m(){return u(h)}function d(t){const e=f.parse(t);if(e.command.includes("\0")||e.args.some(i=>i.includes("\0")))throw new Error("ACP manifest command contains NUL");if(!c.isAbsolute(e.command)&&c.basename(e.command)!==e.command)throw new Error("ACP manifest command must be absolute or a plain command name");return e}function C(t=m()){let e;try{e=o.readdirSync(t).filter(s=>s.endsWith(".json")).sort()}catch{return[]}const i=[],r=new Set;for(const s of e){const l=c.join(t,s);try{const p=o.statSync(l);if(!p.isFile()||p.size>S)continue;const a=d(JSON.parse(o.readFileSync(l,"utf8")));if(!a.enabled||r.has(a.id))continue;r.add(a.id),i.push({id:a.id,name:a.name,homepage:a.homepage,source:"local",launch:{command:a.command,args:a.args},...a.clientCapabilities?{clientCapabilities:a.clientCapabilities}:{}})}catch{}}return i}function M(t,e=m()){const i=d(t);o.mkdirSync(e,{recursive:!0,mode:448}),process.platform!=="win32"&&o.chmodSync(e,448);const r=c.join(e,`${i.id}.json`),s=`${r}.tmp-${process.pid}`;try{o.writeFileSync(s,`${JSON.stringify(i,null,2)}
2
- `,{mode:384,flag:"wx"}),o.renameSync(s,r),process.platform!=="win32"&&o.chmodSync(r,384)}finally{try{o.unlinkSync(s)}catch{}}return r}function j(t,e=m()){const i=g(t);try{return o.unlinkSync(c.join(e,`${i}.json`)),!0}catch{return!1}}function g(t){return f.shape.id.parse(t)}export{h as ACP_MANIFEST_DIRECTORY,w as ACP_MANIFEST_SCHEMA_ID,m as getAcpManifestDirectory,C as readAcpManifests,j as removeAcpManifest,g as validateAcpId,d as validateAcpManifest,M as writeAcpManifest};
1
+ import i from"node:fs";import{renameSyncWithRetry as u}from"../../fs/atomic-rename.js";import c from"node:path";import{z as t}from"zod";import{resolveShennianPath as h}from"../../config/index.js";const M="https://shennian.net/schemas/acp-agent-manifest-v1.json",S="acp-agents.d",g=64*1024,f=t.object({schemaVersion:t.literal(1),id:t.string().regex(/^[a-z0-9][a-z0-9._-]{0,63}$/),name:t.string().trim().min(1).max(80),protocol:t.literal("acp"),command:t.string().trim().min(1).max(4096),args:t.array(t.string().max(4096)).max(64).default([]),enabled:t.boolean().default(!0),homepage:t.string().url().refine(n=>new URL(n).protocol==="https:").optional(),clientCapabilities:t.object({readTextFile:t.boolean().default(!1),writeTextFile:t.boolean().default(!1),terminal:t.boolean().default(!1)}).strict().optional()}).strict();function m(){return h(S)}function d(n){const e=f.parse(n);if(e.command.includes("\0")||e.args.some(o=>o.includes("\0")))throw new Error("ACP manifest command contains NUL");if(!c.isAbsolute(e.command)&&c.basename(e.command)!==e.command)throw new Error("ACP manifest command must be absolute or a plain command name");return e}function j(n=m()){let e;try{e=i.readdirSync(n).filter(s=>s.endsWith(".json")).sort()}catch{return[]}const o=[],r=new Set;for(const s of e){const l=c.join(n,s);try{const p=i.statSync(l);if(!p.isFile()||p.size>g)continue;const a=d(JSON.parse(i.readFileSync(l,"utf8")));if(!a.enabled||r.has(a.id))continue;r.add(a.id),o.push({id:a.id,name:a.name,homepage:a.homepage,source:"local",launch:{command:a.command,args:a.args},...a.clientCapabilities?{clientCapabilities:a.clientCapabilities}:{}})}catch{}}return o}function E(n,e=m()){const o=d(n);i.mkdirSync(e,{recursive:!0,mode:448}),process.platform!=="win32"&&i.chmodSync(e,448);const r=c.join(e,`${o.id}.json`),s=`${r}.tmp-${process.pid}`;try{i.writeFileSync(s,`${JSON.stringify(o,null,2)}
2
+ `,{mode:384,flag:"wx"}),u(s,r),process.platform!=="win32"&&i.chmodSync(r,384)}finally{try{i.unlinkSync(s)}catch{}}return r}function F(n,e=m()){const o=y(n);try{return i.unlinkSync(c.join(e,`${o}.json`)),!0}catch{return!1}}function y(n){return f.shape.id.parse(n)}export{S as ACP_MANIFEST_DIRECTORY,M as ACP_MANIFEST_SCHEMA_ID,m as getAcpManifestDirectory,j as readAcpManifests,F as removeAcpManifest,y as validateAcpId,d as validateAcpManifest,E as writeAcpManifest};
@@ -1,8 +1,10 @@
1
- import p from"node:fs";import o from"node:path";import{createInterface as y}from"node:readline";import{randomUUID as f}from"node:crypto";import{AgentAdapter as S,registerAgent as E}from"./adapter.js";import{resolveBuiltinCommand as m,spawnAgentCommand as x,spawnResolvedCommandSync as v}from"./command-spec.js";import{buildAgentProcessEnv as P,buildManagedAgentProcessEnv as C,buildManagedNativeFullProcessEnv as I}from"../agent-env.js";import{buildPlatformInstructions as g}from"./platform-instructions.js";import{resolveManagedAgentAdapterEnforcement as k,isManagedAgentNativeFull as c}from"../security/managed-agent-policy.js";import{registerManagedAgentRuntimeSecurity as w}from"../security/managed-agent-runtime.js";import{resolveManagedRoomIpcPaths as A}from"../daemon-ipc/paths.js";import{CLAUDE_MANAGED_RUNTIME_SECURITY as _,compileClaudeManagedPermissions as R}from"./claude-managed-permissions.js";w("claude",_);function T(n){return n?.trim()||"default"}const M=new Set(["low","medium","high","xhigh","max"]),h=new Map;function O(n){const e=n?.trim();if(e){if(M.has(e))return e;throw new Error(`Unsupported Claude reasoning effort "${e}". Supported values: low, medium, high, xhigh, max.`)}}function W(){h.clear()}function N(n){const e=n.trim();return e?!e.includes("claude.ai connectors are disabled because"):!1}function D(){const n=m("claude");if(!n)return!1;const e=`${n.kind}:${n.path}:${n.command}:${n.args.join("\0")}`;if(h.has(e))return h.get(e)??!1;try{const t=v(n,["--help"],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:3e3,env:process.env}),s=`${t.stdout??""}
2
- ${t.stderr??""}`,a=/(?:^|\s)--effort(?:\s|,|<)/.test(s);return h.set(e,a),a}catch{return h.set(e,!1),!1}}class F extends S{options;type="claude";get recoveryCapabilities(){return{inspectTerminal:!1,reattachRun:!1,resumeRun:!1,resumeSession:!0}}process=null;agentSessionId=null;sessionId=null;workDir=null;seq=0;runId="";hasEmittedText=!1;terminalState="open";authenticationRetrying=!1;pendingSuccess=null;persistNativeSession=!0;managedAgentPolicy=null;constructor(e={}){super(),this.options=e}externalChannel=null;shennianSessionId=null;extraEnv={};configure(e){this.shennianSessionId=e.sessionId??null,this.externalChannel=e.externalChannel??null,this.extraEnv=e.env??{},"managedAgentPolicy"in e&&(this.managedAgentPolicy=e.managedAgentPolicy??null),this.managedAgentPolicy&&(this.workDir=this.managedAgentPolicy.adapterPolicy.workDir)}async start(e,t,s,a){this.sessionId=e,this.workDir=this.managedAgentPolicy?.adapterPolicy.workDir??t,this.seq=0,this.persistNativeSession=a?.persistNativeSession!==!1,s&&(this.agentSessionId=s)}async send(e,t,s,a,u,r){if(r?.source==="room_activation"&&!this.managedAgentPolicy)throw new Error("managed_agent_policy_missing");await this.killProcess(),this.runId=f(),this.resetRunState();const i=["-p",e,"--output-format","stream-json","--verbose",...this.buildManagedPermissionConfig()?.args??[]];this.persistNativeSession||i.push("--no-session-persistence");const l=this.options.systemPrompt??g(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0,u);l&&i.push("--append-system-prompt",l),this.options.hidden&&i.push("--name","Shennian Manager Substrate"),(!this.managedAgentPolicy||c(this.managedAgentPolicy))&&process.getuid?.()!==0&&i.push("--dangerously-skip-permissions"),i.push("--model",T(t));const d=O(s);d&&D()&&i.push("--effort",d),this.agentSessionId&&i.push("--resume",this.agentSessionId),this.spawnAndParse(i)}async resume(e){await this.killProcess(),this.agentSessionId=e,this.runId=f(),this.resetRunState();const t=["--resume",e,"--output-format","stream-json","--verbose",...this.buildManagedPermissionConfig()?.args??[]],s=this.options.systemPrompt??g(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0);s&&t.push("--append-system-prompt",s),this.options.hidden&&t.push("--name","Shennian Manager Substrate"),(!this.managedAgentPolicy||c(this.managedAgentPolicy))&&process.getuid?.()!==0&&t.push("--dangerously-skip-permissions"),this.spawnAndParse(t)}async stop(){await this.killProcess()}spawnAndParse(e){const t=m("claude");if(!t){this.emit("error",new Error('Command "claude" not found. Is Claude Code CLI installed?'));return}const s=x(t,e,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:this.buildProcessEnv()});this.process=s,y({input:s.stdout}).on("line",r=>{if(r.trim())try{const i=JSON.parse(r);this.handleStreamEvent(i)}catch{}});let u="";s.stderr?.on("data",r=>{const i=r.toString();if(u+=i,this.terminalState==="open")for(const l of i.split(`
3
- `)){const d=l.trim();N(d)&&this.emitEvent({state:"delta",text:d+`
4
- `})}}),s.on("close",r=>{this.process===s&&(this.process=null,this.handleProcessClose(r,u))}),s.on("error",r=>{this.process===s&&(this.process=null,r.code==="ENOENT"?this.emit("error",new Error('Command "claude" not found. Is Claude Code CLI installed?')):this.emit("error",r))})}buildManagedPermissionConfig(){const e=this.managedAgentPolicy;if(!e||c(e))return null;const t=L();return R(k(e),e.adapterPolicy.workDir,{internalReadPaths:t.readPaths,internalUnixSockets:t.unixSockets,shellSubprocessPolicy:e.environmentPolicy.shellSubprocess})}buildProcessEnv(){return this.managedAgentPolicy?c(this.managedAgentPolicy)?I({NO_COLOR:"1",...this.extraEnv}):C({agentType:"claude",providerEnv:this.extraEnv,sessionEnv:this.extraEnv,runtimeEnv:{NO_COLOR:"1"}}):P(this.extraEnv)}handleStreamEvent(e){if(e.type==="system"&&e.subtype==="init"&&e.session_id){this.agentSessionId=e.session_id,this.emitEvent({state:"start",agentSessionId:this.agentSessionId});return}if(e.type==="system"&&e.subtype==="api_retry"&&e.error==="authentication_failed"){this.authenticationRetrying=!0,this.emitEvent({state:"heartbeat",runPhase:"thinking",errorCode:"auth_retrying",message:"Claude authentication is retrying."});return}if(e.type==="assistant"){if(this.authenticationRetrying=!1,e.message?.content){for(const t of e.message.content)if(t.type==="text"&&t.text){const s=this.hasEmittedText?`
1
+ import p from"node:fs";import o from"node:path";import{createInterface as S}from"node:readline";import{randomUUID as f}from"node:crypto";import{AgentAdapter as E,registerAgent as x}from"./adapter.js";import{resolveBuiltinCommand as m,spawnAgentCommand as v,spawnResolvedCommandSync as P}from"./command-spec.js";import{spawnEnoentError as C}from"./spawn-errors.js";import{buildAgentProcessEnv as I,buildManagedAgentProcessEnv as k,buildManagedNativeFullProcessEnv as w}from"../agent-env.js";import{buildPlatformInstructions as g}from"./platform-instructions.js";import{resolveManagedAgentAdapterEnforcement as A,isManagedAgentNativeFull as c}from"../security/managed-agent-policy.js";import{registerManagedAgentRuntimeSecurity as _}from"../security/managed-agent-runtime.js";import{resolveManagedRoomIpcPaths as R}from"../daemon-ipc/paths.js";import{CLAUDE_MANAGED_RUNTIME_SECURITY as T,compileClaudeManagedPermissions as N}from"./claude-managed-permissions.js";_("claude",T);function M(n){return n?.trim()||"default"}const O=new Set(["low","medium","high","xhigh","max"]),h=new Map;function D(n){const e=n?.trim();if(e){if(O.has(e))return e;throw new Error(`Unsupported Claude reasoning effort "${e}". Supported values: low, medium, high, xhigh, max.`)}}function te(){h.clear()}function L(n){const e=n.trim();return e?!e.includes("claude.ai connectors are disabled because"):!1}function F(){const n=m("claude");if(!n)return!1;const e=`${n.kind}:${n.path}:${n.command}:${n.args.join("\0")}`;if(h.has(e))return h.get(e)??!1;try{const t=P(n,["--help"],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:3e3,env:process.env}),s=`${t.stdout??""}
2
+ ${t.stderr??""}`,a=/(?:^|\s)--effort(?:\s|,|<)/.test(s);return h.set(e,a),a}catch{return h.set(e,!1),!1}}const y=64*1024;function U(n){const e=$(n);return e.length>y?`${e.slice(0,y)}
3
+ \u2026[truncated]`:e}function $(n){return typeof n=="string"?n:Array.isArray(n)?n.map(e=>{if(typeof e=="string")return e;if(typeof e!="object"||e===null)return"";const t=e;return typeof t.text=="string"?t.text:t.type==="image"?"[image]":""}).filter(Boolean).join(`
4
+ `):""}class q extends E{options;type="claude";get recoveryCapabilities(){return{inspectTerminal:!1,reattachRun:!1,resumeRun:!1,resumeSession:!0}}process=null;agentSessionId=null;sessionId=null;workDir=null;seq=0;runId="";hasEmittedText=!1;toolNames=new Map;terminalState="open";authenticationRetrying=!1;pendingSuccess=null;persistNativeSession=!0;managedAgentPolicy=null;constructor(e={}){super(),this.options=e}externalChannel=null;shennianSessionId=null;extraEnv={};configure(e){this.shennianSessionId=e.sessionId??null,this.externalChannel=e.externalChannel??null,this.extraEnv=e.env??{},"managedAgentPolicy"in e&&(this.managedAgentPolicy=e.managedAgentPolicy??null),this.managedAgentPolicy&&(this.workDir=this.managedAgentPolicy.adapterPolicy.workDir)}async start(e,t,s,a){this.sessionId=e,this.workDir=this.managedAgentPolicy?.adapterPolicy.workDir??t,this.seq=0,this.persistNativeSession=a?.persistNativeSession!==!1,s&&(this.agentSessionId=s)}async send(e,t,s,a,l,r){if(r?.source==="room_activation"&&!this.managedAgentPolicy)throw new Error("managed_agent_policy_missing");await this.killProcess(),this.runId=f(),this.resetRunState();const i=["-p",e,"--output-format","stream-json","--verbose",...this.buildManagedPermissionConfig()?.args??[]];this.persistNativeSession||i.push("--no-session-persistence");const u=this.options.systemPrompt??g(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0,l);u&&i.push("--append-system-prompt",u),this.options.hidden&&i.push("--name","Shennian Manager Substrate"),(!this.managedAgentPolicy||c(this.managedAgentPolicy))&&process.getuid?.()!==0&&i.push("--dangerously-skip-permissions"),i.push("--model",M(t));const d=D(s);d&&F()&&i.push("--effort",d),this.agentSessionId&&i.push("--resume",this.agentSessionId),this.spawnAndParse(i)}async resume(e){await this.killProcess(),this.agentSessionId=e,this.runId=f(),this.resetRunState();const t=["--resume",e,"--output-format","stream-json","--verbose",...this.buildManagedPermissionConfig()?.args??[]],s=this.options.systemPrompt??g(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0);s&&t.push("--append-system-prompt",s),this.options.hidden&&t.push("--name","Shennian Manager Substrate"),(!this.managedAgentPolicy||c(this.managedAgentPolicy))&&process.getuid?.()!==0&&t.push("--dangerously-skip-permissions"),this.spawnAndParse(t)}async stop(){await this.killProcess()}spawnAndParse(e){const t=m("claude");if(!t){this.emit("error",C(this.workDir,'Command "claude" not found. Is Claude Code CLI installed?'));return}const s=v(t,e,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:this.buildProcessEnv()});this.process=s,S({input:s.stdout}).on("line",r=>{if(r.trim())try{const i=JSON.parse(r);this.handleStreamEvent(i)}catch{}});let l="";s.stderr?.on("data",r=>{const i=r.toString();if(l+=i,this.terminalState==="open")for(const u of i.split(`
5
+ `)){const d=u.trim();L(d)&&this.emitEvent({state:"delta",text:d+`
6
+ `})}}),s.on("close",r=>{this.process===s&&(this.process=null,this.handleProcessClose(r,l))}),s.on("error",r=>{this.process===s&&(this.process=null,r.code==="ENOENT"?this.emit("error",new Error('Command "claude" not found. Is Claude Code CLI installed?')):this.emit("error",r))})}buildManagedPermissionConfig(){const e=this.managedAgentPolicy;if(!e||c(e))return null;const t=z();return N(A(e),e.adapterPolicy.workDir,{internalReadPaths:t.readPaths,internalUnixSockets:t.unixSockets,shellSubprocessPolicy:e.environmentPolicy.shellSubprocess})}buildProcessEnv(){return this.managedAgentPolicy?c(this.managedAgentPolicy)?w({NO_COLOR:"1",...this.extraEnv}):k({agentType:"claude",providerEnv:this.extraEnv,sessionEnv:this.extraEnv,runtimeEnv:{NO_COLOR:"1"}}):I(this.extraEnv)}handleStreamEvent(e){if(e.type==="system"&&e.subtype==="init"&&e.session_id){this.agentSessionId=e.session_id,this.emitEvent({state:"start",agentSessionId:this.agentSessionId});return}if(e.type==="system"&&e.subtype==="api_retry"&&e.error==="authentication_failed"){this.authenticationRetrying=!0,this.emitEvent({state:"heartbeat",runPhase:"thinking",errorCode:"auth_retrying",message:"Claude authentication is retrying."});return}if(e.type==="assistant"){if(this.authenticationRetrying=!1,e.message?.content){for(const t of e.message.content)if(t.type==="text"&&t.text){const s=this.hasEmittedText?`
5
7
 
6
- `:"";this.emitEvent({state:"delta",text:s+t.text}),this.hasEmittedText=!0}else t.type==="thinking"&&t.thinking?this.emitEvent({state:"delta",text:t.thinking,thinking:!0}):t.type==="tool_use"&&this.emitEvent({state:"tool-call",name:t.name,args:t.input});return}if(e.subtype==="text"&&e.text){const t=this.hasEmittedText?`
8
+ `:"";this.emitEvent({state:"delta",text:s+t.text}),this.hasEmittedText=!0}else t.type==="thinking"&&t.thinking?this.emitEvent({state:"delta",text:t.thinking,thinking:!0}):t.type==="tool_use"&&(t.id&&t.name&&this.toolNames.set(t.id,t.name),this.emitEvent({state:"tool-call",name:t.name,args:t.input,...t.id?{toolCallId:t.id}:{}}));return}if(e.subtype==="text"&&e.text){const t=this.hasEmittedText?`
7
9
 
8
- `:"";this.emitEvent({state:"delta",text:t+e.text}),this.hasEmittedText=!0}else e.subtype==="thinking"&&e.thinking?this.emitEvent({state:"delta",text:e.thinking,thinking:!0}):e.subtype==="tool_use"&&this.emitEvent({state:"tool-call",name:e.name,args:e.input});return}if(e.type==="result")if(e.subtype==="tool_result"){const t=typeof e.content=="string"?e.content:JSON.stringify(e.content);this.emitEvent({state:"tool-result",name:e.name,result:t})}else if(e.subtype==="success"){e.session_id&&(this.agentSessionId=e.session_id);const t=typeof e.result=="string"?e.result:"";!this.hasEmittedText&&t.trim()&&(this.emitEvent({state:"delta",text:t}),this.hasEmittedText=!0);const s=e.usage??e.message?.usage;this.pendingSuccess={agentSessionId:this.agentSessionId??void 0,usage:s?{inputTokens:s.input_tokens,outputTokens:s.output_tokens}:void 0}}else e.subtype==="error"&&this.emitErrorIfOpen({state:"error",message:e.error??e.result??"unknown error",...this.authenticationRetrying?{errorCode:"auth_required"}:{}})}handleProcessClose(e,t){if(e!==0&&e!==null){const s=t.trim()||`claude exited with code ${e}`;this.emitErrorIfOpen({state:"error",message:s,...this.authenticationRetrying?{errorCode:"auth_required"}:{}});return}if(!this.hasEmittedText){this.emitErrorIfOpen({state:"error",message:"Claude completed without response text"});return}this.emitFinalIfOpen({state:"final",agentSessionId:this.pendingSuccess?.agentSessionId??this.agentSessionId??void 0,usage:this.pendingSuccess?.usage})}emitFinalIfOpen(e){this.terminalState==="open"&&(this.terminalState="final",this.emitEvent(e))}emitErrorIfOpen(e){this.terminalState==="open"&&(this.terminalState="error",this.emitEvent(e))}resetRunState(){this.seq=0,this.hasEmittedText=!1,this.terminalState="open",this.authenticationRetrying=!1,this.pendingSuccess=null}emitEvent(e){const t={...e,runId:this.runId,seq:this.seq++};this.emit("agentEvent",t)}async killProcess(){const e=this.process;e&&(this.process=null,e.kill("SIGTERM"),await new Promise(t=>{e.on("close",t),setTimeout(()=>{e.kill("SIGKILL"),t()},3e3)}))}}function L(){const n=A(),e=[n.secretFile],t=n.transport==="unix_socket"?[n.endpoint]:[];n.transport==="unix_socket"&&e.push(n.endpoint);const s=m("pi");return s?.path&&e.push(...U(s.path)),{readPaths:[...new Set(e)].sort(),unixSockets:[...new Set(t)].sort()}}function U(n){const e=o.normalize(n.trim());if(!e||!o.isAbsolute(e))return[];const t=[e];try{const s=p.realpathSync(e);t.push(s,o.dirname(s),o.dirname(o.dirname(s)));let a=o.dirname(s);for(let u=0;u<8;u+=1){const r=o.join(a,"package.json");try{if(JSON.parse(p.readFileSync(r,"utf8")).name==="shennian"){t.push(a);break}}catch{}const i=o.dirname(a);if(i===a)break;a=i}}catch{}return[...new Set(t)].sort()}E("claude",()=>new F);export{F as ClaudeAdapter,T as normalizeClaudeModelId,O as normalizeClaudeReasoningEffort,W as resetClaudeCapabilityCacheForTests,L as resolveClaudeManagedInternalAccess,U as resolveClaudeShennianCliReadPaths,N as shouldForwardClaudeStderrLine,D as supportsClaudeReasoningEffort};
10
+ `:"";this.emitEvent({state:"delta",text:t+e.text}),this.hasEmittedText=!0}else e.subtype==="thinking"&&e.thinking?this.emitEvent({state:"delta",text:e.thinking,thinking:!0}):e.subtype==="tool_use"&&this.emitEvent({state:"tool-call",name:e.name,args:e.input});return}if(e.type==="user"){for(const t of e.message?.content??[])t.type!=="tool_result"||!t.tool_use_id||this.emitEvent({state:"tool-result",name:this.toolNames.get(t.tool_use_id),toolCallId:t.tool_use_id,toolStatus:t.is_error===!0?"failed":"completed",result:U(t.content)});return}if(e.type==="result")if(e.subtype==="tool_result"){const t=typeof e.content=="string"?e.content:JSON.stringify(e.content);this.emitEvent({state:"tool-result",name:e.name,result:t})}else if(e.subtype==="success"){e.session_id&&(this.agentSessionId=e.session_id);const t=typeof e.result=="string"?e.result:"";!this.hasEmittedText&&t.trim()&&(this.emitEvent({state:"delta",text:t}),this.hasEmittedText=!0);const s=e.usage??e.message?.usage;this.pendingSuccess={agentSessionId:this.agentSessionId??void 0,usage:s?{inputTokens:s.input_tokens,outputTokens:s.output_tokens}:void 0}}else e.subtype==="error"&&this.emitErrorIfOpen({state:"error",message:e.error??e.result??"unknown error",...this.authenticationRetrying?{errorCode:"auth_required"}:{}})}handleProcessClose(e,t){if(e!==0&&e!==null){const s=t.trim()||`claude exited with code ${e}`;this.emitErrorIfOpen({state:"error",message:s,...this.authenticationRetrying?{errorCode:"auth_required"}:{}});return}if(!this.hasEmittedText){this.emitErrorIfOpen({state:"error",message:"Claude completed without response text"});return}this.emitFinalIfOpen({state:"final",agentSessionId:this.pendingSuccess?.agentSessionId??this.agentSessionId??void 0,usage:this.pendingSuccess?.usage})}emitFinalIfOpen(e){this.terminalState==="open"&&(this.terminalState="final",this.emitEvent(e))}emitErrorIfOpen(e){this.terminalState==="open"&&(this.terminalState="error",this.emitEvent(e))}resetRunState(){this.seq=0,this.hasEmittedText=!1,this.toolNames.clear(),this.terminalState="open",this.authenticationRetrying=!1,this.pendingSuccess=null}emitEvent(e){const t={...e,runId:this.runId,seq:this.seq++};this.emit("agentEvent",t)}async killProcess(){const e=this.process;e&&(this.process=null,e.kill("SIGTERM"),await new Promise(t=>{e.on("close",t),setTimeout(()=>{e.kill("SIGKILL"),t()},3e3)}))}}function z(){const n=R(),e=[n.secretFile],t=n.transport==="unix_socket"?[n.endpoint]:[];n.transport==="unix_socket"&&e.push(n.endpoint);const s=m("pi");return s?.path&&e.push(...G(s.path)),{readPaths:[...new Set(e)].sort(),unixSockets:[...new Set(t)].sort()}}function G(n){const e=o.normalize(n.trim());if(!e||!o.isAbsolute(e))return[];const t=[e];try{const s=p.realpathSync(e);t.push(s,o.dirname(s),o.dirname(o.dirname(s)));let a=o.dirname(s);for(let l=0;l<8;l+=1){const r=o.join(a,"package.json");try{if(JSON.parse(p.readFileSync(r,"utf8")).name==="shennian"){t.push(a);break}}catch{}const i=o.dirname(a);if(i===a)break;a=i}}catch{}return[...new Set(t)].sort()}x("claude",()=>new q);export{q as ClaudeAdapter,M as normalizeClaudeModelId,D as normalizeClaudeReasoningEffort,te as resetClaudeCapabilityCacheForTests,z as resolveClaudeManagedInternalAccess,G as resolveClaudeShennianCliReadPaths,L as shouldForwardClaudeStderrLine,F as supportsClaudeReasoningEffort};
@@ -1,2 +1,2 @@
1
- import{CODEX_DESKTOP_SEND_UNAVAILABLE as x}from"@shennian/wire";import{createHash as v,randomUUID as R}from"node:crypto";import I from"node:path";import{createInterface as y}from"node:readline";import{buildAgentProcessEnv as A,buildManagedAgentProcessEnv as M,buildManagedNativeFullProcessEnv as N}from"../agent-env.js";import{isCodexThreadTailInterrupted as O}from"../native-fusion/codex-files.js";import{isManagedAgentNativeFull as C,resolveManagedAgentAdapterEnforcement as b}from"../security/managed-agent-policy.js";import{registerManagedAgentRuntimeSecurity as k}from"../security/managed-agent-runtime.js";import{registerAgent as D}from"./adapter.js";import{CODEX_MANAGED_RUNTIME_SECURITY as F,assertCodexManagedPermissionProfile as S,compileCodexManagedPermissions as j,extractCodexMcpServerNames as L}from"./codex-managed-permissions.js";import{CODEX_MANAGED_MANAGER_DYNAMIC_TOOLS as q,CODEX_MANAGED_ROOM_DYNAMIC_TOOLS as U}from"./codex-managed-room-tools.js";import{CODEX_APP_SERVER_CLIENT_INFO as B,isCodexUnsupportedEffortError as z,isMissingCodexRolloutError as E,normalizeCodexModelId as g,normalizeCodexReasoningEffort as W,normalizeCodexStderr as G}from"./codex-utils.js";import{resolveBuiltinCommand as f,spawnAgentCommand as w}from"./command-spec.js";import{ensurePlatformInstructionsFile as H}from"./platform-instructions.js";import{buildCodexQueueArgs as xe,buildCodexQueuedText as ve,isCodexActiveWriterError as Ie,isCodexExcludeTurnsUnsupportedError as ye,isCodexPaginatedHistoryUnsupportedError as Ce,isCodexProjectApiUnsupportedError as Se,selectCodexProjectIdForWorkDir as Ee}from"./codex-protocol.js";import{isCodexUnsupportedEffortError as _e,isMissingCodexRolloutError as Pe,normalizeCodexModelId as Re,normalizeCodexReasoningEffort as Ae}from"./codex-utils.js";import{buildCodexQueueArgs as $,buildCodexTextInput as T,isCodexActiveWriterError as _,isCodexExcludeTurnsUnsupportedError as J,isCodexPaginatedHistoryUnsupportedError as V,isCodexProjectApiUnsupportedError as X,selectCodexProjectIdForWorkDir as Q}from"./codex-protocol.js";import{CodexRuntime as Y}from"./codex-runtime.js";k("codex",F);class K extends Y{get supportsActiveInput(){return!0}async injectActiveInput(e){const r=this.agentSessionId,i=this.activeTurnId;if(!r||!i||!this.process)throw new Error("codex_active_turn_unavailable");const s=await this.sendRpc("turn/steer",{threadId:r,expectedTurnId:i,input:[T(e.text,e.attachments)],...e.clientMessageId?{clientUserMessageId:e.clientMessageId}:{}});if(s.turnId&&s.turnId!==i)throw new Error("codex_active_turn_changed")}type="codex";get recoveryCapabilities(){return{inspectTerminal:!1,reattachRun:!1,resumeRun:!1,resumeSession:!0}}configure(e){const r=this.configurationFingerprint();this.shennianSessionId=e.sessionId??null,this.externalChannel=e.externalChannel??null,this.extraEnv=e.env??{},"managedAgentPolicy"in e&&(this.managedAgentPolicy=e.managedAgentPolicy??null),("managedRoomContextToken"in e||"managedRoomExecutor"in e)&&(this.managedRoomTools.deactivateTurn(),this.configuredManagedRoomContextToken=e.managedRoomContextToken?.trim()||null,this.configuredManagedRoomExecutor=e.managedRoomExecutor??null),this.managedAgentPolicy&&(this.workDir=this.managedAgentPolicy.adapterPolicy.workDir);const i=this.configurationFingerprint();r!==i&&this.process&&(this.configurationRestartRequired=!0)}configurationFingerprint(){const e=Object.keys(this.extraEnv).sort().map(r=>[r,this.extraEnv[r]??null]);return v("sha256").update(JSON.stringify({sessionId:this.shennianSessionId,externalChannel:this.externalChannel,env:e,managedAgentPolicy:this.managedAgentPolicy})).digest("hex")}buildProcessEnv(e={}){if(!this.managedAgentPolicy)return A({...e,...this.extraEnv});if(C(this.managedAgentPolicy))return N({...e,...this.extraEnv});const r=Object.fromEntries(Object.entries(this.extraEnv).filter(([i])=>i!=="SHENNIAN_MANAGED_ROOM_CONTEXT"&&i!=="SHENNIAN_MANAGED_ROOM_IPC_ROOT"));return M({agentType:"codex",providerEnv:r,sessionEnv:r,runtimeEnv:e})}async start(e,r,i,s){this.shennianSessionId=e,this.workDir=this.managedAgentPolicy?.adapterPolicy.workDir??r,this.seq=0,this.persistNativeSession=s?.persistNativeSession!==!1,this.nativeSessionVisibility=s?.nativeSessionVisibility??"user",i&&(this.agentSessionId=i),this.notifyNativeSession()}async prepareSend(e,r,i,s,n,t){const o=n?.trim()??"";if(o!==this.agentSystemPrompt&&(this.agentSystemPrompt=o,this.process&&await this.killProcess(!0)),!(!this.agentSessionId||this.activeTurnId)){this.preparedExternalOwnerThreadId=null;try{await this.ensureAppServer(g(r))}catch(a){if(!_(a))throw a;if(t?.source==="room_activation"||t?.source==="managed_private")throw new Error("codex_managed_thread_owned_externally",{cause:a});if(this.isThreadTailInterrupted(this.agentSessionId))throw new Error(x,{cause:a});this.preparedExternalOwnerThreadId=this.agentSessionId}}}async send(e,r,i,s,n,t){if((t?.source==="room_activation"||t?.source==="managed_private")&&!this.managedAgentPolicy)throw new Error("managed_agent_policy_missing");if((t?.source==="room_activation"||t?.source==="managed_private")&&(!this.configuredManagedRoomContextToken||!this.configuredManagedRoomExecutor))throw new Error("codex_managed_room_tool_context_unavailable");const o=t?.source==="room_activation"||t?.source==="managed_private";this.managedRoomCapabilityExpectedForTurn=!1,this.activeTurnId&&(await this.interruptActiveTurn().catch(()=>{}),await this.killProcess(!0)),this.configurationRestartRequired&&this.process&&await this.killProcess(!0),this.configurationRestartRequired=!1;const a=g(r),d=W(i),c=n?.trim()??"";if(c!==this.agentSystemPrompt&&(this.agentSystemPrompt=c,this.process&&await this.killProcess(!0)),(t?.source==="room_activation"||t?.source==="managed_private")&&this.managedRoomTools.configure(this.configuredManagedRoomContextToken,this.configuredManagedRoomExecutor),this.runId=R(),this.seq=0,this.resetRunState(),this.agentSessionId&&this.preparedExternalOwnerThreadId===this.agentSessionId)return this.preparedExternalOwnerThreadId=null,{deliveryMode:"external_owner_queue",queuedSubmissionId:await this.enqueueForExternalOwner(this.agentSessionId,e,s)};this.managedRoomCapabilityExpectedForTurn=o;try{await this.ensureAppServer(a)}catch(h){if(!this.agentSessionId||!_(h))throw h;if(t?.source==="room_activation"||t?.source==="managed_private")throw new Error("codex_managed_thread_owned_externally",{cause:h});if(this.isThreadTailInterrupted(this.agentSessionId))throw new Error(x,{cause:h});return{deliveryMode:"external_owner_queue",queuedSubmissionId:await this.enqueueForExternalOwner(this.agentSessionId,e,s)}}const l=this.agentSessionId;if(!l)throw new Error("codex app-server did not create a thread");this.emitEvent({state:"start",agentSessionId:l}),this.managedTurnReplay=this.managedPermissionConfig?{text:e,modelId:a,reasoningEffort:d,attachments:s,recoveryCount:0}:null;const u=await this.startTurnWithRecovery(l,e,a,d,s),m=this.agentSessionId??l;if(this.activeTurnId=u.turn?.id??null,this.managedRoomTurnBindingFailed)throw await this.killProcess(),new Error("codex_managed_room_turn_binding_failed");if(this.managedRoomCapabilityExpectedForTurn&&this.managedRoomToolThreadId===m&&this.activeTurnId&&!this.managedRoomTools.bindTurn(m,this.activeTurnId))throw await this.killProcess(),new Error("codex_managed_room_turn_binding_failed");return{deliveryMode:"direct"}}isThreadTailInterrupted(e){return this.options.isThreadTailInterrupted?.(e)??O(e)}async enqueueForExternalOwner(e,r,i){if(this.options.hidden||this.nativeSessionVisibility==="internal")throw new Error("codex_managed_thread_owned_externally");const s=f("codex");if(!s)throw new Error('Command "codex" not found. Is OpenAI Codex CLI installed?');const n=$(e,r,i),t=w(s,n,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:this.buildProcessEnv({NO_COLOR:"1"})});return await new Promise((o,a)=>{let d="",c="",l=!1;const u=(h,p)=>{l||(l=!0,clearTimeout(m),h?a(h):o(p))},m=setTimeout(()=>{t.kill("SIGTERM"),u(new Error("Codex Desktop message queue timed out"))},6e4);m.unref?.(),t.stdout?.on("data",h=>{d+=h.toString()}),t.stderr?.on("data",h=>{c+=h.toString()}),t.once("error",h=>u(h)),t.once("close",h=>{const p=`${d}
2
- ${c}`.trim();if(h!==0){u(new Error(p||`codex queue exited with code ${h??"unknown"}`));return}const P=p.match(/Queued message\s+([^\s]+)\s+for thread/i)?.[1];u(void 0,P)})})}async resume(e){await this.killProcess(),this.agentSessionId=e,this.resetTextState()}async setTitle(e,r,i){const s=e.trim(),n=r.replace(/\s+/g," ").trim();!s||!n||(this.agentSessionId=s,this.notifyNativeSession(),i?.trim()&&(this.workDir=i),await this.ensureAppServer(),await this.sendRpc("thread/name/set",{threadId:s,name:n}))}async stop(){this.managedRoomTools.deactivateTurn(),await this.interruptActiveTurn().catch(()=>{}),await this.killProcess()}async getStatus(){const e=this.agentSessionId,r=this.activeTurnId;if(!e||!this.process)return{active:!1,runId:r,runPhase:null,canStop:!1};let i=null;try{i=(await this.sendRpc("thread/read",{threadId:e,includeTurns:!1},5e3)).thread?.status??null}catch{}const s=i?.type==="active"||!!r;return{active:s,runId:r,runPhase:s?this.mapThreadStatusToRunPhase(i):null,canStop:!!(s&&r&&this.process)}}spawnCodex(e){const r=f("codex");if(!r){this.emit("error",new Error('Command "codex" not found. Is OpenAI Codex CLI installed?'));return}const i=w(r,e,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:this.buildProcessEnv()});this.process=i,y({input:i.stdout}).on("line",t=>{if(t.trim())try{const o=JSON.parse(t);this.handleStreamEvent(o)}catch{this.emitEvent({state:"delta",text:t})}});let n="";i.stderr?.on("data",t=>{n+=t.toString()}),i.on("close",t=>{this.process===i&&(this.process=null,this.clearForceCloseTimer(),this.handleProcessClose(t,n))}),i.on("error",t=>{this.process===i&&(this.process=null,t.code==="ENOENT"?this.emit("error",new Error('Command "codex" not found. Is OpenAI Codex CLI installed?')):this.emit("error",t))})}spawnAppServer(){const e=f("codex");if(!e){this.emit("error",new Error('Command "codex" not found. Is OpenAI Codex CLI installed?'));return}const r=["app-server","--listen","stdio://"],i=this.options.modelInstructionsFile??H(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0,this.agentSystemPrompt);i&&r.push("-c",`model_instructions_file=${JSON.stringify(i)}`);const s=w(e,r,{cwd:this.workDir??void 0,stdio:["pipe","pipe","pipe"],env:this.buildProcessEnv({NO_COLOR:"1"})});this.process=s,this.stderrBuf="",this.appServerStartupError=null,y({input:s.stdout}).on("line",t=>{if(!t.trim())return;let o;try{o=JSON.parse(t)}catch{this.handleAppServerNonJsonStdout(t);return}this.handleAppServerMessage(o)}),s.stderr?.on("data",t=>{this.stderrBuf+=t.toString()}),s.on("close",t=>{if(this.process!==s)return;const o=this.activeTurnId!=null;this.process=null,this.appServerReady=null,this.activeTurnId=null,this.managedRoomTools.reset(),this.clearConfiguredManagedRoomContext(),this.rejectAllPending(new Error(G(this.stderrBuf)||`codex app-server exited with code ${t}`)),this.terminalState==="open"&&o&&this.handleProcessClose(t,this.stderrBuf)}),s.on("error",t=>{this.process===s&&(this.process=null,this.managedRoomTools.reset(),this.clearConfiguredManagedRoomContext(),this.rejectAllPending(t),t.code==="ENOENT"?this.emit("error",new Error('Command "codex" not found. Is OpenAI Codex CLI installed?')):this.emit("error",t))})}async ensureAppServer(e){return this.appServerReady?this.appServerReady:(this.spawnAppServer(),this.appServerReady=this.initializeAppServer(e).catch(async r=>{throw this.appServerReady=null,await this.killProcess(),r}),this.appServerReady)}async initializeAppServer(e){const r=g(e);await this.sendRpc("initialize",{clientInfo:B,capabilities:{experimentalApi:!0}}),this.managedPermissionConfig=this.managedAgentPolicy&&!C(this.managedAgentPolicy)?await this.buildManagedPermissionConfig():null;const i=!!(this.configuredManagedRoomContextToken||this.configuredManagedRoomExecutor);if(this.managedAgentPolicy&&i&&!this.managedRoomTools.isConfigured()&&(this.managedRoomTools.configure(this.configuredManagedRoomContextToken,this.configuredManagedRoomExecutor),!this.managedRoomTools.isConfigured()))throw new Error("codex_managed_room_tool_context_unavailable");if(this.agentSessionId&&this.managedAgentPolicy&&i&&this.agentSessionId!==this.managedRoomToolThreadId){if(!this.managedRoomTools.isConfigured())throw new Error("codex_managed_room_tool_context_unavailable");this.agentSessionId=null}if(this.agentSessionId){const d={threadId:this.agentSessionId,cwd:this.workDir,approvalPolicy:"never",...this.managedPermissionConfig?{config:this.managedPermissionConfig.threadConfig}:{sandbox:"danger-full-access"},persistExtendedHistory:!0,...r?{model:r}:{}};let c;try{c=await this.sendRpc("thread/resume",{...d,excludeTurns:!0})}catch(l){if(!J(l))throw l;c=await this.sendRpc("thread/resume",d)}this.agentSessionId=c.thread?.id??this.agentSessionId,this.notifyNativeSession(),this.managedPermissionConfig&&S(c,this.managedPermissionConfig.profileId),this.managedAgentPolicy&&i&&(this.managedRoomTools.bindThread(this.agentSessionId),this.managedRoomToolThreadId=this.agentSessionId);return}const s=this.options.hidden||this.nativeSessionVisibility==="internal"||!this.persistNativeSession,n=s?void 0:await this.resolveCodexProjectId(),t={cwd:this.workDir,approvalPolicy:"never",...this.managedPermissionConfig?{config:this.managedPermissionConfig.threadConfig}:{sandbox:"danger-full-access"},serviceName:"Shennian",threadSource:s?"shennian_internal":"user",experimentalRawEvents:!1,persistExtendedHistory:!0,...this.managedAgentPolicy&&i?{dynamicTools:this.extraEnv.SHENNIAN_MANAGER_SESSION_ID?q:U}:{},...n?{projectId:n}:{},...r?{model:r}:{}};let o;if(s&&!this.managedPermissionConfig)o=await this.sendRpc("thread/start",t);else try{o=await this.sendRpc("thread/start",{...t,historyMode:"paginated"})}catch(d){throw V(d)?new Error("\u5F53\u524D Codex CLI \u4E0D\u652F\u6301\u521B\u5EFA\u53EF\u5728 Codex Desktop \u4E2D\u7EE7\u7EED\u7684\u65B0\u4F1A\u8BDD\uFF0C\u8BF7\u624B\u52A8\u5347\u7EA7 Codex CLI \u540E\u91CD\u8BD5\u3002\u795E\u5FF5\u4E0D\u4F1A\u81EA\u52A8\u5347\u7EA7\uFF0C\u4E5F\u4E0D\u4F1A\u964D\u7EA7\u521B\u5EFA\u4E0D\u53EF\u89C1\u7684 legacy \u4F1A\u8BDD\u3002",{cause:d}):d}const a=o.thread?.id;if(!a)throw new Error("codex app-server thread/start returned no thread id");this.managedPermissionConfig&&S(o,this.managedPermissionConfig.profileId),this.managedAgentPolicy&&i&&(this.managedRoomTools.bindThread(a),this.managedRoomToolThreadId=a),this.agentSessionId=a,this.notifyNativeSession()}notifyNativeSession(){this.agentSessionId&&this.emit("nativeSession","codex",this.agentSessionId)}async buildManagedPermissionConfig(){const e=this.managedAgentPolicy;if(!e)throw new Error("managed_agent_policy_missing");const r=e.adapterPolicy.externalCapabilities.mcp?[]:L(await this.sendRpc("config/read",{cwd:e.adapterPolicy.workDir}));return j(b(e),e.adapterPolicy.workDir,{configuredMcpServerNames:r,shellSubprocessPolicy:e.environmentPolicy.shellSubprocess})}async resolveCodexProjectId(){const e=this.workDir?.trim();if(e)try{const r=[];let i;do{const d=await this.sendRpc("project/list",{limit:100,...i?{cursor:i}:{}});r.push(...d.data??[]),i=d.nextCursor}while(i);const s=Q(r,e);if(s)return s;const n=I.resolve(e),t=`shennian-project-${v("sha256").update(n).digest("hex")}`,a=(await this.sendRpc("project/create",{idempotencyKey:t,name:I.basename(n)||n,roots:[{path:n}],metadata:{createdBy:"Shennian"}})).project?.id;if(!a)throw new Error("codex app-server project/create returned no project id");return a}catch(r){throw X(r)?new Error("\u5F53\u524D Codex CLI \u4E0D\u652F\u6301\u521B\u5EFA\u53EF\u5F52\u5C5E\u5230 Codex Desktop \u9879\u76EE\u7684\u65B0\u4F1A\u8BDD\uFF0C\u8BF7\u624B\u52A8\u5347\u7EA7 Codex CLI \u540E\u91CD\u8BD5\u3002\u795E\u5FF5\u4E0D\u4F1A\u81EA\u52A8\u5347\u7EA7\uFF0C\u4E5F\u4E0D\u4F1A\u76F4\u63A5\u4FEE\u6539 Codex Desktop \u7684\u79C1\u6709\u4FA7\u680F\u7D22\u5F15\u3002",{cause:r}):r}}async startTurnWithRecovery(e,r,i,s,n){try{return await this.startTurn(e,r,i,s,n)}catch(t){if(!E(t))throw t;if(this.managedAgentPolicy||this.managedPermissionConfig){this.logManagedThreadLifecycle("rollout.missing",{threadId:e,recovery:"recreate"}),await this.killProcess(!0),this.agentSessionId=null,this.managedRoomToolThreadId=null,await this.ensureAppServer(i);const o=this.agentSessionId;if(!o)throw new Error("codex app-server did not recreate the managed thread",{cause:t});return this.logManagedThreadLifecycle("thread.recreated",{previousThreadId:e,threadId:o}),this.emitEvent({state:"start",agentSessionId:o}),await this.startFreshManagedTurnWithReadinessRetry(o,r,i,s,n)}return await this.killProcess(),await this.ensureAppServer(i),await this.startTurn(e,r,i,s,n)}}async startFreshManagedTurnWithReadinessRetry(e,r,i,s,n){const t=[0,100,300,1e3];let o;for(let a=0;a<t.length;a+=1){const d=t[a];d>0&&await new Promise(c=>setTimeout(c,d));try{const c=await this.startTurn(e,r,i,s,n);return a>0&&this.logManagedThreadLifecycle("rollout.ready",{threadId:e,attempt:a+1}),c}catch(c){if(o=c,!E(c)||a===t.length-1)throw c;this.logManagedThreadLifecycle("rollout.retry",{threadId:e,attempt:a+2,delayMs:t[a+1]})}}throw o}logManagedThreadLifecycle(e,r){console.error(`[codex.managed] ${JSON.stringify({event:e,...r})}`)}async startTurn(e,r,i,s,n){try{return await this.sendRpc("turn/start",{threadId:e,input:[T(r,n)],approvalPolicy:"never",...this.managedPermissionConfig?{}:{sandboxPolicy:{type:"dangerFullAccess"}},...i?{model:i}:{},...s?{effort:s}:{}})}catch(t){throw s&&z(t)?new Error(`Codex app-server does not accept reasoning effort "${s}" for this turn. Refresh models or upgrade Codex CLI, then retry.`,{cause:t}):t}}async interruptActiveTurn(){const e=this.agentSessionId,r=this.activeTurnId;this.activeTurnId=null,this.managedRoomTools.deactivateTurn(),!(!e||!r||!this.process)&&await this.sendRpc("turn/interrupt",{threadId:e,turnId:r},5e3)}}D("codex",()=>new K);export{K as CodexAdapter,xe as buildCodexQueueArgs,ve as buildCodexQueuedText,Ie as isCodexActiveWriterError,ye as isCodexExcludeTurnsUnsupportedError,Ce as isCodexPaginatedHistoryUnsupportedError,Se as isCodexProjectApiUnsupportedError,_e as isCodexUnsupportedEffortError,Pe as isMissingCodexRolloutError,Re as normalizeCodexModelId,Ae as normalizeCodexReasoningEffort,Ee as selectCodexProjectIdForWorkDir};
1
+ import{CODEX_DESKTOP_SEND_UNAVAILABLE as v}from"@shennian/wire";import{createHash as x,randomUUID as A}from"node:crypto";import y from"node:path";import{createInterface as I}from"node:readline";import{buildAgentProcessEnv as M,buildManagedAgentProcessEnv as b,buildManagedNativeFullProcessEnv as N}from"../agent-env.js";import{isCodexThreadTailInterrupted as O}from"../native-fusion/codex-files.js";import{isManagedAgentNativeFull as S,resolveManagedAgentAdapterEnforcement as k}from"../security/managed-agent-policy.js";import{registerManagedAgentRuntimeSecurity as D}from"../security/managed-agent-runtime.js";import{registerAgent as L}from"./adapter.js";import{CODEX_MANAGED_RUNTIME_SECURITY as F,assertCodexManagedPermissionProfile as C,compileCodexManagedPermissions as j,extractCodexMcpServerNames as q}from"./codex-managed-permissions.js";import{CODEX_MANAGED_MANAGER_DYNAMIC_TOOLS as U,CODEX_MANAGED_ROOM_DYNAMIC_TOOLS as B}from"./codex-managed-room-tools.js";import{CODEX_APP_SERVER_CLIENT_INFO as W,isCodexUnsupportedEffortError as z,isMissingCodexRolloutError as E,normalizeCodexModelId as g,normalizeCodexReasoningEffort as G,normalizeCodexStderr as H}from"./codex-utils.js";import{resolveBuiltinCommand as $,spawnAgentCommand as f}from"./command-spec.js";import{spawnEnoentError as T}from"./spawn-errors.js";const w="codex_command_unavailable: \u8BF7\u786E\u8BA4 Codex CLI \u8DEF\u5F84\u5E76\u5237\u65B0 AI \u5217\u8868\u3002";import{ensurePlatformInstructionsFile as V}from"./platform-instructions.js";import{buildCodexQueueArgs as Ie,buildCodexQueuedText as Se,isCodexActiveWriterError as Ce,isCodexExcludeTurnsUnsupportedError as Ee,isCodexPaginatedHistoryUnsupportedError as Te,isCodexProjectApiUnsupportedError as _e,selectCodexProjectIdForWorkDir as Pe}from"./codex-protocol.js";import{isCodexUnsupportedEffortError as Ae,isMissingCodexRolloutError as Me,normalizeCodexModelId as be,normalizeCodexReasoningEffort as Ne}from"./codex-utils.js";import{buildCodexQueueArgs as X,buildCodexTextInput as _,isCodexActiveWriterError as P,isCodexExcludeTurnsUnsupportedError as J,isCodexPaginatedHistoryUnsupportedError as Q,isCodexProjectApiUnsupportedError as Y,selectCodexProjectIdForWorkDir as K}from"./codex-protocol.js";import{CodexRuntime as Z}from"./codex-runtime.js";D("codex",F);class ee extends Z{get supportsActiveInput(){return!0}async injectActiveInput(e){const r=this.agentSessionId,i=this.activeTurnId;if(!r||!i||!this.process)throw new Error("codex_active_turn_unavailable");const s=await this.sendRpc("turn/steer",{threadId:r,expectedTurnId:i,input:[_(e.text,e.attachments)],...e.clientMessageId?{clientUserMessageId:e.clientMessageId}:{}});if(s.turnId&&s.turnId!==i)throw new Error("codex_active_turn_changed")}launchCommand=null;resolveLaunchCommand(){if(this.process&&this.launchCommand)return this.launchCommand;const e=$("codex");if(!e||process.platform==="win32"&&e.kind==="wsl-bridge")throw new Error(process.platform==="win32"?"codex_windows_runtime_unavailable: \u8BF7\u786E\u8BA4 Windows Codex CLI \u8DEF\u5F84\u5E76\u5237\u65B0 AI \u5217\u8868\uFF1B\u4E0D\u4F1A\u81EA\u52A8\u5207\u6362\u5230 WSL\uFF0C\u5F85\u53D1\u9001\u6D88\u606F\u4FDD\u7559\u3002":w);return this.launchCommand=e,e}type="codex";get recoveryCapabilities(){return{inspectTerminal:!1,reattachRun:!1,resumeRun:!1,resumeSession:!0}}configure(e){const r=this.configurationFingerprint();this.shennianSessionId=e.sessionId??null,this.externalChannel=e.externalChannel??null,this.extraEnv=e.env??{},"managedAgentPolicy"in e&&(this.managedAgentPolicy=e.managedAgentPolicy??null),("managedRoomContextToken"in e||"managedRoomExecutor"in e)&&(this.managedRoomTools.deactivateTurn(),this.configuredManagedRoomContextToken=e.managedRoomContextToken?.trim()||null,this.configuredManagedRoomExecutor=e.managedRoomExecutor??null),this.managedAgentPolicy&&(this.workDir=this.managedAgentPolicy.adapterPolicy.workDir);const i=this.configurationFingerprint();r!==i&&this.process&&(this.configurationRestartRequired=!0)}configurationFingerprint(){const e=Object.keys(this.extraEnv).sort().map(r=>[r,this.extraEnv[r]??null]);return x("sha256").update(JSON.stringify({sessionId:this.shennianSessionId,externalChannel:this.externalChannel,env:e,managedAgentPolicy:this.managedAgentPolicy})).digest("hex")}buildProcessEnv(e={}){if(!this.managedAgentPolicy)return M({...e,...this.extraEnv});if(S(this.managedAgentPolicy))return N({...e,...this.extraEnv});const r=Object.fromEntries(Object.entries(this.extraEnv).filter(([i])=>i!=="SHENNIAN_MANAGED_ROOM_CONTEXT"&&i!=="SHENNIAN_MANAGED_ROOM_IPC_ROOT"));return b({agentType:"codex",providerEnv:r,sessionEnv:r,runtimeEnv:e})}async start(e,r,i,s){this.shennianSessionId=e,this.workDir=this.managedAgentPolicy?.adapterPolicy.workDir??r,this.seq=0,this.persistNativeSession=s?.persistNativeSession!==!1,this.nativeSessionVisibility=s?.nativeSessionVisibility??"user",i&&(this.agentSessionId=i),this.notifyNativeSession()}async prepareSend(e,r,i,s,n,t){const o=n?.trim()??"";if(o!==this.agentSystemPrompt&&(this.agentSystemPrompt=o,this.process&&await this.killProcess(!0)),!this.activeTurnId){this.preparedExternalOwnerThreadId=null;try{await this.ensureAppServer(g(r))}catch(a){if(!P(a)||!this.agentSessionId)throw a;if(t?.source==="room_activation"||t?.source==="managed_private")throw new Error("codex_managed_thread_owned_externally",{cause:a});if(this.isThreadTailInterrupted(this.agentSessionId))throw new Error(v,{cause:a});this.preparedExternalOwnerThreadId=this.agentSessionId}}}async send(e,r,i,s,n,t){if((t?.source==="room_activation"||t?.source==="managed_private")&&!this.managedAgentPolicy)throw new Error("managed_agent_policy_missing");if((t?.source==="room_activation"||t?.source==="managed_private")&&(!this.configuredManagedRoomContextToken||!this.configuredManagedRoomExecutor))throw new Error("codex_managed_room_tool_context_unavailable");const o=t?.source==="room_activation"||t?.source==="managed_private";this.managedRoomCapabilityExpectedForTurn=!1,this.activeTurnId&&(await this.interruptActiveTurn().catch(()=>{}),await this.killProcess(!0)),this.configurationRestartRequired&&this.process&&await this.killProcess(!0),this.configurationRestartRequired=!1;const a=g(r),d=G(i),c=n?.trim()??"";if(c!==this.agentSystemPrompt&&(this.agentSystemPrompt=c,this.process&&await this.killProcess(!0)),(t?.source==="room_activation"||t?.source==="managed_private")&&this.managedRoomTools.configure(this.configuredManagedRoomContextToken,this.configuredManagedRoomExecutor),this.runId=A(),this.seq=0,this.resetRunState(),this.agentSessionId&&this.preparedExternalOwnerThreadId===this.agentSessionId)return this.preparedExternalOwnerThreadId=null,{deliveryMode:"external_owner_queue",queuedSubmissionId:await this.enqueueForExternalOwner(this.agentSessionId,e,s)};this.managedRoomCapabilityExpectedForTurn=o;try{await this.ensureAppServer(a)}catch(h){if(!this.agentSessionId||!P(h))throw h;if(t?.source==="room_activation"||t?.source==="managed_private")throw new Error("codex_managed_thread_owned_externally",{cause:h});if(this.isThreadTailInterrupted(this.agentSessionId))throw new Error(v,{cause:h});return{deliveryMode:"external_owner_queue",queuedSubmissionId:await this.enqueueForExternalOwner(this.agentSessionId,e,s)}}const l=this.agentSessionId;if(!l)throw new Error("codex app-server did not create a thread");this.emitEvent({state:"start",agentSessionId:l}),this.managedTurnReplay=this.managedPermissionConfig?{text:e,modelId:a,reasoningEffort:d,attachments:s,recoveryCount:0}:null;const u=await this.startTurnWithRecovery(l,e,a,d,s),m=this.agentSessionId??l;if(this.activeTurnId=u.turn?.id??null,this.managedRoomTurnBindingFailed)throw await this.killProcess(),new Error("codex_managed_room_turn_binding_failed");if(this.managedRoomCapabilityExpectedForTurn&&this.managedRoomToolThreadId===m&&this.activeTurnId&&!this.managedRoomTools.bindTurn(m,this.activeTurnId))throw await this.killProcess(),new Error("codex_managed_room_turn_binding_failed");return{deliveryMode:"direct"}}isThreadTailInterrupted(e){return this.options.isThreadTailInterrupted?.(e)??O(e)}async enqueueForExternalOwner(e,r,i){if(this.options.hidden||this.nativeSessionVisibility==="internal")throw new Error("codex_managed_thread_owned_externally");const s=this.resolveLaunchCommand(),n=X(e,r,i),t=f(s,n,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:this.buildProcessEnv({NO_COLOR:"1"})});return await new Promise((o,a)=>{let d="",c="",l=!1;const u=(h,p)=>{l||(l=!0,clearTimeout(m),h?a(h):o(p))},m=setTimeout(()=>{t.kill("SIGTERM"),u(new Error("Codex Desktop message queue timed out"))},6e4);m.unref?.(),t.stdout?.on("data",h=>{d+=h.toString()}),t.stderr?.on("data",h=>{c+=h.toString()}),t.once("error",h=>u(h)),t.once("close",h=>{const p=`${d}
2
+ ${c}`.trim();if(h!==0){u(new Error(p||`codex queue exited with code ${h??"unknown"}`));return}const R=p.match(/Queued message\s+([^\s]+)\s+for thread/i)?.[1];u(void 0,R)})})}async resume(e){await this.killProcess(),this.agentSessionId=e,this.resetTextState()}async setTitle(e,r,i){const s=e.trim(),n=r.replace(/\s+/g," ").trim();!s||!n||(this.agentSessionId=s,this.notifyNativeSession(),i?.trim()&&(this.workDir=i),await this.ensureAppServer(),await this.sendRpc("thread/name/set",{threadId:s,name:n}))}async stop(){this.managedRoomTools.deactivateTurn(),await this.interruptActiveTurn().catch(()=>{}),await this.killProcess()}async getStatus(){const e=this.agentSessionId,r=this.activeTurnId;if(!e||!this.process)return{active:!1,runId:r,runPhase:null,canStop:!1};let i=null;try{i=(await this.sendRpc("thread/read",{threadId:e,includeTurns:!1},5e3)).thread?.status??null}catch{}const s=i?.type==="active"||!!r;return{active:s,runId:r,runPhase:s?this.mapThreadStatusToRunPhase(i):null,canStop:!!(s&&r&&this.process)}}spawnCodex(e){const r=this.resolveLaunchCommand(),i=f(r,e,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:this.buildProcessEnv()});this.process=i,I({input:i.stdout}).on("line",t=>{if(t.trim())try{const o=JSON.parse(t);this.handleStreamEvent(o)}catch{this.emitEvent({state:"delta",text:t})}});let n="";i.stderr?.on("data",t=>{n+=t.toString()}),i.on("close",t=>{this.process===i&&(this.process=null,this.clearForceCloseTimer(),this.handleProcessClose(t,n))}),i.on("error",t=>{this.process===i&&(this.process=null,t.code==="ENOENT"?this.emit("error",T(this.workDir,w)):this.emit("error",t))})}spawnAppServer(){const e=this.resolveLaunchCommand(),r=["app-server","--listen","stdio://"],i=this.options.modelInstructionsFile??V(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0,this.agentSystemPrompt);i&&r.push("-c",`model_instructions_file=${JSON.stringify(i)}`);const s=f(e,r,{cwd:this.workDir??void 0,stdio:["pipe","pipe","pipe"],env:this.buildProcessEnv({NO_COLOR:"1"})});this.process=s,this.stderrBuf="",this.appServerStartupError=null,I({input:s.stdout}).on("line",t=>{if(!t.trim())return;let o;try{o=JSON.parse(t)}catch{this.handleAppServerNonJsonStdout(t);return}this.handleAppServerMessage(o)}),s.stderr?.on("data",t=>{this.stderrBuf+=t.toString()}),s.on("close",t=>{if(this.process!==s)return;const o=this.activeTurnId!=null;this.process=null,this.appServerReady=null,this.activeTurnId=null,this.managedRoomTools.reset(),this.clearConfiguredManagedRoomContext(),this.rejectAllPending(new Error(H(this.stderrBuf)||`codex app-server exited with code ${t}`)),this.terminalState==="open"&&o&&this.handleProcessClose(t,this.stderrBuf)}),s.on("error",t=>{this.process===s&&(this.process=null,this.managedRoomTools.reset(),this.clearConfiguredManagedRoomContext(),this.rejectAllPending(t),t.code==="ENOENT"?this.emit("error",T(this.workDir,w)):this.emit("error",t))})}async ensureAppServer(e){return this.appServerReady?this.appServerReady:(this.spawnAppServer(),this.appServerReady=this.initializeAppServer(e).catch(async r=>{throw this.appServerReady=null,await this.killProcess(),r}),this.appServerReady)}async initializeAppServer(e){const r=g(e);await this.sendRpc("initialize",{clientInfo:W,capabilities:{experimentalApi:!0}}),this.managedPermissionConfig=this.managedAgentPolicy&&!S(this.managedAgentPolicy)?await this.buildManagedPermissionConfig():null;const i=!!(this.configuredManagedRoomContextToken||this.configuredManagedRoomExecutor);if(this.managedAgentPolicy&&i&&!this.managedRoomTools.isConfigured()&&(this.managedRoomTools.configure(this.configuredManagedRoomContextToken,this.configuredManagedRoomExecutor),!this.managedRoomTools.isConfigured()))throw new Error("codex_managed_room_tool_context_unavailable");if(this.agentSessionId&&this.managedAgentPolicy&&i&&this.agentSessionId!==this.managedRoomToolThreadId){if(!this.managedRoomTools.isConfigured())throw new Error("codex_managed_room_tool_context_unavailable");this.agentSessionId=null}if(this.agentSessionId){const d={threadId:this.agentSessionId,cwd:this.workDir,approvalPolicy:"never",...this.managedPermissionConfig?{config:this.managedPermissionConfig.threadConfig}:{sandbox:"danger-full-access"},persistExtendedHistory:!0,...r?{model:r}:{}};let c;try{c=await this.sendRpc("thread/resume",{...d,excludeTurns:!0})}catch(l){if(!J(l))throw l;c=await this.sendRpc("thread/resume",d)}this.agentSessionId=c.thread?.id??this.agentSessionId,this.notifyNativeSession(),this.managedPermissionConfig&&C(c,this.managedPermissionConfig.profileId),this.managedAgentPolicy&&i&&(this.managedRoomTools.bindThread(this.agentSessionId),this.managedRoomToolThreadId=this.agentSessionId);return}const s=this.options.hidden||this.nativeSessionVisibility==="internal"||!this.persistNativeSession,n=s?void 0:await this.resolveCodexProjectId(),t={cwd:this.workDir,approvalPolicy:"never",...this.managedPermissionConfig?{config:this.managedPermissionConfig.threadConfig}:{sandbox:"danger-full-access"},serviceName:"Shennian",threadSource:s?"shennian_internal":"user",experimentalRawEvents:!1,persistExtendedHistory:!0,...this.managedAgentPolicy&&i?{dynamicTools:this.extraEnv.SHENNIAN_MANAGER_SESSION_ID?U:B}:{},...n?{projectId:n}:{},...r?{model:r}:{}};let o;if(s&&!this.managedPermissionConfig)o=await this.sendRpc("thread/start",t);else try{o=await this.sendRpc("thread/start",{...t,historyMode:"paginated"})}catch(d){throw Q(d)?new Error("codex_session_capability_unavailable: \u5F53\u524D Codex CLI \u4E0D\u652F\u6301\u521B\u5EFA\u53EF\u5728 Codex Desktop \u4E2D\u7EE7\u7EED\u7684\u65B0\u4F1A\u8BDD\uFF0C\u8BF7\u624B\u52A8\u5347\u7EA7 Codex CLI \u540E\u91CD\u8BD5\u3002\u795E\u5FF5\u4E0D\u4F1A\u81EA\u52A8\u5347\u7EA7\uFF0C\u4E5F\u4E0D\u4F1A\u964D\u7EA7\u521B\u5EFA\u4E0D\u53EF\u89C1\u7684 legacy \u4F1A\u8BDD\u3002",{cause:d}):d}const a=o.thread?.id;if(!a)throw new Error("codex app-server thread/start returned no thread id");this.managedPermissionConfig&&C(o,this.managedPermissionConfig.profileId),this.managedAgentPolicy&&i&&(this.managedRoomTools.bindThread(a),this.managedRoomToolThreadId=a),this.agentSessionId=a,this.notifyNativeSession()}notifyNativeSession(){this.agentSessionId&&this.emit("nativeSession","codex",this.agentSessionId)}async buildManagedPermissionConfig(){const e=this.managedAgentPolicy;if(!e)throw new Error("managed_agent_policy_missing");const r=e.adapterPolicy.externalCapabilities.mcp?[]:q(await this.sendRpc("config/read",{cwd:e.adapterPolicy.workDir}));return j(k(e),e.adapterPolicy.workDir,{configuredMcpServerNames:r,shellSubprocessPolicy:e.environmentPolicy.shellSubprocess})}async resolveCodexProjectId(){const e=this.workDir?.trim();if(e)try{const r=[];let i;do{const d=await this.sendRpc("project/list",{limit:100,...i?{cursor:i}:{}});r.push(...d.data??[]),i=d.nextCursor}while(i);const s=K(r,e);if(s)return s;const n=y.resolve(e),t=`shennian-project-${x("sha256").update(n).digest("hex")}`,a=(await this.sendRpc("project/create",{idempotencyKey:t,name:y.basename(n)||n,roots:[{path:n}],metadata:{createdBy:"Shennian"}})).project?.id;if(!a)throw new Error("codex app-server project/create returned no project id");return a}catch(r){throw Y(r)?new Error("codex_session_capability_unavailable: \u5F53\u524D Codex CLI \u4E0D\u652F\u6301\u521B\u5EFA\u53EF\u5F52\u5C5E\u5230 Codex Desktop \u9879\u76EE\u7684\u65B0\u4F1A\u8BDD\uFF0C\u8BF7\u624B\u52A8\u5347\u7EA7 Codex CLI \u540E\u91CD\u8BD5\u3002\u795E\u5FF5\u4E0D\u4F1A\u81EA\u52A8\u5347\u7EA7\uFF0C\u4E5F\u4E0D\u4F1A\u76F4\u63A5\u4FEE\u6539 Codex Desktop \u7684\u79C1\u6709\u4FA7\u680F\u7D22\u5F15\u3002",{cause:r}):r}}async startTurnWithRecovery(e,r,i,s,n){try{return await this.startTurn(e,r,i,s,n)}catch(t){if(!E(t))throw t;if(this.managedAgentPolicy||this.managedPermissionConfig){this.logManagedThreadLifecycle("rollout.missing",{threadId:e,recovery:"recreate"}),await this.killProcess(!0),this.agentSessionId=null,this.managedRoomToolThreadId=null,await this.ensureAppServer(i);const o=this.agentSessionId;if(!o)throw new Error("codex app-server did not recreate the managed thread",{cause:t});return this.logManagedThreadLifecycle("thread.recreated",{previousThreadId:e,threadId:o}),this.emitEvent({state:"start",agentSessionId:o}),await this.startFreshManagedTurnWithReadinessRetry(o,r,i,s,n)}return await this.killProcess(),await this.ensureAppServer(i),await this.startTurn(e,r,i,s,n)}}async startFreshManagedTurnWithReadinessRetry(e,r,i,s,n){const t=[0,100,300,1e3];let o;for(let a=0;a<t.length;a+=1){const d=t[a];d>0&&await new Promise(c=>setTimeout(c,d));try{const c=await this.startTurn(e,r,i,s,n);return a>0&&this.logManagedThreadLifecycle("rollout.ready",{threadId:e,attempt:a+1}),c}catch(c){if(o=c,!E(c)||a===t.length-1)throw c;this.logManagedThreadLifecycle("rollout.retry",{threadId:e,attempt:a+2,delayMs:t[a+1]})}}throw o}logManagedThreadLifecycle(e,r){console.error(`[codex.managed] ${JSON.stringify({event:e,...r})}`)}async startTurn(e,r,i,s,n){try{return await this.sendRpc("turn/start",{threadId:e,input:[_(r,n)],approvalPolicy:"never",...this.managedPermissionConfig?{}:{sandboxPolicy:{type:"dangerFullAccess"}},...i?{model:i}:{},...s?{effort:s}:{}})}catch(t){throw s&&z(t)?new Error(`Codex app-server does not accept reasoning effort "${s}" for this turn. Refresh models or upgrade Codex CLI, then retry.`,{cause:t}):t}}async interruptActiveTurn(){const e=this.agentSessionId,r=this.activeTurnId;this.activeTurnId=null,this.managedRoomTools.deactivateTurn(),!(!e||!r||!this.process)&&await this.sendRpc("turn/interrupt",{threadId:e,turnId:r},5e3)}}L("codex",()=>new ee);export{ee as CodexAdapter,Ie as buildCodexQueueArgs,Se as buildCodexQueuedText,Ce as isCodexActiveWriterError,Ee as isCodexExcludeTurnsUnsupportedError,Te as isCodexPaginatedHistoryUnsupportedError,_e as isCodexProjectApiUnsupportedError,Ae as isCodexUnsupportedEffortError,Me as isMissingCodexRolloutError,be as normalizeCodexModelId,Ne as normalizeCodexReasoningEffort,Pe as selectCodexProjectIdForWorkDir};
@@ -1,4 +1,4 @@
1
- import{spawn as j,spawnSync as x}from"node:child_process";import l from"node:fs";import $ from"node:crypto";import P from"node:os";import s from"node:path";const A={claude:[{command:"claude",args:[],display:"claude"}],codex:[{command:"codex",args:[],display:"codex"}],workbuddy:[{command:"codebuddy",args:[],display:"WorkBuddy"}],gemini:[{command:"gemini",args:[],display:"gemini"}],cursor:[{command:"agent",args:[],display:"agent"},{command:"cursor",args:["agent"],display:"cursor agent"}],openclaw:[],opencode:[{command:"opencode",args:[],display:"opencode"}],pi:[{command:"shennian",args:[],display:"shennian"}],"pi-coding-agent":[{command:"pi",args:[],display:"pi"}],manager:[{command:"shennian",args:["manager"],display:"shennian manager"}]},m=new Map,f=new Map,h=new Map,p=new Map;function Y(){m.clear(),f.clear(),h.clear(),p.clear()}function d(){return process.platform}function V(n){return n.split(/\r?\n/).map(e=>e.trim()).filter(Boolean)}function C(n){if(s.basename(n)!==n)return[n];const e=P.homedir();if(d()==="win32"){const o=s.win32,r=s.extname(n)?[n]:[n,`${n}.cmd`,`${n}.exe`,`${n}.bat`],a=process.env.APPDATA||o.join(e,"AppData","Roaming"),u=process.env.LOCALAPPDATA||o.join(e,"AppData","Local"),y=[o.join(e,".shennian","node"),o.join("C:\\","nvm4w","nodejs"),o.join(u,"npm-global"),o.join(a,"npm"),o.join(u,"pnpm"),o.join(e,"scoop","shims"),o.join("C:\\","Program Files","nodejs")].flatMap(w=>r.map(g=>o.join(w,g)));if(n==="codebuddy"){const w=[o.join(u,"Programs","WorkBuddy"),o.join(u,"WorkBuddy"),o.join("C:\\","Program Files","WorkBuddy")];for(const g of w)for(const N of["codebuddy.exe","codebuddy.cmd","codebuddy"])y.push(o.join(g,"resources","app.asar.unpacked","cli","bin",N))}return y}const i=[s.join(e,".npm-global","bin"),s.join(e,".local","bin"),s.join(e,".bun","bin"),"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin"].map(o=>s.join(o,n));return n==="claude"&&d()==="darwin"&&i.push(...I(e)),n==="codebuddy"&&d()==="darwin"&&i.push("/Applications/WorkBuddy.app/Contents/Resources/app.asar.unpacked/cli/bin/codebuddy",s.join(e,"Applications","WorkBuddy.app","Contents","Resources","app.asar.unpacked","cli","bin","codebuddy")),i}function z(n=d(),e=P.homedir()){return n!=="darwin"?[]:["/Applications",s.join(e,"Applications")].flatMap(t=>["ChatGPT.app","Codex.app"].map(i=>s.join(t,i,"Contents","Resources","codex")))}function I(n){const e=[s.join(n,"Library","Application Support","Claude","claude-code")],t=[];for(const i of e){let o;try{o=l.readdirSync(i,{withFileTypes:!0}).filter(r=>r.isDirectory()).map(r=>r.name).sort((r,a)=>a.localeCompare(r,void 0,{numeric:!0}))}catch{continue}for(const r of o)t.push(s.join(i,r,"claude.app","Contents","MacOS","claude"))}return t}function S(n,e){const t=n?.split(s.delimiter).filter(Boolean)??[];if(d()==="win32"){if(e&&s.basename(e)!==e){const i=s.win32.dirname(e);t.includes(i)||t.unshift(i)}for(const i of C("shennian")){const o=s.win32.dirname(i);t.includes(o)||t.push(o)}return t.join(s.delimiter)}if(e&&s.basename(e)!==e){const i=s.dirname(e);t.includes(i)||t.unshift(i)}for(const i of C("shennian")){const o=s.dirname(i);t.includes(o)||t.push(o)}return t.join(s.delimiter)}function c(n){if(h.has(n))return h.get(n)??[];const e=d()==="win32",i=x(e?"where":"which",[n],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:3e3,windowsHide:!0,env:{...process.env,PATH:e?process.env.PATH:S(process.env.PATH,n)}}),r=[...i.status===0?V(i.stdout??""):[]];for(const a of C(n))l.existsSync(a)&&!r.includes(a)&&r.push(a);return h.set(n,r),r}function W(){return process.env.ComSpec||"cmd.exe"}function B(n){const e=s.extname(n).toLowerCase();return e===".exe"||e===".com"}function b(n){const e=s.extname(n).toLowerCase();return e===".cmd"||e===".bat"}function H(n){const e=s.extname(n).toLowerCase();return e===".js"||e===".mjs"||e===".cjs"}function L(){return c("node.exe")[0]??c("node")[0]??"node"}function D(n){return`"${n.replace(/"/g,'""')}"`}function v(n){return`'${n.replace(/'/g,"'\\''")}'`}function O(n){if(!n)return;const e=n.replace(/\//g,"\\"),t=e.match(/^([A-Za-z]):\\(.*)$/);if(t){const[,i,o]=t,r=o.replace(/\\/g,"/");return`/mnt/${i.toLowerCase()}/${r}`}if(e.startsWith("\\\\wsl$\\"))return`/${e.replace(/^\\\\wsl\$\\[^\\]+\\?/,"").replace(/\\/g,"/")}`;if(n.startsWith("/"))return n}function M(n){const e=n.trim();if(!e)throw new Error("Command string is empty");if(/[\\/]/.test(e)||/^[A-Za-z]:/.test(e))return b(e)?{kind:"cmd-shim",path:e}:{kind:"direct",path:e};const i=c(e),o=i.find(B);if(o)return{kind:"direct",path:o};const r=i.find(b);return r?{kind:"cmd-shim",path:r}:{kind:"direct",path:e}}function T(n){if(p.has(n))return p.get(n)??!1;const e=c("wsl.exe")[0]??c("wsl")[0];if(!e)return p.set(n,!1),!1;const i=x(e,["-e","sh","-lc",`command -v ${v(n)} >/dev/null 2>&1`],{stdio:"ignore",timeout:5e3,windowsHide:!0}).status===0;return p.set(n,i),i}function nn(n){if(m.has(n))return m.get(n)??!1;const e=c(n).length>0||d()==="win32"&&T(n);return m.set(n,e),e}function en(n){const e=c(n)[0];if(!e)return null;try{const t=l.realpathSync(e),i=l.statSync(t,{bigint:!0}),o=$.createHash("sha256").update(t).digest("hex"),r=$.createHash("sha256").update(`${i.dev}:${i.ino}:${i.size}:${i.mtimeNs}`).digest("hex");return{pathHash:o,fingerprint:r}}catch{return null}}function tn(n){return c(n)[0]??null}function q(n){const e=c(n.command),t=e.find(B);if(t)return{...n,kind:"native",path:t};const i=e.find(b);if(i)return{...n,kind:"cmd-shim",path:i};if(T(n.command)){const o=c("wsl.exe")[0]??c("wsl")[0];if(o)return{...n,kind:"wsl-bridge",path:o}}return null}function on(n){if(f.has(n))return f.get(n)??null;const e=n==="codex"?z().find(i=>l.existsSync(i)?!!R({command:i,args:[],display:"Codex Desktop",kind:"native",path:i}):!1):void 0,t=e?{...A.codex[0],kind:"native",path:e}:A[n].map(i=>{if(d()==="win32")return q(i);const o=c(i.command)[0];return o?{...i,kind:"native",path:o}:null}).find(Boolean)??null;return f.set(n,t),t}function F(n,e,t){if(n.kind==="native")return d()==="win32"&&H(n.path)?{command:L(),args:[n.path,...n.args,...e],cwd:t}:{command:n.path,args:[...n.args,...e],cwd:t};if(n.kind==="cmd-shim"){const r=[n.path,...n.args,...e].map(D).join(" ");return{command:W(),args:["/d","/s","/c",`"${r}"`],cwd:t}}const i=t?O(t):void 0;if(t&&!i)throw new Error(`Cannot map Windows path to WSL workDir: ${t}`);const o=[i?`cd ${v(i)}`:"",`exec ${[n.command,...n.args,...e].map(v).join(" ")}`].filter(Boolean).join(" && ");return{command:n.path,args:["-e","sh","-lc",o],cwd:void 0}}function U(n,e,t={}){const i=F(n,e,t.cwd);return j(i.command,i.args,{...t,cwd:i.cwd,windowsHide:t.windowsHide??!0,...d()==="win32"&&n.kind==="cmd-shim"?{windowsVerbatimArguments:!0}:{}})}function rn(n,e,t={}){return U(n,e,t)}function k(n,e,t={}){const i=F(n,e,t.cwd);return x(i.command,i.args,{...t,cwd:i.cwd,windowsHide:t.windowsHide??!0,...d()==="win32"&&n.kind==="cmd-shim"?{windowsVerbatimArguments:!0}:{}})}function E(n){const e=[];let t="",i=!1,o=!1;for(const r of n){if(r==="'"&&!o){i=!i;continue}if(r==='"'&&!i){o=!o;continue}if(r===" "&&!i&&!o){t&&(e.push(t),t="");continue}t+=r}return t&&e.push(t),e}function Z(n,e,t){const i=E(n),o=i[0];if(!o)throw new Error("Command string is empty");const r=i.slice(1);if(d()!=="win32")return{command:o,args:[...r,...e],cwd:t};const a=M(o);return a.kind==="cmd-shim"?{command:W(),args:["/d","/s","/c",`"${[a.path,...r,...e].map(D).join(" ")}"`],cwd:t}:H(a.path)?{command:L(),args:[a.path,...r,...e],cwd:t}:{command:a.path,args:[...r,...e],cwd:t}}function sn(n,e,t={}){const i=Z(n,e,t.cwd),o=E(n),r=d()==="win32"&&o[0]?M(o[0]):null;return j(i.command,i.args,{...t,cwd:i.cwd,windowsHide:t.windowsHide??!0,env:{...t.env,PATH:S(t.env?.PATH??process.env.PATH,o[0])},...d()==="win32"&&r?.kind==="cmd-shim"?{windowsVerbatimArguments:!0}:{}})}function R(n,e="--version"){const t=k(n,[e],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:5e3});return t.status!==0?void 0:`${t.stdout??""}
2
- ${t.stderr??""}`.trim().match(/\d+\.\d+[\w.-]*/)?.[0]}function an(n,e){if(n==="codex"||n==="claude"){const r=k(e,["--version"],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:5e3});if(r.status!==0)return;const a=`${r.stdout??""}
3
- ${r.stderr??""}`.replace(/\u001b\[[0-9;]*m/g,"");return(n==="codex"?a.match(/^\s*codex-cli\s+(\d+\.\d+\.\d+[\w.-]*)\s*$/im):a.match(/^\s*(\d+\.\d+\.\d+[\w.-]*)\s+\(Claude Code\)\s*$/im))?.[1]}if(n!=="cursor")return R(e);const t=k(e,["about"],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:5e3});return t.status!==0?void 0:`${t.stdout??""}
4
- ${t.stderr??""}`.match(/^\s*CLI Version\s+(\d+\.\d+(?:\.\d+)?[\w.-]*)\s*$/im)?.[1]}export{Z as buildCommandStringLaunchSpec,F as buildLaunchSpec,nn as commandExists,an as getBuiltinAgentVersion,z as getCodexDesktopCommandCandidates,R as getCommandVersion,d as getProcessPlatform,E as parseCommandString,Y as resetCommandSpecCache,on as resolveBuiltinCommand,en as resolveCommandFileIdentity,tn as resolveCommandFilePath,rn as spawnAgentCommand,sn as spawnCommandString,U as spawnResolvedCommand,k as spawnResolvedCommandSync,O as windowsPathToWsl};
1
+ import{spawn as A,spawnSync as b}from"node:child_process";import l from"node:fs";import $ from"node:crypto";import S from"node:os";import s from"node:path";import{resetWindowsInstallationPaths as z,windowsLookupPath as O,windowsCodexDesktopCandidates as _}from"./windows-agent-paths.js";const W={claude:[{command:"claude",args:[],display:"claude"}],codex:[{command:"codex",args:[],display:"codex"}],workbuddy:[{command:"codebuddy",args:[],display:"WorkBuddy"}],gemini:[{command:"gemini",args:[],display:"gemini"}],cursor:[{command:"agent",args:[],display:"agent"},{command:"cursor",args:["agent"],display:"cursor agent"}],openclaw:[],opencode:[{command:"opencode",args:[],display:"opencode"}],pi:[{command:"shennian",args:[],display:"shennian"}],"pi-coding-agent":[{command:"pi",args:[],display:"pi"}],manager:[{command:"shennian",args:["manager"],display:"shennian manager"}]},m=new Map,f=new Map,h=new Map,p=new Map;function rn(){z(),m.clear(),f.clear(),h.clear(),p.clear()}function d(){return process.platform}function q(n){return n.split(/\r?\n/).map(t=>t.trim()).filter(Boolean)}function v(n){if(s.basename(n)!==n)return[n];const t=S.homedir();if(d()==="win32"){const i=s.win32,r=s.extname(n)?[n]:[n,`${n}.cmd`,`${n}.exe`,`${n}.bat`],a=process.env.APPDATA||i.join(t,"AppData","Roaming"),u=process.env.LOCALAPPDATA||i.join(t,"AppData","Local"),P=[i.join(t,".shennian","node"),i.join("C:\\","nvm4w","nodejs"),i.join(u,"npm-global"),i.join(a,"npm"),i.join(u,"pnpm"),i.join(t,"scoop","shims"),i.join("C:\\","Program Files","nodejs")].flatMap(x=>r.map(C=>i.join(x,C)));if(n==="codebuddy"){const x=[i.join(u,"Programs","WorkBuddy"),i.join(u,"WorkBuddy"),i.join("C:\\","Program Files","WorkBuddy")];for(const C of x)for(const V of["codebuddy.exe","codebuddy.cmd","codebuddy"])P.push(i.join(C,"resources","app.asar.unpacked","cli","bin",V))}return P}const o=[s.join(t,".npm-global","bin"),s.join(t,".local","bin"),s.join(t,".bun","bin"),"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin"].map(i=>s.join(i,n));return n==="claude"&&d()==="darwin"&&o.push(...U(t)),n==="codebuddy"&&d()==="darwin"&&o.push("/Applications/WorkBuddy.app/Contents/Resources/app.asar.unpacked/cli/bin/codebuddy",s.join(t,"Applications","WorkBuddy.app","Contents","Resources","app.asar.unpacked","cli","bin","codebuddy")),o}function B(n=d(),t=S.homedir()){return n==="win32"?_(t):n!=="darwin"?[]:["/Applications",s.join(t,"Applications")].flatMap(e=>["ChatGPT.app","Codex.app"].map(o=>s.join(e,o,"Contents","Resources","codex")))}function U(n){const t=[s.join(n,"Library","Application Support","Claude","claude-code")],e=[];for(const o of t){let i;try{i=l.readdirSync(o,{withFileTypes:!0}).filter(r=>r.isDirectory()).map(r=>r.name).sort((r,a)=>a.localeCompare(r,void 0,{numeric:!0}))}catch{continue}for(const r of i)e.push(s.join(o,r,"claude.app","Contents","MacOS","claude"))}return e}function H(n,t){const e=n?.split(s.delimiter).filter(Boolean)??[];if(d()==="win32"){if(t&&s.basename(t)!==t){const o=s.win32.dirname(t);e.includes(o)||e.unshift(o)}for(const o of v("shennian")){const i=s.win32.dirname(o);e.includes(i)||e.push(i)}return e.join(s.delimiter)}if(t&&s.basename(t)!==t){const o=s.dirname(t);e.includes(o)||e.unshift(o)}for(const o of v("shennian")){const i=s.dirname(o);e.includes(i)||e.push(i)}return e.join(s.delimiter)}function c(n){if(h.has(n))return h.get(n)??[];const t=d()==="win32",o=b(t?"where":"which",[n],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:3e3,windowsHide:!0,env:{...process.env,PATH:t?O():H(process.env.PATH,n)}}),r=[...o.status===0?q(o.stdout??""):[]];for(const a of v(n))l.existsSync(a)&&!r.includes(a)&&r.push(a);return h.set(n,r),r}function D(){return process.env.ComSpec||"cmd.exe"}function k(n){const t=s.extname(n).toLowerCase();return t===".exe"||t===".com"}function w(n){const t=s.extname(n).toLowerCase();return t===".cmd"||t===".bat"}function L(n){const t=s.extname(n).toLowerCase();return t===".js"||t===".mjs"||t===".cjs"}function M(){return c("node.exe")[0]??c("node")[0]??"node"}function E(n){return`"${n.replace(/"/g,'""')}"`}function y(n){return`'${n.replace(/'/g,"'\\''")}'`}function Z(n){if(!n)return;const t=n.replace(/\//g,"\\"),e=t.match(/^([A-Za-z]):\\(.*)$/);if(e){const[,o,i]=e,r=i.replace(/\\/g,"/");return`/mnt/${o.toLowerCase()}/${r}`}if(t.startsWith("\\\\wsl$\\"))return`/${t.replace(/^\\\\wsl\$\\[^\\]+\\?/,"").replace(/\\/g,"/")}`;if(n.startsWith("/"))return n}function N(n){const t=n.trim();if(!t)throw new Error("Command string is empty");if(/[\\/]/.test(t)||/^[A-Za-z]:/.test(t))return w(t)?{kind:"cmd-shim",path:t}:{kind:"direct",path:t};const o=c(t),i=o.find(k);if(i)return{kind:"direct",path:i};const r=o.find(w);return r?{kind:"cmd-shim",path:r}:{kind:"direct",path:t}}function T(n){if(p.has(n))return p.get(n)??!1;const t=c("wsl.exe")[0]??c("wsl")[0];if(!t)return p.set(n,!1),!1;const o=b(t,["-e","sh","-lc",`command -v ${y(n)} >/dev/null 2>&1`],{stdio:"ignore",timeout:5e3,windowsHide:!0}).status===0;return p.set(n,o),o}function sn(n){if(m.has(n))return m.get(n)??!1;const t=c(n).length>0||d()==="win32"&&T(n);return m.set(n,t),t}function an(n){const t=c(n)[0];if(!t)return null;try{const e=l.realpathSync(t),o=l.statSync(e,{bigint:!0}),i=$.createHash("sha256").update(e).digest("hex"),r=$.createHash("sha256").update(`${o.dev}:${o.ino}:${o.size}:${o.mtimeNs}`).digest("hex");return{pathHash:i,fingerprint:r}}catch{return null}}function dn(n){return c(n)[0]??null}function G(n){const t=c(n.command);if(n.command==="codex"){const i=process.env.SHENNIAN_CODEX_PATH?.trim(),r=i?[i]:[...t,...B()];for(const a of r){if(i&&!s.win32.isAbsolute(a))return null;const u=k(a)?"native":w(a)?"cmd-shim":null;if(!u)continue;const g={...n,kind:u,path:a};if(I("codex",g))return g}return null}const e=t.find(k);if(e)return{...n,kind:"native",path:e};const o=t.find(w);if(o)return{...n,kind:"cmd-shim",path:o};if(T(n.command)){const i=c("wsl.exe")[0]??c("wsl")[0];if(i)return{...n,kind:"wsl-bridge",path:i}}return null}function cn(n){if(f.has(n))return f.get(n)??null;const t=n==="codex"&&d()==="darwin"?B().find(o=>l.existsSync(o)?!!I("codex",{command:o,args:[],display:"Codex Desktop",kind:"native",path:o}):!1):void 0,e=t?{...W.codex[0],kind:"native",path:t}:W[n].map(o=>{if(d()==="win32")return G(o);const i=c(o.command)[0];return i?{...o,kind:"native",path:i}:null}).find(Boolean)??null;return f.set(n,e),e}function F(n,t,e){if(n.kind==="native")return d()==="win32"&&L(n.path)?{command:M(),args:[n.path,...n.args,...t],cwd:e}:{command:n.path,args:[...n.args,...t],cwd:e};if(n.kind==="cmd-shim"){const r=[n.path,...n.args,...t].map(E).join(" ");return{command:D(),args:["/d","/s","/c",`"${r}"`],cwd:e}}const o=e?Z(e):void 0;if(e&&!o)throw new Error(`Cannot map Windows path to WSL workDir: ${e}`);const i=[o?`cd ${y(o)}`:"",`exec ${[n.command,...n.args,...t].map(y).join(" ")}`].filter(Boolean).join(" && ");return{command:n.path,args:["-e","sh","-lc",i],cwd:void 0}}function X(n,t,e={}){const o=F(n,t,e.cwd);return A(o.command,o.args,{...e,cwd:o.cwd,windowsHide:e.windowsHide??!0,...d()==="win32"&&n.kind==="cmd-shim"?{windowsVerbatimArguments:!0}:{}})}function un(n,t,e={}){return X(n,t,e)}function j(n,t,e={}){const o=F(n,t,e.cwd);return b(o.command,o.args,{...e,cwd:o.cwd,windowsHide:e.windowsHide??!0,...d()==="win32"&&n.kind==="cmd-shim"?{windowsVerbatimArguments:!0}:{}})}function R(n){const t=[];let e="",o=!1,i=!1;for(const r of n){if(r==="'"&&!i){o=!o;continue}if(r==='"'&&!o){i=!i;continue}if(r===" "&&!o&&!i){e&&(t.push(e),e="");continue}e+=r}return e&&t.push(e),t}function J(n,t,e){const o=R(n),i=o[0];if(!i)throw new Error("Command string is empty");const r=o.slice(1);if(d()!=="win32")return{command:i,args:[...r,...t],cwd:e};const a=N(i);return a.kind==="cmd-shim"?{command:D(),args:["/d","/s","/c",`"${[a.path,...r,...t].map(E).join(" ")}"`],cwd:e}:L(a.path)?{command:M(),args:[a.path,...r,...t],cwd:e}:{command:a.path,args:[...r,...t],cwd:e}}function ln(n,t,e={}){const o=J(n,t,e.cwd),i=R(n),r=d()==="win32"&&i[0]?N(i[0]):null;return A(o.command,o.args,{...e,cwd:o.cwd,windowsHide:e.windowsHide??!0,env:{...e.env,PATH:H(e.env?.PATH??process.env.PATH,i[0])},...d()==="win32"&&r?.kind==="cmd-shim"?{windowsVerbatimArguments:!0}:{}})}function K(n,t="--version"){const e=j(n,[t],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:5e3});return e.status!==0?void 0:`${e.stdout??""}
2
+ ${e.stderr??""}`.trim().match(/\d+\.\d+[\w.-]*/)?.[0]}function I(n,t){if(n==="codex"||n==="claude"){const r=j(t,["--version"],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:5e3});if(r.status!==0)return;const a=`${r.stdout??""}
3
+ ${r.stderr??""}`.replace(/\u001b\[[0-9;]*m/g,"");return(n==="codex"?a.match(/^\s*codex-cli\s+(\d+\.\d+\.\d+[\w.-]*)\s*$/im):a.match(/^\s*(\d+\.\d+\.\d+[\w.-]*)\s+\(Claude Code\)\s*$/im))?.[1]}if(n!=="cursor")return K(t);const e=j(t,["about"],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:5e3});return e.status!==0?void 0:`${e.stdout??""}
4
+ ${e.stderr??""}`.match(/^\s*CLI Version\s+(\d+\.\d+(?:\.\d+)?[\w.-]*)\s*$/im)?.[1]}export{J as buildCommandStringLaunchSpec,F as buildLaunchSpec,sn as commandExists,I as getBuiltinAgentVersion,B as getCodexDesktopCommandCandidates,K as getCommandVersion,d as getProcessPlatform,R as parseCommandString,rn as resetCommandSpecCache,cn as resolveBuiltinCommand,an as resolveCommandFileIdentity,dn as resolveCommandFilePath,un as spawnAgentCommand,ln as spawnCommandString,X as spawnResolvedCommand,j as spawnResolvedCommandSync,Z as windowsPathToWsl};
@@ -1 +1 @@
1
- import{createInterface as d}from"node:readline";import{randomUUID as l}from"node:crypto";import{AgentAdapter as c,registerAgent as h}from"./adapter.js";import{resolveBuiltinCommand as u,spawnResolvedCommand as m}from"./command-spec.js";import{buildAgentProcessEnv as g,buildManagedAgentProcessEnv as f,buildManagedNativeFullProcessEnv as p}from"../agent-env.js";import{buildInlineChannelPreamble as v}from"./platform-instructions.js";import{resolveManagedAgentAdapterEnforcement as E,isManagedAgentNativeFull as w}from"../security/managed-agent-policy.js";import{registerManagedAgentRuntimeSecurity as y}from"../security/managed-agent-runtime.js";import{compileCursorManagedPermissions as C,createCursorManagedConfigDirectory as k,CURSOR_MANAGED_RUNTIME_SECURITY as x,disposeCursorManagedConfigDirectory as I}from"./cursor-managed-permissions.js";y("cursor",x);class D extends c{type="cursor";get recoveryCapabilities(){return{inspectTerminal:!1,reattachRun:!1,resumeRun:!1,resumeSession:!0}}process=null;chatId=null;workDir=null;seq=0;runId="";emittedText="";externalChannel=null;shennianSessionId=null;extraEnv={};managedAgentPolicy=null;managedConfigDir=null;configure(t){this.shennianSessionId=t.sessionId??null,this.externalChannel=t.externalChannel??null,this.extraEnv=t.env??{},"managedAgentPolicy"in t&&(this.managedAgentPolicy=t.managedAgentPolicy??null),this.managedAgentPolicy&&(this.workDir=this.managedAgentPolicy.adapterPolicy.workDir)}async start(t,s,e){this.workDir=this.managedAgentPolicy?.adapterPolicy.workDir??s,this.seq=0,e&&(this.chatId=e)}async send(t,s,e,n,o,r){if(r?.source==="room_activation"&&!this.managedAgentPolicy)throw new Error("managed_agent_policy_missing");await this.killProcess(),this.runId=l(),this.resetRunState();const i=`${v(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0,o)}${t}`;await this.spawnAndParse(this.buildSendArgs(i,s))}async resume(t){await this.killProcess(),this.chatId=t,this.runId=l(),this.resetRunState(),await this.spawnAndParse(["--resume",t,"--output-format","stream-json","--stream-partial-output"])}async stop(){await this.killProcess()}buildSendArgs(t,s){const e=["-p",t,"--output-format","stream-json","--stream-partial-output"];return s&&e.push("--model",s),this.chatId&&e.push("--resume",this.chatId),e}async spawnAndParse(t){const s=u("cursor");if(!s){this.emit("error",new Error('Cursor Agent CLI not found. Expected "agent" or "cursor agent".'));return}const e=await this.prepareManagedLaunch();let n;try{n=m(s,[...t,...e.args],{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:e.env})}catch(i){throw await this.disposeManagedConfig(e.configDir),i}this.process=n,this.managedConfigDir=e.configDir,d({input:n.stdout}).on("line",i=>{if(i.trim())try{const a=JSON.parse(i);this.handleStreamEvent(a)}catch{this.emitEvent({state:"delta",text:i})}});let r="";n.stderr?.on("data",i=>{r+=i.toString()}),n.on("close",i=>{if(this.process===n&&(this.process=null,this.disposeManagedConfig(e.configDir),i!==0&&i!==null)){const a=r.trim()||`cursor agent exited with code ${i}`;this.emitEvent({state:"error",message:a})}}),n.on("error",i=>{this.process===n&&(this.process=null,this.disposeManagedConfig(e.configDir),i.code==="ENOENT"?this.emit("error",new Error('Command "cursor" not found. Is Cursor CLI installed?')):this.emit("error",i))})}async prepareManagedLaunch(){const t=this.managedAgentPolicy;if(!t)return{args:["--trust"],env:g(this.extraEnv),configDir:null};if(w(t))return{args:["--trust"],env:p(this.extraEnv),configDir:null};const s=C(E(t),t.adapterPolicy.workDir),e=await k(s),n=f({agentType:"cursor",providerEnv:this.extraEnv,sessionEnv:this.extraEnv,runtimeEnv:{NO_COLOR:"1"}});return n.CURSOR_CONFIG_DIR=e,{args:s.args,env:n,configDir:e}}async disposeManagedConfig(t){t&&(this.managedConfigDir===t&&(this.managedConfigDir=null),await I(t).catch(()=>{}))}handleStreamEvent(t){switch(t.session_id&&!this.chatId&&(this.chatId=t.session_id),t.chat_id&&!this.chatId&&(this.chatId=t.chat_id),t.type??t.event){case"system":break;case"assistant":{if(t.message?.content){if(!this.isLiveAssistantDelta(t))break;for(const e of t.message.content)e.type==="text"&&e.text?this.emitTextDelta(e.text):e.type==="thinking"&&e.thinking?this.emitEvent({state:"delta",text:e.thinking,thinking:!0}):e.type==="tool_use"&&this.emitEvent({state:"tool-call",name:e.name,args:e.input});break}(t.delta??t.text)&&this.emitEvent({state:"delta",text:t.delta??t.text});break}case"user":break;case"result":{if(t.subtype==="success"||!t.is_error){this.emitFinalResultDelta(t.result);const e=t.usage;this.emitEvent({state:"final",agentSessionId:this.chatId??void 0,usage:e?{inputTokens:e.inputTokens??e.input_tokens??0,outputTokens:e.outputTokens??e.output_tokens??0}:void 0})}else this.emitEvent({state:"error",message:t.result??t.error??"unknown error"});break}case"error":{this.emitEvent({state:"error",message:t.error??"unknown error"});break}case"text":case"delta":case"content":{const e=t.delta??t.text;e&&this.emitEvent({state:"delta",text:e});break}case"done":{this.emitEvent({state:"final",agentSessionId:this.chatId??void 0});break}default:t.done?this.emitEvent({state:"final",agentSessionId:this.chatId??void 0}):(t.delta??t.text)&&this.emitEvent({state:"delta",text:t.delta??t.text})}}emitEvent(t){const s={...t,runId:this.runId,seq:this.seq++};this.emit("agentEvent",s)}async killProcess(){const t=this.process;if(!t){await this.disposeManagedConfig(this.managedConfigDir);return}this.process=null,t.kill("SIGTERM"),await new Promise(s=>{t.on("close",s),setTimeout(()=>{t.kill("SIGKILL"),s()},3e3)}),await this.disposeManagedConfig(this.managedConfigDir)}resetRunState(){this.seq=0,this.emittedText=""}isLiveAssistantDelta(t){return t.timestamp_ms!=null&&!t.model_call_id}emitTextDelta(t){t&&(this.emittedText+=t,this.emitEvent({state:"delta",text:t}))}emitFinalResultDelta(t){if(!t)return;if(!this.emittedText){this.emitTextDelta(t);return}if(!t.startsWith(this.emittedText))return;const s=t.slice(this.emittedText.length);s&&this.emitTextDelta(s)}}h("cursor",()=>new D);export{D as CursorAdapter};
1
+ import{createInterface as d}from"node:readline";import{randomUUID as l}from"node:crypto";import{AgentAdapter as c,registerAgent as h}from"./adapter.js";import{resolveBuiltinCommand as u,spawnResolvedCommand as m}from"./command-spec.js";import{spawnEnoentError as g}from"./spawn-errors.js";import{buildAgentProcessEnv as f,buildManagedAgentProcessEnv as p,buildManagedNativeFullProcessEnv as v}from"../agent-env.js";import{buildInlineChannelPreamble as E}from"./platform-instructions.js";import{resolveManagedAgentAdapterEnforcement as w,isManagedAgentNativeFull as k}from"../security/managed-agent-policy.js";import{registerManagedAgentRuntimeSecurity as y}from"../security/managed-agent-runtime.js";import{compileCursorManagedPermissions as C,createCursorManagedConfigDirectory as x,CURSOR_MANAGED_RUNTIME_SECURITY as I,disposeCursorManagedConfigDirectory as D}from"./cursor-managed-permissions.js";y("cursor",I);class A extends c{type="cursor";get recoveryCapabilities(){return{inspectTerminal:!1,reattachRun:!1,resumeRun:!1,resumeSession:!0}}process=null;chatId=null;workDir=null;seq=0;runId="";emittedText="";externalChannel=null;shennianSessionId=null;extraEnv={};managedAgentPolicy=null;managedConfigDir=null;configure(t){this.shennianSessionId=t.sessionId??null,this.externalChannel=t.externalChannel??null,this.extraEnv=t.env??{},"managedAgentPolicy"in t&&(this.managedAgentPolicy=t.managedAgentPolicy??null),this.managedAgentPolicy&&(this.workDir=this.managedAgentPolicy.adapterPolicy.workDir)}async start(t,s,e){this.workDir=this.managedAgentPolicy?.adapterPolicy.workDir??s,this.seq=0,e&&(this.chatId=e)}async send(t,s,e,n,o,r){if(r?.source==="room_activation"&&!this.managedAgentPolicy)throw new Error("managed_agent_policy_missing");await this.killProcess(),this.runId=l(),this.resetRunState();const i=`${E(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0,o)}${t}`;await this.spawnAndParse(this.buildSendArgs(i,s))}async resume(t){await this.killProcess(),this.chatId=t,this.runId=l(),this.resetRunState(),await this.spawnAndParse(["--resume",t,"--output-format","stream-json","--stream-partial-output"])}async stop(){await this.killProcess()}buildSendArgs(t,s){const e=["-p",t,"--output-format","stream-json","--stream-partial-output"];return s&&e.push("--model",s),this.chatId&&e.push("--resume",this.chatId),e}async spawnAndParse(t){const s=u("cursor");if(!s){this.emit("error",new Error('Cursor Agent CLI not found. Expected "agent" or "cursor agent".'));return}const e=await this.prepareManagedLaunch();let n;try{n=m(s,[...t,...e.args],{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:e.env})}catch(i){throw await this.disposeManagedConfig(e.configDir),i}this.process=n,this.managedConfigDir=e.configDir,d({input:n.stdout}).on("line",i=>{if(i.trim())try{const a=JSON.parse(i);this.handleStreamEvent(a)}catch{this.emitEvent({state:"delta",text:i})}});let r="";n.stderr?.on("data",i=>{r+=i.toString()}),n.on("close",i=>{if(this.process===n&&(this.process=null,this.disposeManagedConfig(e.configDir),i!==0&&i!==null)){const a=r.trim()||`cursor agent exited with code ${i}`;this.emitEvent({state:"error",message:a})}}),n.on("error",i=>{this.process===n&&(this.process=null,this.disposeManagedConfig(e.configDir),i.code==="ENOENT"?this.emit("error",g(this.workDir,'Command "cursor" not found. Is Cursor CLI installed?')):this.emit("error",i))})}async prepareManagedLaunch(){const t=this.managedAgentPolicy;if(!t)return{args:["--trust"],env:f(this.extraEnv),configDir:null};if(k(t))return{args:["--trust"],env:v(this.extraEnv),configDir:null};const s=C(w(t),t.adapterPolicy.workDir),e=await x(s),n=p({agentType:"cursor",providerEnv:this.extraEnv,sessionEnv:this.extraEnv,runtimeEnv:{NO_COLOR:"1"}});return n.CURSOR_CONFIG_DIR=e,{args:s.args,env:n,configDir:e}}async disposeManagedConfig(t){t&&(this.managedConfigDir===t&&(this.managedConfigDir=null),await D(t).catch(()=>{}))}handleStreamEvent(t){switch(t.session_id&&!this.chatId&&(this.chatId=t.session_id),t.chat_id&&!this.chatId&&(this.chatId=t.chat_id),t.type??t.event){case"system":break;case"assistant":{if(t.message?.content){if(!this.isLiveAssistantDelta(t))break;for(const e of t.message.content)e.type==="text"&&e.text?this.emitTextDelta(e.text):e.type==="thinking"&&e.thinking?this.emitEvent({state:"delta",text:e.thinking,thinking:!0}):e.type==="tool_use"&&this.emitEvent({state:"tool-call",name:e.name,args:e.input});break}(t.delta??t.text)&&this.emitEvent({state:"delta",text:t.delta??t.text});break}case"user":break;case"result":{if(t.subtype==="success"||!t.is_error){this.emitFinalResultDelta(t.result);const e=t.usage;this.emitEvent({state:"final",agentSessionId:this.chatId??void 0,usage:e?{inputTokens:e.inputTokens??e.input_tokens??0,outputTokens:e.outputTokens??e.output_tokens??0}:void 0})}else this.emitEvent({state:"error",message:t.result??t.error??"unknown error"});break}case"error":{this.emitEvent({state:"error",message:t.error??"unknown error"});break}case"text":case"delta":case"content":{const e=t.delta??t.text;e&&this.emitEvent({state:"delta",text:e});break}case"done":{this.emitEvent({state:"final",agentSessionId:this.chatId??void 0});break}default:t.done?this.emitEvent({state:"final",agentSessionId:this.chatId??void 0}):(t.delta??t.text)&&this.emitEvent({state:"delta",text:t.delta??t.text})}}emitEvent(t){const s={...t,runId:this.runId,seq:this.seq++};this.emit("agentEvent",s)}async killProcess(){const t=this.process;if(!t){await this.disposeManagedConfig(this.managedConfigDir);return}this.process=null,t.kill("SIGTERM"),await new Promise(s=>{t.on("close",s),setTimeout(()=>{t.kill("SIGKILL"),s()},3e3)}),await this.disposeManagedConfig(this.managedConfigDir)}resetRunState(){this.seq=0,this.emittedText=""}isLiveAssistantDelta(t){return t.timestamp_ms!=null&&!t.model_call_id}emitTextDelta(t){t&&(this.emittedText+=t,this.emitEvent({state:"delta",text:t}))}emitFinalResultDelta(t){if(!t)return;if(!this.emittedText){this.emitTextDelta(t);return}if(!t.startsWith(this.emittedText))return;const s=t.slice(this.emittedText.length);s&&this.emitTextDelta(s)}}h("cursor",()=>new A);export{A as CursorAdapter};
@@ -1,2 +1,2 @@
1
- import n from"node:fs";import i from"node:path";import{randomUUID as u}from"node:crypto";import{resolveShennianPath as l}from"../config/index.js";function m(){return l("runtime","recovery-conformance","custom.json")}function f(){try{const e=JSON.parse(n.readFileSync(m(),"utf8"));return e?.schemaVersion===1&&e.agents&&typeof e.agents=="object"?e:{schemaVersion:1,agents:{}}}catch{return{schemaVersion:1,agents:{}}}}function d(e,t,c){if(!t)return!1;const r=f().agents[e];return!!(r&&r.fingerprint===t&&r.runtimeVersion===(c??null))}function g(e,t,c){const r=m();n.mkdirSync(i.dirname(r),{recursive:!0,mode:448}),process.platform!=="win32"&&n.chmodSync(i.dirname(r),448);const s=f();s.agents[e]={fingerprint:t,runtimeVersion:c??null,verifiedAt:new Date().toISOString()};const o=`${r}.tmp-${process.pid}-${u()}`;try{n.writeFileSync(o,`${JSON.stringify(s,null,2)}
2
- `,{mode:384,flag:"wx"});const a=n.openSync(o,"r");try{n.fsyncSync(a)}finally{n.closeSync(a)}n.renameSync(o,r)}finally{try{n.unlinkSync(o)}catch{}}}export{d as hasCustomResumeConformance,g as recordCustomResumeConformance};
1
+ import r from"node:fs";import{renameSyncWithRetry as u}from"../fs/atomic-rename.js";import a from"node:path";import{randomUUID as l}from"node:crypto";import{resolveShennianPath as y}from"../config/index.js";function m(){return y("runtime","recovery-conformance","custom.json")}function f(){try{const e=JSON.parse(r.readFileSync(m(),"utf8"));return e?.schemaVersion===1&&e.agents&&typeof e.agents=="object"?e:{schemaVersion:1,agents:{}}}catch{return{schemaVersion:1,agents:{}}}}function v(e,t,c){if(!t)return!1;const n=f().agents[e];return!!(n&&n.fingerprint===t&&n.runtimeVersion===(c??null))}function C(e,t,c){const n=m();r.mkdirSync(a.dirname(n),{recursive:!0,mode:448}),process.platform!=="win32"&&r.chmodSync(a.dirname(n),448);const i=f();i.agents[e]={fingerprint:t,runtimeVersion:c??null,verifiedAt:new Date().toISOString()};const o=`${n}.tmp-${process.pid}-${l()}`;try{r.writeFileSync(o,`${JSON.stringify(i,null,2)}
2
+ `,{mode:384,flag:"wx"});const s=r.openSync(o,"r");try{r.fsyncSync(s)}finally{r.closeSync(s)}u(o,n)}finally{try{r.unlinkSync(o)}catch{}}}export{v as hasCustomResumeConformance,C as recordCustomResumeConformance};
@@ -1 +1 @@
1
- import{createInterface as m}from"node:readline";import{randomUUID as u}from"node:crypto";import{AgentAdapter as d,registerAgent as h}from"./adapter.js";import{resolveBuiltinCommand as c,spawnResolvedCommand as p}from"./command-spec.js";import{buildAgentProcessEnv as f}from"../agent-env.js";import{buildInlineChannelPreamble as g}from"./platform-instructions.js";function r(t){return typeof t=="number"&&Number.isFinite(t)?t:void 0}function k(t){if(!t)return;const e=r(t.input_tokens)??r(t.prompt_tokens)??r(t.inputTokens)??r(t.promptTokenCount),n=r(t.output_tokens)??r(t.completion_tokens)??r(t.outputTokens)??r(t.candidatesTokenCount)??r(t.responseTokenCount);if(!(e===void 0&&n===void 0))return{inputTokens:e??0,outputTokens:n??0}}class I extends d{type="gemini";get recoveryCapabilities(){return{inspectTerminal:!1,reattachRun:!1,resumeRun:!1,resumeSession:!0}}process=null;agentSessionId=null;workDir=null;seq=0;runId="";externalChannel=null;shennianSessionId=null;extraEnv={};configure(e){this.shennianSessionId=e.sessionId??null,this.externalChannel=e.externalChannel??null,this.extraEnv=e.env??{}}async start(e,n,i){this.workDir=n,this.seq=0,i&&(this.agentSessionId=i)}async send(e,n,i,l,a){await this.killProcess(),this.runId=u(),this.seq=0;const o=["-p",`${g(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0,a)}${e}`,"--output-format","stream-json"];n&&o.push("-m",n),this.agentSessionId&&o.push("--resume",this.agentSessionId),this.spawnAndParse(o)}async resume(e){await this.killProcess(),this.agentSessionId=e,this.runId=u(),this.seq=0,this.spawnAndParse(["--resume",e,"--output-format","stream-json"])}async stop(){await this.killProcess()}spawnAndParse(e){const n=c("gemini");if(!n){this.emit("error",new Error('Command "gemini" not found. Is Gemini CLI installed?'));return}const i=p(n,e,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:f(this.extraEnv)});this.process=i,m({input:i.stdout}).on("line",s=>{if(s.trim())try{const o=JSON.parse(s);this.handleStreamEvent(o)}catch{this.emitEvent({state:"delta",text:s})}});let a="";i.stderr?.on("data",s=>{a+=s.toString()}),i.on("close",s=>{if(this.process===i&&(this.process=null,s!==0&&s!==null)){const o=a.trim()||`gemini exited with code ${s}`;this.emitEvent({state:"error",message:o})}}),i.on("error",s=>{this.process===i&&(this.process=null,s.code==="ENOENT"?this.emit("error",new Error('Command "gemini" not found. Is Gemini CLI installed?')):this.emit("error",s))})}handleStreamEvent(e){switch(e.type){case"init":{e.session_id&&(this.agentSessionId=e.session_id);break}case"message":{e.role==="assistant"&&e.content&&this.emitEvent({state:"delta",text:e.content});break}case"result":{if(e.status==="success")this.emitEvent({state:"final",agentSessionId:this.agentSessionId??void 0,usage:k(e.stats)});else if(e.status==="error"){const n=typeof e.error=="string"&&e.error||typeof e.message=="string"&&e.message||"gemini result error";this.emitEvent({state:"error",message:n})}break}default:break}}emitEvent(e){const n={...e,runId:this.runId,seq:this.seq++};this.emit("agentEvent",n)}async killProcess(){const e=this.process;e&&(this.process=null,e.kill("SIGTERM"),await new Promise(n=>{e.on("close",n),setTimeout(()=>{e.kill("SIGKILL"),n()},3e3)}))}}h("gemini",()=>new I);export{I as GeminiAdapter};
1
+ import{createInterface as l}from"node:readline";import{randomUUID as u}from"node:crypto";import{AgentAdapter as d,registerAgent as h}from"./adapter.js";import{resolveBuiltinCommand as c,spawnResolvedCommand as p}from"./command-spec.js";import{spawnEnoentError as f}from"./spawn-errors.js";import{buildAgentProcessEnv as g}from"../agent-env.js";import{buildInlineChannelPreamble as k}from"./platform-instructions.js";function r(n){return typeof n=="number"&&Number.isFinite(n)?n:void 0}function I(n){if(!n)return;const e=r(n.input_tokens)??r(n.prompt_tokens)??r(n.inputTokens)??r(n.promptTokenCount),t=r(n.output_tokens)??r(n.completion_tokens)??r(n.outputTokens)??r(n.candidatesTokenCount)??r(n.responseTokenCount);if(!(e===void 0&&t===void 0))return{inputTokens:e??0,outputTokens:t??0}}class w extends d{type="gemini";get recoveryCapabilities(){return{inspectTerminal:!1,reattachRun:!1,resumeRun:!1,resumeSession:!0}}process=null;agentSessionId=null;workDir=null;seq=0;runId="";externalChannel=null;shennianSessionId=null;extraEnv={};configure(e){this.shennianSessionId=e.sessionId??null,this.externalChannel=e.externalChannel??null,this.extraEnv=e.env??{}}async start(e,t,i){this.workDir=t,this.seq=0,i&&(this.agentSessionId=i)}async send(e,t,i,m,a){await this.killProcess(),this.runId=u(),this.seq=0;const o=["-p",`${k(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0,a)}${e}`,"--output-format","stream-json"];t&&o.push("-m",t),this.agentSessionId&&o.push("--resume",this.agentSessionId),this.spawnAndParse(o)}async resume(e){await this.killProcess(),this.agentSessionId=e,this.runId=u(),this.seq=0,this.spawnAndParse(["--resume",e,"--output-format","stream-json"])}async stop(){await this.killProcess()}spawnAndParse(e){const t=c("gemini");if(!t){this.emit("error",f(this.workDir,'Command "gemini" not found. Is Gemini CLI installed?'));return}const i=p(t,e,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:g(this.extraEnv)});this.process=i,l({input:i.stdout}).on("line",s=>{if(s.trim())try{const o=JSON.parse(s);this.handleStreamEvent(o)}catch{this.emitEvent({state:"delta",text:s})}});let a="";i.stderr?.on("data",s=>{a+=s.toString()}),i.on("close",s=>{if(this.process===i&&(this.process=null,s!==0&&s!==null)){const o=a.trim()||`gemini exited with code ${s}`;this.emitEvent({state:"error",message:o})}}),i.on("error",s=>{this.process===i&&(this.process=null,s.code==="ENOENT"?this.emit("error",new Error('Command "gemini" not found. Is Gemini CLI installed?')):this.emit("error",s))})}handleStreamEvent(e){switch(e.type){case"init":{e.session_id&&(this.agentSessionId=e.session_id);break}case"message":{e.role==="assistant"&&e.content&&this.emitEvent({state:"delta",text:e.content});break}case"result":{if(e.status==="success")this.emitEvent({state:"final",agentSessionId:this.agentSessionId??void 0,usage:I(e.stats)});else if(e.status==="error"){const t=typeof e.error=="string"&&e.error||typeof e.message=="string"&&e.message||"gemini result error";this.emitEvent({state:"error",message:t})}break}default:break}}emitEvent(e){const t={...e,runId:this.runId,seq:this.seq++};this.emit("agentEvent",t)}async killProcess(){const e=this.process;e&&(this.process=null,e.kill("SIGTERM"),await new Promise(t=>{e.on("close",t),setTimeout(()=>{e.kill("SIGKILL"),t()},3e3)}))}}h("gemini",()=>new w);export{w as GeminiAdapter};
@@ -1,3 +1,3 @@
1
- import{createInterface as k}from"node:readline";import{resolveBuiltinCommand as l,spawnResolvedCommand as w}from"../command-spec.js";import{fallbackClaudeAliasModels as E,discoverClaudeAliasModelsFromEnv as x,fallbackCodexModels as M,fallbackWorkBuddyModels as R,fallbackGeminiModels as O,parseCodexAppServerModels as A,parseCursorModels as D,parseOpenCodeModels as I}from"./parsers.js";import{runResolvedCommand as m}from"./runner.js";import{DISCOVERY_WORKDIR as b,ModelDiscoveryFallbackError as C}from"./types.js";import{buildAgentProcessEnv as _,readLatestUserEnv as S}from"../../agent-env.js";import{CODEX_APP_SERVER_CLIENT_INFO as T}from"../codex-utils.js";import{PiRpcClient as P}from"../pi-rpc-client.js";import{loadConfig as $}from"../../config/index.js";import{discoverOpenCodeModelsViaApi as L}from"./opencode-api.js";function q(r){const e=r instanceof Error?r.message:"";return/timed out/i.test(e)?"app_server_timeout":/\berror\b|invalid|unsupported|unknown (?:method|field)/i.test(e)?"app_server_rpc_error":"app_server_unavailable"}function v(r,e,t,s,n,i){return r.stdin?new Promise((o,a)=>{const c=setTimeout(()=>{e.delete(t),a(new Error(`codex app-server request timed out: ${s}`))},i);e.set(t,{resolve:o,reject:a,timer:c}),r.stdin.write(`${JSON.stringify({id:t,method:s,params:n})}
2
- `,p=>{p&&(clearTimeout(c),e.delete(t),a(p))})}):Promise.reject(new Error("codex app-server stdin unavailable"))}async function j(r){const e=w(r,["app-server","--listen","stdio://"],{cwd:b,stdio:["pipe","pipe","pipe"],env:_({NO_COLOR:"1"})}),t=new Map;let s=1;k({input:e.stdout}).on("line",i=>{if(!i.trim())return;let o;try{o=JSON.parse(i)}catch{return}if(o.id==null)return;const a=t.get(o.id);a&&(clearTimeout(a.timer),t.delete(o.id),o.error?a.reject(new Error(o.error.message||`codex app-server error ${o.error.code??""}`.trim())):a.resolve(o.result))});try{await v(e,t,s++,"initialize",{clientInfo:T,capabilities:{experimentalApi:!0}},1e4);const[i,o]=await Promise.all([v(e,t,s++,"model/list",{},15e3),v(e,t,s++,"config/read",{},15e3).catch(()=>null)]),a=typeof o=="object"&&o!==null&&"config"in o?o.config:void 0;return A({...typeof i=="object"&&i!==null?i:{},config:a})}finally{for(const[i,o]of t)clearTimeout(o.timer),o.reject(new Error("codex app-server stopped")),t.delete(i);e.kill("SIGTERM"),setTimeout(()=>e.kill("SIGKILL"),1e3).unref()}}async function F(){const r=l("cursor");if(!r)return[];const e=await m(r,["--list-models"]);return D(e.stdout)}async function G(){const r=l("opencode");if(!r)return[];const e=await L().catch(()=>[]);if(e.length>0)return e;const t=await m(r,["models"]);return I(t.stdout)}async function N(){const r={id:"shennian-dashscope/deepseek-v4-flash-0731",name:"DeepSeek V4 Flash",provider:"shennian-dashscope",isDefault:!0,supportedReasoningEfforts:["low","high","max"].map(n=>({id:n,name:n})),defaultReasoningEffort:"high"},e=l("pi-coding-agent");if(!e)return[];if($().machineToken?.trim())return[r];const t=w(e,["--mode","rpc","--no-session","--offline","--no-extensions","--no-skills","--no-prompt-templates","--no-context-files","--no-tools"],{cwd:b,stdio:["pipe","pipe","pipe"],env:_({NO_COLOR:"1"})}),s=new P(t,{requestTimeoutMs:1e4});try{const[n,i]=await Promise.all([s.request("get_available_models"),s.request("get_state")]),o=n.data&&typeof n.data=="object"?n.data:{},a=i.data&&typeof i.data=="object"?i.data:{},c=typeof a.model?.id=="string"&&typeof a.model.provider=="string"?`${a.model.provider}/${a.model.id}`:null;return Array.isArray(o.models)?o.models.flatMap(f=>{if(!f||typeof f!="object")return[];const d=f;if(typeof d.id!="string"||typeof d.provider!="string")return[];const h=`${d.provider}/${d.id}`,g=d.reasoning===!0?["off","minimal","low","medium","high","xhigh","max"].map(y=>({id:y,name:y})):void 0;return[{id:h,name:typeof d.name=="string"&&d.name.trim()?d.name:d.id,provider:d.provider,isDefault:h===c,...g?{supportedReasoningEfforts:g,defaultReasoningEffort:"medium"}:{}}]}):[]}catch{return[]}finally{s.close(),t.kill("SIGTERM"),setTimeout(()=>t.kill("SIGKILL"),1e3).unref()}}async function V(){const r=l("claude");if(!r)return[];const e=S(),t=x(e);if(t.length>0)return t;const s=E(e),n=await m(r,["--help"],3e3).catch(()=>null);return!n||/\bfable\b/i.test(`${n.stdout}
3
- ${n.stderr}`)?s:s.filter(i=>i.id!=="fable")}async function B(){const r=l("codex");if(!r)return[];let e;try{e=await j(r)}catch(t){throw new C("codex",q(t),M())}if(e.length===0)throw new C("codex","empty_model_list",M());return e}async function K(){return l("gemini")?O():[]}const u=[{id:"qwen3.6-plus",name:"Qwen 3.6 Plus",provider:"dashscope",isDefault:!0}],U=[{id:"codex",name:"Codex",provider:"shennian",isDefault:!0},{id:"claude",name:"Claude Code",provider:"shennian"}];async function W(r){if(!r.serverUrl||!r.authToken)return u;try{const e=await fetch(`${r.serverUrl.replace(/\/$/,"")}/api/models`,{headers:{Authorization:`Bearer ${r.authToken}`}});if(!e.ok)return u;const t=await e.json(),s=(t.models??[]).map(n=>({id:n.id,name:n.name?.trim()||n.id,provider:n.provider,isDefault:n.id===t.default}));return s.length>0?s:u}catch{return u}}async function z(r,e){switch(r){case"claude":return V();case"codex":return B();case"workbuddy":return l("workbuddy")?R():[];case"gemini":return K();case"cursor":return F();case"openclaw":return[];case"opencode":return G();case"pi":return W(e);case"pi-coding-agent":return N();case"manager":return U}}async function ne(r,e){return r.type.startsWith("custom:")?r.models??[]:z(r.type,e)}export{ne as discoverModelsForAgent};
1
+ import{createInterface as _}from"node:readline";import{resolveBuiltinCommand as l,spawnResolvedCommand as w}from"../command-spec.js";import{fallbackClaudeAliasModels as E,discoverClaudeAliasModelsFromEnv as k,fallbackCodexModels as h,fallbackWorkBuddyModels as x,fallbackGeminiModels as R,parseCodexAppServerModels as O,parseCursorModels as A,parseOpenCodeModels as I}from"./parsers.js";import{runResolvedCommand as f}from"./runner.js";import{DISCOVERY_WORKDIR as M,ModelDiscoveryFallbackError as b}from"./types.js";import{buildAgentProcessEnv as C,readLatestUserEnv as P}from"../../agent-env.js";import{CODEX_APP_SERVER_CLIENT_INFO as S}from"../codex-utils.js";import{PiRpcClient as T}from"../pi-rpc-client.js";import{discoverOpenCodeModelsViaApi as $}from"./opencode-api.js";function D(r){const e=r instanceof Error?r.message:"";return/timed out/i.test(e)?"app_server_timeout":/\berror\b|invalid|unsupported|unknown (?:method|field)/i.test(e)?"app_server_rpc_error":"app_server_unavailable"}function m(r,e,t,n,s,i){return r.stdin?new Promise((o,a)=>{const p=setTimeout(()=>{e.delete(t),a(new Error(`codex app-server request timed out: ${n}`))},i);e.set(t,{resolve:o,reject:a,timer:p}),r.stdin.write(`${JSON.stringify({id:t,method:n,params:s})}
2
+ `,c=>{c&&(clearTimeout(p),e.delete(t),a(c))})}):Promise.reject(new Error("codex app-server stdin unavailable"))}async function L(r){const e=w(r,["app-server","--listen","stdio://"],{cwd:M,stdio:["pipe","pipe","pipe"],env:C({NO_COLOR:"1"})}),t=new Map;let n=1;_({input:e.stdout}).on("line",i=>{if(!i.trim())return;let o;try{o=JSON.parse(i)}catch{return}if(o.id==null)return;const a=t.get(o.id);a&&(clearTimeout(a.timer),t.delete(o.id),o.error?a.reject(new Error(o.error.message||`codex app-server error ${o.error.code??""}`.trim())):a.resolve(o.result))});try{await m(e,t,n++,"initialize",{clientInfo:S,capabilities:{experimentalApi:!0}},1e4);const[i,o]=await Promise.all([m(e,t,n++,"model/list",{},15e3),m(e,t,n++,"config/read",{},15e3).catch(()=>null)]),a=typeof o=="object"&&o!==null&&"config"in o?o.config:void 0;return O({...typeof i=="object"&&i!==null?i:{},config:a})}finally{for(const[i,o]of t)clearTimeout(o.timer),o.reject(new Error("codex app-server stopped")),t.delete(i);e.kill("SIGTERM"),setTimeout(()=>e.kill("SIGKILL"),1e3).unref()}}async function q(){const r=l("cursor");if(!r)return[];const e=await f(r,["--list-models"]);return A(e.stdout)}async function j(){const r=l("opencode");if(!r)return[];const e=await $().catch(()=>[]);if(e.length>0)return e;const t=await f(r,["models"]);return I(t.stdout)}async function G(){const r=l("pi-coding-agent");if(!r)return[];const e=w(r,["--mode","rpc","--no-session","--offline","--no-extensions","--no-skills","--no-prompt-templates","--no-context-files","--no-tools"],{cwd:M,stdio:["pipe","pipe","pipe"],env:C({NO_COLOR:"1"})}),t=new T(e,{requestTimeoutMs:1e4});try{const[n,s]=await Promise.all([t.request("get_available_models"),t.request("get_state")]),i=n.data&&typeof n.data=="object"?n.data:{},o=s.data&&typeof s.data=="object"?s.data:{},a=typeof o.model?.id=="string"&&typeof o.model.provider=="string"?`${o.model.provider}/${o.model.id}`:null;return Array.isArray(i.models)?i.models.flatMap(c=>{if(!c||typeof c!="object")return[];const d=c;if(typeof d.id!="string"||typeof d.provider!="string")return[];const v=`${d.provider}/${d.id}`,y=d.reasoning===!0?["off","minimal","low","medium","high","xhigh","max"].map(g=>({id:g,name:g})):void 0;return[{id:v,name:typeof d.name=="string"&&d.name.trim()?d.name:d.id,provider:d.provider,isDefault:v===a,...y?{supportedReasoningEfforts:y,defaultReasoningEffort:"medium"}:{}}]}):[]}catch{return[]}finally{t.close(),e.kill("SIGTERM"),setTimeout(()=>e.kill("SIGKILL"),1e3).unref()}}async function N(){const r=l("claude");if(!r)return[];const e=P(),t=k(e);if(t.length>0)return t;const n=E(e),s=await f(r,["--help"],3e3).catch(()=>null);return!s||/\bfable\b/i.test(`${s.stdout}
3
+ ${s.stderr}`)?n:n.filter(i=>i.id!=="fable")}async function F(){const r=l("codex");if(!r)return[];let e;try{e=await L(r)}catch(t){throw new b("codex",D(t),h())}if(e.length===0)throw new b("codex","empty_model_list",h());return e}async function B(){return l("gemini")?R():[]}const u=[{id:"qwen3.6-plus",name:"Qwen 3.6 Plus",provider:"dashscope",isDefault:!0}],V=[{id:"codex",name:"Codex",provider:"shennian",isDefault:!0},{id:"claude",name:"Claude Code",provider:"shennian"}];async function W(r){if(!r.serverUrl||!r.authToken)return u;try{const e=await fetch(`${r.serverUrl.replace(/\/$/,"")}/api/models`,{headers:{Authorization:`Bearer ${r.authToken}`}});if(!e.ok)return u;const t=await e.json(),n=(t.models??[]).map(s=>({id:s.id,name:s.name?.trim()||s.id,provider:s.provider,isDefault:s.id===t.default}));return n.length>0?n:u}catch{return u}}async function K(r,e){switch(r){case"claude":return N();case"codex":return F();case"workbuddy":return l("workbuddy")?x():[];case"gemini":return B();case"cursor":return q();case"openclaw":return[];case"opencode":return j();case"pi":return W(e);case"pi-coding-agent":return G();case"manager":return V}}async function re(r,e){return r.type.startsWith("custom:")?r.models??[]:r.type.startsWith("acp:")?[]:K(r.type,e)}export{re as discoverModelsForAgent};
@@ -1 +1 @@
1
- import{getAgentConfigSummary as y}from"../config-status.js";import{isCacheFresh as A,readCache as v,writeCache as S}from"./cache.js";import{discoverModelsForAgent as M}from"./discovery.js";import{ModelDiscoveryFallbackError as R}from"./types.js";import{getAgentRuntimeSummary as g}from"../runtime-compatibility.js";import{resolveManagedAgentRuntimeProtection as b}from"../../security/managed-agent-runtime.js";const x={claude:"claude-alias-v2",codex:"codex-app-server-v2",opencode:"opencode-connected-v1"};function F(o,s,e){console.warn(`[model-discovery] agent=${o} source=fallback reason=${s} usedCache=${e}`)}function E(o){const s=new Set,e=[];for(const i of o)!i.id||s.has(i.id)||(s.add(i.id),e.push(i));return e}function C(o){const s=o.type!=="manager"&&o.type!=="pi"&&o.type!=="openclaw",e=s,i=e&&!o.type.startsWith("acp:"),r=e?b({agentType:o.type,runtimeVersion:o.version,platform:o.runtimePlatform,isWsl:o.runtimeIsWsl,executableFingerprint:o.executableFingerprint,requireExecutableFingerprint:!0}):null,p=i&&(r?.level==="hard"||r?.level==="partial"),t=e,n=p||t,a=s;return{supportsStandardSession:s,supportsManagedAgent:p,supportsManagedNativeFull:t,supportsRoomTools:n,supportsWorker:a,supportsManagerMode:n&&a,supportsExternalWorkerTarget:a,...r?{managedAgentProtection:r}:{}}}function q(o){const s=v();return o.map(e=>{const i=y(e.type),r=g(e);return{type:e.type,models:s.agents[e.type]?.models??e.models??[],...e.integration?{integration:e.integration}:{},...e.display?{display:e.display}:{},...e.acpCapabilities?{acpCapabilities:e.acpCapabilities}:{},...e.authState?{authState:e.authState}:{},...e.acpAuthMethods?{acpAuthMethods:e.acpAuthMethods}:{},...e.catalogRevision?{catalogRevision:e.catalogRevision}:{},...C(e),...i?{config:i}:{},...r?{runtime:r}:{}}})}async function P(o,s){return I(o,s,{forceRefresh:!0})}async function I(o,s,e={}){const i=v();let r=!1;const p=[];for(const t of o){const n=i.agents[t.type],a=x[t.type],u=n&&(!a||n.sourceRevision===a)?n:void 0;let c;if(!e.forceRefresh&&A(n,t.version,a))c=n.models;else{let d=null;try{d=E(await M(t,s)),c=d.length>0?d:u?.models??t.models??[]}catch(l){if(l instanceof R){const m=!!u?.models.length;c=m?u.models:l.fallbackModels,F(t.type,l.failureCode,m)}else c=u?.models??t.models??[]}if(d&&d.length>0){const l={version:t.version,...a?{sourceRevision:a}:{},refreshedAt:Date.now(),models:c};JSON.stringify(n)!==JSON.stringify(l)&&(i.agents[t.type]=l,r=!0)}}const f=y(t.type),h=g(t);p.push({type:t.type,models:c,...t.integration?{integration:t.integration}:{},...t.display?{display:t.display}:{},...t.acpCapabilities?{acpCapabilities:t.acpCapabilities}:{},...t.authState?{authState:t.authState}:{},...t.acpAuthMethods?{acpAuthMethods:t.acpAuthMethods}:{},...t.catalogRevision?{catalogRevision:t.catalogRevision}:{},...C(t),...f?{config:f}:{},...h?{runtime:h}:{}})}return r&&S(i),p}export{q as getCachedAgentInfos,P as refreshAgentInfos,I as resolveAgentInfos};
1
+ import{getAgentConfigSummary as v}from"../config-status.js";import{isCacheFresh as M,readCache as f,writeCache as g}from"./cache.js";import{discoverModelsForAgent as b}from"./discovery.js";import{ModelDiscoveryFallbackError as x}from"./types.js";import{getAgentRuntimeSummary as C}from"../runtime-compatibility.js";import{isRestrictedRoomChatUnsupported as F,resolveManagedAgentRuntimeProtection as w}from"../../security/managed-agent-runtime.js";const E={claude:"claude-alias-v2",codex:"codex-app-server-v2",opencode:"opencode-connected-v1"};function O(t,s,e){console.warn(`[model-discovery] agent=${t} source=fallback reason=${s} usedCache=${e}`)}function A(t){const s=new Set,e=[];for(const r of t)!r.id||s.has(r.id)||(s.add(r.id),e.push(r));return e}function S(t){const s=t.type!=="manager"&&t.type!=="pi"&&t.type!=="openclaw",e=s,r=e&&!t.type.startsWith("acp:"),i=e?w({agentType:t.type,runtimeVersion:t.version,platform:t.runtimePlatform,isWsl:t.runtimeIsWsl,executableFingerprint:t.executableFingerprint,requireExecutableFingerprint:!0}):null,p=r&&!F(t.type)&&(i?.level==="hard"||i?.level==="partial"),o=e,n=p||o,a=s;return{supportsStandardSession:s,supportsManagedAgent:p,supportsManagedNativeFull:o,supportsRoomTools:n,supportsWorker:a,supportsManagerMode:n&&a,supportsExternalWorkerTarget:a,...i?{managedAgentProtection:i}:{}}}function R(t,s){return t.type==="opencode"&&(!t.authState||t.authState==="unknown")&&s.length>0?{authState:"ready"}:t.authState?{authState:t.authState}:{}}function P(t,s){if(!t.startsWith("acp:"))return!1;const e=A(s);if(e.length===0)return!1;const r=f(),i=r.agents[t];return JSON.stringify(i?.models)===JSON.stringify(e)?!1:(r.agents[t]={refreshedAt:Date.now(),models:e},g(r),!0)}function V(t){const s=f();return t.map(e=>{const r=v(e.type),i=C(e);return{type:e.type,models:s.agents[e.type]?.models??e.models??[],...e.integration?{integration:e.integration}:{},...e.display?{display:e.display}:{},...e.acpCapabilities?{acpCapabilities:e.acpCapabilities}:{},...R(e,s.agents[e.type]?.models??e.models??[]),...e.acpAuthMethods?{acpAuthMethods:e.acpAuthMethods}:{},...e.catalogRevision?{catalogRevision:e.catalogRevision}:{},...S(e),...r?{config:r}:{},...i?{runtime:i}:{}}})}async function _(t,s){return k(t,s,{forceRefresh:!0})}async function k(t,s,e={}){const r=f();let i=!1;const p=[];for(const o of t){const n=r.agents[o.type],a=E[o.type],u=n&&(!a||n.sourceRevision===a)?n:void 0;let c;if(!e.forceRefresh&&M(n,o.version,a))c=n.models;else{let d=null;try{d=A(await b(o,s)),c=d.length>0?d:u?.models??o.models??[]}catch(l){if(l instanceof x){const y=!!u?.models.length;c=y?u.models:l.fallbackModels,O(o.type,l.failureCode,y)}else c=u?.models??o.models??[]}if(d&&d.length>0){const l={version:o.version,...a?{sourceRevision:a}:{},refreshedAt:Date.now(),models:c};JSON.stringify(n)!==JSON.stringify(l)&&(r.agents[o.type]=l,i=!0)}}const h=v(o.type),m=C(o);p.push({type:o.type,models:c,...o.integration?{integration:o.integration}:{},...o.display?{display:o.display}:{},...o.acpCapabilities?{acpCapabilities:o.acpCapabilities}:{},...R(o,c),...o.acpAuthMethods?{acpAuthMethods:o.acpAuthMethods}:{},...o.catalogRevision?{catalogRevision:o.catalogRevision}:{},...S(o),...h?{config:h}:{},...m?{runtime:m}:{}})}return i&&g(r),p}export{V as getCachedAgentInfos,P as recordAcpAgentModels,_ as refreshAgentInfos,k as resolveAgentInfos};
@@ -1 +1 @@
1
- import{getCachedAgentInfos as m,refreshAgentInfos as u,resolveAgentInfos as v}from"./model-registry/service.js";import{applyClaudeModelEnvOverrides as e,discoverClaudeAliasModelsFromEnv as s,fallbackCodexModels as o,fallbackClaudeAliasModels as l,parseClaudeBinaryModels as r,parseClaudeModels as d,parseCodexModels as a,parseCodexAppServerModels as p,parseCursorModels as n,parseGeminiModels as i,parseOpenClawModels as t,stripAnsi as C}from"./model-registry/parsers.js";const f={applyClaudeModelEnvOverrides:e,discoverClaudeAliasModelsFromEnv:s,fallbackCodexModels:o,fallbackClaudeAliasModels:l,parseClaudeBinaryModels:r,parseClaudeModels:d,parseCodexModels:a,parseCodexAppServerModels:p,parseCursorModels:n,parseOpenClawModels:t,parseGeminiModels:i,stripAnsi:C};export{m as getCachedAgentInfos,f as modelSwitchingTestExports,u as refreshAgentInfos,v as resolveAgentInfos};
1
+ import{getCachedAgentInfos as g,recordAcpAgentModels as m,refreshAgentInfos as u,resolveAgentInfos as v}from"./model-registry/service.js";import{applyClaudeModelEnvOverrides as e,discoverClaudeAliasModelsFromEnv as s,fallbackCodexModels as o,fallbackClaudeAliasModels as r,parseClaudeBinaryModels as l,parseClaudeModels as d,parseCodexModels as a,parseCodexAppServerModels as p,parseCursorModels as n,parseGeminiModels as t,parseOpenClawModels as i,stripAnsi as M}from"./model-registry/parsers.js";const A={applyClaudeModelEnvOverrides:e,discoverClaudeAliasModelsFromEnv:s,fallbackCodexModels:o,fallbackClaudeAliasModels:r,parseClaudeBinaryModels:l,parseClaudeModels:d,parseCodexModels:a,parseCodexAppServerModels:p,parseCursorModels:n,parseOpenClawModels:i,parseGeminiModels:t,stripAnsi:M};export{g as getCachedAgentInfos,A as modelSwitchingTestExports,m as recordAcpAgentModels,u as refreshAgentInfos,v as resolveAgentInfos};
@@ -1,2 +1,2 @@
1
- import{randomUUID as h}from"node:crypto";import{AgentAdapter as E}from"./adapter.js";import{resolveBuiltinCommand as g,spawnResolvedCommand as w}from"./command-spec.js";import{buildAgentProcessEnv as I}from"../agent-env.js";import{buildInlineChannelPreamble as x}from"./platform-instructions.js";function C(r){if(r==null)return"";if(typeof r=="string")return r;if(typeof r=="object"){const t=r;if(Array.isArray(t.payloads)){const a=[];for(const n of t.payloads)if(n&&typeof n=="object"){const s=n.text;typeof s=="string"&&a.push(s)}if(a.join("").trim())return a.join(`
2
- `)}const e=t.response??t.message??t.text??t.output??t.content??t.result;if(typeof e=="string"&&e.trim())return e}return""}function k(r){if(r==null||typeof r!="object")return;const t=r,n=t.meta?.agentMeta?.sessionId??t.sessionId??t.session_id;return typeof n=="string"&&n?n:void 0}function v(r){if(r==null||typeof r!="object")return;const t=r,n=t.meta?.agentMeta?.usage??t.usage;if(!n||typeof n!="object")return;const s=n,u=s.input??s.inputTokens??s.input_tokens,o=s.output??s.outputTokens??s.output_tokens;if(!(typeof u!="number"&&typeof o!="number"))return{inputTokens:typeof u=="number"?u:0,outputTokens:typeof o=="number"?o:0}}function y(r){if(r==null||typeof r!="object")return;const t=r,e=t.error??t.err??t.errorMessage;if(typeof e=="string"&&e.trim())return e}class O extends E{type="openclaw";process=null;sessionId=null;agentSessionId=null;currentModelId=null;workDir=null;seq=0;runId="";externalChannel=null;shennianSessionId=null;extraEnv={};configure(t){this.shennianSessionId=t.sessionId??null,this.externalChannel=t.externalChannel??null,this.extraEnv=t.env??{}}async start(t,e,a){this.sessionId=t,this.workDir=e,this.seq=0,a&&(this.agentSessionId=a)}async send(t,e,a,n,s){await this.killProcess(),this.runId=h(),this.seq=0;const u=this.agentSessionId??this.sessionId;if(!u){this.emitEvent({state:"error",message:"openclaw: session not started"});return}if(e&&e!==this.currentModelId){const i=await this.runAgentCommand(["--message",`/model ${e}`,"--session-id",u]);if(!i.ok){this.emitEvent({state:"error",message:i.error??"openclaw model switch failed"});return}this.currentModelId=e}const o=`${x(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0,s)}${t}`;this.spawnAgent(["--message",o,"--session-id",u])}async resume(t){await this.killProcess(),this.agentSessionId=t,this.runId=h(),this.seq=0,this.spawnAgent(["--message","\u200B","--session-id",t])}async stop(){await this.killProcess()}spawnAgent(t){const e=g("openclaw");if(!e){this.emit("error",new Error('Command "openclaw" not found. Is OpenClaw CLI installed?'));return}const a=["agent","--local","--json",...t],n=w(e,a,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:I(this.extraEnv)});this.process=n;let s="";n.stdout?.on("data",o=>{s+=o.toString()});let u="";n.stderr?.on("data",o=>{u+=o.toString()}),n.on("close",o=>{if(this.process!==n)return;if(this.process=null,o!==0&&o!==null){const f=u.trim()||`openclaw exited with code ${o}`;this.emitEvent({state:"error",message:f});return}const i=s.trim();if(!i){const f=u.trim()||"openclaw returned empty stdout";this.emitEvent({state:"error",message:f});return}let c;try{c=JSON.parse(i)}catch{this.emitEvent({state:"error",message:`openclaw stdout is not valid JSON: ${i.slice(0,200)}`});return}const l=c;if(l.ok===!1||l.success===!1){this.emitEvent({state:"error",message:y(c)??"openclaw request failed"});return}const p=k(c);p&&(this.agentSessionId=p);const m=C(c);m&&this.emitEvent({state:"delta",text:m});const S=v(c);this.emitEvent({state:"final",agentSessionId:this.agentSessionId??void 0,usage:S})}),n.on("error",o=>{this.process===n&&(this.process=null,o.code==="ENOENT"?this.emit("error",new Error('Command "openclaw" not found. Is OpenClaw CLI installed?')):this.emit("error",o))})}async runAgentCommand(t){return new Promise(e=>{const a=g("openclaw");if(!a){e({ok:!1,error:'Command "openclaw" not found. Is OpenClaw CLI installed?'});return}const n=["agent","--local","--json",...t],s=w(a,n,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:I(this.extraEnv)});let u="",o="";s.stdout?.on("data",i=>{u+=i.toString()}),s.stderr?.on("data",i=>{o+=i.toString()}),s.on("close",i=>{if(i!==0&&i!==null){e({ok:!1,error:o.trim()||`openclaw exited with code ${i}`});return}const c=u.trim();if(!c){e({ok:!0});return}try{const l=JSON.parse(c);if(l.ok===!1||l.success===!1){e({ok:!1,error:y(l)??"openclaw request failed"});return}const d=k(l);d&&(this.agentSessionId=d),e({ok:!0,parsed:l})}catch{e({ok:!1,error:`openclaw stdout is not valid JSON: ${c.slice(0,200)}`})}}),s.on("error",i=>{e({ok:!1,error:i instanceof Error?i.message:String(i)})})})}emitEvent(t){const e={...t,runId:this.runId,seq:this.seq++};this.emit("agentEvent",e)}async killProcess(){const t=this.process;t&&(this.process=null,t.kill("SIGTERM"),await new Promise(e=>{t.on("close",e),setTimeout(()=>{t.kill("SIGKILL"),e()},3e3)}))}}export{O as OpenClawAdapter};
1
+ import{randomUUID as h}from"node:crypto";import{AgentAdapter as S}from"./adapter.js";import{resolveBuiltinCommand as g,spawnResolvedCommand as w}from"./command-spec.js";import{spawnEnoentError as x}from"./spawn-errors.js";import{buildAgentProcessEnv as I}from"../agent-env.js";import{buildInlineChannelPreamble as C}from"./platform-instructions.js";function v(r){if(r==null)return"";if(typeof r=="string")return r;if(typeof r=="object"){const t=r;if(Array.isArray(t.payloads)){const a=[];for(const n of t.payloads)if(n&&typeof n=="object"){const s=n.text;typeof s=="string"&&a.push(s)}if(a.join("").trim())return a.join(`
2
+ `)}const e=t.response??t.message??t.text??t.output??t.content??t.result;if(typeof e=="string"&&e.trim())return e}return""}function k(r){if(r==null||typeof r!="object")return;const t=r,n=t.meta?.agentMeta?.sessionId??t.sessionId??t.session_id;return typeof n=="string"&&n?n:void 0}function b(r){if(r==null||typeof r!="object")return;const t=r,n=t.meta?.agentMeta?.usage??t.usage;if(!n||typeof n!="object")return;const s=n,u=s.input??s.inputTokens??s.input_tokens,o=s.output??s.outputTokens??s.output_tokens;if(!(typeof u!="number"&&typeof o!="number"))return{inputTokens:typeof u=="number"?u:0,outputTokens:typeof o=="number"?o:0}}function y(r){if(r==null||typeof r!="object")return;const t=r,e=t.error??t.err??t.errorMessage;if(typeof e=="string"&&e.trim())return e}class P extends S{type="openclaw";process=null;sessionId=null;agentSessionId=null;currentModelId=null;workDir=null;seq=0;runId="";externalChannel=null;shennianSessionId=null;extraEnv={};configure(t){this.shennianSessionId=t.sessionId??null,this.externalChannel=t.externalChannel??null,this.extraEnv=t.env??{}}async start(t,e,a){this.sessionId=t,this.workDir=e,this.seq=0,a&&(this.agentSessionId=a)}async send(t,e,a,n,s){await this.killProcess(),this.runId=h(),this.seq=0;const u=this.agentSessionId??this.sessionId;if(!u){this.emitEvent({state:"error",message:"openclaw: session not started"});return}if(e&&e!==this.currentModelId){const i=await this.runAgentCommand(["--message",`/model ${e}`,"--session-id",u]);if(!i.ok){this.emitEvent({state:"error",message:i.error??"openclaw model switch failed"});return}this.currentModelId=e}const o=`${C(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0,s)}${t}`;this.spawnAgent(["--message",o,"--session-id",u])}async resume(t){await this.killProcess(),this.agentSessionId=t,this.runId=h(),this.seq=0,this.spawnAgent(["--message","\u200B","--session-id",t])}async stop(){await this.killProcess()}spawnAgent(t){const e=g("openclaw");if(!e){this.emit("error",x(this.workDir,'Command "openclaw" not found. Is OpenClaw CLI installed?'));return}const a=["agent","--local","--json",...t],n=w(e,a,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:I(this.extraEnv)});this.process=n;let s="";n.stdout?.on("data",o=>{s+=o.toString()});let u="";n.stderr?.on("data",o=>{u+=o.toString()}),n.on("close",o=>{if(this.process!==n)return;if(this.process=null,o!==0&&o!==null){const f=u.trim()||`openclaw exited with code ${o}`;this.emitEvent({state:"error",message:f});return}const i=s.trim();if(!i){const f=u.trim()||"openclaw returned empty stdout";this.emitEvent({state:"error",message:f});return}let c;try{c=JSON.parse(i)}catch{this.emitEvent({state:"error",message:`openclaw stdout is not valid JSON: ${i.slice(0,200)}`});return}const l=c;if(l.ok===!1||l.success===!1){this.emitEvent({state:"error",message:y(c)??"openclaw request failed"});return}const p=k(c);p&&(this.agentSessionId=p);const m=v(c);m&&this.emitEvent({state:"delta",text:m});const E=b(c);this.emitEvent({state:"final",agentSessionId:this.agentSessionId??void 0,usage:E})}),n.on("error",o=>{this.process===n&&(this.process=null,o.code==="ENOENT"?this.emit("error",new Error('Command "openclaw" not found. Is OpenClaw CLI installed?')):this.emit("error",o))})}async runAgentCommand(t){return new Promise(e=>{const a=g("openclaw");if(!a){e({ok:!1,error:'Command "openclaw" not found. Is OpenClaw CLI installed?'});return}const n=["agent","--local","--json",...t],s=w(a,n,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:I(this.extraEnv)});let u="",o="";s.stdout?.on("data",i=>{u+=i.toString()}),s.stderr?.on("data",i=>{o+=i.toString()}),s.on("close",i=>{if(i!==0&&i!==null){e({ok:!1,error:o.trim()||`openclaw exited with code ${i}`});return}const c=u.trim();if(!c){e({ok:!0});return}try{const l=JSON.parse(c);if(l.ok===!1||l.success===!1){e({ok:!1,error:y(l)??"openclaw request failed"});return}const d=k(l);d&&(this.agentSessionId=d),e({ok:!0,parsed:l})}catch{e({ok:!1,error:`openclaw stdout is not valid JSON: ${c.slice(0,200)}`})}}),s.on("error",i=>{e({ok:!1,error:i instanceof Error?i.message:String(i)})})})}emitEvent(t){const e={...t,runId:this.runId,seq:this.seq++};this.emit("agentEvent",e)}async killProcess(){const t=this.process;t&&(this.process=null,t.kill("SIGTERM"),await new Promise(e=>{t.on("close",e),setTimeout(()=>{t.kill("SIGKILL"),e()},3e3)}))}}export{P as OpenClawAdapter};