titan-agent 5.4.2 → 5.5.6

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 (302) hide show
  1. package/README.md +1 -1
  2. package/dist/agent/agent.js +9 -5
  3. package/dist/agent/agent.js.map +1 -1
  4. package/dist/agent/agentLoop.js +7 -3
  5. package/dist/agent/agentLoop.js.map +1 -1
  6. package/dist/agent/checkpoint.js +2 -2
  7. package/dist/agent/checkpoint.js.map +1 -1
  8. package/dist/agent/commandPost.js +3 -3
  9. package/dist/agent/commandPost.js.map +1 -1
  10. package/dist/agent/goalProposer.js +2 -2
  11. package/dist/agent/goalProposer.js.map +1 -1
  12. package/dist/agent/goals.js +3 -3
  13. package/dist/agent/goals.js.map +1 -1
  14. package/dist/agent/peerAdvise.js +1 -1
  15. package/dist/agent/peerAdvise.js.map +1 -1
  16. package/dist/agent/planner.js +4 -4
  17. package/dist/agent/planner.js.map +1 -1
  18. package/dist/agent/userProfile.js +2 -2
  19. package/dist/agent/userProfile.js.map +1 -1
  20. package/dist/cli/doctor.js +33 -0
  21. package/dist/cli/doctor.js.map +1 -1
  22. package/dist/cli/onboard.js +4 -4
  23. package/dist/cli/onboard.js.map +1 -1
  24. package/dist/config/config.js +3 -3
  25. package/dist/config/config.js.map +1 -1
  26. package/dist/config/schema.js +8 -1
  27. package/dist/config/schema.js.map +1 -1
  28. package/dist/gateway/routes/adminRouter.js +500 -0
  29. package/dist/gateway/routes/adminRouter.js.map +1 -0
  30. package/dist/gateway/routes/agents.js +231 -0
  31. package/dist/gateway/routes/agents.js.map +1 -0
  32. package/dist/gateway/routes/agentsRouter.js +32 -0
  33. package/dist/gateway/routes/agentsRouter.js.map +1 -0
  34. package/dist/gateway/routes/checkpoints.js +41 -0
  35. package/dist/gateway/routes/checkpoints.js.map +1 -0
  36. package/dist/gateway/routes/commandPost.js +755 -0
  37. package/dist/gateway/routes/commandPost.js.map +1 -0
  38. package/dist/gateway/routes/companies.js +166 -0
  39. package/dist/gateway/routes/companies.js.map +1 -0
  40. package/dist/gateway/routes/files.js +295 -0
  41. package/dist/gateway/routes/files.js.map +1 -0
  42. package/dist/gateway/routes/hardwareRouter.js +151 -0
  43. package/dist/gateway/routes/hardwareRouter.js.map +1 -0
  44. package/dist/gateway/routes/mcpRouter.js +88 -0
  45. package/dist/gateway/routes/mcpRouter.js.map +1 -0
  46. package/dist/gateway/routes/mesh.js +464 -0
  47. package/dist/gateway/routes/mesh.js.map +1 -0
  48. package/dist/gateway/routes/metricsRouter.js +131 -0
  49. package/dist/gateway/routes/metricsRouter.js.map +1 -0
  50. package/dist/gateway/routes/organism.js +82 -0
  51. package/dist/gateway/routes/organism.js.map +1 -0
  52. package/dist/gateway/routes/paperclip.js +101 -0
  53. package/dist/gateway/routes/paperclip.js.map +1 -0
  54. package/dist/gateway/routes/sessions.js +227 -0
  55. package/dist/gateway/routes/sessions.js.map +1 -0
  56. package/dist/gateway/routes/skills.js +295 -0
  57. package/dist/gateway/routes/skills.js.map +1 -0
  58. package/dist/gateway/routes/socialRouter.js +145 -0
  59. package/dist/gateway/routes/socialRouter.js.map +1 -0
  60. package/dist/gateway/routes/systemRouter.js +220 -0
  61. package/dist/gateway/routes/systemRouter.js.map +1 -0
  62. package/dist/gateway/routes/teamsRecipes.js +297 -0
  63. package/dist/gateway/routes/teamsRecipes.js.map +1 -0
  64. package/dist/gateway/routes/tests.js +401 -0
  65. package/dist/gateway/routes/tests.js.map +1 -0
  66. package/dist/gateway/routes/traces.js +33 -0
  67. package/dist/gateway/routes/traces.js.map +1 -0
  68. package/dist/gateway/routes/voiceRouter.js +770 -0
  69. package/dist/gateway/routes/voiceRouter.js.map +1 -0
  70. package/dist/gateway/routes/watchRouter.js +131 -0
  71. package/dist/gateway/routes/watchRouter.js.map +1 -0
  72. package/dist/gateway/server.js +1179 -7379
  73. package/dist/gateway/server.js.map +1 -1
  74. package/dist/mcp/registry.js +2 -2
  75. package/dist/mcp/registry.js.map +1 -1
  76. package/dist/memory/episodic.js +2 -2
  77. package/dist/memory/episodic.js.map +1 -1
  78. package/dist/memory/learning.js +3 -3
  79. package/dist/memory/learning.js.map +1 -1
  80. package/dist/memory/memory.js +3 -3
  81. package/dist/memory/memory.js.map +1 -1
  82. package/dist/organism/drives.js +2 -2
  83. package/dist/organism/drives.js.map +1 -1
  84. package/dist/providers/errorTaxonomy.js +13 -0
  85. package/dist/providers/errorTaxonomy.js.map +1 -1
  86. package/dist/providers/ollama.js +3 -1
  87. package/dist/providers/ollama.js.map +1 -1
  88. package/dist/providers/openai_compat.js +4 -3
  89. package/dist/providers/openai_compat.js.map +1 -1
  90. package/dist/providers/router.js +13 -0
  91. package/dist/providers/router.js.map +1 -1
  92. package/dist/safety/fixOscillation.js +15 -0
  93. package/dist/safety/fixOscillation.js.map +1 -1
  94. package/dist/safety/killSwitch.js +2 -2
  95. package/dist/safety/killSwitch.js.map +1 -1
  96. package/dist/safety/selfRepair.js +7 -3
  97. package/dist/safety/selfRepair.js.map +1 -1
  98. package/dist/skills/builtin/agent_debate.js +2 -2
  99. package/dist/skills/builtin/agent_debate.js.map +1 -1
  100. package/dist/skills/builtin/apply_patch.js +3 -3
  101. package/dist/skills/builtin/apply_patch.js.map +1 -1
  102. package/dist/skills/builtin/shell.js +2 -2
  103. package/dist/skills/builtin/shell.js.map +1 -1
  104. package/dist/skills/builtin/voice_control.js +49 -0
  105. package/dist/skills/builtin/voice_control.js.map +1 -0
  106. package/dist/skills/builtin/widget_gallery.js +6 -1
  107. package/dist/skills/builtin/widget_gallery.js.map +1 -1
  108. package/dist/skills/registry.js +15 -4
  109. package/dist/skills/registry.js.map +1 -1
  110. package/dist/storage/JsonStorage.js +4 -4
  111. package/dist/storage/JsonStorage.js.map +1 -1
  112. package/dist/utils/constants.js +1 -1
  113. package/dist/utils/constants.js.map +1 -1
  114. package/dist/utils/helpers.js +3 -1
  115. package/dist/utils/helpers.js.map +1 -1
  116. package/dist/utils/lifecycle.js +86 -0
  117. package/dist/utils/lifecycle.js.map +1 -0
  118. package/dist/voice/bridge.js +136 -0
  119. package/dist/voice/bridge.js.map +1 -0
  120. package/docs/COO-MASTER-PLAN-2026-05-02.md +474 -0
  121. package/docs/HANDOFF/2026-04-29.md +141 -0
  122. package/docs/HANDOFF-2026-04-30.md +144 -0
  123. package/docs/HANDOFF-2026-05-03.md +114 -0
  124. package/docs/adr/2026-04-29-widget-pipeline-traceability.md +49 -0
  125. package/docs/agent-memory/README.md +45 -0
  126. package/docs/agent-memory/commands.md +100 -0
  127. package/docs/agent-memory/context-tree.md +101 -0
  128. package/docs/agent-memory/current-state.md +54 -0
  129. package/docs/agent-memory/decisions.md +78 -0
  130. package/docs/agent-memory/known-issues.md +76 -0
  131. package/docs/agent-memory/reflections.md +52 -0
  132. package/docs/agent-memory/skills-candidates.md +80 -0
  133. package/docs/superpowers/plans/2026-04-29-comprehensive-audit.md +256 -0
  134. package/docs/superpowers/plans/2026-04-29-comprehensive-test-plan.md +396 -0
  135. package/docs/superpowers/plans/2026-04-29-fix-all-prs.md +251 -0
  136. package/docs/superpowers/plans/2026-04-29-gitnexus-gap-remediation.md +969 -0
  137. package/package.json +5 -2
  138. package/ui/dist/assets/{AuditPanel-CM6Wg9hO.js → AuditPanel-VzSndmDN.js} +2 -2
  139. package/ui/dist/assets/{AutonomyPanel-CESx3ANg.js → AutonomyPanel-BiFouzAV.js} +2 -2
  140. package/ui/dist/assets/AutopilotPanel-fjOfM668.js +1 -0
  141. package/ui/dist/assets/{AutoresearchPanel-DR47NqT5.js → AutoresearchPanel-CVCxzAH3.js} +2 -2
  142. package/ui/dist/assets/BackupPanel-CHVTG--q.js +1 -0
  143. package/ui/dist/assets/{BrowserPanel-C15x9bLn.js → BrowserPanel-D5mvMKFU.js} +2 -2
  144. package/ui/dist/assets/CPActivity-B12mt35m.js +1 -0
  145. package/ui/dist/assets/CPAgentDetail-DsdShc-1.js +1 -0
  146. package/ui/dist/assets/CPAgents-j_7C-oQV.js +1 -0
  147. package/ui/dist/assets/CPApprovals-BShKSX9X.js +1 -0
  148. package/ui/dist/assets/CPCosts-CKPlhBDs.js +1 -0
  149. package/ui/dist/assets/CPDashboard-11c0nkxK.js +1 -0
  150. package/ui/dist/assets/CPFiles-BhLEOnXy.js +1 -0
  151. package/ui/dist/assets/CPGoals-Bi3t1b2P.js +1 -0
  152. package/ui/dist/assets/CPInbox-Bbr7khp6.js +11 -0
  153. package/ui/dist/assets/CPIssueDetail-DSdgNK8r.js +1 -0
  154. package/ui/dist/assets/CPIssues-DDEVKhX6.js +1 -0
  155. package/ui/dist/assets/CPLayout-DgPOfyGv.js +17 -0
  156. package/ui/dist/assets/CPOrg-Df73RrRJ.js +8 -0
  157. package/ui/dist/assets/CPRuns-ByioAz8w.js +1 -0
  158. package/ui/dist/assets/{CPSocial-nb-j7sOE.js → CPSocial-Dlnr_w1X.js} +2 -2
  159. package/ui/dist/assets/ChannelsPanel-DQjQCTK5.js +1 -0
  160. package/ui/dist/assets/CheckpointsPanel-C4vKjlAJ.js +1 -0
  161. package/ui/dist/assets/CommandPostHub-C9pp5Giq.js +24 -0
  162. package/ui/dist/assets/CronPanel-C6bzUfrD.js +1 -0
  163. package/ui/dist/assets/DaemonPanel-BA5Tb_UO.js +1 -0
  164. package/ui/dist/assets/{DataTable-B2Ma8hfi.js → DataTable-CH7IYJJh.js} +1 -1
  165. package/ui/dist/assets/{EmptyState-CcKyk5Yn.js → EmptyState-jU6yNDnF.js} +1 -1
  166. package/ui/dist/assets/{EvalHarnessPanel-BqtMc1ZM.js → EvalHarnessPanel-DnYqredY.js} +2 -2
  167. package/ui/dist/assets/EvalPanel-ChO7CD1r.js +1 -0
  168. package/ui/dist/assets/{FilesPanel-3QKvrWPo.js → FilesPanel-CaUkv2is.js} +2 -2
  169. package/ui/dist/assets/FleetPanel-DC_5uj0N.js +1 -0
  170. package/ui/dist/assets/{HomelabPanel-DhrjTX9m.js → HomelabPanel-CE5PGRpL.js} +2 -2
  171. package/ui/dist/assets/InfraView-C-uSlvb9.js +2 -0
  172. package/ui/dist/assets/InlineEditableField-BMQjiE6-.js +1 -0
  173. package/ui/dist/assets/Input-Bu_b3qmY.js +1 -0
  174. package/ui/dist/assets/IntegrationsPanel-DsYpAq43.js +1 -0
  175. package/ui/dist/assets/IntelligenceView-DUdIO1K7.js +2 -0
  176. package/ui/dist/assets/LearningPanel-UpQZC-mA.js +1 -0
  177. package/ui/dist/assets/LogsPanel-ClXJ4fcr.js +1 -0
  178. package/ui/dist/assets/McpPanel-JKgtIERQ.js +1 -0
  179. package/ui/dist/assets/{MemoryGraphPanel-Bzvjmzvk.js → MemoryGraphPanel-Bo2OrvA6.js} +2 -2
  180. package/ui/dist/assets/MemoryWikiPanel-BqJ1AmYm.js +11 -0
  181. package/ui/dist/assets/{MeshPanel-C3LJSlht.js → MeshPanel-BJVGYvwk.js} +2 -2
  182. package/ui/dist/assets/Modal-CAAooiZU.js +1 -0
  183. package/ui/dist/assets/NvidiaPanel-BtCg3G4w.js +1 -0
  184. package/ui/dist/assets/OrganismPanel-DgrTTzcF.js +1 -0
  185. package/ui/dist/assets/OverviewPanel-rVav1Hox.js +1 -0
  186. package/ui/dist/assets/{PageHeader-BimceqQo.js → PageHeader-CnZtP8ek.js} +1 -1
  187. package/ui/dist/assets/PaperclipPanel-C-FKdhiF.js +1 -0
  188. package/ui/dist/assets/{PersonasPanel-L1j78p6H.js → PersonasPanel-BmlxokfB.js} +1 -1
  189. package/ui/dist/assets/RecipesPanel-BNKKChis.js +1 -0
  190. package/ui/dist/assets/SecurityPanel-I7JRHiNy.js +1 -0
  191. package/ui/dist/assets/SelfImprovePanel-u9h0Lt3p.js +1 -0
  192. package/ui/dist/assets/{SelfProposalsPanel-lNmiDThB.js → SelfProposalsPanel-DKl9iBjM.js} +2 -2
  193. package/ui/dist/assets/SessionsPanel-BhRiWI_g.js +1 -0
  194. package/ui/dist/assets/{SessionsTab-JQbltWww.js → SessionsTab-Bk08wyeY.js} +1 -1
  195. package/ui/dist/assets/SettingsPanel-haLfmG2k.js +1 -0
  196. package/ui/dist/assets/SettingsView--gi3fxI8.js +2 -0
  197. package/ui/dist/assets/{SkeletonLoader-atQtpcF5.js → SkeletonLoader-B5v09EF_.js} +1 -1
  198. package/ui/dist/assets/{SkillsPanel-DlFs2ih7.js → SkillsPanel-BlAHFLcQ.js} +1 -1
  199. package/ui/dist/assets/SomaView-CExtS3zw.js +5 -0
  200. package/ui/dist/assets/{StatCard-DciE_Iqc.js → StatCard-BIsyMybM.js} +1 -1
  201. package/ui/dist/assets/{StatusBadge-BtfSPoW2.js → StatusBadge-D5nU7El8.js} +1 -1
  202. package/ui/dist/assets/Tabs-BBYZrBI8.js +1 -0
  203. package/ui/dist/assets/TeamsPanel-LPXJg823.js +1 -0
  204. package/ui/dist/assets/TelemetryPanel-EqpRBmOI.js +1 -0
  205. package/ui/dist/assets/TitanCanvas-BCbWnLMd.js +985 -0
  206. package/ui/dist/assets/ToolsView-CeP0Zz-N.js +2 -0
  207. package/ui/dist/assets/{Tooltip-70UK0E2I.js → Tooltip-BSO2XVpF.js} +1 -1
  208. package/ui/dist/assets/TraceViewer-BKI7o5B0.js +1 -0
  209. package/ui/dist/assets/TrainingPanel-c-RhjdE1.js +1 -0
  210. package/ui/dist/assets/VoiceOverlay-D-gc58b0.js +27 -0
  211. package/ui/dist/assets/VramPanel-C6xc7zgd.js +1 -0
  212. package/ui/dist/assets/{WatchView-C-sGFpVy.js → WatchView-dqBVCVH0.js} +1 -1
  213. package/ui/dist/assets/WorkTab-CBoLNrTM.js +1 -0
  214. package/ui/dist/assets/{WorkflowsPanel-CvgQU1xI.js → WorkflowsPanel-BAnSTOYe.js} +2 -2
  215. package/ui/dist/assets/approvalHeadline-DB9SgR-9.js +1 -0
  216. package/ui/dist/assets/{arrow-left-DwqHtJiU.js → arrow-left-5chqas7J.js} +1 -1
  217. package/ui/dist/assets/briefcase-D4vLzudp.js +6 -0
  218. package/ui/dist/assets/{chart-column-BtNO6sRy.js → chart-column-CdFlBpoP.js} +1 -1
  219. package/ui/dist/assets/check-Bpm1IONe.js +6 -0
  220. package/ui/dist/assets/chevron-down-D7OLjvuD.js +6 -0
  221. package/ui/dist/assets/chevron-right-aQEw2mUW.js +6 -0
  222. package/ui/dist/assets/chevron-up-C5g6pEj8.js +6 -0
  223. package/ui/dist/assets/{circle-check-big-DZRE_MbN.js → circle-check-big-fPhEdP88.js} +1 -1
  224. package/ui/dist/assets/clock-CTsgP_Sn.js +6 -0
  225. package/ui/dist/assets/{dollar-sign-aVG3a5eL.js → dollar-sign-CudFVYFc.js} +1 -1
  226. package/ui/dist/assets/{download-BxiWJU4G.js → download-DZRxDn67.js} +1 -1
  227. package/ui/dist/assets/external-link-BZ0y_Ahx.js +6 -0
  228. package/ui/dist/assets/{eye-off-CkgfFYhm.js → eye-off-BmJF0YYx.js} +1 -1
  229. package/ui/dist/assets/folder-DA43TRCm.js +11 -0
  230. package/ui/dist/assets/{funnel-PkLdxKyC.js → funnel-J3mULzrz.js} +1 -1
  231. package/ui/dist/assets/{git-branch-BM-Gw95X.js → git-branch-oHibJqDq.js} +1 -1
  232. package/ui/dist/assets/{index-D0RJ8701.css → index-BR0vfkIi.css} +1 -1
  233. package/ui/dist/assets/{index-CahJbWSR.js → index-DzwowwSI.js} +20 -20
  234. package/ui/dist/assets/{layers-BuGf4FIJ.js → layers-DsyEyu7z.js} +1 -1
  235. package/ui/dist/assets/{legacy-CR6o4t-y.js → legacy-8ITl64sV.js} +1 -1
  236. package/ui/dist/assets/{lightbulb-n8gc_XAL.js → lightbulb-C54Ske-p.js} +1 -1
  237. package/ui/dist/assets/list-todo-Cnd4rdoK.js +6 -0
  238. package/ui/dist/assets/loader-circle-1YOBsoQp.js +6 -0
  239. package/ui/dist/assets/network-DbGDAdrn.js +6 -0
  240. package/ui/dist/assets/{pause-DCV52koX.js → pause-CYhO_uQo.js} +1 -1
  241. package/ui/dist/assets/{play-CcJ9BnCh.js → play-DVY9c5Ck.js} +1 -1
  242. package/ui/dist/assets/{plug-CfWBXfCl.js → plug-BcXjlPUL.js} +1 -1
  243. package/ui/dist/assets/plus-Csu2v9GN.js +6 -0
  244. package/ui/dist/assets/{proxy-CzZDfLmm.js → proxy-DxS2_9D7.js} +1 -1
  245. package/ui/dist/assets/rotate-ccw-Co-_W04j.js +6 -0
  246. package/ui/dist/assets/save-Btx-kpoW.js +6 -0
  247. package/ui/dist/assets/search-0hXTwEZR.js +6 -0
  248. package/ui/dist/assets/send-TEpapzQR.js +6 -0
  249. package/ui/dist/assets/shield-check-DjBJXZUr.js +6 -0
  250. package/ui/dist/assets/{square-DJpUhlxi.js → square-OweUvjP-.js} +1 -1
  251. package/ui/dist/assets/{target-DWcmM_9m.js → target-BRW80Xer.js} +1 -1
  252. package/ui/dist/assets/terminal-BtiqJ628.js +16 -0
  253. package/ui/dist/assets/{toggle-right-YusFQ69L.js → toggle-right-CKtSrl28.js} +1 -1
  254. package/ui/dist/assets/{trash-2-CK7yQ55V.js → trash-2-DgWrHVax.js} +1 -1
  255. package/ui/dist/assets/{trending-up-DGjFyubC.js → trending-up-MpIrE4j6.js} +1 -1
  256. package/ui/dist/assets/{trophy-uQv_NgDB.js → trophy-CECuZNhX.js} +1 -1
  257. package/ui/dist/assets/users-dZgv4ePG.js +16 -0
  258. package/ui/dist/assets/wrench-CDz3xYve.js +11 -0
  259. package/ui/dist/index.html +2 -2
  260. package/ui/dist/assets/AutopilotPanel-DtEet1hJ.js +0 -1
  261. package/ui/dist/assets/BackupPanel-BGP8p3l3.js +0 -1
  262. package/ui/dist/assets/CPAgents-DYUtPzSq.js +0 -1
  263. package/ui/dist/assets/CPDashboard-Bf0-SyCh.js +0 -6
  264. package/ui/dist/assets/CPFiles-CxgxjQcO.js +0 -1
  265. package/ui/dist/assets/CPGoals-BsmCMTvT.js +0 -1
  266. package/ui/dist/assets/CPInbox-tMSbmQ9H.js +0 -11
  267. package/ui/dist/assets/ChannelsPanel-DP5C2OKd.js +0 -1
  268. package/ui/dist/assets/CheckpointsPanel-DlranVLZ.js +0 -1
  269. package/ui/dist/assets/CommandPostHub-BgxIa4Ev.js +0 -29
  270. package/ui/dist/assets/CronPanel-LoT5yKwJ.js +0 -1
  271. package/ui/dist/assets/DaemonPanel-DBGMqaE_.js +0 -1
  272. package/ui/dist/assets/EvalPanel-Bc33j0pN.js +0 -1
  273. package/ui/dist/assets/FleetPanel-CSsXuQYj.js +0 -1
  274. package/ui/dist/assets/InfraView-CR6HyrL6.js +0 -2
  275. package/ui/dist/assets/InlineEditableField-CnvF-yFR.js +0 -1
  276. package/ui/dist/assets/Input-GTHp2Rkr.js +0 -1
  277. package/ui/dist/assets/IntegrationsPanel-CymCRE3T.js +0 -1
  278. package/ui/dist/assets/IntelligenceView-C1IHxJRC.js +0 -2
  279. package/ui/dist/assets/LearningPanel-DOCES3lH.js +0 -1
  280. package/ui/dist/assets/LogsPanel-BLnAqEaZ.js +0 -1
  281. package/ui/dist/assets/McpPanel-ChUzmr3z.js +0 -1
  282. package/ui/dist/assets/MemoryWikiPanel-Dwk3Aqwd.js +0 -11
  283. package/ui/dist/assets/NvidiaPanel-CeZK_-CV.js +0 -1
  284. package/ui/dist/assets/OrganismPanel-BB6YOiQV.js +0 -1
  285. package/ui/dist/assets/OverviewPanel-BmtBhQnv.js +0 -1
  286. package/ui/dist/assets/PaperclipPanel-C-brgwA3.js +0 -1
  287. package/ui/dist/assets/RecipesPanel-34lCfynJ.js +0 -1
  288. package/ui/dist/assets/SecurityPanel-CBTPWLj6.js +0 -1
  289. package/ui/dist/assets/SelfImprovePanel-BrPbFHhG.js +0 -1
  290. package/ui/dist/assets/SessionsPanel-DAEYIn83.js +0 -1
  291. package/ui/dist/assets/SettingsPanel-CzRROAYQ.js +0 -1
  292. package/ui/dist/assets/SettingsView-CN7ii2uw.js +0 -2
  293. package/ui/dist/assets/SomaView-Ba642Oqb.js +0 -5
  294. package/ui/dist/assets/TeamsPanel-DKQ5z2Qe.js +0 -1
  295. package/ui/dist/assets/TelemetryPanel-B6KAc55Q.js +0 -1
  296. package/ui/dist/assets/TitanCanvas-C-s0A-lv.js +0 -1092
  297. package/ui/dist/assets/ToolsView-Dei0KMP0.js +0 -2
  298. package/ui/dist/assets/TraceViewer-BniolyBx.js +0 -1
  299. package/ui/dist/assets/TrainingPanel-Bz4CTPGW.js +0 -1
  300. package/ui/dist/assets/VoiceOverlay-CmNCrLcd.js +0 -37
  301. package/ui/dist/assets/VramPanel-Xh_OtRDR.js +0 -1
  302. package/ui/dist/assets/WorkTab-BjLNmgIK.js +0 -1
