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