@graychennpm/codebridge 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (434) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/LICENSE +21 -0
  3. package/README.md +217 -2
  4. package/README.zh-CN.md +222 -0
  5. package/apps/web/public/brand/agent-logo-carbon.svg +1 -0
  6. package/apps/web/public/brand/agent-logo.svg +1 -0
  7. package/docs/zh-CN/npm-release.md +77 -0
  8. package/node_modules/@codebridge/agent-registry/dist/index.d.ts +32 -0
  9. package/node_modules/@codebridge/agent-registry/dist/index.js +177 -0
  10. package/node_modules/@codebridge/agent-registry/dist/setup.d.ts +9 -0
  11. package/node_modules/@codebridge/agent-registry/dist/setup.js +115 -0
  12. package/node_modules/@codebridge/agent-registry/package.json +17 -0
  13. package/node_modules/@codebridge/backends/dist/acp/acp-active-session.d.ts +12 -0
  14. package/node_modules/@codebridge/backends/dist/acp/acp-active-session.js +57 -0
  15. package/node_modules/@codebridge/backends/dist/acp/acp-claude-activity.d.ts +9 -0
  16. package/node_modules/@codebridge/backends/dist/acp/acp-claude-activity.js +49 -0
  17. package/node_modules/@codebridge/backends/dist/acp/acp-config-options.d.ts +46 -0
  18. package/node_modules/@codebridge/backends/dist/acp/acp-config-options.js +220 -0
  19. package/node_modules/@codebridge/backends/dist/acp/acp-doctor.d.ts +3 -0
  20. package/node_modules/@codebridge/backends/dist/acp/acp-doctor.js +18 -0
  21. package/node_modules/@codebridge/backends/dist/acp/acp-event-mapper.d.ts +5 -0
  22. package/node_modules/@codebridge/backends/dist/acp/acp-event-mapper.js +136 -0
  23. package/node_modules/@codebridge/backends/dist/acp/acp-kill.d.ts +10 -0
  24. package/node_modules/@codebridge/backends/dist/acp/acp-kill.js +24 -0
  25. package/node_modules/@codebridge/backends/dist/acp/acp-race.d.ts +6 -0
  26. package/node_modules/@codebridge/backends/dist/acp/acp-race.js +29 -0
  27. package/node_modules/@codebridge/backends/dist/acp/acp-session-list.d.ts +32 -0
  28. package/node_modules/@codebridge/backends/dist/acp/acp-session-list.js +218 -0
  29. package/node_modules/@codebridge/backends/dist/acp/acp-session-pool.d.ts +85 -0
  30. package/node_modules/@codebridge/backends/dist/acp/acp-session-pool.js +165 -0
  31. package/node_modules/@codebridge/backends/dist/acp/acp-session-runner.d.ts +78 -0
  32. package/node_modules/@codebridge/backends/dist/acp/acp-session-runner.js +550 -0
  33. package/node_modules/@codebridge/backends/dist/acp/acp-spawn-profiles.d.ts +9 -0
  34. package/node_modules/@codebridge/backends/dist/acp/acp-spawn-profiles.js +28 -0
  35. package/node_modules/@codebridge/backends/dist/acp/headless-client.d.ts +19 -0
  36. package/node_modules/@codebridge/backends/dist/acp/headless-client.js +47 -0
  37. package/node_modules/@codebridge/backends/dist/acp/index.d.ts +9 -0
  38. package/node_modules/@codebridge/backends/dist/acp/index.js +9 -0
  39. package/node_modules/@codebridge/backends/dist/agent-setup.d.ts +60 -0
  40. package/node_modules/@codebridge/backends/dist/agent-setup.js +504 -0
  41. package/node_modules/@codebridge/backends/dist/attachment-prompt.d.ts +8 -0
  42. package/node_modules/@codebridge/backends/dist/attachment-prompt.js +28 -0
  43. package/node_modules/@codebridge/backends/dist/auth-error-hints.d.ts +8 -0
  44. package/node_modules/@codebridge/backends/dist/auth-error-hints.js +33 -0
  45. package/node_modules/@codebridge/backends/dist/codex-skill-commands.d.ts +3 -0
  46. package/node_modules/@codebridge/backends/dist/codex-skill-commands.js +88 -0
  47. package/node_modules/@codebridge/backends/dist/index.d.ts +18 -0
  48. package/node_modules/@codebridge/backends/dist/index.js +34 -0
  49. package/node_modules/@codebridge/backends/dist/pi-providers.d.ts +45 -0
  50. package/node_modules/@codebridge/backends/dist/pi-providers.js +148 -0
  51. package/node_modules/@codebridge/backends/dist/pi-session-runner.d.ts +85 -0
  52. package/node_modules/@codebridge/backends/dist/pi-session-runner.js +460 -0
  53. package/node_modules/@codebridge/backends/dist/provider-connection.d.ts +17 -0
  54. package/node_modules/@codebridge/backends/dist/provider-connection.js +99 -0
  55. package/node_modules/@codebridge/backends/dist/session-discovery.d.ts +23 -0
  56. package/node_modules/@codebridge/backends/dist/session-discovery.js +340 -0
  57. package/node_modules/@codebridge/backends/dist/skill-control-plane.d.ts +147 -0
  58. package/node_modules/@codebridge/backends/dist/skill-control-plane.js +832 -0
  59. package/node_modules/@codebridge/backends/package.json +22 -0
  60. package/node_modules/@codebridge/bridge/dist/alert-notification-rules.d.ts +14 -0
  61. package/node_modules/@codebridge/bridge/dist/alert-notification-rules.js +37 -0
  62. package/node_modules/@codebridge/bridge/dist/channel-config.d.ts +4 -0
  63. package/node_modules/@codebridge/bridge/dist/channel-config.js +9 -0
  64. package/node_modules/@codebridge/bridge/dist/channel-ingress.d.ts +5 -0
  65. package/node_modules/@codebridge/bridge/dist/channel-ingress.js +403 -0
  66. package/node_modules/@codebridge/bridge/dist/cli.d.ts +3 -0
  67. package/node_modules/@codebridge/bridge/dist/cli.js +581 -0
  68. package/node_modules/@codebridge/bridge/dist/deployment.d.ts +46 -0
  69. package/node_modules/@codebridge/bridge/dist/deployment.js +174 -0
  70. package/node_modules/@codebridge/bridge/dist/event-loop-lag.d.ts +19 -0
  71. package/node_modules/@codebridge/bridge/dist/event-loop-lag.js +33 -0
  72. package/node_modules/@codebridge/bridge/dist/feishu-alert-monitor.d.ts +70 -0
  73. package/node_modules/@codebridge/bridge/dist/feishu-alert-monitor.js +591 -0
  74. package/node_modules/@codebridge/bridge/dist/init-wizard.d.ts +52 -0
  75. package/node_modules/@codebridge/bridge/dist/init-wizard.js +571 -0
  76. package/node_modules/@codebridge/bridge/dist/mcp-api.d.ts +4 -0
  77. package/node_modules/@codebridge/bridge/dist/mcp-api.js +100 -0
  78. package/node_modules/@codebridge/bridge/dist/outbound-api.d.ts +31 -0
  79. package/node_modules/@codebridge/bridge/dist/outbound-api.js +184 -0
  80. package/node_modules/@codebridge/bridge/dist/outbound-publishers.d.ts +54 -0
  81. package/node_modules/@codebridge/bridge/dist/outbound-publishers.js +213 -0
  82. package/node_modules/@codebridge/bridge/dist/project-api.d.ts +4 -0
  83. package/node_modules/@codebridge/bridge/dist/project-api.js +161 -0
  84. package/node_modules/@codebridge/bridge/dist/secrets-command.d.ts +13 -0
  85. package/node_modules/@codebridge/bridge/dist/secrets-command.js +34 -0
  86. package/node_modules/@codebridge/bridge/dist/session-api.d.ts +26 -0
  87. package/node_modules/@codebridge/bridge/dist/session-api.js +1378 -0
  88. package/node_modules/@codebridge/bridge/dist/session-history-import.d.ts +24 -0
  89. package/node_modules/@codebridge/bridge/dist/session-history-import.js +82 -0
  90. package/node_modules/@codebridge/bridge/dist/session-runtime-api.d.ts +19 -0
  91. package/node_modules/@codebridge/bridge/dist/session-runtime-api.js +453 -0
  92. package/node_modules/@codebridge/bridge/dist/session-runtime-migration.d.ts +21 -0
  93. package/node_modules/@codebridge/bridge/dist/session-runtime-migration.js +43 -0
  94. package/node_modules/@codebridge/bridge/dist/session-runtime-types.d.ts +85 -0
  95. package/node_modules/@codebridge/bridge/dist/session-runtime-types.js +98 -0
  96. package/node_modules/@codebridge/bridge/dist/skill-api.d.ts +28 -0
  97. package/node_modules/@codebridge/bridge/dist/skill-api.js +129 -0
  98. package/node_modules/@codebridge/bridge/dist/startup-surfaces.d.ts +15 -0
  99. package/node_modules/@codebridge/bridge/dist/startup-surfaces.js +13 -0
  100. package/node_modules/@codebridge/bridge/dist/web-frontend.d.ts +8 -0
  101. package/node_modules/@codebridge/bridge/dist/web-frontend.js +76 -0
  102. package/node_modules/@codebridge/bridge/dist/work-item-api.d.ts +6 -0
  103. package/node_modules/@codebridge/bridge/dist/work-item-api.js +414 -0
  104. package/node_modules/@codebridge/bridge/package.json +28 -0
  105. package/node_modules/@codebridge/channel-feishu/dist/alert-reactions.d.ts +6 -0
  106. package/node_modules/@codebridge/channel-feishu/dist/alert-reactions.js +58 -0
  107. package/node_modules/@codebridge/channel-feishu/dist/alert-types.d.ts +35 -0
  108. package/node_modules/@codebridge/channel-feishu/dist/alert-types.js +2 -0
  109. package/node_modules/@codebridge/channel-feishu/dist/bridge.d.ts +130 -0
  110. package/node_modules/@codebridge/channel-feishu/dist/bridge.js +1231 -0
  111. package/node_modules/@codebridge/channel-feishu/dist/cardkit-writer.d.ts +48 -0
  112. package/node_modules/@codebridge/channel-feishu/dist/cardkit-writer.js +153 -0
  113. package/node_modules/@codebridge/channel-feishu/dist/chain-topics.d.ts +20 -0
  114. package/node_modules/@codebridge/channel-feishu/dist/chain-topics.js +35 -0
  115. package/node_modules/@codebridge/channel-feishu/dist/coalescing-card-writer.d.ts +12 -0
  116. package/node_modules/@codebridge/channel-feishu/dist/coalescing-card-writer.js +53 -0
  117. package/node_modules/@codebridge/channel-feishu/dist/delivery-reconciler.d.ts +19 -0
  118. package/node_modules/@codebridge/channel-feishu/dist/delivery-reconciler.js +53 -0
  119. package/node_modules/@codebridge/channel-feishu/dist/durable-markdown-card.d.ts +19 -0
  120. package/node_modules/@codebridge/channel-feishu/dist/durable-markdown-card.js +77 -0
  121. package/node_modules/@codebridge/channel-feishu/dist/feishu-extra-events.d.ts +27 -0
  122. package/node_modules/@codebridge/channel-feishu/dist/feishu-extra-events.js +24 -0
  123. package/node_modules/@codebridge/channel-feishu/dist/feishu-http.d.ts +4 -0
  124. package/node_modules/@codebridge/channel-feishu/dist/feishu-http.js +25 -0
  125. package/node_modules/@codebridge/channel-feishu/dist/feishu-inbound-context.d.ts +13 -0
  126. package/node_modules/@codebridge/channel-feishu/dist/feishu-inbound-context.js +45 -0
  127. package/node_modules/@codebridge/channel-feishu/dist/feishu-inbound-media.d.ts +22 -0
  128. package/node_modules/@codebridge/channel-feishu/dist/feishu-inbound-media.js +273 -0
  129. package/node_modules/@codebridge/channel-feishu/dist/feishu-mention-gate.d.ts +13 -0
  130. package/node_modules/@codebridge/channel-feishu/dist/feishu-mention-gate.js +22 -0
  131. package/node_modules/@codebridge/channel-feishu/dist/feishu-outbound-file.d.ts +12 -0
  132. package/node_modules/@codebridge/channel-feishu/dist/feishu-outbound-file.js +38 -0
  133. package/node_modules/@codebridge/channel-feishu/dist/feishu-quoted-message.d.ts +30 -0
  134. package/node_modules/@codebridge/channel-feishu/dist/feishu-quoted-message.js +183 -0
  135. package/node_modules/@codebridge/channel-feishu/dist/index.d.ts +7 -0
  136. package/node_modules/@codebridge/channel-feishu/dist/index.js +3 -0
  137. package/node_modules/@codebridge/channel-feishu/dist/redacting-logger.d.ts +17 -0
  138. package/node_modules/@codebridge/channel-feishu/dist/redacting-logger.js +41 -0
  139. package/node_modules/@codebridge/channel-feishu/dist/run-status.d.ts +39 -0
  140. package/node_modules/@codebridge/channel-feishu/dist/run-status.js +166 -0
  141. package/node_modules/@codebridge/channel-feishu/dist/session-watcher.d.ts +98 -0
  142. package/node_modules/@codebridge/channel-feishu/dist/session-watcher.js +655 -0
  143. package/node_modules/@codebridge/channel-feishu/package.json +19 -0
  144. package/node_modules/@codebridge/channel-telegram/dist/coalescing-message-writer.d.ts +14 -0
  145. package/node_modules/@codebridge/channel-telegram/dist/coalescing-message-writer.js +56 -0
  146. package/node_modules/@codebridge/channel-telegram/dist/index.d.ts +3 -0
  147. package/node_modules/@codebridge/channel-telegram/dist/index.js +3 -0
  148. package/node_modules/@codebridge/channel-telegram/dist/telegram-api.d.ts +62 -0
  149. package/node_modules/@codebridge/channel-telegram/dist/telegram-api.js +72 -0
  150. package/node_modules/@codebridge/channel-telegram/dist/telegram-bridge.d.ts +64 -0
  151. package/node_modules/@codebridge/channel-telegram/dist/telegram-bridge.js +469 -0
  152. package/node_modules/@codebridge/channel-telegram/dist/telegram-session-watcher.d.ts +41 -0
  153. package/node_modules/@codebridge/channel-telegram/dist/telegram-session-watcher.js +184 -0
  154. package/node_modules/@codebridge/channel-telegram/package.json +18 -0
  155. package/node_modules/@codebridge/core/dist/config-schema.d.ts +1195 -0
  156. package/node_modules/@codebridge/core/dist/config-schema.js +293 -0
  157. package/node_modules/@codebridge/core/dist/config-store.d.ts +48 -0
  158. package/node_modules/@codebridge/core/dist/config-store.js +207 -0
  159. package/node_modules/@codebridge/core/dist/index.d.ts +11 -0
  160. package/node_modules/@codebridge/core/dist/index.js +10 -0
  161. package/node_modules/@codebridge/core/dist/json-file-store.d.ts +16 -0
  162. package/node_modules/@codebridge/core/dist/json-file-store.js +46 -0
  163. package/node_modules/@codebridge/core/dist/mcp-types.d.ts +7 -0
  164. package/node_modules/@codebridge/core/dist/mcp-types.js +2 -0
  165. package/node_modules/@codebridge/core/dist/mentions.d.ts +36 -0
  166. package/node_modules/@codebridge/core/dist/mentions.js +138 -0
  167. package/node_modules/@codebridge/core/dist/secret-migration.d.ts +14 -0
  168. package/node_modules/@codebridge/core/dist/secret-migration.js +55 -0
  169. package/node_modules/@codebridge/core/dist/secret-refs.d.ts +34 -0
  170. package/node_modules/@codebridge/core/dist/secret-refs.js +142 -0
  171. package/node_modules/@codebridge/core/dist/session-event-wire.d.ts +17 -0
  172. package/node_modules/@codebridge/core/dist/session-event-wire.js +28 -0
  173. package/node_modules/@codebridge/core/dist/types.d.ts +363 -0
  174. package/node_modules/@codebridge/core/dist/types.js +22 -0
  175. package/node_modules/@codebridge/core/dist/workspace-key.d.ts +11 -0
  176. package/node_modules/@codebridge/core/dist/workspace-key.js +25 -0
  177. package/node_modules/@codebridge/core/package.json +22 -0
  178. package/node_modules/@codebridge/mcp-runtime/dist/.tsbuildinfo +1 -0
  179. package/node_modules/@codebridge/mcp-runtime/dist/index.d.ts +92 -0
  180. package/node_modules/@codebridge/mcp-runtime/dist/index.js +377 -0
  181. package/node_modules/@codebridge/mcp-runtime/package.json +19 -0
  182. package/node_modules/@codebridge/policy/dist/capability-runtime.d.ts +123 -0
  183. package/node_modules/@codebridge/policy/dist/capability-runtime.js +195 -0
  184. package/node_modules/@codebridge/policy/dist/demo-capabilities.d.ts +4 -0
  185. package/node_modules/@codebridge/policy/dist/demo-capabilities.js +134 -0
  186. package/node_modules/@codebridge/policy/dist/equity-capabilities.d.ts +8 -0
  187. package/node_modules/@codebridge/policy/dist/equity-capabilities.js +35 -0
  188. package/node_modules/@codebridge/policy/dist/index.d.ts +107 -0
  189. package/node_modules/@codebridge/policy/dist/index.js +317 -0
  190. package/node_modules/@codebridge/policy/package.json +17 -0
  191. package/node_modules/@codebridge/project-catalog/dist/index.d.ts +145 -0
  192. package/node_modules/@codebridge/project-catalog/dist/index.js +699 -0
  193. package/node_modules/@codebridge/project-catalog/package.json +18 -0
  194. package/node_modules/@codebridge/router/dist/channel-stream-projector.d.ts +19 -0
  195. package/node_modules/@codebridge/router/dist/channel-stream-projector.js +68 -0
  196. package/node_modules/@codebridge/router/dist/command-help.d.ts +14 -0
  197. package/node_modules/@codebridge/router/dist/command-help.js +151 -0
  198. package/node_modules/@codebridge/router/dist/feishu-stream-presenter.d.ts +18 -0
  199. package/node_modules/@codebridge/router/dist/feishu-stream-presenter.js +193 -0
  200. package/node_modules/@codebridge/router/dist/index.d.ts +9 -0
  201. package/node_modules/@codebridge/router/dist/index.js +9 -0
  202. package/node_modules/@codebridge/router/dist/model-effort.d.ts +5 -0
  203. package/node_modules/@codebridge/router/dist/model-effort.js +33 -0
  204. package/node_modules/@codebridge/router/dist/orchestrator.d.ts +56 -0
  205. package/node_modules/@codebridge/router/dist/orchestrator.js +290 -0
  206. package/node_modules/@codebridge/router/dist/session-list-format.d.ts +19 -0
  207. package/node_modules/@codebridge/router/dist/session-list-format.js +97 -0
  208. package/node_modules/@codebridge/router/dist/session-rotation.d.ts +9 -0
  209. package/node_modules/@codebridge/router/dist/session-rotation.js +31 -0
  210. package/node_modules/@codebridge/router/dist/session-router.d.ts +59 -0
  211. package/node_modules/@codebridge/router/dist/session-router.js +182 -0
  212. package/node_modules/@codebridge/router/dist/slash-commands.d.ts +78 -0
  213. package/node_modules/@codebridge/router/dist/slash-commands.js +874 -0
  214. package/node_modules/@codebridge/router/package.json +18 -0
  215. package/node_modules/@codebridge/run-executor/dist/agent-event-aggregator.d.ts +18 -0
  216. package/node_modules/@codebridge/run-executor/dist/agent-event-aggregator.js +88 -0
  217. package/node_modules/@codebridge/run-executor/dist/index.d.ts +55 -0
  218. package/node_modules/@codebridge/run-executor/dist/index.js +754 -0
  219. package/node_modules/@codebridge/run-executor/dist/run-heartbeat.d.ts +14 -0
  220. package/node_modules/@codebridge/run-executor/dist/run-heartbeat.js +24 -0
  221. package/node_modules/@codebridge/run-executor/package.json +20 -0
  222. package/node_modules/@codebridge/runner-client/dist/index.d.ts +142 -0
  223. package/node_modules/@codebridge/runner-client/dist/index.js +439 -0
  224. package/node_modules/@codebridge/runner-client/package.json +18 -0
  225. package/node_modules/@codebridge/runner-host/dist/cli.d.ts +3 -0
  226. package/node_modules/@codebridge/runner-host/dist/cli.js +58 -0
  227. package/node_modules/@codebridge/runner-host/dist/codex-session-ownership.d.ts +13 -0
  228. package/node_modules/@codebridge/runner-host/dist/codex-session-ownership.js +79 -0
  229. package/node_modules/@codebridge/runner-host/dist/deployment-mcp-server.d.ts +10 -0
  230. package/node_modules/@codebridge/runner-host/dist/deployment-mcp-server.js +54 -0
  231. package/node_modules/@codebridge/runner-host/dist/fcb-script.d.ts +3 -0
  232. package/node_modules/@codebridge/runner-host/dist/fcb-script.js +99 -0
  233. package/node_modules/@codebridge/runner-host/dist/index.d.ts +3 -0
  234. package/node_modules/@codebridge/runner-host/dist/index.js +2 -0
  235. package/node_modules/@codebridge/runner-host/dist/materialize-attachments.d.ts +4 -0
  236. package/node_modules/@codebridge/runner-host/dist/materialize-attachments.js +62 -0
  237. package/node_modules/@codebridge/runner-host/dist/server.d.ts +150 -0
  238. package/node_modules/@codebridge/runner-host/dist/server.js +1295 -0
  239. package/node_modules/@codebridge/runner-host/dist/session-lease.d.ts +12 -0
  240. package/node_modules/@codebridge/runner-host/dist/session-lease.js +146 -0
  241. package/node_modules/@codebridge/runner-host/package.json +26 -0
  242. package/node_modules/@codebridge/session-catalog/dist/index.d.ts +124 -0
  243. package/node_modules/@codebridge/session-catalog/dist/index.js +411 -0
  244. package/node_modules/@codebridge/session-catalog/package.json +17 -0
  245. package/node_modules/@codebridge/session-coordinator/dist/coordinator.d.ts +111 -0
  246. package/node_modules/@codebridge/session-coordinator/dist/coordinator.js +364 -0
  247. package/node_modules/@codebridge/session-coordinator/dist/index.d.ts +5 -0
  248. package/node_modules/@codebridge/session-coordinator/dist/index.js +5 -0
  249. package/node_modules/@codebridge/session-coordinator/dist/lease.d.ts +14 -0
  250. package/node_modules/@codebridge/session-coordinator/dist/lease.js +26 -0
  251. package/node_modules/@codebridge/session-coordinator/dist/queued-claim.d.ts +20 -0
  252. package/node_modules/@codebridge/session-coordinator/dist/queued-claim.js +45 -0
  253. package/node_modules/@codebridge/session-coordinator/dist/recovery.d.ts +31 -0
  254. package/node_modules/@codebridge/session-coordinator/dist/recovery.js +114 -0
  255. package/node_modules/@codebridge/session-coordinator/package.json +17 -0
  256. package/node_modules/@codebridge/web/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  257. package/node_modules/@codebridge/web/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  258. package/node_modules/@codebridge/web/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  259. package/node_modules/@codebridge/web/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  260. package/node_modules/@codebridge/web/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  261. package/node_modules/@codebridge/web/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  262. package/node_modules/@codebridge/web/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  263. package/node_modules/@codebridge/web/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  264. package/node_modules/@codebridge/web/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  265. package/node_modules/@codebridge/web/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  266. package/node_modules/@codebridge/web/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  267. package/node_modules/@codebridge/web/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  268. package/node_modules/@codebridge/web/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  269. package/node_modules/@codebridge/web/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  270. package/node_modules/@codebridge/web/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  271. package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  272. package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  273. package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  274. package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  275. package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  276. package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  277. package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  278. package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  279. package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  280. package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  281. package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  282. package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  283. package/node_modules/@codebridge/web/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  284. package/node_modules/@codebridge/web/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  285. package/node_modules/@codebridge/web/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  286. package/node_modules/@codebridge/web/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  287. package/node_modules/@codebridge/web/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  288. package/node_modules/@codebridge/web/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  289. package/node_modules/@codebridge/web/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  290. package/node_modules/@codebridge/web/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  291. package/node_modules/@codebridge/web/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  292. package/node_modules/@codebridge/web/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  293. package/node_modules/@codebridge/web/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  294. package/node_modules/@codebridge/web/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  295. package/node_modules/@codebridge/web/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  296. package/node_modules/@codebridge/web/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  297. package/node_modules/@codebridge/web/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  298. package/node_modules/@codebridge/web/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  299. package/node_modules/@codebridge/web/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  300. package/node_modules/@codebridge/web/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  301. package/node_modules/@codebridge/web/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  302. package/node_modules/@codebridge/web/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  303. package/node_modules/@codebridge/web/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  304. package/node_modules/@codebridge/web/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  305. package/node_modules/@codebridge/web/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  306. package/node_modules/@codebridge/web/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  307. package/node_modules/@codebridge/web/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  308. package/node_modules/@codebridge/web/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  309. package/node_modules/@codebridge/web/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  310. package/node_modules/@codebridge/web/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  311. package/node_modules/@codebridge/web/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  312. package/node_modules/@codebridge/web/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  313. package/node_modules/@codebridge/web/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  314. package/node_modules/@codebridge/web/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  315. package/node_modules/@codebridge/web/dist/assets/abnfDiagram-N423BO3Z-C-JdFv0U.js +1 -0
  316. package/node_modules/@codebridge/web/dist/assets/arc-DsNROjzU.js +1 -0
  317. package/node_modules/@codebridge/web/dist/assets/architecture-TIHT7OUA-ZEBHG2JZ.js +1 -0
  318. package/node_modules/@codebridge/web/dist/assets/architectureDiagram-T3A2C74G-OsrxcwPM.js +36 -0
  319. package/node_modules/@codebridge/web/dist/assets/array-BifhSqXX.js +1 -0
  320. package/node_modules/@codebridge/web/dist/assets/blockDiagram-VBNYF7ZC-DRgfNeNW.js +132 -0
  321. package/node_modules/@codebridge/web/dist/assets/c4Diagram-5PPSVZJV-BtOGKTh8.js +10 -0
  322. package/node_modules/@codebridge/web/dist/assets/channel-MhXyjxUS.js +1 -0
  323. package/node_modules/@codebridge/web/dist/assets/chunk-2GRJ4B5K-Dy1gJ7sY.js +1 -0
  324. package/node_modules/@codebridge/web/dist/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
  325. package/node_modules/@codebridge/web/dist/assets/chunk-4I5QYGJK-1pOLR_SG.js +1 -0
  326. package/node_modules/@codebridge/web/dist/assets/chunk-5RXB4S5H-CP43rgsO.js +231 -0
  327. package/node_modules/@codebridge/web/dist/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
  328. package/node_modules/@codebridge/web/dist/assets/chunk-6Q2QTUOP-Bi3Xrp6W.js +88 -0
  329. package/node_modules/@codebridge/web/dist/assets/chunk-7BUUIJ7U-Bb538aSH.js +1 -0
  330. package/node_modules/@codebridge/web/dist/assets/chunk-7Z6QIM7H-CILAW2Nk.js +10 -0
  331. package/node_modules/@codebridge/web/dist/assets/chunk-GF5L2VYU-CAp09yhq.js +206 -0
  332. package/node_modules/@codebridge/web/dist/assets/chunk-I66GZJ75-B_rJXmNu.js +128 -0
  333. package/node_modules/@codebridge/web/dist/assets/chunk-JQJVKLGR-OVeOJFCx.js +156 -0
  334. package/node_modules/@codebridge/web/dist/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
  335. package/node_modules/@codebridge/web/dist/assets/chunk-KBJHAD2P-uaupp0k5.js +1 -0
  336. package/node_modules/@codebridge/web/dist/assets/chunk-KEIR6QF5-BICK3FdT.js +161 -0
  337. package/node_modules/@codebridge/web/dist/assets/chunk-NSK5VX7P-fIHF5wwn.js +2 -0
  338. package/node_modules/@codebridge/web/dist/assets/chunk-QR6OTTB3-DxkJuF2b.js +62 -0
  339. package/node_modules/@codebridge/web/dist/assets/chunk-RYQCIY6F-CC5j3u-X.js +1 -0
  340. package/node_modules/@codebridge/web/dist/assets/chunk-UBXNYLIW-DB35O-6R.js +1 -0
  341. package/node_modules/@codebridge/web/dist/assets/chunk-W5SLKNZC-bkRBsbq-.js +1 -0
  342. package/node_modules/@codebridge/web/dist/assets/chunk-WRU74C26-DwvEoD-1.js +70 -0
  343. package/node_modules/@codebridge/web/dist/assets/chunk-XXDRQBXY-DRyYA-HY.js +1 -0
  344. package/node_modules/@codebridge/web/dist/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
  345. package/node_modules/@codebridge/web/dist/assets/classDiagram-JCYQIIEL-B8r7z8ii.js +1 -0
  346. package/node_modules/@codebridge/web/dist/assets/classDiagram-v2-OCEON4UE-B8r7z8ii.js +1 -0
  347. package/node_modules/@codebridge/web/dist/assets/cose-bilkent-JH36ORCC-CLkwlrX7.js +1 -0
  348. package/node_modules/@codebridge/web/dist/assets/cynefin-VYW2F7L2-C3_Llw02.js +1 -0
  349. package/node_modules/@codebridge/web/dist/assets/cynefinDiagram-MW4NZA55-D5v7UnJy.js +62 -0
  350. package/node_modules/@codebridge/web/dist/assets/cytoscape.esm-B-NFISlW.js +321 -0
  351. package/node_modules/@codebridge/web/dist/assets/dagre-Buvkdvvj.js +1 -0
  352. package/node_modules/@codebridge/web/dist/assets/dagre-VZM6K2ZE-Cr0IibwW.js +4 -0
  353. package/node_modules/@codebridge/web/dist/assets/defaultLocale-BFoDCU3G.js +1 -0
  354. package/node_modules/@codebridge/web/dist/assets/diagram-7IWD3JNH-CpQXDIzA.js +30 -0
  355. package/node_modules/@codebridge/web/dist/assets/diagram-B4RE2ZJO-VaOkH0Ya.js +3 -0
  356. package/node_modules/@codebridge/web/dist/assets/diagram-LBJQPF4R-D0iXyNks.js +24 -0
  357. package/node_modules/@codebridge/web/dist/assets/diagram-Q27KOJAE-CtqYk01P.js +24 -0
  358. package/node_modules/@codebridge/web/dist/assets/diagram-UB23O5K3-CFnd3H1_.js +41 -0
  359. package/node_modules/@codebridge/web/dist/assets/dist-D2L7nRdk.js +1 -0
  360. package/node_modules/@codebridge/web/dist/assets/ebnfDiagram-BXEA7PRR-B0GIbJYt.js +1 -0
  361. package/node_modules/@codebridge/web/dist/assets/erDiagram-JOGREHBK-BApaLGVA.js +85 -0
  362. package/node_modules/@codebridge/web/dist/assets/eventmodeling-45OFAUF4-DqGGjcld.js +1 -0
  363. package/node_modules/@codebridge/web/dist/assets/flowDiagram-UKHOOZJN-I_qlizLH.js +1 -0
  364. package/node_modules/@codebridge/web/dist/assets/ganttDiagram-PKOTCBZU-B-QZ-J82.js +292 -0
  365. package/node_modules/@codebridge/web/dist/assets/gitGraph-TEB2WS4Q-DK2SJ2Ne.js +1 -0
  366. package/node_modules/@codebridge/web/dist/assets/gitGraphDiagram-DS77QQ5N-B6Z-pu0D.js +106 -0
  367. package/node_modules/@codebridge/web/dist/assets/graphlib-DS17s2tU.js +1 -0
  368. package/node_modules/@codebridge/web/dist/assets/index-8BzpyygS.js +559 -0
  369. package/node_modules/@codebridge/web/dist/assets/index-Bzaz89LE.css +1 -0
  370. package/node_modules/@codebridge/web/dist/assets/info-DKCQHKI2-CGWxt_Py.js +1 -0
  371. package/node_modules/@codebridge/web/dist/assets/infoDiagram-6WML65LV-77XjrPZs.js +2 -0
  372. package/node_modules/@codebridge/web/dist/assets/init-C-OQMol4.js +1 -0
  373. package/node_modules/@codebridge/web/dist/assets/ishikawaDiagram-WSZJBQD7-P1bZAz2x.js +70 -0
  374. package/node_modules/@codebridge/web/dist/assets/journeyDiagram-NVQOT4AX-C4rwMcBY.js +139 -0
  375. package/node_modules/@codebridge/web/dist/assets/kanban-definition-27J2QSJJ-mtw4a9bc.js +89 -0
  376. package/node_modules/@codebridge/web/dist/assets/line-DP4RkYqm.js +1 -0
  377. package/node_modules/@codebridge/web/dist/assets/linear-DMg3PPio.js +1 -0
  378. package/node_modules/@codebridge/web/dist/assets/map-BaFkSB1l.js +1 -0
  379. package/node_modules/@codebridge/web/dist/assets/mermaid-parser.core-HY84kHw1.js +7 -0
  380. package/node_modules/@codebridge/web/dist/assets/mermaid.core-DdgCdsnM.js +42 -0
  381. package/node_modules/@codebridge/web/dist/assets/mindmap-definition-FAOFIHXS-Cw1EnbhZ.js +96 -0
  382. package/node_modules/@codebridge/web/dist/assets/ordinal-BDEzSJ7C.js +1 -0
  383. package/node_modules/@codebridge/web/dist/assets/packet-7NZHBO7P-CEbrbJH3.js +1 -0
  384. package/node_modules/@codebridge/web/dist/assets/path-fybaL0A-.js +1 -0
  385. package/node_modules/@codebridge/web/dist/assets/pegDiagram-VL7TDLO6-CEc1Gedb.js +1 -0
  386. package/node_modules/@codebridge/web/dist/assets/pie-RZYD4A2V-DPXVs-IW.js +1 -0
  387. package/node_modules/@codebridge/web/dist/assets/pieDiagram-7S7Q4E2Y-hoQeGMFH.js +39 -0
  388. package/node_modules/@codebridge/web/dist/assets/quadrantDiagram-CIZ2JOQS-C-Nmxx0f.js +7 -0
  389. package/node_modules/@codebridge/web/dist/assets/radar-I7S5WNFK-BVd3X3Pd.js +1 -0
  390. package/node_modules/@codebridge/web/dist/assets/railroad-3IZDKUUU-CxLxzr_v.js +1 -0
  391. package/node_modules/@codebridge/web/dist/assets/railroad-abnf-AHOZXSZD-MA1zPI84.js +1 -0
  392. package/node_modules/@codebridge/web/dist/assets/railroad-ebnf-EBAXGLYW-Bqug_umD.js +1 -0
  393. package/node_modules/@codebridge/web/dist/assets/railroad-peg-LSFZ7HO6-DRcRFwpq.js +1 -0
  394. package/node_modules/@codebridge/web/dist/assets/railroadDiagram-AXF67PYL-B007ZkL9.js +1 -0
  395. package/node_modules/@codebridge/web/dist/assets/requirementDiagram-LRYGKXZP-LrTCcEi5.js +84 -0
  396. package/node_modules/@codebridge/web/dist/assets/rough.esm-Dy-Kn_BL.js +1 -0
  397. package/node_modules/@codebridge/web/dist/assets/sankeyDiagram-W5VNT64P-Ch4mzHck.js +40 -0
  398. package/node_modules/@codebridge/web/dist/assets/sequenceDiagram-SI44F4Z6-CHg4OzLX.js +162 -0
  399. package/node_modules/@codebridge/web/dist/assets/sizeCapture-X5ZJPWSS-B0uUizjq.js +1 -0
  400. package/node_modules/@codebridge/web/dist/assets/src-BrO6_odD.js +1 -0
  401. package/node_modules/@codebridge/web/dist/assets/stateDiagram-OKZ733FA-7cVkr5nR.js +1 -0
  402. package/node_modules/@codebridge/web/dist/assets/stateDiagram-v2-UEYNNEHI-CTy_mAXb.js +1 -0
  403. package/node_modules/@codebridge/web/dist/assets/swimlanes-SLNWSIFB-BwSVF5qy.js +2 -0
  404. package/node_modules/@codebridge/web/dist/assets/swimlanesDiagram-ULZ7WXOC-BBQnfZ1j.js +8 -0
  405. package/node_modules/@codebridge/web/dist/assets/timeline-definition-Z64GVDOM-BaHEkVDV.js +120 -0
  406. package/node_modules/@codebridge/web/dist/assets/treeView-QDETBFTQ-CF0kLN62.js +1 -0
  407. package/node_modules/@codebridge/web/dist/assets/treemap-6X3UGDF4-BB8A8uux.js +1 -0
  408. package/node_modules/@codebridge/web/dist/assets/vennDiagram-T6HMQDX7-BFK12Iro.js +34 -0
  409. package/node_modules/@codebridge/web/dist/assets/wardley-OPB4EBWU-C_3y61zk.js +1 -0
  410. package/node_modules/@codebridge/web/dist/assets/wardleyDiagram-T6FBY63Y-W2oGu4WK.js +78 -0
  411. package/node_modules/@codebridge/web/dist/assets/xychartDiagram-ELKLHX3M-BiVRnbvz.js +7 -0
  412. package/node_modules/@codebridge/web/dist/brand/agent-logo-carbon.svg +1 -0
  413. package/node_modules/@codebridge/web/dist/brand/agent-logo.svg +1 -0
  414. package/node_modules/@codebridge/web/dist/brand/agnet-logo-carbon.svg +1 -0
  415. package/node_modules/@codebridge/web/dist/brand/agnet-logo.svg +1 -0
  416. package/node_modules/@codebridge/web/dist/brand/agnet-mark-carbon.svg +1 -0
  417. package/node_modules/@codebridge/web/dist/brand/agnet-mark.svg +1 -0
  418. package/node_modules/@codebridge/web/dist/fonts/CommitMono-400-Regular.otf +0 -0
  419. package/node_modules/@codebridge/web/dist/fonts/CommitMono-700-Regular.otf +0 -0
  420. package/node_modules/@codebridge/web/dist/fonts/CommitMono-OFL.txt +21 -0
  421. package/node_modules/@codebridge/web/dist/fonts/DepartureMono-OFL.txt +21 -0
  422. package/node_modules/@codebridge/web/dist/fonts/DepartureMono-Regular.woff2 +0 -0
  423. package/node_modules/@codebridge/web/dist/index.html +25 -0
  424. package/node_modules/@codebridge/web/package.json +7 -0
  425. package/node_modules/@codebridge/work-items/dist/index.d.ts +371 -0
  426. package/node_modules/@codebridge/work-items/dist/index.js +1784 -0
  427. package/node_modules/@codebridge/work-items/dist/session-projector.d.ts +4 -0
  428. package/node_modules/@codebridge/work-items/dist/session-projector.js +506 -0
  429. package/node_modules/@codebridge/work-items/dist/session-runtime.d.ts +274 -0
  430. package/node_modules/@codebridge/work-items/dist/session-runtime.js +1103 -0
  431. package/node_modules/@codebridge/work-items/dist/session-schema.d.ts +9 -0
  432. package/node_modules/@codebridge/work-items/dist/session-schema.js +292 -0
  433. package/node_modules/@codebridge/work-items/package.json +20 -0
  434. package/package.json +75 -4