@@ -0,0 +1,755 @@
1
+ #!/usr/bin/env node
2
+ import { Router } from "express";
3
+ import logger from "../../utils/logger.js";
4
+ import {
5
+ getDashboard as getCPDashboard,
6
+ getRegisteredAgents,
7
+ reportHeartbeat,
8
+ removeAgent,
9
+ checkoutTask,
10
+ checkinTask,
11
+ getActiveCheckouts,
12
+ getBudgetPolicies,
13
+ createBudgetPolicy,
14
+ updateBudgetPolicy,
15
+ deleteBudgetPolicy,
16
+ getActivity,
17
+ getGoalTree,
18
+ getAncestryChain,
19
+ validateGoalAncestry,
20
+ validateGoalParentAssignment,
21
+ sweepExpiredCheckoutsManual,
22
+ getStaleAgents,
23
+ enforceBudgetForAgent,
24
+ getBudgetPolicyForAgent,
25
+ createIssue,
26
+ updateIssue,
27
+ getIssue,
28
+ listIssues,
29
+ searchIssues,
30
+ checkoutIssue,
31
+ deleteIssue,
32
+ addIssueComment,
33
+ getIssueComments,
34
+ createApproval,
35
+ approveApproval,
36
+ rejectApproval,
37
+ listApprovals,
38
+ replyToApproval,
39
+ snoozeApproval,
40
+ unsnoozeApproval,
41
+ batchApprove,
42
+ batchReject,
43
+ getAgentMessages,
44
+ markAgentMessageRead,
45
+ startRun,
46
+ listRuns,
47
+ getOrgTree,
48
+ updateRegisteredAgent
49
+ } from "../../agent/commandPost.js";
50
+ import {
51
+ getAgentInbox,
52
+ queueWakeup,
53
+ getWakeupRequest,
54
+ cancelWakeup,
55
+ drainPendingResults
56
+ } from "../../agent/agentWakeup.js";
57
+ import { titanEvents } from "../../agent/daemon.js";
58
+ import { createGoal } from "../../agent/goals.js";
59
+ const COMPONENT = "CommandPostRouter";
60
+ function createCommandPostRouter() {
61
+ const router = Router();
62
+ router.get("/dashboard", async (_req, res) => {
63
+ const dashboard = getCPDashboard();
64
+ try {
65
+ const { listCompanies, getActiveRunners } = await import("../../agent/company.js");
66
+ const companies = listCompanies();
67
+ const runners = getActiveRunners();
68
+ dashboard.companies = companies.map((c) => ({
69
+ ...c,
70
+ runnerActive: runners.includes(c.id)
71
+ }));
72
+ } catch {
73
+ dashboard.companies = [];
74
+ }
75
+ res.json(dashboard);
76
+ });
77
+ router.get("/agents", (_req, res) => {
78
+ res.json(getRegisteredAgents());
79
+ });
80
+ router.post("/agents/:id/heartbeat", (req, res) => {
81
+ const ok = reportHeartbeat(req.params.id);
82
+ res.json({ success: ok });
83
+ });
84
+ router.post("/agents/:id/fire", async (req, res) => {
85
+ try {
86
+ const { fireHeartbeat } = await import("../../agent/heartbeatScheduler.js");
87
+ await fireHeartbeat(req.params.id);
88
+ res.json({ success: true });
89
+ } catch (err) {
90
+ res.status(500).json({ success: false, error: err.message });
91
+ }
92
+ });
93
+ router.delete("/agents/:id", (req, res) => {
94
+ const ok = removeAgent(req.params.id);
95
+ if (!ok) {
96
+ res.status(400).json({ error: "Cannot remove agent (not found or is the primary agent)" });
97
+ return;
98
+ }
99
+ res.json({ success: true });
100
+ });
101
+ router.patch("/agents/:id", async (req, res) => {
102
+ const { reportsTo, role, title, name, status, model } = req.body;
103
+ const updated = updateRegisteredAgent(req.params.id, { reportsTo, role, title, name, model });
104
+ if (!updated) {
105
+ res.status(404).json({ error: "Agent not found" });
106
+ return;
107
+ }
108
+ if (status && typeof status === "string") {
109
+ try {
110
+ const { updateAgentStatus } = await import("../../agent/commandPost.js");
111
+ updateAgentStatus(req.params.id, status);
112
+ } catch {
113
+ }
114
+ }
115
+ res.json(updated);
116
+ });
117
+ router.patch("/agents/:id/identity", async (req, res) => {
118
+ const { voiceId, personaId, systemPromptOverride, memoryNamespace, characterSummary, model } = req.body || {};
119
+ const coerce = (v) => {
120
+ if (v === null) return null;
121
+ if (typeof v === "string") return v;
122
+ if (v === void 0) return void 0;
123
+ res.status(400).json({ error: `Invalid identity field: expected string or null, got ${typeof v}` });
124
+ return void 0;
125
+ };
126
+ if (res.headersSent) return;
127
+ const { updateAgentIdentity } = await import("../../agent/commandPost.js");
128
+ const updated = updateAgentIdentity(req.params.id, {
129
+ voiceId: coerce(voiceId),
130
+ personaId: coerce(personaId),
131
+ systemPromptOverride: coerce(systemPromptOverride),
132
+ memoryNamespace: coerce(memoryNamespace),
133
+ characterSummary: coerce(characterSummary),
134
+ model: coerce(model)
135
+ });
136
+ if (res.headersSent) return;
137
+ if (!updated) {
138
+ res.status(404).json({ error: "Agent not found" });
139
+ return;
140
+ }
141
+ res.json(updated);
142
+ });
143
+ router.get("/agents/stale", (_req, res) => {
144
+ const stale = getStaleAgents();
145
+ res.json({ stale, total: stale.length });
146
+ });
147
+ router.post("/tasks/:goalId/:subtaskId/checkout", (req, res) => {
148
+ const agentId = req.body.agentId || "manual";
149
+ const lock = checkoutTask(req.params.goalId, req.params.subtaskId, agentId);
150
+ if (!lock) {
151
+ res.status(409).json({ error: "Task already checked out by another agent" });
152
+ return;
153
+ }
154
+ res.json(lock);
155
+ });
156
+ router.post("/tasks/:goalId/:subtaskId/checkin", (req, res) => {
157
+ const runId = req.body.runId || "";
158
+ const ok = checkinTask(req.params.subtaskId, runId);
159
+ if (!ok) {
160
+ res.status(404).json({ error: "No matching checkout found" });
161
+ return;
162
+ }
163
+ res.json({ success: true });
164
+ });
165
+ router.get("/checkouts", (_req, res) => {
166
+ res.json(getActiveCheckouts());
167
+ });
168
+ router.post("/checkouts/sweep", (_req, res) => {
169
+ const result = sweepExpiredCheckoutsManual();
170
+ res.json(result);
171
+ });
172
+ router.get("/checkouts/expired", (_req, res) => {
173
+ const result = sweepExpiredCheckoutsManual();
174
+ res.json({ expired: result.swept, details: result.details });
175
+ });
176
+ router.get("/budgets", (_req, res) => {
177
+ res.json(getBudgetPolicies());
178
+ });
179
+ router.get("/budgets/reservations", (_req, res) => {
180
+ res.json([]);
181
+ });
182
+ router.post("/budgets", (req, res) => {
183
+ try {
184
+ const body = req.body;
185
+ const policy = createBudgetPolicy({
186
+ name: body.name,
187
+ scope: body.scope,
188
+ period: body.period,
189
+ limitUsd: body.limitUsd,
190
+ warningThresholdPercent: body.warningThresholdPercent ?? 80,
191
+ action: body.action ?? "pause",
192
+ enabled: body.enabled ?? true
193
+ });
194
+ res.status(201).json(policy);
195
+ } catch (err) {
196
+ res.status(400).json({ error: err.message });
197
+ }
198
+ });
199
+ router.put("/budgets/:id", (req, res) => {
200
+ const updated = updateBudgetPolicy(req.params.id, req.body);
201
+ if (!updated) {
202
+ res.status(404).json({ error: "Budget policy not found" });
203
+ return;
204
+ }
205
+ res.json(updated);
206
+ });
207
+ router.delete("/budgets/:id", (req, res) => {
208
+ const ok = deleteBudgetPolicy(req.params.id);
209
+ if (!ok) {
210
+ res.status(404).json({ error: "Budget policy not found" });
211
+ return;
212
+ }
213
+ res.json({ success: true });
214
+ });
215
+ router.post("/budgets/:agentId/enforce", (req, res) => {
216
+ const result = enforceBudgetForAgent(req.params.agentId);
217
+ if (!result.budgetOk) {
218
+ res.status(403).json({ budgetOk: false, policies: result.policies, message: "Budget exceeded \u2014 agent paused" });
219
+ return;
220
+ }
221
+ res.json({ budgetOk: true, policies: result.policies });
222
+ });
223
+ router.get("/budgets/agent/:agentId", (req, res) => {
224
+ const budgetInfo = getBudgetPolicyForAgent(req.params.agentId);
225
+ res.json(budgetInfo);
226
+ });
227
+ router.get("/activity", (req, res) => {
228
+ const limit = parseInt(req.query.limit) || 50;
229
+ const type = req.query.type;
230
+ res.json(getActivity({ limit, type }));
231
+ });
232
+ router.get("/audit", async (req, res) => {
233
+ try {
234
+ const { queryAudit } = await import("../../agent/auditStore.js");
235
+ const query = {
236
+ agentId: req.query.agentId,
237
+ sessionId: req.query.sessionId,
238
+ type: req.query.type,
239
+ toolName: req.query.toolName,
240
+ from: req.query.from,
241
+ to: req.query.to,
242
+ limit: req.query.limit ? parseInt(req.query.limit) : 100
243
+ };
244
+ res.json(queryAudit(query));
245
+ } catch (err) {
246
+ res.status(500).json({ error: err.message });
247
+ }
248
+ });
249
+ router.get("/audit/costs", async (req, res) => {
250
+ try {
251
+ const { getAgentCostSummary, getDailyCostBreakdown } = await import("../../agent/auditStore.js");
252
+ const groupBy = req.query.groupBy || "agent";
253
+ if (groupBy === "day") {
254
+ const days = req.query.days ? parseInt(req.query.days) : 30;
255
+ res.json(getDailyCostBreakdown(days));
256
+ } else {
257
+ const agentId = req.query.agentId;
258
+ res.json(getAgentCostSummary(agentId));
259
+ }
260
+ } catch (err) {
261
+ res.status(500).json({ error: err.message });
262
+ }
263
+ });
264
+ router.post("/goals", (req, res) => {
265
+ const { title, description, subtasks, priority, tags, force } = req.body;
266
+ if (!title) {
267
+ res.status(400).json({ error: "title is required" });
268
+ return;
269
+ }
270
+ try {
271
+ const goal = createGoal({
272
+ title,
273
+ description: description || "",
274
+ subtasks: subtasks || [],
275
+ priority,
276
+ tags,
277
+ force: !!force
278
+ });
279
+ res.status(201).json({ goal });
280
+ } catch (err) {
281
+ res.status(429).json({ error: err.message });
282
+ }
283
+ });
284
+ router.get("/goals/tree", (_req, res) => {
285
+ res.json(getGoalTree());
286
+ });
287
+ router.get("/goals/:id/ancestry", (req, res) => {
288
+ const chain = getAncestryChain(req.params.id);
289
+ if (chain.length === 0) {
290
+ res.status(404).json({ error: "Goal not found" });
291
+ return;
292
+ }
293
+ res.json(chain);
294
+ });
295
+ router.post("/goals/:id/validate", (req, res) => {
296
+ const { parentGoalId } = req.body;
297
+ if (parentGoalId !== void 0) {
298
+ const result = validateGoalParentAssignment(req.params.id, parentGoalId || null);
299
+ if (!result.valid) {
300
+ res.status(422).json({ valid: false, errors: result.errors });
301
+ return;
302
+ }
303
+ res.json({ valid: true });
304
+ } else {
305
+ const result = validateGoalAncestry(req.params.id);
306
+ if (!result.valid) {
307
+ res.status(422).json({ valid: false, errors: result.errors });
308
+ return;
309
+ }
310
+ res.json({ valid: true });
311
+ }
312
+ });
313
+ router.post("/conflicts/propose", async (req, res) => {
314
+ try {
315
+ const { conflictResolver } = await import("../../agent/conflictResolver.js");
316
+ const { entities, type, description, metadata } = req.body;
317
+ if (!entities || !Array.isArray(entities) || entities.length === 0) {
318
+ res.status(400).json({ error: "entities array is required" });
319
+ return;
320
+ }
321
+ if (!type || !["file", "goal", "resource", "agent", "config", "other"].includes(type)) {
322
+ res.status(400).json({ error: "valid type is required (file, goal, resource, agent, config, other)" });
323
+ return;
324
+ }
325
+ if (!description || typeof description !== "string") {
326
+ res.status(400).json({ error: "description string is required" });
327
+ return;
328
+ }
329
+ const proposal = await conflictResolver.generateProposal({ entities, type, description, metadata: metadata || {} });
330
+ res.json(proposal);
331
+ } catch (error) {
332
+ logger.error(COMPONENT, "Conflict proposal generation error:", error);
333
+ res.status(500).json({ error: "Failed to generate conflict resolution proposal" });
334
+ }
335
+ });
336
+ router.post("/conflicts/propose/formatted", async (req, res) => {
337
+ try {
338
+ const { conflictResolver } = await import("../../agent/conflictResolver.js");
339
+ const { entities, type, description, metadata } = req.body;
340
+ if (!entities || !Array.isArray(entities) || entities.length === 0) {
341
+ res.status(400).json({ error: "entities array is required" });
342
+ return;
343
+ }
344
+ if (!type || !["file", "goal", "resource", "agent", "config", "other"].includes(type)) {
345
+ res.status(400).json({ error: "valid type is required (file, goal, resource, agent, config, other)" });
346
+ return;
347
+ }
348
+ if (!description || typeof description !== "string") {
349
+ res.status(400).json({ error: "description string is required" });
350
+ return;
351
+ }
352
+ const proposal = await conflictResolver.generateProposal({ entities, type, description, metadata: metadata || {} });
353
+ const formatted = conflictResolver.formatProposal(proposal);
354
+ res.type("text/plain").send(formatted);
355
+ } catch (error) {
356
+ logger.error(COMPONENT, "Conflict proposal formatting error:", error);
357
+ res.status(500).json({ error: "Failed to format conflict resolution proposal" });
358
+ }
359
+ });
360
+ router.get("/conflicts/types", (_req, res) => {
361
+ res.json({
362
+ types: [
363
+ { id: "file", name: "File Conflict", description: "Merge conflicts, version conflicts" },
364
+ { id: "goal", name: "Goal Conflict", description: "Competing or conflicting goals" },
365
+ { id: "resource", name: "Resource Conflict", description: "Resource contention (GPU, memory, etc.)" },
366
+ { id: "agent", name: "Agent Conflict", description: "Agent coordination conflicts" },
367
+ { id: "config", name: "Configuration Conflict", description: "Conflicting configuration values" },
368
+ { id: "other", name: "Other", description: "Unclassified conflict type" }
369
+ ]
370
+ });
371
+ });
372
+ const CP_SSE_EVENTS = [
373
+ "commandpost:activity",
374
+ "commandpost:task:checkout",
375
+ "commandpost:task:checkin",
376
+ "commandpost:task:expired",
377
+ "commandpost:budget:warning",
378
+ "commandpost:budget:exceeded",
379
+ "commandpost:agent:heartbeat",
380
+ "commandpost:agent:status"
381
+ ];
382
+ router.get("/stream", (req, res) => {
383
+ res.writeHead(200, {
384
+ "Content-Type": "text/event-stream",
385
+ "Cache-Control": "no-cache",
386
+ Connection: "keep-alive",
387
+ "X-Accel-Buffering": "no"
388
+ });
389
+ const onEvent = (event, data) => {
390
+ try {
391
+ res.write(`event: ${event}
392
+ data: ${JSON.stringify(data)}
393
+
394
+ `);
395
+ } catch {
396
+ }
397
+ };
398
+ const listeners = /* @__PURE__ */ new Map();
399
+ for (const evt of CP_SSE_EVENTS) {
400
+ const handler = (data) => onEvent(evt, data);
401
+ listeners.set(evt, handler);
402
+ titanEvents.on(evt, handler);
403
+ }
404
+ const keepalive = setInterval(() => {
405
+ try {
406
+ res.write(": keepalive\n\n");
407
+ } catch {
408
+ }
409
+ }, 15e3);
410
+ req.on("close", () => {
411
+ clearInterval(keepalive);
412
+ for (const [evt, handler] of listeners) {
413
+ titanEvents.removeListener(evt, handler);
414
+ }
415
+ });
416
+ });
417
+ router.get("/org", async (_req, res) => {
418
+ const org = getOrgTree();
419
+ try {
420
+ const { listCompanies } = await import("../../agent/company.js");
421
+ const companies = listCompanies();
422
+ const companyNodes = companies.map((c) => ({
423
+ id: c.id,
424
+ name: c.name,
425
+ role: "Company",
426
+ title: c.description,
427
+ status: c.status,
428
+ model: "",
429
+ reports: c.agents.map((a) => ({
430
+ id: a.id,
431
+ name: a.name,
432
+ role: a.role,
433
+ title: a.template,
434
+ status: a.status,
435
+ model: "",
436
+ reports: []
437
+ }))
438
+ }));
439
+ if (Array.isArray(org)) {
440
+ org.push(...companyNodes);
441
+ } else if (org && typeof org === "object") {
442
+ org.companies = companyNodes;
443
+ }
444
+ } catch {
445
+ }
446
+ res.json(org);
447
+ });
448
+ router.get("/issues", (req, res) => {
449
+ const filters = {
450
+ status: req.query.status,
451
+ assigneeAgentId: req.query.assignee,
452
+ goalId: req.query.goalId
453
+ };
454
+ res.json(listIssues(filters));
455
+ });
456
+ router.get("/issues/search", (req, res) => {
457
+ const q = req.query.q;
458
+ if (!q || q.trim().length < 2) {
459
+ res.status(400).json({ error: "Query must be at least 2 characters" });
460
+ return;
461
+ }
462
+ res.json(searchIssues(q));
463
+ });
464
+ router.post("/issues", (req, res) => {
465
+ const { title, description, priority, assigneeAgentId, goalId, parentId } = req.body;
466
+ if (!title) {
467
+ res.status(400).json({ error: "title is required" });
468
+ return;
469
+ }
470
+ const issue = createIssue({ title, description, priority, assigneeAgentId, goalId, parentId, createdByUser: "board" });
471
+ res.status(201).json(issue);
472
+ });
473
+ router.get("/issues/:id/context", (req, res) => {
474
+ const issue = getIssue(req.params.id);
475
+ if (!issue) {
476
+ res.status(404).json({ error: "Issue not found" });
477
+ return;
478
+ }
479
+ res.json({ ancestry: issue.goalId || "", issue });
480
+ });
481
+ router.get("/issues/:id", (req, res) => {
482
+ const issue = getIssue(req.params.id);
483
+ if (!issue) {
484
+ res.status(404).json({ error: "Issue not found" });
485
+ return;
486
+ }
487
+ const issueComments = getIssueComments(req.params.id);
488
+ res.json({ ...issue, comments: issueComments });
489
+ });
490
+ router.get("/issues/:id/comments", (req, res) => {
491
+ const issue = getIssue(req.params.id);
492
+ if (!issue) {
493
+ res.status(404).json({ error: "Issue not found" });
494
+ return;
495
+ }
496
+ res.json(getIssueComments(req.params.id));
497
+ });
498
+ router.patch("/issues/:id", (req, res) => {
499
+ const { title, description, status, priority, assigneeAgentId, goalId } = req.body;
500
+ const updated = updateIssue(req.params.id, { title, description, status, priority, assigneeAgentId, goalId });
501
+ if (!updated) {
502
+ res.status(404).json({ error: "Issue not found" });
503
+ return;
504
+ }
505
+ res.json(updated);
506
+ });
507
+ router.delete("/issues/:id", (req, res) => {
508
+ const ok = deleteIssue(req.params.id);
509
+ if (!ok) {
510
+ res.status(404).json({ error: "Issue not found" });
511
+ return;
512
+ }
513
+ res.json({ success: true });
514
+ });
515
+ router.post("/issues/:id/checkout", (req, res) => {
516
+ const { agentId } = req.body;
517
+ if (!agentId) {
518
+ res.status(400).json({ error: "agentId is required" });
519
+ return;
520
+ }
521
+ const result = checkoutIssue(req.params.id, agentId);
522
+ if (!result) {
523
+ res.status(409).json({ error: "Issue already checked out by another agent" });
524
+ return;
525
+ }
526
+ res.json(result);
527
+ });
528
+ router.post("/issues/:id/comments", (req, res) => {
529
+ const { body: commentBody, agentId } = req.body;
530
+ if (!commentBody) {
531
+ res.status(400).json({ error: "body is required" });
532
+ return;
533
+ }
534
+ const comment = addIssueComment(req.params.id, commentBody, { agentId, user: agentId ? void 0 : "board" });
535
+ if (!comment) {
536
+ res.status(404).json({ error: "Issue not found" });
537
+ return;
538
+ }
539
+ res.status(201).json(comment);
540
+ });
541
+ router.get("/approvals", (req, res) => {
542
+ const status = req.query.status;
543
+ res.json(listApprovals(status));
544
+ });
545
+ router.post("/approvals", (req, res) => {
546
+ const { type, requestedBy, payload, linkedIssueIds } = req.body;
547
+ if (!type) {
548
+ res.status(400).json({ error: "type is required" });
549
+ return;
550
+ }
551
+ const approval = createApproval({ type, requestedBy: requestedBy || "board", payload: payload || {}, linkedIssueIds });
552
+ res.status(201).json(approval);
553
+ });
554
+ router.post("/approvals/:id/approve", async (req, res) => {
555
+ const { decidedBy, note } = req.body;
556
+ const result = await approveApproval(req.params.id, decidedBy || "board", note);
557
+ if (!result) {
558
+ res.status(404).json({ error: "Approval not found or already decided" });
559
+ return;
560
+ }
561
+ res.json(result);
562
+ });
563
+ router.post("/approvals/:id/reject", (req, res) => {
564
+ const { decidedBy, note } = req.body;
565
+ const result = rejectApproval(req.params.id, decidedBy || "board", note);
566
+ if (!result) {
567
+ res.status(404).json({ error: "Approval not found or already decided" });
568
+ return;
569
+ }
570
+ res.json(result);
571
+ });
572
+ router.post("/approvals/:id/reply", (req, res) => {
573
+ const { author, body } = req.body;
574
+ if (!body || typeof body !== "string") {
575
+ res.status(400).json({ error: "body is required" });
576
+ return;
577
+ }
578
+ const result = replyToApproval(req.params.id, author || "user", body);
579
+ if (!result) {
580
+ res.status(404).json({ error: "Approval not found" });
581
+ return;
582
+ }
583
+ res.json(result);
584
+ });
585
+ router.post("/approvals/:id/snooze", (req, res) => {
586
+ const { until } = req.body;
587
+ if (!until) {
588
+ res.status(400).json({ error: "until timestamp is required" });
589
+ return;
590
+ }
591
+ const result = snoozeApproval(req.params.id, until);
592
+ if (!result) {
593
+ res.status(404).json({ error: "Approval not found or not pending" });
594
+ return;
595
+ }
596
+ res.json(result);
597
+ });
598
+ router.post("/approvals/:id/unsnooze", (req, res) => {
599
+ const result = unsnoozeApproval(req.params.id);
600
+ if (!result) {
601
+ res.status(404).json({ error: "Approval not found" });
602
+ return;
603
+ }
604
+ res.json(result);
605
+ });
606
+ router.get("/approvals/:id/thread", (req, res) => {
607
+ const approval = listApprovals().find((a) => a.id === req.params.id);
608
+ if (!approval) {
609
+ res.status(404).json({ error: "Approval not found" });
610
+ return;
611
+ }
612
+ res.json({ approvalId: approval.id, thread: approval.thread || [] });
613
+ });
614
+ router.post("/approvals/batch", async (req, res) => {
615
+ const { ids, action, decidedBy, note } = req.body;
616
+ if (!Array.isArray(ids) || ids.length === 0) {
617
+ res.status(400).json({ error: "ids array required" });
618
+ return;
619
+ }
620
+ if (action === "approve") {
621
+ const result = await batchApprove(ids, decidedBy || "board", note);
622
+ res.json(result);
623
+ } else if (action === "reject") {
624
+ const result = batchReject(ids, decidedBy || "board", note);
625
+ res.json(result);
626
+ } else {
627
+ res.status(400).json({ error: "action must be approve or reject" });
628
+ }
629
+ });
630
+ router.post("/approvals/sweep", async (_req, res) => {
631
+ const { sweepStaleApprovalsManual } = await import("../../agent/commandPost.js");
632
+ const result = sweepStaleApprovalsManual();
633
+ res.json(result);
634
+ });
635
+ router.get("/agent-messages", (req, res) => {
636
+ const agentId = req.query.agentId;
637
+ const userId = req.query.userId;
638
+ const unreadOnly = req.query.unread === "true";
639
+ res.json(getAgentMessages(agentId, userId, unreadOnly));
640
+ });
641
+ router.post("/agent-messages/:id/read", (req, res) => {
642
+ const ok = markAgentMessageRead(req.params.id);
643
+ if (!ok) {
644
+ res.status(404).json({ error: "Message not found" });
645
+ return;
646
+ }
647
+ res.json({ read: true });
648
+ });
649
+ router.post("/debates", async (req, res) => {
650
+ try {
651
+ const { question, participants, rounds, resolution, judgeModel } = req.body || {};
652
+ if (!question || !Array.isArray(participants) || participants.length < 2) {
653
+ res.status(400).json({ error: "question + 2-5 participants required" });
654
+ return;
655
+ }
656
+ const { runDebate } = await import("../../skills/builtin/agent_debate.js");
657
+ const result = await runDebate({
658
+ question: String(question),
659
+ participants,
660
+ rounds: Math.max(1, Math.min(4, Number(rounds) || 2)),
661
+ resolution: resolution === "vote" || resolution === "synthesize" || resolution === "judge" ? resolution : "judge",
662
+ judgeModel: judgeModel ? String(judgeModel) : void 0
663
+ });
664
+ res.json({ ok: true, id: result.id, winner: result.winner });
665
+ } catch (err) {
666
+ res.status(500).json({ error: err.message });
667
+ }
668
+ });
669
+ router.get("/debates", async (req, res) => {
670
+ const limit = parseInt(req.query.limit) || 50;
671
+ const { listDebates } = await import("../../skills/builtin/agent_debate.js");
672
+ res.json({ items: listDebates(limit) });
673
+ });
674
+ router.get("/debates/:id", async (req, res) => {
675
+ const { getDebate } = await import("../../skills/builtin/agent_debate.js");
676
+ const debate = getDebate(req.params.id);
677
+ if (!debate) {
678
+ res.status(404).json({ error: "Debate not found" });
679
+ return;
680
+ }
681
+ res.json(debate);
682
+ });
683
+ router.get("/runs", (req, res) => {
684
+ const agentId = req.query.agentId;
685
+ const limit = parseInt(req.query.limit) || 50;
686
+ res.json(listRuns(agentId, limit));
687
+ });
688
+ router.post("/runs/:id/retry", async (req, res) => {
689
+ const allRuns = listRuns(void 0, 500);
690
+ const run = allRuns.find((r) => r.id === req.params.id);
691
+ if (!run) {
692
+ res.status(404).json({ error: "Run not found" });
693
+ return;
694
+ }
695
+ const agent = getRegisteredAgents().find((a) => a.id === run.agentId);
696
+ if (!agent) {
697
+ res.status(404).json({ error: "Agent not found" });
698
+ return;
699
+ }
700
+ let task = `Retry failed run (${run.id})`;
701
+ if (run.error) task += `: ${run.error}`;
702
+ let issueDesc = task;
703
+ if (run.issueId) {
704
+ const originalIssue = getIssue(run.issueId);
705
+ if (originalIssue) {
706
+ task = `Retry: ${originalIssue.title}`;
707
+ issueDesc = `${originalIssue.description || ""}
708
+
709
+ Retrying after failure: ${run.error || "unknown error"}`;
710
+ }
711
+ }
712
+ const issue = createIssue({ title: task, description: issueDesc, priority: "high", assigneeAgentId: agent.id, createdByUser: "board" });
713
+ const newRun = startRun(agent.id, "manual", issue.id);
714
+ queueWakeup({ issueId: issue.id, issueIdentifier: issue.identifier, agentId: agent.id, agentName: agent.name, parentSessionId: null, task, templateName: agent.role || "default" });
715
+ res.json({ retried: true, runId: newRun.id, issueId: issue.id });
716
+ });
717
+ router.get("/agents/:agentId/inbox", (req, res) => {
718
+ const items = getAgentInbox(req.params.agentId);
719
+ res.json({ items, total: items.length });
720
+ });
721
+ router.post("/wakeup", (req, res) => {
722
+ const { issueId, agentId, agentName, task, templateName } = req.body;
723
+ if (!issueId || !agentId || !task) {
724
+ res.status(400).json({ error: "issueId, agentId, and task are required" });
725
+ return;
726
+ }
727
+ const wakeup = queueWakeup({ issueId, issueIdentifier: issueId, agentId, agentName: agentName || "Agent", parentSessionId: null, task, templateName: templateName || "" });
728
+ res.json({ wakeupRequestId: wakeup.id, status: wakeup.status });
729
+ });
730
+ router.get("/wakeup/:requestId", (req, res) => {
731
+ const request = getWakeupRequest(req.params.requestId);
732
+ if (!request) {
733
+ res.status(404).json({ error: "Wakeup request not found" });
734
+ return;
735
+ }
736
+ res.json(request);
737
+ });
738
+ router.delete("/wakeup/:requestId", (req, res) => {
739
+ const cancelled = cancelWakeup(req.params.requestId);
740
+ if (!cancelled) {
741
+ res.status(409).json({ error: "Request already running or completed" });
742
+ return;
743
+ }
744
+ res.json({ cancelled: true });
745
+ });
746
+ router.get("/sessions/:sessionId/pending-results", (req, res) => {
747
+ const results = drainPendingResults(req.params.sessionId);
748
+ res.json({ results, count: results.length });
749
+ });
750
+ return router;
751
+ }
752
+ export {
753
+ createCommandPostRouter
754
+ };
755
+ //# sourceMappingURL=commandPost.js.map