shennian 0.5.0 → 0.5.1

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 (336) hide show
  1. package/README.md +2 -2
  2. package/dist/publish-build-manifest.json +157 -107
  3. package/dist/src/agents/acp/capability-cache.js +2 -2
  4. package/dist/src/agents/acp/catalog.js +2 -2
  5. package/dist/src/agents/acp/manifests.js +2 -2
  6. package/dist/src/agents/claude.js +8 -6
  7. package/dist/src/agents/codex.js +2 -2
  8. package/dist/src/agents/command-spec.js +4 -4
  9. package/dist/src/agents/cursor.js +1 -1
  10. package/dist/src/agents/custom-recovery-conformance.js +2 -2
  11. package/dist/src/agents/gemini.js +1 -1
  12. package/dist/src/agents/model-registry/service.js +1 -1
  13. package/dist/src/agents/openclaw.js +2 -2
  14. package/dist/src/agents/opencode.js +1 -1
  15. package/dist/src/agents/pi-coding-agent.js +4 -4
  16. package/dist/src/agents/pi-session-ownership.js +2 -2
  17. package/dist/src/agents/spawn-errors.js +1 -0
  18. package/dist/src/agents/windows-agent-paths.js +1 -0
  19. package/dist/src/commands/agent-readiness.js +2 -2
  20. package/dist/src/commands/daemon-service-spec.js +1 -1
  21. package/dist/src/commands/daemon.js +6 -6
  22. package/dist/src/commands/queue.js +1 -0
  23. package/dist/src/commands/room.js +3 -3
  24. package/dist/src/config/index.js +2 -2
  25. package/dist/src/fs/atomic-rename.js +1 -0
  26. package/dist/src/index.js +3 -3
  27. package/dist/src/native-fusion/claude-entry-parser.js +7 -0
  28. package/dist/src/native-fusion/local-repository.js +2 -2
  29. package/dist/src/native-fusion/native-source-deletions.js +2 -2
  30. package/dist/src/native-fusion/parsers.js +1 -3
  31. package/dist/src/native-fusion/state.js +2 -2
  32. package/dist/src/personal-sync/epoch.js +2 -2
  33. package/dist/src/personal-sync/identity.js +2 -2
  34. package/dist/src/relay/client.js +1 -1
  35. package/dist/src/room/activation-service.js +6 -6
  36. package/dist/src/room/attachment-cache.js +2 -2
  37. package/dist/src/room/host-session-observations.js +2 -2
  38. package/dist/src/room/managed-context.js +1 -1
  39. package/dist/src/room/managed-room-ipc.js +2 -2
  40. package/dist/src/room/mirror-sync-service.js +1 -1
  41. package/dist/src/room/public-attachment-cache.js +2 -2
  42. package/dist/src/room/room-error-guidance.js +1 -0
  43. package/dist/src/room/session-registry.js +2 -2
  44. package/dist/src/security/managed-agent-policy.js +1 -1
  45. package/dist/src/security/managed-agent-runtime.js +1 -1
  46. package/dist/src/session/attachment-transfer-store.js +2 -2
  47. package/dist/src/session/canonical-store.js +5 -5
  48. package/dist/src/session/deletion-sync-state.js +2 -2
  49. package/dist/src/session/handlers/chat-adapter-config.js +1 -1
  50. package/dist/src/session/handlers/chat-events.js +2 -2
  51. package/dist/src/session/handlers/chat-recovery.js +1 -1
  52. package/dist/src/session/handlers/chat.js +1 -1
  53. package/dist/src/session/manager.js +1 -1
  54. package/dist/src/session/native-cleanup-outbox.js +2 -2
  55. package/dist/src/session/queue-diagnostics.js +1 -0
  56. package/dist/src/session/queue-dispatch-failure.js +1 -0
  57. package/dist/src/session/queue-helpers.js +5 -5
  58. package/dist/src/session/queue-retry.js +1 -1
  59. package/dist/src/session/queue-storage.js +2 -2
  60. package/dist/src/session/queue.js +1 -1
  61. package/dist/src/session/room-reply-notice.js +1 -0
  62. package/dist/src/session/run-recovery/journal.js +2 -2
  63. package/dist/src/session/run-stall.js +1 -0
  64. package/dist/src/session/store.js +2 -2
  65. package/dist/src/session/tool-detail-store.js +2 -2
  66. package/node_modules/@shennian/wire/dist/agent-capabilities.js +1 -1
  67. package/node_modules/@shennian/wire/dist/agent-workspace.js +1 -144
  68. package/node_modules/@shennian/wire/dist/envelope.js +1 -1
  69. package/node_modules/@shennian/wire/dist/events.js +1 -1
  70. package/node_modules/@shennian/wire/dist/external-message-format.js +3 -70
  71. package/node_modules/@shennian/wire/dist/frames.js +1 -1
  72. package/node_modules/@shennian/wire/dist/fs.js +2 -7
  73. package/node_modules/@shennian/wire/dist/index.js +1 -21
  74. package/node_modules/@shennian/wire/dist/machine.js +1 -1
  75. package/node_modules/@shennian/wire/dist/message-payload.js +8 -307
  76. package/node_modules/@shennian/wire/dist/methods.js +1 -3
  77. package/node_modules/@shennian/wire/dist/native-session.js +1 -1
  78. package/node_modules/@shennian/wire/dist/project-fs.js +1 -462
  79. package/node_modules/@shennian/wire/dist/project-path.js +1 -25
  80. package/node_modules/@shennian/wire/dist/project.js +1 -3
  81. package/node_modules/@shennian/wire/dist/relay-connectivity.js +1 -29
  82. package/node_modules/@shennian/wire/dist/room.js +1 -20
  83. package/node_modules/@shennian/wire/dist/schedule.js +1 -1
  84. package/node_modules/@shennian/wire/dist/session-sync.js +1 -123
  85. package/node_modules/@shennian/wire/dist/session.js +1 -60
  86. package/node_modules/@shennian/wire/dist/tool-detail.js +1 -9
  87. package/node_modules/@shennian/wire/dist/voice-chief.js +1 -3
  88. package/package.json +3 -8
  89. package/dist/bin/shennian.d.ts +0 -2
  90. package/dist/src/agent-env.d.ts +0 -44
  91. package/dist/src/agents/acp/adapter.d.ts +0 -82
  92. package/dist/src/agents/acp/auth-state.d.ts +0 -3
  93. package/dist/src/agents/acp/auth.d.ts +0 -7
  94. package/dist/src/agents/acp/capability-cache.d.ts +0 -14
  95. package/dist/src/agents/acp/catalog.d.ts +0 -11
  96. package/dist/src/agents/acp/client-services.d.ts +0 -37
  97. package/dist/src/agents/acp/discovery.d.ts +0 -10
  98. package/dist/src/agents/acp/events.d.ts +0 -4
  99. package/dist/src/agents/acp/manifests.d.ts +0 -63
  100. package/dist/src/agents/acp/metrics.d.ts +0 -24
  101. package/dist/src/agents/acp/package-commands.d.ts +0 -4
  102. package/dist/src/agents/acp/process-client.d.ts +0 -41
  103. package/dist/src/agents/acp/process-tree.d.ts +0 -2
  104. package/dist/src/agents/acp/types.d.ts +0 -31
  105. package/dist/src/agents/acp/watcher.d.ts +0 -22
  106. package/dist/src/agents/adapter.d.ts +0 -180
  107. package/dist/src/agents/auth-status.d.ts +0 -4
  108. package/dist/src/agents/claude-managed-permissions.d.ts +0 -33
  109. package/dist/src/agents/claude.d.ts +0 -69
  110. package/dist/src/agents/codex-managed-permissions.d.ts +0 -32
  111. package/dist/src/agents/codex-managed-room-tools.d.ts +0 -41
  112. package/dist/src/agents/codex-protocol.d.ts +0 -103
  113. package/dist/src/agents/codex-runtime.d.ts +0 -91
  114. package/dist/src/agents/codex-utils.d.ts +0 -29
  115. package/dist/src/agents/codex.d.ts +0 -59
  116. package/dist/src/agents/command-spec.d.ts +0 -55
  117. package/dist/src/agents/config-status.d.ts +0 -18
  118. package/dist/src/agents/cursor-managed-permissions.d.ts +0 -28
  119. package/dist/src/agents/cursor.d.ts +0 -44
  120. package/dist/src/agents/custom-managed-runtime.d.ts +0 -37
  121. package/dist/src/agents/custom-recovery-conformance.d.ts +0 -2
  122. package/dist/src/agents/custom.d.ts +0 -62
  123. package/dist/src/agents/detect.d.ts +0 -23
  124. package/dist/src/agents/event-terminal-gate.d.ts +0 -16
  125. package/dist/src/agents/external-channel-instructions.d.ts +0 -4
  126. package/dist/src/agents/gemini.d.ts +0 -32
  127. package/dist/src/agents/manager.d.ts +0 -57
  128. package/dist/src/agents/model-registry/cache.d.ts +0 -4
  129. package/dist/src/agents/model-registry/discovery.d.ts +0 -4
  130. package/dist/src/agents/model-registry/opencode-api.d.ts +0 -2
  131. package/dist/src/agents/model-registry/parsers.d.ts +0 -20
  132. package/dist/src/agents/model-registry/runner.d.ts +0 -6
  133. package/dist/src/agents/model-registry/service.d.ts +0 -10
  134. package/dist/src/agents/model-registry/types.d.ts +0 -39
  135. package/dist/src/agents/model-registry.d.ts +0 -17
  136. package/dist/src/agents/native-capabilities.d.ts +0 -10
  137. package/dist/src/agents/openclaw.d.ts +0 -29
  138. package/dist/src/agents/opencode-managed-permissions.d.ts +0 -25
  139. package/dist/src/agents/opencode.d.ts +0 -46
  140. package/dist/src/agents/pi-coding-agent-managed-permissions.d.ts +0 -7
  141. package/dist/src/agents/pi-coding-agent.d.ts +0 -63
  142. package/dist/src/agents/pi-managed-extension.d.ts +0 -12
  143. package/dist/src/agents/pi-managed-model-broker.d.ts +0 -27
  144. package/dist/src/agents/pi-rpc-client.d.ts +0 -31
  145. package/dist/src/agents/pi-session-ownership.d.ts +0 -2
  146. package/dist/src/agents/platform-instructions.d.ts +0 -5
  147. package/dist/src/agents/runtime-compatibility.d.ts +0 -11
  148. package/dist/src/agents/workbuddy-managed-permissions.d.ts +0 -37
  149. package/dist/src/agents/workbuddy.d.ts +0 -63
  150. package/dist/src/commands/agent-readiness.d.ts +0 -17
  151. package/dist/src/commands/agent.d.ts +0 -2
  152. package/dist/src/commands/daemon-instance-lock.d.ts +0 -21
  153. package/dist/src/commands/daemon-process.d.ts +0 -6
  154. package/dist/src/commands/daemon-service-spec.d.ts +0 -26
  155. package/dist/src/commands/daemon-start-wait.d.ts +0 -9
  156. package/dist/src/commands/daemon-state.d.ts +0 -57
  157. package/dist/src/commands/daemon-windows.d.ts +0 -33
  158. package/dist/src/commands/daemon.d.ts +0 -67
  159. package/dist/src/commands/integration.d.ts +0 -3
  160. package/dist/src/commands/logout.d.ts +0 -3
  161. package/dist/src/commands/manager.d.ts +0 -2
  162. package/dist/src/commands/pair-authorization.d.ts +0 -3
  163. package/dist/src/commands/pair-browser.d.ts +0 -44
  164. package/dist/src/commands/pair-qr.d.ts +0 -4
  165. package/dist/src/commands/pair.d.ts +0 -19
  166. package/dist/src/commands/room.d.ts +0 -16
  167. package/dist/src/commands/runtime.d.ts +0 -2
  168. package/dist/src/commands/schedule.d.ts +0 -2
  169. package/dist/src/commands/tools.d.ts +0 -2
  170. package/dist/src/commands/upgrade.d.ts +0 -31
  171. package/dist/src/commands/worker.d.ts +0 -11
  172. package/dist/src/config/index.d.ts +0 -58
  173. package/dist/src/daemon-ipc/agent-readiness.d.ts +0 -15
  174. package/dist/src/daemon-ipc/client.d.ts +0 -8
  175. package/dist/src/daemon-ipc/control.d.ts +0 -16
  176. package/dist/src/daemon-ipc/json.d.ts +0 -3
  177. package/dist/src/daemon-ipc/paths.d.ts +0 -15
  178. package/dist/src/daemon-ipc/protocol.d.ts +0 -31
  179. package/dist/src/daemon-ipc/secret.d.ts +0 -3
  180. package/dist/src/daemon-ipc/server.d.ts +0 -20
  181. package/dist/src/daemon-log.d.ts +0 -9
  182. package/dist/src/env-path.d.ts +0 -15
  183. package/dist/src/fs/boundary.d.ts +0 -23
  184. package/dist/src/fs/handler.d.ts +0 -26
  185. package/dist/src/fs/security.d.ts +0 -2
  186. package/dist/src/fs/text-decoder.d.ts +0 -10
  187. package/dist/src/index.d.ts +0 -1
  188. package/dist/src/log-redaction.d.ts +0 -4
  189. package/dist/src/log-reporter.d.ts +0 -41
  190. package/dist/src/manager/prompt.d.ts +0 -2
  191. package/dist/src/manager/registry.d.ts +0 -184
  192. package/dist/src/manager/retired-external-channel-compat.d.ts +0 -78
  193. package/dist/src/manager/runtime.d.ts +0 -90
  194. package/dist/src/manager/worker-ipc.d.ts +0 -28
  195. package/dist/src/manager/worker-markdown.d.ts +0 -10
  196. package/dist/src/native-fusion/codex-files.d.ts +0 -10
  197. package/dist/src/native-fusion/codex-message-parser.d.ts +0 -9
  198. package/dist/src/native-fusion/codex-parser.d.ts +0 -8
  199. package/dist/src/native-fusion/codex-user-input.d.ts +0 -11
  200. package/dist/src/native-fusion/config.d.ts +0 -1
  201. package/dist/src/native-fusion/file-identity.d.ts +0 -9
  202. package/dist/src/native-fusion/file-watcher.d.ts +0 -26
  203. package/dist/src/native-fusion/local-repository.d.ts +0 -90
  204. package/dist/src/native-fusion/native-source-deletions.d.ts +0 -47
  205. package/dist/src/native-fusion/opencode-parser.d.ts +0 -29
  206. package/dist/src/native-fusion/parser-common.d.ts +0 -35
  207. package/dist/src/native-fusion/parsers.d.ts +0 -13
  208. package/dist/src/native-fusion/service.d.ts +0 -64
  209. package/dist/src/native-fusion/session-header.d.ts +0 -13
  210. package/dist/src/native-fusion/session-native-sources.d.ts +0 -24
  211. package/dist/src/native-fusion/source-visibility-audit.d.ts +0 -16
  212. package/dist/src/native-fusion/source-visibility.d.ts +0 -25
  213. package/dist/src/native-fusion/state.d.ts +0 -4
  214. package/dist/src/native-fusion/types.d.ts +0 -82
  215. package/dist/src/personal-sync/epoch.d.ts +0 -17
  216. package/dist/src/personal-sync/identity.d.ts +0 -1
  217. package/dist/src/personal-sync/machine-authority.d.ts +0 -12
  218. package/dist/src/personal-sync/metrics.d.ts +0 -25
  219. package/dist/src/personal-sync/paths.d.ts +0 -5
  220. package/dist/src/region.d.ts +0 -15
  221. package/dist/src/relay/client.d.ts +0 -81
  222. package/dist/src/room/activation-audit.d.ts +0 -15
  223. package/dist/src/room/activation-policy.d.ts +0 -8
  224. package/dist/src/room/activation-service.d.ts +0 -77
  225. package/dist/src/room/attachment-cache.d.ts +0 -44
  226. package/dist/src/room/attachment-upload.d.ts +0 -20
  227. package/dist/src/room/device-authorization-client.d.ts +0 -91
  228. package/dist/src/room/host-session-observations.d.ts +0 -54
  229. package/dist/src/room/invite-bootstrap.d.ts +0 -49
  230. package/dist/src/room/invite-qr.d.ts +0 -6
  231. package/dist/src/room/live-delivery.d.ts +0 -5
  232. package/dist/src/room/managed-context.d.ts +0 -49
  233. package/dist/src/room/managed-prompt-composer.d.ts +0 -47
  234. package/dist/src/room/managed-room-binding.d.ts +0 -69
  235. package/dist/src/room/managed-room-ipc.d.ts +0 -65
  236. package/dist/src/room/mirror-sync-service.d.ts +0 -49
  237. package/dist/src/room/public-attachment-cache.d.ts +0 -34
  238. package/dist/src/room/public-room-client.d.ts +0 -37
  239. package/dist/src/room/registration-authority.d.ts +0 -4
  240. package/dist/src/room/room-action-client-types.d.ts +0 -137
  241. package/dist/src/room/room-action-client.d.ts +0 -116
  242. package/dist/src/room/room-binding-client.d.ts +0 -62
  243. package/dist/src/room/session-registry.d.ts +0 -158
  244. package/dist/src/runtime-distribution.d.ts +0 -7
  245. package/dist/src/schedules/personal-context.d.ts +0 -2
  246. package/dist/src/schedules/server-client.d.ts +0 -19
  247. package/dist/src/security/managed-agent-credential-paths.d.ts +0 -6
  248. package/dist/src/security/managed-agent-executable.d.ts +0 -19
  249. package/dist/src/security/managed-agent-policy.d.ts +0 -66
  250. package/dist/src/security/managed-agent-runtime.d.ts +0 -44
  251. package/dist/src/session/archive-zip.d.ts +0 -10
  252. package/dist/src/session/attachment-reference.d.ts +0 -2
  253. package/dist/src/session/attachment-transfer-store.d.ts +0 -45
  254. package/dist/src/session/canonical-store.d.ts +0 -104
  255. package/dist/src/session/deletion-sync-state.d.ts +0 -20
  256. package/dist/src/session/deletion-sync-validation.d.ts +0 -2
  257. package/dist/src/session/deletion-synchronizer.d.ts +0 -9
  258. package/dist/src/session/handlers/agent-capabilities.d.ts +0 -3
  259. package/dist/src/session/handlers/agent-config.d.ts +0 -7
  260. package/dist/src/session/handlers/agent-control.d.ts +0 -4
  261. package/dist/src/session/handlers/agent-workspace-validation.d.ts +0 -28
  262. package/dist/src/session/handlers/agents.d.ts +0 -11
  263. package/dist/src/session/handlers/chat-adapter-config.d.ts +0 -11
  264. package/dist/src/session/handlers/chat-context.d.ts +0 -31
  265. package/dist/src/session/handlers/chat-events.d.ts +0 -5
  266. package/dist/src/session/handlers/chat-recovery.d.ts +0 -4
  267. package/dist/src/session/handlers/chat-session-lifecycle.d.ts +0 -9
  268. package/dist/src/session/handlers/chat.d.ts +0 -6
  269. package/dist/src/session/handlers/control.d.ts +0 -5
  270. package/dist/src/session/handlers/fs.d.ts +0 -14
  271. package/dist/src/session/handlers/message-status.d.ts +0 -3
  272. package/dist/src/session/handlers/pi-validation-session.d.ts +0 -7
  273. package/dist/src/session/handlers/project-fs.d.ts +0 -11
  274. package/dist/src/session/handlers/remote-access.d.ts +0 -4
  275. package/dist/src/session/handlers/room-managed.d.ts +0 -6
  276. package/dist/src/session/handlers/session-refresh.d.ts +0 -3
  277. package/dist/src/session/handlers/title.d.ts +0 -3
  278. package/dist/src/session/handlers/tool-detail.d.ts +0 -3
  279. package/dist/src/session/handlers/voice-window.d.ts +0 -3
  280. package/dist/src/session/history-subscriptions.d.ts +0 -29
  281. package/dist/src/session/index-publisher.d.ts +0 -3
  282. package/dist/src/session/manager-event-authority.d.ts +0 -3
  283. package/dist/src/session/manager.d.ts +0 -95
  284. package/dist/src/session/native-cleanup-outbox.d.ts +0 -64
  285. package/dist/src/session/native-session-lifecycle.d.ts +0 -56
  286. package/dist/src/session/project-fs-store.d.ts +0 -43
  287. package/dist/src/session/projection.d.ts +0 -3
  288. package/dist/src/session/queue-control.d.ts +0 -27
  289. package/dist/src/session/queue-helpers.d.ts +0 -20
  290. package/dist/src/session/queue-message.d.ts +0 -35
  291. package/dist/src/session/queue-retry.d.ts +0 -11
  292. package/dist/src/session/queue-storage.d.ts +0 -8
  293. package/dist/src/session/queue-types.d.ts +0 -31
  294. package/dist/src/session/queue.d.ts +0 -73
  295. package/dist/src/session/queued-chat-dispatch.d.ts +0 -12
  296. package/dist/src/session/run-recovery/barrier.d.ts +0 -12
  297. package/dist/src/session/run-recovery/coordinator.d.ts +0 -32
  298. package/dist/src/session/run-recovery/journal.d.ts +0 -30
  299. package/dist/src/session/run-recovery/schema.d.ts +0 -48
  300. package/dist/src/session/store.d.ts +0 -128
  301. package/dist/src/session/tool-detail-store.d.ts +0 -17
  302. package/dist/src/session/turn-trigger.d.ts +0 -43
  303. package/dist/src/session/types.d.ts +0 -93
  304. package/dist/src/tools/markdown-to-pdf.d.ts +0 -42
  305. package/dist/src/upgrade/channel.d.ts +0 -5
  306. package/dist/src/upgrade/distribution.d.ts +0 -21
  307. package/dist/src/upgrade/engine.d.ts +0 -104
  308. package/dist/src/upgrade/scheduler.d.ts +0 -60
  309. package/dist/src/upgrade/updater-bootstrap.d.ts +0 -12
  310. package/dist/src/upgrade/updater-launcher.d.ts +0 -37
  311. package/dist/src/upgrade/updater-protocol.d.ts +0 -40
  312. package/dist/src/upgrade/updater-service-entry.d.ts +0 -7
  313. package/dist/src/upgrade/updater-worker.d.ts +0 -57
  314. package/dist/src/windows-shell.d.ts +0 -6
  315. package/node_modules/@shennian/wire/dist/agent-capabilities.d.ts +0 -16
  316. package/node_modules/@shennian/wire/dist/agent-workspace.d.ts +0 -133
  317. package/node_modules/@shennian/wire/dist/envelope.d.ts +0 -7
  318. package/node_modules/@shennian/wire/dist/events.d.ts +0 -125
  319. package/node_modules/@shennian/wire/dist/external-message-format.d.ts +0 -37
  320. package/node_modules/@shennian/wire/dist/frames.d.ts +0 -33
  321. package/node_modules/@shennian/wire/dist/fs.d.ts +0 -107
  322. package/node_modules/@shennian/wire/dist/index.d.ts +0 -21
  323. package/node_modules/@shennian/wire/dist/machine.d.ts +0 -160
  324. package/node_modules/@shennian/wire/dist/message-payload.d.ts +0 -71
  325. package/node_modules/@shennian/wire/dist/methods.d.ts +0 -5
  326. package/node_modules/@shennian/wire/dist/native-session.d.ts +0 -20
  327. package/node_modules/@shennian/wire/dist/project-fs.d.ts +0 -146
  328. package/node_modules/@shennian/wire/dist/project-path.d.ts +0 -4
  329. package/node_modules/@shennian/wire/dist/project.d.ts +0 -16
  330. package/node_modules/@shennian/wire/dist/relay-connectivity.d.ts +0 -30
  331. package/node_modules/@shennian/wire/dist/room.d.ts +0 -190
  332. package/node_modules/@shennian/wire/dist/schedule.d.ts +0 -37
  333. package/node_modules/@shennian/wire/dist/session-sync.d.ts +0 -406
  334. package/node_modules/@shennian/wire/dist/session.d.ts +0 -465
  335. package/node_modules/@shennian/wire/dist/tool-detail.d.ts +0 -38
  336. package/node_modules/@shennian/wire/dist/voice-chief.d.ts +0 -116
