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.
- package/README.md +1 -1
- package/dist/agent/agent.js +9 -5
- package/dist/agent/agent.js.map +1 -1
- package/dist/agent/agentLoop.js +7 -3
- package/dist/agent/agentLoop.js.map +1 -1
- package/dist/agent/checkpoint.js +2 -2
- package/dist/agent/checkpoint.js.map +1 -1
- package/dist/agent/commandPost.js +3 -3
- package/dist/agent/commandPost.js.map +1 -1
- package/dist/agent/goalProposer.js +2 -2
- package/dist/agent/goalProposer.js.map +1 -1
- package/dist/agent/goals.js +3 -3
- package/dist/agent/goals.js.map +1 -1
- package/dist/agent/peerAdvise.js +1 -1
- package/dist/agent/peerAdvise.js.map +1 -1
- package/dist/agent/planner.js +4 -4
- package/dist/agent/planner.js.map +1 -1
- package/dist/agent/userProfile.js +2 -2
- package/dist/agent/userProfile.js.map +1 -1
- package/dist/cli/doctor.js +33 -0
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/onboard.js +4 -4
- package/dist/cli/onboard.js.map +1 -1
- package/dist/config/config.js +3 -3
- package/dist/config/config.js.map +1 -1
- package/dist/config/schema.js +8 -1
- package/dist/config/schema.js.map +1 -1
- package/dist/gateway/routes/adminRouter.js +500 -0
- package/dist/gateway/routes/adminRouter.js.map +1 -0
- package/dist/gateway/routes/agents.js +231 -0
- package/dist/gateway/routes/agents.js.map +1 -0
- package/dist/gateway/routes/agentsRouter.js +32 -0
- package/dist/gateway/routes/agentsRouter.js.map +1 -0
- package/dist/gateway/routes/checkpoints.js +41 -0
- package/dist/gateway/routes/checkpoints.js.map +1 -0
- package/dist/gateway/routes/commandPost.js +755 -0
- package/dist/gateway/routes/commandPost.js.map +1 -0
- package/dist/gateway/routes/companies.js +166 -0
- package/dist/gateway/routes/companies.js.map +1 -0
- package/dist/gateway/routes/files.js +295 -0
- package/dist/gateway/routes/files.js.map +1 -0
- package/dist/gateway/routes/hardwareRouter.js +151 -0
- package/dist/gateway/routes/hardwareRouter.js.map +1 -0
- package/dist/gateway/routes/mcpRouter.js +88 -0
- package/dist/gateway/routes/mcpRouter.js.map +1 -0
- package/dist/gateway/routes/mesh.js +464 -0
- package/dist/gateway/routes/mesh.js.map +1 -0
- package/dist/gateway/routes/metricsRouter.js +131 -0
- package/dist/gateway/routes/metricsRouter.js.map +1 -0
- package/dist/gateway/routes/organism.js +82 -0
- package/dist/gateway/routes/organism.js.map +1 -0
- package/dist/gateway/routes/paperclip.js +101 -0
- package/dist/gateway/routes/paperclip.js.map +1 -0
- package/dist/gateway/routes/sessions.js +227 -0
- package/dist/gateway/routes/sessions.js.map +1 -0
- package/dist/gateway/routes/skills.js +295 -0
- package/dist/gateway/routes/skills.js.map +1 -0
- package/dist/gateway/routes/socialRouter.js +145 -0
- package/dist/gateway/routes/socialRouter.js.map +1 -0
- package/dist/gateway/routes/systemRouter.js +220 -0
- package/dist/gateway/routes/systemRouter.js.map +1 -0
- package/dist/gateway/routes/teamsRecipes.js +297 -0
- package/dist/gateway/routes/teamsRecipes.js.map +1 -0
- package/dist/gateway/routes/tests.js +401 -0
- package/dist/gateway/routes/tests.js.map +1 -0
- package/dist/gateway/routes/traces.js +33 -0
- package/dist/gateway/routes/traces.js.map +1 -0
- package/dist/gateway/routes/voiceRouter.js +770 -0
- package/dist/gateway/routes/voiceRouter.js.map +1 -0
- package/dist/gateway/routes/watchRouter.js +131 -0
- package/dist/gateway/routes/watchRouter.js.map +1 -0
- package/dist/gateway/server.js +1179 -7379
- package/dist/gateway/server.js.map +1 -1
- package/dist/mcp/registry.js +2 -2
- package/dist/mcp/registry.js.map +1 -1
- package/dist/memory/episodic.js +2 -2
- package/dist/memory/episodic.js.map +1 -1
- package/dist/memory/learning.js +3 -3
- package/dist/memory/learning.js.map +1 -1
- package/dist/memory/memory.js +3 -3
- package/dist/memory/memory.js.map +1 -1
- package/dist/organism/drives.js +2 -2
- package/dist/organism/drives.js.map +1 -1
- package/dist/providers/errorTaxonomy.js +13 -0
- package/dist/providers/errorTaxonomy.js.map +1 -1
- package/dist/providers/ollama.js +3 -1
- package/dist/providers/ollama.js.map +1 -1
- package/dist/providers/openai_compat.js +4 -3
- package/dist/providers/openai_compat.js.map +1 -1
- package/dist/providers/router.js +13 -0
- package/dist/providers/router.js.map +1 -1
- package/dist/safety/fixOscillation.js +15 -0
- package/dist/safety/fixOscillation.js.map +1 -1
- package/dist/safety/killSwitch.js +2 -2
- package/dist/safety/killSwitch.js.map +1 -1
- package/dist/safety/selfRepair.js +7 -3
- package/dist/safety/selfRepair.js.map +1 -1
- package/dist/skills/builtin/agent_debate.js +2 -2
- package/dist/skills/builtin/agent_debate.js.map +1 -1
- package/dist/skills/builtin/apply_patch.js +3 -3
- package/dist/skills/builtin/apply_patch.js.map +1 -1
- package/dist/skills/builtin/shell.js +2 -2
- package/dist/skills/builtin/shell.js.map +1 -1
- package/dist/skills/builtin/voice_control.js +49 -0
- package/dist/skills/builtin/voice_control.js.map +1 -0
- package/dist/skills/builtin/widget_gallery.js +6 -1
- package/dist/skills/builtin/widget_gallery.js.map +1 -1
- package/dist/skills/registry.js +15 -4
- package/dist/skills/registry.js.map +1 -1
- package/dist/storage/JsonStorage.js +4 -4
- package/dist/storage/JsonStorage.js.map +1 -1
- package/dist/utils/constants.js +1 -1
- package/dist/utils/constants.js.map +1 -1
- package/dist/utils/helpers.js +3 -1
- package/dist/utils/helpers.js.map +1 -1
- package/dist/utils/lifecycle.js +86 -0
- package/dist/utils/lifecycle.js.map +1 -0
- package/dist/voice/bridge.js +136 -0
- package/dist/voice/bridge.js.map +1 -0
- package/docs/COO-MASTER-PLAN-2026-05-02.md +474 -0
- package/docs/HANDOFF/2026-04-29.md +141 -0
- package/docs/HANDOFF-2026-04-30.md +144 -0
- package/docs/HANDOFF-2026-05-03.md +114 -0
- package/docs/adr/2026-04-29-widget-pipeline-traceability.md +49 -0
- package/docs/agent-memory/README.md +45 -0
- package/docs/agent-memory/commands.md +100 -0
- package/docs/agent-memory/context-tree.md +101 -0
- package/docs/agent-memory/current-state.md +54 -0
- package/docs/agent-memory/decisions.md +78 -0
- package/docs/agent-memory/known-issues.md +76 -0
- package/docs/agent-memory/reflections.md +52 -0
- package/docs/agent-memory/skills-candidates.md +80 -0
- package/docs/superpowers/plans/2026-04-29-comprehensive-audit.md +256 -0
- package/docs/superpowers/plans/2026-04-29-comprehensive-test-plan.md +396 -0
- package/docs/superpowers/plans/2026-04-29-fix-all-prs.md +251 -0
- package/docs/superpowers/plans/2026-04-29-gitnexus-gap-remediation.md +969 -0
- package/package.json +5 -2
- package/ui/dist/assets/{AuditPanel-CM6Wg9hO.js → AuditPanel-VzSndmDN.js} +2 -2
- package/ui/dist/assets/{AutonomyPanel-CESx3ANg.js → AutonomyPanel-BiFouzAV.js} +2 -2
- package/ui/dist/assets/AutopilotPanel-fjOfM668.js +1 -0
- package/ui/dist/assets/{AutoresearchPanel-DR47NqT5.js → AutoresearchPanel-CVCxzAH3.js} +2 -2
- package/ui/dist/assets/BackupPanel-CHVTG--q.js +1 -0
- package/ui/dist/assets/{BrowserPanel-C15x9bLn.js → BrowserPanel-D5mvMKFU.js} +2 -2
- package/ui/dist/assets/CPActivity-B12mt35m.js +1 -0
- package/ui/dist/assets/CPAgentDetail-DsdShc-1.js +1 -0
- package/ui/dist/assets/CPAgents-j_7C-oQV.js +1 -0
- package/ui/dist/assets/CPApprovals-BShKSX9X.js +1 -0
- package/ui/dist/assets/CPCosts-CKPlhBDs.js +1 -0
- package/ui/dist/assets/CPDashboard-11c0nkxK.js +1 -0
- package/ui/dist/assets/CPFiles-BhLEOnXy.js +1 -0
- package/ui/dist/assets/CPGoals-Bi3t1b2P.js +1 -0
- package/ui/dist/assets/CPInbox-Bbr7khp6.js +11 -0
- package/ui/dist/assets/CPIssueDetail-DSdgNK8r.js +1 -0
- package/ui/dist/assets/CPIssues-DDEVKhX6.js +1 -0
- package/ui/dist/assets/CPLayout-DgPOfyGv.js +17 -0
- package/ui/dist/assets/CPOrg-Df73RrRJ.js +8 -0
- package/ui/dist/assets/CPRuns-ByioAz8w.js +1 -0
- package/ui/dist/assets/{CPSocial-nb-j7sOE.js → CPSocial-Dlnr_w1X.js} +2 -2
- package/ui/dist/assets/ChannelsPanel-DQjQCTK5.js +1 -0
- package/ui/dist/assets/CheckpointsPanel-C4vKjlAJ.js +1 -0
- package/ui/dist/assets/CommandPostHub-C9pp5Giq.js +24 -0
- package/ui/dist/assets/CronPanel-C6bzUfrD.js +1 -0
- package/ui/dist/assets/DaemonPanel-BA5Tb_UO.js +1 -0
- package/ui/dist/assets/{DataTable-B2Ma8hfi.js → DataTable-CH7IYJJh.js} +1 -1
- package/ui/dist/assets/{EmptyState-CcKyk5Yn.js → EmptyState-jU6yNDnF.js} +1 -1
- package/ui/dist/assets/{EvalHarnessPanel-BqtMc1ZM.js → EvalHarnessPanel-DnYqredY.js} +2 -2
- package/ui/dist/assets/EvalPanel-ChO7CD1r.js +1 -0
- package/ui/dist/assets/{FilesPanel-3QKvrWPo.js → FilesPanel-CaUkv2is.js} +2 -2
- package/ui/dist/assets/FleetPanel-DC_5uj0N.js +1 -0
- package/ui/dist/assets/{HomelabPanel-DhrjTX9m.js → HomelabPanel-CE5PGRpL.js} +2 -2
- package/ui/dist/assets/InfraView-C-uSlvb9.js +2 -0
- package/ui/dist/assets/InlineEditableField-BMQjiE6-.js +1 -0
- package/ui/dist/assets/Input-Bu_b3qmY.js +1 -0
- package/ui/dist/assets/IntegrationsPanel-DsYpAq43.js +1 -0
- package/ui/dist/assets/IntelligenceView-DUdIO1K7.js +2 -0
- package/ui/dist/assets/LearningPanel-UpQZC-mA.js +1 -0
- package/ui/dist/assets/LogsPanel-ClXJ4fcr.js +1 -0
- package/ui/dist/assets/McpPanel-JKgtIERQ.js +1 -0
- package/ui/dist/assets/{MemoryGraphPanel-Bzvjmzvk.js → MemoryGraphPanel-Bo2OrvA6.js} +2 -2
- package/ui/dist/assets/MemoryWikiPanel-BqJ1AmYm.js +11 -0
- package/ui/dist/assets/{MeshPanel-C3LJSlht.js → MeshPanel-BJVGYvwk.js} +2 -2
- package/ui/dist/assets/Modal-CAAooiZU.js +1 -0
- package/ui/dist/assets/NvidiaPanel-BtCg3G4w.js +1 -0
- package/ui/dist/assets/OrganismPanel-DgrTTzcF.js +1 -0
- package/ui/dist/assets/OverviewPanel-rVav1Hox.js +1 -0
- package/ui/dist/assets/{PageHeader-BimceqQo.js → PageHeader-CnZtP8ek.js} +1 -1
- package/ui/dist/assets/PaperclipPanel-C-FKdhiF.js +1 -0
- package/ui/dist/assets/{PersonasPanel-L1j78p6H.js → PersonasPanel-BmlxokfB.js} +1 -1
- package/ui/dist/assets/RecipesPanel-BNKKChis.js +1 -0
- package/ui/dist/assets/SecurityPanel-I7JRHiNy.js +1 -0
- package/ui/dist/assets/SelfImprovePanel-u9h0Lt3p.js +1 -0
- package/ui/dist/assets/{SelfProposalsPanel-lNmiDThB.js → SelfProposalsPanel-DKl9iBjM.js} +2 -2
- package/ui/dist/assets/SessionsPanel-BhRiWI_g.js +1 -0
- package/ui/dist/assets/{SessionsTab-JQbltWww.js → SessionsTab-Bk08wyeY.js} +1 -1
- package/ui/dist/assets/SettingsPanel-haLfmG2k.js +1 -0
- package/ui/dist/assets/SettingsView--gi3fxI8.js +2 -0
- package/ui/dist/assets/{SkeletonLoader-atQtpcF5.js → SkeletonLoader-B5v09EF_.js} +1 -1
- package/ui/dist/assets/{SkillsPanel-DlFs2ih7.js → SkillsPanel-BlAHFLcQ.js} +1 -1
- package/ui/dist/assets/SomaView-CExtS3zw.js +5 -0
- package/ui/dist/assets/{StatCard-DciE_Iqc.js → StatCard-BIsyMybM.js} +1 -1
- package/ui/dist/assets/{StatusBadge-BtfSPoW2.js → StatusBadge-D5nU7El8.js} +1 -1
- package/ui/dist/assets/Tabs-BBYZrBI8.js +1 -0
- package/ui/dist/assets/TeamsPanel-LPXJg823.js +1 -0
- package/ui/dist/assets/TelemetryPanel-EqpRBmOI.js +1 -0
- package/ui/dist/assets/TitanCanvas-BCbWnLMd.js +985 -0
- package/ui/dist/assets/ToolsView-CeP0Zz-N.js +2 -0
- package/ui/dist/assets/{Tooltip-70UK0E2I.js → Tooltip-BSO2XVpF.js} +1 -1
- package/ui/dist/assets/TraceViewer-BKI7o5B0.js +1 -0
- package/ui/dist/assets/TrainingPanel-c-RhjdE1.js +1 -0
- package/ui/dist/assets/VoiceOverlay-D-gc58b0.js +27 -0
- package/ui/dist/assets/VramPanel-C6xc7zgd.js +1 -0
- package/ui/dist/assets/{WatchView-C-sGFpVy.js → WatchView-dqBVCVH0.js} +1 -1
- package/ui/dist/assets/WorkTab-CBoLNrTM.js +1 -0
- package/ui/dist/assets/{WorkflowsPanel-CvgQU1xI.js → WorkflowsPanel-BAnSTOYe.js} +2 -2
- package/ui/dist/assets/approvalHeadline-DB9SgR-9.js +1 -0
- package/ui/dist/assets/{arrow-left-DwqHtJiU.js → arrow-left-5chqas7J.js} +1 -1
- package/ui/dist/assets/briefcase-D4vLzudp.js +6 -0
- package/ui/dist/assets/{chart-column-BtNO6sRy.js → chart-column-CdFlBpoP.js} +1 -1
- package/ui/dist/assets/check-Bpm1IONe.js +6 -0
- package/ui/dist/assets/chevron-down-D7OLjvuD.js +6 -0
- package/ui/dist/assets/chevron-right-aQEw2mUW.js +6 -0
- package/ui/dist/assets/chevron-up-C5g6pEj8.js +6 -0
- package/ui/dist/assets/{circle-check-big-DZRE_MbN.js → circle-check-big-fPhEdP88.js} +1 -1
- package/ui/dist/assets/clock-CTsgP_Sn.js +6 -0
- package/ui/dist/assets/{dollar-sign-aVG3a5eL.js → dollar-sign-CudFVYFc.js} +1 -1
- package/ui/dist/assets/{download-BxiWJU4G.js → download-DZRxDn67.js} +1 -1
- package/ui/dist/assets/external-link-BZ0y_Ahx.js +6 -0
- package/ui/dist/assets/{eye-off-CkgfFYhm.js → eye-off-BmJF0YYx.js} +1 -1
- package/ui/dist/assets/folder-DA43TRCm.js +11 -0
- package/ui/dist/assets/{funnel-PkLdxKyC.js → funnel-J3mULzrz.js} +1 -1
- package/ui/dist/assets/{git-branch-BM-Gw95X.js → git-branch-oHibJqDq.js} +1 -1
- package/ui/dist/assets/{index-D0RJ8701.css → index-BR0vfkIi.css} +1 -1
- package/ui/dist/assets/{index-CahJbWSR.js → index-DzwowwSI.js} +20 -20
- package/ui/dist/assets/{layers-BuGf4FIJ.js → layers-DsyEyu7z.js} +1 -1
- package/ui/dist/assets/{legacy-CR6o4t-y.js → legacy-8ITl64sV.js} +1 -1
- package/ui/dist/assets/{lightbulb-n8gc_XAL.js → lightbulb-C54Ske-p.js} +1 -1
- package/ui/dist/assets/list-todo-Cnd4rdoK.js +6 -0
- package/ui/dist/assets/loader-circle-1YOBsoQp.js +6 -0
- package/ui/dist/assets/network-DbGDAdrn.js +6 -0
- package/ui/dist/assets/{pause-DCV52koX.js → pause-CYhO_uQo.js} +1 -1
- package/ui/dist/assets/{play-CcJ9BnCh.js → play-DVY9c5Ck.js} +1 -1
- package/ui/dist/assets/{plug-CfWBXfCl.js → plug-BcXjlPUL.js} +1 -1
- package/ui/dist/assets/plus-Csu2v9GN.js +6 -0
- package/ui/dist/assets/{proxy-CzZDfLmm.js → proxy-DxS2_9D7.js} +1 -1
- package/ui/dist/assets/rotate-ccw-Co-_W04j.js +6 -0
- package/ui/dist/assets/save-Btx-kpoW.js +6 -0
- package/ui/dist/assets/search-0hXTwEZR.js +6 -0
- package/ui/dist/assets/send-TEpapzQR.js +6 -0
- package/ui/dist/assets/shield-check-DjBJXZUr.js +6 -0
- package/ui/dist/assets/{square-DJpUhlxi.js → square-OweUvjP-.js} +1 -1
- package/ui/dist/assets/{target-DWcmM_9m.js → target-BRW80Xer.js} +1 -1
- package/ui/dist/assets/terminal-BtiqJ628.js +16 -0
- package/ui/dist/assets/{toggle-right-YusFQ69L.js → toggle-right-CKtSrl28.js} +1 -1
- package/ui/dist/assets/{trash-2-CK7yQ55V.js → trash-2-DgWrHVax.js} +1 -1
- package/ui/dist/assets/{trending-up-DGjFyubC.js → trending-up-MpIrE4j6.js} +1 -1
- package/ui/dist/assets/{trophy-uQv_NgDB.js → trophy-CECuZNhX.js} +1 -1
- package/ui/dist/assets/users-dZgv4ePG.js +16 -0
- package/ui/dist/assets/wrench-CDz3xYve.js +11 -0
- package/ui/dist/index.html +2 -2
- package/ui/dist/assets/AutopilotPanel-DtEet1hJ.js +0 -1
- package/ui/dist/assets/BackupPanel-BGP8p3l3.js +0 -1
- package/ui/dist/assets/CPAgents-DYUtPzSq.js +0 -1
- package/ui/dist/assets/CPDashboard-Bf0-SyCh.js +0 -6
- package/ui/dist/assets/CPFiles-CxgxjQcO.js +0 -1
- package/ui/dist/assets/CPGoals-BsmCMTvT.js +0 -1
- package/ui/dist/assets/CPInbox-tMSbmQ9H.js +0 -11
- package/ui/dist/assets/ChannelsPanel-DP5C2OKd.js +0 -1
- package/ui/dist/assets/CheckpointsPanel-DlranVLZ.js +0 -1
- package/ui/dist/assets/CommandPostHub-BgxIa4Ev.js +0 -29
- package/ui/dist/assets/CronPanel-LoT5yKwJ.js +0 -1
- package/ui/dist/assets/DaemonPanel-DBGMqaE_.js +0 -1
- package/ui/dist/assets/EvalPanel-Bc33j0pN.js +0 -1
- package/ui/dist/assets/FleetPanel-CSsXuQYj.js +0 -1
- package/ui/dist/assets/InfraView-CR6HyrL6.js +0 -2
- package/ui/dist/assets/InlineEditableField-CnvF-yFR.js +0 -1
- package/ui/dist/assets/Input-GTHp2Rkr.js +0 -1
- package/ui/dist/assets/IntegrationsPanel-CymCRE3T.js +0 -1
- package/ui/dist/assets/IntelligenceView-C1IHxJRC.js +0 -2
- package/ui/dist/assets/LearningPanel-DOCES3lH.js +0 -1
- package/ui/dist/assets/LogsPanel-BLnAqEaZ.js +0 -1
- package/ui/dist/assets/McpPanel-ChUzmr3z.js +0 -1
- package/ui/dist/assets/MemoryWikiPanel-Dwk3Aqwd.js +0 -11
- package/ui/dist/assets/NvidiaPanel-CeZK_-CV.js +0 -1
- package/ui/dist/assets/OrganismPanel-BB6YOiQV.js +0 -1
- package/ui/dist/assets/OverviewPanel-BmtBhQnv.js +0 -1
- package/ui/dist/assets/PaperclipPanel-C-brgwA3.js +0 -1
- package/ui/dist/assets/RecipesPanel-34lCfynJ.js +0 -1
- package/ui/dist/assets/SecurityPanel-CBTPWLj6.js +0 -1
- package/ui/dist/assets/SelfImprovePanel-BrPbFHhG.js +0 -1
- package/ui/dist/assets/SessionsPanel-DAEYIn83.js +0 -1
- package/ui/dist/assets/SettingsPanel-CzRROAYQ.js +0 -1
- package/ui/dist/assets/SettingsView-CN7ii2uw.js +0 -2
- package/ui/dist/assets/SomaView-Ba642Oqb.js +0 -5
- package/ui/dist/assets/TeamsPanel-DKQ5z2Qe.js +0 -1
- package/ui/dist/assets/TelemetryPanel-B6KAc55Q.js +0 -1
- package/ui/dist/assets/TitanCanvas-C-s0A-lv.js +0 -1092
- package/ui/dist/assets/ToolsView-Dei0KMP0.js +0 -2
- package/ui/dist/assets/TraceViewer-BniolyBx.js +0 -1
- package/ui/dist/assets/TrainingPanel-Bz4CTPGW.js +0 -1
- package/ui/dist/assets/VoiceOverlay-CmNCrLcd.js +0 -37
- package/ui/dist/assets/VramPanel-Xh_OtRDR.js +0 -1
- package/ui/dist/assets/WorkTab-BjLNmgIK.js +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/gateway/routes/metricsRouter.ts"],"sourcesContent":["/**\n * Metrics Router\n *\n * Extracted from gateway/server.ts.\n * Consolidates Prometheus metrics, JSON summaries, telemetry, and analytics routes.\n */\n\nimport { Router } from 'express';\nimport { serializePrometheus, getMetricsSummary } from '../metrics.js';\nimport { loadConfig, updateConfig } from '../../config/config.js';\nimport { collectSystemProfile, recordStartupAnalytics, getRemoteAnalyticsStatus } from '../../analytics/collector.js';\nimport { TITAN_VERSION } from '../../utils/constants.js';\n\nfunction getUserIdFromReq(req: { headers: { authorization?: string } }): string {\n const token = req.headers.authorization?.replace('Bearer ', '');\n if (token) {\n return token; // simplified; server.ts tracks authTokens but this matches prior usage\n }\n return 'default-user';\n}\n\nexport function createMetricsRouter(): Router {\n const router = Router();\n\n // ── Prometheus / JSON metrics ───────────────────────────────\n router.get('/metrics', (_req, res) => {\n res.setHeader('Content-Type', 'text/plain; version=0.0.4');\n res.send(serializePrometheus());\n });\n\n router.get('/metrics/summary', (_req, res) => {\n res.json(getMetricsSummary());\n });\n\n // ── Telemetry ───────────────────────────────────────────────\n router.post('/telemetry', (req, res) => {\n const cfg = loadConfig();\n if (!cfg.telemetry?.enabled) {\n res.status(204).end();\n return;\n }\n const { event, properties, timestamp } = req.body || {};\n if (!event || typeof event !== 'string') {\n res.status(400).json({ error: 'event is required' });\n return;\n }\n const entry = {\n event,\n properties: properties || {},\n timestamp: timestamp || new Date().toISOString(),\n sessionId: getUserIdFromReq(req),\n };\n // Fire-and-forget append to storage\n import('../../storage/index.js')\n .then(({ getStorage }) => getStorage())\n .then((storage) => storage.appendTelemetryEvent?.(entry))\n .catch(() => {});\n res.status(204).end();\n });\n\n router.get('/telemetry/events', async (_req, res) => {\n const cfg = loadConfig();\n if (!cfg.telemetry?.enabled) {\n res.json({ enabled: false, events: [] });\n return;\n }\n const limit = Math.min(parseInt((_req.query.limit as string) || '100', 10), 1000);\n try {\n const { getStorage } = await import('../../storage/index.js');\n const storage = await getStorage();\n const events = await storage.queryTelemetryEvents?.({ limit }) ?? [];\n res.json({ enabled: true, events });\n } catch (err) {\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // ── Analytics Profile ───────────────────────────────────────\n router.get('/analytics/profile', async (_req, res) => {\n try {\n const profile = await collectSystemProfile();\n res.json(profile);\n } catch (err) {\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // ── Consent management ─────────────────────────────────────\n router.post('/telemetry/consent', async (req, res) => {\n try {\n const body = (req.body || {}) as { enabled?: boolean; crashReports?: boolean };\n const enabled = body.enabled === true;\n const crashReports = body.crashReports !== false; // default true when opted in\n const patch = {\n telemetry: {\n enabled,\n crashReports,\n consentedAt: enabled ? new Date().toISOString() : undefined,\n consentedVersion: enabled ? TITAN_VERSION : undefined,\n },\n } as unknown as Parameters<typeof updateConfig>[0];\n updateConfig(patch);\n\n if (enabled) {\n (async () => {\n try {\n const { recordStartupAnalytics: record } = await import('../../analytics/collector.js');\n await record();\n } catch { /* best-effort */ }\n })();\n }\n\n res.json({ ok: true, enabled, crashReports });\n } catch (err) {\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n router.get('/telemetry/consent', (_req, res) => {\n const cfg = loadConfig();\n const t = cfg.telemetry as unknown as {\n enabled?: boolean;\n crashReports?: boolean;\n consentedAt?: string;\n consentedVersion?: string;\n remoteUrl?: string;\n } | undefined;\n res.json({\n enabled: Boolean(t?.enabled),\n crashReports: t?.crashReports !== false,\n consentedAt: t?.consentedAt,\n consentedVersion: t?.consentedVersion,\n remoteUrl: t?.remoteUrl,\n });\n });\n\n router.get('/telemetry/status', async (_req, res) => {\n try {\n const cfg = loadConfig();\n const t = cfg.telemetry as unknown as {\n enabled?: boolean;\n crashReports?: boolean;\n consentedAt?: string;\n consentedVersion?: string;\n remoteUrl?: string;\n } | undefined;\n const remote = getRemoteAnalyticsStatus();\n res.json({\n consent: {\n enabled: Boolean(t?.enabled),\n crashReports: t?.crashReports !== false,\n consentedAt: t?.consentedAt,\n consentedVersion: t?.consentedVersion,\n remoteUrl: t?.remoteUrl,\n },\n remote,\n });\n } catch (err) {\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n return router;\n}\n"],"mappings":";AAOA,SAAS,cAAc;AACvB,SAAS,qBAAqB,yBAAyB;AACvD,SAAS,YAAY,oBAAoB;AACzC,SAAS,sBAA8C,gCAAgC;AACvF,SAAS,qBAAqB;AAE9B,SAAS,iBAAiB,KAAsD;AAC9E,QAAM,QAAQ,IAAI,QAAQ,eAAe,QAAQ,WAAW,EAAE;AAC9D,MAAI,OAAO;AACT,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEO,SAAS,sBAA8B;AAC5C,QAAM,SAAS,OAAO;AAGtB,SAAO,IAAI,YAAY,CAAC,MAAM,QAAQ;AACpC,QAAI,UAAU,gBAAgB,2BAA2B;AACzD,QAAI,KAAK,oBAAoB,CAAC;AAAA,EAChC,CAAC;AAED,SAAO,IAAI,oBAAoB,CAAC,MAAM,QAAQ;AAC5C,QAAI,KAAK,kBAAkB,CAAC;AAAA,EAC9B,CAAC;AAGD,SAAO,KAAK,cAAc,CAAC,KAAK,QAAQ;AACtC,UAAM,MAAM,WAAW;AACvB,QAAI,CAAC,IAAI,WAAW,SAAS;AAC3B,UAAI,OAAO,GAAG,EAAE,IAAI;AACpB;AAAA,IACF;AACA,UAAM,EAAE,OAAO,YAAY,UAAU,IAAI,IAAI,QAAQ,CAAC;AACtD,QAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,oBAAoB,CAAC;AACnD;AAAA,IACF;AACA,UAAM,QAAQ;AAAA,MACZ;AAAA,MACA,YAAY,cAAc,CAAC;AAAA,MAC3B,WAAW,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,MAC/C,WAAW,iBAAiB,GAAG;AAAA,IACjC;AAEA,WAAO,wBAAwB,EAC5B,KAAK,CAAC,EAAE,WAAW,MAAM,WAAW,CAAC,EACrC,KAAK,CAAC,YAAY,QAAQ,uBAAuB,KAAK,CAAC,EACvD,MAAM,MAAM;AAAA,IAAC,CAAC;AACjB,QAAI,OAAO,GAAG,EAAE,IAAI;AAAA,EACtB,CAAC;AAED,SAAO,IAAI,qBAAqB,OAAO,MAAM,QAAQ;AACnD,UAAM,MAAM,WAAW;AACvB,QAAI,CAAC,IAAI,WAAW,SAAS;AAC3B,UAAI,KAAK,EAAE,SAAS,OAAO,QAAQ,CAAC,EAAE,CAAC;AACvC;AAAA,IACF;AACA,UAAM,QAAQ,KAAK,IAAI,SAAU,KAAK,MAAM,SAAoB,OAAO,EAAE,GAAG,GAAI;AAChF,QAAI;AACF,YAAM,EAAE,WAAW,IAAI,MAAM,OAAO,wBAAwB;AAC5D,YAAM,UAAU,MAAM,WAAW;AACjC,YAAM,SAAS,MAAM,QAAQ,uBAAuB,EAAE,MAAM,CAAC,KAAK,CAAC;AACnE,UAAI,KAAK,EAAE,SAAS,MAAM,OAAO,CAAC;AAAA,IACpC,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAQ,IAAc,QAAQ,CAAC;AAAA,IACxD;AAAA,EACF,CAAC;AAGD,SAAO,IAAI,sBAAsB,OAAO,MAAM,QAAQ;AACpD,QAAI;AACF,YAAM,UAAU,MAAM,qBAAqB;AAC3C,UAAI,KAAK,OAAO;AAAA,IAClB,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAQ,IAAc,QAAQ,CAAC;AAAA,IACxD;AAAA,EACF,CAAC;AAGD,SAAO,KAAK,sBAAsB,OAAO,KAAK,QAAQ;AACpD,QAAI;AACF,YAAM,OAAQ,IAAI,QAAQ,CAAC;AAC3B,YAAM,UAAU,KAAK,YAAY;AACjC,YAAM,eAAe,KAAK,iBAAiB;AAC3C,YAAM,QAAQ;AAAA,QACZ,WAAW;AAAA,UACT;AAAA,UACA;AAAA,UACA,aAAa,WAAU,oBAAI,KAAK,GAAE,YAAY,IAAI;AAAA,UAClD,kBAAkB,UAAU,gBAAgB;AAAA,QAC9C;AAAA,MACF;AACA,mBAAa,KAAK;AAElB,UAAI,SAAS;AACX,SAAC,YAAY;AACX,cAAI;AACF,kBAAM,EAAE,wBAAwB,OAAO,IAAI,MAAM,OAAO,8BAA8B;AACtF,kBAAM,OAAO;AAAA,UACf,QAAQ;AAAA,UAAoB;AAAA,QAC9B,GAAG;AAAA,MACL;AAEA,UAAI,KAAK,EAAE,IAAI,MAAM,SAAS,aAAa,CAAC;AAAA,IAC9C,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAQ,IAAc,QAAQ,CAAC;AAAA,IACxD;AAAA,EACF,CAAC;AAED,SAAO,IAAI,sBAAsB,CAAC,MAAM,QAAQ;AAC9C,UAAM,MAAM,WAAW;AACvB,UAAM,IAAI,IAAI;AAOd,QAAI,KAAK;AAAA,MACP,SAAS,QAAQ,GAAG,OAAO;AAAA,MAC3B,cAAc,GAAG,iBAAiB;AAAA,MAClC,aAAa,GAAG;AAAA,MAChB,kBAAkB,GAAG;AAAA,MACrB,WAAW,GAAG;AAAA,IAChB,CAAC;AAAA,EACH,CAAC;AAED,SAAO,IAAI,qBAAqB,OAAO,MAAM,QAAQ;AACnD,QAAI;AACF,YAAM,MAAM,WAAW;AACvB,YAAM,IAAI,IAAI;AAOd,YAAM,SAAS,yBAAyB;AACxC,UAAI,KAAK;AAAA,QACP,SAAS;AAAA,UACP,SAAS,QAAQ,GAAG,OAAO;AAAA,UAC3B,cAAc,GAAG,iBAAiB;AAAA,UAClC,aAAa,GAAG;AAAA,UAChB,kBAAkB,GAAG;AAAA,UACrB,WAAW,GAAG;AAAA,QAChB;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAQ,IAAc,QAAQ,CAAC;AAAA,IACxD;AAAA,EACF,CAAC;AAED,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Router } from "express";
|
|
3
|
+
import logger from "../../utils/logger.js";
|
|
4
|
+
const COMPONENT = "OrganismRouter";
|
|
5
|
+
function createOrganismRouter() {
|
|
6
|
+
const router = Router();
|
|
7
|
+
router.get("/organism/history", async (_req, res) => {
|
|
8
|
+
res.status(501).json({ error: "Not implemented" });
|
|
9
|
+
});
|
|
10
|
+
router.get("/organism/safety-trend", async (_req, res) => {
|
|
11
|
+
res.status(501).json({ error: "Not implemented" });
|
|
12
|
+
});
|
|
13
|
+
router.get("/organism/safety-metrics", async (_req, res) => {
|
|
14
|
+
res.status(501).json({ error: "Not implemented" });
|
|
15
|
+
});
|
|
16
|
+
router.get("/organism/alerts", async (_req, res) => {
|
|
17
|
+
try {
|
|
18
|
+
const { getAlerts } = await import("../../organism/alertsStore.js");
|
|
19
|
+
res.json({ alerts: getAlerts() });
|
|
20
|
+
} catch (e) {
|
|
21
|
+
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
22
|
+
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
router.get("/organism/alerts/stats", async (_req, res) => {
|
|
26
|
+
try {
|
|
27
|
+
const { getAlertStats } = await import("../../organism/alertsStore.js");
|
|
28
|
+
res.json(getAlertStats());
|
|
29
|
+
} catch (e) {
|
|
30
|
+
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
31
|
+
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
router.get("/organism/alerts/config", async (_req, res) => {
|
|
35
|
+
try {
|
|
36
|
+
const { getAlertConfig } = await import("../../organism/alertsStore.js");
|
|
37
|
+
res.json(getAlertConfig());
|
|
38
|
+
} catch (e) {
|
|
39
|
+
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
40
|
+
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
router.post("/organism/alerts/config", async (_req, res) => {
|
|
44
|
+
try {
|
|
45
|
+
const { setAlertConfig } = await import("../../organism/alertsStore.js");
|
|
46
|
+
setAlertConfig(_req.body || {});
|
|
47
|
+
res.json({ success: true });
|
|
48
|
+
} catch (e) {
|
|
49
|
+
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
50
|
+
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
router.post("/organism/alerts/:id/acknowledge", async (req, res) => {
|
|
54
|
+
try {
|
|
55
|
+
const { acknowledgeAlert } = await import("../../organism/alertsStore.js");
|
|
56
|
+
const ok = acknowledgeAlert(req.params.id);
|
|
57
|
+
if (!ok) {
|
|
58
|
+
res.status(404).json({ error: "Alert not found" });
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
res.json({ success: true });
|
|
62
|
+
} catch (e) {
|
|
63
|
+
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
64
|
+
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
router.delete("/organism/alerts/old", async (_req, res) => {
|
|
68
|
+
try {
|
|
69
|
+
const { deleteOldAlerts } = await import("../../organism/alertsStore.js");
|
|
70
|
+
const removed = deleteOldAlerts();
|
|
71
|
+
res.json({ removed });
|
|
72
|
+
} catch (e) {
|
|
73
|
+
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
74
|
+
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
return router;
|
|
78
|
+
}
|
|
79
|
+
export {
|
|
80
|
+
createOrganismRouter
|
|
81
|
+
};
|
|
82
|
+
//# sourceMappingURL=organism.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/gateway/routes/organism.ts"],"sourcesContent":["/**\n * Organism Router\n *\n * Extracted from gateway/server.ts.\n * Consolidates all /api/organism/* routes.\n */\n\nimport { Router } from 'express';\nimport logger from '../../utils/logger.js';\n\nconst COMPONENT = 'OrganismRouter';\n\nexport function createOrganismRouter(): Router {\n const router = Router();\n\n router.get('/organism/history', async (_req, res) => {\n res.status(501).json({ error: 'Not implemented' });\n });\n\n router.get('/organism/safety-trend', async (_req, res) => {\n res.status(501).json({ error: 'Not implemented' });\n });\n\n router.get('/organism/safety-metrics', async (_req, res) => {\n res.status(501).json({ error: 'Not implemented' });\n });\n\n router.get('/organism/alerts', async (_req, res) => {\n try {\n const { getAlerts } = await import('../../organism/alertsStore.js');\n res.json({ alerts: getAlerts() });\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('/organism/alerts/stats', async (_req, res) => {\n try {\n const { getAlertStats } = await import('../../organism/alertsStore.js');\n res.json(getAlertStats());\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('/organism/alerts/config', async (_req, res) => {\n try {\n const { getAlertConfig } = await import('../../organism/alertsStore.js');\n res.json(getAlertConfig());\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('/organism/alerts/config', async (_req, res) => {\n try {\n const { setAlertConfig } = await import('../../organism/alertsStore.js');\n setAlertConfig(_req.body || {});\n res.json({ success: true });\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('/organism/alerts/:id/acknowledge', async (req, res) => {\n try {\n const { acknowledgeAlert } = await import('../../organism/alertsStore.js');\n const ok = acknowledgeAlert(req.params.id);\n if (!ok) { res.status(404).json({ error: 'Alert not found' }); return; }\n res.json({ success: true });\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.delete('/organism/alerts/old', async (_req, res) => {\n try {\n const { deleteOldAlerts } = await import('../../organism/alertsStore.js');\n const removed = deleteOldAlerts();\n res.json({ removed });\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 return router;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Router } from "express";
|
|
3
|
+
import { startPaperclip, stopPaperclip, getPaperclipStatus } from "../../addons/paperclipSidecar.js";
|
|
4
|
+
import logger from "../../utils/logger.js";
|
|
5
|
+
import { titanEvents } from "../../agent/daemon.js";
|
|
6
|
+
const COMPONENT = "Gateway:Paperclip";
|
|
7
|
+
const PAPERCLIP_PORT = 3100;
|
|
8
|
+
function createPaperclipRouter() {
|
|
9
|
+
const router = Router();
|
|
10
|
+
router.get("/status", async (_req, res) => {
|
|
11
|
+
try {
|
|
12
|
+
res.json(await getPaperclipStatus());
|
|
13
|
+
} catch (err) {
|
|
14
|
+
res.status(500).json({ error: err.message });
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
router.post("/start", async (_req, res) => {
|
|
18
|
+
try {
|
|
19
|
+
await startPaperclip({ enabled: true, port: PAPERCLIP_PORT, autoStart: true }, titanEvents);
|
|
20
|
+
res.json({ ok: true });
|
|
21
|
+
} catch (err) {
|
|
22
|
+
logger.error(COMPONENT, `Paperclip start failed: ${err.message}`);
|
|
23
|
+
res.status(500).json({ error: err.message });
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
router.post("/stop", async (_req, res) => {
|
|
27
|
+
try {
|
|
28
|
+
await stopPaperclip();
|
|
29
|
+
res.json({ ok: true });
|
|
30
|
+
} catch (err) {
|
|
31
|
+
logger.error(COMPONENT, `Paperclip stop failed: ${err.message}`);
|
|
32
|
+
res.status(500).json({ error: err.message });
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
router.post("/reset", async (_req, res) => {
|
|
36
|
+
try {
|
|
37
|
+
await stopPaperclip();
|
|
38
|
+
await startPaperclip({ enabled: true, port: PAPERCLIP_PORT, autoStart: true }, titanEvents);
|
|
39
|
+
res.json({ ok: true });
|
|
40
|
+
} catch (err) {
|
|
41
|
+
logger.error(COMPONENT, `Paperclip reset failed: ${err.message}`);
|
|
42
|
+
res.status(500).json({ error: err.message });
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
router.all("/*", async (req, res) => {
|
|
46
|
+
const targetPath = req.path.replace(/^\/api\/paperclip/, "/api");
|
|
47
|
+
const query = req.url.includes("?") ? "?" + req.url.split("?")[1] : "";
|
|
48
|
+
const targetUrl = `http://localhost:${PAPERCLIP_PORT}${targetPath}${query}`;
|
|
49
|
+
try {
|
|
50
|
+
const headers = new Headers();
|
|
51
|
+
for (const [k, v] of Object.entries(req.headers)) {
|
|
52
|
+
if (v && k.toLowerCase() !== "host") headers.set(k, Array.isArray(v) ? v[0] : v);
|
|
53
|
+
}
|
|
54
|
+
const upstream = await fetch(targetUrl, {
|
|
55
|
+
method: req.method,
|
|
56
|
+
headers,
|
|
57
|
+
body: ["GET", "HEAD"].includes(req.method) ? void 0 : JSON.stringify(req.body)
|
|
58
|
+
});
|
|
59
|
+
res.status(upstream.status);
|
|
60
|
+
upstream.headers.forEach((v, k) => res.setHeader(k, v));
|
|
61
|
+
const body = await upstream.arrayBuffer();
|
|
62
|
+
res.end(Buffer.from(body));
|
|
63
|
+
} catch (err) {
|
|
64
|
+
logger.error(COMPONENT, `Paperclip API proxy error: ${err.message}`);
|
|
65
|
+
res.status(502).json({ error: "Paperclip API proxy error", message: err.message });
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
return router;
|
|
69
|
+
}
|
|
70
|
+
function createPaperclipUIRouter() {
|
|
71
|
+
const router = Router();
|
|
72
|
+
router.all("/*", async (req, res) => {
|
|
73
|
+
const targetPath = req.path.replace(/^\/paperclip/, "") || "/";
|
|
74
|
+
const query = req.url.includes("?") ? "?" + req.url.split("?")[1] : "";
|
|
75
|
+
const targetUrl = `http://localhost:${PAPERCLIP_PORT}${targetPath}${query}`;
|
|
76
|
+
try {
|
|
77
|
+
const headers = new Headers();
|
|
78
|
+
for (const [k, v] of Object.entries(req.headers)) {
|
|
79
|
+
if (v && k.toLowerCase() !== "host") headers.set(k, Array.isArray(v) ? v[0] : v);
|
|
80
|
+
}
|
|
81
|
+
const upstream = await fetch(targetUrl, {
|
|
82
|
+
method: req.method,
|
|
83
|
+
headers,
|
|
84
|
+
body: ["GET", "HEAD"].includes(req.method) ? void 0 : JSON.stringify(req.body)
|
|
85
|
+
});
|
|
86
|
+
res.status(upstream.status);
|
|
87
|
+
upstream.headers.forEach((v, k) => res.setHeader(k, v));
|
|
88
|
+
const body = await upstream.arrayBuffer();
|
|
89
|
+
res.end(Buffer.from(body));
|
|
90
|
+
} catch (err) {
|
|
91
|
+
logger.error(COMPONENT, `Paperclip UI proxy error: ${err.message}`);
|
|
92
|
+
res.status(502).json({ error: "Paperclip UI proxy error", message: err.message });
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
return router;
|
|
96
|
+
}
|
|
97
|
+
export {
|
|
98
|
+
createPaperclipRouter,
|
|
99
|
+
createPaperclipUIRouter
|
|
100
|
+
};
|
|
101
|
+
//# sourceMappingURL=paperclip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/gateway/routes/paperclip.ts"],"sourcesContent":["/**\n * Gateway sub-router for /api/paperclip/* and /paperclip/* routes.\n *\n * Extracted from src/gateway/server.ts to decompose the gateway monolith\n * and make the Paperclip sidecar API surface independently testable.\n *\n * Routes:\n * GET /api/paperclip/status\n * POST /api/paperclip/start\n * POST /api/paperclip/stop\n * POST /api/paperclip/reset\n * ALL /api/paperclip/* → proxy to Paperclip API\n * ALL /paperclip/* → proxy to Paperclip web UI\n */\n\nimport { Router, Request, Response } from 'express';\nimport { startPaperclip, stopPaperclip, getPaperclipStatus } from '../../addons/paperclipSidecar.js';\nimport logger from '../../utils/logger.js';\nimport { titanEvents } from '../../agent/daemon.js';\n\nconst COMPONENT = 'Gateway:Paperclip';\nconst PAPERCLIP_PORT = 3100;\n\nexport function createPaperclipRouter(): Router {\n const router = Router();\n\n // ── Management routes ──\n\n router.get('/status', async (_req, res) => {\n try {\n res.json(await getPaperclipStatus());\n } catch (err) {\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n router.post('/start', async (_req, res) => {\n try {\n await startPaperclip({ enabled: true, port: PAPERCLIP_PORT, autoStart: true }, titanEvents);\n res.json({ ok: true });\n } catch (err) {\n logger.error(COMPONENT, `Paperclip start failed: ${(err as Error).message}`);\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n router.post('/stop', async (_req, res) => {\n try {\n await stopPaperclip();\n res.json({ ok: true });\n } catch (err) {\n logger.error(COMPONENT, `Paperclip stop failed: ${(err as Error).message}`);\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n router.post('/reset', async (_req, res) => {\n try {\n await stopPaperclip();\n await startPaperclip({ enabled: true, port: PAPERCLIP_PORT, autoStart: true }, titanEvents);\n res.json({ ok: true });\n } catch (err) {\n logger.error(COMPONENT, `Paperclip reset failed: ${(err as Error).message}`);\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // ── API proxy (/api/paperclip/* → http://localhost:3100/api/*) ──\n\n router.all('/*', async (req: Request, res: Response) => {\n const targetPath = req.path.replace(/^\\/api\\/paperclip/, '/api');\n const query = req.url.includes('?') ? '?' + req.url.split('?')[1] : '';\n const targetUrl = `http://localhost:${PAPERCLIP_PORT}${targetPath}${query}`;\n\n try {\n const headers = new Headers();\n for (const [k, v] of Object.entries(req.headers)) {\n if (v && k.toLowerCase() !== 'host') headers.set(k, Array.isArray(v) ? v[0] : v);\n }\n\n const upstream = await fetch(targetUrl, {\n method: req.method,\n headers: headers as any,\n body: ['GET', 'HEAD'].includes(req.method) ? undefined : JSON.stringify(req.body),\n });\n\n res.status(upstream.status);\n upstream.headers.forEach((v, k) => res.setHeader(k, v));\n const body = await upstream.arrayBuffer();\n res.end(Buffer.from(body));\n } catch (err) {\n logger.error(COMPONENT, `Paperclip API proxy error: ${(err as Error).message}`);\n res.status(502).json({ error: 'Paperclip API proxy error', message: (err as Error).message });\n }\n });\n\n return router;\n}\n\n// ── Web UI proxy (/paperclip/* → http://localhost:3100/*) ──\n\nexport function createPaperclipUIRouter(): Router {\n const router = Router();\n\n router.all('/*', async (req: Request, res: Response) => {\n const targetPath = req.path.replace(/^\\/paperclip/, '') || '/';\n const query = req.url.includes('?') ? '?' + req.url.split('?')[1] : '';\n const targetUrl = `http://localhost:${PAPERCLIP_PORT}${targetPath}${query}`;\n\n try {\n const headers = new Headers();\n for (const [k, v] of Object.entries(req.headers)) {\n if (v && k.toLowerCase() !== 'host') headers.set(k, Array.isArray(v) ? v[0] : v);\n }\n\n const upstream = await fetch(targetUrl, {\n method: req.method,\n headers: headers as any,\n body: ['GET', 'HEAD'].includes(req.method) ? undefined : JSON.stringify(req.body),\n });\n\n res.status(upstream.status);\n upstream.headers.forEach((v, k) => res.setHeader(k, v));\n const body = await upstream.arrayBuffer();\n res.end(Buffer.from(body));\n } catch (err) {\n logger.error(COMPONENT, `Paperclip UI proxy error: ${(err as Error).message}`);\n res.status(502).json({ error: 'Paperclip UI proxy error', message: (err as Error).message });\n }\n });\n\n return router;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Router } from "express";
|
|
3
|
+
import logger from "../../utils/logger.js";
|
|
4
|
+
import { listSessions, closeSession, renameSession, sweepSessions } from "../../agent/session.js";
|
|
5
|
+
import { getHistory } from "../../memory/memory.js";
|
|
6
|
+
const COMPONENT = "SessionsRouter";
|
|
7
|
+
function createSessionsRouter(sessionAborts) {
|
|
8
|
+
const router = Router();
|
|
9
|
+
router.get("/", (_req, res) => {
|
|
10
|
+
const sessions = listSessions();
|
|
11
|
+
res.json(sessions);
|
|
12
|
+
});
|
|
13
|
+
router.post("/", async (req, res) => {
|
|
14
|
+
try {
|
|
15
|
+
const { createNewSession } = await import("../../agent/session.js");
|
|
16
|
+
const channel = req.body?.channel || "webchat";
|
|
17
|
+
const userId = req.body?.userId || "api-user";
|
|
18
|
+
const session = createNewSession(channel, userId);
|
|
19
|
+
res.json({ id: session.id, channel: session.channel, userId: session.userId });
|
|
20
|
+
} catch (e) {
|
|
21
|
+
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
22
|
+
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
router.get("/search", (req, res) => {
|
|
26
|
+
const query = (req.query.q || "").toLowerCase().trim();
|
|
27
|
+
if (!query || query.length < 2) {
|
|
28
|
+
res.status(400).json({ error: "Query must be at least 2 characters" });
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
const sessions = listSessions();
|
|
33
|
+
const results = [];
|
|
34
|
+
const limit = parseInt(req.query.limit) || 50;
|
|
35
|
+
for (const session of sessions) {
|
|
36
|
+
const history = getHistory(session.id, 1e3);
|
|
37
|
+
for (const msg of history) {
|
|
38
|
+
if (msg.content.toLowerCase().includes(query)) {
|
|
39
|
+
results.push({
|
|
40
|
+
sessionId: session.id,
|
|
41
|
+
sessionName: session.name || session.id.slice(0, 8),
|
|
42
|
+
role: msg.role,
|
|
43
|
+
content: msg.content.slice(0, 200),
|
|
44
|
+
timestamp: msg.createdAt || ""
|
|
45
|
+
});
|
|
46
|
+
if (results.length >= limit) break;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (results.length >= limit) break;
|
|
50
|
+
}
|
|
51
|
+
res.json({ query, results, total: results.length });
|
|
52
|
+
} catch (err) {
|
|
53
|
+
res.status(500).json({ error: err.message });
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
router.get("/:id/export", (req, res) => {
|
|
57
|
+
const sessionId = req.params.id;
|
|
58
|
+
const format = req.query.format || "json";
|
|
59
|
+
try {
|
|
60
|
+
const history = getHistory(sessionId, 1e4);
|
|
61
|
+
if (!history || history.length === 0) {
|
|
62
|
+
res.status(404).json({ error: "Session not found or empty" });
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (format === "markdown" || format === "md") {
|
|
66
|
+
const sessions = listSessions();
|
|
67
|
+
const session = sessions.find((s) => s.id === sessionId);
|
|
68
|
+
const title = session?.name || sessionId.slice(0, 8);
|
|
69
|
+
let md = `# ${title}
|
|
70
|
+
|
|
71
|
+
Exported: ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
`;
|
|
76
|
+
for (const msg of history) {
|
|
77
|
+
const role = msg.role === "user" ? "**You**" : "**TITAN**";
|
|
78
|
+
md += `${role} (${msg.createdAt || ""}):
|
|
79
|
+
|
|
80
|
+
${msg.content}
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
`;
|
|
85
|
+
}
|
|
86
|
+
res.setHeader("Content-Type", "text/markdown");
|
|
87
|
+
res.setHeader("Content-Disposition", `attachment; filename="titan-${sessionId.slice(0, 8)}.md"`);
|
|
88
|
+
res.send(md);
|
|
89
|
+
} else {
|
|
90
|
+
res.setHeader("Content-Type", "application/json");
|
|
91
|
+
res.setHeader("Content-Disposition", `attachment; filename="titan-${sessionId.slice(0, 8)}.json"`);
|
|
92
|
+
res.json({ sessionId, exportedAt: (/* @__PURE__ */ new Date()).toISOString(), messages: history });
|
|
93
|
+
}
|
|
94
|
+
} catch (err) {
|
|
95
|
+
res.status(500).json({ error: err.message });
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
router.get("/:id", (req, res) => {
|
|
99
|
+
try {
|
|
100
|
+
const history = getHistory(req.params.id);
|
|
101
|
+
res.json(history);
|
|
102
|
+
} catch (e) {
|
|
103
|
+
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
104
|
+
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
router.get("/:id/messages", (req, res) => {
|
|
108
|
+
try {
|
|
109
|
+
const history = getHistory(req.params.id);
|
|
110
|
+
const messages = Array.isArray(history) ? history : history.messages || [];
|
|
111
|
+
if (messages.length === 0) {
|
|
112
|
+
const allSessions = listSessions();
|
|
113
|
+
const sessionExists = allSessions.some((s) => s.id === req.params.id);
|
|
114
|
+
if (!sessionExists) {
|
|
115
|
+
res.status(404).json({ error: "Session not found" });
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
res.json(messages);
|
|
120
|
+
} catch (e) {
|
|
121
|
+
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
122
|
+
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
router.post("/:id/close", (req, res) => {
|
|
126
|
+
try {
|
|
127
|
+
closeSession(req.params.id);
|
|
128
|
+
res.json({ ok: true });
|
|
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.delete("/:id", (req, res) => {
|
|
135
|
+
try {
|
|
136
|
+
closeSession(req.params.id);
|
|
137
|
+
res.json({ ok: true });
|
|
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("/sweep", (req, res) => {
|
|
144
|
+
try {
|
|
145
|
+
const { channel, channelPrefix, idleMs, force } = req.body ?? {};
|
|
146
|
+
const opts = {};
|
|
147
|
+
if (typeof channel === "string" && channel.length <= 64) opts.channel = channel;
|
|
148
|
+
if (typeof channelPrefix === "string" && channelPrefix.length <= 64) opts.channelPrefix = channelPrefix;
|
|
149
|
+
if (typeof idleMs === "number" && Number.isFinite(idleMs) && idleMs >= 0) opts.idleMs = idleMs;
|
|
150
|
+
if (typeof force === "boolean") opts.force = force;
|
|
151
|
+
const result = sweepSessions(opts);
|
|
152
|
+
res.json({ ok: true, ...result });
|
|
153
|
+
} catch (e) {
|
|
154
|
+
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
155
|
+
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
router.patch("/:id", (req, res) => {
|
|
159
|
+
try {
|
|
160
|
+
const { name } = req.body;
|
|
161
|
+
if (!name || typeof name !== "string") {
|
|
162
|
+
res.status(400).json({ error: "name is required" });
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const ok = renameSession(req.params.id, name);
|
|
166
|
+
if (!ok) {
|
|
167
|
+
res.status(404).json({ error: "Session not found" });
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
res.json({ ok: true });
|
|
171
|
+
} catch (e) {
|
|
172
|
+
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
173
|
+
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
router.post("/:id/steer", async (req, res) => {
|
|
177
|
+
try {
|
|
178
|
+
const { message } = req.body;
|
|
179
|
+
if (!message || typeof message !== "string") {
|
|
180
|
+
res.status(400).json({ error: "message is required" });
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
const { pushSteer } = await import("../../agent/agentLoop.js");
|
|
184
|
+
pushSteer(req.params.id, message);
|
|
185
|
+
res.json({ ok: true, sessionId: req.params.id });
|
|
186
|
+
} catch (e) {
|
|
187
|
+
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
188
|
+
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
router.get("/:id/checkpoints", async (req, res) => {
|
|
192
|
+
try {
|
|
193
|
+
const { listCheckpoints } = await import("../../checkpoint/manager.js");
|
|
194
|
+
const checkpoints = listCheckpoints(req.params.id);
|
|
195
|
+
res.json({ checkpoints });
|
|
196
|
+
} catch (e) {
|
|
197
|
+
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
198
|
+
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
router.post("/:id/checkpoints/:checkpointId/restore", async (req, res) => {
|
|
202
|
+
try {
|
|
203
|
+
const { restoreCheckpoint } = await import("../../checkpoint/manager.js");
|
|
204
|
+
const result = restoreCheckpoint(req.params.id, req.params.checkpointId);
|
|
205
|
+
res.json({ ok: result.success, restored: result.restored, errors: result.errors });
|
|
206
|
+
} catch (e) {
|
|
207
|
+
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
208
|
+
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
router.post("/:id/abort", (req, res) => {
|
|
212
|
+
const { id } = req.params;
|
|
213
|
+
const controller = sessionAborts.get(id);
|
|
214
|
+
if (controller) {
|
|
215
|
+
controller.abort();
|
|
216
|
+
sessionAborts.delete(id);
|
|
217
|
+
res.json({ ok: true, message: "Session aborted" });
|
|
218
|
+
} else {
|
|
219
|
+
res.json({ ok: true, message: "No active session to abort" });
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
return router;
|
|
223
|
+
}
|
|
224
|
+
export {
|
|
225
|
+
createSessionsRouter
|
|
226
|
+
};
|
|
227
|
+
//# sourceMappingURL=sessions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/gateway/routes/sessions.ts"],"sourcesContent":["/**\n * Sessions Router\n *\n * Extracted from gateway/server.ts v5.5.0.\n */\n\nimport { Router } from 'express';\nimport { homedir } from 'os';\nimport { dirname, join } from 'path';\nimport fs from 'fs';\nimport logger from '../../utils/logger.js';\nimport { listSessions, closeSession, renameSession, sweepSessions } from '../../agent/session.js';\nimport { getHistory } from '../../memory/memory.js';\n\nconst COMPONENT = 'SessionsRouter';\n\nexport function createSessionsRouter(sessionAborts: Map<string, AbortController>): Router {\n const router = Router();\n\n router.get('/', (_req, res) => {\n const sessions = listSessions();\n res.json(sessions);\n });\n\n // Create a new session explicitly\n router.post('/', async (req, res) => {\n try {\n const { createNewSession } = await import('../../agent/session.js');\n const channel = req.body?.channel || 'webchat';\n const userId = req.body?.userId || 'api-user';\n const session = createNewSession(channel, userId);\n res.json({ id: session.id, channel: session.channel, userId: session.userId });\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 // Conversation search — full-text search across all sessions\n router.get('/search', (req, res) => {\n const query = (req.query.q as string || '').toLowerCase().trim();\n if (!query || query.length < 2) { res.status(400).json({ error: 'Query must be at least 2 characters' }); return; }\n try {\n const sessions = listSessions();\n const results: Array<{ sessionId: string; sessionName: string; role: string; content: string; timestamp: string }> = [];\n const limit = parseInt(req.query.limit as string) || 50;\n\n for (const session of sessions) {\n const history = getHistory(session.id, 1000);\n for (const msg of history as Array<{ content: string; role: string; createdAt?: string }>) {\n if (msg.content.toLowerCase().includes(query)) {\n results.push({\n sessionId: session.id,\n sessionName: (session as { name?: string }).name || session.id.slice(0, 8),\n role: msg.role,\n content: msg.content.slice(0, 200),\n timestamp: msg.createdAt || '',\n });\n if (results.length >= limit) break;\n }\n }\n if (results.length >= limit) break;\n }\n res.json({ query, results, total: results.length });\n } catch (err) {\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // Conversation export\n router.get('/:id/export', (req, res) => {\n const sessionId = req.params.id;\n const format = (req.query.format as string) || 'json';\n try {\n const history = getHistory(sessionId, 10000);\n if (!history || (history as unknown[]).length === 0) { res.status(404).json({ error: 'Session not found or empty' }); return; }\n\n if (format === 'markdown' || format === 'md') {\n const sessions = listSessions();\n const session = sessions.find(s => s.id === sessionId);\n const title = (session as { name?: string })?.name || sessionId.slice(0, 8);\n let md = `# ${title}\\n\\nExported: ${new Date().toISOString()}\\n\\n---\\n\\n`;\n for (const msg of history as Array<{ role: string; content: string; createdAt?: string }>) {\n const role = msg.role === 'user' ? '**You**' : '**TITAN**';\n md += `${role} (${msg.createdAt || ''}):\\n\\n${msg.content}\\n\\n---\\n\\n`;\n }\n res.setHeader('Content-Type', 'text/markdown');\n res.setHeader('Content-Disposition', `attachment; filename=\"titan-${sessionId.slice(0, 8)}.md\"`);\n res.send(md);\n } else {\n res.setHeader('Content-Type', 'application/json');\n res.setHeader('Content-Disposition', `attachment; filename=\"titan-${sessionId.slice(0, 8)}.json\"`);\n res.json({ sessionId, exportedAt: new Date().toISOString(), messages: history });\n }\n } catch (err) {\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n router.get('/:id', (req, res) => {\n try {\n const history = getHistory(req.params.id);\n res.json(history);\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.get('/:id/messages', (req, res) => {\n try {\n const history = getHistory(req.params.id);\n const messages = Array.isArray(history) ? history : ((history as Record<string, unknown>).messages || []);\n if ((messages as unknown[]).length === 0) {\n const allSessions = listSessions();\n const sessionExists = allSessions.some(s => s.id === req.params.id);\n if (!sessionExists) { res.status(404).json({ error: 'Session not found' }); return; }\n }\n res.json(messages);\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.post('/:id/close', (req, res) => {\n try {\n closeSession(req.params.id);\n res.json({ ok: true });\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.delete('/:id', (req, res) => {\n try {\n closeSession(req.params.id);\n res.json({ ok: true });\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.post('/sweep', (req, res) => {\n try {\n const { channel, channelPrefix, idleMs, force } = (req.body ?? {}) as {\n channel?: unknown; channelPrefix?: unknown; idleMs?: unknown; force?: unknown;\n };\n const opts: Parameters<typeof sweepSessions>[0] = {};\n if (typeof channel === 'string' && channel.length <= 64) opts.channel = channel;\n if (typeof channelPrefix === 'string' && channelPrefix.length <= 64) opts.channelPrefix = channelPrefix;\n if (typeof idleMs === 'number' && Number.isFinite(idleMs) && idleMs >= 0) opts.idleMs = idleMs;\n if (typeof force === 'boolean') opts.force = force;\n const result = sweepSessions(opts);\n res.json({ ok: true, ...result });\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('/:id', (req, res) => {\n try {\n const { name } = req.body as { name?: string };\n if (!name || typeof name !== 'string') { res.status(400).json({ error: 'name is required' }); return; }\n const ok = renameSession(req.params.id, name);\n if (!ok) { res.status(404).json({ error: 'Session not found' }); return; }\n res.json({ ok: true });\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 // v5.0: Steer\n router.post('/:id/steer', async (req, res) => {\n try {\n const { message } = req.body as { message?: string };\n if (!message || typeof message !== 'string') { res.status(400).json({ error: 'message is required' }); return; }\n const { pushSteer } = await import('../../agent/agentLoop.js');\n pushSteer(req.params.id, message);\n res.json({ ok: true, sessionId: req.params.id });\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 // v5.0: Checkpoints\n router.get('/:id/checkpoints', async (req, res) => {\n try {\n const { listCheckpoints } = await import('../../checkpoint/manager.js');\n const checkpoints = listCheckpoints(req.params.id);\n res.json({ checkpoints });\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.post('/:id/checkpoints/:checkpointId/restore', async (req, res) => {\n try {\n const { restoreCheckpoint } = await import('../../checkpoint/manager.js');\n const result = restoreCheckpoint(req.params.id, req.params.checkpointId);\n res.json({ ok: result.success, restored: result.restored, errors: result.errors });\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 // v5.0: Abort\n router.post('/:id/abort', (req, res) => {\n const { id } = req.params;\n const controller = sessionAborts.get(id);\n if (controller) {\n controller.abort();\n sessionAborts.delete(id);\n res.json({ ok: true, message: 'Session aborted' });\n } else {\n res.json({ ok: true, message: 'No active session to abort' });\n }\n });\n\n return router;\n}\n"],"mappings":";AAMA,SAAS,cAAc;AAIvB,OAAO,YAAY;AACnB,SAAS,cAAc,cAAc,eAAe,qBAAqB;AACzE,SAAS,kBAAkB;AAE3B,MAAM,YAAY;AAEX,SAAS,qBAAqB,eAAqD;AACxF,QAAM,SAAS,OAAO;AAEtB,SAAO,IAAI,KAAK,CAAC,MAAM,QAAQ;AAC7B,UAAM,WAAW,aAAa;AAC9B,QAAI,KAAK,QAAQ;AAAA,EACnB,CAAC;AAGD,SAAO,KAAK,KAAK,OAAO,KAAK,QAAQ;AACnC,QAAI;AACF,YAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,wBAAwB;AAClE,YAAM,UAAU,IAAI,MAAM,WAAW;AACrC,YAAM,SAAS,IAAI,MAAM,UAAU;AACnC,YAAM,UAAU,iBAAiB,SAAS,MAAM;AAChD,UAAI,KAAK,EAAE,IAAI,QAAQ,IAAI,SAAS,QAAQ,SAAS,QAAQ,QAAQ,OAAO,CAAC;AAAA,IAC/E,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,mBAAoB,EAAY,OAAO,EAAE;AAAG,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,iEAAiE,CAAC;AAAA,IACtK;AAAA,EACF,CAAC;AAGD,SAAO,IAAI,WAAW,CAAC,KAAK,QAAQ;AAClC,UAAM,SAAS,IAAI,MAAM,KAAe,IAAI,YAAY,EAAE,KAAK;AAC/D,QAAI,CAAC,SAAS,MAAM,SAAS,GAAG;AAAE,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,sCAAsC,CAAC;AAAG;AAAA,IAAQ;AAClH,QAAI;AACF,YAAM,WAAW,aAAa;AAC9B,YAAM,UAA+G,CAAC;AACtH,YAAM,QAAQ,SAAS,IAAI,MAAM,KAAe,KAAK;AAErD,iBAAW,WAAW,UAAU;AAC9B,cAAM,UAAU,WAAW,QAAQ,IAAI,GAAI;AAC3C,mBAAW,OAAO,SAAyE;AACzF,cAAI,IAAI,QAAQ,YAAY,EAAE,SAAS,KAAK,GAAG;AAC7C,oBAAQ,KAAK;AAAA,cACX,WAAW,QAAQ;AAAA,cACnB,aAAc,QAA8B,QAAQ,QAAQ,GAAG,MAAM,GAAG,CAAC;AAAA,cACzE,MAAM,IAAI;AAAA,cACV,SAAS,IAAI,QAAQ,MAAM,GAAG,GAAG;AAAA,cACjC,WAAW,IAAI,aAAa;AAAA,YAC9B,CAAC;AACD,gBAAI,QAAQ,UAAU,MAAO;AAAA,UAC/B;AAAA,QACF;AACA,YAAI,QAAQ,UAAU,MAAO;AAAA,MAC/B;AACA,UAAI,KAAK,EAAE,OAAO,SAAS,OAAO,QAAQ,OAAO,CAAC;AAAA,IACpD,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAQ,IAAc,QAAQ,CAAC;AAAA,IACxD;AAAA,EACF,CAAC;AAGD,SAAO,IAAI,eAAe,CAAC,KAAK,QAAQ;AACtC,UAAM,YAAY,IAAI,OAAO;AAC7B,UAAM,SAAU,IAAI,MAAM,UAAqB;AAC/C,QAAI;AACF,YAAM,UAAU,WAAW,WAAW,GAAK;AAC3C,UAAI,CAAC,WAAY,QAAsB,WAAW,GAAG;AAAE,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,6BAA6B,CAAC;AAAG;AAAA,MAAQ;AAE9H,UAAI,WAAW,cAAc,WAAW,MAAM;AAC5C,cAAM,WAAW,aAAa;AAC9B,cAAM,UAAU,SAAS,KAAK,OAAK,EAAE,OAAO,SAAS;AACrD,cAAM,QAAS,SAA+B,QAAQ,UAAU,MAAM,GAAG,CAAC;AAC1E,YAAI,KAAK,KAAK,KAAK;AAAA;AAAA,aAAiB,oBAAI,KAAK,GAAE,YAAY,CAAC;AAAA;AAAA;AAAA;AAAA;AAC5D,mBAAW,OAAO,SAAyE;AACzF,gBAAM,OAAO,IAAI,SAAS,SAAS,YAAY;AAC/C,gBAAM,GAAG,IAAI,KAAK,IAAI,aAAa,EAAE;AAAA;AAAA,EAAS,IAAI,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA,QAC3D;AACA,YAAI,UAAU,gBAAgB,eAAe;AAC7C,YAAI,UAAU,uBAAuB,+BAA+B,UAAU,MAAM,GAAG,CAAC,CAAC,MAAM;AAC/F,YAAI,KAAK,EAAE;AAAA,MACb,OAAO;AACL,YAAI,UAAU,gBAAgB,kBAAkB;AAChD,YAAI,UAAU,uBAAuB,+BAA+B,UAAU,MAAM,GAAG,CAAC,CAAC,QAAQ;AACjG,YAAI,KAAK,EAAE,WAAW,aAAY,oBAAI,KAAK,GAAE,YAAY,GAAG,UAAU,QAAQ,CAAC;AAAA,MACjF;AAAA,IACF,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAQ,IAAc,QAAQ,CAAC;AAAA,IACxD;AAAA,EACF,CAAC;AAED,SAAO,IAAI,QAAQ,CAAC,KAAK,QAAQ;AAC/B,QAAI;AACF,YAAM,UAAU,WAAW,IAAI,OAAO,EAAE;AACxC,UAAI,KAAK,OAAO;AAAA,IAClB,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,mBAAoB,EAAY,OAAO,EAAE;AAAG,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,iEAAiE,CAAC;AAAA,IACtK;AAAA,EACF,CAAC;AAED,SAAO,IAAI,iBAAiB,CAAC,KAAK,QAAQ;AACxC,QAAI;AACF,YAAM,UAAU,WAAW,IAAI,OAAO,EAAE;AACxC,YAAM,WAAW,MAAM,QAAQ,OAAO,IAAI,UAAY,QAAoC,YAAY,CAAC;AACvG,UAAK,SAAuB,WAAW,GAAG;AACxC,cAAM,cAAc,aAAa;AACjC,cAAM,gBAAgB,YAAY,KAAK,OAAK,EAAE,OAAO,IAAI,OAAO,EAAE;AAClE,YAAI,CAAC,eAAe;AAAE,cAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,oBAAoB,CAAC;AAAG;AAAA,QAAQ;AAAA,MACtF;AACA,UAAI,KAAK,QAAQ;AAAA,IACnB,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,mBAAoB,EAAY,OAAO,EAAE;AAAG,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,iEAAiE,CAAC;AAAA,IACtK;AAAA,EACF,CAAC;AAED,SAAO,KAAK,cAAc,CAAC,KAAK,QAAQ;AACtC,QAAI;AACF,mBAAa,IAAI,OAAO,EAAE;AAC1B,UAAI,KAAK,EAAE,IAAI,KAAK,CAAC;AAAA,IACvB,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,mBAAoB,EAAY,OAAO,EAAE;AAAG,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,iEAAiE,CAAC;AAAA,IACtK;AAAA,EACF,CAAC;AAED,SAAO,OAAO,QAAQ,CAAC,KAAK,QAAQ;AAClC,QAAI;AACF,mBAAa,IAAI,OAAO,EAAE;AAC1B,UAAI,KAAK,EAAE,IAAI,KAAK,CAAC;AAAA,IACvB,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,mBAAoB,EAAY,OAAO,EAAE;AAAG,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,iEAAiE,CAAC;AAAA,IACtK;AAAA,EACF,CAAC;AAED,SAAO,KAAK,UAAU,CAAC,KAAK,QAAQ;AAClC,QAAI;AACF,YAAM,EAAE,SAAS,eAAe,QAAQ,MAAM,IAAK,IAAI,QAAQ,CAAC;AAGhE,YAAM,OAA4C,CAAC;AACnD,UAAI,OAAO,YAAY,YAAY,QAAQ,UAAU,GAAI,MAAK,UAAU;AACxE,UAAI,OAAO,kBAAkB,YAAY,cAAc,UAAU,GAAI,MAAK,gBAAgB;AAC1F,UAAI,OAAO,WAAW,YAAY,OAAO,SAAS,MAAM,KAAK,UAAU,EAAG,MAAK,SAAS;AACxF,UAAI,OAAO,UAAU,UAAW,MAAK,QAAQ;AAC7C,YAAM,SAAS,cAAc,IAAI;AACjC,UAAI,KAAK,EAAE,IAAI,MAAM,GAAG,OAAO,CAAC;AAAA,IAClC,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,mBAAoB,EAAY,OAAO,EAAE;AAAG,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,iEAAiE,CAAC;AAAA,IACtK;AAAA,EACF,CAAC;AAED,SAAO,MAAM,QAAQ,CAAC,KAAK,QAAQ;AACjC,QAAI;AACF,YAAM,EAAE,KAAK,IAAI,IAAI;AACrB,UAAI,CAAC,QAAQ,OAAO,SAAS,UAAU;AAAE,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,mBAAmB,CAAC;AAAG;AAAA,MAAQ;AACtG,YAAM,KAAK,cAAc,IAAI,OAAO,IAAI,IAAI;AAC5C,UAAI,CAAC,IAAI;AAAE,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,oBAAoB,CAAC;AAAG;AAAA,MAAQ;AACzE,UAAI,KAAK,EAAE,IAAI,KAAK,CAAC;AAAA,IACvB,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,mBAAoB,EAAY,OAAO,EAAE;AAAG,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,iEAAiE,CAAC;AAAA,IACtK;AAAA,EACF,CAAC;AAGD,SAAO,KAAK,cAAc,OAAO,KAAK,QAAQ;AAC5C,QAAI;AACF,YAAM,EAAE,QAAQ,IAAI,IAAI;AACxB,UAAI,CAAC,WAAW,OAAO,YAAY,UAAU;AAAE,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,sBAAsB,CAAC;AAAG;AAAA,MAAQ;AAC/G,YAAM,EAAE,UAAU,IAAI,MAAM,OAAO,0BAA0B;AAC7D,gBAAU,IAAI,OAAO,IAAI,OAAO;AAChC,UAAI,KAAK,EAAE,IAAI,MAAM,WAAW,IAAI,OAAO,GAAG,CAAC;AAAA,IACjD,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,mBAAoB,EAAY,OAAO,EAAE;AAAG,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,iEAAiE,CAAC;AAAA,IACtK;AAAA,EACF,CAAC;AAGD,SAAO,IAAI,oBAAoB,OAAO,KAAK,QAAQ;AACjD,QAAI;AACF,YAAM,EAAE,gBAAgB,IAAI,MAAM,OAAO,6BAA6B;AACtE,YAAM,cAAc,gBAAgB,IAAI,OAAO,EAAE;AACjD,UAAI,KAAK,EAAE,YAAY,CAAC;AAAA,IAC1B,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,mBAAoB,EAAY,OAAO,EAAE;AAAG,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,iEAAiE,CAAC;AAAA,IACtK;AAAA,EACF,CAAC;AAED,SAAO,KAAK,0CAA0C,OAAO,KAAK,QAAQ;AACxE,QAAI;AACF,YAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,6BAA6B;AACxE,YAAM,SAAS,kBAAkB,IAAI,OAAO,IAAI,IAAI,OAAO,YAAY;AACvE,UAAI,KAAK,EAAE,IAAI,OAAO,SAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,OAAO,CAAC;AAAA,IACnF,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,mBAAoB,EAAY,OAAO,EAAE;AAAG,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,iEAAiE,CAAC;AAAA,IACtK;AAAA,EACF,CAAC;AAGD,SAAO,KAAK,cAAc,CAAC,KAAK,QAAQ;AACtC,UAAM,EAAE,GAAG,IAAI,IAAI;AACnB,UAAM,aAAa,cAAc,IAAI,EAAE;AACvC,QAAI,YAAY;AACd,iBAAW,MAAM;AACjB,oBAAc,OAAO,EAAE;AACvB,UAAI,KAAK,EAAE,IAAI,MAAM,SAAS,kBAAkB,CAAC;AAAA,IACnD,OAAO;AACL,UAAI,KAAK,EAAE,IAAI,MAAM,SAAS,6BAA6B,CAAC;AAAA,IAC9D;AAAA,EACF,CAAC;AAED,SAAO;AACT;","names":[]}
|