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/commandPost.ts"],"sourcesContent":["/**\n * Command Post Router\n *\n * Extracted from gateway/server.ts v5.4.5 → v5.5.0.\n * Consolidates all /api/command-post/* routes for agent governance.\n */\n\nimport { Router, type Request, type Response } from 'express';\nimport logger from '../../utils/logger.js';\n\n// Command Post core\nimport {\n getDashboard as getCPDashboard,\n getRegisteredAgents,\n reportHeartbeat,\n removeAgent,\n checkoutTask,\n checkinTask,\n getActiveCheckouts,\n getBudgetPolicies,\n createBudgetPolicy,\n updateBudgetPolicy,\n deleteBudgetPolicy,\n getActivity,\n getGoalTree,\n getAncestryChain,\n validateGoalAncestry,\n validateGoalParentAssignment,\n sweepExpiredCheckoutsManual,\n getStaleAgents,\n enforceBudgetForAgent,\n getBudgetPolicyForAgent,\n createIssue,\n updateIssue,\n getIssue,\n listIssues,\n searchIssues,\n checkoutIssue,\n deleteIssue,\n addIssueComment,\n getIssueComments,\n createApproval,\n approveApproval,\n rejectApproval,\n listApprovals,\n getApproval,\n replyToApproval,\n snoozeApproval,\n unsnoozeApproval,\n batchApprove,\n batchReject,\n getAgentMessages,\n markAgentMessageRead,\n startRun,\n endRun,\n listRuns,\n getOrgTree,\n updateRegisteredAgent,\n} from '../../agent/commandPost.js';\n\n// Agent wakeup\nimport {\n getAgentInbox,\n queueWakeup,\n getWakeupRequest,\n cancelWakeup,\n drainPendingResults,\n} from '../../agent/agentWakeup.js';\n\n// Daemon events (for SSE)\nimport { titanEvents } from '../../agent/daemon.js';\n\n// Goals\nimport { createGoal } from '../../agent/goals.js';\n\nconst COMPONENT = 'CommandPostRouter';\n\nexport function createCommandPostRouter(): Router {\n const router = Router();\n\n // ── Dashboard ─────────────────────────────────────────────\n router.get('/dashboard', async (_req, res) => {\n const dashboard = getCPDashboard();\n try {\n const { listCompanies, getActiveRunners } = await import('../../agent/company.js');\n const companies = listCompanies();\n const runners = getActiveRunners();\n (dashboard as Record<string, unknown>).companies = companies.map(c => ({\n ...c,\n runnerActive: runners.includes(c.id),\n }));\n } catch { (dashboard as Record<string, unknown>).companies = []; }\n res.json(dashboard);\n });\n\n // ── Agents ──────────────────────────────────────────────────\n router.get('/agents', (_req, res) => {\n res.json(getRegisteredAgents());\n });\n\n router.post('/agents/:id/heartbeat', (req, res) => {\n const ok = reportHeartbeat(req.params.id);\n res.json({ success: ok });\n });\n\n router.post('/agents/:id/fire', async (req, res) => {\n try {\n const { fireHeartbeat } = await import('../../agent/heartbeatScheduler.js');\n await fireHeartbeat(req.params.id);\n res.json({ success: true });\n } catch (err) {\n res.status(500).json({ success: false, error: (err as Error).message });\n }\n });\n\n router.delete('/agents/:id', (req, res) => {\n const ok = removeAgent(req.params.id);\n if (!ok) { res.status(400).json({ error: 'Cannot remove agent (not found or is the primary agent)' }); return; }\n res.json({ success: true });\n });\n\n router.patch('/agents/:id', async (req, res) => {\n const { reportsTo, role, title, name, status, model } = req.body;\n const updated = updateRegisteredAgent(req.params.id, { reportsTo, role, title, name, model });\n if (!updated) { res.status(404).json({ error: 'Agent not found' }); return; }\n if (status && typeof status === 'string') {\n try {\n const { updateAgentStatus } = await import('../../agent/commandPost.js');\n updateAgentStatus(req.params.id, status as 'active' | 'idle' | 'paused' | 'error' | 'stopped');\n } catch { /* ok */ }\n }\n res.json(updated);\n });\n\n router.patch('/agents/:id/identity', async (req, res) => {\n const { voiceId, personaId, systemPromptOverride, memoryNamespace, characterSummary, model } = req.body || {};\n const coerce = (v: unknown): string | null | undefined => {\n if (v === null) return null;\n if (typeof v === 'string') return v;\n if (v === undefined) return undefined;\n res.status(400).json({ error: `Invalid identity field: expected string or null, got ${typeof v}` });\n return undefined;\n };\n if (res.headersSent) return;\n const { updateAgentIdentity } = await import('../../agent/commandPost.js');\n const updated = updateAgentIdentity(req.params.id, {\n voiceId: coerce(voiceId),\n personaId: coerce(personaId),\n systemPromptOverride: coerce(systemPromptOverride),\n memoryNamespace: coerce(memoryNamespace),\n characterSummary: coerce(characterSummary),\n model: coerce(model),\n });\n if (res.headersSent) return;\n if (!updated) { res.status(404).json({ error: 'Agent not found' }); return; }\n res.json(updated);\n });\n\n router.get('/agents/stale', (_req, res) => {\n const stale = getStaleAgents();\n res.json({ stale, total: stale.length });\n });\n\n // ── Tasks (checkout/checkin) ────────────────────────────────\n router.post('/tasks/:goalId/:subtaskId/checkout', (req, res) => {\n const agentId = (req.body as { agentId?: string }).agentId || 'manual';\n const lock = checkoutTask(req.params.goalId, req.params.subtaskId, agentId);\n if (!lock) { res.status(409).json({ error: 'Task already checked out by another agent' }); return; }\n res.json(lock);\n });\n\n router.post('/tasks/:goalId/:subtaskId/checkin', (req, res) => {\n const runId = (req.body as { runId?: string }).runId || '';\n const ok = checkinTask(req.params.subtaskId, runId);\n if (!ok) { res.status(404).json({ error: 'No matching checkout found' }); return; }\n res.json({ success: true });\n });\n\n // ── Checkouts ───────────────────────────────────────────────\n router.get('/checkouts', (_req, res) => {\n res.json(getActiveCheckouts());\n });\n\n router.post('/checkouts/sweep', (_req, res) => {\n const result = sweepExpiredCheckoutsManual();\n res.json(result);\n });\n\n router.get('/checkouts/expired', (_req, res) => {\n const result = sweepExpiredCheckoutsManual();\n res.json({ expired: result.swept, details: result.details });\n });\n\n // ── Budgets ─────────────────────────────────────────────────\n router.get('/budgets', (_req, res) => {\n res.json(getBudgetPolicies());\n });\n\n router.get('/budgets/reservations', (_req, res) => {\n res.json([]);\n });\n\n router.post('/budgets', (req, res) => {\n try {\n const body = req.body as {\n name: string;\n scope: { type: 'agent' | 'goal' | 'global'; targetId?: string };\n period: 'daily' | 'weekly' | 'monthly';\n limitUsd: number;\n warningThresholdPercent?: number;\n action?: 'warn' | 'pause' | 'stop';\n enabled?: boolean;\n };\n const policy = createBudgetPolicy({\n name: body.name,\n scope: body.scope,\n period: body.period,\n limitUsd: body.limitUsd,\n warningThresholdPercent: body.warningThresholdPercent ?? 80,\n action: body.action ?? 'pause',\n enabled: body.enabled ?? true,\n });\n res.status(201).json(policy);\n } catch (err) {\n res.status(400).json({ error: (err as Error).message });\n }\n });\n\n router.put('/budgets/:id', (req, res) => {\n const updated = updateBudgetPolicy(req.params.id, req.body as Record<string, unknown>);\n if (!updated) { res.status(404).json({ error: 'Budget policy not found' }); return; }\n res.json(updated);\n });\n\n router.delete('/budgets/:id', (req, res) => {\n const ok = deleteBudgetPolicy(req.params.id);\n if (!ok) { res.status(404).json({ error: 'Budget policy not found' }); return; }\n res.json({ success: true });\n });\n\n router.post('/budgets/:agentId/enforce', (req, res) => {\n const result = enforceBudgetForAgent(req.params.agentId);\n if (!result.budgetOk) {\n res.status(403).json({ budgetOk: false, policies: result.policies, message: 'Budget exceeded — agent paused' });\n return;\n }\n res.json({ budgetOk: true, policies: result.policies });\n });\n\n router.get('/budgets/agent/:agentId', (req, res) => {\n const budgetInfo = getBudgetPolicyForAgent(req.params.agentId);\n res.json(budgetInfo);\n });\n\n // ── Activity ──────────────────────────────────────────────\n router.get('/activity', (req, res) => {\n const limit = parseInt(req.query.limit as string) || 50;\n const type = req.query.type as string | undefined;\n res.json(getActivity({ limit, type }));\n });\n\n // ── Audit ───────────────────────────────────────────────────\n router.get('/audit', async (req, res) => {\n try {\n const { queryAudit } = await import('../../agent/auditStore.js');\n const query = {\n agentId: req.query.agentId as string | undefined,\n sessionId: req.query.sessionId as string | undefined,\n type: req.query.type as string | undefined,\n toolName: req.query.toolName as string | undefined,\n from: req.query.from as string | undefined,\n to: req.query.to as string | undefined,\n limit: req.query.limit ? parseInt(req.query.limit as string) : 100,\n };\n res.json(queryAudit(query));\n } catch (err) {\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n router.get('/audit/costs', async (req, res) => {\n try {\n const { getAgentCostSummary, getDailyCostBreakdown } = await import('../../agent/auditStore.js');\n const groupBy = req.query.groupBy as string || 'agent';\n if (groupBy === 'day') {\n const days = req.query.days ? parseInt(req.query.days as string) : 30;\n res.json(getDailyCostBreakdown(days));\n } else {\n const agentId = req.query.agentId as string | undefined;\n res.json(getAgentCostSummary(agentId));\n }\n } catch (err) {\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // ── Goals ───────────────────────────────────────────────────\n router.post('/goals', (req, res) => {\n const { title, description, subtasks, priority, tags, force } = req.body;\n if (!title) { res.status(400).json({ error: 'title is required' }); return; }\n try {\n const goal = createGoal({\n title,\n description: description || '',\n subtasks: subtasks || [],\n priority,\n tags,\n force: !!force,\n });\n res.status(201).json({ goal });\n } catch (err) {\n res.status(429).json({ error: (err as Error).message });\n }\n });\n\n router.get('/goals/tree', (_req, res) => {\n res.json(getGoalTree());\n });\n\n router.get('/goals/:id/ancestry', (req, res) => {\n const chain = getAncestryChain(req.params.id);\n if (chain.length === 0) { res.status(404).json({ error: 'Goal not found' }); return; }\n res.json(chain);\n });\n\n router.post('/goals/:id/validate', (req, res) => {\n const { parentGoalId } = req.body as { parentGoalId?: string | null };\n if (parentGoalId !== undefined) {\n const result = validateGoalParentAssignment(req.params.id, parentGoalId || null);\n if (!result.valid) {\n res.status(422).json({ valid: false, errors: result.errors });\n return;\n }\n res.json({ valid: true });\n } else {\n const result = validateGoalAncestry(req.params.id);\n if (!result.valid) {\n res.status(422).json({ valid: false, errors: result.errors });\n return;\n }\n res.json({ valid: true });\n }\n });\n\n // ── Conflict Resolution ─────────────────────────────────────\n router.post('/conflicts/propose', async (req, res) => {\n try {\n const { conflictResolver } = await import('../../agent/conflictResolver.js');\n const { entities, type, description, metadata } = req.body;\n if (!entities || !Array.isArray(entities) || entities.length === 0) {\n res.status(400).json({ error: 'entities array is required' }); return;\n }\n if (!type || !['file', 'goal', 'resource', 'agent', 'config', 'other'].includes(type)) {\n res.status(400).json({ error: 'valid type is required (file, goal, resource, agent, config, other)' }); return;\n }\n if (!description || typeof description !== 'string') {\n res.status(400).json({ error: 'description string is required' }); return;\n }\n const proposal = await conflictResolver.generateProposal({ entities, type, description, metadata: metadata || {} });\n res.json(proposal);\n } catch (error) {\n logger.error(COMPONENT, 'Conflict proposal generation error:', error);\n res.status(500).json({ error: 'Failed to generate conflict resolution proposal' });\n }\n });\n\n router.post('/conflicts/propose/formatted', async (req, res) => {\n try {\n const { conflictResolver } = await import('../../agent/conflictResolver.js');\n const { entities, type, description, metadata } = req.body;\n if (!entities || !Array.isArray(entities) || entities.length === 0) {\n res.status(400).json({ error: 'entities array is required' }); return;\n }\n if (!type || !['file', 'goal', 'resource', 'agent', 'config', 'other'].includes(type)) {\n res.status(400).json({ error: 'valid type is required (file, goal, resource, agent, config, other)' }); return;\n }\n if (!description || typeof description !== 'string') {\n res.status(400).json({ error: 'description string is required' }); return;\n }\n const proposal = await conflictResolver.generateProposal({ entities, type, description, metadata: metadata || {} });\n const formatted = conflictResolver.formatProposal(proposal);\n res.type('text/plain').send(formatted);\n } catch (error) {\n logger.error(COMPONENT, 'Conflict proposal formatting error:', error);\n res.status(500).json({ error: 'Failed to format conflict resolution proposal' });\n }\n });\n\n router.get('/conflicts/types', (_req, res) => {\n res.json({\n types: [\n { id: 'file', name: 'File Conflict', description: 'Merge conflicts, version conflicts' },\n { id: 'goal', name: 'Goal Conflict', description: 'Competing or conflicting goals' },\n { id: 'resource', name: 'Resource Conflict', description: 'Resource contention (GPU, memory, etc.)' },\n { id: 'agent', name: 'Agent Conflict', description: 'Agent coordination conflicts' },\n { id: 'config', name: 'Configuration Conflict', description: 'Conflicting configuration values' },\n { id: 'other', name: 'Other', description: 'Unclassified conflict type' }\n ]\n });\n });\n\n // ── SSE Stream ────────────────────────────────────────────\n const CP_SSE_EVENTS = [\n 'commandpost:activity', 'commandpost:task:checkout', 'commandpost:task:checkin',\n 'commandpost:task:expired', 'commandpost:budget:warning', 'commandpost:budget:exceeded',\n 'commandpost:agent:heartbeat', 'commandpost:agent:status',\n ];\n\n router.get('/stream', (req, res) => {\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n Connection: 'keep-alive',\n 'X-Accel-Buffering': 'no',\n });\n\n const onEvent = (event: string, data: unknown) => {\n try { res.write(`event: ${event}\\ndata: ${JSON.stringify(data)}\\n\\n`); } catch { /* client gone */ }\n };\n\n const listeners = new Map<string, (data: unknown) => void>();\n for (const evt of CP_SSE_EVENTS) {\n const handler = (data: unknown) => onEvent(evt, data);\n listeners.set(evt, handler);\n titanEvents.on(evt, handler);\n }\n\n const keepalive = setInterval(() => {\n try { res.write(': keepalive\\n\\n'); } catch { /* client gone */ }\n }, 15_000);\n\n req.on('close', () => {\n clearInterval(keepalive);\n for (const [evt, handler] of listeners) {\n titanEvents.removeListener(evt, handler);\n }\n });\n });\n\n // ── Org Chart ───────────────────────────────────────────────\n router.get('/org', async (_req, res) => {\n const org = getOrgTree();\n try {\n const { listCompanies } = await import('../../agent/company.js');\n const companies = listCompanies();\n const companyNodes = companies.map(c => ({\n id: c.id,\n name: c.name,\n role: 'Company',\n title: c.description,\n status: c.status,\n model: '',\n reports: c.agents.map(a => ({\n id: a.id,\n name: a.name,\n role: a.role,\n title: a.template,\n status: a.status,\n model: '',\n reports: [],\n })),\n }));\n if (Array.isArray(org)) {\n org.push(...companyNodes);\n } else if (org && typeof org === 'object') {\n (org as Record<string, unknown>).companies = companyNodes;\n }\n } catch { /* non-critical */ }\n res.json(org);\n });\n\n // ── Issues ──────────────────────────────────────────────────\n router.get('/issues', (req, res) => {\n const filters = {\n status: req.query.status as string | undefined,\n assigneeAgentId: req.query.assignee as string | undefined,\n goalId: req.query.goalId as string | undefined,\n };\n res.json(listIssues(filters));\n });\n\n router.get('/issues/search', (req, res) => {\n const q = req.query.q as string | undefined;\n if (!q || q.trim().length < 2) {\n res.status(400).json({ error: 'Query must be at least 2 characters' }); return;\n }\n res.json(searchIssues(q));\n });\n\n router.post('/issues', (req, res) => {\n const { title, description, priority, assigneeAgentId, goalId, parentId } = req.body;\n if (!title) { res.status(400).json({ error: 'title is required' }); return; }\n const issue = createIssue({ title, description, priority, assigneeAgentId, goalId, parentId, createdByUser: 'board' });\n res.status(201).json(issue);\n });\n\n router.get('/issues/:id/context', (req, res) => {\n const issue = getIssue(req.params.id);\n if (!issue) { res.status(404).json({ error: 'Issue not found' }); return; }\n res.json({ ancestry: issue.goalId || '', issue });\n });\n\n router.get('/issues/:id', (req, res) => {\n const issue = getIssue(req.params.id);\n if (!issue) { res.status(404).json({ error: 'Issue not found' }); return; }\n const issueComments = getIssueComments(req.params.id);\n res.json({ ...issue, comments: issueComments });\n });\n\n router.get('/issues/:id/comments', (req, res) => {\n const issue = getIssue(req.params.id);\n if (!issue) { res.status(404).json({ error: 'Issue not found' }); return; }\n res.json(getIssueComments(req.params.id));\n });\n\n router.patch('/issues/:id', (req, res) => {\n const { title, description, status, priority, assigneeAgentId, goalId } = req.body;\n const updated = updateIssue(req.params.id, { title, description, status, priority, assigneeAgentId, goalId });\n if (!updated) { res.status(404).json({ error: 'Issue not found' }); return; }\n res.json(updated);\n });\n\n router.delete('/issues/:id', (req, res) => {\n const ok = deleteIssue(req.params.id);\n if (!ok) { res.status(404).json({ error: 'Issue not found' }); return; }\n res.json({ success: true });\n });\n\n router.post('/issues/:id/checkout', (req, res) => {\n const { agentId } = req.body;\n if (!agentId) { res.status(400).json({ error: 'agentId is required' }); return; }\n const result = checkoutIssue(req.params.id, agentId);\n if (!result) { res.status(409).json({ error: 'Issue already checked out by another agent' }); return; }\n res.json(result);\n });\n\n router.post('/issues/:id/comments', (req, res) => {\n const { body: commentBody, agentId } = req.body;\n if (!commentBody) { res.status(400).json({ error: 'body is required' }); return; }\n const comment = addIssueComment(req.params.id, commentBody, { agentId, user: agentId ? undefined : 'board' });\n if (!comment) { res.status(404).json({ error: 'Issue not found' }); return; }\n res.status(201).json(comment);\n });\n\n // ── Approvals ─────────────────────────────────────────────\n router.get('/approvals', (req, res) => {\n const status = req.query.status as string | undefined;\n res.json(listApprovals(status));\n });\n\n router.post('/approvals', (req, res) => {\n const { type, requestedBy, payload, linkedIssueIds } = req.body;\n if (!type) { res.status(400).json({ error: 'type is required' }); return; }\n const approval = createApproval({ type, requestedBy: requestedBy || 'board', payload: payload || {}, linkedIssueIds });\n res.status(201).json(approval);\n });\n\n router.post('/approvals/:id/approve', async (req, res) => {\n const { decidedBy, note } = req.body;\n const result = await approveApproval(req.params.id, decidedBy || 'board', note);\n if (!result) { res.status(404).json({ error: 'Approval not found or already decided' }); return; }\n res.json(result);\n });\n\n router.post('/approvals/:id/reject', (req, res) => {\n const { decidedBy, note } = req.body;\n const result = rejectApproval(req.params.id, decidedBy || 'board', note);\n if (!result) { res.status(404).json({ error: 'Approval not found or already decided' }); return; }\n res.json(result);\n });\n\n router.post('/approvals/:id/reply', (req, res) => {\n const { author, body } = req.body;\n if (!body || typeof body !== 'string') { res.status(400).json({ error: 'body is required' }); return; }\n const result = replyToApproval(req.params.id, author || 'user', body);\n if (!result) { res.status(404).json({ error: 'Approval not found' }); return; }\n res.json(result);\n });\n\n router.post('/approvals/:id/snooze', (req, res) => {\n const { until } = req.body;\n if (!until) { res.status(400).json({ error: 'until timestamp is required' }); return; }\n const result = snoozeApproval(req.params.id, until);\n if (!result) { res.status(404).json({ error: 'Approval not found or not pending' }); return; }\n res.json(result);\n });\n\n router.post('/approvals/:id/unsnooze', (req, res) => {\n const result = unsnoozeApproval(req.params.id);\n if (!result) { res.status(404).json({ error: 'Approval not found' }); return; }\n res.json(result);\n });\n\n router.get('/approvals/:id/thread', (req, res) => {\n const approval = listApprovals().find(a => a.id === req.params.id);\n if (!approval) { res.status(404).json({ error: 'Approval not found' }); return; }\n res.json({ approvalId: approval.id, thread: approval.thread || [] });\n });\n\n router.post('/approvals/batch', async (req, res) => {\n const { ids, action, decidedBy, note } = req.body;\n if (!Array.isArray(ids) || ids.length === 0) { res.status(400).json({ error: 'ids array required' }); return; }\n if (action === 'approve') {\n const result = await batchApprove(ids, decidedBy || 'board', note);\n res.json(result);\n } else if (action === 'reject') {\n const result = batchReject(ids, decidedBy || 'board', note);\n res.json(result);\n } else {\n res.status(400).json({ error: 'action must be approve or reject' });\n }\n });\n\n router.post('/approvals/sweep', async (_req, res) => {\n const { sweepStaleApprovalsManual } = await import('../../agent/commandPost.js');\n const result = sweepStaleApprovalsManual();\n res.json(result);\n });\n\n // ── Agent Messages ──────────────────────────────────────────\n router.get('/agent-messages', (req, res) => {\n const agentId = req.query.agentId as string | undefined;\n const userId = req.query.userId as string | undefined;\n const unreadOnly = req.query.unread === 'true';\n res.json(getAgentMessages(agentId, userId, unreadOnly));\n });\n\n router.post('/agent-messages/:id/read', (req, res) => {\n const ok = markAgentMessageRead(req.params.id);\n if (!ok) { res.status(404).json({ error: 'Message not found' }); return; }\n res.json({ read: true });\n });\n\n // ── Debates ─────────────────────────────────────────────────\n router.post('/debates', async (req, res) => {\n try {\n const { question, participants, rounds, resolution, judgeModel } = req.body || {};\n if (!question || !Array.isArray(participants) || participants.length < 2) {\n res.status(400).json({ error: 'question + 2-5 participants required' }); return;\n }\n const { runDebate } = await import('../../skills/builtin/agent_debate.js');\n const result = await runDebate({\n question: String(question),\n participants,\n rounds: Math.max(1, Math.min(4, Number(rounds) || 2)),\n resolution: (resolution === 'vote' || resolution === 'synthesize' || resolution === 'judge') ? resolution : 'judge',\n judgeModel: judgeModel ? String(judgeModel) : undefined,\n });\n res.json({ ok: true, id: result.id, winner: result.winner });\n } catch (err) {\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n router.get('/debates', async (req, res) => {\n const limit = parseInt(req.query.limit as string) || 50;\n const { listDebates } = await import('../../skills/builtin/agent_debate.js');\n res.json({ items: listDebates(limit) });\n });\n\n router.get('/debates/:id', async (req, res) => {\n const { getDebate } = await import('../../skills/builtin/agent_debate.js');\n const debate = getDebate(req.params.id);\n if (!debate) { res.status(404).json({ error: 'Debate not found' }); return; }\n res.json(debate);\n });\n\n // ── Runs ────────────────────────────────────────────────────\n router.get('/runs', (req, res) => {\n const agentId = req.query.agentId as string | undefined;\n const limit = parseInt(req.query.limit as string) || 50;\n res.json(listRuns(agentId, limit));\n });\n\n router.post('/runs/:id/retry', async (req, res) => {\n const allRuns = listRuns(undefined, 500);\n const run = allRuns.find(r => r.id === req.params.id);\n if (!run) { res.status(404).json({ error: 'Run not found' }); return; }\n const agent = getRegisteredAgents().find(a => a.id === run.agentId);\n if (!agent) { res.status(404).json({ error: 'Agent not found' }); return; }\n\n let task = `Retry failed run (${run.id})`;\n if (run.error) task += `: ${run.error}`;\n let issueDesc = task;\n if (run.issueId) {\n const originalIssue = getIssue(run.issueId);\n if (originalIssue) {\n task = `Retry: ${originalIssue.title}`;\n issueDesc = `${originalIssue.description || ''}\\n\\nRetrying after failure: ${run.error || 'unknown error'}`;\n }\n }\n\n const issue = createIssue({ title: task, description: issueDesc, priority: 'high', assigneeAgentId: agent.id, createdByUser: 'board' });\n const newRun = startRun(agent.id, 'manual', issue.id);\n queueWakeup({ issueId: issue.id, issueIdentifier: issue.identifier, agentId: agent.id, agentName: agent.name, parentSessionId: null, task, templateName: agent.role || 'default' });\n res.json({ retried: true, runId: newRun.id, issueId: issue.id });\n });\n\n // ── Wakeup System ───────────────────────────────────────────\n router.get('/agents/:agentId/inbox', (req, res) => {\n const items = getAgentInbox(req.params.agentId);\n res.json({ items, total: items.length });\n });\n\n router.post('/wakeup', (req, res) => {\n const { issueId, agentId, agentName, task, templateName } = req.body;\n if (!issueId || !agentId || !task) {\n res.status(400).json({ error: 'issueId, agentId, and task are required' }); return;\n }\n const wakeup = queueWakeup({ issueId, issueIdentifier: issueId, agentId, agentName: agentName || 'Agent', parentSessionId: null, task, templateName: templateName || '' });\n res.json({ wakeupRequestId: wakeup.id, status: wakeup.status });\n });\n\n router.get('/wakeup/:requestId', (req, res) => {\n const request = getWakeupRequest(req.params.requestId);\n if (!request) { res.status(404).json({ error: 'Wakeup request not found' }); return; }\n res.json(request);\n });\n\n router.delete('/wakeup/:requestId', (req, res) => {\n const cancelled = cancelWakeup(req.params.requestId);\n if (!cancelled) { res.status(409).json({ error: 'Request already running or completed' }); return; }\n res.json({ cancelled: true });\n });\n\n router.get('/sessions/:sessionId/pending-results', (req, res) => {\n const results = drainPendingResults(req.params.sessionId);\n res.json({ results, count: results.length });\n });\n\n return router;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Router } from "express";
|
|
3
|
+
import { logger } from "../../utils/logger.js";
|
|
4
|
+
const COMPONENT = "companies-router";
|
|
5
|
+
function createCompaniesRouter() {
|
|
6
|
+
const router = Router();
|
|
7
|
+
router.get("/", async (_req, res) => {
|
|
8
|
+
try {
|
|
9
|
+
const { listCompanies, getActiveRunners } = await import("../../agent/company.js");
|
|
10
|
+
const includeArchived = _req.query.archived === "true";
|
|
11
|
+
const companies = listCompanies(includeArchived);
|
|
12
|
+
const runners = getActiveRunners();
|
|
13
|
+
res.json({ companies: companies.map((c) => ({ ...c, runnerActive: runners.includes(c.id) })) });
|
|
14
|
+
} catch (e) {
|
|
15
|
+
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
16
|
+
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
router.post("/", async (req, res) => {
|
|
20
|
+
try {
|
|
21
|
+
const { createCompany } = await import("../../agent/company.js");
|
|
22
|
+
const company = createCompany(req.body);
|
|
23
|
+
res.json(company);
|
|
24
|
+
} catch (e) {
|
|
25
|
+
res.status(400).json({ error: e.message });
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
router.get("/:id", async (req, res) => {
|
|
29
|
+
try {
|
|
30
|
+
const { getCompany, isRunnerActive } = await import("../../agent/company.js");
|
|
31
|
+
const company = getCompany(req.params.id);
|
|
32
|
+
if (!company) {
|
|
33
|
+
res.status(404).json({ error: "Company not found" });
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
res.json({ ...company, runnerActive: isRunnerActive(company.id) });
|
|
37
|
+
} catch (e) {
|
|
38
|
+
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
39
|
+
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
router.patch("/:id", async (req, res) => {
|
|
43
|
+
try {
|
|
44
|
+
const { updateCompany } = await import("../../agent/company.js");
|
|
45
|
+
const company = updateCompany(req.params.id, req.body);
|
|
46
|
+
if (!company) {
|
|
47
|
+
res.status(404).json({ error: "Company not found" });
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
res.json(company);
|
|
51
|
+
} catch (e) {
|
|
52
|
+
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
53
|
+
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
router.delete("/:id", async (req, res) => {
|
|
57
|
+
try {
|
|
58
|
+
const { deleteCompany, stopCompanyRunner } = await import("../../agent/company.js");
|
|
59
|
+
stopCompanyRunner(req.params.id);
|
|
60
|
+
const ok = deleteCompany(req.params.id);
|
|
61
|
+
res.json({ success: ok });
|
|
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.post("/:id/start", async (req, res) => {
|
|
68
|
+
try {
|
|
69
|
+
const { startCompanyRunner } = await import("../../agent/company.js");
|
|
70
|
+
const interval = parseInt(req.body?.intervalMs || "60000", 10);
|
|
71
|
+
const ok = startCompanyRunner(req.params.id, interval);
|
|
72
|
+
res.json({ success: ok, message: ok ? "Runner started" : "Already running or company not active" });
|
|
73
|
+
} catch (e) {
|
|
74
|
+
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
75
|
+
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
router.post("/:id/stop", async (req, res) => {
|
|
79
|
+
try {
|
|
80
|
+
const { stopCompanyRunner } = await import("../../agent/company.js");
|
|
81
|
+
const ok = stopCompanyRunner(req.params.id);
|
|
82
|
+
res.json({ success: ok });
|
|
83
|
+
} catch (e) {
|
|
84
|
+
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
85
|
+
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
router.post("/:id/agents", async (req, res) => {
|
|
89
|
+
try {
|
|
90
|
+
const { addAgentToCompany } = await import("../../agent/company.js");
|
|
91
|
+
const agent = addAgentToCompany(req.params.id, req.body);
|
|
92
|
+
if (!agent) {
|
|
93
|
+
res.status(404).json({ error: "Company not found" });
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
res.json(agent);
|
|
97
|
+
} catch (e) {
|
|
98
|
+
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
99
|
+
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
router.post("/:id/goals", async (req, res) => {
|
|
103
|
+
try {
|
|
104
|
+
const { addGoalToCompany } = await import("../../agent/company.js");
|
|
105
|
+
const goal = addGoalToCompany(req.params.id, req.body);
|
|
106
|
+
if (!goal) {
|
|
107
|
+
res.status(404).json({ error: "Company not found" });
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
res.json(goal);
|
|
111
|
+
} catch (e) {
|
|
112
|
+
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
113
|
+
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
router.post("/:id/export", async (req, res) => {
|
|
117
|
+
try {
|
|
118
|
+
const { getCompany } = await import("../../agent/company.js");
|
|
119
|
+
const { writeCompanyPackage } = await import("../../agent/companyPortability.js");
|
|
120
|
+
const company = getCompany(req.params.id);
|
|
121
|
+
if (!company) {
|
|
122
|
+
res.status(404).json({ error: "Company not found" });
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const outPath = writeCompanyPackage(company, req.body?.outDir);
|
|
126
|
+
res.json({ success: true, path: outPath, name: company.name });
|
|
127
|
+
} catch (e) {
|
|
128
|
+
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
129
|
+
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
router.get("/exports", async (_req, res) => {
|
|
133
|
+
try {
|
|
134
|
+
const { listExportedPackages } = await import("../../agent/companyPortability.js");
|
|
135
|
+
res.json(listExportedPackages());
|
|
136
|
+
} catch (e) {
|
|
137
|
+
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
138
|
+
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
router.post("/import", async (req, res) => {
|
|
142
|
+
try {
|
|
143
|
+
const { importCompanyFromDirectory, importCompanyFromMarkdown } = await import("../../agent/companyPortability.js");
|
|
144
|
+
const { createCompany } = await import("../../agent/company.js");
|
|
145
|
+
let imported = null;
|
|
146
|
+
if (req.body?.packagePath) {
|
|
147
|
+
imported = importCompanyFromDirectory(req.body.packagePath);
|
|
148
|
+
} else if (req.body?.markdown) {
|
|
149
|
+
imported = importCompanyFromMarkdown(req.body.markdown);
|
|
150
|
+
}
|
|
151
|
+
if (!imported) {
|
|
152
|
+
res.status(400).json({ error: "Invalid import. Provide packagePath or markdown." });
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const company = createCompany(imported);
|
|
156
|
+
res.json({ success: true, company });
|
|
157
|
+
} catch (e) {
|
|
158
|
+
res.status(400).json({ error: e.message });
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
return router;
|
|
162
|
+
}
|
|
163
|
+
export {
|
|
164
|
+
createCompaniesRouter
|
|
165
|
+
};
|
|
166
|
+
//# sourceMappingURL=companies.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/gateway/routes/companies.ts"],"sourcesContent":["import { Router } from 'express';\nimport { logger } from '../../utils/logger.js';\n\nconst COMPONENT = 'companies-router';\n\nexport function createCompaniesRouter() {\n const router = Router();\n\n router.get('/', async (_req, res) => {\n try {\n const { listCompanies, getActiveRunners } = await import('../../agent/company.js');\n const includeArchived = _req.query.archived === 'true';\n const companies = listCompanies(includeArchived);\n const runners = getActiveRunners();\n res.json({ companies: companies.map(c => ({ ...c, runnerActive: runners.includes(c.id) })) });\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('/', async (req, res) => {\n try {\n const { createCompany } = await import('../../agent/company.js');\n const company = createCompany(req.body);\n res.json(company);\n } catch (e) { res.status(400).json({ error: (e as Error).message }); }\n });\n\n router.get('/:id', async (req, res) => {\n try {\n const { getCompany, isRunnerActive } = await import('../../agent/company.js');\n const company = getCompany(req.params.id);\n if (!company) { res.status(404).json({ error: 'Company not found' }); return; }\n res.json({ ...company, runnerActive: isRunnerActive(company.id) });\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.patch('/:id', async (req, res) => {\n try {\n const { updateCompany } = await import('../../agent/company.js');\n const company = updateCompany(req.params.id, req.body);\n if (!company) { res.status(404).json({ error: 'Company not found' }); return; }\n res.json(company);\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('/:id', async (req, res) => {\n try {\n const { deleteCompany, stopCompanyRunner } = await import('../../agent/company.js');\n stopCompanyRunner(req.params.id);\n const ok = deleteCompany(req.params.id);\n res.json({ success: ok });\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 // Start/stop company heartbeat runner\n router.post('/:id/start', async (req, res) => {\n try {\n const { startCompanyRunner } = await import('../../agent/company.js');\n const interval = parseInt(req.body?.intervalMs || '60000', 10);\n const ok = startCompanyRunner(req.params.id, interval);\n res.json({ success: ok, message: ok ? 'Runner started' : 'Already running or company not active' });\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('/:id/stop', async (req, res) => {\n try {\n const { stopCompanyRunner } = await import('../../agent/company.js');\n const ok = stopCompanyRunner(req.params.id);\n res.json({ success: ok });\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 // Add agent/goal to company\n router.post('/:id/agents', async (req, res) => {\n try {\n const { addAgentToCompany } = await import('../../agent/company.js');\n const agent = addAgentToCompany(req.params.id, req.body);\n if (!agent) { res.status(404).json({ error: 'Company not found' }); return; }\n res.json(agent);\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('/:id/goals', async (req, res) => {\n try {\n const { addGoalToCompany } = await import('../../agent/company.js');\n const goal = addGoalToCompany(req.params.id, req.body);\n if (!goal) { res.status(404).json({ error: 'Company not found' }); return; }\n res.json(goal);\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 // Company Portability (Export/Import)\n router.post('/:id/export', async (req, res) => {\n try {\n const { getCompany } = await import('../../agent/company.js');\n const { writeCompanyPackage } = await import('../../agent/companyPortability.js');\n const company = getCompany(req.params.id);\n if (!company) { res.status(404).json({ error: 'Company not found' }); return; }\n const outPath = writeCompanyPackage(company, req.body?.outDir);\n res.json({ success: true, path: outPath, name: company.name });\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('/exports', async (_req, res) => {\n try {\n const { listExportedPackages } = await import('../../agent/companyPortability.js');\n res.json(listExportedPackages());\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('/import', async (req, res) => {\n try {\n const { importCompanyFromDirectory, importCompanyFromMarkdown } = await import('../../agent/companyPortability.js');\n const { createCompany } = await import('../../agent/company.js');\n let imported = null;\n if (req.body?.packagePath) {\n imported = importCompanyFromDirectory(req.body.packagePath);\n } else if (req.body?.markdown) {\n imported = importCompanyFromMarkdown(req.body.markdown);\n }\n if (!imported) { res.status(400).json({ error: 'Invalid import. Provide packagePath or markdown.' }); return; }\n const company = createCompany(imported);\n res.json({ success: true, company });\n } catch (e) { res.status(400).json({ error: (e as Error).message }); }\n });\n\n return router;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Router } from "express";
|
|
3
|
+
import { homedir } from "os";
|
|
4
|
+
import { join, dirname, resolve } from "path";
|
|
5
|
+
import fs from "fs";
|
|
6
|
+
import logger from "../../utils/logger.js";
|
|
7
|
+
import { loadConfig } from "../../config/config.js";
|
|
8
|
+
const COMPONENT = "FilesRouter";
|
|
9
|
+
function getFileRoots() {
|
|
10
|
+
const cfg = loadConfig();
|
|
11
|
+
const fmCfg = cfg.fileManager;
|
|
12
|
+
const roots = fmCfg?.roots || ["~/.titan"];
|
|
13
|
+
return roots.map((r) => {
|
|
14
|
+
const expanded = r.replace(/^~/, homedir());
|
|
15
|
+
const abs = resolve(expanded);
|
|
16
|
+
const label = abs.split("/").filter(Boolean).pop() || abs;
|
|
17
|
+
return { label, path: abs };
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
function validateFilePath(reqPath, rootParam) {
|
|
21
|
+
const roots = getFileRoots();
|
|
22
|
+
if (roots.length === 0) return { valid: false, fullPath: "", basePath: "", error: "No file roots configured" };
|
|
23
|
+
let selectedRoot = roots[0];
|
|
24
|
+
if (rootParam) {
|
|
25
|
+
const byIndex = roots[parseInt(rootParam, 10)];
|
|
26
|
+
const byLabel = roots.find((r) => r.label === rootParam || r.path === rootParam);
|
|
27
|
+
selectedRoot = byIndex || byLabel || roots[0];
|
|
28
|
+
}
|
|
29
|
+
const basePath = selectedRoot.path;
|
|
30
|
+
const fullPath = resolve(basePath, reqPath.replace(/^\//, ""));
|
|
31
|
+
const basePathWithSep = basePath.endsWith("/") ? basePath : basePath + "/";
|
|
32
|
+
if (fullPath !== basePath && !fullPath.startsWith(basePathWithSep)) {
|
|
33
|
+
return { valid: false, fullPath, basePath, error: "Access denied: path outside allowed root" };
|
|
34
|
+
}
|
|
35
|
+
const cfg = loadConfig();
|
|
36
|
+
const fmCfg = cfg.fileManager;
|
|
37
|
+
const blocked = fmCfg?.blockedPatterns || [".ssh", ".env", ".aws", ".gnupg", "node_modules", ".git/objects"];
|
|
38
|
+
for (const pattern of blocked) {
|
|
39
|
+
if (fullPath.includes(`/${pattern}`) || fullPath.endsWith(`/${pattern}`)) {
|
|
40
|
+
return { valid: false, fullPath, basePath, error: `Access denied: blocked pattern "${pattern}"` };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return { valid: true, fullPath, basePath };
|
|
44
|
+
}
|
|
45
|
+
function createFilesRouter() {
|
|
46
|
+
const router = Router();
|
|
47
|
+
const UPLOADS_DIR = join(homedir(), ".titan", "uploads");
|
|
48
|
+
router.get("/roots", (_req, res) => {
|
|
49
|
+
res.json({ roots: getFileRoots() });
|
|
50
|
+
});
|
|
51
|
+
router.get("/", (req, res) => {
|
|
52
|
+
const reqPath = req.query.path || "";
|
|
53
|
+
const rootParam = req.query.root;
|
|
54
|
+
const { valid, fullPath, basePath, error } = validateFilePath(reqPath, rootParam);
|
|
55
|
+
if (!valid) {
|
|
56
|
+
res.status(403).json({ error });
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
if (!fs.existsSync(fullPath)) {
|
|
61
|
+
res.status(404).json({ error: "Path not found" });
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const stat = fs.statSync(fullPath);
|
|
65
|
+
if (!stat.isDirectory()) {
|
|
66
|
+
res.status(400).json({ error: "Not a directory. Use /api/files/read for files." });
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const entries = fs.readdirSync(fullPath).map((name) => {
|
|
70
|
+
try {
|
|
71
|
+
const entryPath = join(fullPath, name);
|
|
72
|
+
const entryStat = fs.statSync(entryPath);
|
|
73
|
+
return {
|
|
74
|
+
name,
|
|
75
|
+
path: reqPath ? `${reqPath}/${name}` : name,
|
|
76
|
+
type: entryStat.isDirectory() ? "directory" : "file",
|
|
77
|
+
size: entryStat.size,
|
|
78
|
+
modified: entryStat.mtime.toISOString()
|
|
79
|
+
};
|
|
80
|
+
} catch {
|
|
81
|
+
return { name, path: reqPath ? `${reqPath}/${name}` : name, type: "file", size: 0, modified: "" };
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
entries.sort((a, b) => {
|
|
85
|
+
if (a.type !== b.type) return a.type === "directory" ? -1 : 1;
|
|
86
|
+
return a.name.localeCompare(b.name);
|
|
87
|
+
});
|
|
88
|
+
res.json({ path: reqPath || "/", entries, basePath });
|
|
89
|
+
} catch (err) {
|
|
90
|
+
res.status(500).json({ error: err.message });
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
router.get("/read", (req, res) => {
|
|
94
|
+
const reqPath = req.query.path;
|
|
95
|
+
if (!reqPath) {
|
|
96
|
+
res.status(400).json({ error: "path parameter required" });
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const rootParam = req.query.root;
|
|
100
|
+
const { valid, fullPath, error } = validateFilePath(reqPath, rootParam);
|
|
101
|
+
if (!valid) {
|
|
102
|
+
res.status(403).json({ error });
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
try {
|
|
106
|
+
if (!fs.existsSync(fullPath)) {
|
|
107
|
+
res.status(404).json({ error: "File not found" });
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const stat = fs.statSync(fullPath);
|
|
111
|
+
if (stat.isDirectory()) {
|
|
112
|
+
res.status(400).json({ error: "Path is a directory" });
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const MAX_SIZE = 1024 * 1024;
|
|
116
|
+
if (stat.size > MAX_SIZE) {
|
|
117
|
+
const content2 = fs.readFileSync(fullPath, "utf-8").slice(0, MAX_SIZE);
|
|
118
|
+
res.json({ path: reqPath, content: content2, truncated: true, size: stat.size, modified: stat.mtime.toISOString() });
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const content = fs.readFileSync(fullPath, "utf-8");
|
|
122
|
+
res.json({ path: reqPath, content, truncated: false, size: stat.size, modified: stat.mtime.toISOString() });
|
|
123
|
+
} catch (err) {
|
|
124
|
+
res.status(500).json({ error: err.message });
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
router.post("/write", (req, res) => {
|
|
128
|
+
const { path: reqPath, content, root: rootParam } = req.body;
|
|
129
|
+
if (!reqPath) {
|
|
130
|
+
res.status(400).json({ error: "path required" });
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
if (content === void 0) {
|
|
134
|
+
res.status(400).json({ error: "content required" });
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const { valid, fullPath, error } = validateFilePath(reqPath, rootParam);
|
|
138
|
+
if (!valid) {
|
|
139
|
+
res.status(403).json({ error });
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
try {
|
|
143
|
+
const dir = dirname(fullPath);
|
|
144
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
145
|
+
fs.writeFileSync(fullPath, content, "utf-8");
|
|
146
|
+
const stat = fs.statSync(fullPath);
|
|
147
|
+
res.json({ success: true, path: reqPath, size: stat.size, modified: stat.mtime.toISOString() });
|
|
148
|
+
} catch (err) {
|
|
149
|
+
res.status(500).json({ error: err.message });
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
router.post("/mkdir", (req, res) => {
|
|
153
|
+
const { path: reqPath, root: rootParam } = req.body;
|
|
154
|
+
if (!reqPath) {
|
|
155
|
+
res.status(400).json({ error: "path required" });
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
const { valid, fullPath, error } = validateFilePath(reqPath, rootParam);
|
|
159
|
+
if (!valid) {
|
|
160
|
+
res.status(403).json({ error });
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
try {
|
|
164
|
+
if (fs.existsSync(fullPath)) {
|
|
165
|
+
res.status(409).json({ error: "Path already exists" });
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
fs.mkdirSync(fullPath, { recursive: true });
|
|
169
|
+
res.json({ success: true, path: reqPath });
|
|
170
|
+
} catch (err) {
|
|
171
|
+
res.status(500).json({ error: err.message });
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
router.post("/rename", (req, res) => {
|
|
175
|
+
const { oldPath, newPath, root: rootParam } = req.body;
|
|
176
|
+
if (!oldPath || !newPath) {
|
|
177
|
+
res.status(400).json({ error: "oldPath and newPath required" });
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
const oldValidation = validateFilePath(oldPath, rootParam);
|
|
181
|
+
const newValidation = validateFilePath(newPath, rootParam);
|
|
182
|
+
if (!oldValidation.valid) {
|
|
183
|
+
res.status(403).json({ error: oldValidation.error });
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
if (!newValidation.valid) {
|
|
187
|
+
res.status(403).json({ error: newValidation.error });
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
try {
|
|
191
|
+
if (!fs.existsSync(oldValidation.fullPath)) {
|
|
192
|
+
res.status(404).json({ error: "Source not found" });
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
if (fs.existsSync(newValidation.fullPath)) {
|
|
196
|
+
res.status(409).json({ error: "Destination already exists" });
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
fs.renameSync(oldValidation.fullPath, newValidation.fullPath);
|
|
200
|
+
res.json({ success: true, oldPath, newPath });
|
|
201
|
+
} catch (err) {
|
|
202
|
+
res.status(500).json({ error: err.message });
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
router.delete("/delete", (req, res) => {
|
|
206
|
+
const reqPath = req.query.path;
|
|
207
|
+
const rootParam = req.query.root;
|
|
208
|
+
if (!reqPath) {
|
|
209
|
+
res.status(400).json({ error: "path required" });
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
const { valid, fullPath, error } = validateFilePath(reqPath, rootParam);
|
|
213
|
+
if (!valid) {
|
|
214
|
+
res.status(403).json({ error });
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
try {
|
|
218
|
+
if (!fs.existsSync(fullPath)) {
|
|
219
|
+
res.status(404).json({ error: "Not found" });
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
const stat = fs.statSync(fullPath);
|
|
223
|
+
if (stat.isDirectory()) {
|
|
224
|
+
const contents = fs.readdirSync(fullPath);
|
|
225
|
+
if (contents.length > 0) {
|
|
226
|
+
res.status(400).json({ error: "Directory not empty. Delete contents first." });
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
fs.rmdirSync(fullPath);
|
|
230
|
+
} else {
|
|
231
|
+
fs.unlinkSync(fullPath);
|
|
232
|
+
}
|
|
233
|
+
res.json({ success: true, path: reqPath });
|
|
234
|
+
} catch (err) {
|
|
235
|
+
res.status(500).json({ error: err.message });
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
router.post("/upload", (req, res) => {
|
|
239
|
+
try {
|
|
240
|
+
const fileName = req.headers["x-filename"] || `upload-${Date.now()}`;
|
|
241
|
+
const safeName = fileName.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 100);
|
|
242
|
+
const sessionId = req.headers["x-session-id"] || "default";
|
|
243
|
+
const body = Buffer.isBuffer(req.body) ? req.body : Buffer.from(JSON.stringify(req.body));
|
|
244
|
+
if (!body || body.length === 0) {
|
|
245
|
+
res.status(400).json({ error: "Empty upload body" });
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
const sessionDir = join(UPLOADS_DIR, sessionId);
|
|
249
|
+
if (!fs.existsSync(sessionDir)) fs.mkdirSync(sessionDir, { recursive: true });
|
|
250
|
+
const filePath = join(sessionDir, safeName);
|
|
251
|
+
fs.writeFileSync(filePath, body);
|
|
252
|
+
const stat = fs.statSync(filePath);
|
|
253
|
+
logger.info(COMPONENT, `File uploaded: ${safeName} (${(stat.size / 1024).toFixed(0)}KB) \u2192 session ${sessionId}`);
|
|
254
|
+
res.json({ ok: true, file: { name: safeName, path: filePath, size: stat.size, session: sessionId, uploadedAt: (/* @__PURE__ */ new Date()).toISOString() } });
|
|
255
|
+
} catch (err) {
|
|
256
|
+
res.status(500).json({ error: err.message });
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
router.get("/uploads", (req, res) => {
|
|
260
|
+
try {
|
|
261
|
+
const sessionId = req.query.session || "default";
|
|
262
|
+
const sessionDir = join(UPLOADS_DIR, sessionId);
|
|
263
|
+
if (!fs.existsSync(sessionDir)) {
|
|
264
|
+
res.json({ files: [] });
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
const files = fs.readdirSync(sessionDir).map((name) => {
|
|
268
|
+
const stat = fs.statSync(join(sessionDir, name));
|
|
269
|
+
return { name, size: stat.size, modified: stat.mtime.toISOString() };
|
|
270
|
+
});
|
|
271
|
+
res.json({ files, session: sessionId });
|
|
272
|
+
} catch (err) {
|
|
273
|
+
res.status(500).json({ error: err.message });
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
router.delete("/uploads/:name", (req, res) => {
|
|
277
|
+
try {
|
|
278
|
+
const sessionId = req.query.session || "default";
|
|
279
|
+
const filePath = join(UPLOADS_DIR, sessionId, req.params.name.replace(/[^a-zA-Z0-9._-]/g, "_"));
|
|
280
|
+
if (!filePath.startsWith(UPLOADS_DIR)) {
|
|
281
|
+
res.status(403).json({ error: "Access denied" });
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
if (fs.existsSync(filePath)) fs.unlinkSync(filePath);
|
|
285
|
+
res.json({ ok: true });
|
|
286
|
+
} catch (err) {
|
|
287
|
+
res.status(500).json({ error: err.message });
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
return router;
|
|
291
|
+
}
|
|
292
|
+
export {
|
|
293
|
+
createFilesRouter
|
|
294
|
+
};
|
|
295
|
+
//# sourceMappingURL=files.js.map
|