@@ -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 +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 y}from"../config-status.js";import{isCacheFresh as S,readCache as v,writeCache as A}from"./cache.js";import{discoverModelsForAgent as M}from"./discovery.js";import{ModelDiscoveryFallbackError as b}from"./types.js";import{getAgentRuntimeSummary as C}from"../runtime-compatibility.js";import{isRestrictedRoomChatUnsupported as x,resolveManagedAgentRuntimeProtection as F}from"../../security/managed-agent-runtime.js";const E={claude:"claude-alias-v2",codex:"codex-app-server-v2",opencode:"opencode-connected-v1"};function k(o,s,e){console.warn(`[model-discovery] agent=${o} source=fallback reason=${s} usedCache=${e}`)}function w(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 g(o){const s=o.type!=="manager"&&o.type!=="pi"&&o.type!=="openclaw",e=s,i=e&&!o.type.startsWith("acp:"),r=e?F({agentType:o.type,runtimeVersion:o.version,platform:o.runtimePlatform,isWsl:o.runtimeIsWsl,executableFingerprint:o.executableFingerprint,requireExecutableFingerprint:!0}):null,p=i&&!x(o.type)&&(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 R(o,s){return o.type==="opencode"&&(!o.authState||o.authState==="unknown")&&s.length>0?{authState:"ready"}:o.authState?{authState:o.authState}:{}}function T(o){const s=v();return o.map(e=>{const i=y(e.type),r=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}:{},...g(e),...i?{config:i}:{},...r?{runtime:r}:{}}})}async function V(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=E[t.type],u=n&&(!a||n.sourceRevision===a)?n:void 0;let c;if(!e.forceRefresh&&S(n,t.version,a))c=n.models;else{let d=null;try{d=w(await M(t,s)),c=d.length>0?d:u?.models??t.models??[]}catch(l){if(l instanceof b){const m=!!u?.models.length;c=m?u.models:l.fallbackModels,k(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=C(t);p.push({type:t.type,models:c,...t.integration?{integration:t.integration}:{},...t.display?{display:t.display}:{},...t.acpCapabilities?{acpCapabilities:t.acpCapabilities}:{},...R(t,c),...t.acpAuthMethods?{acpAuthMethods:t.acpAuthMethods}:{},...t.catalogRevision?{catalogRevision:t.catalogRevision}:{},...g(t),...f?{config:f}:{},...h?{runtime:h}:{}})}return r&&A(i),p}export{T as getCachedAgentInfos,V as refreshAgentInfos,I 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};
@@ -1 +1 @@
1
- import{createInterface as g}from"node:readline";import{randomUUID as l}from"node:crypto";import{AgentAdapter as h,registerAgent as f}from"./adapter.js";import{resolveBuiltinCommand as m,spawnAgentCommand as E}from"./command-spec.js";import{buildAgentProcessEnv as C,buildManagedAgentProcessEnv as y,buildManagedNativeFullProcessEnv as O}from"../agent-env.js";import{buildInlineChannelPreamble as D}from"./platform-instructions.js";import{resolveManagedAgentAdapterEnforcement as I,isManagedAgentNativeFull as S}from"../security/managed-agent-policy.js";import{registerManagedAgentRuntimeSecurity as P}from"../security/managed-agent-runtime.js";import{compileOpenCodeManagedPermissions as w,createOpenCodeManagedConfigDirectory as _,disposeOpenCodeManagedConfigDirectory as A,OPENCODE_MANAGED_RUNTIME_SECURITY as v}from"./opencode-managed-permissions.js";P("opencode",v);function N(n){if(!n)return;const e=n.input,t=n.output;if(!(typeof e!="number"&&typeof t!="number"))return{inputTokens:typeof e=="number"?e:0,outputTokens:typeof t=="number"?t:0}}function u(n){if(n==null)return"";if(typeof n=="string")return n;try{return JSON.stringify(n)}catch{return String(n)}}function c(n){if(!n)return"opencode request failed";if(typeof n=="string")return n;if(typeof n!="object")return String(n);const e=n;return typeof e.message=="string"?e.message:typeof e.name=="string"?e.name:"data"in e?c(e.data):u(n)||"opencode request failed"}class x extends h{type="opencode";get recoveryCapabilities(){return{inspectTerminal:!1,reattachRun:!1,resumeRun:!1,resumeSession:!0}}process=null;agentSessionId=null;workDir=null;seq=0;runId="";terminalState="closed";runUsage;externalChannel=null;shennianSessionId=null;extraEnv={};managedAgentPolicy=null;managedConfigDir=null;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,o){this.workDir=this.managedAgentPolicy?.adapterPolicy.workDir??t,o&&(this.agentSessionId=o),this.resetRunState()}async send(e,t,o,i,s,d){if(d?.source==="room_activation"&&!this.managedAgentPolicy)throw new Error("managed_agent_policy_missing");await this.killProcess(),this.runId=l(),this.resetRunState();const a=["run","--format","json","--dir",this.workDir??process.cwd()];this.agentSessionId&&a.push("--session",this.agentSessionId),t&&a.push("--model",t);const r=`${D(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0,s)}${e}`;await this.spawnAndParse(a,r)}async resume(e){await this.killProcess(),this.agentSessionId=e,this.runId=l(),this.resetRunState(),this.emitEvent({state:"start",agentSessionId:e}),this.emitFinalIfOpen({state:"final",agentSessionId:e})}async stop(){await this.killProcess()}resetRunState(){this.seq=0,this.terminalState="open",this.runUsage=void 0}async spawnAndParse(e,t){const o=m("opencode");if(!o){this.emit("error",new Error('Command "opencode" not found. Install it with "npm i -g opencode-ai@latest".'));return}const i=await this.prepareManagedLaunch();let s;try{s=E(o,[e[0],...i.args,...e.slice(1)],{cwd:this.workDir??void 0,stdio:["pipe","pipe","pipe"],env:i.env})}catch(r){throw await this.disposeManagedConfig(i.configDir),r}this.process=s,this.managedConfigDir=i.configDir,g({input:s.stdout}).on("line",r=>{this.handleProcessLine(s,r)});let a="";s.stderr?.on("data",r=>{a+=r.toString()}),s.on("close",(r,p)=>{this.process===s&&(this.process=null,this.disposeManagedConfig(i.configDir),this.terminalState==="open"&&this.completeRunAfterProcessExit(r,p,a.trim()))}),s.on("error",r=>{this.process===s&&(this.process=null,this.disposeManagedConfig(i.configDir),r.code==="ENOENT"?this.emit("error",new Error('Command "opencode" not found. Install it with "npm i -g opencode-ai@latest".')):this.emit("error",r))}),s.stdin.on("error",r=>{this.process===s&&this.emitErrorIfOpen({state:"error",message:r.message})}),s.stdin.end(t)}async prepareManagedLaunch(){const e=this.managedAgentPolicy;if(!e)return{args:["--auto"],env:C({NO_COLOR:"1",...this.extraEnv}),configDir:null};if(S(e))return{args:["--auto"],env:O({NO_COLOR:"1",...this.extraEnv}),configDir:null};const t=w(I(e),e.adapterPolicy.workDir),o=await _(t),i=y({agentType:"opencode",providerEnv:this.extraEnv,sessionEnv:this.extraEnv,runtimeEnv:{NO_COLOR:"1"}});return i.OPENCODE_CONFIG=o.configPath,i.OPENCODE_CONFIG_DIR=o.directory,i.OPENCODE_CONFIG_CONTENT=JSON.stringify(t.config),i.OPENCODE_DISABLE_PROJECT_CONFIG="true",i.OPENCODE_DISABLE_CLAUDE_CODE="1",i.OPENCODE_DISABLE_CLAUDE_CODE_PROMPT="1",i.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS="1",{args:t.args,env:i,configDir:o.directory}}async disposeManagedConfig(e){e&&(this.managedConfigDir===e&&(this.managedConfigDir=null),await A(e).catch(()=>{}))}handleStreamEvent(e){e.sessionID&&e.sessionID!==this.agentSessionId&&(this.agentSessionId=e.sessionID,this.emitEvent({state:"start",agentSessionId:e.sessionID}));const t=e.part;if(e.type==="text"&&t?.text){this.emitEvent({state:"delta",text:t.text});return}if(e.type==="reasoning"&&t?.text){this.emitEvent({state:"delta",text:t.text,thinking:!0});return}if(e.type==="tool_use"&&t?.type==="tool"){t.state?.status==="completed"||t.state?.status==="error"?this.emitEvent({state:"tool-result",name:t.tool??"tool",result:t.state.status==="error"?t.state.error??"tool failed":u(t.state?.output)}):this.emitEvent({state:"tool-call",name:t.tool??"tool",args:t.state?.input??{}});return}if(e.type==="error"){this.emitErrorIfOpen({state:"error",message:c(e.error)});return}e.type==="step_finish"&&this.recordStepUsage(N(t?.tokens))}handleProcessLine(e,t){if(!(this.process!==e||!t.trim()))try{this.handleStreamEvent(JSON.parse(t))}catch{this.emitEvent({state:"delta",text:t})}}recordStepUsage(e){e&&(this.runUsage={inputTokens:(this.runUsage?.inputTokens??0)+e.inputTokens,outputTokens:(this.runUsage?.outputTokens??0)+e.outputTokens})}completeRunAfterProcessExit(e=0,t=null,o=""){if(e!==0||t!==null){this.emitErrorIfOpen({state:"error",message:o||(t?`opencode exited with signal ${t}`:`opencode exited with code ${String(e)}`)});return}this.emitFinalIfOpen({state:"final",agentSessionId:this.agentSessionId??void 0,usage:this.runUsage})}emitEvent(e){const t={...e,runId:this.runId,seq:this.seq++};this.emit("agentEvent",t)}emitFinalIfOpen(e){this.terminalState==="open"&&(this.terminalState="closed",this.emitEvent(e))}emitErrorIfOpen(e){this.terminalState==="open"&&(this.terminalState="closed",this.emitEvent(e))}async killProcess(){const e=this.process;if(!e){await this.disposeManagedConfig(this.managedConfigDir);return}this.process=null,e.kill("SIGTERM"),await new Promise(t=>{e.on("close",t),setTimeout(()=>{e.kill("SIGKILL"),t()},3e3)}),await this.disposeManagedConfig(this.managedConfigDir)}}f("opencode",()=>new x);export{x as OpenCodeAdapter};
1
+ import{createInterface as g}from"node:readline";import{randomUUID as l}from"node:crypto";import{AgentAdapter as h,registerAgent as f}from"./adapter.js";import{resolveBuiltinCommand as m,spawnAgentCommand as E}from"./command-spec.js";import{spawnEnoentError as C}from"./spawn-errors.js";import{buildAgentProcessEnv as y,buildManagedAgentProcessEnv as O,buildManagedNativeFullProcessEnv as D}from"../agent-env.js";import{buildInlineChannelPreamble as I}from"./platform-instructions.js";import{resolveManagedAgentAdapterEnforcement as S,isManagedAgentNativeFull as P}from"../security/managed-agent-policy.js";import{registerManagedAgentRuntimeSecurity as w}from"../security/managed-agent-runtime.js";import{compileOpenCodeManagedPermissions as _,createOpenCodeManagedConfigDirectory as A,disposeOpenCodeManagedConfigDirectory as v,OPENCODE_MANAGED_RUNTIME_SECURITY as N}from"./opencode-managed-permissions.js";w("opencode",N);function k(n){if(!n)return;const e=n.input,t=n.output;if(!(typeof e!="number"&&typeof t!="number"))return{inputTokens:typeof e=="number"?e:0,outputTokens:typeof t=="number"?t:0}}function u(n){if(n==null)return"";if(typeof n=="string")return n;try{return JSON.stringify(n)}catch{return String(n)}}function c(n){if(!n)return"opencode request failed";if(typeof n=="string")return n;if(typeof n!="object")return String(n);const e=n;return typeof e.message=="string"?e.message:typeof e.name=="string"?e.name:"data"in e?c(e.data):u(n)||"opencode request failed"}class x extends h{type="opencode";get recoveryCapabilities(){return{inspectTerminal:!1,reattachRun:!1,resumeRun:!1,resumeSession:!0}}process=null;agentSessionId=null;workDir=null;seq=0;runId="";terminalState="closed";runUsage;externalChannel=null;shennianSessionId=null;extraEnv={};managedAgentPolicy=null;managedConfigDir=null;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,o){this.workDir=this.managedAgentPolicy?.adapterPolicy.workDir??t,o&&(this.agentSessionId=o),this.resetRunState()}async send(e,t,o,i,s,d){if(d?.source==="room_activation"&&!this.managedAgentPolicy)throw new Error("managed_agent_policy_missing");await this.killProcess(),this.runId=l(),this.resetRunState();const a=["run","--format","json","--dir",this.workDir??process.cwd()];this.agentSessionId&&a.push("--session",this.agentSessionId),t&&a.push("--model",t);const r=`${I(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0,s)}${e}`;await this.spawnAndParse(a,r)}async resume(e){await this.killProcess(),this.agentSessionId=e,this.runId=l(),this.resetRunState(),this.emitEvent({state:"start",agentSessionId:e}),this.emitFinalIfOpen({state:"final",agentSessionId:e})}async stop(){await this.killProcess()}resetRunState(){this.seq=0,this.terminalState="open",this.runUsage=void 0}async spawnAndParse(e,t){const o=m("opencode");if(!o){this.emit("error",new Error('Command "opencode" not found. Install it with "npm i -g opencode-ai@latest".'));return}const i=await this.prepareManagedLaunch();let s;try{s=E(o,[e[0],...i.args,...e.slice(1)],{cwd:this.workDir??void 0,stdio:["pipe","pipe","pipe"],env:i.env})}catch(r){throw await this.disposeManagedConfig(i.configDir),r}this.process=s,this.managedConfigDir=i.configDir,g({input:s.stdout}).on("line",r=>{this.handleProcessLine(s,r)});let a="";s.stderr?.on("data",r=>{a+=r.toString()}),s.on("close",(r,p)=>{this.process===s&&(this.process=null,this.disposeManagedConfig(i.configDir),this.terminalState==="open"&&this.completeRunAfterProcessExit(r,p,a.trim()))}),s.on("error",r=>{this.process===s&&(this.process=null,this.disposeManagedConfig(i.configDir),r.code==="ENOENT"?this.emit("error",C(this.workDir,'Command "opencode" not found. Install it with "npm i -g opencode-ai@latest".')):this.emit("error",r))}),s.stdin.on("error",r=>{this.process===s&&this.emitErrorIfOpen({state:"error",message:r.message})}),s.stdin.end(t)}async prepareManagedLaunch(){const e=this.managedAgentPolicy;if(!e)return{args:["--auto"],env:y({NO_COLOR:"1",...this.extraEnv}),configDir:null};if(P(e))return{args:["--auto"],env:D({NO_COLOR:"1",...this.extraEnv}),configDir:null};const t=_(S(e),e.adapterPolicy.workDir),o=await A(t),i=O({agentType:"opencode",providerEnv:this.extraEnv,sessionEnv:this.extraEnv,runtimeEnv:{NO_COLOR:"1"}});return i.OPENCODE_CONFIG=o.configPath,i.OPENCODE_CONFIG_DIR=o.directory,i.OPENCODE_CONFIG_CONTENT=JSON.stringify(t.config),i.OPENCODE_DISABLE_PROJECT_CONFIG="true",i.OPENCODE_DISABLE_CLAUDE_CODE="1",i.OPENCODE_DISABLE_CLAUDE_CODE_PROMPT="1",i.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS="1",{args:t.args,env:i,configDir:o.directory}}async disposeManagedConfig(e){e&&(this.managedConfigDir===e&&(this.managedConfigDir=null),await v(e).catch(()=>{}))}handleStreamEvent(e){e.sessionID&&e.sessionID!==this.agentSessionId&&(this.agentSessionId=e.sessionID,this.emitEvent({state:"start",agentSessionId:e.sessionID}));const t=e.part;if(e.type==="text"&&t?.text){this.emitEvent({state:"delta",text:t.text});return}if(e.type==="reasoning"&&t?.text){this.emitEvent({state:"delta",text:t.text,thinking:!0});return}if(e.type==="tool_use"&&t?.type==="tool"){t.state?.status==="completed"||t.state?.status==="error"?this.emitEvent({state:"tool-result",name:t.tool??"tool",result:t.state.status==="error"?t.state.error??"tool failed":u(t.state?.output)}):this.emitEvent({state:"tool-call",name:t.tool??"tool",args:t.state?.input??{}});return}if(e.type==="error"){this.emitErrorIfOpen({state:"error",message:c(e.error)});return}e.type==="step_finish"&&this.recordStepUsage(k(t?.tokens))}handleProcessLine(e,t){if(!(this.process!==e||!t.trim()))try{this.handleStreamEvent(JSON.parse(t))}catch{this.emitEvent({state:"delta",text:t})}}recordStepUsage(e){e&&(this.runUsage={inputTokens:(this.runUsage?.inputTokens??0)+e.inputTokens,outputTokens:(this.runUsage?.outputTokens??0)+e.outputTokens})}completeRunAfterProcessExit(e=0,t=null,o=""){if(e!==0||t!==null){this.emitErrorIfOpen({state:"error",message:o||(t?`opencode exited with signal ${t}`:`opencode exited with code ${String(e)}`)});return}this.emitFinalIfOpen({state:"final",agentSessionId:this.agentSessionId??void 0,usage:this.runUsage})}emitEvent(e){const t={...e,runId:this.runId,seq:this.seq++};this.emit("agentEvent",t)}emitFinalIfOpen(e){this.terminalState==="open"&&(this.terminalState="closed",this.emitEvent(e))}emitErrorIfOpen(e){this.terminalState==="open"&&(this.terminalState="closed",this.emitEvent(e))}async killProcess(){const e=this.process;if(!e){await this.disposeManagedConfig(this.managedConfigDir);return}this.process=null,e.kill("SIGTERM"),await new Promise(t=>{e.on("close",t),setTimeout(()=>{e.kill("SIGKILL"),t()},3e3)}),await this.disposeManagedConfig(this.managedConfigDir)}}f("opencode",()=>new x);export{x as OpenCodeAdapter};
@@ -1,4 +1,4 @@
1
- import h from"node:fs";import u from"node:path";import{randomUUID as w}from"node:crypto";import{AgentAdapter as A,registerAgent as k}from"./adapter.js";import{resolveBuiltinCommand as x,spawnAgentCommand as R}from"./command-spec.js";import{buildAgentProcessEnv as T,buildManagedAgentProcessEnv as N,buildManagedNativeFullProcessEnv as b}from"../agent-env.js";import{loadConfig as M,resolveShennianPath as f}from"../config/index.js";import{buildInlineChannelPreamble as C,buildPlatformInstructions as D}from"./platform-instructions.js";import{isManagedAgentNativeFull as P}from"../security/managed-agent-policy.js";import{PiRpcClient as B}from"./pi-rpc-client.js";import{registerManagedAgentRuntimeSecurity as O}from"../security/managed-agent-runtime.js";import{PI_CODING_AGENT_MANAGED_RUNTIME_SECURITY as j}from"./pi-coding-agent-managed-permissions.js";import{PiManagedModelBroker as q}from"./pi-managed-model-broker.js";import{writePiManagedExtension as F}from"./pi-managed-extension.js";import{recordPiSessionOwnership as U}from"./pi-session-ownership.js";O("pi-coding-agent",j);const $=32*1024,G=256*1024,z=3e3;function g(n){return n.replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,180)||"session"}function H(n){return n.data&&typeof n.data=="object"&&!Array.isArray(n.data)?n.data:{}}function X(n){if(typeof n=="string")return n;if(!n||typeof n!="object")return"";const t=n.content;return Array.isArray(t)?t.map(s=>{if(!s||typeof s!="object")return"";const e=s;return e.type==="text"&&typeof e.text=="string"?e.text:""}).join(""):""}function y(n,t=G){return n.length<=t?n:`${n.slice(0,t)}
2
- [truncated]`}function L(n){return y(n,2e3).replace(/Bearer\s+[A-Za-z0-9._~-]+/gi,"Bearer [redacted]").replace(/\b(?:pimc|mrc)_[A-Za-z0-9_-]{20,}\b/g,"[redacted-capability]").replace(/\bsk-[A-Za-z0-9_-]{12,}\b/g,"[redacted-key]")}function Z(n){try{return y(JSON.stringify(n))}catch{return"[unserializable]"}}function I(n){if(!n||typeof n!="object")return;const t=n;if(!(typeof t.input!="number"&&typeof t.output!="number"))return{inputTokens:typeof t.input=="number"?t.input:0,outputTokens:typeof t.output=="number"?t.output:0}}function K(n){const t=n?.trim();if(!t)return{};const s=t.indexOf("/");return s<=0||s===t.length-1?{modelId:t}:{provider:t.slice(0,s),modelId:t.slice(s+1)}}function _(n,t,s,e,i,a){const l=C(s,e,i,a),c=t?.filter(o=>o.kind!=="image")??[];if(!c.length)return`${l}${n}`;const p=c.map(o=>`[${o.name}](<${o.path}>)`);return`${l}${[n,"",...p].join(`
3
- `)}`}function E(n,t){const s=[];for(const e of n??[]){if(e.kind!=="image"||!e.mimeType.startsWith("image/"))continue;let i=e.previewData?.trim()??"";const a=i.indexOf(",");if(i.startsWith("data:")&&a>=0&&(i=i.slice(a+1)),!i&&t&&e.path&&!/^https?:\/\//i.test(e.path))try{const l=h.statSync(e.path);l.isFile()&&l.size<=10*1024*1024&&(i=h.readFileSync(e.path).toString("base64"))}catch{i=""}i&&s.push({type:"image",data:i,mimeType:e.mimeType})}return s}class W extends A{type="pi-coding-agent";get supportsActiveInput(){return!0}async injectActiveInput(t){const s=await this.readState();if(!this.rpc||!this.runId||!s.isStreaming&&!s.isCompacting)throw new Error("pi_active_turn_unavailable");const e={message:_(t.text,t.attachments,this.workDir,this.externalChannel,this.shennianSessionId,null)},i=E(t.attachments,!this.managedAgentPolicy);i.length&&!this.modelBroker&&(e.images=i),await this.rpc.request("steer",e)}get recoveryCapabilities(){return{inspectTerminal:!1,reattachRun:!1,resumeRun:!1,resumeSession:!0}}process=null;rpc=null;shennianSessionId="";workDir="";sessionDir="";agentSessionId=null;externalChannel=null;extraEnv={};managedAgentPolicy=null;runId="";seq=0;active=!1;terminal=!0;stderr="";lastUsage;promptFile=null;modelBroker=null;persistNativeSession=!0;validationRoot=null;runPhase=null;configure(t){t.sessionId&&(this.shennianSessionId=t.sessionId),this.externalChannel=t.externalChannel??null,this.extraEnv=t.env??{},"managedAgentPolicy"in t&&(this.managedAgentPolicy=t.managedAgentPolicy??null)}async start(t,s,e,i){await this.stopProcess(),this.shennianSessionId=t,this.workDir=this.managedAgentPolicy?.adapterPolicy.workDir??s,this.agentSessionId=e??null;const a=f("runtime","pi-coding-agent",g(t));this.persistNativeSession=i?.persistNativeSession!==!1,this.validationRoot=this.persistNativeSession?null:u.join(a,`validation-${w()}`),this.sessionDir=this.validationRoot?u.join(this.validationRoot,"sessions"):u.join(a,"sessions"),h.mkdirSync(this.sessionDir,{recursive:!0,mode:448}),process.platform!=="win32"&&h.chmodSync(this.sessionDir,448),this.active=!1,this.terminal=!0}async send(t,s,e,i,a,l){await this.ensureProcess(a);const c=this.requireRpc(),p=await this.readState(),o=!!(p.isStreaming||p.isCompacting);(!o||!this.runId)&&(this.runId=w(),this.seq=0,this.terminal=!1,this.lastUsage=void 0,this.runPhase="thinking");const d=K(s);if(d.modelId&&!o&&(p.model?.id!==d.modelId||d.provider&&p.model?.provider!==d.provider)){if(!d.provider)throw new Error("Pi model selection must include provider/modelId");await c.request("set_model",{provider:d.provider,modelId:d.modelId})}e&&!o&&await c.request("set_thinking_level",{level:e});const r=o?l?.source==="room_activation"?"follow_up":"steer":"prompt",m={message:_(t,i,this.workDir,this.externalChannel,this.shennianSessionId,null)},S=E(i,!this.managedAgentPolicy);S.length&&!this.modelBroker&&(m.images=S),this.modelBroker?.setTurnActive(!0);try{await c.request(r,m)}catch(v){throw this.modelBroker?.setTurnActive(!1),v}}async resume(t){await this.stopProcess(),this.agentSessionId=t}async stop(){const t=this.rpc;t&&(await t.request("clear_queue").catch(()=>{}),await t.request("abort").catch(()=>{})),!this.terminal&&this.runId&&this.emitTerminal({state:"aborted"}),await this.stopProcess()}async getStatus(){if(!this.rpc||!this.process)return{active:!1,runId:null,canStop:!1};const t=await this.readState().catch(()=>null),s=!!(t?.isStreaming||t?.isCompacting||this.active);return{active:s,runId:s?this.runId:null,runPhase:s?this.runPhase??"thinking":null,canStop:s}}async setTitle(t,s){this.rpc&&await this.rpc.request("set_session_name",{name:s.slice(0,200)})}async ensureProcess(t){if(this.process&&this.rpc)return;const s=x("pi-coding-agent");if(!s)throw new Error('Command "pi" not found. Install @earendil-works/pi-coding-agent from the official package.');const e=["--mode","rpc","--session-dir",this.sessionDir,"--offline"];this.agentSessionId&&e.push("--session",this.agentSessionId);const i=await this.prepareHostedModel();if(i&&e.push("--provider","shennian-dashscope","--model","deepseek-v4-flash-0731"),this.managedAgentPolicy&&!P(this.managedAgentPolicy)){e.push("--no-extensions","--no-skills","--no-prompt-templates","--no-context-files");const r=this.managedTools(),m=F({outputPath:u.join(f("runtime","pi-coding-agent",g(this.shennianSessionId)),"managed-extension.ts"),policy:this.managedAgentPolicy,allowRoomControl:!!this.extraEnv.SHENNIAN_MANAGED_ROOM_CONTEXT,allowManagerControl:!!this.extraEnv.SHENNIAN_MANAGER_SESSION_ID,allowHostShell:this.managedAgentPolicy.adapterPolicy.fileAccess==="host-full"});e.push("--no-builtin-tools","--extension",m),r.length?e.push("--tools",r.join(",")):e.push("--no-tools")}const a=D(this.workDir,this.externalChannel,this.shennianSessionId,t),l=this.validationRoot??f("runtime","pi-coding-agent",g(this.shennianSessionId));h.mkdirSync(l,{recursive:!0,mode:448}),this.promptFile=u.join(l,"instructions.md"),h.writeFileSync(this.promptFile,a,{encoding:"utf8",mode:384}),process.platform!=="win32"&&h.chmodSync(this.promptFile,384),e.push("--append-system-prompt",this.promptFile);const c={NO_COLOR:"1",...i?{PI_CODING_AGENT_DIR:i.configDir}:{}},p=this.managedAgentPolicy&&!P(this.managedAgentPolicy)?N({agentType:this.type,providerEnv:this.extraEnv,sessionEnv:this.extraEnv,runtimeEnv:c}):this.managedAgentPolicy?b({...c,...this.extraEnv}):T({...c,...this.extraEnv});let o;try{o=R(s,e,{cwd:this.workDir,stdio:["pipe","pipe","pipe"],env:p})}catch(r){throw await this.stopModelBroker(),r}this.process=o,this.stderr="",o.stderr?.on("data",r=>{const m=typeof r=="string"?r:r.toString("utf8");this.stderr=y(`${this.stderr}${m}`,$)});const d=new B(o);this.rpc=d,d.on("event",r=>this.handleRpcEvent(r)),d.on("protocolError",r=>this.emitError(r.message)),o.once("close",r=>{this.process===o&&(this.process=null,this.rpc=null,this.terminal||this.emitError(r===0?"Pi RPC process closed before agent_settled":`Pi RPC process exited with code ${r??"unknown"}${this.stderr?`: ${this.stderr}`:""}`),this.stopModelBroker())}),o.once("error",r=>{this.process===o&&this.emitError(r.message)});try{const r=await this.readState();if(!r.sessionId)throw new Error("Pi RPC did not return a session ID");if(r.isStreaming||r.isCompacting)throw new Error("Pi RPC session is not idle after startup");if(this.agentSessionId&&r.sessionId!==this.agentSessionId)throw new Error("Pi RPC resumed a different session");if(!r.sessionFile||!this.ownsSessionFile(r.sessionFile))throw new Error("Pi RPC returned a session file outside the Shennian-owned directory");this.agentSessionId=r.sessionId,this.persistNativeSession&&U(r.sessionId,this.sessionDir)}catch(r){throw await this.stopProcess(),r}}managedTools(){const t=this.managedAgentPolicy?.adapterPolicy;if(!t)return[];const s=["read","grep","find","ls"];(t.fileAccess==="workspace-write"||t.fileAccess==="host-full")&&s.push("edit","write");const e=!!this.extraEnv.SHENNIAN_MANAGER_SESSION_ID,i=!!this.extraEnv.SHENNIAN_MANAGED_ROOM_CONTEXT;return(e||i||t.fileAccess==="host-full")&&s.push("bash"),s}ownsSessionFile(t){const s=u.resolve(this.sessionDir),e=u.resolve(t),i=u.relative(s,e);return i!==""&&!i.startsWith("..")&&!u.isAbsolute(i)}async readState(){const t=await this.requireRpc().request("get_state");return H(t)}requireRpc(){if(!this.rpc)throw new Error("Pi RPC process is not running");return this.rpc}handleRpcEvent(t){if(t.type==="agent_start"){this.active=!0,this.runPhase="thinking",this.emitEvent({state:"start",agentSessionId:this.agentSessionId??void 0});return}if(t.type==="message_update"){this.lastUsage=I(t.usage)??this.lastUsage;const s=t.assistantMessageEvent;if(!s||typeof s!="object")return;const e=s;e.type==="text_delta"&&typeof e.delta=="string"?(this.runPhase="streaming_text",this.emitEvent({state:"delta",text:e.delta})):e.type==="thinking_delta"&&typeof e.delta=="string"&&(this.runPhase="thinking",this.emitEvent({state:"delta",text:e.delta,thinking:!0}));return}if(t.type==="tool_execution_start"){this.runPhase="tool_running",this.emitEvent({state:"tool-call",name:typeof t.toolName=="string"?t.toolName:"tool",args:t.args&&typeof t.args=="object"&&!Array.isArray(t.args)?t.args:{}});return}if(t.type==="tool_execution_end"){this.runPhase="thinking",this.emitEvent({state:"tool-result",name:typeof t.toolName=="string"?t.toolName:"tool",result:X(t.result)||Z(t.result)});return}if(t.type==="tool_execution_update"){this.emitEvent({state:"notify",runPhase:"tool_running",message:"Pi tool is running"});return}if(t.type==="message_end"){const s=t.message;if(s&&typeof s=="object"){const e=s;this.lastUsage=I(e.usage)??this.lastUsage,e.stopReason==="error"&&(this.modelBroker?.setTurnActive(!1),this.emitError(typeof e.errorMessage=="string"?e.errorMessage:"Pi model request failed"))}return}if(t.type==="compaction_start"){this.runPhase="thinking",this.emitEvent({state:"notify",runPhase:"thinking",message:"Pi is compacting context"});return}if(t.type==="auto_retry_start"||t.type==="summarization_retry_scheduled"){this.runPhase="thinking",this.emitEvent({state:"notify",runPhase:"thinking",message:"Pi is retrying"});return}if(t.type==="extension_ui_request"){typeof t.id=="string"&&this.rpc?.notify("extension_ui_response",{id:t.id,cancelled:!0});return}if(t.type==="extension_error"){this.modelBroker?.setTurnActive(!1),this.emitError(typeof t.error=="string"?t.error:"Pi extension failed");return}t.type==="agent_settled"&&(this.active=!1,this.modelBroker?.setTurnActive(!1),this.emitTerminal({state:"final",agentSessionId:this.agentSessionId??void 0,usage:this.lastUsage}))}emitEvent(t){this.runId&&this.emit("agentEvent",{...t,runId:this.runId,seq:this.seq++})}emitTerminal(t){this.terminal||(this.terminal=!0,this.active=!1,this.runPhase=null,this.emitEvent(t))}emitError(t){this.modelBroker?.setTurnActive(!1),this.emitTerminal({state:"error",message:L(t)})}async prepareHostedModel(){const t=M(),s=t.machineToken?.trim();if(!s)return null;const e=new q({serverUrl:t.serverUrl?.trim()||"https://shennian.net",machineToken:s,sessionId:this.shennianSessionId}),i=await e.start(),a=this.validationRoot?u.join(this.validationRoot,"agent-config"):f("runtime","pi-coding-agent",g(this.shennianSessionId),"agent-config");h.mkdirSync(a,{recursive:!0,mode:448}),process.platform!=="win32"&&h.chmodSync(a,448);const l=u.join(a,"models.json"),c={providers:{"shennian-dashscope":{baseUrl:i.baseUrl,api:"openai-completions",apiKey:i.apiKey,authHeader:!0,compat:{supportsDeveloperRole:!1,supportsReasoningEffort:!0},models:[{id:"deepseek-v4-flash-0731",name:"DeepSeek V4 Flash",reasoning:!0,input:["text"],thinkingLevelMap:{off:null,minimal:null,low:"low",medium:null,high:"high",xhigh:null,max:"max"}}]}}};return h.writeFileSync(l,`${JSON.stringify(c,null,2)}
4
- `,{encoding:"utf8",mode:384}),process.platform!=="win32"&&h.chmodSync(l,384),this.modelBroker=e,{configDir:a}}async stopModelBroker(){const t=this.modelBroker;this.modelBroker=null,await t?.stop().catch(()=>{})}async stopProcess(){const t=this.process;this.process=null,this.rpc?.close(),this.rpc=null,t?(t.kill("SIGTERM"),await new Promise(s=>{let e=!1;const i=()=>{e||(e=!0,s())};t.once("close",i),setTimeout(()=>{t.kill("SIGKILL"),i()},z).unref()}),await this.stopModelBroker()):await this.stopModelBroker(),this.validationRoot&&(h.rmSync(this.validationRoot,{recursive:!0,force:!0}),this.validationRoot=null)}}k("pi-coding-agent",()=>new W);export{W as PiCodingAgentAdapter};
1
+ import h from"node:fs";import u from"node:path";import{randomUUID as w}from"node:crypto";import{AgentAdapter as v,registerAgent as x}from"./adapter.js";import{resolveBuiltinCommand as k,spawnAgentCommand as R}from"./command-spec.js";import{buildAgentProcessEnv as N,buildManagedAgentProcessEnv as T,buildManagedNativeFullProcessEnv as C}from"../agent-env.js";import{loadConfig as b,resolveShennianPath as f}from"../config/index.js";import{buildInlineChannelPreamble as M,buildPlatformInstructions as D}from"./platform-instructions.js";import{isManagedAgentNativeFull as P}from"../security/managed-agent-policy.js";import{PiRpcClient as B}from"./pi-rpc-client.js";import{registerManagedAgentRuntimeSecurity as O}from"../security/managed-agent-runtime.js";import{PI_CODING_AGENT_MANAGED_RUNTIME_SECURITY as j}from"./pi-coding-agent-managed-permissions.js";import{PiManagedModelBroker as q}from"./pi-managed-model-broker.js";import{writePiManagedExtension as F}from"./pi-managed-extension.js";import{recordPiSessionOwnership as U}from"./pi-session-ownership.js";O("pi-coding-agent",j);const $=32*1024,G=256*1024,H=3e3;function g(n){return n.replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,180)||"session"}function z(n){return n.data&&typeof n.data=="object"&&!Array.isArray(n.data)?n.data:{}}function X(n){if(typeof n=="string")return n;if(!n||typeof n!="object")return"";const t=n.content;return Array.isArray(t)?t.map(s=>{if(!s||typeof s!="object")return"";const e=s;return e.type==="text"&&typeof e.text=="string"?e.text:""}).join(""):""}function y(n,t=G){return n.length<=t?n:`${n.slice(0,t)}
2
+ [truncated]`}function L(n){return y(n,2e3).replace(/Bearer\s+[A-Za-z0-9._~-]+/gi,"Bearer [redacted]").replace(/\b(?:pimc|mrc)_[A-Za-z0-9_-]{20,}\b/g,"[redacted-capability]").replace(/\bsk-[A-Za-z0-9_-]{12,}\b/g,"[redacted-key]")}function Z(n){try{return y(JSON.stringify(n))}catch{return"[unserializable]"}}function _(n){if(!n||typeof n!="object")return;const t=n;if(!(typeof t.input!="number"&&typeof t.output!="number"))return{inputTokens:typeof t.input=="number"?t.input:0,outputTokens:typeof t.output=="number"?t.output:0}}function K(n){const t=n?.trim();if(!t)return{};const s=t.indexOf("/");return s<=0||s===t.length-1?{modelId:t}:{provider:t.slice(0,s),modelId:t.slice(s+1)}}function I(n,t,s,e,i,a){const l=M(s,e,i,a),c=t?.filter(o=>o.kind!=="image")??[];if(!c.length)return`${l}${n}`;const p=c.map(o=>`[${o.name}](<${o.path}>)`);return`${l}${[n,"",...p].join(`
3
+ `)}`}function E(n,t){const s=[];for(const e of n??[]){if(e.kind!=="image"||!e.mimeType.startsWith("image/"))continue;let i=e.previewData?.trim()??"";const a=i.indexOf(",");if(i.startsWith("data:")&&a>=0&&(i=i.slice(a+1)),!i&&t&&e.path&&!/^https?:\/\//i.test(e.path))try{const l=h.statSync(e.path);l.isFile()&&l.size<=10*1024*1024&&(i=h.readFileSync(e.path).toString("base64"))}catch{i=""}i&&s.push({type:"image",data:i,mimeType:e.mimeType})}return s}class W extends v{type="pi-coding-agent";get supportsActiveInput(){return!0}async injectActiveInput(t){const s=await this.readState();if(!this.rpc||!this.runId||!s.isStreaming&&!s.isCompacting)throw new Error("pi_active_turn_unavailable");const e={message:I(t.text,t.attachments,this.workDir,this.externalChannel,this.shennianSessionId,null)},i=E(t.attachments,!this.managedAgentPolicy);i.length&&!this.modelBroker&&(e.images=i),await this.rpc.request("steer",e)}get recoveryCapabilities(){return{inspectTerminal:!1,reattachRun:!1,resumeRun:!1,resumeSession:!0}}process=null;rpc=null;shennianSessionId="";workDir="";sessionDir="";agentSessionId=null;externalChannel=null;extraEnv={};spawnedRoomContext=null;managedAgentPolicy=null;runId="";seq=0;active=!1;terminal=!0;stderr="";lastUsage;promptFile=null;modelBroker=null;persistNativeSession=!0;validationRoot=null;runPhase=null;configure(t){t.sessionId&&(this.shennianSessionId=t.sessionId),this.externalChannel=t.externalChannel??null,this.extraEnv=t.env??{},"managedAgentPolicy"in t&&(this.managedAgentPolicy=t.managedAgentPolicy??null)}async start(t,s,e,i){await this.stopProcess(),this.shennianSessionId=t,this.workDir=this.managedAgentPolicy?.adapterPolicy.workDir??s,this.agentSessionId=e??null;const a=f("runtime","pi-coding-agent",g(t));this.persistNativeSession=i?.persistNativeSession!==!1,this.validationRoot=this.persistNativeSession?null:u.join(a,`validation-${w()}`),this.sessionDir=this.validationRoot?u.join(this.validationRoot,"sessions"):u.join(a,"sessions"),h.mkdirSync(this.sessionDir,{recursive:!0,mode:448}),process.platform!=="win32"&&h.chmodSync(this.sessionDir,448),this.active=!1,this.terminal=!0}async send(t,s,e,i,a,l){await this.ensureProcess(a);const c=this.requireRpc(),p=await this.readState(),o=!!(p.isStreaming||p.isCompacting);(!o||!this.runId)&&(this.runId=w(),this.seq=0,this.terminal=!1,this.lastUsage=void 0,this.runPhase="thinking");const d=K(s);if(d.modelId&&!o&&(p.model?.id!==d.modelId||d.provider&&p.model?.provider!==d.provider)){if(!d.provider)throw new Error("Pi model selection must include provider/modelId");await c.request("set_model",{provider:d.provider,modelId:d.modelId})}e&&!o&&await c.request("set_thinking_level",{level:e});const r=o?l?.source==="room_activation"?"follow_up":"steer":"prompt",m={message:I(t,i,this.workDir,this.externalChannel,this.shennianSessionId,null)},S=E(i,!this.managedAgentPolicy);S.length&&!this.modelBroker&&(m.images=S),this.modelBroker?.setTurnActive(!0);try{await c.request(r,m)}catch(A){throw this.modelBroker?.setTurnActive(!1),A}}async resume(t){await this.stopProcess(),this.agentSessionId=t}async stop(){const t=this.rpc;t&&(await t.request("clear_queue").catch(()=>{}),await t.request("abort").catch(()=>{})),!this.terminal&&this.runId&&this.emitTerminal({state:"aborted"}),await this.stopProcess()}async getStatus(){if(!this.rpc||!this.process)return{active:!1,runId:null,canStop:!1};const t=await this.readState().catch(()=>null),s=!!(t?.isStreaming||t?.isCompacting||this.active);return{active:s,runId:s?this.runId:null,runPhase:s?this.runPhase??"thinking":null,canStop:s}}async setTitle(t,s){this.rpc&&await this.rpc.request("set_session_name",{name:s.slice(0,200)})}async ensureProcess(t){if(this.process&&this.rpc){if(!await this.roomContextStale())return;await this.stopProcess()}const s=k("pi-coding-agent");if(!s)throw new Error('Command "pi" not found. Install @earendil-works/pi-coding-agent from the official package.');const e=["--mode","rpc","--session-dir",this.sessionDir,"--offline"];this.agentSessionId&&e.push("--session",this.agentSessionId);const i=await this.prepareHostedModel();if(i&&e.push("--provider","shennian-dashscope","--model","deepseek-v4-flash-0731"),this.managedAgentPolicy&&!P(this.managedAgentPolicy)){e.push("--no-extensions","--no-skills","--no-prompt-templates","--no-context-files");const r=this.managedTools(),m=F({outputPath:u.join(f("runtime","pi-coding-agent",g(this.shennianSessionId)),"managed-extension.ts"),policy:this.managedAgentPolicy,allowRoomControl:!!this.extraEnv.SHENNIAN_MANAGED_ROOM_CONTEXT,allowManagerControl:!!this.extraEnv.SHENNIAN_MANAGER_SESSION_ID,allowHostShell:this.managedAgentPolicy.adapterPolicy.fileAccess==="host-full"});e.push("--no-builtin-tools","--extension",m),r.length?e.push("--tools",r.join(",")):e.push("--no-tools")}const a=D(this.workDir,this.externalChannel,this.shennianSessionId,t),l=this.validationRoot??f("runtime","pi-coding-agent",g(this.shennianSessionId));h.mkdirSync(l,{recursive:!0,mode:448}),this.promptFile=u.join(l,"instructions.md"),h.writeFileSync(this.promptFile,a,{encoding:"utf8",mode:384}),process.platform!=="win32"&&h.chmodSync(this.promptFile,384),e.push("--append-system-prompt",this.promptFile);const c={NO_COLOR:"1",...i?{PI_CODING_AGENT_DIR:i.configDir}:{}},p=this.managedAgentPolicy&&!P(this.managedAgentPolicy)?T({agentType:this.type,providerEnv:this.extraEnv,sessionEnv:this.extraEnv,runtimeEnv:c}):this.managedAgentPolicy?C({...c,...this.extraEnv}):N({...c,...this.extraEnv});let o;try{o=R(s,e,{cwd:this.workDir,stdio:["pipe","pipe","pipe"],env:p})}catch(r){throw await this.stopModelBroker(),r}this.process=o,this.spawnedRoomContext=this.currentRoomContext(),this.stderr="",o.stderr?.on("data",r=>{const m=typeof r=="string"?r:r.toString("utf8");this.stderr=y(`${this.stderr}${m}`,$)});const d=new B(o);this.rpc=d,d.on("event",r=>this.handleRpcEvent(r)),d.on("protocolError",r=>this.emitError(r.message)),o.once("close",r=>{this.process===o&&(this.process=null,this.rpc=null,this.terminal||this.emitError(r===0?"Pi RPC process closed before agent_settled":`Pi RPC process exited with code ${r??"unknown"}${this.stderr?`: ${this.stderr}`:""}`),this.stopModelBroker())}),o.once("error",r=>{this.process===o&&this.emitError(r.message)});try{const r=await this.readState();if(!r.sessionId)throw new Error("Pi RPC did not return a session ID");if(r.isStreaming||r.isCompacting)throw new Error("Pi RPC session is not idle after startup");if(this.agentSessionId&&r.sessionId!==this.agentSessionId)throw new Error("Pi RPC resumed a different session");if(!r.sessionFile||!this.ownsSessionFile(r.sessionFile))throw new Error("Pi RPC returned a session file outside the Shennian-owned directory");this.agentSessionId=r.sessionId,this.persistNativeSession&&U(r.sessionId,this.sessionDir)}catch(r){throw await this.stopProcess(),r}}currentRoomContext(){return this.extraEnv.SHENNIAN_MANAGED_ROOM_CONTEXT??null}async roomContextStale(){if(this.currentRoomContext()===this.spawnedRoomContext)return!1;const t=await this.readState().catch(()=>null);return!t?.isStreaming&&!t?.isCompacting}managedTools(){const t=this.managedAgentPolicy?.adapterPolicy;if(!t)return[];const s=["read","grep","find","ls"];(t.fileAccess==="workspace-write"||t.fileAccess==="host-full")&&s.push("edit","write");const e=!!this.extraEnv.SHENNIAN_MANAGER_SESSION_ID,i=!!this.extraEnv.SHENNIAN_MANAGED_ROOM_CONTEXT;return(e||i||t.fileAccess==="host-full")&&s.push("bash"),s}ownsSessionFile(t){const s=u.resolve(this.sessionDir),e=u.resolve(t),i=u.relative(s,e);return i!==""&&!i.startsWith("..")&&!u.isAbsolute(i)}async readState(){const t=await this.requireRpc().request("get_state");return z(t)}requireRpc(){if(!this.rpc)throw new Error("Pi RPC process is not running");return this.rpc}handleRpcEvent(t){if(t.type==="agent_start"){this.active=!0,this.runPhase="thinking",this.emitEvent({state:"start",agentSessionId:this.agentSessionId??void 0});return}if(t.type==="message_update"){this.lastUsage=_(t.usage)??this.lastUsage;const s=t.assistantMessageEvent;if(!s||typeof s!="object")return;const e=s;e.type==="text_delta"&&typeof e.delta=="string"?(this.runPhase="streaming_text",this.emitEvent({state:"delta",text:e.delta})):e.type==="thinking_delta"&&typeof e.delta=="string"&&(this.runPhase="thinking",this.emitEvent({state:"delta",text:e.delta,thinking:!0}));return}if(t.type==="tool_execution_start"){this.runPhase="tool_running",this.emitEvent({state:"tool-call",name:typeof t.toolName=="string"?t.toolName:"tool",args:t.args&&typeof t.args=="object"&&!Array.isArray(t.args)?t.args:{}});return}if(t.type==="tool_execution_end"){this.runPhase="thinking",this.emitEvent({state:"tool-result",name:typeof t.toolName=="string"?t.toolName:"tool",result:X(t.result)||Z(t.result)});return}if(t.type==="tool_execution_update"){this.emitEvent({state:"notify",runPhase:"tool_running",message:"Pi tool is running"});return}if(t.type==="message_end"){const s=t.message;if(s&&typeof s=="object"){const e=s;this.lastUsage=_(e.usage)??this.lastUsage,e.stopReason==="error"&&(this.modelBroker?.setTurnActive(!1),this.emitError(typeof e.errorMessage=="string"?e.errorMessage:"Pi model request failed"))}return}if(t.type==="compaction_start"){this.runPhase="thinking",this.emitEvent({state:"notify",runPhase:"thinking",message:"Pi is compacting context"});return}if(t.type==="auto_retry_start"||t.type==="summarization_retry_scheduled"){this.runPhase="thinking",this.emitEvent({state:"notify",runPhase:"thinking",message:"Pi is retrying"});return}if(t.type==="extension_ui_request"){typeof t.id=="string"&&this.rpc?.notify("extension_ui_response",{id:t.id,cancelled:!0});return}if(t.type==="extension_error"){this.modelBroker?.setTurnActive(!1),this.emitError(typeof t.error=="string"?t.error:"Pi extension failed");return}t.type==="agent_settled"&&(this.active=!1,this.modelBroker?.setTurnActive(!1),this.emitTerminal({state:"final",agentSessionId:this.agentSessionId??void 0,usage:this.lastUsage}))}emitEvent(t){this.runId&&this.emit("agentEvent",{...t,runId:this.runId,seq:this.seq++})}emitTerminal(t){this.terminal||(this.terminal=!0,this.active=!1,this.runPhase=null,this.emitEvent(t))}emitError(t){this.modelBroker?.setTurnActive(!1),this.emitTerminal({state:"error",message:L(t)})}async prepareHostedModel(){const t=b(),s=t.machineToken?.trim();if(!s)return null;const e=new q({serverUrl:t.serverUrl?.trim()||"https://shennian.net",machineToken:s,sessionId:this.shennianSessionId}),i=await e.start(),a=this.validationRoot?u.join(this.validationRoot,"agent-config"):f("runtime","pi-coding-agent",g(this.shennianSessionId),"agent-config");h.mkdirSync(a,{recursive:!0,mode:448}),process.platform!=="win32"&&h.chmodSync(a,448);const l=u.join(a,"models.json"),c={providers:{"shennian-dashscope":{baseUrl:i.baseUrl,api:"openai-completions",apiKey:i.apiKey,authHeader:!0,compat:{supportsDeveloperRole:!1,supportsReasoningEffort:!0},models:[{id:"deepseek-v4-flash-0731",name:"DeepSeek V4 Flash",reasoning:!0,input:["text"],thinkingLevelMap:{off:null,minimal:null,low:"low",medium:null,high:"high",xhigh:null,max:"max"}}]}}};return h.writeFileSync(l,`${JSON.stringify(c,null,2)}
4
+ `,{encoding:"utf8",mode:384}),process.platform!=="win32"&&h.chmodSync(l,384),this.modelBroker=e,{configDir:a}}async stopModelBroker(){const t=this.modelBroker;this.modelBroker=null,await t?.stop().catch(()=>{})}async stopProcess(){const t=this.process;this.process=null,this.rpc?.close(),this.rpc=null,t?(t.kill("SIGTERM"),await new Promise(s=>{let e=!1;const i=()=>{e||(e=!0,s())};t.once("close",i),setTimeout(()=>{t.kill("SIGKILL"),i()},H).unref()}),await this.stopModelBroker()):await this.stopModelBroker(),this.validationRoot&&(h.rmSync(this.validationRoot,{recursive:!0,force:!0}),this.validationRoot=null)}}x("pi-coding-agent",()=>new W);export{W as PiCodingAgentAdapter};
@@ -1,2 +1,2 @@
1
- import{createHash as p}from"node:crypto";import i from"node:fs";import o from"node:path";import{resolveShennianPath as c}from"../config/index.js";function a(){return c("runtime","pi-coding-agent","session-owners")}function d(e){const t=p("sha256").update(e).digest("hex");return o.join(a(),`${t}.json`)}function u(e){const t=o.resolve(c("runtime","pi-coding-agent")),r=o.resolve(e),n=o.relative(t,r);return n!==""&&!n.startsWith("..")&&!o.isAbsolute(n)&&o.basename(r)==="sessions"}function y(e,t){if(!e||!u(t))throw new Error("pi_session_ownership_invalid");const r=a();i.mkdirSync(r,{recursive:!0,mode:448});const n=d(e),s=`${n}.${process.pid}.tmp`,m={version:1,agentSessionId:e,sessionDir:o.resolve(t)};i.writeFileSync(s,`${JSON.stringify(m)}
2
- `,{encoding:"utf8",mode:384}),i.renameSync(s,n),process.platform!=="win32"&&i.chmodSync(n,384)}function w(e){if(!e||e.length>255||/[\0\r\n]/.test(e))return"invalid_identity";const t=d(e);let r;try{r=JSON.parse(i.readFileSync(t,"utf8"))}catch(n){return n.code==="ENOENT"?"already_absent":"invalid_identity"}return r.version!==1||r.agentSessionId!==e||!u(r.sessionDir)?"invalid_identity":(i.rmSync(r.sessionDir,{recursive:!0,force:!0}),i.rmSync(t,{force:!0}),"deleted")}export{w as deleteOwnedPiSession,y as recordPiSessionOwnership};
1
+ import{createHash as p}from"node:crypto";import n from"node:fs";import{renameSyncWithRetry as f}from"../fs/atomic-rename.js";import o from"node:path";import{resolveShennianPath as c}from"../config/index.js";function a(){return c("runtime","pi-coding-agent","session-owners")}function d(r){const t=p("sha256").update(r).digest("hex");return o.join(a(),`${t}.json`)}function u(r){const t=o.resolve(c("runtime","pi-coding-agent")),e=o.resolve(r),i=o.relative(t,e);return i!==""&&!i.startsWith("..")&&!o.isAbsolute(i)&&o.basename(e)==="sessions"}function S(r,t){if(!r||!u(t))throw new Error("pi_session_ownership_invalid");const e=a();n.mkdirSync(e,{recursive:!0,mode:448});const i=d(r),s=`${i}.${process.pid}.tmp`,m={version:1,agentSessionId:r,sessionDir:o.resolve(t)};n.writeFileSync(s,`${JSON.stringify(m)}
2
+ `,{encoding:"utf8",mode:384}),f(s,i),process.platform!=="win32"&&n.chmodSync(i,384)}function _(r){if(!r||r.length>255||/[\0\r\n]/.test(r))return"invalid_identity";const t=d(r);let e;try{e=JSON.parse(n.readFileSync(t,"utf8"))}catch(i){return i.code==="ENOENT"?"already_absent":"invalid_identity"}return e.version!==1||e.agentSessionId!==r||!u(e.sessionDir)?"invalid_identity":(n.rmSync(e.sessionDir,{recursive:!0,force:!0}),n.rmSync(t,{force:!0}),"deleted")}export{_ as deleteOwnedPiSession,S as recordPiSessionOwnership};
@@ -0,0 +1 @@
1
+ import o from"node:fs";function e(r,n){return r&&!o.existsSync(r)?new Error(`agent_workdir_not_found: \u5DE5\u4F5C\u76EE\u5F55\u4E0D\u5B58\u5728\uFF1A${r}`):new Error(n)}export{e as spawnEnoentError};
@@ -0,0 +1 @@
1
+ import{spawnSync as c}from"node:child_process";import s from"node:fs";import p from"node:os";import n from"node:path";import{buildWindowsSystemEnv as d,resolveWindowsPowerShellPath as m}from"../windows-shell.js";let r;function P(){r=void 0}function a(){if(r)return r;r={path:"",codexRoots:[]};const i=["$ErrorActionPreference = 'Stop'","[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false)","$paths = @([Environment]::GetEnvironmentVariable('Path', 'Machine'), [Environment]::GetEnvironmentVariable('Path', 'User'))","$roots = @()","try { $roots = @(Get-AppxPackage -Name '*Codex*' -ErrorAction Stop | Where-Object { $_.Name -eq 'OpenAI.Codex' } | Sort-Object InstallLocation | Select-Object -ExpandProperty InstallLocation) } catch {}","@{ path = ($paths -join ';'); codexRoots = @($roots) } | ConvertTo-Json -Compress"].join("; ");try{const t=c(m(),["-NoProfile","-NonInteractive","-Command",i],{env:{...process.env,...d()},encoding:"utf8",stdio:["ignore","pipe","ignore"],timeout:3e3,maxBuffer:65536,windowsHide:!0});if(t.status!==0||typeof t.stdout!="string")return r;const e=JSON.parse(t.stdout.replace(/^\uFEFF/,""));r={path:typeof e.path=="string"?e.path:"",codexRoots:Array.isArray(e.codexRoots)?e.codexRoots.filter(o=>typeof o=="string"&&n.win32.isAbsolute(o)):[]}}catch{}return r}function y(){const t=[...(process.env.PATH??process.env.Path??"").split(";"),...a().path.split(";")],e=new Set;return t.map(o=>o.trim().replace(/^"(.*)"$/,"$1")).filter(o=>!o||e.has(o.toLowerCase())?!1:(e.add(o.toLowerCase()),!0)).join(";")}function l(i){const t=n.win32.join(i,"OpenAI","Codex","bin");try{return s.readdirSync(t,{withFileTypes:!0}).filter(e=>e.isDirectory()).map(e=>n.win32.join(t,e.name)).map(e=>({dir:e,modified:s.statSync(e).mtimeMs})).sort((e,o)=>o.modified-e.modified).map(({dir:e})=>n.win32.join(e,"codex.exe"))}catch{return[]}}function C(i=p.homedir()){const t=process.env.LOCALAPPDATA||n.win32.join(i,"AppData","Local"),e=[...a().codexRoots,n.win32.join(t,"Programs","Codex"),n.win32.join(t,"Codex")];return[...l(t),...e.flatMap(o=>[n.win32.join(o,"app","resources","codex.exe"),n.win32.join(o,"resources","codex.exe")])]}export{a as readWindowsInstallationPaths,P as resetWindowsInstallationPaths,C as windowsCodexDesktopCandidates,y as windowsLookupPath};
@@ -1,2 +1,2 @@
1
- import{callDaemonIpc as a}from"../daemon-ipc/client.js";import{DaemonIpcError as i}from"../daemon-ipc/protocol.js";const s={method_not_found:"Update the existing Shennian installation: Desktop through Desktop updates, standalone CLI through its own update flow. Do not install a second Client.",daemon_unavailable:"Check shennian status --json on the target computer. Do not resume an intentional pause without the user requesting it.",daemon_paused:"Shennian is paused. Ask the user to resume it before checking.",ipc_timeout:"The result is unknown. Check the target machine and wait for the current check to finish; do not repeatedly send tests.",agent_check_in_progress:"Wait for the running check to finish before trying again.",agent_validation_runtime_unavailable:"Refresh discovery. If the tool is still missing, guide the user through its official installation on this computer.",agent_validation_runtime_auth_required:"Guide the user through the provider\u2019s own sign-in on this computer, then retry the selected AI and model.",agent_validation_model_unavailable:"Choose a model returned by discovery and check the provider account\u2019s model access.",agent_validation_quota_exceeded:"Check the provider account\u2019s credits, subscription or rate limit before another test.",agent_validation_network_failed:"Check the target computer\u2019s connection to the provider, then retry when it is available."};async function c(o,r,t=a){try{const e=await t({method:o,params:r,timeoutMs:9e4});if(o==="agent.check"&&(!e||typeof e!="object"||Array.isArray(e)||e.ready!==!0))throw new i("agent_check_invalid_response","The daemon did not confirm a successful hello reply.");return{ok:!0,command:o,result:e}}catch(e){const n=e instanceof i?e.code:"agent_check_failed";return{ok:!1,command:o,error:n,nextAction:s[n]??"Return to the AI preparation guide on this machine. Check the selected directory, account, model and network; do not reinstall by default."}}}function h(o){const r=async(t,e)=>{const n=await c(t,e);process.stdout.write(`${JSON.stringify(n)}
2
- `),n.ok||(process.exitCode=1)};o.command("discover").description("Read the daemon AI snapshot; use --refresh only to rerun local provider and model discovery").option("--agent <type>","Return only one discovered Agent type").option("--compact","Return capability summary without the full model list").option("--refresh","Rerun discovery; with --agent, probe only that Agent").option("--json","Print JSON (default)").action(t=>r("agent.discover",{...t.agent?{agentType:t.agent}:{},compact:t.compact===!0,refresh:t.refresh===!0})),o.command("check <agentType>").description("Send one hello test using the selected AI and model; uses provider quota, creates no managed Agent or room").requiredOption("--workdir <path>","Absolute project directory on this machine").option("--model <id>","Model returned by discovery; otherwise use the provider default").option("--json","Print JSON (default)").action((t,e)=>r("agent.check",{agentType:t,workDir:e.workdir,modelId:e.model??null}))}export{c as executeAgentReadinessCommand,h as registerAgentReadinessCommands};
1
+ import{callDaemonIpc as s}from"../daemon-ipc/client.js";import{DaemonIpcError as i}from"../daemon-ipc/protocol.js";const d={method_not_found:"Update the existing Shennian installation: Desktop through Desktop updates, standalone CLI through its own update flow. Do not install a second Client.",daemon_unavailable:"Check shennian status --json on the target computer. Do not resume an intentional pause without the user requesting it.",daemon_paused:"Shennian is paused. Ask the user to resume it before checking.",ipc_timeout:"The result is unknown. Check the target machine and wait for the current check to finish; do not repeatedly send tests.",agent_check_in_progress:"Wait for the running check to finish before trying again.",agent_validation_runtime_unavailable:"Refresh discovery. If the tool is still missing, guide the user through its official installation on this computer.",agent_validation_runtime_auth_required:"Guide the user through the provider\u2019s own sign-in on this computer, then retry the selected AI and model.",agent_validation_model_unavailable:"Choose a model returned by discovery and check the provider account\u2019s model access.",agent_validation_quota_exceeded:"Check the provider account\u2019s credits, subscription or rate limit before another test.",agent_validation_network_failed:"Check the target computer\u2019s connection to the provider, then retry when it is available.",agent_validation_workdir_invalid:"Use an existing absolute project directory on this computer that the user allows Shennian to use.",agent_validation_workdir_not_found:"The working directory does not exist on this computer. Ask the user for an existing absolute project directory (it may have been moved, deleted or is on an unmounted drive); do not create it for them.",agent_validation_workdir_not_directory:"The working directory path is a file, not a folder. Ask the user for the project folder.",agent_validation_workdir_unavailable:"The working directory exists but this user cannot access it. Check its permissions on this computer or choose another directory.",agent_validation_start_failed:"The AI could not start. Run the tool once on this computer to see its own error, fix its installation or configuration, then retry.",agent_validation_response_timeout:"The AI started but gave no hello reply within 60 seconds. Check its provider sign-in, selected model and network, then retry once; do not repeatedly send tests.",agent_validation_response_mismatch:"The AI replied but not with hello. Check the selected model; a reply that ignores simple instructions usually means a wrong or misconfigured model.",agent_validation_response_failed:"The AI started but failed while replying. Check its provider sign-in, selected model, quota and network, then retry once."},r={agent_validation_runtime_unavailable:"start",agent_validation_workdir_invalid:"start",agent_validation_workdir_not_found:"start",agent_validation_workdir_not_directory:"start",agent_validation_workdir_unavailable:"start",agent_validation_start_failed:"start",agent_validation_runtime_auth_required:"auth",agent_validation_model_unavailable:"model",agent_validation_quota_exceeded:"quota",agent_validation_network_failed:"network",agent_validation_response_timeout:"reply",agent_validation_response_mismatch:"reply",agent_validation_response_failed:"reply"},l="A successful check only proves one standard-mode hello reply; it does not prove the AI can send messages in a Room.",c={authState:'unknown means Shennian has no login probe for this AI; it is not "not logged in".',defaultModelId:"null means no model is marked default; it does not mean no model is available. The AI picks its own model when none is passed."};async function u(t,a,o=s){try{const e=await o({method:t,params:a,timeoutMs:9e4});if(t==="agent.check"&&(!e||typeof e!="object"||Array.isArray(e)||e.ready!==!0))throw new i("agent_check_invalid_response","The daemon did not confirm a successful hello reply.");return t==="agent.discover"&&e&&typeof e=="object"&&!Array.isArray(e)?{ok:!0,command:t,result:{...e,notes:c}}:t==="agent.check"&&e&&typeof e=="object"&&!Array.isArray(e)?{ok:!0,command:t,result:{...e,note:l}}:{ok:!0,command:t,result:e}}catch(e){const n=e instanceof i?e.code:"agent_check_failed";return{ok:!1,command:t,error:n,...r[n]?{stage:r[n]}:{},nextAction:d[n]??"Return to the AI preparation guide on this machine. Check the selected directory, account, model and network; do not reinstall by default."}}}function m(t){const a=async(o,e)=>{const n=await u(o,e);process.stdout.write(`${JSON.stringify(n)}
2
+ `),n.ok||(process.exitCode=1)};t.command("discover").description("Read the daemon AI snapshot; use --refresh only to rerun local provider and model discovery").option("--agent <type>","Return only one discovered Agent type").option("--compact","Return capability summary without the full model list").option("--refresh","Rerun discovery; with --agent, probe only that Agent").option("--json","Print JSON (default)").action(o=>a("agent.discover",{...o.agent?{agentType:o.agent}:{},compact:o.compact===!0,refresh:o.refresh===!0})),t.command("check <agentType>").description("Send one hello test using the selected AI and model; uses provider quota, creates no managed Agent or room").requiredOption("--workdir <path>","Absolute project directory on this machine").option("--model <id>","Model returned by discovery; otherwise use the provider default").option("--json","Print JSON (default)").action((o,e)=>a("agent.check",{agentType:o,workDir:e.workdir,modelId:e.model??null}))}export{u as executeAgentReadinessCommand,m as registerAgentReadinessCommands};