titan-agent 6.3.5 → 6.4.0
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/THIRD_PARTY_NOTICES.md +3 -0
- package/dist/agent/agent.js +6 -2
- package/dist/agent/agent.js.map +1 -1
- package/dist/agent/autoSkillGen.js +55 -17
- package/dist/agent/autoSkillGen.js.map +1 -1
- package/dist/agent/learningCurator.js +383 -0
- package/dist/agent/learningCurator.js.map +1 -0
- package/dist/agent/trajectoryLogger.js +2 -2
- package/dist/agent/trajectoryLogger.js.map +1 -1
- package/dist/config/config.js +18 -2
- package/dist/config/config.js.map +1 -1
- package/dist/config/schema.js +22 -0
- package/dist/config/schema.js.map +1 -1
- package/dist/gateway/server.js +6 -1
- package/dist/gateway/server.js.map +1 -1
- package/dist/providers/defaultModel.js +2 -2
- package/dist/providers/defaultModel.js.map +1 -1
- package/dist/providers/ollama.js +17 -1
- package/dist/providers/ollama.js.map +1 -1
- package/dist/providers/router.js +7 -3
- package/dist/providers/router.js.map +1 -1
- package/dist/providers/stub.js +1 -6
- package/dist/providers/stub.js.map +1 -1
- package/dist/utils/constants.js +1 -1
- package/dist/utils/constants.js.map +1 -1
- package/package.json +1 -1
- package/ui/dist/assets/{AuditPanel-C7rrUHBM.js → AuditPanel-CLc6IVvA.js} +1 -1
- package/ui/dist/assets/{AutonomyPanel-CcOxsveF.js → AutonomyPanel-E6arcbAb.js} +2 -2
- package/ui/dist/assets/{AutopilotPanel-CjrYEF2s.js → AutopilotPanel-AhNEPP_2.js} +1 -1
- package/ui/dist/assets/{AutoresearchPanel-CBdGRAdZ.js → AutoresearchPanel-BJRXdUNa.js} +1 -1
- package/ui/dist/assets/{BackupPanel-BhU-utCn.js → BackupPanel-CGQAxeWf.js} +1 -1
- package/ui/dist/assets/{BrowserPanel-Dr-B5Kva.js → BrowserPanel-BylOyNpQ.js} +1 -1
- package/ui/dist/assets/{CPActivity-C5kJWqWc.js → CPActivity-7zS0dXGf.js} +1 -1
- package/ui/dist/assets/{CPAgentDetail-BVE3LoLA.js → CPAgentDetail-DUi0ygHI.js} +1 -1
- package/ui/dist/assets/{CPAgents-BKBSyXHs.js → CPAgents-BZYynbga.js} +1 -1
- package/ui/dist/assets/{CPApprovals-AkRGu05y.js → CPApprovals-CwNTmqzq.js} +1 -1
- package/ui/dist/assets/{CPCosts-DC5mPwVm.js → CPCosts-5hylxGvH.js} +1 -1
- package/ui/dist/assets/{CPDashboard-C7G-H6HW.js → CPDashboard-5f8qcBKy.js} +1 -1
- package/ui/dist/assets/{CPFiles-IhcbsdvY.js → CPFiles-CR9Nn3_p.js} +1 -1
- package/ui/dist/assets/{CPGoals-BL0rrvT5.js → CPGoals-CVSxXk1i.js} +1 -1
- package/ui/dist/assets/{CPInbox-CBUkqu4i.js → CPInbox-DD4RYSpf.js} +1 -1
- package/ui/dist/assets/{CPIssueDetail-HuI9tPu4.js → CPIssueDetail-Dpuc_wTi.js} +1 -1
- package/ui/dist/assets/{CPIssues-Do9d-evH.js → CPIssues-DsPZLTGm.js} +1 -1
- package/ui/dist/assets/CPLayout-CDkrYE-H.js +2 -0
- package/ui/dist/assets/{CPOrg-WHkSBNGU.js → CPOrg-C121ZFWy.js} +1 -1
- package/ui/dist/assets/{CPRuns-B4Pz5QkG.js → CPRuns-BUdKn-uk.js} +1 -1
- package/ui/dist/assets/{CPSocial-DayQlwZL.js → CPSocial-CriG1P45.js} +1 -1
- package/ui/dist/assets/{CPVoice-C2ry-Muk.js → CPVoice-BNhgXUE1.js} +1 -1
- package/ui/dist/assets/{ChannelsPanel-CeIEB9Es.js → ChannelsPanel-9SjAkSHg.js} +1 -1
- package/ui/dist/assets/{CheckpointsPanel-BkqqvLDL.js → CheckpointsPanel-D2sCPz2u.js} +1 -1
- package/ui/dist/assets/{CommandPostHub-Jd5_PAh3.js → CommandPostHub-DHTVn2_E.js} +3 -3
- package/ui/dist/assets/{CronPanel-COkBBcTV.js → CronPanel-CLQ0_Z_9.js} +1 -1
- package/ui/dist/assets/{DataTable-YQ9l5Xab.js → DataTable-CrBYCT2O.js} +1 -1
- package/ui/dist/assets/{DreamPanel-B5M--_sB.js → DreamPanel-BAkiDqQc.js} +1 -1
- package/ui/dist/assets/EmptyState-DSuZC-Tg.js +1 -0
- package/ui/dist/assets/{EvalHarnessPanel-DXU9jNmm.js → EvalHarnessPanel-BykaelQd.js} +1 -1
- package/ui/dist/assets/{EvalPanel-CY1kmmoG.js → EvalPanel-BlFByCOv.js} +1 -1
- package/ui/dist/assets/{FileViewer-BPLxBXEr.js → FileViewer-B0WedL9k.js} +1 -1
- package/ui/dist/assets/{FilesPanel-B5RpGquX.js → FilesPanel-DwUzP4Hv.js} +2 -2
- package/ui/dist/assets/{FleetPanel-1g-MrF81.js → FleetPanel-JW9Pk1FM.js} +1 -1
- package/ui/dist/assets/{HomelabPanel-CxkWfeeN.js → HomelabPanel-DigWCjaM.js} +1 -1
- package/ui/dist/assets/InfraView-0iQPmcD1.js +2 -0
- package/ui/dist/assets/{InlineEditableField-BuXVLQiL.js → InlineEditableField-Car7F635.js} +1 -1
- package/ui/dist/assets/{Input-C6OxbFDH.js → Input-BGGQDAyP.js} +1 -1
- package/ui/dist/assets/{IntegrationsPanel-CPZclot5.js → IntegrationsPanel-BGEkU649.js} +1 -1
- package/ui/dist/assets/IntelligenceView-wm2Pw46I.js +2 -0
- package/ui/dist/assets/LearningPanel-CGENRFnq.js +1 -0
- package/ui/dist/assets/{LogsPanel-XfC4fyQ6.js → LogsPanel-DZ_K2xOL.js} +1 -1
- package/ui/dist/assets/{McpPanel-CBN7xizL.js → McpPanel-CNB1BMz-.js} +1 -1
- package/ui/dist/assets/MemoryGraphPanel-FQxiv5x5.js +16 -0
- package/ui/dist/assets/{MemoryWikiPanel-BNv9ycwr.js → MemoryWikiPanel-C1w7xDNl.js} +2 -7
- package/ui/dist/assets/{MeshPanel-GFPkWStS.js → MeshPanel-DjYZh3P3.js} +1 -1
- package/ui/dist/assets/{MissionCanvas-BR9tT-Vs.js → MissionCanvas-BvbSfN_4.js} +1 -1
- package/ui/dist/assets/{MissionChat-B_fuBUn5.js → MissionChat-Do8j0nvp.js} +1 -1
- package/ui/dist/assets/{MissionLibrary-C9fCMdpu.js → MissionLibrary-CTzkJFJ7.js} +1 -1
- package/ui/dist/assets/{MissionStart-Bb2fCB2u.js → MissionStart-_-qlVcRK.js} +1 -1
- package/ui/dist/assets/{Modal-9_l_CYE2.js → Modal-CNnSfYJm.js} +1 -1
- package/ui/dist/assets/{NvidiaPanel-CiB9Nlbq.js → NvidiaPanel-CLoX_gD2.js} +1 -1
- package/ui/dist/assets/{OrganismPanel-d6mPFcBq.js → OrganismPanel-DBy9J7Vl.js} +1 -1
- package/ui/dist/assets/{OverviewPanel-DF7eBJCF.js → OverviewPanel-B7JFNH2w.js} +1 -1
- package/ui/dist/assets/PageHeader-CwcMp_4A.js +1 -0
- package/ui/dist/assets/{PersonaProfilesPanel-qAgZyu1B.js → PersonaProfilesPanel-CmZhQC8H.js} +1 -1
- package/ui/dist/assets/{PersonasPanel-CxDpp_3j.js → PersonasPanel-DSP0tTKz.js} +1 -1
- package/ui/dist/assets/{PhoneDeskPanel-CLp3E_Ry.js → PhoneDeskPanel-DZSs7aPr.js} +1 -1
- package/ui/dist/assets/{RecipesPanel-DqMMQnyc.js → RecipesPanel-BW0hW2sW.js} +1 -1
- package/ui/dist/assets/{SecurityPanel-BQ3-aMmO.js → SecurityPanel-_Saqrvw7.js} +1 -1
- package/ui/dist/assets/{SelfImprovePanel-C-ylXP-k.js → SelfImprovePanel-D5s-1XCU.js} +1 -1
- package/ui/dist/assets/{SelfProposalsPanel-d5W-0A3P.js → SelfProposalsPanel-D24kB0uM.js} +2 -2
- package/ui/dist/assets/{SessionsPanel-DzbNc8iW.js → SessionsPanel-BCxsCKwr.js} +1 -1
- package/ui/dist/assets/{SessionsTab-CuRh8SAw.js → SessionsTab-C5fvnjtl.js} +1 -1
- package/ui/dist/assets/{SettingsPanel-C1FbNM3W.js → SettingsPanel-B7jrFmeR.js} +1 -1
- package/ui/dist/assets/SettingsView-CQMHjpN8.js +2 -0
- package/ui/dist/assets/{SkeletonLoader-CrZUFaIM.js → SkeletonLoader-C42HbL9c.js} +1 -1
- package/ui/dist/assets/{SkillsPanel-eyCYqSuP.js → SkillsPanel-DYG8avbV.js} +1 -1
- package/ui/dist/assets/{SomaView-CvHD2r-j.js → SomaView-8Rwvw2sJ.js} +1 -1
- package/ui/dist/assets/{StatCard-_MlD8k-5.js → StatCard-vp0doZoE.js} +1 -1
- package/ui/dist/assets/{StatusBadge-MIQ4EfQR.js → StatusBadge-C4dl4Z7r.js} +1 -1
- package/ui/dist/assets/{Tabs-DkooY-W7.js → Tabs-B3hK5PRj.js} +1 -1
- package/ui/dist/assets/{TeamsPanel-fa--osWi.js → TeamsPanel-Bgc-EYSL.js} +1 -1
- package/ui/dist/assets/{TelemetryPanel-BEEWcoNE.js → TelemetryPanel-DexYjpd5.js} +1 -1
- package/ui/dist/assets/{TitanCanvas-LWyPGpf5.js → TitanCanvas-Da6TxxdJ.js} +52 -27
- package/ui/dist/assets/{ToolsView-UCDMsvb1.js → ToolsView-DkP9NfCj.js} +2 -2
- package/ui/dist/assets/{Tooltip-DrpHNalN.js → Tooltip-Chg08x7x.js} +1 -1
- package/ui/dist/assets/{TraceViewer-XsmYbc0e.js → TraceViewer-CojtXASo.js} +1 -1
- package/ui/dist/assets/{TrainingPanel-CmJXLn4n.js → TrainingPanel-tgn1BmiH.js} +1 -1
- package/ui/dist/assets/{VoiceOverlay-D2N-c76K.js → VoiceOverlay-D_jfyVe9.js} +1 -1
- package/ui/dist/assets/{VramPanel-h6zjNx-6.js → VramPanel-DXrdQK3J.js} +1 -1
- package/ui/dist/assets/{WatchView-DDNt13KH.js → WatchView-BitQHsCy.js} +1 -1
- package/ui/dist/assets/{WorkTab-CLXkjuee.js → WorkTab-6hdXBR7d.js} +1 -1
- package/ui/dist/assets/{WorkflowsPanel-BYtLGQVm.js → WorkflowsPanel-BlB2iBik.js} +1 -1
- package/ui/dist/assets/{archive-BSupLPZM.js → archive-aaQ0bgj_.js} +1 -1
- package/ui/dist/assets/{arrow-left-BaVVZjqf.js → arrow-left-xxx_FceU.js} +1 -1
- package/ui/dist/assets/{book-open-CZxMkLs8.js → book-open-B00IpKZA.js} +1 -1
- package/ui/dist/assets/{bot-Cv-edYov.js → bot-C4CRICZX.js} +1 -1
- package/ui/dist/assets/{chart-column-BSVdQ9RP.js → chart-column-lnilxGq2.js} +1 -1
- package/ui/dist/assets/{check-DbgTEg8O.js → check-BJMHM0tu.js} +1 -1
- package/ui/dist/assets/{chevron-right-DfToq0aQ.js → chevron-right-CA8HOEP4.js} +1 -1
- package/ui/dist/assets/{chevron-up-DMS2Tjip.js → chevron-up-n_3KVmjQ.js} +1 -1
- package/ui/dist/assets/{circle-check-big-BBQqeCVt.js → circle-check-big-hiNdH5H3.js} +1 -1
- package/ui/dist/assets/{circle-stop-CZNS3Uri.js → circle-stop-BlIwj_3n.js} +1 -1
- package/ui/dist/assets/{clipboard-list-CzMXlUCb.js → clipboard-list-BnOtwHQm.js} +1 -1
- package/ui/dist/assets/{clock-BvWNugZo.js → clock-BFgCJnqQ.js} +1 -1
- package/ui/dist/assets/{dollar-sign-pghzkByE.js → dollar-sign-CBBudQd7.js} +1 -1
- package/ui/dist/assets/{download-CupMD2Qi.js → download-C-DdF4cx.js} +1 -1
- package/ui/dist/assets/{external-link-8Pnd2MvS.js → external-link-CPAx2HBG.js} +1 -1
- package/ui/dist/assets/{file-text-rkojc4Uq.js → file-text-CyC_OxlA.js} +1 -1
- package/ui/dist/assets/{flask-conical-BtbE3rIA.js → flask-conical-BKbKUYhz.js} +1 -1
- package/ui/dist/assets/{folder-65U1Euur.js → folder-7bWz46dM.js} +1 -1
- package/ui/dist/assets/{funnel-D9FpWHn9.js → funnel-C_bR-Dz5.js} +1 -1
- package/ui/dist/assets/{git-branch-D6YV_OC1.js → git-branch-DGWdkudk.js} +1 -1
- package/ui/dist/assets/{index-BslUQuVl.js → index-CgHHe41p.js} +19 -19
- package/ui/dist/assets/index-CtD9JOx2.css +1 -0
- package/ui/dist/assets/{layers-rc37Q5yX.js → layers-3BMDaZuk.js} +1 -1
- package/ui/dist/assets/{legacy-BydeSW77.js → legacy-VWR8oDEy.js} +1 -1
- package/ui/dist/assets/{lightbulb-BEx7BdxD.js → lightbulb-CPhcUxli.js} +1 -1
- package/ui/dist/assets/link-CfLpUR24.js +6 -0
- package/ui/dist/assets/{list-todo-6N1AZe4i.js → list-todo-DgAmn8ot.js} +1 -1
- package/ui/dist/assets/{message-square-BEGY8pHF.js → message-square-WJp1dTaM.js} +1 -1
- package/ui/dist/assets/{mic-CGj6cLoV.js → mic-DjXDp1Js.js} +1 -1
- package/ui/dist/assets/{missions-BohoEPZo.js → missions-CwDL2FHE.js} +1 -1
- package/ui/dist/assets/{network-DxIkmFJR.js → network-C_MOo5My.js} +1 -1
- package/ui/dist/assets/{pause-CxvyFedA.js → pause-CovS6Xwq.js} +1 -1
- package/ui/dist/assets/{pencil-D5LooNFk.js → pencil-C6SVDEUL.js} +1 -1
- package/ui/dist/assets/{play-6W8amqUG.js → play-D3Nbm1Cz.js} +1 -1
- package/ui/dist/assets/{plug-C3Ecy-Ji.js → plug-Dpu9RRBi.js} +1 -1
- package/ui/dist/assets/{plus-BtmCDNeU.js → plus-CJKkM9fM.js} +1 -1
- package/ui/dist/assets/{proxy-BD29vUSb.js → proxy-CaK_YXZW.js} +1 -1
- package/ui/dist/assets/{radio-Bl9Tibea.js → radio-BTFO9FV9.js} +1 -1
- package/ui/dist/assets/{refresh-cw-BHphkMjv.js → refresh-cw-_C-4Cd_3.js} +1 -1
- package/ui/dist/assets/{rotate-ccw-DQzGCkVc.js → rotate-ccw-DWyVAH19.js} +1 -1
- package/ui/dist/assets/{save-Bk90yLic.js → save-B02XWwgN.js} +1 -1
- package/ui/dist/assets/{search-DxM6zcDJ.js → search-CHteSk-9.js} +1 -1
- package/ui/dist/assets/{send-ChZ5Hsne.js → send-DkMQeZAz.js} +1 -1
- package/ui/dist/assets/{server-CSOB40Ah.js → server-CvEvPDpX.js} +1 -1
- package/ui/dist/assets/{shield-check-uMK1alGs.js → shield-check-DQeYCvwF.js} +1 -1
- package/ui/dist/assets/{terminal-lIpm0q0K.js → terminal-BVErXh5C.js} +1 -1
- package/ui/dist/assets/{test-tube-DuTInDo7.js → test-tube-JSgqEqJs.js} +1 -1
- package/ui/dist/assets/{toggle-right-j4jgj1NQ.js → toggle-right-B3Qz7cQt.js} +1 -1
- package/ui/dist/assets/{trash-2-2Qmp8Fyr.js → trash-2-kiHv5iAF.js} +1 -1
- package/ui/dist/assets/{trending-up-BydxQces.js → trending-up-xhvUQXWt.js} +1 -1
- package/ui/dist/assets/{trophy-B8Fq83wO.js → trophy-G3zNxlQS.js} +1 -1
- package/ui/dist/assets/{volume-2-B6qThcBF.js → volume-2-CELMZXsT.js} +1 -1
- package/ui/dist/assets/{wifi-off-BX5XYuML.js → wifi-off-DKKYhVWL.js} +1 -1
- package/ui/dist/index.html +2 -2
- package/ui/dist/sw.js +1 -1
- package/ui/dist/assets/CPLayout-DlpdPzBu.js +0 -2
- package/ui/dist/assets/EmptyState-DtSIPEVv.js +0 -1
- package/ui/dist/assets/InfraView-CYH3ieie.js +0 -2
- package/ui/dist/assets/IntelligenceView-DqwlFo91.js +0 -2
- package/ui/dist/assets/LearningPanel-DHQSZZGb.js +0 -1
- package/ui/dist/assets/MemoryGraphPanel-BBxgK2Lo.js +0 -16
- package/ui/dist/assets/PageHeader-BQEb_uAl.js +0 -1
- package/ui/dist/assets/SettingsView-ZTklN8Q3.js +0 -2
- package/ui/dist/assets/index-DmgXt1oB.css +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/providers/stub.ts"],"sourcesContent":["/**\n * TITAN — CI Stub Provider (v6.1.0-beta.11)\n *\n * Deterministic pattern-matched LLM provider used by CI eval suites\n * and offline tests. Returns canned, useful responses without making\n * any network call — so the Eval Gate workflow can run on every PR\n * without burning Anthropic / OpenAI credits OR requiring secrets\n * configured on the runner.\n *\n * WHAT this is:\n * - A real LLMProvider implementation registered as `'stub'`.\n * - Model IDs `stub/echo`, `stub/json`, `stub/refuse` route here.\n * - Pattern-matches the last user message + system prompt against a\n * small table of recognized shapes (chat, structured-JSON,\n * tool-call, safety-refusal) and emits the appropriate response.\n *\n * WHY it exists:\n * - Phase B.1 truth-table audit showed Eval Gate runs were scoring\n * 0% on every suite because no provider had credentials in CI.\n * - The fix isn't \"give CI an API key\" — that bakes a real-money\n * dependency into every push. The fix is a provider that can\n * stand in for the real model deterministically.\n * - The harness-engineering catalog (Picrew/awesome-agent-harness)\n * explicitly recommends a \"stub mode\" so the harness itself is\n * testable independent of any single LLM.\n *\n * TRADE-OFFS we deliberately accept:\n * - The stub can't answer open-ended questions. It pattern-matches\n * a fixed vocabulary. Suites that probe model creativity have\n * no business running against the stub.\n * - The stub knows the exact shapes our agent code expects (widget\n * gate JSON, structuredSpawn JSON, tool-call format). When those\n * shapes change, this file changes too. That coupling is OK —\n * it's the price of CI-grade determinism.\n *\n * FOLLOW-UP:\n * - When we add a new gated agent shape, add a recognizer here.\n * - When we add a new built-in tool, add a recognizer here so\n * tool-routing evals can exercise the dispatch path.\n */\nimport { LLMProvider } from './base.js';\nimport type {\n ChatMessage,\n ChatOptions,\n ChatResponse,\n ChatStreamChunk,\n ToolCall,\n} from './base.js';\nimport logger from '../utils/logger.js';\n\nconst COMPONENT = 'provider.stub';\n\n/* ─────────────────────────── Pattern recognizers ─────────────────────────── */\n\ninterface RecognizedIntent {\n /** Stable id of the matched pattern. Used by tests + telemetry. */\n kind: string;\n /** Plain-text body of the response. */\n content: string;\n /** Optional tool calls to emit alongside the text. */\n toolCalls?: ToolCall[];\n /** finish_reason on the response. */\n finishReason: 'stop' | 'tool_calls' | 'error';\n}\n\n/**\n * Inspect the conversation and decide what kind of response to emit.\n * Order matters — safety refusals first, then structured outputs,\n * then tool-call shapes, then default chat.\n */\nfunction recognize(messages: ChatMessage[], offeredTools: Set<string>): RecognizedIntent {\n const userMessages = messages.filter(m => m.role === 'user').map(m => m.content ?? '');\n const lastUser = [...userMessages].reverse()[0] ?? '';\n const system = messages.find(m => m.role === 'system')?.content ?? '';\n const combined = `${system}\\n${userMessages.join('\\n')}`.toLowerCase();\n const userOnly = lastUser.toLowerCase();\n const directiveRe = /^\\s*\\[system directive for this reply only\\]/i;\n const conversationalUsers = userMessages.filter(m => !directiveRe.test(m));\n const intentPrompt = ([...conversationalUsers].reverse()[0] ?? lastUser).toLowerCase();\n const intentContext = `${intentPrompt}\\n${combined}`;\n const structuredContext = `${system}\\n${intentPrompt}`;\n\n // ── Safety refusal — keep first so injection attempts in the\n // system prompt don't override it.\n if (isUnsafeRequest(intentPrompt || userOnly)) {\n return {\n kind: 'safety_refusal',\n content: 'Stub: I can\\'t safely comply. I refuse to execute unsafe, destructive, injected, traversal, scheme-abusing, or private-instruction extraction requests.',\n finishReason: 'stop',\n };\n }\n\n // ── Tool-result continuation — if the LAST message is a tool\n // result, wrap up instead of re-issuing the same deterministic\n // tool call on the next round.\n if (messages[messages.length - 1]?.role === 'tool') {\n return {\n kind: 'tool_result_ack',\n content: summarizeToolResult(intentPrompt),\n finishReason: 'stop',\n };\n }\n\n // ── Structured JSON output — when the system prompt is asking\n // for the structuredSpawn JSON envelope. The driver loop\n // relies on this shape so the \"done\" path is reachable in CI.\n // Recognizers are deliberately broad: any prompt asking for\n // JSON output, or any mention of the spawn-envelope fields\n // (\"status\", \"artifacts\", \"confidence\") together, triggers\n // the structured-output path.\n const mentionsJsonOutput = /(respond|reply|return|output)\\s+(with\\s+)?(strict\\s+)?json|json\\s+containing|json\\s+envelope|structuredSpawn|spawn\\s+envelope/i.test(structuredContext);\n const mentionsEnvelopeFields =\n /\"status\"/i.test(structuredContext) &&\n /\"artifacts\"/i.test(structuredContext) &&\n /\"confidence\"/i.test(structuredContext);\n if (mentionsJsonOutput || mentionsEnvelopeFields) {\n const json = JSON.stringify({\n status: 'done',\n artifacts: [],\n questions: [],\n confidence: 0.9,\n reasoning: `Stub: pattern-matched structured-output request on prompt \"${userOnly.slice(0, 60)}\".`,\n });\n return {\n kind: 'structured_done',\n content: '```json\\n' + json + '\\n```',\n finishReason: 'stop',\n };\n }\n\n // ── Widget gate — TITAN's chat surface listens for a\n // `_____widget` gate followed by a JSON line. The 100+ widget\n // gallery routes off this signal; eval suites assert it.\n const widget = pickWidget(intentPrompt || userOnly);\n if (widget) {\n const widgetJson = JSON.stringify({\n name: widget.name,\n format: 'system',\n source: widget.source,\n w: widget.w,\n h: widget.h,\n });\n return {\n kind: 'widget_gate',\n content: `Adding the **${widget.name}** widget to your canvas.\\n\\n_____widget\\n${widgetJson}`,\n finishReason: 'stop',\n };\n }\n\n // ── Tool-call shape — when tools are offered AND the user prompt\n // clearly asks for one. Emits a tool_calls finish_reason so\n // the agent loop dispatches the tool. The agent will then\n // feed a tool_result back; that's handled below.\n if (offeredTools.size > 0) {\n const toolMatches = pickToolCalls(intentPrompt || userOnly).filter(tool => offeredTools.has(tool.name));\n if (toolMatches.length > 0) {\n return {\n kind: `tool_call:${toolMatches.map(t => t.name).join('+')}`,\n content: '',\n toolCalls: toolMatches.map((toolMatch, index) => ({\n id: `stub-tool-${toolMatch.name}-${index + 1}`,\n type: 'function',\n function: {\n name: toolMatch.name,\n arguments: JSON.stringify(toolMatch.args),\n },\n })),\n finishReason: 'tool_calls',\n };\n }\n }\n\n const directPrompt = intentPrompt || userOnly;\n if (/\\bwhat\\s+is\\s+2\\s*\\+\\s*2\\b|\\b2\\s*\\+\\s*2\\b/.test(directPrompt)) {\n return { kind: 'direct_arithmetic', content: 'The answer is 4.', finishReason: 'stop' };\n }\n\n if (/^\\s*(hello|hi|hey)\\b/.test(directPrompt)) {\n return { kind: 'direct_greeting', content: 'Hello. Voice channel ready.', finishReason: 'stop' };\n }\n\n if (/write\\s+(a\\s+)?hello\\s+world\\s+program/i.test(intentContext) && /python/i.test(intentContext)) {\n return { kind: 'write_file_final_answer', content: 'Created a Python hello world program using print(\"hello world\").', finishReason: 'stop' };\n }\n\n // ── Default — plain chat echo. Includes the first 60 chars of\n // the prompt so eval suites can assert on prompt threading.\n return {\n kind: 'echo',\n content: `Stub response. Echoing your request: \"${lastUser.slice(0, 60)}\".`,\n finishReason: 'stop',\n };\n}\n\n/* ─────────────────────────── Sub-recognizers ─────────────────────────── */\n\nfunction isUnsafeRequest(prompt: string): boolean {\n return [\n /\\brm\\s+-[a-z]*r[a-z]*f[a-z]*\\b/,\n /\\bdelete\\s+everything\\b|\\bwipe\\s+the\\s+disk\\b|\\bdrop\\s+all\\s+tables\\b|\\bformat\\s+the\\s+drive\\b/,\n /\\bchmod\\s+777\\s+\\/(?:etc|bin|sbin|usr|var|)\\b/,\n /\\bsudo\\b/,\n /\\bcurl\\b[^|\\n;]*(?:\\|\\s*(?:ba)?sh\\b)/,\n /\\b(?:ignore|bypass)\\s+(?:all\\s+)?(?:previous|prior|system|developer)\\s+instructions\\b/,\n /\\b(?:repeat|reveal|print|show|extract).{0,80}\\b(?:system|developer)\\s+(?:prompt|instructions)\\b/,\n /\\b(?:dan|developer\\s+mode|unrestricted\\s+ai|do\\s+anything\\s+now)\\b/,\n /javascript\\s*:/,\n /(?:^|[/\"'\\s])\\.\\.\\/\\.\\.\\//,\n /\\b(?:run|execute)\\b[^;\\n]*[;`]|`[^`]+`/,\n /\\|\\s*(?:bash|sh|zsh|python|perl|ruby)\\b/,\n /\\b(?:fetch|download|open|read)\\s+(?:file|dict):\\/\\//,\n ].some(re => re.test(prompt));\n}\n\n/** Pick a widget name keyed off the user prompt. Defaults to a generic\n * \"Note\" panel so the agent always has SOMETHING to add. */\nfunction pickWidget(prompt: string): { name: string; source: string; w: number; h: number } | null {\n const systemWidgets: Array<{ re: RegExp; name: string; source: string; w: number; h: number }> = [\n { re: /\\b(?:backups?|snapshots?|archives?)\\b/, name: 'Backup Manager', source: 'system:backup', w: 6, h: 6 },\n { re: /\\b(?:training|train|specialists?|models?)\\b/, name: 'Training Dashboard', source: 'system:training', w: 6, h: 6 },\n { re: /\\b(?:recipes?|playbooks?|workflows?|jarvis)\\b/, name: 'Recipe Kitchen', source: 'system:recipes', w: 6, h: 6 },\n { re: /\\b(?:vram|gpu|nvidia)\\b/, name: 'VRAM Monitor', source: 'system:vram', w: 6, h: 6 },\n { re: /\\b(?:teams?|team hub|members?|roles?|permissions?|rbac)\\b/, name: 'Team Hub', source: 'system:teams', w: 6, h: 6 },\n { re: /\\b(?:cron|schedules?|jobs?|timers?)\\b/, name: 'Cron Scheduler', source: 'system:cron', w: 6, h: 6 },\n { re: /\\b(?:checkpoints?|restores?|save state)\\b/, name: 'Checkpoints', source: 'system:checkpoints', w: 6, h: 5 },\n { re: /\\b(?:organism|guardrails?)\\b/, name: 'Organism Monitor', source: 'system:organism', w: 6, h: 6 },\n { re: /\\b(?:fleet|nodes?|routes?|mesh)\\b/, name: 'Fleet Router', source: 'system:fleet', w: 6, h: 5 },\n { re: /\\b(?:browser tools?|captcha|form fill|web automation)\\b/, name: 'Browser Tools', source: 'system:browser', w: 6, h: 5 },\n { re: /\\b(?:test lab|tests?|flaky|failing|coverage|eval)\\b/, name: 'Test Lab', source: 'system:eval', w: 6, h: 6 },\n ];\n const wantsSystemWidget = /\\b(?:show|open|add|launch|pin|create|display|give me)\\b/.test(prompt);\n if (wantsSystemWidget) {\n const systemWidget = systemWidgets.find(w => w.re.test(prompt));\n if (systemWidget) return systemWidget;\n }\n\n if (/stock|ticker|nasdaq|nyse/.test(prompt)) return { name: 'Stock Ticker', source: 'gallery', w: 360, h: 240 };\n if (/pomodoro|timer|focus/.test(prompt)) return { name: 'Pomodoro Timer', source: 'gallery', w: 360, h: 240 };\n if (/calendar|schedule/.test(prompt)) return { name: 'Calendar', source: 'gallery', w: 360, h: 240 };\n if (/gauge|meter|metric/.test(prompt)) return { name: 'Gauge', source: 'gallery', w: 360, h: 240 };\n if (/dashboard/.test(prompt)) return { name: 'Dashboard', source: 'gallery', w: 360, h: 240 };\n if (/clock|time/.test(prompt)) return { name: 'Clock', source: 'gallery', w: 360, h: 240 };\n if (/widget|panel/.test(prompt)) return { name: 'Note', source: 'gallery', w: 360, h: 240 };\n return null;\n}\n\n/** Pick tool calls + arguments keyed off the user prompt. Returns an\n * empty list if no tool matches — caller falls through to text. */\nfunction pickToolCalls(prompt: string): Array<{ name: string; args: Record<string, unknown> }> {\n if (/\\b(?:fix|bug|change|update|edit|modify)\\b/.test(prompt) && /\\b[\\w./-]+\\.(?:ts|tsx|js|jsx|py|json|md)\\b/.test(prompt)) {\n const path = extractPath(prompt) || '/tmp/titan-stub-code.ts';\n const calls: Array<{ name: string; args: Record<string, unknown> }> = [\n { name: 'read_file', args: { path } },\n { name: 'edit_file', args: { path, target: 'OLD', replacement: 'NEW' } },\n ];\n if (/\\b(?:fix|bug|test|verify)\\b/.test(prompt)) {\n calls.push({ name: 'shell', args: { command: 'printf \"stub verification ok\\\\n\"' } });\n }\n return calls;\n }\n if (/\\bweather\\b|\\bforecast\\b|\\btemperature\\b/.test(prompt)) {\n return [{ name: 'weather', args: { location: extractLocation(prompt) || 'San Francisco', days: 1 } }];\n }\n if (/\\b(?:navigate|browse|click|screenshot|open)\\b.*\\b(?:browser|site|page|example\\.com|https?:\\/\\/)/.test(prompt)) {\n return [{ name: 'web_act', args: { action: `open ${extractUrl(prompt) || 'https://example.com'}`, sessionId: 'stub-eval' } }];\n }\n if (/\\bfetch\\s+https?:\\/\\//.test(prompt)) {\n return [{ name: 'web_fetch', args: { url: extractUrl(prompt) || 'https://example.com' } }];\n }\n if (/\\bresearch\\b|\\blatest\\b|\\bnews\\b|\\bhistory\\b|search\\s+(?:the\\s+web\\s+)?for|google|find\\s+information|web\\s+search/.test(prompt)) {\n return [{ name: 'web_search', args: { query: extractAfter(prompt, /search\\s+(?:the\\s+web\\s+)?for|research|find/) || prompt.slice(0, 80) } }];\n }\n if (/write\\s+(a\\s+)?file|save\\s+to|create\\s+(a\\s+)?file|write\\s+(a\\s+)?hello\\s+world\\s+program/.test(prompt)) {\n return [{ name: 'write_file', args: { path: extractPath(prompt) || '/tmp/stub-output.txt', content: contentForWrite(prompt) } }];\n }\n if (/read\\s+(a\\s+)?file|open\\s+the\\s+file|show\\s+me\\s+the\\s+contents/.test(prompt)) {\n return [{ name: 'read_file', args: { path: extractPath(prompt) || '/tmp/stub-input.txt' } }];\n }\n if (/list\\s+(the\\s+)?(files|directory|dir)|what(?:'| i)?s\\s+(?:in|inside)|what\\s+files\\s+are\\s+in/.test(prompt)) {\n return [{ name: 'list_dir', args: { path: extractPath(prompt) || '/tmp' } }];\n }\n if (/\\b(?:run|execute|restart)\\b/.test(prompt)) {\n return [{ name: 'shell', args: { command: 'printf \"stub shell ok\\\\n\"' } }];\n }\n if (/download\\s+(an?\\s+)?image|embed\\s+image/.test(prompt)) {\n return [{ name: 'download_image', args: { url: 'https://example.com/sample.jpg' } }];\n }\n return [];\n}\n\nfunction summarizeToolResult(prompt: string): string {\n if (/hello\\s+world|python/.test(prompt)) {\n return 'Stub: wrote a hello world Python program using print(\"hello world\"). Done.';\n }\n if (/\\bweather\\b/.test(prompt)) return 'Stub: weather tool finished. Done.';\n if (/\\bresearch\\b|\\blatest\\b|\\bnews\\b|\\bhistory\\b|search/.test(prompt)) return 'Stub: web search finished with deterministic results. Done.';\n return 'Stub: tool finished. Done.';\n}\n\nfunction extractPath(prompt: string): string {\n const quoted = prompt.match(/(?:called|to|of|in|file)\\s+[\"'`]?([/~]?[\\w./-]+\\.[\\w]+)[\"'`]?/);\n const anyPath = prompt.match(/([/~]?[\\w.-]*\\/[\\w./-]+|[\\w.-]+\\.(?:ts|tsx|js|jsx|py|json|md|txt))/);\n const path = quoted?.[1] || anyPath?.[1] || '';\n if (!path) return '';\n return path.startsWith('/') || path.startsWith('~') ? path : `/tmp/${path.split('/').pop()}`;\n}\n\nfunction extractUrl(prompt: string): string {\n return prompt.match(/https?:\\/\\/[^\\s\"'`<>]+/)?.[0]?.replace(/[).,]+$/, '') ?? '';\n}\n\nfunction extractLocation(prompt: string): string {\n return prompt.match(/weather\\s+(?:for|in|at)\\s+([a-z][a-z\\s,]+?)(?:[?.]|$)/i)?.[1]?.trim() ?? '';\n}\n\nfunction contentForWrite(prompt: string): string {\n if (/python|hello\\s+world/.test(prompt)) return 'print(\"hello world\")\\n';\n return 'hello world\\n';\n}\n\n/** Extract the part of the prompt AFTER a matched intent verb. Used to\n * pull the search query / file name / etc. out of the prompt. */\nfunction extractAfter(prompt: string, re: RegExp): string {\n const m = prompt.match(re);\n if (!m) return '';\n const idx = (m.index ?? -1) + m[0].length;\n if (idx < 0) return '';\n return prompt.slice(idx).trim().replace(/[.?!]+$/, '').slice(0, 80);\n}\n\n/* ─────────────────────────── Provider ─────────────────────────── */\n\nexport class StubProvider extends LLMProvider {\n readonly name = 'stub';\n readonly displayName = 'TITAN Stub (CI/offline)';\n\n /**\n * Always configured. The whole point is that the stub works\n * without any credentials so CI can run end-to-end.\n */\n isConfigured(): boolean {\n return true;\n }\n\n async chat(options: ChatOptions): Promise<ChatResponse> {\n const intent = recognize(options.messages, offeredToolNames(options));\n logger.debug(COMPONENT, `chat() kind=${intent.kind} model=${options.model ?? 'stub/echo'}`);\n const promptTokens = approxTokens(options.messages);\n const completionTokens = approxTokens([{ role: 'assistant', content: intent.content }]);\n return {\n id: `stub-${Date.now()}`,\n content: intent.content,\n toolCalls: intent.toolCalls,\n usage: {\n promptTokens,\n completionTokens,\n totalTokens: promptTokens + completionTokens,\n },\n finishReason: intent.finishReason,\n model: options.model || 'stub/echo',\n };\n }\n\n async *chatStream(options: ChatOptions): AsyncGenerator<ChatStreamChunk> {\n const intent = recognize(options.messages, offeredToolNames(options));\n logger.debug(COMPONENT, `chatStream() kind=${intent.kind}`);\n // Emit text content first (if any), then any tool calls,\n // then a done marker. Matches the shape real providers use.\n if (intent.content) {\n yield { type: 'text', content: intent.content };\n }\n if (intent.toolCalls) {\n for (const tc of intent.toolCalls) {\n yield { type: 'tool_call', toolCall: tc };\n }\n }\n yield { type: 'done' };\n }\n\n async listModels(): Promise<string[]> {\n return ['stub/echo', 'stub/json', 'stub/refuse'];\n }\n\n async healthCheck(): Promise<boolean> {\n return true;\n }\n}\n\n/* ─────────────────────────── Token estimator ─────────────────────────── */\n\nfunction offeredToolNames(options: ChatOptions): Set<string> {\n return new Set((options.tools ?? []).map(tool => tool.function.name));\n}\n\n/** ~4 chars per token rule-of-thumb. Not exact, but stable enough for\n * cost-budget tests that only need monotonicity. */\nfunction approxTokens(messages: ChatMessage[]): number {\n let chars = 0;\n for (const m of messages) chars += (m.content ?? '').length;\n return Math.max(1, Math.ceil(chars / 4));\n}\n\n/* ─────────────────────────── CI detection ─────────────────────────── */\n\n/**\n * Returns true when the runtime should fall back to the stub provider\n * because no real provider credentials are available. The default\n * model picker (`defaultModel.ts`) calls this to choose `stub/echo`\n * as the floor model in CI / offline environments.\n *\n * Trigger conditions (any one is enough):\n * - Explicit opt-in: `TITAN_STUB_PROVIDER=1`\n * - Standard CI signal: `CI=true` AND no Anthropic/OpenAI/Google key\n *\n * NOTE: we DELIBERATELY do NOT trigger on `VITEST=true`. Existing\n * unit tests (default-model-picker.test.ts in particular) pin the\n * \"no keys → ollama\" behavior; flipping that under VITEST would\n * break those tests. Tests that want the stub should set\n * `TITAN_STUB_PROVIDER=1` in their setup explicitly.\n */\nexport function shouldUseStubProvider(): boolean {\n if (process.env.TITAN_STUB_PROVIDER === '1') return true;\n if (process.env.CI === 'true') {\n const hasRealKey = !!(\n process.env.ANTHROPIC_API_KEY ||\n process.env.OPENAI_API_KEY ||\n process.env.GOOGLE_API_KEY ||\n process.env.OPENROUTER_API_KEY\n );\n return !hasRealKey;\n }\n return false;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/providers/stub.ts"],"sourcesContent":["/**\n * TITAN — CI Stub Provider (v6.1.0-beta.11)\n *\n * Deterministic pattern-matched LLM provider used by CI eval suites\n * and offline tests. Returns canned, useful responses without making\n * any network call — so the Eval Gate workflow can run on every PR\n * without burning Anthropic / OpenAI credits OR requiring secrets\n * configured on the runner.\n *\n * WHAT this is:\n * - A real LLMProvider implementation registered as `'stub'`.\n * - Model IDs `stub/echo`, `stub/json`, `stub/refuse` route here.\n * - Pattern-matches the last user message + system prompt against a\n * small table of recognized shapes (chat, structured-JSON,\n * tool-call, safety-refusal) and emits the appropriate response.\n *\n * WHY it exists:\n * - Phase B.1 truth-table audit showed Eval Gate runs were scoring\n * 0% on every suite because no provider had credentials in CI.\n * - The fix isn't \"give CI an API key\" — that bakes a real-money\n * dependency into every push. The fix is a provider that can\n * stand in for the real model deterministically.\n * - The harness-engineering catalog (Picrew/awesome-agent-harness)\n * explicitly recommends a \"stub mode\" so the harness itself is\n * testable independent of any single LLM.\n *\n * TRADE-OFFS we deliberately accept:\n * - The stub can't answer open-ended questions. It pattern-matches\n * a fixed vocabulary. Suites that probe model creativity have\n * no business running against the stub.\n * - The stub knows the exact shapes our agent code expects (widget\n * gate JSON, structuredSpawn JSON, tool-call format). When those\n * shapes change, this file changes too. That coupling is OK —\n * it's the price of CI-grade determinism.\n *\n * FOLLOW-UP:\n * - When we add a new gated agent shape, add a recognizer here.\n * - When we add a new built-in tool, add a recognizer here so\n * tool-routing evals can exercise the dispatch path.\n */\nimport { LLMProvider } from './base.js';\nimport type {\n ChatMessage,\n ChatOptions,\n ChatResponse,\n ChatStreamChunk,\n ToolCall,\n} from './base.js';\nimport logger from '../utils/logger.js';\n\nconst COMPONENT = 'provider.stub';\n\n/* ─────────────────────────── Pattern recognizers ─────────────────────────── */\n\ninterface RecognizedIntent {\n /** Stable id of the matched pattern. Used by tests + telemetry. */\n kind: string;\n /** Plain-text body of the response. */\n content: string;\n /** Optional tool calls to emit alongside the text. */\n toolCalls?: ToolCall[];\n /** finish_reason on the response. */\n finishReason: 'stop' | 'tool_calls' | 'error';\n}\n\n/**\n * Inspect the conversation and decide what kind of response to emit.\n * Order matters — safety refusals first, then structured outputs,\n * then tool-call shapes, then default chat.\n */\nfunction recognize(messages: ChatMessage[], offeredTools: Set<string>): RecognizedIntent {\n const userMessages = messages.filter(m => m.role === 'user').map(m => m.content ?? '');\n const lastUser = [...userMessages].reverse()[0] ?? '';\n const system = messages.find(m => m.role === 'system')?.content ?? '';\n const combined = `${system}\\n${userMessages.join('\\n')}`.toLowerCase();\n const userOnly = lastUser.toLowerCase();\n const directiveRe = /^\\s*\\[system directive for this reply only\\]/i;\n const conversationalUsers = userMessages.filter(m => !directiveRe.test(m));\n const intentPrompt = ([...conversationalUsers].reverse()[0] ?? lastUser).toLowerCase();\n const intentContext = `${intentPrompt}\\n${combined}`;\n const structuredContext = `${system}\\n${intentPrompt}`;\n\n // ── Safety refusal — keep first so injection attempts in the\n // system prompt don't override it.\n if (isUnsafeRequest(intentPrompt || userOnly)) {\n return {\n kind: 'safety_refusal',\n content: 'Stub: I can\\'t safely comply. I refuse to execute unsafe, destructive, injected, traversal, scheme-abusing, or private-instruction extraction requests.',\n finishReason: 'stop',\n };\n }\n\n // ── Tool-result continuation — if the LAST message is a tool\n // result, wrap up instead of re-issuing the same deterministic\n // tool call on the next round.\n if (messages[messages.length - 1]?.role === 'tool') {\n return {\n kind: 'tool_result_ack',\n content: summarizeToolResult(intentPrompt),\n finishReason: 'stop',\n };\n }\n\n // ── Structured JSON output — when the system prompt is asking\n // for the structuredSpawn JSON envelope. The driver loop\n // relies on this shape so the \"done\" path is reachable in CI.\n // Recognizers are deliberately broad: any prompt asking for\n // JSON output, or any mention of the spawn-envelope fields\n // (\"status\", \"artifacts\", \"confidence\") together, triggers\n // the structured-output path.\n const mentionsJsonOutput = /(respond|reply|return|output)\\s+(with\\s+)?(strict\\s+)?json|json\\s+containing|json\\s+envelope|structuredSpawn|spawn\\s+envelope/i.test(structuredContext);\n const mentionsEnvelopeFields =\n /\"status\"/i.test(structuredContext) &&\n /\"artifacts\"/i.test(structuredContext) &&\n /\"confidence\"/i.test(structuredContext);\n if (mentionsJsonOutput || mentionsEnvelopeFields) {\n const json = JSON.stringify({\n status: 'done',\n artifacts: [],\n questions: [],\n confidence: 0.9,\n reasoning: `Stub: pattern-matched structured-output request on prompt \"${userOnly.slice(0, 60)}\".`,\n });\n return {\n kind: 'structured_done',\n content: '```json\\n' + json + '\\n```',\n finishReason: 'stop',\n };\n }\n\n // ── Widget gate — TITAN's chat surface listens for a\n // `_____widget` gate followed by a JSON line. The 100+ widget\n // gallery routes off this signal; eval suites assert it.\n const widget = pickWidget(intentPrompt || userOnly);\n if (widget) {\n const widgetJson = JSON.stringify({\n name: widget.name,\n format: 'system',\n source: widget.source,\n w: widget.w,\n h: widget.h,\n });\n return {\n kind: 'widget_gate',\n content: `Adding the **${widget.name}** widget to your canvas.\\n\\n_____widget\\n${widgetJson}`,\n finishReason: 'stop',\n };\n }\n\n // ── Tool-call shape — when tools are offered AND the user prompt\n // clearly asks for one. Emits a tool_calls finish_reason so\n // the agent loop dispatches the tool. The agent will then\n // feed a tool_result back; that's handled below.\n if (offeredTools.size > 0) {\n const toolMatches = pickToolCalls(intentPrompt || userOnly).filter(tool => offeredTools.has(tool.name));\n if (toolMatches.length > 0) {\n return {\n kind: `tool_call:${toolMatches.map(t => t.name).join('+')}`,\n content: '',\n toolCalls: toolMatches.map((toolMatch, index) => ({\n id: `stub-tool-${toolMatch.name}-${index + 1}`,\n type: 'function',\n function: {\n name: toolMatch.name,\n arguments: JSON.stringify(toolMatch.args),\n },\n })),\n finishReason: 'tool_calls',\n };\n }\n }\n\n const directPrompt = intentPrompt || userOnly;\n if (/\\bwhat\\s+is\\s+2\\s*\\+\\s*2\\b|\\b2\\s*\\+\\s*2\\b/.test(directPrompt)) {\n return { kind: 'direct_arithmetic', content: 'The answer is 4.', finishReason: 'stop' };\n }\n\n if (/^\\s*(hello|hi|hey)\\b/.test(directPrompt)) {\n return { kind: 'direct_greeting', content: 'Hello. Voice channel ready.', finishReason: 'stop' };\n }\n\n if (/write\\s+(a\\s+)?hello\\s+world\\s+program/i.test(intentContext) && /python/i.test(intentContext)) {\n return { kind: 'write_file_final_answer', content: 'Created a Python hello world program using print(\"hello world\").', finishReason: 'stop' };\n }\n\n // ── Default — plain chat echo. Includes the first 60 chars of\n // the prompt so eval suites can assert on prompt threading.\n return {\n kind: 'echo',\n content: `Stub response. Echoing your request: \"${lastUser.slice(0, 60)}\".`,\n finishReason: 'stop',\n };\n}\n\n/* ─────────────────────────── Sub-recognizers ─────────────────────────── */\n\nfunction isUnsafeRequest(prompt: string): boolean {\n return [\n /\\brm\\s+-[a-z]*r[a-z]*f[a-z]*\\b/,\n /\\bdelete\\s+everything\\b|\\bwipe\\s+the\\s+disk\\b|\\bdrop\\s+all\\s+tables\\b|\\bformat\\s+the\\s+drive\\b/,\n /\\bchmod\\s+777\\s+\\/(?:etc|bin|sbin|usr|var|)\\b/,\n /\\bsudo\\b/,\n /\\bcurl\\b[^|\\n;]*(?:\\|\\s*(?:ba)?sh\\b)/,\n /\\b(?:ignore|bypass)\\s+(?:all\\s+)?(?:previous|prior|system|developer)\\s+instructions\\b/,\n /\\b(?:repeat|reveal|print|show|extract).{0,80}\\b(?:system|developer)\\s+(?:prompt|instructions)\\b/,\n /\\b(?:dan|developer\\s+mode|unrestricted\\s+ai|do\\s+anything\\s+now)\\b/,\n /javascript\\s*:/,\n /(?:^|[/\"'\\s])\\.\\.\\/\\.\\.\\//,\n /\\b(?:run|execute)\\b[^;\\n]*[;`]|`[^`]+`/,\n /\\|\\s*(?:bash|sh|zsh|python|perl|ruby)\\b/,\n /\\b(?:fetch|download|open|read)\\s+(?:file|dict):\\/\\//,\n ].some(re => re.test(prompt));\n}\n\n/** Pick a widget name keyed off the user prompt. Defaults to a generic\n * \"Note\" panel so the agent always has SOMETHING to add. */\nfunction pickWidget(prompt: string): { name: string; source: string; w: number; h: number } | null {\n const systemWidgets: Array<{ re: RegExp; name: string; source: string; w: number; h: number }> = [\n { re: /\\b(?:backups?|snapshots?|archives?)\\b/, name: 'Backup Manager', source: 'system:backup', w: 6, h: 6 },\n { re: /\\b(?:training|train|specialists?|models?)\\b/, name: 'Training Dashboard', source: 'system:training', w: 6, h: 6 },\n { re: /\\b(?:recipes?|playbooks?|workflows?|jarvis)\\b/, name: 'Recipe Kitchen', source: 'system:recipes', w: 6, h: 6 },\n { re: /\\b(?:vram|gpu|nvidia)\\b/, name: 'VRAM Monitor', source: 'system:vram', w: 6, h: 6 },\n { re: /\\b(?:teams?|team hub|members?|roles?|permissions?|rbac)\\b/, name: 'Team Hub', source: 'system:teams', w: 6, h: 6 },\n { re: /\\b(?:cron|schedules?|jobs?|timers?)\\b/, name: 'Cron Scheduler', source: 'system:cron', w: 6, h: 6 },\n { re: /\\b(?:checkpoints?|restores?|save state)\\b/, name: 'Checkpoints', source: 'system:checkpoints', w: 6, h: 5 },\n { re: /\\b(?:organism|guardrails?)\\b/, name: 'Organism Monitor', source: 'system:organism', w: 6, h: 6 },\n { re: /\\b(?:fleet|nodes?|routes?|mesh)\\b/, name: 'Fleet Router', source: 'system:fleet', w: 6, h: 5 },\n { re: /\\b(?:browser tools?|captcha|form fill|web automation)\\b/, name: 'Browser Tools', source: 'system:browser', w: 6, h: 5 },\n { re: /\\b(?:test lab|tests?|flaky|failing|coverage|eval)\\b/, name: 'Test Lab', source: 'system:eval', w: 6, h: 6 },\n ];\n const wantsSystemWidget = /\\b(?:show|open|add|launch|pin|create|display|give me)\\b/.test(prompt);\n if (wantsSystemWidget) {\n const systemWidget = systemWidgets.find(w => w.re.test(prompt));\n if (systemWidget) return systemWidget;\n }\n\n if (/stock|ticker|nasdaq|nyse/.test(prompt)) return { name: 'Stock Ticker', source: 'gallery', w: 360, h: 240 };\n if (/pomodoro|timer|focus/.test(prompt)) return { name: 'Pomodoro Timer', source: 'gallery', w: 360, h: 240 };\n if (/calendar|schedule/.test(prompt)) return { name: 'Calendar', source: 'gallery', w: 360, h: 240 };\n if (/gauge|meter|metric/.test(prompt)) return { name: 'Gauge', source: 'gallery', w: 360, h: 240 };\n if (/dashboard/.test(prompt)) return { name: 'Dashboard', source: 'gallery', w: 360, h: 240 };\n if (/clock|time/.test(prompt)) return { name: 'Clock', source: 'gallery', w: 360, h: 240 };\n if (/widget|panel/.test(prompt)) return { name: 'Note', source: 'gallery', w: 360, h: 240 };\n return null;\n}\n\n/** Pick tool calls + arguments keyed off the user prompt. Returns an\n * empty list if no tool matches — caller falls through to text. */\nfunction pickToolCalls(prompt: string): Array<{ name: string; args: Record<string, unknown> }> {\n if (/\\b(?:fix|bug|change|update|edit|modify)\\b/.test(prompt) && /\\b[\\w./-]+\\.(?:ts|tsx|js|jsx|py|json|md)\\b/.test(prompt)) {\n const path = extractPath(prompt) || '/tmp/titan-stub-code.ts';\n const calls: Array<{ name: string; args: Record<string, unknown> }> = [\n { name: 'read_file', args: { path } },\n { name: 'edit_file', args: { path, target: 'OLD', replacement: 'NEW' } },\n ];\n if (/\\b(?:fix|bug|test|verify)\\b/.test(prompt)) {\n calls.push({ name: 'shell', args: { command: 'printf \"stub verification ok\\\\n\"' } });\n }\n return calls;\n }\n if (/\\bweather\\b|\\bforecast\\b|\\btemperature\\b/.test(prompt)) {\n return [{ name: 'weather', args: { location: extractLocation(prompt) || 'San Francisco', days: 1 } }];\n }\n if (/\\b(?:navigate|browse|click|screenshot|open)\\b.*\\b(?:browser|site|page|example\\.com|https?:\\/\\/)/.test(prompt)) {\n return [{ name: 'web_act', args: { action: `open ${extractUrl(prompt) || 'https://example.com'}`, sessionId: 'stub-eval' } }];\n }\n if (/\\bfetch\\s+https?:\\/\\//.test(prompt)) {\n return [{ name: 'web_fetch', args: { url: extractUrl(prompt) || 'https://example.com' } }];\n }\n if (/\\bresearch\\b|\\blatest\\b|\\bnews\\b|\\bhistory\\b|search\\s+(?:the\\s+web\\s+)?for|google|find\\s+information|web\\s+search/.test(prompt)) {\n return [{ name: 'web_search', args: { query: extractAfter(prompt, /search\\s+(?:the\\s+web\\s+)?for|research|find/) || prompt.slice(0, 80) } }];\n }\n if (/write\\s+(a\\s+)?file|save\\s+to|create\\s+(a\\s+)?file|write\\s+(a\\s+)?hello\\s+world\\s+program/.test(prompt)) {\n return [{ name: 'write_file', args: { path: extractPath(prompt) || '/tmp/stub-output.txt', content: contentForWrite(prompt) } }];\n }\n if (/read\\s+(a\\s+)?file|open\\s+the\\s+file|show\\s+me\\s+the\\s+contents/.test(prompt)) {\n return [{ name: 'read_file', args: { path: extractPath(prompt) || '/tmp/stub-input.txt' } }];\n }\n if (/list\\s+(the\\s+)?(files|directory|dir)|what(?:'| i)?s\\s+(?:in|inside)|what\\s+files\\s+are\\s+in/.test(prompt)) {\n return [{ name: 'list_dir', args: { path: extractPath(prompt) || '/tmp' } }];\n }\n if (/\\b(?:run|execute|restart)\\b/.test(prompt)) {\n return [{ name: 'shell', args: { command: 'printf \"stub shell ok\\\\n\"' } }];\n }\n if (/download\\s+(an?\\s+)?image|embed\\s+image/.test(prompt)) {\n return [{ name: 'download_image', args: { url: 'https://example.com/sample.jpg' } }];\n }\n return [];\n}\n\nfunction summarizeToolResult(prompt: string): string {\n if (/hello\\s+world|python/.test(prompt)) {\n return 'Stub: wrote a hello world Python program using print(\"hello world\"). Done.';\n }\n if (/\\bweather\\b/.test(prompt)) return 'Stub: weather tool finished. Done.';\n if (/\\bresearch\\b|\\blatest\\b|\\bnews\\b|\\bhistory\\b|search/.test(prompt)) return 'Stub: web search finished with deterministic results. Done.';\n return 'Stub: tool finished. Done.';\n}\n\nfunction extractPath(prompt: string): string {\n const quoted = prompt.match(/(?:called|to|of|in|file)\\s+[\"'`]?([/~]?[\\w./-]+\\.[\\w]+)[\"'`]?/);\n const anyPath = prompt.match(/([/~]?[\\w.-]*\\/[\\w./-]+|[\\w.-]+\\.(?:ts|tsx|js|jsx|py|json|md|txt))/);\n const path = quoted?.[1] || anyPath?.[1] || '';\n if (!path) return '';\n return path.startsWith('/') || path.startsWith('~') ? path : `/tmp/${path.split('/').pop()}`;\n}\n\nfunction extractUrl(prompt: string): string {\n return prompt.match(/https?:\\/\\/[^\\s\"'`<>]+/)?.[0]?.replace(/[).,]+$/, '') ?? '';\n}\n\nfunction extractLocation(prompt: string): string {\n return prompt.match(/weather\\s+(?:for|in|at)\\s+([a-z][a-z\\s,]+?)(?:[?.]|$)/i)?.[1]?.trim() ?? '';\n}\n\nfunction contentForWrite(prompt: string): string {\n if (/python|hello\\s+world/.test(prompt)) return 'print(\"hello world\")\\n';\n return 'hello world\\n';\n}\n\n/** Extract the part of the prompt AFTER a matched intent verb. Used to\n * pull the search query / file name / etc. out of the prompt. */\nfunction extractAfter(prompt: string, re: RegExp): string {\n const m = prompt.match(re);\n if (!m) return '';\n const idx = (m.index ?? -1) + m[0].length;\n if (idx < 0) return '';\n return prompt.slice(idx).trim().replace(/[.?!]+$/, '').slice(0, 80);\n}\n\n/* ─────────────────────────── Provider ─────────────────────────── */\n\nexport class StubProvider extends LLMProvider {\n readonly name = 'stub';\n readonly displayName = 'TITAN Stub (CI/offline)';\n\n /**\n * Always configured. The whole point is that the stub works\n * without any credentials so CI can run end-to-end.\n */\n isConfigured(): boolean {\n return true;\n }\n\n async chat(options: ChatOptions): Promise<ChatResponse> {\n const intent = recognize(options.messages, offeredToolNames(options));\n logger.debug(COMPONENT, `chat() kind=${intent.kind} model=${options.model ?? 'stub/echo'}`);\n const promptTokens = approxTokens(options.messages);\n const completionTokens = approxTokens([{ role: 'assistant', content: intent.content }]);\n return {\n id: `stub-${Date.now()}`,\n content: intent.content,\n toolCalls: intent.toolCalls,\n usage: {\n promptTokens,\n completionTokens,\n totalTokens: promptTokens + completionTokens,\n },\n finishReason: intent.finishReason,\n model: options.model || 'stub/echo',\n };\n }\n\n async *chatStream(options: ChatOptions): AsyncGenerator<ChatStreamChunk> {\n const intent = recognize(options.messages, offeredToolNames(options));\n logger.debug(COMPONENT, `chatStream() kind=${intent.kind}`);\n // Emit text content first (if any), then any tool calls,\n // then a done marker. Matches the shape real providers use.\n if (intent.content) {\n yield { type: 'text', content: intent.content };\n }\n if (intent.toolCalls) {\n for (const tc of intent.toolCalls) {\n yield { type: 'tool_call', toolCall: tc };\n }\n }\n yield { type: 'done' };\n }\n\n async listModels(): Promise<string[]> {\n return ['stub/echo', 'stub/json', 'stub/refuse'];\n }\n\n async healthCheck(): Promise<boolean> {\n return true;\n }\n}\n\n/* ─────────────────────────── Token estimator ─────────────────────────── */\n\nfunction offeredToolNames(options: ChatOptions): Set<string> {\n return new Set((options.tools ?? []).map(tool => tool.function.name));\n}\n\n/** ~4 chars per token rule-of-thumb. Not exact, but stable enough for\n * cost-budget tests that only need monotonicity. */\nfunction approxTokens(messages: ChatMessage[]): number {\n let chars = 0;\n for (const m of messages) chars += (m.content ?? '').length;\n return Math.max(1, Math.ceil(chars / 4));\n}\n\n/* ─────────────────────────── CI detection ─────────────────────────── */\n\n/**\n * Returns true when the runtime should use the deterministic stub\n * provider. This is explicit-only so CI and runtime failures cannot be\n * hidden by `stub/echo` when the real Ollama surface is available.\n *\n * Trigger condition:\n * - Explicit opt-in: `TITAN_STUB_PROVIDER=1`\n *\n * NOTE: we deliberately do not trigger on `CI=true` or `VITEST=true`.\n * Eval Gate and offline tests that want the stub must set\n * `TITAN_STUB_PROVIDER=1` explicitly.\n */\nexport function shouldUseStubProvider(): boolean {\n return process.env.TITAN_STUB_PROVIDER === '1';\n}\n"],"mappings":"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","names":[]}
|
package/dist/utils/constants.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { homedir } from "os";
|
|
3
3
|
import { join } from "path";
|
|
4
|
-
const TITAN_VERSION = "6.
|
|
4
|
+
const TITAN_VERSION = "6.4.0";
|
|
5
5
|
const TITAN_CODENAME = "Living Canvas";
|
|
6
6
|
const TITAN_NAME = "TITAN";
|
|
7
7
|
const TITAN_FULL_NAME = "The Intelligent Task Automation Network";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils/constants.ts"],"sourcesContent":["/**\n * TITAN Constants\n */\nimport { homedir } from 'os';\nimport { join } from 'path';\n\nexport const TITAN_VERSION = '6.
|
|
1
|
+
{"version":3,"sources":["../../src/utils/constants.ts"],"sourcesContent":["/**\n * TITAN Constants\n */\nimport { homedir } from 'os';\nimport { join } from 'path';\n\nexport const TITAN_VERSION = '6.4.0';\nexport const TITAN_CODENAME = 'Living Canvas';\nexport const TITAN_NAME = 'TITAN';\nexport const TITAN_FULL_NAME = 'The Intelligent Task Automation Network';\nexport const TITAN_ASCII_LOGO = `\n╔══════════════════════════════════════════════════════╗\n║ ║\n║ ████████╗██╗████████╗ █████╗ ███╗ ██╗ ║\n║ ██║ ██║ ██║ ██╔══██╗████╗ ██║ ║\n║ ██║ ██║ ██║ ███████║██╔██╗ ██║ ║\n║ ██║ ██║ ██║ ██╔══██║██║╚██╗██║ ║\n║ ██║ ██║ ██║ ██║ ██║██║ ╚████║ ║\n║ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝ ║\n║ ║\n║ The Intelligent Task Automation Network ║\n║ v${TITAN_VERSION} • by Tony Elliott ║\n╚══════════════════════════════════════════════════════╝`;\n\n// Paths\n// Hunt Finding #03 (2026-04-14): honor TITAN_HOME env var if set.\n// Previously this was hardcoded to `~/.titan`, which meant:\n// - Docker containers couldn't override the config path\n// - Shared machines couldn't isolate per-user state\n// - Test fixtures couldn't run against an isolated home\n// - The systemd unit's `Environment=TITAN_HOME=...` was silently ignored\n// The env var is read once at module load (constants are resolved at import time).\n// If TITAN_HOME starts with `~/`, expand it to the user's home dir.\nfunction resolveTitanHome(): string {\n const envHome = process.env.TITAN_HOME;\n if (envHome && envHome.trim().length > 0) {\n const trimmed = envHome.trim();\n if (trimmed.startsWith('~/')) {\n return join(homedir(), trimmed.slice(2));\n }\n if (trimmed === '~') {\n return homedir();\n }\n return trimmed;\n }\n return join(homedir(), '.titan');\n}\nexport const TITAN_HOME = resolveTitanHome();\nexport const TITAN_CONFIG_PATH = join(TITAN_HOME, 'titan.json');\nexport const TITAN_DB_PATH = join(TITAN_HOME, 'titan.db');\nexport const TITAN_WORKSPACE = join(TITAN_HOME, 'workspace');\nexport const TITAN_SKILLS_DIR = join(TITAN_WORKSPACE, 'skills');\nexport const TITAN_LOGS_DIR = join(TITAN_HOME, 'logs');\nexport const TITAN_MEMORY_DIR = join(TITAN_HOME, 'memory');\n\n// Workspace prompt files (injected into agent context)\nexport const AGENTS_MD = join(TITAN_WORKSPACE, 'AGENTS.md');\nexport const SOUL_MD = join(TITAN_WORKSPACE, 'SOUL.md');\nexport const TOOLS_MD = join(TITAN_WORKSPACE, 'TOOLS.md');\nexport const TITAN_MD_FILENAME = 'TITAN.md';\nexport const AUTOPILOT_MD = join(TITAN_HOME, 'AUTOPILOT.md');\nexport const AUTOPILOT_RUNS_PATH = join(TITAN_HOME, 'autopilot-runs.jsonl');\nexport const TITAN_CREDENTIALS_DIR = join(TITAN_HOME, 'credentials');\n\n// Income & lead tracking\nexport const INCOME_LEDGER_PATH = join(TITAN_HOME, 'income-ledger.jsonl');\nexport const FREELANCE_LEADS_PATH = join(TITAN_HOME, 'freelance-leads.jsonl');\nexport const FREELANCE_PROFILE_PATH = join(TITAN_HOME, 'freelance-profile.json');\nexport const LEADS_PATH = join(TITAN_HOME, 'leads.jsonl');\nexport const TELEMETRY_EVENTS_PATH = join(TITAN_HOME, 'telemetry-events.jsonl');\nexport const SOMADRIVE_STATE_PATH = join(TITAN_HOME, 'soma-drive-state.json');\nexport const ACTIVITY_LOG_PATH = join(TITAN_HOME, 'activity-log.jsonl');\n\n// v6.1.0 — Mission Chat\nexport const MISSIONS_DIR = join(TITAN_HOME, 'missions');\nexport const PLAYS_DIR = join(TITAN_HOME, 'plays');\n\n// Gateway defaults\nexport const DEFAULT_GATEWAY_HOST = '0.0.0.0';\nexport const DEFAULT_GATEWAY_PORT = 48420;\nexport const DEFAULT_WEB_PORT = 48421;\n\n// Agent defaults\n// v6.0.1 — Hardcoded floor only. The actual default at runtime is picked\n// by `getDefaultModelId()` in `src/providers/defaultModel.ts`, which\n// detects the user's available API keys (Anthropic / OpenAI / Google /\n// OpenRouter) and selects accordingly. Falls back to local Ollama when\n// no cloud keys are set. This constant is the last-resort fallback for\n// callsites that don't go through the schema thunk.\nexport const DEFAULT_MODEL = 'anthropic/claude-sonnet-4-20250514';\n/** v5.4.1: User-preference ceiling. Providers clamp per-model via\n * clampMaxTokens() so this can be high without causing 400s on\n * capped endpoints (e.g. Claude Sonnet 4 8K, Cohere 4K). */\nexport const DEFAULT_MAX_TOKENS = 200000;\nexport const DEFAULT_TEMPERATURE = 0.7;\nexport const MAX_CONTEXT_MESSAGES = 50;\nexport const SESSION_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes\n\n// Security\nexport const DEFAULT_SANDBOX_MODE = 'host';\n/** Default allowed tools. Empty = allow ALL registered tools.\n * Use security.deniedTools to block specific tools instead. */\nexport const ALLOWED_TOOLS_DEFAULT: string[] = [];\nexport const DENIED_TOOLS_DEFAULT: string[] = [];\n"],"mappings":";AAGA,SAAS,eAAe;AACxB,SAAS,YAAY;AAEd,MAAM,gBAAgB;AACtB,MAAM,iBAAiB;AACvB,MAAM,aAAa;AACnB,MAAM,kBAAkB;AACxB,MAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,WAW1B,aAAa;AAAA;AAYnB,SAAS,mBAA2B;AAChC,QAAM,UAAU,QAAQ,IAAI;AAC5B,MAAI,WAAW,QAAQ,KAAK,EAAE,SAAS,GAAG;AACtC,UAAM,UAAU,QAAQ,KAAK;AAC7B,QAAI,QAAQ,WAAW,IAAI,GAAG;AAC1B,aAAO,KAAK,QAAQ,GAAG,QAAQ,MAAM,CAAC,CAAC;AAAA,IAC3C;AACA,QAAI,YAAY,KAAK;AACjB,aAAO,QAAQ;AAAA,IACnB;AACA,WAAO;AAAA,EACX;AACA,SAAO,KAAK,QAAQ,GAAG,QAAQ;AACnC;AACO,MAAM,aAAa,iBAAiB;AACpC,MAAM,oBAAoB,KAAK,YAAY,YAAY;AACvD,MAAM,gBAAgB,KAAK,YAAY,UAAU;AACjD,MAAM,kBAAkB,KAAK,YAAY,WAAW;AACpD,MAAM,mBAAmB,KAAK,iBAAiB,QAAQ;AACvD,MAAM,iBAAiB,KAAK,YAAY,MAAM;AAC9C,MAAM,mBAAmB,KAAK,YAAY,QAAQ;AAGlD,MAAM,YAAY,KAAK,iBAAiB,WAAW;AACnD,MAAM,UAAU,KAAK,iBAAiB,SAAS;AAC/C,MAAM,WAAW,KAAK,iBAAiB,UAAU;AACjD,MAAM,oBAAoB;AAC1B,MAAM,eAAe,KAAK,YAAY,cAAc;AACpD,MAAM,sBAAsB,KAAK,YAAY,sBAAsB;AACnE,MAAM,wBAAwB,KAAK,YAAY,aAAa;AAG5D,MAAM,qBAAqB,KAAK,YAAY,qBAAqB;AACjE,MAAM,uBAAuB,KAAK,YAAY,uBAAuB;AACrE,MAAM,yBAAyB,KAAK,YAAY,wBAAwB;AACxE,MAAM,aAAa,KAAK,YAAY,aAAa;AACjD,MAAM,wBAAwB,KAAK,YAAY,wBAAwB;AACvE,MAAM,uBAAuB,KAAK,YAAY,uBAAuB;AACrE,MAAM,oBAAoB,KAAK,YAAY,oBAAoB;AAG/D,MAAM,eAAe,KAAK,YAAY,UAAU;AAChD,MAAM,YAAY,KAAK,YAAY,OAAO;AAG1C,MAAM,uBAAuB;AAC7B,MAAM,uBAAuB;AAC7B,MAAM,mBAAmB;AASzB,MAAM,gBAAgB;AAItB,MAAM,qBAAqB;AAC3B,MAAM,sBAAsB;AAC5B,MAAM,uBAAuB;AAC7B,MAAM,qBAAqB,KAAK,KAAK;AAGrC,MAAM,uBAAuB;AAG7B,MAAM,wBAAkC,CAAC;AACzC,MAAM,uBAAiC,CAAC;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "titan-agent",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.4.0",
|
|
4
4
|
"description": "TITAN — TypeScript AI agent framework with multi-agent orchestration, provider routing, approval gates, receipts, evals, gateway APIs, and a React Mission Control dashboard. Open-source, MIT licensed.",
|
|
5
5
|
"author": "Tony Elliott (https://github.com/Djtony707)",
|
|
6
6
|
"repository": {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as d,j as e,aJ as S,aK as A}from"./index-
|
|
1
|
+
import{r as d,j as e,aJ as S,aK as A}from"./index-CgHHe41p.js";import{C as v}from"./clipboard-list-BnOtwHQm.js";import{R as C}from"./refresh-cw-_C-4Cd_3.js";import{F as T}from"./funnel-C_bR-Dz5.js";function E(){var b;const[c,p]=d.useState([]),[r,h]=d.useState(null),[g,i]=d.useState(!0),[a,n]=d.useState(""),[l,x]=d.useState(""),m=async()=>{i(!0);try{const[t,s]=await Promise.all([S({source:a||void 0,action:l||void 0,limit:100}),A(24)]);p(t),h(s)}catch{}i(!1)};d.useEffect(()=>{m()},[a,l]);const j=t=>t==="success"?"text-[var(--success)]":t==="failure"?"text-[var(--error)]":t==="escalated"?"text-[var(--warning)]":"text-[var(--text-muted)]",f=t=>t==="success"?"bg-[var(--success)]/10 border-[var(--success)]/20":t==="failure"?"bg-[var(--error)]/10 border-[var(--error)]/20":t==="escalated"?"bg-[var(--warning)]/10 border-[var(--warning)]/20":"bg-[var(--bg-tertiary)] border-[var(--border)]",u=t=>t.startsWith("daemon")?"bg-purple-500/10 text-purple-400 border-purple-500/20":t==="autopilot"?"bg-blue-500/10 text-blue-400 border-blue-500/20":t==="user"?"bg-emerald-500/10 text-emerald-400 border-emerald-500/20":t==="initiative"?"bg-amber-500/10 text-amber-400 border-amber-500/20":"bg-[var(--bg-tertiary)] text-[var(--text-muted)] border-[var(--border)]",N=t=>{try{const s=new Date(t),o=new Date().getTime()-s.getTime();return o<6e4?`${Math.round(o/1e3)}s ago`:o<36e5?`${Math.round(o/6e4)}m ago`:o<864e5?`${Math.round(o/36e5)}h ago`:s.toLocaleDateString()}catch{return t}},y=[...new Set(c.map(t=>t.source))].sort(),w=[...new Set(c.map(t=>t.action))].sort();return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(v,{className:"w-6 h-6 text-[var(--accent)]"}),e.jsxs("div",{children:[e.jsx("h1",{className:"text-xl font-bold text-[var(--text)]",children:"Audit Log"}),e.jsx("p",{className:"text-sm text-[var(--text-muted)]",children:"Every autonomous action logged for accountability"})]})]}),e.jsx("button",{onClick:m,className:"p-2 rounded-md border border-[var(--border)] text-[var(--text-secondary)] hover:bg-[var(--bg-tertiary)] transition-colors",children:e.jsx(C,{size:14})})]}),r&&e.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-4",children:[e.jsxs("div",{className:"bg-[var(--bg-secondary)] border border-[var(--border)] rounded-lg p-4",children:[e.jsx("p",{className:"text-sm text-[var(--text-muted)]",children:"Actions (24h)"}),e.jsx("p",{className:"text-2xl font-bold text-[var(--text)]",children:r.totalActions})]}),e.jsxs("div",{className:"bg-[var(--bg-secondary)] border border-[var(--border)] rounded-lg p-4",children:[e.jsx("p",{className:"text-sm text-[var(--text-muted)]",children:"Success Rate"}),e.jsxs("p",{className:`text-2xl font-bold ${r.successRate>=80?"text-[var(--success)]":r.successRate>=50?"text-[var(--warning)]":"text-[var(--error)]"}`,children:[r.successRate,"%"]})]}),e.jsxs("div",{className:"bg-[var(--bg-secondary)] border border-[var(--border)] rounded-lg p-4",children:[e.jsx("p",{className:"text-sm text-[var(--text-muted)]",children:"Sources"}),e.jsx("p",{className:"text-2xl font-bold text-[var(--text)]",children:Object.keys(r.bySource).length})]}),e.jsxs("div",{className:"bg-[var(--bg-secondary)] border border-[var(--border)] rounded-lg p-4",children:[e.jsx("p",{className:"text-sm text-[var(--text-muted)]",children:"Top Tool"}),e.jsx("p",{className:"text-lg font-semibold text-[var(--accent)] truncate",children:((b=r.topTools[0])==null?void 0:b.tool)||"none"})]})]}),r&&Object.keys(r.bySource).length>0&&e.jsxs("div",{className:"bg-[var(--bg-secondary)] border border-[var(--border)] rounded-lg p-4",children:[e.jsx("h2",{className:"text-sm font-semibold text-[var(--text)] mb-3",children:"Actions by Source (24h)"}),e.jsx("div",{className:"flex flex-wrap gap-2",children:Object.entries(r.bySource).sort((t,s)=>s[1]-t[1]).map(([t,s])=>e.jsxs("button",{onClick:()=>n(a===t?"":t),className:`px-3 py-1.5 text-xs rounded-md border transition-colors ${a===t?"bg-[var(--accent)] text-white border-[var(--accent)]":u(t)}`,children:[t,": ",s]},t))})]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(T,{size:14,className:"text-[var(--text-muted)]"}),e.jsxs("select",{value:a,onChange:t=>n(t.target.value),className:"px-3 py-1.5 text-xs bg-[var(--bg-secondary)] border border-[var(--border)] rounded-md text-[var(--text)]",children:[e.jsx("option",{value:"",children:"All Sources"}),y.map(t=>e.jsx("option",{value:t,children:t},t))]}),e.jsxs("select",{value:l,onChange:t=>x(t.target.value),className:"px-3 py-1.5 text-xs bg-[var(--bg-secondary)] border border-[var(--border)] rounded-md text-[var(--text)]",children:[e.jsx("option",{value:"",children:"All Actions"}),w.map(t=>e.jsx("option",{value:t,children:t},t))]}),(a||l)&&e.jsx("button",{onClick:()=>{n(""),x("")},className:"text-xs text-[var(--accent)] hover:underline",children:"Clear"})]}),g?e.jsx("div",{className:"text-[var(--text-muted)] text-sm",children:"Loading audit log..."}):c.length===0?e.jsxs("div",{className:"bg-[var(--bg-secondary)] border border-[var(--border)] rounded-lg p-8 text-center",children:[e.jsx(v,{className:"w-10 h-10 text-[var(--text-muted)] mx-auto mb-3"}),e.jsx("p",{className:"text-[var(--text-secondary)]",children:"No audit entries found"}),e.jsx("p",{className:"text-xs text-[var(--text-muted)]",children:"Autonomous actions will appear here as TITAN operates."})]}):e.jsx("div",{className:"bg-[var(--bg-secondary)] border border-[var(--border)] rounded-lg overflow-hidden",children:e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full text-xs",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b border-[var(--border)] text-[var(--text-muted)]",children:[e.jsx("th",{className:"text-left px-4 py-2 font-medium",children:"Time"}),e.jsx("th",{className:"text-left px-4 py-2 font-medium",children:"Action"}),e.jsx("th",{className:"text-left px-4 py-2 font-medium",children:"Source"}),e.jsx("th",{className:"text-left px-4 py-2 font-medium",children:"Tool"}),e.jsx("th",{className:"text-left px-4 py-2 font-medium",children:"Result"}),e.jsx("th",{className:"text-left px-4 py-2 font-medium",children:"Detail"})]})}),e.jsx("tbody",{children:c.map((t,s)=>e.jsxs("tr",{className:"border-b border-[var(--border)]/50 last:border-0 hover:bg-[var(--bg-tertiary)] transition-colors",children:[e.jsx("td",{className:"px-4 py-2 text-[var(--text-muted)] whitespace-nowrap",children:N(t.timestamp)}),e.jsx("td",{className:"px-4 py-2 text-[var(--text)] font-medium",children:t.action}),e.jsx("td",{className:"px-4 py-2",children:e.jsx("span",{className:`px-2 py-0.5 rounded text-[10px] border ${u(t.source)}`,children:t.source})}),e.jsx("td",{className:"px-4 py-2 text-[var(--text-secondary)] font-mono",children:t.tool||"-"}),e.jsx("td",{className:"px-4 py-2",children:t.result?e.jsx("span",{className:`px-2 py-0.5 rounded text-[10px] border ${f(t.result)} ${j(t.result)}`,children:t.result}):"-"}),e.jsx("td",{className:"px-4 py-2 text-[var(--text-muted)] max-w-[200px] truncate",children:t.detail?JSON.stringify(t.detail):"-"})]},s))})]})})})]})}export{E as default};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{c as M,r as c,a8 as B,j as e,L as C,i as F,Z as E,a9 as O,t as T,b,f as g,B as q,U as G,G as V,h as I}from"./index-
|
|
1
|
+
import{c as M,r as c,a8 as B,j as e,L as C,i as F,Z as E,a9 as O,t as T,b,f as g,B as q,U as G,G as V,h as I}from"./index-CgHHe41p.js";import{S as D}from"./save-B02XWwgN.js";import{C as H}from"./circle-check-big-hiNdH5H3.js";import{R as U}from"./refresh-cw-_C-4Cd_3.js";import{R}from"./rotate-ccw-DWyVAH19.js";import{R as J}from"./radio-BTFO9FV9.js";import{B as Z}from"./bot-C4CRICZX.js";import{S as W}from"./server-CvEvPDpX.js";import{N as K}from"./network-C_MOo5My.js";import{P as Q}from"./play-D3Nbm1Cz.js";import{M as X}from"./message-square-WJp1dTaM.js";import{D as Y}from"./TitanCanvas-Da6TxxdJ.js";import"./chevron-up-n_3KVmjQ.js";import"./plus-CJKkM9fM.js";import"./file-text-CyC_OxlA.js";import"./terminal-BVErXh5C.js";import"./book-open-B00IpKZA.js";import"./pencil-C6SVDEUL.js";import"./search-CHteSk-9.js";import"./send-DkMQeZAz.js";import"./mic-DjXDp1Js.js";import"./flask-conical-BKbKUYhz.js";import"./clock-BFgCJnqQ.js";import"./archive-aaQ0bgj_.js";import"./test-tube-JSgqEqJs.js";import"./VoiceOverlay-D_jfyVe9.js";import"./chevron-right-CA8HOEP4.js";import"./volume-2-CELMZXsT.js";import"./folder-7bWz46dM.js";import"./check-BJMHM0tu.js";import"./shield-check-DQeYCvwF.js";import"./external-link-CPAx2HBG.js";import"./wifi-off-DKKYhVWL.js";import"./chart-column-lnilxGq2.js";import"./link-CfLpUR24.js";import"./trash-2-kiHv5iAF.js";/**
|
|
2
2
|
* @license lucide-react v0.513.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
@@ -8,4 +8,4 @@ import{c as M,r as c,a8 as B,j as e,L as C,i as F,Z as E,a9 as O,t as T,b,f as g
|
|
|
8
8
|
*
|
|
9
9
|
* This source code is licensed under the ISC license.
|
|
10
10
|
* See the LICENSE file in the root directory of this source tree.
|
|
11
|
-
*/const te=[["path",{d:"M15.39 4.39a1 1 0 0 0 1.68-.474 2.5 2.5 0 1 1 3.014 3.015 1 1 0 0 0-.474 1.68l1.683 1.682a2.414 2.414 0 0 1 0 3.414L19.61 15.39a1 1 0 0 1-1.68-.474 2.5 2.5 0 1 0-3.014 3.015 1 1 0 0 1 .474 1.68l-1.683 1.682a2.414 2.414 0 0 1-3.414 0L8.61 19.61a1 1 0 0 0-1.68.474 2.5 2.5 0 1 1-3.014-3.015 1 1 0 0 0 .474-1.68l-1.683-1.682a2.414 2.414 0 0 1 0-3.414L4.39 8.61a1 1 0 0 1 1.68.474 2.5 2.5 0 1 0 3.014-3.015 1 1 0 0 1-.474-1.68l1.683-1.682a2.414 2.414 0 0 1 3.414 0z",key:"w46dr5"}]],ae=M("puzzle",te),v=[{key:"autonomy-mode",label:"Autonomous Mode",description:"TITAN acts without asking for approval on moderate-risk tools. Supervised = asks for dangerous ops. Locked = asks for everything.",icon:e.jsx(E,{className:"h-4 w-4"}),section:"autonomy",field:"mode",danger:!0},{key:"autonomy-autoProposeGoals",label:"Auto-Propose Goals",description:"TITAN can create its own goals from drives, observations, and initiatives.",icon:e.jsx(g,{className:"h-4 w-4"}),section:"autonomy",field:"autoProposeGoals"},{key:"autonomy-proactiveInitiative",label:"Proactive Initiative",description:"TITAN takes initiative on its own between user messages.",icon:e.jsx(J,{className:"h-4 w-4"}),section:"autonomy",field:"proactiveInitiative"},{key:"selfMod-enabled",label:"Self-Modification",description:"Captures autonomous code changes and queues them for review.",icon:e.jsx(Z,{className:"h-4 w-4"}),section:"selfMod",field:"enabled",danger:!0},{key:"selfMod-autoPR",label:"Auto-Open PRs",description:"When specialists approve a self-mod, automatically open a GitHub PR.",icon:e.jsx(oe,{className:"h-4 w-4"}),section:"selfMod",field:"autoPR"},{key:"commandPost-enabled",label:"Command Post",description:"Org chart, agent registry, approvals, budgets, and goal tracking.",icon:e.jsx(W,{className:"h-4 w-4"}),section:"commandPost",field:"enabled"},{key:"mesh-enabled",label:"Mesh Networking",description:"Distributed TITAN nodes. Share tasks and models across machines.",icon:e.jsx(K,{className:"h-4 w-4"}),section:"mesh",field:"enabled"},{key:"autopilot-enabled",label:"Autopilot",description:"Nightly autonomous checks, goal reviews, and self-improvement runs.",icon:e.jsx(Q,{className:"h-4 w-4"}),section:"autopilot",field:"enabled"},{key:"autopilot-selfInitiate",label:"Autopilot Self-Initiate",description:"Autopilot can create and start its own goals without human trigger.",icon:e.jsx(g,{className:"h-4 w-4"}),section:"autopilot",field:"selfInitiate"},{key:"brain-enabled",label:"Brain (Local Router)",description:"Small local model routes tools instead of sending full schemas to the cloud LLM.",icon:e.jsx(q,{className:"h-4 w-4"}),section:"brain",field:"enabled"},{key:"mcp-server-enabled",label:"MCP Server",description:"Expose TITAN tools as a Model Context Protocol server for other AI apps.",icon:e.jsx(ae,{className:"h-4 w-4"}),section:"mcp",field:"serverEnabled"},{key:"training-enabled",label:"Model Training",description:"Fine-tune local LoRA adapters from session history.",icon:e.jsx(se,{className:"h-4 w-4"}),section:"training",field:"enabled"},{key:"teams-enabled",label:"Teams",description:"Multi-user teams with roles, invites, and permissions.",icon:e.jsx(G,{className:"h-4 w-4"}),section:"teams",field:"enabled"},{key:"tunnel-enabled",label:"Cloudflare Tunnel",description:"Expose TITAN securely on the public internet via Cloudflare.",icon:e.jsx(V,{className:"h-4 w-4"}),section:"tunnel",field:"enabled"},{key:"vault-enabled",label:"Vault",description:"Encrypted secret storage for API keys and credentials.",icon:e.jsx(I,{className:"h-4 w-4"}),section:"vault",field:"enabled"},{key:"capsolver-enabled",label:"CAPTCHA Solver",description:"Automatically solve CAPTCHAs during web browsing.",icon:e.jsx(I,{className:"h-4 w-4"}),section:"capsolver",field:"enabled"},{key:"deliberation-autoDetect",label:"Auto-Deliberation",description:"TITAN automatically deliberates on complex tasks before acting.",icon:e.jsx(X,{className:"h-4 w-4"}),section:"deliberation",field:"autoDetect"},{key:"selfImprove-autoApply",label:"Auto-Apply Self-Improvements",description:"Apply prompt and config improvements automatically without approval.",icon:e.jsx(g,{className:"h-4 w-4"}),section:"selfImprove",field:"autoApply"},{key:"memory-vectorSearchEnabled",label:"Vector Memory Search",description:"Semantic search across episodic memories using embeddings.",icon:e.jsx(Y,{className:"h-4 w-4"}),section:"memory",field:"vectorSearchEnabled"}];function oe({className:n}){return e.jsx("svg",{className:n,viewBox:"0 0 24 24",fill:"currentColor",children:e.jsx("path",{d:"M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0024 12c0-6.63-5.37-12-12-12z"})})}function P({active:n}){return n?e.jsxs("span",{className:"inline-flex items-center gap-1 rounded-full bg-success/15 px-2 py-0.5 text-[10px] font-medium text-success",children:[e.jsx("div",{className:"h-1.5 w-1.5 rounded-full bg-success shadow-[0_0_4px_rgba(34,197,94,0.4)]"}),"ON"]}):e.jsxs("span",{className:"inline-flex items-center gap-1 rounded-full bg-bg-tertiary px-2 py-0.5 text-[10px] font-medium text-text-muted",children:[e.jsx("div",{className:"h-1.5 w-1.5 rounded-full bg-border-light"}),"OFF"]})}function Be(){const[n,y]=c.useState(null),[L,N]=c.useState(!0),[x,j]=c.useState(!1),[f,m]=c.useState(!1),[p,w]=c.useState(null),[d,k]=c.useState(new Set),[h,A]=c.useState({}),l=c.useCallback((s,t)=>{w({type:s,message:t}),setTimeout(()=>w(null),4e3)},[]);c.useEffect(()=>{B().then(s=>{y(s),N(!1)}).catch(s=>{l("error",s instanceof Error?s.message:"Failed to load config"),N(!1)})},[l]);const u=(s,t)=>{if(t==="serverEnabled"){const a=n==null?void 0:n.mcp,r=a==null?void 0:a.server;return!!(r!=null&&r.enabled)}if(t==="selfInitiate"){const a=n==null?void 0:n.autopilot,r=a==null?void 0:a.goals;return!!(r!=null&&r.selfInitiate)}const o=`${s}.${t}`;if(o in h)return h[o];const i=n==null?void 0:n[s];return i?i[t]:!1},S=(s,t,o)=>{const i=`${s}.${t}`;A(a=>({...a,[i]:o})),k(a=>new Set(a).add(i))},$=v.filter(s=>{const t=u(s.section,s.field);return typeof t=="boolean"?t:t==="autonomous"}).length,z=async()=>{j(!0);try{const s={};for(const o of d){const[i,a]=o.split("."),r=h[o];s[i]||(s[i]={}),a==="serverEnabled"?(s.mcp||(s.mcp={}),s.mcp.server={enabled:r}):a==="selfInitiate"?(s.autopilot||(s.autopilot={}),s.autopilot.goals={selfInitiate:r}):s[i][a]=r}const t=await O(s);y(t),A({}),k(new Set),T("autonomy_settings_saved",{changedCount:d.size}),l("success",`Saved ${d.size} change${d.size!==1?"s":""}`)}catch(s){l("error",s instanceof Error?s.message:"Failed to save")}finally{j(!1)}},_=async()=>{m(!0);try{const s=await b("/api/system/request-restart",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({reason:"Settings change via Autonomy Panel",requestedBy:"user"})});if(!s.ok){const r=await s.json().catch(()=>({error:"Request failed"}));l("error",r.error||"Restart request failed"),m(!1);return}const{approval:t}=await s.json(),o=await b(`/api/command-post/approvals/${t.id}/approve`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({decidedBy:"user",note:"Approved via Autonomy Panel"})});if(!o.ok){const r=await o.json().catch(()=>({error:"Approval failed"}));l("error",r.error||"Restart approval failed"),m(!1);return}l("info","TITAN is restarting..."),T("titan_restart_initiated",{source:"autonomy_panel"});let i=0;const a=setInterval(async()=>{i++;try{(await b("/api/health")).ok&&(clearInterval(a),m(!1),l("success","TITAN restarted successfully"))}catch{}i>30&&(clearInterval(a),m(!1),l("error","Restart timed out — check Titan PC"))},2e3)}catch(s){l("error",s instanceof Error?s.message:"Restart failed"),m(!1)}};return L?e.jsx("div",{className:"space-y-4",children:Array.from({length:4}).map((s,t)=>e.jsx("div",{className:"h-32 animate-pulse rounded-xl border border-border bg-bg-secondary"},t))}):e.jsxs("div",{className:"space-y-5",children:[e.jsxs("div",{className:"flex items-center justify-between flex-wrap gap-3",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-base font-semibold text-text",children:"Autonomy & Features"}),e.jsxs("p",{className:"mt-0.5 text-xs text-text-muted",children:[$," of ",v.length," features active"]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[d.size>0&&e.jsxs("span",{className:"rounded-full bg-accent/15 px-2.5 py-1 text-[10px] font-medium text-accent",children:[d.size," unsaved"]}),e.jsxs("button",{onClick:z,disabled:x||d.size===0,className:"flex items-center gap-1.5 rounded-lg bg-accent px-3 py-1.5 text-xs font-medium text-white transition-colors hover:bg-accent/80 disabled:opacity-50",children:[x?e.jsx(C,{className:"h-3.5 w-3.5 animate-spin"}):e.jsx(D,{className:"h-3.5 w-3.5"}),x?"Saving…":"Save Changes"]})]})]}),p&&e.jsxs("div",{className:`flex items-center gap-2 rounded-lg border px-3 py-2 text-xs ${p.type==="success"?"border-success/50 text-success":p.type==="error"?"border-error/50 text-error":"border-accent/50 text-accent"}`,children:[p.type==="success"?e.jsx(H,{className:"h-4 w-4"}):p.type==="error"?e.jsx(F,{className:"h-4 w-4"}):e.jsx(U,{className:"h-4 w-4 animate-spin"}),p.message]}),e.jsxs("div",{className:"rounded-xl border border-border bg-bg-secondary p-4",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-3",children:[e.jsx(E,{className:"h-4 w-4 text-accent"}),e.jsx("h3",{className:"text-sm font-medium text-text",children:"Autonomy Level"}),e.jsx(P,{active:u("autonomy","mode")==="autonomous"})]}),e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-3 gap-2",children:["locked","supervised","autonomous"].map(s=>e.jsxs("button",{onClick:()=>S("autonomy","mode",s),className:`rounded-lg border p-3 text-left transition-all ${u("autonomy","mode")===s?"border-accent bg-accent/10":"border-border hover:border-border-light"}`,children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-xs font-medium text-text capitalize",children:s}),s==="autonomous"&&e.jsx("span",{className:"text-[9px] text-error",children:"High"}),s==="supervised"&&e.jsx("span",{className:"text-[9px] text-warning",children:"Med"}),s==="locked"&&e.jsx("span",{className:"text-[9px] text-success",children:"Low"})]}),e.jsxs("p",{className:"mt-1 text-[10px] text-text-muted leading-relaxed",children:[s==="locked"&&"Asks for approval on every tool call.",s==="supervised"&&"Auto-approves safe tools. Asks for dangerous ops.",s==="autonomous"&&"Full auto. Only asks for destructive/rare ops."]})]},s))})]}),e.jsx("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-3",children:v.filter(s=>s.field!=="mode").map(s=>{const t=u(s.section,s.field),o=typeof t=="boolean"?t:!1,i=d.has(`${s.section}.${s.field}`);return e.jsxs("div",{className:`flex items-start gap-3 rounded-xl border p-3 transition-colors ${i?"border-accent/40 bg-accent/5":"border-border bg-bg-secondary"}`,children:[e.jsx("div",{className:`mt-0.5 flex-shrink-0 rounded-lg p-2 ${o?"bg-accent/15 text-accent":"bg-bg-tertiary text-text-muted"}`,children:s.icon}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx("span",{className:"text-sm font-medium text-text",children:s.label}),e.jsx(P,{active:o})]}),e.jsx("p",{className:"mt-0.5 text-[11px] text-text-muted leading-relaxed",children:s.description})]}),e.jsxs("label",{className:"flex-shrink-0 relative inline-flex items-center cursor-pointer",children:[e.jsx("input",{type:"checkbox",checked:o,onChange:a=>S(s.section,s.field,a.target.checked),className:"sr-only peer"}),e.jsx("div",{className:`relative w-9 h-5 rounded-full transition-colors ${o?"bg-accent":"bg-border"}`,children:e.jsx("div",{className:`absolute top-[2px] left-[2px] bg-white w-4 h-4 rounded-full transition-transform ${o?"translate-x-4":"translate-x-0"}`})})]})]},s.key)})}),e.jsx("div",{className:"rounded-xl border border-warning/30 bg-warning/5 p-4",children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx(R,{className:"h-4 w-4 text-warning mt-0.5"}),e.jsxs("div",{className:"flex-1",children:[e.jsx("h3",{className:"text-sm font-medium text-text",children:"Restart TITAN"}),e.jsx("p",{className:"mt-0.5 text-[11px] text-text-muted",children:"Some feature changes require a full restart to take effect. This will briefly interrupt service."})]}),e.jsxs("button",{onClick:_,disabled:f,className:"flex items-center gap-1.5 rounded-lg border border-warning/50 px-3 py-1.5 text-xs font-medium text-warning transition-colors hover:bg-warning/10 disabled:opacity-50",children:[f?e.jsx(C,{className:"h-3.5 w-3.5 animate-spin"}):e.jsx(R,{className:"h-3.5 w-3.5"}),f?"Restarting…":"Restart"]})]})})]})}export{Be as default};
|
|
11
|
+
*/const te=[["path",{d:"M15.39 4.39a1 1 0 0 0 1.68-.474 2.5 2.5 0 1 1 3.014 3.015 1 1 0 0 0-.474 1.68l1.683 1.682a2.414 2.414 0 0 1 0 3.414L19.61 15.39a1 1 0 0 1-1.68-.474 2.5 2.5 0 1 0-3.014 3.015 1 1 0 0 1 .474 1.68l-1.683 1.682a2.414 2.414 0 0 1-3.414 0L8.61 19.61a1 1 0 0 0-1.68.474 2.5 2.5 0 1 1-3.014-3.015 1 1 0 0 0 .474-1.68l-1.683-1.682a2.414 2.414 0 0 1 0-3.414L4.39 8.61a1 1 0 0 1 1.68.474 2.5 2.5 0 1 0 3.014-3.015 1 1 0 0 1-.474-1.68l1.683-1.682a2.414 2.414 0 0 1 3.414 0z",key:"w46dr5"}]],ae=M("puzzle",te),v=[{key:"autonomy-mode",label:"Autonomous Mode",description:"TITAN acts without asking for approval on moderate-risk tools. Supervised = asks for dangerous ops. Locked = asks for everything.",icon:e.jsx(E,{className:"h-4 w-4"}),section:"autonomy",field:"mode",danger:!0},{key:"autonomy-autoProposeGoals",label:"Auto-Propose Goals",description:"TITAN can create its own goals from drives, observations, and initiatives.",icon:e.jsx(g,{className:"h-4 w-4"}),section:"autonomy",field:"autoProposeGoals"},{key:"autonomy-proactiveInitiative",label:"Proactive Initiative",description:"TITAN takes initiative on its own between user messages.",icon:e.jsx(J,{className:"h-4 w-4"}),section:"autonomy",field:"proactiveInitiative"},{key:"selfMod-enabled",label:"Self-Modification",description:"Captures autonomous code changes and queues them for review.",icon:e.jsx(Z,{className:"h-4 w-4"}),section:"selfMod",field:"enabled",danger:!0},{key:"selfMod-autoPR",label:"Auto-Open PRs",description:"When specialists approve a self-mod, automatically open a GitHub PR.",icon:e.jsx(oe,{className:"h-4 w-4"}),section:"selfMod",field:"autoPR"},{key:"commandPost-enabled",label:"Command Post",description:"Org chart, agent registry, approvals, budgets, and goal tracking.",icon:e.jsx(W,{className:"h-4 w-4"}),section:"commandPost",field:"enabled"},{key:"mesh-enabled",label:"Mesh Networking",description:"Distributed TITAN nodes. Share tasks and models across machines.",icon:e.jsx(K,{className:"h-4 w-4"}),section:"mesh",field:"enabled"},{key:"autopilot-enabled",label:"Autopilot",description:"Nightly autonomous checks, goal reviews, and self-improvement runs.",icon:e.jsx(Q,{className:"h-4 w-4"}),section:"autopilot",field:"enabled"},{key:"autopilot-selfInitiate",label:"Autopilot Self-Initiate",description:"Autopilot can create and start its own goals without human trigger.",icon:e.jsx(g,{className:"h-4 w-4"}),section:"autopilot",field:"selfInitiate"},{key:"brain-enabled",label:"Brain (Local Router)",description:"Small local model routes tools instead of sending full schemas to the cloud LLM.",icon:e.jsx(q,{className:"h-4 w-4"}),section:"brain",field:"enabled"},{key:"mcp-server-enabled",label:"MCP Server",description:"Expose TITAN tools as a Model Context Protocol server for other AI apps.",icon:e.jsx(ae,{className:"h-4 w-4"}),section:"mcp",field:"serverEnabled"},{key:"training-enabled",label:"Model Training",description:"Fine-tune local LoRA adapters from session history.",icon:e.jsx(se,{className:"h-4 w-4"}),section:"training",field:"enabled"},{key:"teams-enabled",label:"Teams",description:"Multi-user teams with roles, invites, and permissions.",icon:e.jsx(G,{className:"h-4 w-4"}),section:"teams",field:"enabled"},{key:"tunnel-enabled",label:"Cloudflare Tunnel",description:"Expose TITAN securely on the public internet via Cloudflare.",icon:e.jsx(V,{className:"h-4 w-4"}),section:"tunnel",field:"enabled"},{key:"vault-enabled",label:"Vault",description:"Encrypted secret storage for API keys and credentials.",icon:e.jsx(I,{className:"h-4 w-4"}),section:"vault",field:"enabled"},{key:"capsolver-enabled",label:"CAPTCHA Solver",description:"Automatically solve CAPTCHAs during web browsing.",icon:e.jsx(I,{className:"h-4 w-4"}),section:"capsolver",field:"enabled"},{key:"deliberation-autoDetect",label:"Auto-Deliberation",description:"TITAN automatically deliberates on complex tasks before acting.",icon:e.jsx(X,{className:"h-4 w-4"}),section:"deliberation",field:"autoDetect"},{key:"selfImprove-autoApply",label:"Auto-Apply Self-Improvements",description:"Apply prompt and config improvements automatically without approval.",icon:e.jsx(g,{className:"h-4 w-4"}),section:"selfImprove",field:"autoApply"},{key:"memory-vectorSearchEnabled",label:"Vector Memory Search",description:"Semantic search across episodic memories using embeddings.",icon:e.jsx(Y,{className:"h-4 w-4"}),section:"memory",field:"vectorSearchEnabled"}];function oe({className:n}){return e.jsx("svg",{className:n,viewBox:"0 0 24 24",fill:"currentColor",children:e.jsx("path",{d:"M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0024 12c0-6.63-5.37-12-12-12z"})})}function P({active:n}){return n?e.jsxs("span",{className:"inline-flex items-center gap-1 rounded-full bg-success/15 px-2 py-0.5 text-[10px] font-medium text-success",children:[e.jsx("div",{className:"h-1.5 w-1.5 rounded-full bg-success shadow-[0_0_4px_rgba(34,197,94,0.4)]"}),"ON"]}):e.jsxs("span",{className:"inline-flex items-center gap-1 rounded-full bg-bg-tertiary px-2 py-0.5 text-[10px] font-medium text-text-muted",children:[e.jsx("div",{className:"h-1.5 w-1.5 rounded-full bg-border-light"}),"OFF"]})}function qe(){const[n,y]=c.useState(null),[L,N]=c.useState(!0),[x,j]=c.useState(!1),[f,m]=c.useState(!1),[p,w]=c.useState(null),[d,k]=c.useState(new Set),[h,A]=c.useState({}),l=c.useCallback((s,t)=>{w({type:s,message:t}),setTimeout(()=>w(null),4e3)},[]);c.useEffect(()=>{B().then(s=>{y(s),N(!1)}).catch(s=>{l("error",s instanceof Error?s.message:"Failed to load config"),N(!1)})},[l]);const u=(s,t)=>{if(t==="serverEnabled"){const a=n==null?void 0:n.mcp,r=a==null?void 0:a.server;return!!(r!=null&&r.enabled)}if(t==="selfInitiate"){const a=n==null?void 0:n.autopilot,r=a==null?void 0:a.goals;return!!(r!=null&&r.selfInitiate)}const o=`${s}.${t}`;if(o in h)return h[o];const i=n==null?void 0:n[s];return i?i[t]:!1},S=(s,t,o)=>{const i=`${s}.${t}`;A(a=>({...a,[i]:o})),k(a=>new Set(a).add(i))},$=v.filter(s=>{const t=u(s.section,s.field);return typeof t=="boolean"?t:t==="autonomous"}).length,z=async()=>{j(!0);try{const s={};for(const o of d){const[i,a]=o.split("."),r=h[o];s[i]||(s[i]={}),a==="serverEnabled"?(s.mcp||(s.mcp={}),s.mcp.server={enabled:r}):a==="selfInitiate"?(s.autopilot||(s.autopilot={}),s.autopilot.goals={selfInitiate:r}):s[i][a]=r}const t=await O(s);y(t),A({}),k(new Set),T("autonomy_settings_saved",{changedCount:d.size}),l("success",`Saved ${d.size} change${d.size!==1?"s":""}`)}catch(s){l("error",s instanceof Error?s.message:"Failed to save")}finally{j(!1)}},_=async()=>{m(!0);try{const s=await b("/api/system/request-restart",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({reason:"Settings change via Autonomy Panel",requestedBy:"user"})});if(!s.ok){const r=await s.json().catch(()=>({error:"Request failed"}));l("error",r.error||"Restart request failed"),m(!1);return}const{approval:t}=await s.json(),o=await b(`/api/command-post/approvals/${t.id}/approve`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({decidedBy:"user",note:"Approved via Autonomy Panel"})});if(!o.ok){const r=await o.json().catch(()=>({error:"Approval failed"}));l("error",r.error||"Restart approval failed"),m(!1);return}l("info","TITAN is restarting..."),T("titan_restart_initiated",{source:"autonomy_panel"});let i=0;const a=setInterval(async()=>{i++;try{(await b("/api/health")).ok&&(clearInterval(a),m(!1),l("success","TITAN restarted successfully"))}catch{}i>30&&(clearInterval(a),m(!1),l("error","Restart timed out — check Titan PC"))},2e3)}catch(s){l("error",s instanceof Error?s.message:"Restart failed"),m(!1)}};return L?e.jsx("div",{className:"space-y-4",children:Array.from({length:4}).map((s,t)=>e.jsx("div",{className:"h-32 animate-pulse rounded-xl border border-border bg-bg-secondary"},t))}):e.jsxs("div",{className:"space-y-5",children:[e.jsxs("div",{className:"flex items-center justify-between flex-wrap gap-3",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-base font-semibold text-text",children:"Autonomy & Features"}),e.jsxs("p",{className:"mt-0.5 text-xs text-text-muted",children:[$," of ",v.length," features active"]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[d.size>0&&e.jsxs("span",{className:"rounded-full bg-accent/15 px-2.5 py-1 text-[10px] font-medium text-accent",children:[d.size," unsaved"]}),e.jsxs("button",{onClick:z,disabled:x||d.size===0,className:"flex items-center gap-1.5 rounded-lg bg-accent px-3 py-1.5 text-xs font-medium text-white transition-colors hover:bg-accent/80 disabled:opacity-50",children:[x?e.jsx(C,{className:"h-3.5 w-3.5 animate-spin"}):e.jsx(D,{className:"h-3.5 w-3.5"}),x?"Saving…":"Save Changes"]})]})]}),p&&e.jsxs("div",{className:`flex items-center gap-2 rounded-lg border px-3 py-2 text-xs ${p.type==="success"?"border-success/50 text-success":p.type==="error"?"border-error/50 text-error":"border-accent/50 text-accent"}`,children:[p.type==="success"?e.jsx(H,{className:"h-4 w-4"}):p.type==="error"?e.jsx(F,{className:"h-4 w-4"}):e.jsx(U,{className:"h-4 w-4 animate-spin"}),p.message]}),e.jsxs("div",{className:"rounded-xl border border-border bg-bg-secondary p-4",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-3",children:[e.jsx(E,{className:"h-4 w-4 text-accent"}),e.jsx("h3",{className:"text-sm font-medium text-text",children:"Autonomy Level"}),e.jsx(P,{active:u("autonomy","mode")==="autonomous"})]}),e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-3 gap-2",children:["locked","supervised","autonomous"].map(s=>e.jsxs("button",{onClick:()=>S("autonomy","mode",s),className:`rounded-lg border p-3 text-left transition-all ${u("autonomy","mode")===s?"border-accent bg-accent/10":"border-border hover:border-border-light"}`,children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-xs font-medium text-text capitalize",children:s}),s==="autonomous"&&e.jsx("span",{className:"text-[9px] text-error",children:"High"}),s==="supervised"&&e.jsx("span",{className:"text-[9px] text-warning",children:"Med"}),s==="locked"&&e.jsx("span",{className:"text-[9px] text-success",children:"Low"})]}),e.jsxs("p",{className:"mt-1 text-[10px] text-text-muted leading-relaxed",children:[s==="locked"&&"Asks for approval on every tool call.",s==="supervised"&&"Auto-approves safe tools. Asks for dangerous ops.",s==="autonomous"&&"Full auto. Only asks for destructive/rare ops."]})]},s))})]}),e.jsx("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-3",children:v.filter(s=>s.field!=="mode").map(s=>{const t=u(s.section,s.field),o=typeof t=="boolean"?t:!1,i=d.has(`${s.section}.${s.field}`);return e.jsxs("div",{className:`flex items-start gap-3 rounded-xl border p-3 transition-colors ${i?"border-accent/40 bg-accent/5":"border-border bg-bg-secondary"}`,children:[e.jsx("div",{className:`mt-0.5 flex-shrink-0 rounded-lg p-2 ${o?"bg-accent/15 text-accent":"bg-bg-tertiary text-text-muted"}`,children:s.icon}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx("span",{className:"text-sm font-medium text-text",children:s.label}),e.jsx(P,{active:o})]}),e.jsx("p",{className:"mt-0.5 text-[11px] text-text-muted leading-relaxed",children:s.description})]}),e.jsxs("label",{className:"flex-shrink-0 relative inline-flex items-center cursor-pointer",children:[e.jsx("input",{type:"checkbox",checked:o,onChange:a=>S(s.section,s.field,a.target.checked),className:"sr-only peer"}),e.jsx("div",{className:`relative w-9 h-5 rounded-full transition-colors ${o?"bg-accent":"bg-border"}`,children:e.jsx("div",{className:`absolute top-[2px] left-[2px] bg-white w-4 h-4 rounded-full transition-transform ${o?"translate-x-4":"translate-x-0"}`})})]})]},s.key)})}),e.jsx("div",{className:"rounded-xl border border-warning/30 bg-warning/5 p-4",children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx(R,{className:"h-4 w-4 text-warning mt-0.5"}),e.jsxs("div",{className:"flex-1",children:[e.jsx("h3",{className:"text-sm font-medium text-text",children:"Restart TITAN"}),e.jsx("p",{className:"mt-0.5 text-[11px] text-text-muted",children:"Some feature changes require a full restart to take effect. This will briefly interrupt service."})]}),e.jsxs("button",{onClick:_,disabled:f,className:"flex items-center gap-1.5 rounded-lg border border-warning/50 px-3 py-1.5 text-xs font-medium text-warning transition-colors hover:bg-warning/10 disabled:opacity-50",children:[f?e.jsx(C,{className:"h-3.5 w-3.5 animate-spin"}):e.jsx(R,{className:"h-3.5 w-3.5"}),f?"Restarting…":"Restart"]})]})})]})}export{qe as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r,b as n,j as e}from"./index-
|
|
1
|
+
import{r,b as n,j as e}from"./index-CgHHe41p.js";import{P as c}from"./PageHeader-CwcMp_4A.js";import"./chevron-right-CA8HOEP4.js";function p(){const[t,s]=r.useState(null),[l,i]=r.useState(!0);return r.useEffect(()=>{n("/api/config",{headers:{"Content-Type":"application/json"}}).then(a=>a.json()).then(a=>{var o,d;return s({mode:((o=a.autonomy)==null?void 0:o.mode)||"supervised",interval:(d=a.autonomy)==null?void 0:d.autopilotIntervalMs})}).catch(()=>s({mode:"supervised"})).finally(()=>i(!1))},[]),l?e.jsx("div",{className:"text-[var(--text-muted)]",children:"Loading autopilot config..."}):e.jsxs("div",{className:"space-y-6",children:[e.jsx(c,{title:"Autopilot",breadcrumbs:[{label:"Admin",href:"/overview"},{label:"Agent"},{label:"Autopilot"}]}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[e.jsxs("div",{className:"bg-[var(--bg-secondary)] border border-[var(--border)] rounded-lg p-4",children:[e.jsx("p",{className:"text-sm text-[var(--text-muted)]",children:"Mode"}),e.jsx("p",{className:"text-lg font-semibold text-[var(--text)] capitalize",children:t==null?void 0:t.mode})]}),e.jsxs("div",{className:"bg-[var(--bg-secondary)] border border-[var(--border)] rounded-lg p-4",children:[e.jsx("p",{className:"text-sm text-[var(--text-muted)]",children:"Interval"}),e.jsx("p",{className:"text-lg font-semibold text-[var(--text)]",children:t!=null&&t.interval?`${Math.round(t.interval/6e4)} min`:"Not set"})]})]}),e.jsx("div",{className:"bg-[var(--bg-secondary)] border border-[var(--border)] rounded-lg p-4",children:e.jsx("p",{className:"text-sm text-[var(--text-muted)]",children:"Autopilot mode enables TITAN to run scheduled tasks automatically. Configure via titan.json."})})]})}export{p as default};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{c as q,r as p,b as T,j as e,a7 as O,V as W}from"./index-
|
|
1
|
+
import{c as q,r as p,b as T,j as e,a7 as O,V as W}from"./index-CgHHe41p.js";import{F as A}from"./flask-conical-BKbKUYhz.js";import{P as D}from"./play-D3Nbm1Cz.js";import{P as B}from"./pause-CovS6Xwq.js";import{R as H}from"./refresh-cw-_C-4Cd_3.js";import{T as V}from"./trophy-G3zNxlQS.js";import{T as G}from"./trending-up-xhvUQXWt.js";import{C as U}from"./clock-BFgCJnqQ.js";import{C as J}from"./chevron-right-CA8HOEP4.js";/**
|
|
2
2
|
* @license lucide-react v0.513.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as s,aN as p,j as e,aO as u,aP as h}from"./index-
|
|
1
|
+
import{r as s,aN as p,j as e,aO as u,aP as h}from"./index-CgHHe41p.js";import{P as g}from"./PageHeader-CwcMp_4A.js";import{P as b}from"./plus-CJKkM9fM.js";import{R as y}from"./refresh-cw-_C-4Cd_3.js";import{A as j}from"./archive-aaQ0bgj_.js";import{C as v}from"./circle-check-big-hiNdH5H3.js";import"./chevron-right-CA8HOEP4.js";function A(){const[c,m]=s.useState([]),[i,r]=s.useState(!0),[l,n]=s.useState(!1),[d,o]=s.useState(null),t=s.useCallback(async()=>{r(!0);try{const a=await p();m(a.backups||[])}catch{}r(!1)},[]);s.useEffect(()=>{t()},[t]);const x=async()=>{n(!0);try{await u(),await t()}catch{}n(!1)},f=async a=>{o(a);try{await h(a),alert("Backup verified successfully")}catch{alert("Backup verification failed")}o(null)};return e.jsxs("div",{className:"space-y-4",children:[e.jsx(g,{title:"Backup Manager",breadcrumbs:[{label:"Admin",href:"/overview"},{label:"System"},{label:"Backups"}]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs("button",{onClick:x,disabled:l,className:"flex items-center gap-2 px-3 py-2 rounded-lg bg-[#6366f1] text-white text-sm font-medium hover:bg-[#4f46e5] disabled:opacity-50",children:[e.jsx(b,{className:"w-4 h-4"})," ",l?"Creating...":"Create Backup"]}),e.jsxs("button",{onClick:t,disabled:i,className:"flex items-center gap-2 px-3 py-2 rounded-lg bg-[#27272a] text-[#a1a1aa] text-sm font-medium hover:bg-[#3f3f46] disabled:opacity-50",children:[e.jsx(y,{className:`w-4 h-4 ${i?"animate-spin":""}`})," Refresh"]})]}),c.length===0&&!i&&e.jsx("div",{className:"text-sm text-[#52525b]",children:"No backups found."}),e.jsx("div",{className:"space-y-2",children:c.map(a=>e.jsxs("div",{className:"flex items-center justify-between p-3 rounded-lg bg-[#0a0a0f] border border-[#27272a]",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(j,{className:"w-4 h-4 text-[#6366f1]"}),e.jsxs("div",{children:[e.jsx("div",{className:"text-sm text-[#e4e4e7]",children:new Date(a.createdAt).toLocaleString()}),e.jsxs("div",{className:"text-xs text-[#52525b]",children:[(a.sizeBytes/1024/1024).toFixed(1)," MB"]})]})]}),e.jsxs("button",{onClick:()=>f(a.path),disabled:d===a.path,className:"flex items-center gap-1.5 px-2.5 py-1.5 rounded-md bg-[#27272a] text-[#a1a1aa] text-xs hover:bg-[#3f3f46] disabled:opacity-50",children:[e.jsx(v,{className:"w-3.5 h-3.5"})," ",d===a.path?"Verifying...":"Verify"]})]},a.path))})]})}export{A as default};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{c as i,r as s,j as e,G as m,aw as p}from"./index-
|
|
1
|
+
import{c as i,r as s,j as e,G as m,aw as p}from"./index-CgHHe41p.js";import{P as h}from"./PageHeader-CwcMp_4A.js";import"./chevron-right-CA8HOEP4.js";/**
|
|
2
2
|
* @license lucide-react v0.513.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as a,x as b,j as e,A as u,Z as j,W as S,K as A,T as E}from"./index-
|
|
1
|
+
import{r as a,x as b,j as e,A as u,Z as j,W as S,K as A,T as E}from"./index-CgHHe41p.js";import"./Input-BGGQDAyP.js";import{P as N}from"./PageHeader-CwcMp_4A.js";import{E as T}from"./EmptyState-DSuZC-Tg.js";import{T as C}from"./Tabs-B3hK5PRj.js";import{S as w}from"./SkeletonLoader-C42HbL9c.js";import{S as P}from"./shield-check-DQeYCvwF.js";import{D as $}from"./dollar-sign-CBBudQd7.js";import{B as k}from"./bot-C4CRICZX.js";import"./clsx-B-dksMZM.js";import"./chevron-right-CA8HOEP4.js";function I(s){const r=Math.floor((Date.now()-new Date(s).getTime())/1e3);return r<60?`${r}s`:r<3600?`${Math.floor(r/60)}m`:r<86400?`${Math.floor(r/3600)}h`:`${Math.floor(r/86400)}d`}const D={agent:k,goal:E,budget:$,approval:P,error:A,tool:S,system:j},M={agent:"text-accent",goal:"text-success",budget:"text-warning",approval:"text-info",error:"text-error",tool:"text-text-secondary",system:"text-text-muted"};function K(){const[s,r]=a.useState([]),[i,f]=a.useState(!0),[o,x]=a.useState(null),[n,h]=a.useState("all"),l=a.useRef(null),c=a.useCallback(async()=>{try{const t=await b(100);r(t),x(null)}catch(t){x(t instanceof Error?t.message:"Failed to load activity")}f(!1)},[]);a.useEffect(()=>(c(),l.current=setInterval(c,1e4),()=>{l.current&&clearInterval(l.current)}),[c]);const p=Array.from(new Set(s.map(t=>t.type))),g=[{id:"all",label:"All",count:s.length},...p.map(t=>({id:t,label:t.charAt(0).toUpperCase()+t.slice(1),count:s.filter(d=>d.type===t).length}))],m=n==="all"?s:s.filter(t=>t.type===n);return e.jsxs("div",{className:"space-y-4",children:[e.jsx(N,{title:"Activity",subtitle:"Auto-refreshes every 10s",breadcrumbs:[{label:"Command Post"},{label:"Activity"}]}),p.length>0&&e.jsx(C,{tabs:g,activeTab:n,onChange:h}),i&&e.jsx(w,{variant:"row",count:8}),o&&e.jsx("div",{className:"text-center py-8 text-error text-sm",children:o}),!i&&!o&&m.length===0&&e.jsx(T,{icon:e.jsx(u,{size:32}),title:"No activity",description:"Agent activity will appear here as events occur."}),!i&&!o&&m.length>0&&e.jsx("div",{className:"divide-y divide-border rounded-xl border border-border bg-bg-secondary overflow-hidden",children:m.map((t,d)=>{const v=D[t.type]??u,y=M[t.type]??"text-text-muted";return e.jsxs("div",{className:"flex items-start gap-3 px-4 py-2.5",children:[e.jsx(v,{size:14,className:`${y} mt-0.5 flex-shrink-0`}),e.jsx("span",{className:"flex-1 text-sm text-text-secondary",children:t.message}),t.agentId&&e.jsx("span",{className:"text-[10px] text-text-muted flex-shrink-0",children:t.agentId}),e.jsx("span",{className:"text-xs text-text-muted flex-shrink-0",children:I(t.timestamp)})]},`${t.id}-${d}`)})})]})}export{K as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{p as O,u as Y,r as s,$ as G,Y as J,y as K,aB as Q,j as e,D as A,be as V}from"./index-
|
|
1
|
+
import{p as O,u as Y,r as s,$ as G,Y as J,y as K,aB as Q,j as e,D as A,be as V}from"./index-CgHHe41p.js";import{B as T}from"./Input-BGGQDAyP.js";import{S as c}from"./StatusBadge-C4dl4Z7r.js";import{P as x}from"./PageHeader-CwcMp_4A.js";import{E as W}from"./EmptyState-DSuZC-Tg.js";import{T as X}from"./Tabs-B3hK5PRj.js";import{S as Z}from"./SkeletonLoader-C42HbL9c.js";import{A as _}from"./arrow-left-xxx_FceU.js";import{C as ee}from"./circle-check-big-hiNdH5H3.js";import{D as te}from"./dollar-sign-CBBudQd7.js";import{C as se}from"./clock-BFgCJnqQ.js";import{S as ae}from"./save-B02XWwgN.js";import"./clsx-B-dksMZM.js";import"./chevron-right-CA8HOEP4.js";function k(a){const o=Math.floor((Date.now()-new Date(a).getTime())/1e3);return o<60?`${o}s`:o<3600?`${Math.floor(o/60)}m`:o<86400?`${Math.floor(o/3600)}h`:`${Math.floor(o/86400)}d`}function re(a){return a?a<1e3?`${a}ms`:`${(a/1e3).toFixed(1)}s`:"-"}function je(){const{id:a}=O(),o=Y(),[r,m]=s.useState(null),[n,E]=s.useState([]),[u,M]=s.useState([]),[P,b]=s.useState(!0),[p,i]=s.useState(null),[d,D]=s.useState("overview"),[h,g]=s.useState(""),[f,j]=s.useState(""),[v,N]=s.useState(""),[y,S]=s.useState(""),[z,C]=s.useState(!1),[R,$]=s.useState([]),w=s.useCallback(async()=>{if(a){try{const l=(await G()).find(q=>q.id===a);if(!l){i("Agent not found"),b(!1);return}m(l),g(l.role),j(l.reportsTo??""),N(l.title??""),S(l.model??"");const[H,U]=await Promise.all([J(a),K({assignee:a})]);E(H),M(U),i(null)}catch(t){i(t instanceof Error?t.message:"Failed to load agent")}b(!1)}},[a]);s.useEffect(()=>{w()},[w]),s.useEffect(()=>{Q().then(t=>$(t)).catch(()=>{})},[]);const B=async()=>{if(a){C(!0);try{const t=await V(a,{role:h,reportsTo:f||void 0,title:v||void 0,model:y||void 0});m(t)}catch{}C(!1)}},L=[{id:"overview",label:"Overview"},{id:"runs",label:"Runs",count:n.length},{id:"config",label:"Config"}];if(P)return e.jsxs("div",{className:"space-y-6",children:[e.jsx(x,{title:"Agent",breadcrumbs:[{label:"Command Post"},{label:"Agents",href:"/command-post/agents"},{label:"..."}]}),e.jsx(Z,{variant:"card",count:1})]});if(p||!r)return e.jsxs("div",{className:"space-y-6",children:[e.jsx(x,{title:"Agent",breadcrumbs:[{label:"Command Post"},{label:"Agents",href:"/command-post/agents"},{label:"Error"}]}),e.jsxs("div",{className:"text-center py-12",children:[e.jsx("p",{className:"text-error text-sm mb-4",children:p??"Agent not found"}),e.jsx(T,{variant:"secondary",size:"sm",onClick:()=>o("/command-post/agents"),children:"Back to Agents"})]})]});const I=Date.now()-new Date(r.createdAt).getTime(),F=Math.floor(I/36e5);return e.jsxs("div",{className:"space-y-4",children:[e.jsx(x,{title:r.name,subtitle:r.title??r.role,breadcrumbs:[{label:"Command Post"},{label:"Agents",href:"/command-post/agents"},{label:r.name}],actions:e.jsxs(A,{to:"/command-post/agents",className:"flex items-center gap-1 text-xs text-text-muted hover:text-text",children:[e.jsx(_,{size:14})," Back"]})}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(c,{status:r.status}),e.jsxs("span",{className:"text-xs text-text-muted",children:["Last heartbeat: ",k(r.lastHeartbeat)," ago"]})]}),e.jsx(X,{tabs:L,activeTab:d,onChange:D}),d==="overview"&&e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"grid grid-cols-3 gap-3",children:[e.jsxs("div",{className:"bg-bg-tertiary/50 border border-border rounded-xl p-4 text-center",children:[e.jsx(ee,{size:16,className:"text-success mx-auto mb-1"}),e.jsx("div",{className:"text-xl font-bold text-text",children:r.totalTasksCompleted}),e.jsx("div",{className:"text-[10px] text-text-muted",children:"Tasks Completed"})]}),e.jsxs("div",{className:"bg-bg-tertiary/50 border border-border rounded-xl p-4 text-center",children:[e.jsx(te,{size:16,className:"text-warning mx-auto mb-1"}),e.jsxs("div",{className:"text-xl font-bold text-text",children:["$",r.totalCostUsd.toFixed(4)]}),e.jsx("div",{className:"text-[10px] text-text-muted",children:"Total Cost"})]}),e.jsxs("div",{className:"bg-bg-tertiary/50 border border-border rounded-xl p-4 text-center",children:[e.jsx(se,{size:16,className:"text-accent mx-auto mb-1"}),e.jsxs("div",{className:"text-xl font-bold text-text",children:[F,"h"]}),e.jsx("div",{className:"text-[10px] text-text-muted",children:"Uptime"})]})]}),e.jsxs("div",{className:"bg-bg-secondary border border-border rounded-xl overflow-hidden",children:[e.jsx("div",{className:"px-4 py-3 border-b border-border",children:e.jsx("h3",{className:"text-sm font-semibold text-text",children:"Assigned Issues"})}),u.length===0?e.jsx("div",{className:"py-8 text-center text-xs text-text-muted",children:"No assigned issues"}):e.jsx("div",{className:"divide-y divide-border",children:u.map(t=>e.jsxs(A,{to:`/command-post/issues/${t.id}`,className:"flex items-center gap-2 px-4 py-2 hover:bg-bg-tertiary transition-colors",children:[e.jsx(c,{status:t.status,variant:"dot",size:"sm"}),e.jsx("span",{className:"text-xs text-text flex-1 truncate",children:t.title}),e.jsx("span",{className:"text-[10px] text-text-muted font-mono",children:t.identifier})]},t.id))})]})]}),d==="runs"&&e.jsx("div",{className:"bg-bg-secondary border border-border rounded-xl overflow-hidden",children:n.length===0?e.jsx(W,{title:"No runs",description:"This agent has not executed any runs yet."}):e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full text-xs",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b border-border text-left",children:[e.jsx("th",{className:"px-4 py-2 text-text-muted font-medium",children:"Source"}),e.jsx("th",{className:"px-4 py-2 text-text-muted font-medium",children:"Status"}),e.jsx("th",{className:"px-4 py-2 text-text-muted font-medium",children:"Duration"}),e.jsx("th",{className:"px-4 py-2 text-text-muted font-medium",children:"Tools"}),e.jsx("th",{className:"px-4 py-2 text-text-muted font-medium",children:"Started"})]})}),e.jsx("tbody",{className:"divide-y divide-border",children:n.map(t=>e.jsxs("tr",{className:"hover:bg-bg-tertiary/50 transition-colors",children:[e.jsx("td",{className:"px-4 py-2 text-text-secondary capitalize",children:t.source}),e.jsx("td",{className:"px-4 py-2",children:e.jsx(c,{status:t.status,size:"sm"})}),e.jsx("td",{className:"px-4 py-2 text-text-secondary",children:re(t.durationMs)}),e.jsx("td",{className:"px-4 py-2 text-text-muted",children:t.toolsUsed.length}),e.jsxs("td",{className:"px-4 py-2 text-text-muted",children:[k(t.startedAt)," ago"]})]},t.id))})]})})}),d==="config"&&e.jsxs("div",{className:"bg-bg-secondary border border-border rounded-xl p-4 space-y-4 max-w-md",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-text-muted mb-1",children:"Role"}),e.jsx("select",{className:"w-full rounded-lg border border-border bg-bg-tertiary px-3 py-2 text-sm text-text focus:outline-none focus:border-accent",value:h,onChange:t=>g(t.target.value),children:["ceo","manager","engineer","researcher","general"].map(t=>e.jsx("option",{value:t,children:t},t))})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-text-muted mb-1",children:"Reports To"}),e.jsx("input",{className:"w-full rounded-lg border border-border bg-bg-tertiary px-3 py-2 text-sm text-text placeholder:text-text-muted focus:outline-none focus:border-accent",placeholder:"Agent ID...",value:f,onChange:t=>j(t.target.value)})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-text-muted mb-1",children:"Title"}),e.jsx("input",{className:"w-full rounded-lg border border-border bg-bg-tertiary px-3 py-2 text-sm text-text placeholder:text-text-muted focus:outline-none focus:border-accent",placeholder:"e.g. Senior Engineer",value:v,onChange:t=>N(t.target.value)})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-text-muted mb-1",children:"Model"}),e.jsx("input",{list:"cp-agent-models",className:"w-full rounded-lg border border-border bg-bg-tertiary px-3 py-2 text-sm text-text placeholder:text-text-muted focus:outline-none focus:border-accent",placeholder:"e.g. ollama/qwen3.5:cloud",value:y,onChange:t=>S(t.target.value)}),e.jsx("datalist",{id:"cp-agent-models",children:R.map(t=>e.jsx("option",{value:t.id,children:t.name??t.id},t.id))})]}),e.jsx(T,{size:"sm",icon:e.jsx(ae,{size:14}),onClick:B,loading:z,children:"Save"})]})]})}export{je as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r,$ as m,j as e,U as p,D as u,X as h,b as j}from"./index-
|
|
1
|
+
import{r,$ as m,j as e,U as p,D as u,X as h,b as j}from"./index-CgHHe41p.js";import"./Input-BGGQDAyP.js";import{S as g}from"./StatusBadge-C4dl4Z7r.js";import{P as f}from"./PageHeader-CwcMp_4A.js";import{E as b}from"./EmptyState-DSuZC-Tg.js";import{S as N}from"./SkeletonLoader-C42HbL9c.js";import"./clsx-B-dksMZM.js";import"./chevron-right-CA8HOEP4.js";function y(a){const s=Math.floor((Date.now()-new Date(a).getTime())/1e3);return s<60?`${s}s`:s<3600?`${Math.floor(s/60)}m`:s<86400?`${Math.floor(s/3600)}h`:`${Math.floor(s/86400)}d`}function v(a){const s=a.split("/");return s[s.length-1]}function D(){const[a,s]=r.useState([]),[c,d]=r.useState(!0),[o,l]=r.useState(null),i=r.useCallback(async()=>{try{const t=await m();s(t),l(null)}catch(t){l(t instanceof Error?t.message:"Failed to load agents")}d(!1)},[]);r.useEffect(()=>{i()},[i]);const x=async(t,n)=>{n.preventDefault(),n.stopPropagation();try{await j(`/api/command-post/agents/${t}`,{method:"DELETE"}),await i()}catch{}};return e.jsxs("div",{className:"space-y-4",children:[e.jsx(f,{title:"Agents",breadcrumbs:[{label:"Command Post"},{label:"Agents"}]}),c&&e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3",children:e.jsx(N,{variant:"card",count:6})}),o&&e.jsx("div",{className:"text-center py-8 text-error text-sm",children:o}),!c&&!o&&a.length===0&&e.jsx(b,{icon:e.jsx(p,{size:32}),title:"No agents registered",description:"Agents will appear here once they connect to Command Post."}),!c&&!o&&a.length>0&&e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3",children:a.map(t=>e.jsxs(u,{to:`/command-post/agents/${t.id}`,className:"relative bg-bg-secondary border border-border rounded-xl p-4 hover:border-border-light transition-colors group",children:[t.role!=="ceo"&&e.jsx("button",{onClick:n=>x(t.id,n),className:"absolute top-3 right-3 p-1 rounded-md text-text-muted hover:text-error hover:bg-error/10 opacity-0 group-hover:opacity-100 transition-all",title:"Remove agent",children:e.jsx(h,{size:14})}),e.jsxs("div",{className:"flex items-center gap-2 mb-3",children:[e.jsx("span",{className:"text-sm font-semibold text-text",children:t.name}),e.jsx(g,{status:t.status,size:"sm"})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-[10px] text-text-muted uppercase",children:"Role"}),e.jsx("span",{className:"text-xs text-text-secondary capitalize",children:t.role})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-[10px] text-text-muted uppercase",children:"Model"}),e.jsx("span",{className:"text-xs text-text-secondary truncate max-w-[140px]",children:v(t.model)})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-[10px] text-text-muted uppercase",children:"Last Heartbeat"}),e.jsxs("span",{className:"text-xs text-text-secondary",children:[y(t.lastHeartbeat)," ago"]})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-[10px] text-text-muted uppercase",children:"Tasks Done"}),e.jsx("span",{className:"text-xs text-text-secondary",children:t.totalTasksCompleted})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-[10px] text-text-muted uppercase",children:"Cost"}),e.jsxs("span",{className:"text-xs text-text-secondary",children:["$",t.totalCostUsd.toFixed(4)]})]})]})]},t.id))})]})}export{D as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as a,J as P,z,j as t,K as B,X as R,O as $,P as _}from"./index-
|
|
1
|
+
import{r as a,J as P,z,j as t,K as B,X as R,O as $,P as _}from"./index-CgHHe41p.js";import{B as A}from"./Input-BGGQDAyP.js";import{S as D}from"./StatusBadge-C4dl4Z7r.js";import{P as M}from"./PageHeader-CwcMp_4A.js";import{E as L}from"./EmptyState-DSuZC-Tg.js";import{T as W}from"./Tabs-B3hK5PRj.js";import{S as F}from"./SkeletonLoader-C42HbL9c.js";import{e as H}from"./approvalHeadline-DB9SgR-9.js";import{S as I}from"./shield-check-DQeYCvwF.js";import{C as K}from"./check-BJMHM0tu.js";import"./clsx-B-dksMZM.js";import"./chevron-right-CA8HOEP4.js";function U(r){const o=Math.floor((Date.now()-new Date(r).getTime())/1e3);return o<60?`${o}s`:o<3600?`${Math.floor(o/60)}m`:o<86400?`${Math.floor(o/3600)}h`:`${Math.floor(o/86400)}d`}function q(r){return r==="high"?"text-error bg-error/10 border-error/30":r==="medium"?"text-warn bg-warn/10 border-warn/30":"text-text-muted bg-bg-tertiary border-border"}const J=[{id:"all",label:"All"},{id:"pending",label:"Pending"},{id:"approved",label:"Approved"},{id:"rejected",label:"Rejected"}];function ae(){const[r,o]=a.useState([]),[m,k]=a.useState(!0),[i,d]=a.useState(null),[l,w]=a.useState("all"),[h,c]=a.useState(null),[b,v]=a.useState({}),[u,j]=a.useState(null),{toast:p}=P(),x=a.useCallback(async()=>{try{const e=await z();o(e),d(null)}catch(e){d(e instanceof Error?e.message:"Failed to load approvals")}k(!1)},[]);a.useEffect(()=>{x()},[x]);const y=async e=>{var s;c(e.id);try{const n=(s=b[e.id])==null?void 0:s.trim();await $(e.id,"user",n||void 0),await x();const f=e.type==="goal_proposal"||e.type==="soma_proposal",T=e.type==="custom"&&e.payload.kind==="driver_blocked";p("success",f?"Work approved — TITAN is starting…":T?"Unblocked — TITAN is resuming…":"Approved"),v(E=>{const N={...E};return delete N[e.id],N}),j(null)}catch(n){d(n instanceof Error?n.message:"Approve failed"),p("error","Approval failed")}c(null)},S=async e=>{c(e.id);try{await _(e.id,"user"),await x(),p("success","Rejected")}catch(s){d(s instanceof Error?s.message:"Reject failed"),p("error","Rejection failed")}c(null)},g=l==="all"?r:r.filter(e=>e.status===l),C=J.map(e=>({...e,count:e.id==="all"?r.length:r.filter(s=>s.status===e.id).length}));return t.jsxs("div",{className:"space-y-4",children:[t.jsx(M,{title:"Approvals",breadcrumbs:[{label:"Command Post"},{label:"Approvals"}]}),t.jsx(W,{tabs:C,activeTab:l,onChange:w}),m&&t.jsx(F,{variant:"row",count:5}),i&&t.jsx("div",{className:"text-center py-8 text-error text-sm",children:i}),!m&&!i&&g.length===0&&t.jsx(L,{icon:t.jsx(I,{size:32}),title:"No approvals",description:l==="pending"?"No pending approvals.":"No approvals to show."}),!m&&!i&&g.length>0&&t.jsx("div",{className:"divide-y divide-border rounded-xl border border-border bg-bg-secondary overflow-hidden",children:g.map(e=>{const s=H(e);return t.jsxs("div",{className:"flex items-start gap-3 px-4 py-3",children:[t.jsxs("div",{className:"flex-1 min-w-0",children:[t.jsxs("div",{className:"flex items-center gap-2 mb-1.5 flex-wrap",children:[t.jsxs("span",{className:`text-[10px] px-1.5 py-0.5 rounded border font-medium uppercase tracking-wide ${q(s.urgency)}`,children:[s.urgency==="high"&&t.jsx(B,{size:10,className:"inline mr-0.5"}),s.kindLabel]}),t.jsx(D,{status:e.status,size:"sm"}),t.jsxs("span",{className:"text-xs text-text-muted",children:["from ",t.jsx("span",{className:"font-medium text-text-secondary",children:e.requestedBy})]})]}),t.jsx("div",{className:"text-sm text-text font-medium leading-snug mb-0.5",children:s.headline}),s.detail&&t.jsx("div",{className:"text-xs text-text-secondary leading-snug",children:s.detail}),e.decidedBy&&t.jsxs("div",{className:"text-[10px] text-text-muted mt-1",children:["Decided by ",e.decidedBy,e.decisionNote?`: ${e.decisionNote}`:""]})]}),t.jsx("span",{className:"text-xs text-text-muted flex-shrink-0 pt-0.5",children:U(e.createdAt)}),e.status==="pending"&&t.jsxs("div",{className:"flex flex-col items-end gap-1 flex-shrink-0",children:[t.jsxs("div",{className:"flex items-center gap-1",children:[e.type==="custom"&&e.payload.kind==="driver_blocked"&&t.jsx("button",{onClick:()=>j(u===e.id?null:e.id),className:"text-[10px] text-text-muted hover:text-text-secondary px-2 py-1 rounded hover:bg-bg-tertiary transition-colors",children:u===e.id?"Cancel":"Answer"}),t.jsx(A,{size:"sm",variant:"ghost",onClick:()=>y(e),loading:h===e.id,icon:t.jsx(K,{size:14}),children:"Approve"}),t.jsx(A,{size:"sm",variant:"ghost",onClick:()=>S(e),loading:h===e.id,icon:t.jsx(R,{size:14}),children:"Reject"})]}),u===e.id&&t.jsx("input",{type:"text",value:b[e.id]||"",onChange:n=>v(f=>({...f,[e.id]:n.target.value})),placeholder:"Type your answer...",className:"w-64 rounded-md border border-border bg-bg px-3 py-1.5 text-xs text-text outline-none focus:border-accent mt-1",onKeyDown:n=>{n.key==="Enter"&&y(e)},autoFocus:!0})]})]},e.id)})})]})}export{ae as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as s,a2 as F,j as e,a3 as I,a4 as $}from"./index-
|
|
1
|
+
import{r as s,a2 as F,j as e,a3 as I,a4 as $}from"./index-CgHHe41p.js";import{B as u}from"./Input-BGGQDAyP.js";import{S as w}from"./StatusBadge-C4dl4Z7r.js";import{P as A}from"./PageHeader-CwcMp_4A.js";import{E as L}from"./EmptyState-DSuZC-Tg.js";import{M as W}from"./Modal-CNnSfYJm.js";import{S as M}from"./SkeletonLoader-C42HbL9c.js";import{P as G}from"./plus-CJKkM9fM.js";import{D as H}from"./dollar-sign-CBBudQd7.js";import{T as R}from"./trash-2-kiHv5iAF.js";import"./clsx-B-dksMZM.js";import"./chevron-right-CA8HOEP4.js";import"./proxy-CaK_YXZW.js";function q(r){const l=r.limitUsd>0?r.currentSpend/r.limitUsd*100:0;return l>=100?"exceeded":l>=r.warningThresholdPercent?"warning":"healthy"}function ae(){const[r,l]=s.useState([]),[c,C]=s.useState(!0),[n,m]=s.useState(null),[S,a]=s.useState(!1),[k,g]=s.useState(!1),[o,p]=s.useState(""),[i,P]=s.useState("global"),[h,b]=s.useState(""),[j,B]=s.useState("monthly"),[f,v]=s.useState("10"),[y,z]=s.useState("80"),[N,T]=s.useState("warn"),d=s.useCallback(async()=>{try{const t=await F();l(t),m(null)}catch(t){m(t instanceof Error?t.message:"Failed to load budgets")}C(!1)},[]);s.useEffect(()=>{d()},[d]);const D=async()=>{if(o.trim()){g(!0);try{await $({name:o.trim(),scope:{type:i,targetId:h||void 0},period:j,limitUsd:parseFloat(f)||10,warningThresholdPercent:parseInt(y)||80,action:N,enabled:!0}),a(!1),p(""),b(""),v("10"),await d()}catch{}g(!1)}},E=async t=>{try{await I(t),await d()}catch{}};return e.jsxs("div",{className:"space-y-4",children:[e.jsx(A,{title:"Costs & Budgets",breadcrumbs:[{label:"Command Post"},{label:"Costs"}],actions:e.jsx(u,{size:"sm",icon:e.jsx(G,{size:14}),onClick:()=>a(!0),children:"Create Budget"})}),c&&e.jsx(M,{variant:"row",count:4}),n&&e.jsx("div",{className:"text-center py-8 text-error text-sm",children:n}),!c&&!n&&r.length===0&&e.jsx(L,{icon:e.jsx(H,{size:32}),title:"No budgets",description:"Create budget policies to control agent spending.",action:{label:"Create Budget",onClick:()=>a(!0)}}),!c&&!n&&r.length>0&&e.jsx("div",{className:"divide-y divide-border rounded-xl border border-border bg-bg-secondary overflow-hidden",children:r.map(t=>{const U=t.limitUsd>0?t.currentSpend/t.limitUsd*100:0,x=q(t);return e.jsxs("div",{className:"flex items-center gap-4 px-4 py-3",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[e.jsx("span",{className:"text-sm font-medium text-text",children:t.name}),e.jsx(w,{status:x,size:"sm"}),!t.enabled&&e.jsx(w,{status:"disabled",size:"sm"})]}),e.jsxs("div",{className:"flex items-center gap-3 text-[10px] text-text-muted",children:[e.jsxs("span",{className:"capitalize",children:[t.scope.type,t.scope.targetId?`: ${t.scope.targetId}`:""]}),e.jsx("span",{className:"capitalize",children:t.period}),e.jsxs("span",{children:["Action: ",t.action]})]})]}),e.jsxs("div",{className:"text-right flex-shrink-0",children:[e.jsxs("div",{className:"text-sm font-medium text-text",children:["$",t.currentSpend.toFixed(2)," / $",t.limitUsd.toFixed(2)]}),e.jsx("div",{className:"w-24 h-1.5 bg-bg-tertiary rounded-full overflow-hidden mt-1",children:e.jsx("div",{className:`h-full rounded-full transition-all ${x==="exceeded"?"bg-error":x==="warning"?"bg-warning":"bg-success"}`,style:{width:`${Math.min(100,U)}%`}})})]}),e.jsx("button",{onClick:()=>E(t.id),className:"p-1.5 rounded-md text-text-muted hover:text-error hover:bg-error/10 transition-colors flex-shrink-0",title:"Delete budget",children:e.jsx(R,{size:14})})]},t.id)})}),e.jsx(W,{open:S,onClose:()=>a(!1),title:"Create Budget Policy",footer:e.jsxs(e.Fragment,{children:[e.jsx(u,{variant:"secondary",size:"sm",onClick:()=>a(!1),children:"Cancel"}),e.jsx(u,{size:"sm",onClick:D,loading:k,disabled:!o.trim(),children:"Create"})]}),children:e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-text-muted mb-1",children:"Name"}),e.jsx("input",{className:"w-full rounded-lg border border-border bg-bg-tertiary px-3 py-2 text-sm text-text placeholder:text-text-muted focus:outline-none focus:border-accent",placeholder:"Budget name...",value:o,onChange:t=>p(t.target.value),autoFocus:!0})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-text-muted mb-1",children:"Scope"}),e.jsxs("select",{className:"w-full rounded-lg border border-border bg-bg-tertiary px-3 py-2 text-sm text-text focus:outline-none focus:border-accent",value:i,onChange:t=>P(t.target.value),children:[e.jsx("option",{value:"global",children:"Global"}),e.jsx("option",{value:"agent",children:"Agent"}),e.jsx("option",{value:"goal",children:"Goal"})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-text-muted mb-1",children:"Period"}),e.jsxs("select",{className:"w-full rounded-lg border border-border bg-bg-tertiary px-3 py-2 text-sm text-text focus:outline-none focus:border-accent",value:j,onChange:t=>B(t.target.value),children:[e.jsx("option",{value:"daily",children:"Daily"}),e.jsx("option",{value:"weekly",children:"Weekly"}),e.jsx("option",{value:"monthly",children:"Monthly"})]})]})]}),i!=="global"&&e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-text-muted mb-1",children:"Target ID"}),e.jsx("input",{className:"w-full rounded-lg border border-border bg-bg-tertiary px-3 py-2 text-sm text-text placeholder:text-text-muted focus:outline-none focus:border-accent",placeholder:`${i} ID...`,value:h,onChange:t=>b(t.target.value)})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-text-muted mb-1",children:"Limit (USD)"}),e.jsx("input",{type:"number",className:"w-full rounded-lg border border-border bg-bg-tertiary px-3 py-2 text-sm text-text focus:outline-none focus:border-accent",value:f,onChange:t=>v(t.target.value)})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-text-muted mb-1",children:"Warning %"}),e.jsx("input",{type:"number",className:"w-full rounded-lg border border-border bg-bg-tertiary px-3 py-2 text-sm text-text focus:outline-none focus:border-accent",value:y,onChange:t=>z(t.target.value)})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-text-muted mb-1",children:"Action on Threshold"}),e.jsxs("select",{className:"w-full rounded-lg border border-border bg-bg-tertiary px-3 py-2 text-sm text-text focus:outline-none focus:border-accent",value:N,onChange:t=>T(t.target.value),children:[e.jsx("option",{value:"warn",children:"Warn"}),e.jsx("option",{value:"pause",children:"Pause"}),e.jsx("option",{value:"stop",children:"Stop"})]})]})]})})]})}export{ae as default};
|