@@ -0,0 +1,1378 @@
1
+ import { cloneSetupManifest, projectAgentStatus, projectSetupState } from "@codebridge/agent-registry";
2
+ import { canonicalWorkspaceKey, isSupportedAgentId } from "@codebridge/core";
3
+ import { Hono } from "hono";
4
+ import { randomUUID } from "node:crypto";
5
+ import { ProviderHistoryImporter } from "./session-history-import.js";
6
+ import { registerSessionRuntimeCommandRoutes, registerSessionRuntimeReadRoutes } from "./session-runtime-api.js";
7
+ export function createSessionApp(options, token) {
8
+ const app = new Hono();
9
+ const channelOriginToken = randomUUID();
10
+ const currentAgents = () => options.agentRegistry?.list()
11
+ ?? (typeof options.agents === "function" ? options.agents() : options.agents);
12
+ const currentProfiles = () => new Map(currentAgents().map((agent) => [agent.agentId, agent]));
13
+ const configOptionRequests = new Map();
14
+ const historyImporter = options.runner
15
+ ? new ProviderHistoryImporter({
16
+ store: options.workItems,
17
+ catalog: options.catalog,
18
+ runner: options.runner,
19
+ defaultCwd: options.defaultCwd,
20
+ })
21
+ : undefined;
22
+ function agentListPayload() {
23
+ const agents = currentAgents();
24
+ const defaultAgentId = options.configStore?.get().defaultAgent ?? null;
25
+ return {
26
+ agents: agents.map(toApiAgent),
27
+ default_agent_id: defaultAgentId,
28
+ effective_default_agent_id: resolveEffectiveDefaultAgentId(agents, defaultAgentId),
29
+ };
30
+ }
31
+ function applySetupToAgent(agent, setup) {
32
+ return options.agentRegistry?.updateSetup(agent.agentId, setup) ?? mergeAgentSetup(agent, setup);
33
+ }
34
+ app.use("/v1/*", async (c, next) => {
35
+ if (c.req.header("authorization") !== `Bearer ${token}`) {
36
+ return c.json({ error: "unauthorized" }, 401);
37
+ }
38
+ await next();
39
+ });
40
+ registerSessionRuntimeReadRoutes(app, {
41
+ catalog: options.catalog,
42
+ workItems: options.workItems,
43
+ });
44
+ if (options.coordinator) {
45
+ registerSessionRuntimeCommandRoutes(app, {
46
+ catalog: options.catalog,
47
+ workItems: options.workItems,
48
+ coordinator: options.coordinator,
49
+ executor: options.executor,
50
+ capabilities: options.capabilities,
51
+ channelOriginToken,
52
+ });
53
+ }
54
+ app.get("/v1/agents", (c) => c.json(agentListPayload()));
55
+ app.get("/v1/agents/:agent_id", (c) => {
56
+ const agent = currentProfiles().get(c.req.param("agent_id"));
57
+ if (!agent)
58
+ return c.json({ error: "agent_not_found" }, 404);
59
+ return c.json(toApiAgent(agent));
60
+ });
61
+ app.post("/v1/agents/detect", async (c) => {
62
+ if (!options.runner)
63
+ return c.json({ error: "runner_unavailable" }, 503);
64
+ try {
65
+ const setup = await options.runner.detectAllAgents();
66
+ for (const agent of setup.agents) {
67
+ const profile = currentProfiles().get(agent.agentId);
68
+ if (profile)
69
+ applySetupToAgent(profile, agent);
70
+ }
71
+ return c.json(agentListPayload());
72
+ }
73
+ catch (error) {
74
+ return c.json({ error: "agent_setup_failed", message: error instanceof Error ? error.message : String(error) }, 503);
75
+ }
76
+ });
77
+ app.post("/v1/agents/:agent_id/detect", async (c) => {
78
+ const agentId = c.req.param("agent_id");
79
+ const agent = currentProfiles().get(agentId);
80
+ if (!agent)
81
+ return c.json({ error: "agent_not_found" }, 404);
82
+ if (!options.runner)
83
+ return c.json({ error: "runner_unavailable" }, 503);
84
+ try {
85
+ const setup = await options.runner.detectAgent(agentId);
86
+ const nextAgent = applySetupToAgent(agent, setup);
87
+ return c.json(toApiAgent(nextAgent));
88
+ }
89
+ catch (error) {
90
+ const status = errorStatus(error, 500);
91
+ return c.json(formatAgentSetupError(error, agent), status);
92
+ }
93
+ });
94
+ app.post("/v1/agents/:agent_id/install", async (c) => {
95
+ const agentId = c.req.param("agent_id");
96
+ const agent = currentProfiles().get(agentId);
97
+ if (!agent)
98
+ return c.json({ error: "agent_not_found" }, 404);
99
+ if (!options.runner)
100
+ return c.json({ error: "runner_unavailable" }, 503);
101
+ const body = await c.req.json().catch(() => null);
102
+ if (!body || typeof body.strategy_id !== "string" || !body.strategy_id.trim()) {
103
+ return c.json({ error: "install_strategy_not_found" }, 400);
104
+ }
105
+ try {
106
+ const result = await options.runner.installAgent(agentId, body.strategy_id.trim());
107
+ const nextAgent = applySetupToAgent(agent, result);
108
+ if (!result.ok) {
109
+ return c.json({
110
+ error: result.diagnostic?.code ?? "install_failed",
111
+ message: result.diagnostic?.message ?? "Agent installation failed.",
112
+ details: result.diagnostic?.details,
113
+ agent: toApiAgent(nextAgent),
114
+ }, result.diagnostic?.code === "install_not_supported" ? 400 : 409);
115
+ }
116
+ return c.json(toApiAgent(nextAgent));
117
+ }
118
+ catch (error) {
119
+ const status = errorStatus(error, 500);
120
+ return c.json(formatAgentSetupError(error, agent), status);
121
+ }
122
+ });
123
+ app.patch("/v1/settings/default-agent", async (c) => {
124
+ const body = await c.req.json().catch(() => null);
125
+ const agentId = typeof body?.agent_id === "string" ? body.agent_id.trim() : "";
126
+ if (!agentId)
127
+ return c.json({ error: "agent_not_found" }, 404);
128
+ const agent = currentProfiles().get(agentId);
129
+ if (!agent)
130
+ return c.json({ error: "agent_not_found" }, 404);
131
+ const setup = agent.setup;
132
+ if (!setup || setup.installation !== "installed") {
133
+ return c.json({ error: "agent_not_installed", message: `${agent.displayName ?? agent.agentId} is not installed.` }, 409);
134
+ }
135
+ if (setup.configuration !== "configured") {
136
+ return c.json({ error: "agent_not_configured", message: `${agent.displayName ?? agent.agentId} is not configured.` }, 409);
137
+ }
138
+ if (!options.configStore) {
139
+ return c.json({ error: "config_store_unavailable" }, 503);
140
+ }
141
+ try {
142
+ options.configStore.update((current) => ({
143
+ ...current,
144
+ defaultAgent: agentId,
145
+ ...(isSupportedAgentId(agentId) ? { defaultBackend: agentId } : {}),
146
+ }));
147
+ return c.json(agentListPayload());
148
+ }
149
+ catch (error) {
150
+ return c.json({
151
+ error: "default_agent_persist_failed",
152
+ message: error instanceof Error ? error.message : String(error),
153
+ }, 500);
154
+ }
155
+ });
156
+ app.get("/v1/attachments/:attachment_id", (c) => {
157
+ const attachment = options.workItems.getMessageAttachment(c.req.param("attachment_id"));
158
+ if (!attachment)
159
+ return c.json({ error: "attachment_not_found" }, 404);
160
+ return c.json(toApiAttachment(attachment));
161
+ });
162
+ // Pi provider management, proxied to the runner (docs/orchestration/agent-providers.md).
163
+ app.get("/v1/providers", async (c) => {
164
+ if (!options.runner)
165
+ return c.json({ error: "runner_unavailable" }, 503);
166
+ return c.json(await options.runner.listPiProviders());
167
+ });
168
+ app.put("/v1/providers", async (c) => {
169
+ if (!options.runner)
170
+ return c.json({ error: "runner_unavailable" }, 503);
171
+ const body = await c.req.json().catch(() => null);
172
+ if (!body)
173
+ return c.json({ error: "invalid_json" }, 400);
174
+ try {
175
+ const result = await options.runner.savePiProviders(body);
176
+ configOptionRequests.clear();
177
+ return c.json(result);
178
+ }
179
+ catch (error) {
180
+ return c.json({ error: "invalid_providers", message: error instanceof Error ? error.message : String(error) }, 400);
181
+ }
182
+ });
183
+ app.get("/v1/providers/presets", async (c) => {
184
+ if (!options.runner)
185
+ return c.json({ error: "runner_unavailable" }, 503);
186
+ return c.json(await options.runner.listPiProviderPresets());
187
+ });
188
+ app.post("/v1/providers/test", async (c) => {
189
+ if (!options.runner)
190
+ return c.json({ error: "runner_unavailable" }, 503);
191
+ const body = (await c.req.json().catch(() => null));
192
+ if (!body || typeof body.baseUrl !== "string")
193
+ return c.json({ error: "baseUrl is required" }, 400);
194
+ return c.json(await options.runner.testPiProvider({
195
+ baseUrl: body.baseUrl,
196
+ apiKey: body.apiKey,
197
+ authHeader: body.authHeader,
198
+ api: typeof body.api === "string" ? body.api : undefined,
199
+ model: typeof body.model === "string" ? body.model : undefined,
200
+ }));
201
+ });
202
+ app.get("/v1/sessions", (c) => {
203
+ if (c.req.query("import") === "true") {
204
+ return c.json({ error: "provider_import_moved" }, 410);
205
+ }
206
+ const agentId = c.req.query("agent_id");
207
+ const profiles = currentProfiles();
208
+ return c.json({
209
+ sessions: options.catalog.listSessions(agentId, {
210
+ includeArchived: c.req.query("include_archived") === "true",
211
+ }).map((session) => ({
212
+ ...toApiSession(session),
213
+ agent: profiles.get(session.agentId)?.displayName ?? session.agentId,
214
+ })),
215
+ provider_errors: [],
216
+ });
217
+ });
218
+ app.post("/v1/sessions/import", async (c) => {
219
+ const body = await readJson(c);
220
+ const cwd = typeof body?.cwd === "string"
221
+ ? body.cwd
222
+ : options.defaultCwd;
223
+ if (!cwd)
224
+ return c.json({ error: "workspace_required" }, 400);
225
+ const agentId = typeof body?.agent_id === "string"
226
+ ? body.agent_id
227
+ : undefined;
228
+ const sync = await syncProviderSessions(options, currentProfiles(), agentId, cwd);
229
+ return c.json({
230
+ sessions: options.catalog
231
+ .listSessions(agentId)
232
+ .map(toApiSession),
233
+ provider_errors: sync.errors,
234
+ });
235
+ });
236
+ app.post("/v1/sessions", async (c) => {
237
+ const body = await readJson(c);
238
+ const agent = typeof body?.agent_id === "string" ? currentProfiles().get(body.agent_id) : undefined;
239
+ if (!agent) {
240
+ return c.json({ error: "agent_id must reference a registered Agent" }, 400);
241
+ }
242
+ if (agent.status !== "healthy") {
243
+ return c.json({ error: "agent_unavailable", status: agent.status }, 409);
244
+ }
245
+ const idempotencyKey = c.req.header("idempotency-key");
246
+ if (idempotencyKey) {
247
+ const cached = options.workItems.getIdempotencyResponse("session:create", idempotencyKey);
248
+ if (cached !== undefined)
249
+ return c.json(cached, 201);
250
+ }
251
+ const sessionBody = body ?? {};
252
+ const configOverrides = Object.hasOwn(sessionBody, "config_overrides")
253
+ ? parseConfigOverrides(sessionBody.config_overrides)
254
+ : {};
255
+ if (!configOverrides)
256
+ return c.json({ error: "config_overrides must contain only string or boolean values" }, 400);
257
+ const requestedCwd = asNullableString(sessionBody.cwd) ?? options.defaultCwd ?? null;
258
+ let cwd = requestedCwd;
259
+ if (requestedCwd && options.runner) {
260
+ const authorization = await options.runner.authorizeDirectory(requestedCwd);
261
+ if (!authorization.ok) {
262
+ return c.json({ error: "workspace_not_authorized", detail: authorization.error ?? "目录无法访问" }, 403);
263
+ }
264
+ cwd = authorization.path ?? requestedCwd;
265
+ }
266
+ const session = options.catalog.createSession({
267
+ agentId: agent.agentId,
268
+ model: asNullableString(sessionBody.model),
269
+ effort: asNullableString(sessionBody.effort),
270
+ configOverrides,
271
+ permissionMode: asNullableString(sessionBody.permission_mode),
272
+ folderId: asNullableString(sessionBody.folder_id),
273
+ cwd,
274
+ title: asNullableString(sessionBody.title),
275
+ });
276
+ const response = toApiSession(session);
277
+ if (idempotencyKey)
278
+ options.workItems.putIdempotencyResponse("session:create", idempotencyKey, response);
279
+ return c.json(response, 201);
280
+ });
281
+ app.post("/v1/channels/:channel/conversations/:conversation_id/messages", async (c) => {
282
+ const body = await readJson(c);
283
+ if (!body || typeof body.message !== "string" || !body.message.trim()) {
284
+ return c.json({ error: "message is required" }, 400);
285
+ }
286
+ const channel = c.req.param("channel");
287
+ const conversationId = c.req.param("conversation_id");
288
+ const requestedAgent = typeof body.agent_id === "string" ? currentProfiles().get(body.agent_id) : undefined;
289
+ const agent = requestedAgent ?? currentAgents().find((candidate) => candidate.status === "healthy");
290
+ if (!agent)
291
+ return c.json({ error: "agent_unavailable" }, 409);
292
+ let cwd = asNullableString(body.cwd);
293
+ if (cwd && options.runner) {
294
+ const authorization = await options.runner.authorizeDirectory(cwd);
295
+ if (!authorization.ok) {
296
+ return c.json({ error: "workspace_not_authorized", detail: authorization.error ?? "目录无法访问" }, 403);
297
+ }
298
+ cwd = authorization.path ?? cwd;
299
+ }
300
+ const generation = Number.isSafeInteger(body.generation)
301
+ ? Number(body.generation)
302
+ : 0;
303
+ const hasReplyToMessageId = Object.hasOwn(body, "reply_to_message_id");
304
+ const hasShowThinking = Object.hasOwn(body, "show_thinking");
305
+ if (hasReplyToMessageId !== hasShowThinking) {
306
+ return c.json({ error: "channel_delivery_incomplete" }, 400);
307
+ }
308
+ if (hasReplyToMessageId
309
+ && (typeof body.reply_to_message_id !== "string"
310
+ || !body.reply_to_message_id.trim()
311
+ || typeof body.show_thinking !== "boolean")) {
312
+ return c.json({ error: "invalid_delivery" }, 400);
313
+ }
314
+ const rawActorRef = body.actor_ref && typeof body.actor_ref === "object"
315
+ ? body.actor_ref
316
+ : null;
317
+ const actorRef = (channel === "feishu" || channel === "telegram")
318
+ ? {
319
+ channel,
320
+ id: rawActorRef?.channel === channel && typeof rawActorRef.id === "string" && rawActorRef.id.trim()
321
+ ? rawActorRef.id.trim()
322
+ : "unknown",
323
+ }
324
+ : undefined;
325
+ const slot = {
326
+ channel,
327
+ conversationId,
328
+ agentId: agent.agentId,
329
+ workspaceKey: canonicalWorkspaceKey(cwd ?? options.defaultCwd ?? "").key,
330
+ generation,
331
+ };
332
+ const session = options.catalog.getOrCreateBoundSession(slot, {
333
+ agentId: agent.agentId,
334
+ model: asNullableString(body.model),
335
+ effort: asNullableString(body.effort),
336
+ permissionMode: asNullableString(body.permission_mode),
337
+ cwd: slot.workspaceKey || null,
338
+ title: asNullableString(body.title),
339
+ });
340
+ if (options.coordinator && typeof options.catalog.listChannelBindings === "function") {
341
+ for (const binding of options.catalog.listChannelBindings(channel, conversationId)) {
342
+ if (binding.sessionId === session.id)
343
+ continue;
344
+ options.coordinator.pauseQueue({
345
+ sessionId: binding.sessionId,
346
+ reason: "stale",
347
+ });
348
+ }
349
+ }
350
+ if (session.providerSessionId) {
351
+ options.workItems.setSessionProviderSessionId(session.id, session.providerSessionId);
352
+ }
353
+ const idempotencyKey = c.req.header("idempotency-key");
354
+ const childHeaders = {
355
+ authorization: `Bearer ${token}`,
356
+ "content-type": "application/json",
357
+ "x-codebridge-channel-origin": channelOriginToken,
358
+ ...(idempotencyKey ? { "idempotency-key": `${idempotencyKey}:message` } : {}),
359
+ };
360
+ const messageResponse = await app.request(`/v1/sessions/${session.id}/messages`, {
361
+ method: "POST",
362
+ headers: childHeaders,
363
+ body: JSON.stringify({
364
+ message: body.message,
365
+ inputs: channelInputRecord(body.inputs),
366
+ ...(actorRef ? { actor_ref: actorRef } : {}),
367
+ model: asNullableString(body.model),
368
+ attachments: body.attachments,
369
+ delivery: hasReplyToMessageId
370
+ ? {
371
+ channel,
372
+ conversation_id: conversationId,
373
+ reply_to_message_id: String(body.reply_to_message_id).trim(),
374
+ show_thinking: body.show_thinking,
375
+ }
376
+ : undefined,
377
+ }),
378
+ });
379
+ if (!messageResponse.ok)
380
+ return c.json(await messageResponse.json(), messageResponse.status);
381
+ if (options.coordinator) {
382
+ const result = await messageResponse.json();
383
+ const updatedSession = options.catalog.getSession(session.id);
384
+ return c.json({
385
+ channel,
386
+ conversation_id: conversationId,
387
+ session_id: session.id,
388
+ task_record_id: updatedSession?.taskRecordId ?? null,
389
+ event_sequence: result.runtime.last_event_sequence,
390
+ acceptance: result.acceptance,
391
+ queue_state: result.runtime.queue_state,
392
+ turn_id: result.turn.turn_id,
393
+ run_id: result.acceptance === "dispatched"
394
+ ? result.run_id
395
+ : null,
396
+ }, 202);
397
+ }
398
+ const messageResult = await messageResponse.json();
399
+ const runResponse = await app.request(`/v1/sessions/${session.id}/runs`, {
400
+ method: "POST",
401
+ headers: {
402
+ authorization: `Bearer ${token}`,
403
+ "content-type": "application/json",
404
+ "x-codebridge-channel-origin": channelOriginToken,
405
+ ...(idempotencyKey ? { "idempotency-key": `${idempotencyKey}:run` } : {}),
406
+ },
407
+ body: JSON.stringify({
408
+ inputs: channelInputRecord(body.inputs),
409
+ model: asNullableString(body.model),
410
+ }),
411
+ });
412
+ if (!runResponse.ok)
413
+ return c.json(await runResponse.json(), runResponse.status);
414
+ const runResult = await runResponse.json();
415
+ return c.json({
416
+ channel,
417
+ conversation_id: conversationId,
418
+ session_id: session.id,
419
+ task_record_id: messageResult.task_record_id,
420
+ event_sequence: messageResult.sequence,
421
+ ...runResult,
422
+ }, 202);
423
+ });
424
+ app.post("/v1/sessions/:session_id/directories", async (c) => {
425
+ const session = options.catalog.getSession(c.req.param("session_id"));
426
+ if (!session)
427
+ return c.json({ error: "session_not_found" }, 404);
428
+ if (!options.runner)
429
+ return c.json({ error: "runner_unavailable" }, 503);
430
+ const body = await readJson(c);
431
+ if (!body || typeof body.path !== "string" || !body.path.trim()) {
432
+ return c.json({ error: "path is required" }, 400);
433
+ }
434
+ const authorization = await options.runner.authorizeDirectory(body.path);
435
+ if (!authorization.ok) {
436
+ return c.json({ error: "workspace_not_authorized", detail: authorization.error ?? "目录无法访问" }, 403);
437
+ }
438
+ const directory = authorization.path ?? body.path;
439
+ const additionalDirectories = session.additionalDirectories.includes(directory)
440
+ ? session.additionalDirectories
441
+ : [...session.additionalDirectories, directory];
442
+ return c.json(toApiSession(options.catalog.updateSession(session.id, { additionalDirectories })));
443
+ });
444
+ app.post("/v1/sessions/:session_id/directories/pick", async (c) => {
445
+ const session = options.catalog.getSession(c.req.param("session_id"));
446
+ if (!session)
447
+ return c.json({ error: "session_not_found" }, 404);
448
+ if (!options.runner)
449
+ return c.json({ error: "runner_unavailable" }, 503);
450
+ const selected = await options.runner.pickDirectory();
451
+ if (!selected.ok) {
452
+ return c.json({ error: "directory_picker_failed", detail: selected.error }, 503);
453
+ }
454
+ if (selected.cancelled || !selected.path)
455
+ return c.json({ cancelled: true });
456
+ const additionalDirectories = session.additionalDirectories.includes(selected.path)
457
+ ? session.additionalDirectories
458
+ : [...session.additionalDirectories, selected.path];
459
+ return c.json(toApiSession(options.catalog.updateSession(session.id, { additionalDirectories })));
460
+ });
461
+ app.get("/v1/sessions/:session_id/files", async (c) => {
462
+ const session = options.catalog.getSession(c.req.param("session_id"));
463
+ if (!session)
464
+ return c.json({ error: "session_not_found" }, 404);
465
+ if (!options.runner)
466
+ return c.json({ error: "runner_unavailable" }, 503);
467
+ const roots = [session.cwd, ...session.additionalDirectories]
468
+ .filter((value) => Boolean(value));
469
+ const root = c.req.query("root") ?? roots[0];
470
+ if (!root)
471
+ return c.json({ ok: true, entries: [], error: "workspace_required" });
472
+ if (!roots.includes(root))
473
+ return c.json({ error: "workspace_not_authorized" }, 403);
474
+ const result = await options.runner.listDirectory(root, c.req.query("path") ?? "");
475
+ return c.json(result, result.ok ? 200 : 400);
476
+ });
477
+ app.delete("/v1/sessions/:session_id/directories", async (c) => {
478
+ const session = options.catalog.getSession(c.req.param("session_id"));
479
+ if (!session)
480
+ return c.json({ error: "session_not_found" }, 404);
481
+ const body = await readJson(c);
482
+ if (!body || typeof body.path !== "string" || !body.path.trim()) {
483
+ return c.json({ error: "path is required" }, 400);
484
+ }
485
+ const additionalDirectories = session.additionalDirectories.filter((directory) => directory !== body.path);
486
+ return c.json(toApiSession(options.catalog.updateSession(session.id, { additionalDirectories })));
487
+ });
488
+ app.post("/v1/sessions/:session_id/provider-history/preview", async (c) => {
489
+ if (!historyImporter) {
490
+ return c.json({ error: "runner_unavailable" }, 503);
491
+ }
492
+ try {
493
+ return c.json(await historyImporter.preview(c.req.param("session_id")));
494
+ }
495
+ catch (error) {
496
+ return providerHistoryError(c, error);
497
+ }
498
+ });
499
+ app.post("/v1/sessions/:session_id/provider-history/import", async (c) => {
500
+ if (!historyImporter) {
501
+ return c.json({ error: "runner_unavailable" }, 503);
502
+ }
503
+ const idempotencyKey = c.req.header("idempotency-key");
504
+ const body = await readJson(c);
505
+ if (!idempotencyKey || body?.confirm !== true) {
506
+ return c.json({ error: "confirmation_and_idempotency_key_required" }, 400);
507
+ }
508
+ try {
509
+ return c.json(await historyImporter.import(c.req.param("session_id"), idempotencyKey));
510
+ }
511
+ catch (error) {
512
+ return providerHistoryError(c, error);
513
+ }
514
+ });
515
+ app.get("/v1/sessions/:session_id", (c) => {
516
+ const session = options.catalog.getSession(c.req.param("session_id"));
517
+ if (!session)
518
+ return c.json({ error: "session_not_found" }, 404);
519
+ return c.json(toApiSession(session));
520
+ });
521
+ app.get("/v1/sessions/:session_id/config-options", async (c) => {
522
+ const session = options.catalog.getSession(c.req.param("session_id"));
523
+ if (!session)
524
+ return c.json({ error: "session_not_found" }, 404);
525
+ if (!options.runner)
526
+ return c.json({ error: "runner_unavailable" }, 503);
527
+ const cwd = session.cwd ?? options.defaultCwd;
528
+ if (!cwd)
529
+ return c.json({ options: [], error: "workspace_required" });
530
+ const cacheKey = `${session.agentId}\0${cwd}\0${session.model ?? ""}`;
531
+ let request = configOptionRequests.get(cacheKey);
532
+ if (!request) {
533
+ request = options.runner.listConfigOptions(session.agentId, cwd, session.model);
534
+ configOptionRequests.set(cacheKey, request);
535
+ void request.then(() => {
536
+ if (configOptionRequests.get(cacheKey) === request)
537
+ configOptionRequests.delete(cacheKey);
538
+ }, () => {
539
+ if (configOptionRequests.get(cacheKey) === request)
540
+ configOptionRequests.delete(cacheKey);
541
+ });
542
+ }
543
+ return c.json(await request);
544
+ });
545
+ app.get("/v1/sessions/:session_id/commands", async (c) => {
546
+ const session = options.catalog.getSession(c.req.param("session_id"));
547
+ if (!session)
548
+ return c.json({ error: "session_not_found" }, 404);
549
+ const cwd = session.cwd ?? options.defaultCwd;
550
+ let native = { commands: [] };
551
+ if (options.runner && cwd) {
552
+ try {
553
+ native = await options.runner.listCommands(session.agentId, cwd);
554
+ }
555
+ catch (error) {
556
+ native = { commands: [], error: error instanceof Error ? error.message : String(error) };
557
+ }
558
+ }
559
+ const commands = new Map(native.commands.map((command) => [command.name, command]));
560
+ if (session.taskRecordId) {
561
+ const events = options.workItems.listEvents(session.taskRecordId).reverse();
562
+ const update = events.find((event) => {
563
+ const agentEvent = event.payload.event;
564
+ return event.type === "AGENT_EVENT" && agentEvent?.type === "available_commands_update";
565
+ });
566
+ const available = update?.payload.event?.availableCommands;
567
+ if (Array.isArray(available)) {
568
+ for (const value of available) {
569
+ if (!value || typeof value !== "object")
570
+ continue;
571
+ const command = value;
572
+ if (typeof command.name !== "string" || typeof command.description !== "string")
573
+ continue;
574
+ commands.set(command.name, {
575
+ name: command.name,
576
+ description: command.description,
577
+ ...(command.input && typeof command.input === "object" ? { input: command.input } : {}),
578
+ });
579
+ }
580
+ }
581
+ }
582
+ return c.json({ commands: [...commands.values()], ...(native.error ? { error: native.error } : {}) });
583
+ });
584
+ app.patch("/v1/sessions/:session_id", async (c) => {
585
+ const session = options.catalog.getSession(c.req.param("session_id"));
586
+ if (!session)
587
+ return c.json({ error: "session_not_found" }, 404);
588
+ const body = await readJson(c);
589
+ if (!body)
590
+ return c.json({ error: "invalid_session_update" }, 400);
591
+ const update = {};
592
+ if (Object.hasOwn(body, "title")) {
593
+ if (typeof body.title !== "string" || !body.title.trim()) {
594
+ return c.json({ error: "title must be a non-empty string" }, 400);
595
+ }
596
+ update.title = body.title.trim();
597
+ }
598
+ if (Object.hasOwn(body, "model")) {
599
+ if (body.model !== null && (typeof body.model !== "string" || !body.model.trim())) {
600
+ return c.json({ error: "model must be a non-empty string or null" }, 400);
601
+ }
602
+ update.model = body.model === null ? null : body.model.trim();
603
+ }
604
+ if (Object.hasOwn(body, "permission_mode")) {
605
+ if (body.permission_mode !== null && (typeof body.permission_mode !== "string" || !body.permission_mode.trim())) {
606
+ return c.json({ error: "permission_mode must be a non-empty string or null" }, 400);
607
+ }
608
+ update.permissionMode = body.permission_mode === null ? null : body.permission_mode.trim();
609
+ }
610
+ if (Object.hasOwn(body, "effort")) {
611
+ if (body.effort !== null && (typeof body.effort !== "string" || !body.effort.trim())) {
612
+ return c.json({ error: "effort must be a non-empty string or null" }, 400);
613
+ }
614
+ update.effort = body.effort === null ? null : body.effort.trim();
615
+ }
616
+ if (Object.hasOwn(body, "config_overrides")) {
617
+ const configOverrides = parseConfigOverrides(body.config_overrides);
618
+ if (!configOverrides) {
619
+ return c.json({ error: "config_overrides must contain only string or boolean values" }, 400);
620
+ }
621
+ update.configOverrides = configOverrides;
622
+ }
623
+ for (const field of ["pinned", "archived"]) {
624
+ if (!Object.hasOwn(body, field))
625
+ continue;
626
+ if (typeof body[field] !== "boolean") {
627
+ return c.json({ error: `${field} must be a boolean` }, 400);
628
+ }
629
+ update[field] = body[field];
630
+ }
631
+ if (!Object.keys(update).length)
632
+ return c.json({ error: "invalid_session_update" }, 400);
633
+ return c.json(toApiSession(options.catalog.updateSession(session.id, update)));
634
+ });
635
+ app.post("/v1/sessions/:session_id/messages", async (c) => {
636
+ let session = options.catalog.getSession(c.req.param("session_id"));
637
+ const body = await readJson(c);
638
+ if (!session)
639
+ return c.json({ error: "session_not_found" }, 404);
640
+ if (!body || typeof body.message !== "string" || !body.message.trim()) {
641
+ return c.json({ error: "message is required" }, 400);
642
+ }
643
+ if (!session.cwd && options.defaultCwd) {
644
+ session = options.catalog.updateSession(session.id, { cwd: options.defaultCwd });
645
+ }
646
+ const attachmentInput = parseMessageAttachments(body.attachments);
647
+ if (!attachmentInput)
648
+ return c.json({ error: "invalid_attachments" }, 400);
649
+ const idempotencyKey = c.req.header("idempotency-key");
650
+ if (idempotencyKey) {
651
+ const cached = options.workItems.getIdempotencyResponse(`session:message:${session.id}`, idempotencyKey);
652
+ if (cached !== undefined)
653
+ return c.json(cached, 202);
654
+ }
655
+ const task = session.taskRecordId
656
+ ? options.workItems.getWorkItem(session.taskRecordId)
657
+ : undefined;
658
+ const model = Object.hasOwn(body, "model") ? asNullableString(body.model) : session.model;
659
+ const effort = Object.hasOwn(body, "effort") ? asNullableString(body.effort) : session.effort;
660
+ const permissionMode = Object.hasOwn(body, "permission_mode")
661
+ ? asNullableString(body.permission_mode)
662
+ : session.permissionMode;
663
+ const workItem = task ??
664
+ options.workItems.createWorkItem({
665
+ title: deriveTitle(body.message),
666
+ mode: "auto",
667
+ conversationId: `conv_${session.id.slice("sess_".length)}`,
668
+ agentId: session.agentId,
669
+ workflowId: null,
670
+ workflowRevision: null,
671
+ workspaceScope: session.cwd ? [session.cwd] : [],
672
+ riskLevel: "read_only",
673
+ });
674
+ let attachments;
675
+ try {
676
+ attachments = attachmentInput.map((attachment) => options.workItems.createMessageAttachment({
677
+ workItemId: workItem.id,
678
+ name: attachment.name,
679
+ mimeType: attachment.mimeType,
680
+ dataBase64: attachment.dataBase64,
681
+ }));
682
+ }
683
+ catch (error) {
684
+ return c.json({ error: "invalid_attachments", detail: error instanceof Error ? error.message : String(error) }, 400);
685
+ }
686
+ const event = options.workItems.appendEvent({
687
+ workItemId: workItem.id,
688
+ type: "MESSAGE_RECEIVED",
689
+ actor: "user",
690
+ payload: { message: body.message, attachment_ids: attachments.map((attachment) => attachment.id) },
691
+ });
692
+ options.catalog.updateSession(session.id, {
693
+ taskRecordId: workItem.id,
694
+ model,
695
+ effort,
696
+ permissionMode,
697
+ title: session.title ?? deriveTitle(body.message),
698
+ status: "active",
699
+ });
700
+ if (!task && options.discovery && session.cwd) {
701
+ void options.discovery.observe(session.cwd, workItem.id).catch((error) => {
702
+ options.workItems.appendEvent({
703
+ workItemId: workItem.id,
704
+ type: "AGENT_EVENT",
705
+ actor: "system",
706
+ payload: {
707
+ kind: "discovery_failed",
708
+ message: error instanceof Error ? error.message : String(error),
709
+ },
710
+ });
711
+ });
712
+ }
713
+ const response = {
714
+ request_id: `req_${randomUUID().replaceAll("-", "")}`,
715
+ accepted: true,
716
+ session_id: session.id,
717
+ task_record_id: workItem.id,
718
+ event_id: event.eventId,
719
+ sequence: event.sequence,
720
+ attachment_ids: attachments.map((attachment) => attachment.id),
721
+ };
722
+ if (idempotencyKey)
723
+ options.workItems.putIdempotencyResponse(`session:message:${session.id}`, idempotencyKey, response);
724
+ return c.json(response, 202);
725
+ });
726
+ app.get("/v1/sessions/:session_id/runs", (c) => {
727
+ const session = options.catalog.getSession(c.req.param("session_id"));
728
+ if (!session)
729
+ return c.json({ error: "session_not_found" }, 404);
730
+ if (!session.taskRecordId)
731
+ return c.json({ runs: [] });
732
+ return c.json({ runs: options.workItems.listRuns(session.taskRecordId).map((run) => toApiRun(run, session.id)) });
733
+ });
734
+ app.post("/v1/sessions/:session_id/cancel", async (c) => {
735
+ const session = options.catalog.getSession(c.req.param("session_id"));
736
+ if (!session)
737
+ return c.json({ error: "session_not_found" }, 404);
738
+ if (!session.taskRecordId)
739
+ return c.json({ stopped: false });
740
+ const run = options.workItems.listRuns(session.taskRecordId).reverse().find((candidate) => ["queued", "running", "waiting"].includes(candidate.status));
741
+ if (!run)
742
+ return c.json({ stopped: false });
743
+ if (options.executor)
744
+ await options.executor.cancelRunAndWait(run.id);
745
+ else {
746
+ options.workItems.updateRunStatus(run.id, "cancelled");
747
+ options.workItems.appendEvent({
748
+ workItemId: run.workItemId,
749
+ runId: run.id,
750
+ type: "RUN_CANCELLED",
751
+ actor: "user",
752
+ target: run.id,
753
+ });
754
+ }
755
+ return c.json({ stopped: true, run_id: run.id });
756
+ });
757
+ app.post("/v1/sessions/:session_id/runs", async (c) => {
758
+ const session = options.catalog.getSession(c.req.param("session_id"));
759
+ if (!session)
760
+ return c.json({ error: "session_not_found" }, 404);
761
+ const body = await readJson(c);
762
+ const task = session.taskRecordId ? options.workItems.getWorkItem(session.taskRecordId) : undefined;
763
+ if (!task)
764
+ return c.json({ error: "message_required", message: "先向 Session 发送消息" }, 409);
765
+ const idempotencyKey = c.req.header("idempotency-key");
766
+ if (idempotencyKey) {
767
+ const cached = options.workItems.getIdempotencyResponse(`session:run:${session.id}`, idempotencyKey);
768
+ if (cached !== undefined)
769
+ return c.json(cached, 202);
770
+ }
771
+ const model = body && Object.hasOwn(body, "model") ? asNullableString(body.model) : session.model;
772
+ const effort = body && Object.hasOwn(body, "effort") ? asNullableString(body.effort) : session.effort;
773
+ const permissionMode = body && Object.hasOwn(body, "permission_mode")
774
+ ? asNullableString(body.permission_mode)
775
+ : session.permissionMode;
776
+ options.catalog.updateSession(session.id, { model, effort, permissionMode });
777
+ const runId = `run_${randomUUID().replaceAll("-", "")}`;
778
+ const run = options.workItems.createRun({
779
+ id: runId,
780
+ workItemId: task.id,
781
+ mode: "auto",
782
+ executionKind: "agent",
783
+ agentId: session.agentId,
784
+ planId: null,
785
+ planIrHash: null,
786
+ workflowRevision: null,
787
+ });
788
+ if (options.executor)
789
+ void options.executor.execute(run.id).catch(() => { });
790
+ const response = {
791
+ run_id: run.id,
792
+ status: run.status,
793
+ plan_id: run.planId,
794
+ workflow_revision: run.workflowRevision,
795
+ };
796
+ if (idempotencyKey)
797
+ options.workItems.putIdempotencyResponse(`session:run:${session.id}`, idempotencyKey, response);
798
+ return c.json(response, 202);
799
+ });
800
+ app.post("/v1/sessions/:session_id/resume", (c) => {
801
+ const session = options.catalog.getSession(c.req.param("session_id"));
802
+ if (!session)
803
+ return c.json({ error: "session_not_found" }, 404);
804
+ if (!session.providerSessionId)
805
+ return c.json({ error: "provider_session_not_bound" }, 409);
806
+ return c.json(toApiSession(options.catalog.updateSession(session.id, { status: "active" })));
807
+ });
808
+ app.post("/v1/sessions/:session_id/fork", async (c) => {
809
+ const session = options.catalog.getSession(c.req.param("session_id"));
810
+ if (!session)
811
+ return c.json({ error: "session_not_found" }, 404);
812
+ if (!options.runner)
813
+ return c.json({ error: "runner_unavailable" }, 503);
814
+ if (!session.providerSessionId || !session.cwd) {
815
+ return c.json({ error: "provider_session_not_bound" }, 409);
816
+ }
817
+ const body = await readJson(c);
818
+ const targetCwd = asNullableString(body?.target_cwd) ?? session.cwd;
819
+ const result = await options.runner.forkSession(session.agentId, session.cwd, session.providerSessionId, targetCwd);
820
+ if (!result.ok || !result.sessionId)
821
+ return c.json(result, 409);
822
+ const forked = options.catalog.createSession({
823
+ agentId: session.agentId,
824
+ providerSessionId: result.sessionId,
825
+ model: asNullableString(body?.model) ?? session.model,
826
+ effort: asNullableString(body?.effort) ?? session.effort,
827
+ configOverrides: session.configOverrides,
828
+ permissionMode: asNullableString(body?.permission_mode) ?? session.permissionMode,
829
+ folderId: session.folderId,
830
+ cwd: result.cwd ?? targetCwd,
831
+ additionalDirectories: session.additionalDirectories,
832
+ title: asNullableString(body?.title) ?? session.title,
833
+ });
834
+ return c.json(toApiSession(forked), 201);
835
+ });
836
+ app.post("/v1/directories/authorize", async (c) => {
837
+ if (!options.runner)
838
+ return c.json({ ok: false, error: "runner_unavailable" }, 503);
839
+ const body = await readJson(c);
840
+ if (!body || typeof body.path !== "string" || !body.path.trim())
841
+ return c.json({ ok: false, error: "path is required" }, 400);
842
+ const result = await options.runner.authorizeDirectory(body.path);
843
+ return c.json(result, result.ok ? 200 : 403);
844
+ });
845
+ app.post("/v1/sessions/:session_id/close", async (c) => {
846
+ const session = options.catalog.getSession(c.req.param("session_id"));
847
+ if (!session)
848
+ return c.json({ error: "session_not_found" }, 404);
849
+ if (options.runner && session.providerSessionId && session.cwd) {
850
+ const result = await options.runner.closeSession(session.agentId, session.cwd, session.providerSessionId);
851
+ if (!result.ok)
852
+ return c.json(result, 409);
853
+ }
854
+ return c.json(toApiSession(options.catalog.updateSession(session.id, { status: "closed" })));
855
+ });
856
+ app.delete("/v1/sessions/:session_id", async (c) => {
857
+ const session = options.catalog.getSession(c.req.param("session_id"));
858
+ if (!session)
859
+ return c.json({ error: "session_not_found" }, 404);
860
+ if (options.runner && session.providerSessionId && session.cwd) {
861
+ const result = await options.runner.deleteSession(session.agentId, session.cwd, session.providerSessionId);
862
+ if (!result.ok)
863
+ return c.json(result, 409);
864
+ }
865
+ if (!options.catalog.deleteSession(session.id))
866
+ return c.json({ error: "session_not_found" }, 404);
867
+ return c.body(null, 204);
868
+ });
869
+ app.get("/v1/deliveries", (c) => {
870
+ const channel = c.req.query("channel");
871
+ if (!channel)
872
+ return c.json({ error: "channel_required" }, 400);
873
+ return c.json({
874
+ deliveries: options.workItems.listDeliveries(channel, c.req.query("surface_message_id")),
875
+ });
876
+ });
877
+ app.post("/v1/deliveries/:turn_id/claim", async (c) => {
878
+ const body = await readJson(c);
879
+ const owner = typeof body?.owner === "string" && body.owner
880
+ ? body.owner
881
+ : null;
882
+ if (!owner)
883
+ return c.json({ error: "owner_required" }, 400);
884
+ const now = new Date();
885
+ const claimed = options.workItems.withSessionTransaction((tx) => tx.claimDelivery(c.req.param("turn_id"), owner, now.toISOString(), new Date(now.getTime() + 60_000).toISOString()));
886
+ return c.json({ claimed });
887
+ });
888
+ app.post("/v1/deliveries/:turn_id/ack", async (c) => {
889
+ const body = await readJson(c);
890
+ const owner = typeof body?.owner === "string" && body.owner
891
+ ? body.owner
892
+ : null;
893
+ const surfaceMessageId = typeof body?.surface_message_id === "string"
894
+ ? body.surface_message_id
895
+ : null;
896
+ const surfaceCardId = typeof body?.surface_card_id === "string"
897
+ ? body.surface_card_id
898
+ : undefined;
899
+ if (!owner || !surfaceMessageId) {
900
+ return c.json({ error: "owner_and_surface_message_id_required" }, 400);
901
+ }
902
+ const acked = options.workItems.withSessionTransaction((tx) => tx.ackDelivery(c.req.param("turn_id"), owner, surfaceMessageId, surfaceCardId));
903
+ return c.json({ acked });
904
+ });
905
+ app.post("/v1/deliveries/:turn_id/complete", async (c) => {
906
+ const body = await readJson(c);
907
+ const owner = typeof body?.owner === "string" && body.owner
908
+ ? body.owner
909
+ : null;
910
+ if (!owner)
911
+ return c.json({ error: "owner_required" }, 400);
912
+ const completed = options.workItems.withSessionTransaction((tx) => tx.completeDelivery(c.req.param("turn_id"), owner));
913
+ return c.json({ completed });
914
+ });
915
+ app.post("/v1/sessions/:session_id/approval", async (c) => {
916
+ if (!options.approvals) {
917
+ return c.json({ resolved: false, error: "approval_unavailable" }, 503);
918
+ }
919
+ const session = options.catalog.getSession(c.req.param("session_id"));
920
+ if (!session?.taskRecordId)
921
+ return c.json({ resolved: false });
922
+ const body = await readJson(c);
923
+ const runId = typeof body?.run_id === "string" ? body.run_id : undefined;
924
+ const approvalId = typeof body?.approval_id === "string"
925
+ ? body.approval_id
926
+ : undefined;
927
+ if (!runId || !approvalId) {
928
+ return c.json({ error: "run_id_and_approval_id_required" }, 400);
929
+ }
930
+ const runs = options.workItems.listRuns(session.taskRecordId);
931
+ const run = runs.find((candidate) => candidate.id === runId);
932
+ if (!run)
933
+ return c.json({ resolved: false });
934
+ const pending = options.approvals
935
+ .listForRun(run.id)
936
+ .find((approval) => approval.status === "requested"
937
+ && approval.id === approvalId);
938
+ if (!pending)
939
+ return c.json({ resolved: false });
940
+ const approve = body?.approve === true;
941
+ const record = approve
942
+ ? options.approvals.grant(pending.id, "channel")
943
+ : options.approvals.revoke(pending.id, "channel");
944
+ if (!record
945
+ || (approve ? record.status !== "granted" : record.status !== "revoked")) {
946
+ return c.json({ resolved: false });
947
+ }
948
+ if (approve) {
949
+ options.workItems.requeueRun(run.id);
950
+ if (options.executor)
951
+ void options.executor.execute(run.id).catch(() => { });
952
+ }
953
+ else if (options.executor) {
954
+ options.executor.cancelRun(run.id);
955
+ }
956
+ else {
957
+ options.workItems.updateRunStatus(run.id, "cancelled");
958
+ options.workItems.appendEvent({
959
+ workItemId: run.workItemId,
960
+ runId: run.id,
961
+ type: "RUN_CANCELLED",
962
+ actor: "channel",
963
+ target: run.id,
964
+ payload: { approval_id: record.id, reason: "approval_rejected" },
965
+ });
966
+ }
967
+ return c.json({ resolved: true, approval_id: record.id });
968
+ });
969
+ app.post("/v1/channels/:channel/conversations/:conversation_id/reset", async (c) => {
970
+ const body = await readJson(c);
971
+ const rawAgentId = body?.agent_id;
972
+ const rawWorkspaceKey = body?.workspace_key;
973
+ const rawGeneration = body?.generation;
974
+ if (typeof rawAgentId !== "string"
975
+ || typeof rawWorkspaceKey !== "string"
976
+ || !Number.isSafeInteger(rawGeneration)) {
977
+ return c.json({ reset: false });
978
+ }
979
+ return c.json({
980
+ reset: options.catalog.unbindChannelConversation({
981
+ channel: c.req.param("channel"),
982
+ conversationId: c.req.param("conversation_id"),
983
+ agentId: rawAgentId,
984
+ workspaceKey: rawWorkspaceKey,
985
+ generation: Number(rawGeneration),
986
+ }),
987
+ });
988
+ });
989
+ // D6:/resume —— 幂等先于建 Session,Lease 预检(UX)后原子建+绑。
990
+ // 真 Claim 由 executor 在 Run 前执行;此处 busy 只读预检,不影响旧 Run。
991
+ app.post("/v1/channels/:channel/conversations/:conversation_id/resume", async (c) => {
992
+ const body = await readJson(c);
993
+ if (!body
994
+ || typeof body.provider_session_id !== "string"
995
+ || !body.provider_session_id.trim()) {
996
+ return c.json({ error: "provider_session_id is required" }, 400);
997
+ }
998
+ const channel = c.req.param("channel");
999
+ const conversationId = c.req.param("conversation_id");
1000
+ // 禁止 fallback:agent 必须显式存在且健康,否则 lease 键 (agent_id, provider_session_id)
1001
+ // 会用错 agent,导致跨 agent 开同一 ACP session。
1002
+ const agent = typeof body.agent_id === "string"
1003
+ ? currentProfiles().get(body.agent_id)
1004
+ : undefined;
1005
+ if (!agent) {
1006
+ return c.json({ error: "agent_id must reference a registered Agent" }, 400);
1007
+ }
1008
+ if (agent.status !== "healthy") {
1009
+ return c.json({ error: "agent_unavailable", status: agent.status }, 409);
1010
+ }
1011
+ const generation = Number.isSafeInteger(body.generation)
1012
+ ? Number(body.generation)
1013
+ : 0;
1014
+ const slot = {
1015
+ channel,
1016
+ conversationId,
1017
+ agentId: agent.agentId,
1018
+ workspaceKey: typeof body.workspace_key === "string" && body.workspace_key
1019
+ ? body.workspace_key
1020
+ : canonicalWorkspaceKey(options.defaultCwd ?? "").key,
1021
+ generation,
1022
+ };
1023
+ const providerSessionId = body.provider_session_id;
1024
+ // 幂等:槽位已绑同 provider session → 直接返回,不重复建 Session。
1025
+ const bound = options.catalog.getChannelSession(slot);
1026
+ if (bound?.providerSessionId === providerSessionId) {
1027
+ return c.json({ session_id: bound.id });
1028
+ }
1029
+ // Lease 预检(UX,只读):provider session 正被其他 run 持有 → busy。
1030
+ const liveLease = options.workItems.findLiveProviderLease(agent.agentId, providerSessionId, new Date().toISOString());
1031
+ if (liveLease) {
1032
+ return c.json({
1033
+ error: "provider_session_busy",
1034
+ detail: `provider session ${providerSessionId} 正被 run ${liveLease.runId} 使用`,
1035
+ }, 409);
1036
+ }
1037
+ try {
1038
+ const session = options.catalog.createAndBindHistoricalSession(slot, providerSessionId);
1039
+ return c.json({ session_id: session.id });
1040
+ }
1041
+ catch (error) {
1042
+ if (error instanceof Error && error.message === "slot_already_bound") {
1043
+ return c.json({ error: "slot_already_bound" }, 409);
1044
+ }
1045
+ throw error;
1046
+ }
1047
+ });
1048
+ app.post("/v1/channels/command-context", async (c) => {
1049
+ const body = await readJson(c);
1050
+ const slot = parseChannelSlot(body?.slot);
1051
+ if (!slot)
1052
+ return c.json({ error: "invalid_slot" }, 400);
1053
+ const session = options.catalog.getChannelSession(slot);
1054
+ if (!session) {
1055
+ return c.json({
1056
+ session_id: null,
1057
+ active_run_id: null,
1058
+ provider_session_id: null,
1059
+ });
1060
+ }
1061
+ const runtime = options.workItems.getSessionRuntime(session.id);
1062
+ const usage = options.workItems.getContextUsage(session.id);
1063
+ // The catalog row is bumped at submit/run start; runtime is bumped by every event, incl. run end.
1064
+ const lastActivityAt = [session.updatedAt, runtime?.updatedAt]
1065
+ .filter((value) => Boolean(value))
1066
+ .sort()
1067
+ .at(-1) ?? null;
1068
+ return c.json({
1069
+ session_id: session.id,
1070
+ active_run_id: runtime?.activeRunId ?? null,
1071
+ provider_session_id: session.providerSessionId,
1072
+ last_activity_at: lastActivityAt,
1073
+ context_used: usage?.latest.used ?? null,
1074
+ context_size: usage?.latest.size ?? null,
1075
+ context_first_used: usage?.first.used ?? null,
1076
+ queued_turns: options.workItems.listQueuedTurns(session.id, { limit: 1 }).total,
1077
+ });
1078
+ });
1079
+ app.post("/v1/runs/:run_id/permission", async (c) => {
1080
+ if (!options.runner) {
1081
+ return c.json({ resolved: false, error: "runner_unavailable" }, 503);
1082
+ }
1083
+ const body = await readJson(c);
1084
+ if (typeof body?.approve !== "boolean") {
1085
+ return c.json({ error: "approve (boolean) is required" }, 400);
1086
+ }
1087
+ const resolved = await options.runner.resolvePermission(c.req.param("run_id"), body.approve);
1088
+ return c.json({ resolved });
1089
+ });
1090
+ app.post("/v1/runs/:run_id/steer", async (c) => {
1091
+ if (!options.runner) {
1092
+ return c.json({ ok: false, error: "runner_unavailable" }, 503);
1093
+ }
1094
+ const body = await readJson(c);
1095
+ if (typeof body?.prompt !== "string" || !body.prompt.trim()) {
1096
+ return c.json({ ok: false, error: "prompt is required" }, 400);
1097
+ }
1098
+ // 按 runId 直接打 Runner,不依赖 orchestrator 的 activeChatRuns。
1099
+ return c.json(await options.runner.steer(c.req.param("run_id"), body.prompt));
1100
+ });
1101
+ return app;
1102
+ }
1103
+ function providerHistoryError(c, error) {
1104
+ const code = error instanceof Error ? error.message : String(error);
1105
+ if (code === "session_not_found") {
1106
+ return c.json({ error: code }, 404);
1107
+ }
1108
+ if (code === "provider_session_not_bound"
1109
+ || code === "provider_history_prefix_changed"
1110
+ || code === "provider_history_cursor_conflict") {
1111
+ return c.json({ error: code }, 409);
1112
+ }
1113
+ return c.json({ error: "provider_history_unavailable" }, 502);
1114
+ }
1115
+ async function syncProviderSessions(options, profiles, agentId, cwd) {
1116
+ if (!options.runner)
1117
+ return { errors: [] };
1118
+ const ids = agentId ? [agentId] : [...profiles.keys()];
1119
+ const errors = [];
1120
+ for (const id of ids) {
1121
+ const profile = profiles.get(id);
1122
+ if (!profile || profile.status !== "healthy")
1123
+ continue;
1124
+ try {
1125
+ const result = await options.runner.listSessions(id, cwd, { all: true, limit: 100 });
1126
+ for (const provider of result.sessions) {
1127
+ const existing = options.catalog.getByProviderSession(id, provider.id);
1128
+ const session = existing ?? options.catalog.createSession({
1129
+ agentId: id,
1130
+ providerSessionId: provider.id,
1131
+ cwd: provider.cwd,
1132
+ additionalDirectories: provider.additionalDirectories,
1133
+ title: provider.preview || null,
1134
+ updatedAt: provider.updatedAt,
1135
+ });
1136
+ options.catalog.updateSession(session.id, {
1137
+ providerSessionId: provider.id,
1138
+ cwd: provider.cwd,
1139
+ additionalDirectories: provider.additionalDirectories,
1140
+ title: provider.preview || session.title,
1141
+ status: "idle",
1142
+ updatedAt: provider.updatedAt,
1143
+ });
1144
+ }
1145
+ if (result.error)
1146
+ errors.push(result.error);
1147
+ }
1148
+ catch (error) {
1149
+ errors.push(error instanceof Error ? error.message : String(error));
1150
+ }
1151
+ }
1152
+ return { errors };
1153
+ }
1154
+ function resolveEffectiveDefaultAgentId(agents, defaultAgentId) {
1155
+ if (defaultAgentId) {
1156
+ const saved = agents.find((agent) => agent.agentId === defaultAgentId && agent.setup?.canSelectDefault);
1157
+ if (saved)
1158
+ return saved.agentId;
1159
+ }
1160
+ return agents.find((agent) => agent.setup?.canSelectDefault)?.agentId ?? null;
1161
+ }
1162
+ function mergeAgentSetup(agent, setup) {
1163
+ const nextSetup = projectSetupState(setup);
1164
+ return {
1165
+ ...agent,
1166
+ status: projectAgentStatus(nextSetup),
1167
+ setup: nextSetup,
1168
+ setupManifest: cloneSetupManifest(agent.setupManifest),
1169
+ capabilities: [...agent.capabilities],
1170
+ models: [...agent.models],
1171
+ sessionFeatures: [...agent.sessionFeatures],
1172
+ };
1173
+ }
1174
+ function formatAgentSetupError(error, agent) {
1175
+ const message = error instanceof Error ? error.message : String(error);
1176
+ const details = error && typeof error === "object" && "details" in error && typeof error.details === "string"
1177
+ ? error.details
1178
+ : undefined;
1179
+ const code = error && typeof error === "object" && "code" in error && typeof error.code === "string"
1180
+ ? error.code
1181
+ : "agent_setup_failed";
1182
+ return {
1183
+ error: code,
1184
+ message,
1185
+ details,
1186
+ ...(agent ? { agent: toApiAgent(agent) } : {}),
1187
+ };
1188
+ }
1189
+ function errorStatus(error, fallback) {
1190
+ if (error && typeof error === "object" && "status" in error && typeof error.status === "number") {
1191
+ return error.status;
1192
+ }
1193
+ return fallback;
1194
+ }
1195
+ function toApiAgent(agent) {
1196
+ return {
1197
+ agent_id: agent.agentId,
1198
+ display_name: agent.displayName,
1199
+ adapter: agent.adapter,
1200
+ status: agent.status,
1201
+ capabilities: agent.capabilities,
1202
+ models: agent.models,
1203
+ session_features: agent.sessionFeatures,
1204
+ setup: agent.setup ? {
1205
+ installation: agent.setup.installation,
1206
+ configuration: agent.setup.configuration,
1207
+ runtime: agent.setup.runtime,
1208
+ version: agent.setup.version,
1209
+ executable_path: agent.setup.executablePath,
1210
+ diagnostic: agent.setup.diagnostic ? {
1211
+ stage: agent.setup.diagnostic.stage,
1212
+ code: agent.setup.diagnostic.code,
1213
+ message: agent.setup.diagnostic.message,
1214
+ details: agent.setup.diagnostic.details,
1215
+ exit_code: agent.setup.diagnostic.exitCode,
1216
+ } : undefined,
1217
+ can_select_default: agent.setup.canSelectDefault,
1218
+ can_create_session: agent.setup.canCreateSession,
1219
+ } : undefined,
1220
+ setup_manifest: agent.setupManifest ? {
1221
+ agent_id: agent.setupManifest.agentId,
1222
+ display_name: agent.setupManifest.displayName,
1223
+ adapter: agent.setupManifest.adapter,
1224
+ install_strategies: agent.setupManifest.installStrategies.map((strategy) => ({
1225
+ id: strategy.id,
1226
+ label: strategy.label,
1227
+ command: strategy.command,
1228
+ args: [...strategy.args],
1229
+ available: strategy.available,
1230
+ requires_confirmation: strategy.requiresConfirmation,
1231
+ })),
1232
+ configuration_owner: agent.setupManifest.configurationOwner,
1233
+ configuration_path: agent.setupManifest.configurationPath,
1234
+ documentation_url: agent.setupManifest.documentationUrl,
1235
+ supports_managed_configuration: agent.setupManifest.supportsManagedConfiguration,
1236
+ } : undefined,
1237
+ };
1238
+ }
1239
+ function toApiSession(session) {
1240
+ if (!session)
1241
+ throw new Error("session is required");
1242
+ return {
1243
+ schema_version: session.schemaVersion,
1244
+ session_id: session.id,
1245
+ agent_id: session.agentId,
1246
+ provider_session_id: session.providerSessionId,
1247
+ task_record_id: session.taskRecordId,
1248
+ model: session.model,
1249
+ effort: session.effort,
1250
+ config_overrides: session.configOverrides,
1251
+ permission_mode: session.permissionMode,
1252
+ folder_id: session.folderId,
1253
+ cwd: session.cwd,
1254
+ additional_directories: session.additionalDirectories,
1255
+ title: session.title,
1256
+ status: session.status,
1257
+ pinned_at: session.pinnedAt,
1258
+ archived_at: session.archivedAt,
1259
+ created_at: session.createdAt,
1260
+ updated_at: session.updatedAt,
1261
+ };
1262
+ }
1263
+ function toApiRun(run, sessionId) {
1264
+ if (!run)
1265
+ throw new Error("run is required");
1266
+ return {
1267
+ schema_version: run.schemaVersion,
1268
+ run_id: run.id,
1269
+ session_id: sessionId,
1270
+ work_item_id: run.workItemId,
1271
+ agent_id: run.agentId,
1272
+ plan_id: run.planId,
1273
+ workflow_revision: run.workflowRevision,
1274
+ mode: run.mode,
1275
+ status: run.status,
1276
+ created_at: run.createdAt,
1277
+ updated_at: run.updatedAt,
1278
+ };
1279
+ }
1280
+ function toApiAttachment(attachment) {
1281
+ if (!attachment)
1282
+ throw new Error("attachment is required");
1283
+ return {
1284
+ schema_version: attachment.schemaVersion,
1285
+ id: attachment.id,
1286
+ work_item_id: attachment.workItemId,
1287
+ name: attachment.name,
1288
+ mime_type: attachment.mimeType,
1289
+ byte_size: attachment.byteSize,
1290
+ content_hash: attachment.contentHash,
1291
+ created_at: attachment.createdAt,
1292
+ };
1293
+ }
1294
+ async function readJson(c) {
1295
+ const body = await c.req.json().catch(() => null);
1296
+ return body && typeof body === "object" && !Array.isArray(body)
1297
+ ? body
1298
+ : null;
1299
+ }
1300
+ function channelInputRecord(value) {
1301
+ return value && typeof value === "object" && !Array.isArray(value)
1302
+ ? value
1303
+ : {};
1304
+ }
1305
+ function parseChannelSlot(value) {
1306
+ if (!value || typeof value !== "object")
1307
+ return undefined;
1308
+ const slot = value;
1309
+ if (typeof slot.channel !== "string"
1310
+ || typeof slot.conversation_id !== "string"
1311
+ || typeof slot.agent_id !== "string"
1312
+ || typeof slot.workspace_key !== "string"
1313
+ || !Number.isSafeInteger(slot.generation)) {
1314
+ return undefined;
1315
+ }
1316
+ return {
1317
+ channel: slot.channel,
1318
+ conversationId: slot.conversation_id,
1319
+ agentId: slot.agent_id,
1320
+ workspaceKey: slot.workspace_key,
1321
+ generation: Number(slot.generation),
1322
+ };
1323
+ }
1324
+ function asNullableString(value) {
1325
+ return typeof value === "string" && value.trim() ? value : null;
1326
+ }
1327
+ function parseConfigOverrides(value) {
1328
+ if (!value || typeof value !== "object" || Array.isArray(value))
1329
+ return null;
1330
+ const overrides = {};
1331
+ for (const [key, candidate] of Object.entries(value)) {
1332
+ if (!key.trim())
1333
+ return null;
1334
+ if (typeof candidate === "boolean")
1335
+ overrides[key] = candidate;
1336
+ else if (typeof candidate === "string" && candidate.trim())
1337
+ overrides[key] = candidate;
1338
+ else
1339
+ return null;
1340
+ }
1341
+ return overrides;
1342
+ }
1343
+ function parseMessageAttachments(value) {
1344
+ if (value === undefined)
1345
+ return [];
1346
+ if (!Array.isArray(value) || value.length > 10)
1347
+ return null;
1348
+ let totalBytes = 0;
1349
+ const attachments = [];
1350
+ for (const item of value) {
1351
+ if (!item || typeof item !== "object" || Array.isArray(item))
1352
+ return null;
1353
+ const record = item;
1354
+ if (typeof record.name !== "string" || !record.name.trim() || typeof record.data_base64 !== "string")
1355
+ return null;
1356
+ if (record.mime_type !== undefined && typeof record.mime_type !== "string")
1357
+ return null;
1358
+ if (!/^[A-Za-z0-9+/]*={0,2}$/.test(record.data_base64) || record.data_base64.length % 4 === 1)
1359
+ return null;
1360
+ const byteSize = Buffer.byteLength(record.data_base64, "base64");
1361
+ if (byteSize === 0 || byteSize > 10_000_000)
1362
+ return null;
1363
+ totalBytes += byteSize;
1364
+ if (totalBytes > 25_000_000)
1365
+ return null;
1366
+ attachments.push({
1367
+ name: record.name,
1368
+ mimeType: typeof record.mime_type === "string" && record.mime_type ? record.mime_type : "application/octet-stream",
1369
+ dataBase64: record.data_base64,
1370
+ });
1371
+ }
1372
+ return attachments;
1373
+ }
1374
+ function deriveTitle(message) {
1375
+ const compact = message.replace(/\s+/g, " ").trim();
1376
+ return compact.length > 48 ? `${compact.slice(0, 47)}…` : compact;
1377
+ }
1378
+ //# sourceMappingURL=session-api.js.map