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,295 @@
1
+ #!/usr/bin/env node
2
+ import { Router } from "express";
3
+ import logger from "../../utils/logger.js";
4
+ import { loadConfig, updateConfig } from "../../config/config.js";
5
+ import { getSkills, toggleSkill, getSkillTools } from "../../skills/registry.js";
6
+ import { listPersonas, getPersona, invalidatePersonaCache } from "../../personas/manager.js";
7
+ import {
8
+ searchSkills as marketplaceSearch,
9
+ installSkill,
10
+ uninstallSkill,
11
+ listSkills as listMarketplaceSkills,
12
+ listInstalled as listInstalledMarketplace
13
+ } from "../../skills/marketplace.js";
14
+ import { getRegisteredTools } from "../../agent/toolRunner.js";
15
+ import { auditSecurity } from "../../security/sandbox.js";
16
+ import { healthCheckAll } from "../../providers/router.js";
17
+ import { TITAN_VERSION } from "../../utils/constants.js";
18
+ const COMPONENT = "SkillsRouter";
19
+ function createSkillsRouter(channels) {
20
+ const router = Router();
21
+ router.get("/skills", (_req, res) => {
22
+ const skills = getSkills();
23
+ res.json(skills);
24
+ });
25
+ router.post("/skills/:name/toggle", (req, res) => {
26
+ try {
27
+ const { name } = req.params;
28
+ const enabled = toggleSkill(name);
29
+ const tools = getSkillTools(name);
30
+ res.json({ ok: true, skill: name, enabled, tools });
31
+ } catch (e) {
32
+ res.status(404).json({ error: e.message });
33
+ }
34
+ });
35
+ router.get("/specialists", async (_req, res) => {
36
+ try {
37
+ const { SPECIALISTS } = await import("../../agent/specialists.js");
38
+ const cfg = loadConfig();
39
+ const overrides = cfg.specialists?.overrides || {};
40
+ const out = SPECIALISTS.map((s) => ({
41
+ id: s.id,
42
+ name: s.name,
43
+ role: s.role,
44
+ title: s.title,
45
+ defaultModel: s.model,
46
+ activeModel: overrides[s.id]?.model || s.model,
47
+ overridden: Boolean(overrides[s.id]?.model && overrides[s.id].model !== s.model),
48
+ templateMatches: s.templateMatches,
49
+ reportsTo: s.reportsTo
50
+ }));
51
+ res.json(out);
52
+ } catch (e) {
53
+ logger.error(COMPONENT, `Endpoint error: ${e.message}`);
54
+ res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
55
+ }
56
+ });
57
+ router.patch("/specialists/:id", async (req, res) => {
58
+ try {
59
+ const { id } = req.params;
60
+ const { model } = req.body || {};
61
+ const { SPECIALISTS } = await import("../../agent/specialists.js");
62
+ const specialist = SPECIALISTS.find((s) => s.id === id);
63
+ if (!specialist) {
64
+ res.status(404).json({ error: `Unknown specialist: ${id}` });
65
+ return;
66
+ }
67
+ const cfg = loadConfig();
68
+ const cfgAny = cfg;
69
+ const overrides = { ...cfgAny.specialists?.overrides || {} };
70
+ if (model === null || model === "" || model === void 0) {
71
+ delete overrides[id];
72
+ } else if (typeof model === "string") {
73
+ overrides[id] = { model };
74
+ } else {
75
+ res.status(400).json({ error: "model must be a string or null" });
76
+ return;
77
+ }
78
+ updateConfig({ specialists: { overrides } });
79
+ res.json({ ok: true, id, activeModel: overrides[id]?.model || specialist.model });
80
+ } catch (e) {
81
+ logger.error(COMPONENT, `Endpoint error: ${e.message}`);
82
+ res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
83
+ }
84
+ });
85
+ router.get("/marketplace", async (_req, res) => {
86
+ try {
87
+ const skills = await listMarketplaceSkills();
88
+ const installed = listInstalledMarketplace();
89
+ res.json({ skills: skills.map((s) => ({ ...s, installed: installed.includes(s.file.replace(".js", "")) })), installed });
90
+ } catch (e) {
91
+ logger.error(COMPONENT, `Endpoint error: ${e.message}`);
92
+ res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
93
+ }
94
+ });
95
+ router.get("/marketplace/search", async (req, res) => {
96
+ try {
97
+ const q = req.query.q || "";
98
+ const results = await marketplaceSearch(q, 50);
99
+ const installed = listInstalledMarketplace();
100
+ res.json({ ...results, skills: results.skills.map((s) => ({ ...s, installed: installed.includes(s.file.replace(".js", "")) })) });
101
+ } catch (e) {
102
+ logger.error(COMPONENT, `Endpoint error: ${e.message}`);
103
+ res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
104
+ }
105
+ });
106
+ router.post("/marketplace/install", async (req, res) => {
107
+ try {
108
+ const { skill } = req.body;
109
+ if (!skill) {
110
+ res.status(400).json({ error: 'Missing "skill" field' });
111
+ return;
112
+ }
113
+ const result = await installSkill(skill);
114
+ res.json(result);
115
+ } catch (e) {
116
+ logger.error(COMPONENT, `Endpoint error: ${e.message}`);
117
+ res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
118
+ }
119
+ });
120
+ router.post("/marketplace/uninstall", (req, res) => {
121
+ try {
122
+ const { skill } = req.body;
123
+ if (!skill) {
124
+ res.status(400).json({ error: 'Missing "skill" field' });
125
+ return;
126
+ }
127
+ const result = uninstallSkill(skill);
128
+ res.json(result);
129
+ } catch (e) {
130
+ logger.error(COMPONENT, `Endpoint error: ${e.message}`);
131
+ res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
132
+ }
133
+ });
134
+ router.get("/personas", (_req, res) => {
135
+ try {
136
+ const cfg = loadConfig();
137
+ res.json({ personas: listPersonas(), active: cfg.agent.persona || "default" });
138
+ } catch (e) {
139
+ logger.error(COMPONENT, `Endpoint error: ${e.message}`);
140
+ res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
141
+ }
142
+ });
143
+ router.post("/persona/switch", (req, res) => {
144
+ try {
145
+ const { persona } = req.body;
146
+ if (!persona || typeof persona !== "string") {
147
+ res.status(400).json({ error: "Missing persona ID" });
148
+ return;
149
+ }
150
+ if (persona !== "default" && !getPersona(persona)) {
151
+ res.status(404).json({ error: `Persona "${persona}" not found` });
152
+ return;
153
+ }
154
+ const cfg = loadConfig();
155
+ updateConfig({ agent: { ...cfg.agent, persona } });
156
+ invalidatePersonaCache();
157
+ res.json({ ok: true, active: persona });
158
+ } catch (e) {
159
+ logger.error(COMPONENT, `Endpoint error: ${e.message}`);
160
+ res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
161
+ }
162
+ });
163
+ router.get("/widget-gallery", async (_req, res) => {
164
+ try {
165
+ const { listTemplates, listCategories } = await import("../../skills/builtin/widget_gallery.js");
166
+ const templates = listTemplates();
167
+ const categories = listCategories();
168
+ res.json({ count: templates.length, categories, templates });
169
+ } catch (e) {
170
+ logger.error(COMPONENT, `Endpoint error: ${e.message}`);
171
+ res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
172
+ }
173
+ });
174
+ router.get("/widget-gallery/:id", async (req, res) => {
175
+ try {
176
+ const { getTemplate } = await import("../../skills/builtin/widget_gallery.js");
177
+ const template = getTemplate(String(req.params.id || ""));
178
+ if (!template) {
179
+ res.status(404).json({ error: `Template not found: ${req.params.id}` });
180
+ return;
181
+ }
182
+ const w = template.defaultSize?.w ?? 4;
183
+ const h = template.defaultSize?.h ?? 4;
184
+ const source = template.source.startsWith("system:") ? template.source : `// __WIDGET_META__ w=${w} h=${h}
185
+ ${template.source || ""}`;
186
+ res.json({
187
+ id: template.id,
188
+ name: template.name,
189
+ category: template.category,
190
+ defaultSize: template.defaultSize,
191
+ source,
192
+ placeholders: template.placeholders ?? []
193
+ });
194
+ } catch (e) {
195
+ logger.error(COMPONENT, `Endpoint error: ${e.message}`);
196
+ res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
197
+ }
198
+ });
199
+ router.get("/tools", (req, res) => {
200
+ const includeSchema = req.query.include === "schema";
201
+ const q = typeof req.query.q === "string" ? req.query.q.toLowerCase() : "";
202
+ const limit = Math.min(parseInt(req.query.limit, 10) || 100, 1e3);
203
+ const offset = Math.max(parseInt(req.query.offset, 10) || 0, 0);
204
+ let tools = getRegisteredTools().map((t) => {
205
+ const item = {
206
+ name: t.name,
207
+ description: t.description
208
+ };
209
+ if (includeSchema) {
210
+ item.parameters = t.parameters;
211
+ }
212
+ return item;
213
+ });
214
+ if (q) {
215
+ tools = tools.filter(
216
+ (t) => t.name.toLowerCase().includes(q) || t.description.toLowerCase().includes(q)
217
+ );
218
+ }
219
+ const total = tools.length;
220
+ const paginated = tools.slice(offset, offset + limit);
221
+ res.json({
222
+ total,
223
+ count: paginated.length,
224
+ offset,
225
+ tools: paginated
226
+ });
227
+ });
228
+ router.get("/channels", (_req, res) => {
229
+ const statuses = Array.from(channels.values()).map((ch) => ch.getStatus());
230
+ res.json(statuses);
231
+ });
232
+ router.get("/security", (_req, res) => {
233
+ const audit = auditSecurity();
234
+ res.json(audit);
235
+ });
236
+ router.get("/providers", async (_req, res) => {
237
+ const health = await healthCheckAll();
238
+ res.json(health);
239
+ });
240
+ router.get("/health", (_req, res) => {
241
+ const cfg = loadConfig();
242
+ res.json({ status: "ok", version: TITAN_VERSION, uptime: process.uptime(), onboarded: cfg.onboarded });
243
+ });
244
+ router.get("/bug-reports", async (req, res) => {
245
+ try {
246
+ const limit = Math.min(Math.max(parseInt(String(req.query.limit ?? "50"), 10) || 50, 1), 200);
247
+ const { listRecentBugReports } = await import("../../analytics/bugReports.js");
248
+ const reports = listRecentBugReports(limit);
249
+ res.json({ count: reports.length, reports });
250
+ } catch (err) {
251
+ res.status(500).json({ error: "bug_reports_unavailable", message: err.message });
252
+ }
253
+ });
254
+ router.get("/bug-reports/:id", async (req, res) => {
255
+ try {
256
+ const { getBugReport } = await import("../../analytics/bugReports.js");
257
+ const r = getBugReport(req.params.id);
258
+ if (!r) {
259
+ res.status(404).json({ error: "not_found" });
260
+ return;
261
+ }
262
+ res.json(r);
263
+ } catch (err) {
264
+ res.status(500).json({ error: "bug_report_unavailable", message: err.message });
265
+ }
266
+ });
267
+ router.post("/sandbox/execute", async (req, res) => {
268
+ try {
269
+ const { code, language, timeoutMs } = req.body;
270
+ if (!code || typeof code !== "string") {
271
+ res.status(400).json({ error: "code is required" });
272
+ return;
273
+ }
274
+ const { executeInSandbox } = await import("../../agent/sandbox.js");
275
+ const result = await executeInSandbox(code, language || "javascript", timeoutMs || 6e4);
276
+ res.json(result);
277
+ } catch (err) {
278
+ logger.error(COMPONENT, `Sandbox execute error: ${err.message}`);
279
+ res.status(500).json({ error: "Sandbox execution failed", message: err.message });
280
+ }
281
+ });
282
+ router.get("/sandbox/status", async (_req, res) => {
283
+ try {
284
+ const { getSandboxStatus } = await import("../../agent/sandbox.js");
285
+ res.json(getSandboxStatus());
286
+ } catch (err) {
287
+ res.status(500).json({ error: "Sandbox status unavailable", message: err.message });
288
+ }
289
+ });
290
+ return router;
291
+ }
292
+ export {
293
+ createSkillsRouter
294
+ };
295
+ //# sourceMappingURL=skills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/gateway/routes/skills.ts"],"sourcesContent":["/**\n * Skills & Meta Router\n *\n * Extracted from gateway/server.ts.\n * Consolidates all /api/skills, /api/specialists, /api/marketplace,\n * /api/personas, /api/widget-gallery, /api/tools, /api/channels,\n * /api/security, /api/providers, /api/health, /api/bug-reports,\n * and /api/sandbox routes.\n */\n\nimport { Router, type Request, type Response } from 'express';\nimport logger from '../../utils/logger.js';\nimport { loadConfig, updateConfig } from '../../config/config.js';\nimport { getSkills, toggleSkill, getSkillTools } from '../../skills/registry.js';\nimport { listPersonas, getPersona, invalidatePersonaCache } from '../../personas/manager.js';\nimport {\n searchSkills as marketplaceSearch,\n installSkill,\n uninstallSkill,\n listSkills as listMarketplaceSkills,\n listInstalled as listInstalledMarketplace,\n} from '../../skills/marketplace.js';\nimport { getRegisteredTools } from '../../agent/toolRunner.js';\nimport { auditSecurity } from '../../security/sandbox.js';\nimport { healthCheckAll } from '../../providers/router.js';\nimport { TITAN_VERSION } from '../../utils/constants.js';\nimport type { ChannelAdapter } from '../../channels/base.js';\n\nconst COMPONENT = 'SkillsRouter';\n\nexport function createSkillsRouter(channels: Map<string, ChannelAdapter>): Router {\n const router = Router();\n\n // ── Skills ──────────────────────────────────────────────────\n router.get('/skills', (_req, res) => {\n const skills = getSkills();\n res.json(skills);\n });\n\n router.post('/skills/:name/toggle', (req, res) => {\n try {\n const { name } = req.params;\n const enabled = toggleSkill(name);\n const tools = getSkillTools(name);\n res.json({ ok: true, skill: name, enabled, tools });\n } catch (e) {\n res.status(404).json({ error: (e as Error).message });\n }\n });\n\n // ── Specialists ─────────────────────────────────────────────\n router.get('/specialists', async (_req, res) => {\n try {\n const { SPECIALISTS } = await import('../../agent/specialists.js');\n const cfg = loadConfig();\n const overrides = (cfg as unknown as { specialists?: { overrides?: Record<string, { model?: string }> } }).specialists?.overrides || {};\n const out = SPECIALISTS.map((s) => ({\n id: s.id,\n name: s.name,\n role: s.role,\n title: s.title,\n defaultModel: s.model,\n activeModel: overrides[s.id]?.model || s.model,\n overridden: Boolean(overrides[s.id]?.model && overrides[s.id].model !== s.model),\n templateMatches: s.templateMatches,\n reportsTo: s.reportsTo,\n }));\n res.json(out);\n } catch (e) {\n logger.error(COMPONENT, `Endpoint error: ${(e as Error).message}`); res.status(500).json({ error: 'Something went wrong on our end. Please try again in a moment.' });\n }\n });\n\n router.patch('/specialists/:id', async (req, res) => {\n try {\n const { id } = req.params;\n const { model } = (req.body || {}) as { model?: string | null };\n const { SPECIALISTS } = await import('../../agent/specialists.js');\n const specialist = SPECIALISTS.find((s) => s.id === id);\n if (!specialist) { res.status(404).json({ error: `Unknown specialist: ${id}` }); return; }\n const cfg = loadConfig();\n const cfgAny = cfg as unknown as { specialists?: { overrides?: Record<string, { model?: string }> } };\n const overrides = { ...(cfgAny.specialists?.overrides || {}) };\n if (model === null || model === '' || model === undefined) {\n delete overrides[id];\n } else if (typeof model === 'string') {\n overrides[id] = { model };\n } else {\n res.status(400).json({ error: 'model must be a string or null' });\n return;\n }\n updateConfig({ specialists: { overrides } } as unknown as Parameters<typeof updateConfig>[0]);\n res.json({ ok: true, id, activeModel: overrides[id]?.model || specialist.model });\n } catch (e) {\n logger.error(COMPONENT, `Endpoint error: ${(e as Error).message}`); res.status(500).json({ error: 'Something went wrong on our end. Please try again in a moment.' });\n }\n });\n\n // ── Marketplace ─────────────────────────────────────────────\n router.get('/marketplace', async (_req, res) => {\n try {\n const skills = await listMarketplaceSkills();\n const installed = listInstalledMarketplace();\n res.json({ skills: skills.map(s => ({ ...s, installed: installed.includes(s.file.replace('.js', '')) })), installed });\n } catch (e) { logger.error(COMPONENT, `Endpoint error: ${(e as Error).message}`); res.status(500).json({ error: 'Something went wrong on our end. Please try again in a moment.' }); }\n });\n\n router.get('/marketplace/search', async (req, res) => {\n try {\n const q = (req.query.q as string) || '';\n const results = await marketplaceSearch(q, 50);\n const installed = listInstalledMarketplace();\n res.json({ ...results, skills: results.skills.map(s => ({ ...s, installed: installed.includes(s.file.replace('.js', '')) })) });\n } catch (e) { logger.error(COMPONENT, `Endpoint error: ${(e as Error).message}`); res.status(500).json({ error: 'Something went wrong on our end. Please try again in a moment.' }); }\n });\n\n router.post('/marketplace/install', async (req, res): Promise<void> => {\n try {\n const { skill } = req.body as { skill: string };\n if (!skill) { res.status(400).json({ error: 'Missing \"skill\" field' }); return; }\n const result = await installSkill(skill);\n res.json(result);\n } catch (e) { logger.error(COMPONENT, `Endpoint error: ${(e as Error).message}`); res.status(500).json({ error: 'Something went wrong on our end. Please try again in a moment.' }); }\n });\n\n router.post('/marketplace/uninstall', (req, res): void => {\n try {\n const { skill } = req.body as { skill: string };\n if (!skill) { res.status(400).json({ error: 'Missing \"skill\" field' }); return; }\n const result = uninstallSkill(skill);\n res.json(result);\n } catch (e) { logger.error(COMPONENT, `Endpoint error: ${(e as Error).message}`); res.status(500).json({ error: 'Something went wrong on our end. Please try again in a moment.' }); }\n });\n\n // ── Personas ──────────────────────────────────────────────────\n router.get('/personas', (_req, res) => {\n try {\n const cfg = loadConfig();\n res.json({ personas: listPersonas(), active: cfg.agent.persona || 'default' });\n } catch (e) { logger.error(COMPONENT, `Endpoint error: ${(e as Error).message}`); res.status(500).json({ error: 'Something went wrong on our end. Please try again in a moment.' }); }\n });\n\n router.post('/persona/switch', (req, res): void => {\n try {\n const { persona } = req.body as { persona: string };\n if (!persona || typeof persona !== 'string') { res.status(400).json({ error: 'Missing persona ID' }); return; }\n if (persona !== 'default' && !getPersona(persona)) { res.status(404).json({ error: `Persona \"${persona}\" not found` }); return; }\n const cfg = loadConfig();\n updateConfig({ agent: { ...cfg.agent, persona } });\n invalidatePersonaCache();\n res.json({ ok: true, active: persona });\n } catch (e) { logger.error(COMPONENT, `Endpoint error: ${(e as Error).message}`); res.status(500).json({ error: 'Something went wrong on our end. Please try again in a moment.' }); }\n });\n\n // ── Widget Gallery ──────────────────────────────────────────\n router.get('/widget-gallery', async (_req, res) => {\n try {\n const { listTemplates, listCategories } = await import('../../skills/builtin/widget_gallery.js');\n const templates = listTemplates();\n const categories = listCategories();\n res.json({ count: templates.length, categories, templates });\n } catch (e) { logger.error(COMPONENT, `Endpoint error: ${(e as Error).message}`); res.status(500).json({ error: 'Something went wrong on our end. Please try again in a moment.' }); }\n });\n\n router.get('/widget-gallery/:id', async (req, res): Promise<void> => {\n try {\n const { getTemplate } = await import('../../skills/builtin/widget_gallery.js');\n const template = getTemplate(String(req.params.id || ''));\n if (!template) {\n res.status(404).json({ error: `Template not found: ${req.params.id}` });\n return;\n }\n\n const w = template.defaultSize?.w ?? 4;\n const h = template.defaultSize?.h ?? 4;\n const source = template.source.startsWith('system:')\n ? template.source\n : `// __WIDGET_META__ w=${w} h=${h}\\n${template.source || ''}`;\n\n res.json({\n id: template.id,\n name: template.name,\n category: template.category,\n defaultSize: template.defaultSize,\n source,\n placeholders: template.placeholders ?? [],\n });\n } catch (e) { logger.error(COMPONENT, `Endpoint error: ${(e as Error).message}`); res.status(500).json({ error: 'Something went wrong on our end. Please try again in a moment.' }); }\n });\n\n // ── Tools ───────────────────────────────────────────────────\n router.get('/tools', (req, res) => {\n const includeSchema = req.query.include === 'schema';\n const q = typeof req.query.q === 'string' ? req.query.q.toLowerCase() : '';\n const limit = Math.min(parseInt(req.query.limit as string, 10) || 100, 1000);\n const offset = Math.max(parseInt(req.query.offset as string, 10) || 0, 0);\n\n let tools = getRegisteredTools().map((t) => {\n const item: Record<string, unknown> = {\n name: t.name,\n description: t.description,\n };\n if (includeSchema) {\n item.parameters = t.parameters;\n }\n return item;\n });\n\n if (q) {\n tools = tools.filter((t) =>\n (t.name as string).toLowerCase().includes(q) ||\n (t.description as string).toLowerCase().includes(q),\n );\n }\n\n const total = tools.length;\n const paginated = tools.slice(offset, offset + limit);\n\n res.json({\n total,\n count: paginated.length,\n offset,\n tools: paginated,\n });\n });\n\n // ── Channels ──────────────────────────────────────────────\n router.get('/channels', (_req, res) => {\n const statuses = Array.from(channels.values()).map((ch) => ch.getStatus());\n res.json(statuses);\n });\n\n // ── Security ────────────────────────────────────────────────\n router.get('/security', (_req, res) => {\n const audit = auditSecurity();\n res.json(audit);\n });\n\n // ── Providers ─────────────────────────────────────────────\n router.get('/providers', async (_req, res) => {\n const health = await healthCheckAll();\n res.json(health);\n });\n\n // ── Health ──────────────────────────────────────────────────\n router.get('/health', (_req, res) => {\n const cfg = loadConfig();\n res.json({ status: 'ok', version: TITAN_VERSION, uptime: process.uptime(), onboarded: cfg.onboarded });\n });\n\n // ── Bug Reports ─────────────────────────────────────────────\n router.get('/bug-reports', async (req, res) => {\n try {\n const limit = Math.min(Math.max(parseInt(String(req.query.limit ?? '50'), 10) || 50, 1), 200);\n const { listRecentBugReports } = await import('../../analytics/bugReports.js');\n const reports = listRecentBugReports(limit);\n res.json({ count: reports.length, reports });\n } catch (err) {\n res.status(500).json({ error: 'bug_reports_unavailable', message: (err as Error).message });\n }\n });\n\n router.get('/bug-reports/:id', async (req, res) => {\n try {\n const { getBugReport } = await import('../../analytics/bugReports.js');\n const r = getBugReport(req.params.id);\n if (!r) {\n res.status(404).json({ error: 'not_found' });\n return;\n }\n res.json(r);\n } catch (err) {\n res.status(500).json({ error: 'bug_report_unavailable', message: (err as Error).message });\n }\n });\n\n // ── Sandbox ─────────────────────────────────────────────────\n router.post('/sandbox/execute', async (req, res) => {\n try {\n const { code, language, timeoutMs } = req.body;\n if (!code || typeof code !== 'string') {\n res.status(400).json({ error: 'code is required' });\n return;\n }\n const { executeInSandbox } = await import('../../agent/sandbox.js');\n const result = await executeInSandbox(code, language || 'javascript', timeoutMs || 60000);\n res.json(result);\n } catch (err) {\n logger.error(COMPONENT, `Sandbox execute error: ${(err as Error).message}`);\n res.status(500).json({ error: 'Sandbox execution failed', message: (err as Error).message });\n }\n });\n\n router.get('/sandbox/status', async (_req, res) => {\n try {\n const { getSandboxStatus } = await import('../../agent/sandbox.js');\n res.json(getSandboxStatus());\n } catch (err) {\n res.status(500).json({ error: 'Sandbox status unavailable', message: (err as Error).message });\n }\n });\n\n return router;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,145 @@
1
+ #!/usr/bin/env node
2
+ import { Router } from "express";
3
+ import logger from "../../utils/logger.js";
4
+ function createSocialRouter() {
5
+ const router = Router();
6
+ router.get("/social/state", async (_req, res) => {
7
+ try {
8
+ const { loadConfig } = await import("../../config/config.js");
9
+ const { loadState, resetDailyCounters, CONTENT_ROTATION } = await import("../../skills/builtin/fb_autopilot.js");
10
+ const { loadQueue } = await import("../../skills/builtin/facebook.js");
11
+ const { getEpisodesBySource } = await import("../../memory/graph.js");
12
+ const config = loadConfig();
13
+ const fbConfig = config.facebook;
14
+ const state = loadState();
15
+ resetDailyCounters(state);
16
+ const queue = loadQueue();
17
+ const pending = queue.posts.filter((p) => p.status === "pending");
18
+ const graphPosts = getEpisodesBySource(["facebook_post", "facebook_autopilot"], 20);
19
+ const recentPosts = state.postHistory.slice(-20).reverse().map((h) => {
20
+ if (h.content) return h;
21
+ const match = graphPosts.find((g) => g.createdAt.slice(0, 16) === h.date.slice(0, 16));
22
+ return { ...h, content: match ? match.content : void 0 };
23
+ });
24
+ res.json({
25
+ autopilot: {
26
+ enabled: fbConfig?.autopilotEnabled !== false,
27
+ postsToday: state.postsToday,
28
+ maxPostsPerDay: Number(fbConfig?.maxPostsPerDay ?? 6),
29
+ repliesToday: state.repliesToday,
30
+ lastPostAt: state.lastPostAt,
31
+ nextContentType: CONTENT_ROTATION[state.contentIndex % CONTENT_ROTATION.length]
32
+ },
33
+ queue: pending,
34
+ recentPosts
35
+ });
36
+ } catch (e) {
37
+ logger.error("SocialRouter", `Social state error: ${e.message}`);
38
+ res.status(500).json({ error: "Failed to load social state" });
39
+ }
40
+ });
41
+ router.post("/social/autopilot/toggle", async (req, res) => {
42
+ try {
43
+ const { loadConfig, updateConfig } = await import("../../config/config.js");
44
+ const config = loadConfig();
45
+ const enabled = !!req.body.enabled;
46
+ const fb = { ...config.facebook || {}, autopilotEnabled: enabled };
47
+ updateConfig({ facebook: fb });
48
+ res.json({ enabled });
49
+ } catch (e) {
50
+ logger.error("SocialRouter", `Social toggle error: ${e.message}`);
51
+ res.status(500).json({ error: "Failed to toggle autopilot" });
52
+ }
53
+ });
54
+ router.post("/social/post", async (req, res) => {
55
+ try {
56
+ const { postToPage } = await import("../../skills/builtin/facebook.js");
57
+ const content = String(req.body.content || "");
58
+ if (!content || content.length < 5) {
59
+ res.status(400).json({ error: "Content too short" });
60
+ return;
61
+ }
62
+ const result = await postToPage(content, { source: "manual:api" });
63
+ if (result.success) {
64
+ res.json({ success: true, postId: result.postId });
65
+ } else if (result.skipped) {
66
+ res.status(409).json({ success: false, skipped: result.skipped });
67
+ } else {
68
+ res.status(500).json({ success: false, error: result.error });
69
+ }
70
+ } catch (e) {
71
+ logger.error("SocialRouter", `Social post error: ${e.message}`);
72
+ res.status(500).json({ error: "Failed to post" });
73
+ }
74
+ });
75
+ router.post("/social/drafts/:id/approve", async (req, res) => {
76
+ try {
77
+ const { loadQueue, saveQueue, postToPage, hasApiAccess } = await import("../../skills/builtin/facebook.js");
78
+ const queue = loadQueue();
79
+ const post = queue.posts.find((p) => p.id === req.params.id);
80
+ if (!post) {
81
+ res.status(404).json({ error: "Draft not found" });
82
+ return;
83
+ }
84
+ if (post.status !== "pending") {
85
+ res.status(409).json({ error: `Already ${post.status}` });
86
+ return;
87
+ }
88
+ if (hasApiAccess()) {
89
+ const result = await postToPage(post.content, { source: "queue:approved" });
90
+ if (result.success) {
91
+ post.status = "posted";
92
+ post.postedAt = (/* @__PURE__ */ new Date()).toISOString();
93
+ post.fbPostId = result.postId;
94
+ } else {
95
+ res.status(500).json({ error: result.error || "Post failed" });
96
+ return;
97
+ }
98
+ } else {
99
+ post.status = "approved";
100
+ }
101
+ saveQueue(queue);
102
+ res.json({ success: true, status: post.status, postId: post.fbPostId });
103
+ } catch (e) {
104
+ logger.error("SocialRouter", `Draft approve error: ${e.message}`);
105
+ res.status(500).json({ error: "Failed to approve draft" });
106
+ }
107
+ });
108
+ router.post("/social/drafts/:id/reject", async (req, res) => {
109
+ try {
110
+ const { loadQueue, saveQueue } = await import("../../skills/builtin/facebook.js");
111
+ const queue = loadQueue();
112
+ const post = queue.posts.find((p) => p.id === req.params.id);
113
+ if (!post) {
114
+ res.status(404).json({ error: "Draft not found" });
115
+ return;
116
+ }
117
+ post.status = "rejected";
118
+ saveQueue(queue);
119
+ res.json({ success: true });
120
+ } catch (e) {
121
+ logger.error("SocialRouter", `Draft reject error: ${e.message}`);
122
+ res.status(500).json({ error: "Failed to reject draft" });
123
+ }
124
+ });
125
+ router.get("/social/graph-context", async (_req, res) => {
126
+ try {
127
+ const { getEpisodesBySource } = await import("../../memory/graph.js");
128
+ const recentPosts = getEpisodesBySource(["facebook_post", "facebook_autopilot"], 5);
129
+ const topics = recentPosts.map((ep) => ({
130
+ content: ep.content.slice(0, 200),
131
+ date: ep.createdAt,
132
+ entities: ep.entities
133
+ }));
134
+ res.json({ recentTopics: topics });
135
+ } catch (e) {
136
+ logger.error("SocialRouter", `Social graph context error: ${e.message}`);
137
+ res.status(500).json({ error: "Failed to load graph context" });
138
+ }
139
+ });
140
+ return router;
141
+ }
142
+ export {
143
+ createSocialRouter
144
+ };
145
+ //# sourceMappingURL=socialRouter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/gateway/routes/socialRouter.ts"],"sourcesContent":["/**\n * Social Media Router\n *\n * Extracted from gateway/server.ts.\n * Consolidates all /api/social/* routes.\n */\n\nimport { Router, type Request, type Response } from 'express';\nimport logger from '../../utils/logger.js';\n\nexport function createSocialRouter(): Router {\n const router = Router();\n\n router.get('/social/state', async (_req, res) => {\n try {\n const { loadConfig } = await import('../../config/config.js');\n const { loadState, resetDailyCounters, CONTENT_ROTATION } = await import('../../skills/builtin/fb_autopilot.js');\n const { loadQueue } = await import('../../skills/builtin/facebook.js');\n const { getEpisodesBySource } = await import('../../memory/graph.js');\n const config = loadConfig();\n const fbConfig = (config as Record<string, unknown>).facebook as Record<string, unknown> | undefined;\n const state = loadState();\n resetDailyCounters(state);\n const queue = loadQueue();\n const pending = queue.posts.filter(p => p.status === 'pending');\n // Enrich recentPosts with Graphiti content when state file lacks it\n const graphPosts = getEpisodesBySource(['facebook_post', 'facebook_autopilot'], 20);\n const recentPosts = state.postHistory.slice(-20).reverse().map(h => {\n if (h.content) return h;\n // Try to find matching content in Graphiti by date proximity\n const match = graphPosts.find(g => g.createdAt.slice(0, 16) === h.date.slice(0, 16));\n return { ...h, content: match ? match.content : undefined };\n });\n res.json({\n autopilot: {\n enabled: fbConfig?.autopilotEnabled !== false,\n postsToday: state.postsToday,\n maxPostsPerDay: Number(fbConfig?.maxPostsPerDay ?? 6),\n repliesToday: state.repliesToday,\n lastPostAt: state.lastPostAt,\n nextContentType: CONTENT_ROTATION[state.contentIndex % CONTENT_ROTATION.length],\n },\n queue: pending,\n recentPosts,\n });\n } catch (e) {\n logger.error('SocialRouter', `Social state error: ${(e as Error).message}`);\n res.status(500).json({ error: 'Failed to load social state' });\n }\n });\n\n router.post('/social/autopilot/toggle', async (req, res) => {\n try {\n const { loadConfig, updateConfig } = await import('../../config/config.js');\n const config = loadConfig();\n const enabled = !!(req.body as Record<string, unknown>).enabled;\n const fb = { ...((config as Record<string, unknown>).facebook as Record<string, unknown> || {}), autopilotEnabled: enabled } as Record<string, unknown>;\n updateConfig({ facebook: fb } as Partial<typeof config>);\n res.json({ enabled });\n } catch (e) {\n logger.error('SocialRouter', `Social toggle error: ${(e as Error).message}`);\n res.status(500).json({ error: 'Failed to toggle autopilot' });\n }\n });\n\n router.post('/social/post', async (req, res) => {\n try {\n const { postToPage } = await import('../../skills/builtin/facebook.js');\n const content = String((req.body as Record<string, unknown>).content || '');\n if (!content || content.length < 5) { res.status(400).json({ error: 'Content too short' }); return; }\n const result = await postToPage(content, { source: 'manual:api' });\n if (result.success) {\n res.json({ success: true, postId: result.postId });\n } else if (result.skipped) {\n res.status(409).json({ success: false, skipped: result.skipped });\n } else {\n res.status(500).json({ success: false, error: result.error });\n }\n } catch (e) {\n logger.error('SocialRouter', `Social post error: ${(e as Error).message}`);\n res.status(500).json({ error: 'Failed to post' });\n }\n });\n\n router.post('/social/drafts/:id/approve', async (req, res) => {\n try {\n const { loadQueue, saveQueue, postToPage, hasApiAccess } = await import('../../skills/builtin/facebook.js') as any;\n const queue = loadQueue();\n const post = queue.posts.find((p: { id: string }) => p.id === req.params.id);\n if (!post) { res.status(404).json({ error: 'Draft not found' }); return; }\n if (post.status !== 'pending') { res.status(409).json({ error: `Already ${post.status}` }); return; }\n if (hasApiAccess()) {\n const result = await postToPage(post.content, { source: 'queue:approved' });\n if (result.success) {\n post.status = 'posted';\n post.postedAt = new Date().toISOString();\n post.fbPostId = result.postId;\n } else {\n res.status(500).json({ error: result.error || 'Post failed' });\n return;\n }\n } else {\n post.status = 'approved';\n }\n saveQueue(queue);\n res.json({ success: true, status: post.status, postId: post.fbPostId });\n } catch (e) {\n logger.error('SocialRouter', `Draft approve error: ${(e as Error).message}`);\n res.status(500).json({ error: 'Failed to approve draft' });\n }\n });\n\n router.post('/social/drafts/:id/reject', async (req, res) => {\n try {\n const { loadQueue, saveQueue } = await import('../../skills/builtin/facebook.js');\n const queue = loadQueue();\n const post = queue.posts.find(p => p.id === req.params.id);\n if (!post) { res.status(404).json({ error: 'Draft not found' }); return; }\n post.status = 'rejected';\n saveQueue(queue);\n res.json({ success: true });\n } catch (e) {\n logger.error('SocialRouter', `Draft reject error: ${(e as Error).message}`);\n res.status(500).json({ error: 'Failed to reject draft' });\n }\n });\n\n router.get('/social/graph-context', async (_req, res) => {\n try {\n const { getEpisodesBySource } = await import('../../memory/graph.js');\n const recentPosts = getEpisodesBySource(['facebook_post', 'facebook_autopilot'], 5);\n const topics = recentPosts.map(ep => ({\n content: ep.content.slice(0, 200),\n date: ep.createdAt,\n entities: ep.entities,\n }));\n res.json({ recentTopics: topics });\n } catch (e) {\n logger.error('SocialRouter', `Social graph context error: ${(e as Error).message}`);\n res.status(500).json({ error: 'Failed to load graph context' });\n }\n });\n\n return router;\n}\n"],"mappings":"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","names":[]}