titan-agent 6.5.3 → 7.1.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.
Files changed (411) hide show
  1. package/README.md +200 -47
  2. package/assets/agent-skills/NOTICE-ECC.md +39 -0
  3. package/assets/agent-skills/agent-introspection-debugging/SKILL.md +153 -0
  4. package/assets/agent-skills/continuous-agent-loop/SKILL.md +45 -0
  5. package/assets/agent-skills/continuous-learning/SKILL.md +131 -0
  6. package/assets/agent-skills/continuous-learning/config.json +18 -0
  7. package/assets/agent-skills/continuous-learning/evaluate-session.sh +69 -0
  8. package/assets/agent-skills/production-audit/SKILL.md +206 -0
  9. package/assets/agent-skills/recursive-decision-ledger/SKILL.md +79 -0
  10. package/assets/agent-skills/scientific-thinking-literature-review/SKILL.md +192 -0
  11. package/assets/agent-skills/scientific-thinking-scholar-evaluation/SKILL.md +160 -0
  12. package/assets/agent-skills/verification-loop/SKILL.md +126 -0
  13. package/dist/agent/agent.js +104 -29
  14. package/dist/agent/agent.js.map +1 -1
  15. package/dist/agent/agentLoop.js +6 -2
  16. package/dist/agent/agentLoop.js.map +1 -1
  17. package/dist/agent/autoModeClassifier.js +26 -2
  18. package/dist/agent/autoModeClassifier.js.map +1 -1
  19. package/dist/agent/contextManager.js +1 -1
  20. package/dist/agent/contextManager.js.map +1 -1
  21. package/dist/agent/goalDriver.js +2 -0
  22. package/dist/agent/goalDriver.js.map +1 -1
  23. package/dist/agent/goalSpec.js +229 -0
  24. package/dist/agent/goalSpec.js.map +1 -0
  25. package/dist/agent/heartbeat.js +130 -0
  26. package/dist/agent/heartbeat.js.map +1 -0
  27. package/dist/agent/missionDecompose.js +38 -0
  28. package/dist/agent/missionDecompose.js.map +1 -0
  29. package/dist/agent/muscleMemory.js +291 -0
  30. package/dist/agent/muscleMemory.js.map +1 -0
  31. package/dist/agent/observationWriter.js +56 -0
  32. package/dist/agent/observationWriter.js.map +1 -0
  33. package/dist/agent/promptSectionCaps.js +6 -0
  34. package/dist/agent/promptSectionCaps.js.map +1 -1
  35. package/dist/agent/reminders.js +101 -0
  36. package/dist/agent/reminders.js.map +1 -0
  37. package/dist/agent/systemWidgets.js +41 -0
  38. package/dist/agent/systemWidgets.js.map +1 -0
  39. package/dist/agent/toolRunner.js +24 -0
  40. package/dist/agent/toolRunner.js.map +1 -1
  41. package/dist/agent/toolSearch.js +12 -2
  42. package/dist/agent/toolSearch.js.map +1 -1
  43. package/dist/channels/messenger.js +39 -0
  44. package/dist/channels/messenger.js.map +1 -1
  45. package/dist/config/config.js +7 -0
  46. package/dist/config/config.js.map +1 -1
  47. package/dist/config/schema.js +36 -1
  48. package/dist/config/schema.js.map +1 -1
  49. package/dist/eval/harness.js +17 -4
  50. package/dist/eval/harness.js.map +1 -1
  51. package/dist/gateway/onboarding.js +91 -0
  52. package/dist/gateway/onboarding.js.map +1 -0
  53. package/dist/gateway/routes/skills.js +2 -1
  54. package/dist/gateway/routes/skills.js.map +1 -1
  55. package/dist/gateway/routes/studioRouter.js +88 -0
  56. package/dist/gateway/routes/studioRouter.js.map +1 -0
  57. package/dist/gateway/routes/watchRouter.js +4 -4
  58. package/dist/gateway/routes/watchRouter.js.map +1 -1
  59. package/dist/gateway/server.js +270 -46
  60. package/dist/gateway/server.js.map +1 -1
  61. package/dist/gateway/slashCommands.js +31 -0
  62. package/dist/gateway/slashCommands.js.map +1 -1
  63. package/dist/mcp/agentTools.js +135 -0
  64. package/dist/mcp/agentTools.js.map +1 -0
  65. package/dist/mcp/server.js +19 -2
  66. package/dist/mcp/server.js.map +1 -1
  67. package/dist/memory/graph.js +2 -0
  68. package/dist/memory/graph.js.map +1 -1
  69. package/dist/memory/taxonomy.js +117 -0
  70. package/dist/memory/taxonomy.js.map +1 -0
  71. package/dist/providers/errorTaxonomy.js +4 -0
  72. package/dist/providers/errorTaxonomy.js.map +1 -1
  73. package/dist/providers/moa.js +151 -0
  74. package/dist/providers/moa.js.map +1 -0
  75. package/dist/providers/modelCapabilities.js +78 -2
  76. package/dist/providers/modelCapabilities.js.map +1 -1
  77. package/dist/providers/ollama.js +9 -2
  78. package/dist/providers/ollama.js.map +1 -1
  79. package/dist/providers/openai.js +1 -1
  80. package/dist/providers/openai.js.map +1 -1
  81. package/dist/providers/openai_compat.js +52 -4
  82. package/dist/providers/openai_compat.js.map +1 -1
  83. package/dist/providers/router.js +16 -0
  84. package/dist/providers/router.js.map +1 -1
  85. package/dist/recipes/runner.js +8 -1
  86. package/dist/recipes/runner.js.map +1 -1
  87. package/dist/recipes/store.js +2 -1
  88. package/dist/recipes/store.js.map +1 -1
  89. package/dist/skills/builtin/codebase_explore.js +214 -0
  90. package/dist/skills/builtin/codebase_explore.js.map +1 -0
  91. package/dist/skills/builtin/config_audit.js +160 -0
  92. package/dist/skills/builtin/config_audit.js.map +1 -0
  93. package/dist/skills/builtin/delegate_agent.js +107 -0
  94. package/dist/skills/builtin/delegate_agent.js.map +1 -0
  95. package/dist/skills/builtin/memory_map.js +38 -0
  96. package/dist/skills/builtin/memory_map.js.map +1 -0
  97. package/dist/skills/builtin/reminders.js +67 -0
  98. package/dist/skills/builtin/reminders.js.map +1 -0
  99. package/dist/skills/builtin/spec.js +139 -0
  100. package/dist/skills/builtin/spec.js.map +1 -0
  101. package/dist/skills/builtin/widget_gallery.js +12 -5
  102. package/dist/skills/builtin/widget_gallery.js.map +1 -1
  103. package/dist/skills/frontmatterLoader.js +7 -1
  104. package/dist/skills/frontmatterLoader.js.map +1 -1
  105. package/dist/skills/registry.js +12 -0
  106. package/dist/skills/registry.js.map +1 -1
  107. package/dist/substrate/traceBus.js.map +1 -1
  108. package/dist/telemetry/traceStore.js +127 -0
  109. package/dist/telemetry/traceStore.js.map +1 -0
  110. package/dist/utils/benchMode.js +8 -0
  111. package/dist/utils/benchMode.js.map +1 -0
  112. package/dist/utils/constants.js +1 -1
  113. package/dist/utils/constants.js.map +1 -1
  114. package/dist/utils/contrast.js +69 -0
  115. package/dist/utils/contrast.js.map +1 -0
  116. package/dist/watch/sessionContext.js +14 -0
  117. package/dist/watch/sessionContext.js.map +1 -0
  118. package/dist/watch/sessionTrace.js +51 -0
  119. package/dist/watch/sessionTrace.js.map +1 -0
  120. package/dist/watch/studioBuffer.js +53 -0
  121. package/dist/watch/studioBuffer.js.map +1 -0
  122. package/package.json +29 -28
  123. package/ui/dist/assets/AboutYouMemory-57X5SqHQ.js +1 -0
  124. package/ui/dist/assets/AuditPanel-AyB8ciLZ.js +1 -0
  125. package/ui/dist/assets/AutonomyPanel-wmVPr-n3.js +1 -0
  126. package/ui/dist/assets/AutopilotPanel-CbLy4lJP.js +1 -0
  127. package/ui/dist/assets/AutoresearchPanel-DxRO1rBF.js +1 -0
  128. package/ui/dist/assets/BackupPanel-BUh9rQ-3.js +1 -0
  129. package/ui/dist/assets/BrowserPanel-OqKwGrIL.js +1 -0
  130. package/ui/dist/assets/CPActivity-DGfS7EY3.js +1 -0
  131. package/ui/dist/assets/CPAgentDetail-p0Kvzhhb.js +1 -0
  132. package/ui/dist/assets/CPAgents-B6wSSQZM.js +1 -0
  133. package/ui/dist/assets/CPApprovals-CYv9Do0i.js +1 -0
  134. package/ui/dist/assets/CPCosts-Dx6Q71rN.js +1 -0
  135. package/ui/dist/assets/CPDashboard-DA8-tE-l.js +1 -0
  136. package/ui/dist/assets/CPFiles-BJ49tzai.js +1 -0
  137. package/ui/dist/assets/CPGoals-h0dKL5V_.js +1 -0
  138. package/ui/dist/assets/CPInbox-CDvefgNH.js +1 -0
  139. package/ui/dist/assets/CPIssueDetail-CnmLzzDD.js +1 -0
  140. package/ui/dist/assets/CPIssues-DknAIMyl.js +1 -0
  141. package/ui/dist/assets/CPLayout-C2nqgkmY.js +2 -0
  142. package/ui/dist/assets/CPOrg-tDbHFphX.js +1 -0
  143. package/ui/dist/assets/CPRuns-UlrIURqG.js +1 -0
  144. package/ui/dist/assets/CPSocial-B-gHgvEw.js +1 -0
  145. package/ui/dist/assets/CPVoice-CJy938ZF.js +1 -0
  146. package/ui/dist/assets/ChannelsPanel-DLbxg1zO.js +1 -0
  147. package/ui/dist/assets/CheckpointsPanel-BB6TT0aE.js +1 -0
  148. package/ui/dist/assets/CommandPostHub-fIslwU_t.js +2 -0
  149. package/ui/dist/assets/ConfirmDialog-6hcNjmAh.js +9 -0
  150. package/ui/dist/assets/CronPanel-DLpw3Y25.js +1 -0
  151. package/ui/dist/assets/DataTable-KVqtDzvP.js +1 -0
  152. package/ui/dist/assets/DreamPanel-lcMXpbEb.js +5 -0
  153. package/ui/dist/assets/EmptyState-D-Dg8B8r.js +1 -0
  154. package/ui/dist/assets/EvalHarnessPanel-BKzRiiQw.js +2 -0
  155. package/ui/dist/assets/EvalPanel-Dtodacmj.js +1 -0
  156. package/ui/dist/assets/FileViewer-DjcVKkO2.js +60 -0
  157. package/ui/dist/assets/FilesPanel-BI90Pplh.js +1 -0
  158. package/ui/dist/assets/FleetPanel-tr0wjAwr.js +1 -0
  159. package/ui/dist/assets/HomelabPanel-m8vMm5rE.js +1 -0
  160. package/ui/dist/assets/InfraView-3WriJnyE.js +2 -0
  161. package/ui/dist/assets/IntegrationsPanel-BmL70fOw.js +1 -0
  162. package/ui/dist/assets/IntelligenceView-BGVxCKD3.js +2 -0
  163. package/ui/dist/assets/LearningPanel-CrYLQ6eV.js +1 -0
  164. package/ui/dist/assets/LiveStudio-CnW3eZYF.js +2 -0
  165. package/ui/dist/assets/LogsPanel-DbShr4Ic.js +1 -0
  166. package/ui/dist/assets/McpPanel-uMYEsPI4.js +1 -0
  167. package/ui/dist/assets/MemoryGraphPanel-C7-Z8f0v.js +1 -0
  168. package/ui/dist/assets/MemoryTaxonomyPanel-KrxN8U1G.js +1 -0
  169. package/ui/dist/assets/MemoryWikiPanel-DI3q6IHC.js +1 -0
  170. package/ui/dist/assets/MeshPanel-D4-g2tlu.js +1 -0
  171. package/ui/dist/assets/MissionCanvas-D8cjakJe.js +61 -0
  172. package/ui/dist/assets/MissionChat-BvqCUf1E.js +3 -0
  173. package/ui/dist/assets/MissionLibrary-CZoJQ9WD.js +1 -0
  174. package/ui/dist/assets/MissionStart-CXCq-_AD.js +1 -0
  175. package/ui/dist/assets/NvidiaPanel-BfI1K5Pg.js +1 -0
  176. package/ui/dist/assets/OrganismPanel-B7Gm9pP-.js +1 -0
  177. package/ui/dist/assets/OverviewPanel-B9tKWRK2.js +1 -0
  178. package/ui/dist/assets/PageHeader-CH85uoZG.js +1 -0
  179. package/ui/dist/assets/PersonaProfilesPanel-BPi8fl-U.js +3 -0
  180. package/ui/dist/assets/PersonasPanel-Dwr7sycT.js +1 -0
  181. package/ui/dist/assets/PhoneDeskPanel-D7qc6wUI.js +1 -0
  182. package/ui/dist/assets/RecipesPanel-DcqPWRSU.js +1 -0
  183. package/ui/dist/assets/SecurityPanel-Bv_B9Ahf.js +1 -0
  184. package/ui/dist/assets/SelfImprovePanel-Ca4rGwEG.js +1 -0
  185. package/ui/dist/assets/SelfProposalsPanel-DteMSASq.js +1 -0
  186. package/ui/dist/assets/SessionsPanel-BdbbKTbL.js +1 -0
  187. package/ui/dist/assets/SessionsTab-BJipiVJs.js +1 -0
  188. package/ui/dist/assets/SettingsPanel-mV7ykOCc.js +1 -0
  189. package/ui/dist/assets/SettingsView-Bu_wYTT5.js +2 -0
  190. package/ui/dist/assets/SkeletonLoader-9H7QWa9E.js +1 -0
  191. package/ui/dist/assets/SkillsPanel-CHwX2kDR.js +1 -0
  192. package/ui/dist/assets/SomaView-Bpsm4ZW7.js +5 -0
  193. package/ui/dist/assets/SomaView-Dghh9om4.css +1 -0
  194. package/ui/dist/assets/StatCard-wmSgMAM3.js +1 -0
  195. package/ui/dist/assets/TeamsPanel-XJiHxdDX.js +1 -0
  196. package/ui/dist/assets/TelemetryPanel-_pmGVxpO.js +1 -0
  197. package/ui/dist/assets/TitanCanvas-Cb7KG80W.css +1 -0
  198. package/ui/dist/assets/TitanCanvas-CmLy7p2N.js +883 -0
  199. package/ui/dist/assets/ToolsView-PHizHZBx.js +2 -0
  200. package/ui/dist/assets/TraceViewer-CYAzIcfB.js +1 -0
  201. package/ui/dist/assets/TracesPanel-CRSN_dzK.js +1 -0
  202. package/ui/dist/assets/TrainingPanel-B9rcuMsV.js +1 -0
  203. package/ui/dist/assets/VoiceOverlay-BL_ns1ZA.js +7 -0
  204. package/ui/dist/assets/VramPanel-BNPQ06_9.js +1 -0
  205. package/ui/dist/assets/WatchView-BgAkNnur.js +13 -0
  206. package/ui/dist/assets/WorkTab-RRpPpEOg.js +1 -0
  207. package/ui/dist/assets/WorkflowBuilderPanel-BPHIH8pf.js +1 -0
  208. package/ui/dist/assets/WorkflowsPanel-DqtmT0NB.js +1 -0
  209. package/ui/dist/assets/approvalHeadline-BRg3ReTi.js +1 -0
  210. package/ui/dist/assets/archive-DcK9HrbE.js +1 -0
  211. package/ui/dist/assets/arrow-left-4c2FnES1.js +1 -0
  212. package/ui/dist/assets/book-open-Ds_yciQm.js +1 -0
  213. package/ui/dist/assets/bot-CWDCc265.js +1 -0
  214. package/ui/dist/assets/chart-column-hhZMdCgB.js +1 -0
  215. package/ui/dist/assets/chevron-right-A_pvnRh_.js +1 -0
  216. package/ui/dist/assets/circle-check-big-C-JUM7wb.js +1 -0
  217. package/ui/dist/assets/circle-stop-yZuG9ZAE.js +1 -0
  218. package/ui/dist/assets/clipboard-list-C2HUEjZc.js +1 -0
  219. package/ui/dist/assets/clock-DSPgndSD.js +1 -0
  220. package/ui/dist/assets/clsx-CjueKrWZ.js +1 -0
  221. package/ui/dist/assets/createLucideIcon-qnlrxww7.js +1 -0
  222. package/ui/dist/assets/database-C1SgHa8T.js +1 -0
  223. package/ui/dist/assets/dollar-sign-D9siqK91.js +1 -0
  224. package/ui/dist/assets/download-CJZWQNfV.js +1 -0
  225. package/ui/dist/assets/external-link-CpQLWKKE.js +1 -0
  226. package/ui/dist/assets/file-text-BbGTi-Po.js +1 -0
  227. package/ui/dist/assets/flask-conical-B1YVft4E.js +1 -0
  228. package/ui/dist/assets/folder-EbR-w2Mq.js +1 -0
  229. package/ui/dist/assets/funnel-D2Dkn8Pf.js +1 -0
  230. package/ui/dist/assets/git-branch-CQ2yNSzU.js +1 -0
  231. package/ui/dist/assets/git-pull-request-BxL5wlGX.js +1 -0
  232. package/ui/dist/assets/index-Cz8190xO.css +2 -0
  233. package/ui/dist/assets/index-WI-E4I3h.js +243 -0
  234. package/ui/dist/assets/jsx-runtime-B15e6lOy.js +1 -0
  235. package/ui/dist/assets/layers-BPu5SRjI.js +1 -0
  236. package/ui/dist/assets/legacy-BIzifT-t.js +3 -0
  237. package/ui/dist/assets/lightbulb-BY7CpMte.js +1 -0
  238. package/ui/dist/assets/link-VDQkrGJw.js +1 -0
  239. package/ui/dist/assets/list-todo-DfnNUV_T.js +1 -0
  240. package/ui/dist/assets/message-square-BpzrINHz.js +1 -0
  241. package/ui/dist/assets/mic-De6oZFaV.js +1 -0
  242. package/ui/dist/assets/missions-y-qg_f9b.js +1 -0
  243. package/ui/dist/assets/network-CM7y1ats.js +1 -0
  244. package/ui/dist/assets/pause-C4TDJSfA.js +1 -0
  245. package/ui/dist/assets/pencil-Dd_vzHE-.js +1 -0
  246. package/ui/dist/assets/play-9WxZWVHA.js +1 -0
  247. package/ui/dist/assets/plug-Dm25Wbrc.js +1 -0
  248. package/ui/dist/assets/plus-CHryCIkk.js +1 -0
  249. package/ui/dist/assets/radio-D-XnoAVu.js +1 -0
  250. package/ui/dist/assets/refresh-cw-Disd5wRB.js +1 -0
  251. package/ui/dist/assets/rotate-ccw-Cw1T2W1T.js +1 -0
  252. package/ui/dist/assets/save-DP7oNar2.js +1 -0
  253. package/ui/dist/assets/search-aNVcX-nv.js +1 -0
  254. package/ui/dist/assets/send-D7iQD57b.js +1 -0
  255. package/ui/dist/assets/server-DFfeYjoM.js +1 -0
  256. package/ui/dist/assets/settings-5NWXzgyY.js +1 -0
  257. package/ui/dist/assets/shared-DLz_Jtg3.js +1 -0
  258. package/ui/dist/assets/shield-check-Cd50jCAn.js +1 -0
  259. package/ui/dist/assets/square-DlcoJ1ZM.js +1 -0
  260. package/ui/dist/assets/terminal-DgFz2Vsf.js +1 -0
  261. package/ui/dist/assets/test-tube-BimtS92_.js +1 -0
  262. package/ui/dist/assets/toggle-right-BMaR-sfT.js +1 -0
  263. package/ui/dist/assets/trash-2-CwUv7ww1.js +1 -0
  264. package/ui/dist/assets/trending-up-Ba9TwEow.js +1 -0
  265. package/ui/dist/assets/trophy-Gfv1QC45.js +1 -0
  266. package/ui/dist/assets/volume-2-BVlfVl2U.js +1 -0
  267. package/ui/dist/assets/wifi-off-CWLeusSV.js +1 -0
  268. package/ui/dist/assets/zoom-out-DeggJ7RM.js +1 -0
  269. package/ui/dist/index.html +4 -2
  270. package/ui/dist/sw.js +1 -1
  271. package/ui/dist/assets/AuditPanel-BaftX5MP.js +0 -1
  272. package/ui/dist/assets/AutonomyPanel-CmaXJV8d.js +0 -11
  273. package/ui/dist/assets/AutopilotPanel-CbohPtXW.js +0 -1
  274. package/ui/dist/assets/AutoresearchPanel-DCwiQ2v2.js +0 -6
  275. package/ui/dist/assets/BackupPanel-DAy9G7Wt.js +0 -1
  276. package/ui/dist/assets/BrowserPanel-D6UaSxap.js +0 -6
  277. package/ui/dist/assets/CPActivity-BYDsUoMn.js +0 -1
  278. package/ui/dist/assets/CPAgentDetail-Bb9-GAJY.js +0 -1
  279. package/ui/dist/assets/CPAgents-BTZuGnki.js +0 -1
  280. package/ui/dist/assets/CPApprovals-BME2ARkO.js +0 -1
  281. package/ui/dist/assets/CPCosts-mOXwWq0i.js +0 -1
  282. package/ui/dist/assets/CPDashboard-CTlKGXXQ.js +0 -1
  283. package/ui/dist/assets/CPFiles-BO73EZwJ.js +0 -1
  284. package/ui/dist/assets/CPGoals-BNWhNP14.js +0 -1
  285. package/ui/dist/assets/CPInbox-ybe4r8LW.js +0 -16
  286. package/ui/dist/assets/CPIssueDetail-DaMMGbjw.js +0 -1
  287. package/ui/dist/assets/CPIssues-BgpQOISw.js +0 -1
  288. package/ui/dist/assets/CPLayout-bgErauTx.js +0 -2
  289. package/ui/dist/assets/CPOrg-C8l5SIWJ.js +0 -8
  290. package/ui/dist/assets/CPRuns-DB8S7loF.js +0 -1
  291. package/ui/dist/assets/CPSocial-Qw5rKy_4.js +0 -11
  292. package/ui/dist/assets/CPVoice-DfwHPewA.js +0 -1
  293. package/ui/dist/assets/ChannelsPanel-DS21E-Iz.js +0 -1
  294. package/ui/dist/assets/CheckpointsPanel-9-l_8GdG.js +0 -1
  295. package/ui/dist/assets/CommandPostHub-z55Yrhj1.js +0 -24
  296. package/ui/dist/assets/CronPanel-kEZK3gpx.js +0 -1
  297. package/ui/dist/assets/DataTable-PnhPeDBG.js +0 -1
  298. package/ui/dist/assets/DreamPanel-DIrtlk2K.js +0 -15
  299. package/ui/dist/assets/EmptyState-CfvU7SdB.js +0 -1
  300. package/ui/dist/assets/EvalHarnessPanel-uYb_ZEQG.js +0 -2
  301. package/ui/dist/assets/EvalPanel-CDG-njyj.js +0 -1
  302. package/ui/dist/assets/FileViewer-CVO3TRs3.js +0 -61
  303. package/ui/dist/assets/FilesPanel-CaLPog2e.js +0 -16
  304. package/ui/dist/assets/FleetPanel-BtlaV6pH.js +0 -1
  305. package/ui/dist/assets/HomelabPanel-BZvN4LPM.js +0 -6
  306. package/ui/dist/assets/InfraView-C0zEuFrR.js +0 -2
  307. package/ui/dist/assets/InlineEditableField-mBzpbcLB.js +0 -1
  308. package/ui/dist/assets/Input-CbrMbLgn.js +0 -1
  309. package/ui/dist/assets/IntegrationsPanel-B4TyR6jC.js +0 -1
  310. package/ui/dist/assets/IntelligenceView-DZ4HxYZ3.js +0 -2
  311. package/ui/dist/assets/LearningPanel-B4RIm_iQ.js +0 -1
  312. package/ui/dist/assets/LogsPanel-DbP3Mwnr.js +0 -1
  313. package/ui/dist/assets/McpPanel-BmNUFozc.js +0 -1
  314. package/ui/dist/assets/MemoryGraphPanel-JPurHV0L.js +0 -16
  315. package/ui/dist/assets/MemoryWikiPanel-DdvCAZHa.js +0 -6
  316. package/ui/dist/assets/MeshPanel-Bf-4brXL.js +0 -11
  317. package/ui/dist/assets/MissionCanvas-CJyhnauG.js +0 -72
  318. package/ui/dist/assets/MissionChat-C2Nto3zM.js +0 -7
  319. package/ui/dist/assets/MissionLibrary-RXyBHsLL.js +0 -5
  320. package/ui/dist/assets/MissionStart-wUkcEP0T.js +0 -1
  321. package/ui/dist/assets/Modal-BmS7C6FN.js +0 -1
  322. package/ui/dist/assets/NvidiaPanel-4DlcQlyl.js +0 -1
  323. package/ui/dist/assets/OrganismPanel-C2LYDPrn.js +0 -1
  324. package/ui/dist/assets/OverviewPanel-DK8uuq4D.js +0 -1
  325. package/ui/dist/assets/PageHeader-bnc85wQN.js +0 -1
  326. package/ui/dist/assets/PersonaProfilesPanel-DGtokXUu.js +0 -8
  327. package/ui/dist/assets/PersonasPanel-dR8VppcD.js +0 -1
  328. package/ui/dist/assets/PhoneDeskPanel-CdVOY7H9.js +0 -11
  329. package/ui/dist/assets/RecipesPanel-D3Zs2wxr.js +0 -1
  330. package/ui/dist/assets/SecurityPanel-BMERf796.js +0 -1
  331. package/ui/dist/assets/SelfImprovePanel-BxqWHXCU.js +0 -1
  332. package/ui/dist/assets/SelfProposalsPanel-CuC94vdx.js +0 -2
  333. package/ui/dist/assets/SessionsPanel-CQ8qvzp7.js +0 -1
  334. package/ui/dist/assets/SessionsTab-B3eHV3jf.js +0 -1
  335. package/ui/dist/assets/SettingsPanel-Cumls7N2.js +0 -1
  336. package/ui/dist/assets/SettingsView-BtA67pol.js +0 -2
  337. package/ui/dist/assets/SkeletonLoader-Cax7YTqW.js +0 -1
  338. package/ui/dist/assets/SkillsPanel-CA415CT8.js +0 -11
  339. package/ui/dist/assets/SomaView-BtCkeWfZ.css +0 -1
  340. package/ui/dist/assets/SomaView-eG3wI4S1.js +0 -5
  341. package/ui/dist/assets/StatCard-Djr487DV.js +0 -1
  342. package/ui/dist/assets/StatusBadge-JpCoA33_.js +0 -1
  343. package/ui/dist/assets/Tabs-DJHu-roP.js +0 -1
  344. package/ui/dist/assets/TeamsPanel-C_Vu6vnY.js +0 -1
  345. package/ui/dist/assets/TelemetryPanel-D4PXsd-X.js +0 -1
  346. package/ui/dist/assets/TitanCanvas-BfitWg9R.css +0 -1
  347. package/ui/dist/assets/TitanCanvas-TuYZSZO7.js +0 -1117
  348. package/ui/dist/assets/ToolsView-BvTN6vFn.js +0 -2
  349. package/ui/dist/assets/Tooltip-B1LhTXJ8.js +0 -6
  350. package/ui/dist/assets/TraceViewer-Bh8Jo3Dr.js +0 -1
  351. package/ui/dist/assets/TrainingPanel-Dmbd1rJ-.js +0 -1
  352. package/ui/dist/assets/VoiceOverlay-B_ss7Zg_.js +0 -17
  353. package/ui/dist/assets/VramPanel-CPICbZ2s.js +0 -1
  354. package/ui/dist/assets/WatchView-BCgLVfiV.js +0 -13
  355. package/ui/dist/assets/WorkTab-iptofXO9.js +0 -1
  356. package/ui/dist/assets/WorkflowsPanel-3RYkFHyf.js +0 -11
  357. package/ui/dist/assets/approvalHeadline-DB9SgR-9.js +0 -1
  358. package/ui/dist/assets/archive-gZFnGd5A.js +0 -6
  359. package/ui/dist/assets/arrow-left-qA0Qer2h.js +0 -6
  360. package/ui/dist/assets/book-open-DIxdPqmD.js +0 -6
  361. package/ui/dist/assets/bot-CvIF1uHi.js +0 -6
  362. package/ui/dist/assets/chart-column-BQiM-Td4.js +0 -6
  363. package/ui/dist/assets/check-DgyDEFtq.js +0 -6
  364. package/ui/dist/assets/chevron-right-CQ1NTOtd.js +0 -6
  365. package/ui/dist/assets/chevron-up-UyfdjRp6.js +0 -6
  366. package/ui/dist/assets/circle-check-big-CAFcaPPH.js +0 -6
  367. package/ui/dist/assets/circle-stop-C-8xGv0n.js +0 -6
  368. package/ui/dist/assets/clipboard-list-9DdqBj1F.js +0 -6
  369. package/ui/dist/assets/clock-CF9BCIpL.js +0 -6
  370. package/ui/dist/assets/clsx-B-dksMZM.js +0 -1
  371. package/ui/dist/assets/dollar-sign-LDRZBae6.js +0 -6
  372. package/ui/dist/assets/download-BBNXvBO0.js +0 -6
  373. package/ui/dist/assets/external-link-D_ji4Bec.js +0 -6
  374. package/ui/dist/assets/file-text-DrdTDEYp.js +0 -6
  375. package/ui/dist/assets/flask-conical-BGn5PgFX.js +0 -6
  376. package/ui/dist/assets/folder-BeZZUGnK.js +0 -6
  377. package/ui/dist/assets/funnel-CAJgGO5M.js +0 -6
  378. package/ui/dist/assets/git-branch-BcXabeOs.js +0 -6
  379. package/ui/dist/assets/index-CUgepw5Q.js +0 -337
  380. package/ui/dist/assets/index-Dm6zcSTS.css +0 -1
  381. package/ui/dist/assets/layers-DxYDmPA_.js +0 -6
  382. package/ui/dist/assets/legacy-dHWI7k8P.js +0 -3
  383. package/ui/dist/assets/lightbulb-B0Du4SM4.js +0 -6
  384. package/ui/dist/assets/link-CUpaumqr.js +0 -6
  385. package/ui/dist/assets/list-todo-CDDhmPQB.js +0 -6
  386. package/ui/dist/assets/message-square-D5VWlv-Q.js +0 -6
  387. package/ui/dist/assets/mic-Ddcc6Ann.js +0 -6
  388. package/ui/dist/assets/missions-2zox16Tc.js +0 -1
  389. package/ui/dist/assets/network-DaJ7ugwX.js +0 -6
  390. package/ui/dist/assets/pause-BukaK6rs.js +0 -6
  391. package/ui/dist/assets/pencil-D_YwQBeg.js +0 -6
  392. package/ui/dist/assets/play-BjdwtYMk.js +0 -6
  393. package/ui/dist/assets/plug-yISDdeW2.js +0 -6
  394. package/ui/dist/assets/plus-BSjTdepW.js +0 -6
  395. package/ui/dist/assets/proxy-CWET5FFX.js +0 -9
  396. package/ui/dist/assets/radio-B7kX_yWE.js +0 -6
  397. package/ui/dist/assets/refresh-cw-CwDpzXUn.js +0 -6
  398. package/ui/dist/assets/rotate-ccw-7SQDTI0_.js +0 -6
  399. package/ui/dist/assets/save-CjTPAQM0.js +0 -6
  400. package/ui/dist/assets/search-BP7VlNxX.js +0 -6
  401. package/ui/dist/assets/send-C2XDuRPf.js +0 -6
  402. package/ui/dist/assets/server-BE8W-AT4.js +0 -6
  403. package/ui/dist/assets/shield-check-s7la2J2K.js +0 -6
  404. package/ui/dist/assets/terminal-B8IK4WsO.js +0 -6
  405. package/ui/dist/assets/test-tube-Xfn9DJeg.js +0 -11
  406. package/ui/dist/assets/toggle-right-CHpzOIlj.js +0 -11
  407. package/ui/dist/assets/trash-2-B1C85ePK.js +0 -6
  408. package/ui/dist/assets/trending-up-DDGHQZY1.js +0 -6
  409. package/ui/dist/assets/trophy-D0LhJSPA.js +0 -6
  410. package/ui/dist/assets/volume-2-DMaE91b5.js +0 -6
  411. package/ui/dist/assets/wifi-off-DR9h8HGA.js +0 -6
@@ -20,6 +20,22 @@ function getAutoModePolicy() {
20
20
  }
21
21
  return "standard";
22
22
  }
23
+ const NAME_GATED_EXACT = /* @__PURE__ */ new Set([
24
+ "shell",
25
+ "run_shell",
26
+ "bash",
27
+ "run_command",
28
+ "execute_command",
29
+ "exec",
30
+ "delete_file",
31
+ "bulk_delete_labels",
32
+ "phone_call",
33
+ "make_call"
34
+ ]);
35
+ const NAME_GATED_PATTERN = /(^|_)(delete|destroy|wipe|purge|deploy|publish|transfer|payment|purchase|wire|send_email|email_send)(_|$)/i;
36
+ function nameLooksHighImpact(toolName) {
37
+ return NAME_GATED_EXACT.has(toolName) || NAME_GATED_PATTERN.test(toolName);
38
+ }
23
39
  function classifyToolCall(toolName) {
24
40
  const policy = getAutoModePolicy();
25
41
  const contract = getToolContract(toolName);
@@ -42,9 +58,16 @@ function classifyToolCall(toolName) {
42
58
  };
43
59
  }
44
60
  if (!contract) {
61
+ if (nameLooksHighImpact(toolName)) {
62
+ return {
63
+ decision: "gate",
64
+ reason: `no contract + high-impact name "${toolName}" \u2014 gating`,
65
+ policy
66
+ };
67
+ }
45
68
  return {
46
- decision: "gate",
47
- reason: `no contract registered for "${toolName}" \u2014 gating by default`,
69
+ decision: "notify",
70
+ reason: `no contract for "${toolName}" \u2014 notify (benign long-tail)`,
48
71
  policy
49
72
  };
50
73
  }
@@ -90,6 +113,7 @@ export {
90
113
  classifyToolCall,
91
114
  formatBreadcrumb,
92
115
  getAutoModePolicy,
116
+ nameLooksHighImpact,
93
117
  shouldGate
94
118
  };
95
119
  //# sourceMappingURL=autoModeClassifier.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/agent/autoModeClassifier.ts"],"sourcesContent":["/**\n * TITAN — Auto-Mode Classifier (v6.1.0-beta.16, Phase D.4)\n *\n * Reads the tool contract registry to decide whether an incoming\n * tool call can run autonomously, deserves a passive notification,\n * or requires explicit human approval. Pattern from Anthropic's\n * \"Claude Code auto-mode\" blog (in the Picrew/awesome-agent-harness\n * featured-reading list): classifier-backed approval delegation\n * gives the agent autonomy on safe paths while keeping a kill\n * switch on the risky ones.\n *\n * THREE DECISIONS:\n *\n * - 'auto' — run without prompting. Read-only ops + workspace\n * writes. Most missions run mostly 'auto' calls.\n * - 'notify' — run, but record a passive notification so a\n * watcher (Mission Canvas, log tail) can see it\n * happened. Default for network calls.\n * - 'gate' — require explicit human approval before running.\n * Default for destructive ops (shell, delete, etc.)\n * AND for any tool without a registered contract\n * (unknown → conservative).\n *\n * POLICY OVERRIDES (config.security.autoMode.policy):\n *\n * - 'standard' (default) — riskLevel drives the decision per\n * the table above.\n * - 'paranoid' — every tool call is 'gate'. For\n * demos, regulated environments, or\n * when Tony is debugging a misbehaving\n * agent.\n * - 'permissive' — riskLevel 'moderate' is auto-run\n * (still 'gate' on 'high'). For\n * trusted hot loops where ping-the-user\n * on every web_search is annoying.\n * - 'yolo' — everything auto, including 'high'.\n * ONLY for sandboxed eval runs. Logs\n * a loud warning on init.\n *\n * WHY this module exists:\n *\n * - Phase D.3 added riskLevel + sideEffects metadata to the 9\n * canonical contracts. D.4 makes the metadata actually do\n * something — gating decisions, not just labels.\n *\n * - The existing approval-gate path in toolRunner uses a hardcoded\n * \"is this tool name dangerous?\" list. That's a string-match\n * allowlist that doesn't scale and doesn't account for HOW the\n * tool is being used. The classifier is the structural answer:\n * contracts declare risk; the classifier reads contracts.\n *\n * - Decoupling the policy from the runner means changing the\n * gating semantics (e.g. add a new 'risky-during-business-hours'\n * decision) is a one-file change — never a wholesale runner\n * refactor.\n *\n * TRADE-OFFS:\n *\n * - First cut keys decisions on contract.riskLevel alone. A\n * follow-up could consider call ARGS (e.g. shell with\n * `command: 'ls'` could be 'auto' while shell with\n * `command: 'rm -rf'` is still 'gate'). Skipped for now to\n * keep the surface small + predictable.\n *\n * - Tools without a registered contract default to 'gate'. This\n * is conservative but means the long-tail 239 skills will hit\n * the approval gate on every call until their contracts ship.\n * If that becomes painful, lift the default to 'notify' via\n * the `unknownToolDefault` config field.\n *\n * FOLLOW-UP:\n *\n * - Phase D.5 reads sideEffects==='destructive' to route the\n * call into a worktree-isolated executor.\n * - Args-aware classification (shell `rm -rf` vs shell `ls`).\n * - Per-session policy override so a \"draft a quick email\"\n * mission can opt into 'permissive' while a \"review and merge\n * this PR\" mission stays on 'paranoid'.\n */\n\nimport { getToolContract, type RiskLevel } from './toolContract.js';\nimport { loadConfig } from '../config/config.js';\nimport logger from '../utils/logger.js';\n\nconst COMPONENT = 'autoMode';\n\n/* ────────────────────────── Types ────────────────────────── */\n\nexport type AutoModeDecision = 'auto' | 'notify' | 'gate';\nexport type AutoModePolicy = 'standard' | 'paranoid' | 'permissive' | 'yolo';\n\nexport interface ClassificationResult {\n /** What the runner should do with the call. */\n decision: AutoModeDecision;\n /** Plain-english reason — logged and surfaced in the trajectory. */\n reason: string;\n /** Policy that produced this decision (drives observability). */\n policy: AutoModePolicy;\n /** Risk level from the contract, if any. Undefined for unknown tools. */\n riskLevel?: RiskLevel;\n}\n\n/* ────────────────────────── Policy loader ────────────────────────── */\n\n/**\n * Resolve the current auto-mode policy. Reads\n * `config.security.autoMode.policy` if present; defaults to 'standard'.\n * Pure synchronous lookup — no IO, safe to call per-tool-call.\n */\nexport function getAutoModePolicy(): AutoModePolicy {\n // beta.21 — env override. Lets the test suite (and any embedder\n // that wants a process-wide policy without touching config files)\n // short-circuit the classifier without mutating loaded config.\n // Production callers should configure via `config.security.autoMode.policy`\n // — this env hook is opt-in and silent when unset.\n const envPolicy = process.env.TITAN_AUTOMODE_POLICY;\n if (envPolicy === 'paranoid' || envPolicy === 'permissive' || envPolicy === 'yolo' || envPolicy === 'standard') {\n return envPolicy;\n }\n try {\n const cfg = loadConfig();\n const sec = (cfg as Record<string, unknown>).security as Record<string, unknown> | undefined;\n const am = sec?.autoMode as Record<string, unknown> | undefined;\n const policy = am?.policy as string | undefined;\n if (policy === 'paranoid' || policy === 'permissive' || policy === 'yolo' || policy === 'standard') {\n return policy;\n }\n } catch { /* config unavailable — fall through */ }\n return 'standard';\n}\n\n/* ────────────────────────── Classifier ────────────────────────── */\n\n/**\n * Decide whether a tool call should run automatically, with a\n * notification, or with explicit approval. The runner uses this to\n * decide whether to short-circuit the existing approval-gate path.\n *\n * Pure: no IO beyond reading the config + contract registry. Cheap\n * enough to call on every tool call without measuring.\n */\nexport function classifyToolCall(toolName: string): ClassificationResult {\n const policy = getAutoModePolicy();\n const contract = getToolContract(toolName);\n const riskLevel = contract?.riskLevel;\n\n // yolo short-circuit: regardless of risk, run. ONLY for sandboxed\n // eval runs — logs a loud warning the first time per process.\n if (policy === 'yolo') {\n warnYoloOnce();\n return {\n decision: 'auto',\n reason: 'yolo policy — gating disabled',\n policy,\n riskLevel,\n };\n }\n\n // paranoid short-circuit: every call gated.\n if (policy === 'paranoid') {\n return {\n decision: 'gate',\n reason: 'paranoid policy — every tool call requires approval',\n policy,\n riskLevel,\n };\n }\n\n // Unknown tool (no registered contract) → conservative 'gate'.\n // The long-tail 239 skills without contracts hit this branch\n // until their contracts ship. Override via config if the prompt\n // pings become annoying.\n if (!contract) {\n return {\n decision: 'gate',\n reason: `no contract registered for \"${toolName}\" — gating by default`,\n policy,\n };\n }\n\n // Standard + permissive paths read riskLevel.\n if (riskLevel === 'safe') {\n return { decision: 'auto', reason: 'contract riskLevel=safe', policy, riskLevel };\n }\n if (riskLevel === 'moderate') {\n if (policy === 'permissive') {\n return { decision: 'auto', reason: 'permissive policy — moderate risk auto-runs', policy, riskLevel };\n }\n return { decision: 'notify', reason: 'contract riskLevel=moderate', policy, riskLevel };\n }\n if (riskLevel === 'high') {\n return { decision: 'gate', reason: 'contract riskLevel=high', policy, riskLevel };\n }\n\n // Defensive fallback for an unknown future riskLevel value.\n return {\n decision: 'gate',\n reason: `unrecognised riskLevel \"${riskLevel}\" — gating defensively`,\n policy,\n riskLevel,\n };\n}\n\n/* ────────────────────────── Helpers ────────────────────────── */\n\nlet _yoloWarned = false;\nfunction warnYoloOnce(): void {\n if (_yoloWarned) return;\n _yoloWarned = true;\n logger.warn(\n COMPONENT,\n 'AUTO_MODE=yolo — every tool call will run without approval. This mode is ONLY intended for sandboxed eval runs. If you see this in production logs, something is misconfigured.',\n );\n}\n\n/** For tests. */\nexport function _resetYoloWarning(): void {\n _yoloWarned = false;\n}\n\n/**\n * Convenience: returns true iff the decision means the call should\n * NOT proceed without explicit human approval. Used by the runner\n * to short-circuit the existing approval-gate path on 'auto' /\n * 'notify' decisions.\n */\nexport function shouldGate(result: ClassificationResult): boolean {\n return result.decision === 'gate';\n}\n\n/**\n * Format the classification as a one-line breadcrumb suitable for\n * the trajectory `note` event. Used by the runner on 'notify'\n * decisions so the trajectory captures what the agent did\n * autonomously vs what required a human prompt.\n */\nexport function formatBreadcrumb(toolName: string, result: ClassificationResult): string {\n return `automode:${result.decision} tool=${toolName} risk=${result.riskLevel ?? 'unknown'} policy=${result.policy} (${result.reason})`;\n}\n"],"mappings":";AAgFA,SAAS,uBAAuC;AAChD,SAAS,kBAAkB;AAC3B,OAAO,YAAY;AAEnB,MAAM,YAAY;AAyBX,SAAS,oBAAoC;AAMhD,QAAM,YAAY,QAAQ,IAAI;AAC9B,MAAI,cAAc,cAAc,cAAc,gBAAgB,cAAc,UAAU,cAAc,YAAY;AAC5G,WAAO;AAAA,EACX;AACA,MAAI;AACA,UAAM,MAAM,WAAW;AACvB,UAAM,MAAO,IAAgC;AAC7C,UAAM,KAAK,KAAK;AAChB,UAAM,SAAS,IAAI;AACnB,QAAI,WAAW,cAAc,WAAW,gBAAgB,WAAW,UAAU,WAAW,YAAY;AAChG,aAAO;AAAA,IACX;AAAA,EACJ,QAAQ;AAAA,EAA0C;AAClD,SAAO;AACX;AAYO,SAAS,iBAAiB,UAAwC;AACrE,QAAM,SAAS,kBAAkB;AACjC,QAAM,WAAW,gBAAgB,QAAQ;AACzC,QAAM,YAAY,UAAU;AAI5B,MAAI,WAAW,QAAQ;AACnB,iBAAa;AACb,WAAO;AAAA,MACH,UAAU;AAAA,MACV,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,IACJ;AAAA,EACJ;AAGA,MAAI,WAAW,YAAY;AACvB,WAAO;AAAA,MACH,UAAU;AAAA,MACV,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,IACJ;AAAA,EACJ;AAMA,MAAI,CAAC,UAAU;AACX,WAAO;AAAA,MACH,UAAU;AAAA,MACV,QAAQ,+BAA+B,QAAQ;AAAA,MAC/C;AAAA,IACJ;AAAA,EACJ;AAGA,MAAI,cAAc,QAAQ;AACtB,WAAO,EAAE,UAAU,QAAQ,QAAQ,2BAA2B,QAAQ,UAAU;AAAA,EACpF;AACA,MAAI,cAAc,YAAY;AAC1B,QAAI,WAAW,cAAc;AACzB,aAAO,EAAE,UAAU,QAAQ,QAAQ,oDAA+C,QAAQ,UAAU;AAAA,IACxG;AACA,WAAO,EAAE,UAAU,UAAU,QAAQ,+BAA+B,QAAQ,UAAU;AAAA,EAC1F;AACA,MAAI,cAAc,QAAQ;AACtB,WAAO,EAAE,UAAU,QAAQ,QAAQ,2BAA2B,QAAQ,UAAU;AAAA,EACpF;AAGA,SAAO;AAAA,IACH,UAAU;AAAA,IACV,QAAQ,2BAA2B,SAAS;AAAA,IAC5C;AAAA,IACA;AAAA,EACJ;AACJ;AAIA,IAAI,cAAc;AAClB,SAAS,eAAqB;AAC1B,MAAI,YAAa;AACjB,gBAAc;AACd,SAAO;AAAA,IACH;AAAA,IACA;AAAA,EACJ;AACJ;AAGO,SAAS,oBAA0B;AACtC,gBAAc;AAClB;AAQO,SAAS,WAAW,QAAuC;AAC9D,SAAO,OAAO,aAAa;AAC/B;AAQO,SAAS,iBAAiB,UAAkB,QAAsC;AACrF,SAAO,YAAY,OAAO,QAAQ,SAAS,QAAQ,SAAS,OAAO,aAAa,SAAS,WAAW,OAAO,MAAM,KAAK,OAAO,MAAM;AACvI;","names":[]}
1
+ {"version":3,"sources":["../../src/agent/autoModeClassifier.ts"],"sourcesContent":["/**\n * TITAN — Auto-Mode Classifier (v6.1.0-beta.16, Phase D.4)\n *\n * Reads the tool contract registry to decide whether an incoming\n * tool call can run autonomously, deserves a passive notification,\n * or requires explicit human approval. Pattern from Anthropic's\n * \"Claude Code auto-mode\" blog (in the Picrew/awesome-agent-harness\n * featured-reading list): classifier-backed approval delegation\n * gives the agent autonomy on safe paths while keeping a kill\n * switch on the risky ones.\n *\n * THREE DECISIONS:\n *\n * - 'auto' — run without prompting. Read-only ops + workspace\n * writes. Most missions run mostly 'auto' calls.\n * - 'notify' — run, but record a passive notification so a\n * watcher (Mission Canvas, log tail) can see it\n * happened. Default for network calls.\n * - 'gate' — require explicit human approval before running.\n * Default for destructive ops (shell, delete, etc.)\n * AND for any tool without a registered contract\n * (unknown → conservative).\n *\n * POLICY OVERRIDES (config.security.autoMode.policy):\n *\n * - 'standard' (default) — riskLevel drives the decision per\n * the table above.\n * - 'paranoid' — every tool call is 'gate'. For\n * demos, regulated environments, or\n * when Tony is debugging a misbehaving\n * agent.\n * - 'permissive' — riskLevel 'moderate' is auto-run\n * (still 'gate' on 'high'). For\n * trusted hot loops where ping-the-user\n * on every web_search is annoying.\n * - 'yolo' — everything auto, including 'high'.\n * ONLY for sandboxed eval runs. Logs\n * a loud warning on init.\n *\n * WHY this module exists:\n *\n * - Phase D.3 added riskLevel + sideEffects metadata to the 9\n * canonical contracts. D.4 makes the metadata actually do\n * something — gating decisions, not just labels.\n *\n * - The existing approval-gate path in toolRunner uses a hardcoded\n * \"is this tool name dangerous?\" list. That's a string-match\n * allowlist that doesn't scale and doesn't account for HOW the\n * tool is being used. The classifier is the structural answer:\n * contracts declare risk; the classifier reads contracts.\n *\n * - Decoupling the policy from the runner means changing the\n * gating semantics (e.g. add a new 'risky-during-business-hours'\n * decision) is a one-file change — never a wholesale runner\n * refactor.\n *\n * TRADE-OFFS:\n *\n * - First cut keys decisions on contract.riskLevel alone. A\n * follow-up could consider call ARGS (e.g. shell with\n * `command: 'ls'` could be 'auto' while shell with\n * `command: 'rm -rf'` is still 'gate'). Skipped for now to\n * keep the surface small + predictable.\n *\n * - Tools without a registered contract default to 'gate'. This\n * is conservative but means the long-tail 239 skills will hit\n * the approval gate on every call until their contracts ship.\n * If that becomes painful, lift the default to 'notify' via\n * the `unknownToolDefault` config field.\n *\n * FOLLOW-UP:\n *\n * - Phase D.5 reads sideEffects==='destructive' to route the\n * call into a worktree-isolated executor.\n * - Args-aware classification (shell `rm -rf` vs shell `ls`).\n * - Per-session policy override so a \"draft a quick email\"\n * mission can opt into 'permissive' while a \"review and merge\n * this PR\" mission stays on 'paranoid'.\n */\n\nimport { getToolContract, type RiskLevel } from './toolContract.js';\nimport { loadConfig } from '../config/config.js';\nimport logger from '../utils/logger.js';\n\nconst COMPONENT = 'autoMode';\n\n/* ────────────────────────── Types ────────────────────────── */\n\nexport type AutoModeDecision = 'auto' | 'notify' | 'gate';\nexport type AutoModePolicy = 'standard' | 'paranoid' | 'permissive' | 'yolo';\n\nexport interface ClassificationResult {\n /** What the runner should do with the call. */\n decision: AutoModeDecision;\n /** Plain-english reason — logged and surfaced in the trajectory. */\n reason: string;\n /** Policy that produced this decision (drives observability). */\n policy: AutoModePolicy;\n /** Risk level from the contract, if any. Undefined for unknown tools. */\n riskLevel?: RiskLevel;\n}\n\n/* ────────────────────────── Policy loader ────────────────────────── */\n\n/**\n * Resolve the current auto-mode policy. Reads\n * `config.security.autoMode.policy` if present; defaults to 'standard'.\n * Pure synchronous lookup — no IO, safe to call per-tool-call.\n */\nexport function getAutoModePolicy(): AutoModePolicy {\n // beta.21 — env override. Lets the test suite (and any embedder\n // that wants a process-wide policy without touching config files)\n // short-circuit the classifier without mutating loaded config.\n // Production callers should configure via `config.security.autoMode.policy`\n // — this env hook is opt-in and silent when unset.\n const envPolicy = process.env.TITAN_AUTOMODE_POLICY;\n if (envPolicy === 'paranoid' || envPolicy === 'permissive' || envPolicy === 'yolo' || envPolicy === 'standard') {\n return envPolicy;\n }\n try {\n const cfg = loadConfig();\n const sec = (cfg as Record<string, unknown>).security as Record<string, unknown> | undefined;\n const am = sec?.autoMode as Record<string, unknown> | undefined;\n const policy = am?.policy as string | undefined;\n if (policy === 'paranoid' || policy === 'permissive' || policy === 'yolo' || policy === 'standard') {\n return policy;\n }\n } catch { /* config unavailable — fall through */ }\n return 'standard';\n}\n\n/**\n * Inherently high-impact operations that stay gated even without a declared\n * contract — arbitrary command execution, destructive deletes, deploys, and\n * irreversible external sends/payments. Everything else uncontracted runs with\n * a notify (see classifyToolCall). Curated conservatively; a tool that should\n * gate but is missing here can still be added to the user approval list.\n */\nconst NAME_GATED_EXACT = new Set<string>([\n 'shell', 'run_shell', 'bash', 'run_command', 'execute_command', 'exec',\n 'delete_file', 'bulk_delete_labels', 'phone_call', 'make_call',\n]);\nconst NAME_GATED_PATTERN = /(^|_)(delete|destroy|wipe|purge|deploy|publish|transfer|payment|purchase|wire|send_email|email_send)(_|$)/i;\n\nexport function nameLooksHighImpact(toolName: string): boolean {\n return NAME_GATED_EXACT.has(toolName) || NAME_GATED_PATTERN.test(toolName);\n}\n\n/* ────────────────────────── Classifier ────────────────────────── */\n\n/**\n * Decide whether a tool call should run automatically, with a\n * notification, or with explicit approval. The runner uses this to\n * decide whether to short-circuit the existing approval-gate path.\n *\n * Pure: no IO beyond reading the config + contract registry. Cheap\n * enough to call on every tool call without measuring.\n */\nexport function classifyToolCall(toolName: string): ClassificationResult {\n const policy = getAutoModePolicy();\n const contract = getToolContract(toolName);\n const riskLevel = contract?.riskLevel;\n\n // yolo short-circuit: regardless of risk, run. ONLY for sandboxed\n // eval runs — logs a loud warning the first time per process.\n if (policy === 'yolo') {\n warnYoloOnce();\n return {\n decision: 'auto',\n reason: 'yolo policy — gating disabled',\n policy,\n riskLevel,\n };\n }\n\n // paranoid short-circuit: every call gated.\n if (policy === 'paranoid') {\n return {\n decision: 'gate',\n reason: 'paranoid policy — every tool call requires approval',\n policy,\n riskLevel,\n };\n }\n\n // Unknown tool (no registered contract). The long-tail of ~239 skills has\n // no contract, so gating ALL of them walled benign actions (search, read,\n // widget-building, …) behind approval on every call — which broke the\n // \"ask TITAN to build a weather widget\" flow and made the agent feel broken.\n //\n // v7.0 fix: uncontracted tools run with a 'notify' (visible, logged) by\n // default, EXCEPT a curated set of inherently high-impact operations that\n // stay gated by name. Dangerous shell commands + URLs are independently\n // caught by preExecScan (toolRunner), and external-send tools (email/slack/\n // x/publisher) self-gate via the approval_gates skill — so 'notify' here is\n // safe for the benign majority. Strict users can still set policy='paranoid'.\n if (!contract) {\n if (nameLooksHighImpact(toolName)) {\n return {\n decision: 'gate',\n reason: `no contract + high-impact name \"${toolName}\" — gating`,\n policy,\n };\n }\n return {\n decision: 'notify',\n reason: `no contract for \"${toolName}\" — notify (benign long-tail)`,\n policy,\n };\n }\n\n // Standard + permissive paths read riskLevel.\n if (riskLevel === 'safe') {\n return { decision: 'auto', reason: 'contract riskLevel=safe', policy, riskLevel };\n }\n if (riskLevel === 'moderate') {\n if (policy === 'permissive') {\n return { decision: 'auto', reason: 'permissive policy — moderate risk auto-runs', policy, riskLevel };\n }\n return { decision: 'notify', reason: 'contract riskLevel=moderate', policy, riskLevel };\n }\n if (riskLevel === 'high') {\n return { decision: 'gate', reason: 'contract riskLevel=high', policy, riskLevel };\n }\n\n // Defensive fallback for an unknown future riskLevel value.\n return {\n decision: 'gate',\n reason: `unrecognised riskLevel \"${riskLevel}\" — gating defensively`,\n policy,\n riskLevel,\n };\n}\n\n/* ────────────────────────── Helpers ────────────────────────── */\n\nlet _yoloWarned = false;\nfunction warnYoloOnce(): void {\n if (_yoloWarned) return;\n _yoloWarned = true;\n logger.warn(\n COMPONENT,\n 'AUTO_MODE=yolo — every tool call will run without approval. This mode is ONLY intended for sandboxed eval runs. If you see this in production logs, something is misconfigured.',\n );\n}\n\n/** For tests. */\nexport function _resetYoloWarning(): void {\n _yoloWarned = false;\n}\n\n/**\n * Convenience: returns true iff the decision means the call should\n * NOT proceed without explicit human approval. Used by the runner\n * to short-circuit the existing approval-gate path on 'auto' /\n * 'notify' decisions.\n */\nexport function shouldGate(result: ClassificationResult): boolean {\n return result.decision === 'gate';\n}\n\n/**\n * Format the classification as a one-line breadcrumb suitable for\n * the trajectory `note` event. Used by the runner on 'notify'\n * decisions so the trajectory captures what the agent did\n * autonomously vs what required a human prompt.\n */\nexport function formatBreadcrumb(toolName: string, result: ClassificationResult): string {\n return `automode:${result.decision} tool=${toolName} risk=${result.riskLevel ?? 'unknown'} policy=${result.policy} (${result.reason})`;\n}\n"],"mappings":";AAgFA,SAAS,uBAAuC;AAChD,SAAS,kBAAkB;AAC3B,OAAO,YAAY;AAEnB,MAAM,YAAY;AAyBX,SAAS,oBAAoC;AAMhD,QAAM,YAAY,QAAQ,IAAI;AAC9B,MAAI,cAAc,cAAc,cAAc,gBAAgB,cAAc,UAAU,cAAc,YAAY;AAC5G,WAAO;AAAA,EACX;AACA,MAAI;AACA,UAAM,MAAM,WAAW;AACvB,UAAM,MAAO,IAAgC;AAC7C,UAAM,KAAK,KAAK;AAChB,UAAM,SAAS,IAAI;AACnB,QAAI,WAAW,cAAc,WAAW,gBAAgB,WAAW,UAAU,WAAW,YAAY;AAChG,aAAO;AAAA,IACX;AAAA,EACJ,QAAQ;AAAA,EAA0C;AAClD,SAAO;AACX;AASA,MAAM,mBAAmB,oBAAI,IAAY;AAAA,EACrC;AAAA,EAAS;AAAA,EAAa;AAAA,EAAQ;AAAA,EAAe;AAAA,EAAmB;AAAA,EAChE;AAAA,EAAe;AAAA,EAAsB;AAAA,EAAc;AACvD,CAAC;AACD,MAAM,qBAAqB;AAEpB,SAAS,oBAAoB,UAA2B;AAC3D,SAAO,iBAAiB,IAAI,QAAQ,KAAK,mBAAmB,KAAK,QAAQ;AAC7E;AAYO,SAAS,iBAAiB,UAAwC;AACrE,QAAM,SAAS,kBAAkB;AACjC,QAAM,WAAW,gBAAgB,QAAQ;AACzC,QAAM,YAAY,UAAU;AAI5B,MAAI,WAAW,QAAQ;AACnB,iBAAa;AACb,WAAO;AAAA,MACH,UAAU;AAAA,MACV,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,IACJ;AAAA,EACJ;AAGA,MAAI,WAAW,YAAY;AACvB,WAAO;AAAA,MACH,UAAU;AAAA,MACV,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,IACJ;AAAA,EACJ;AAaA,MAAI,CAAC,UAAU;AACX,QAAI,oBAAoB,QAAQ,GAAG;AAC/B,aAAO;AAAA,QACH,UAAU;AAAA,QACV,QAAQ,mCAAmC,QAAQ;AAAA,QACnD;AAAA,MACJ;AAAA,IACJ;AACA,WAAO;AAAA,MACH,UAAU;AAAA,MACV,QAAQ,oBAAoB,QAAQ;AAAA,MACpC;AAAA,IACJ;AAAA,EACJ;AAGA,MAAI,cAAc,QAAQ;AACtB,WAAO,EAAE,UAAU,QAAQ,QAAQ,2BAA2B,QAAQ,UAAU;AAAA,EACpF;AACA,MAAI,cAAc,YAAY;AAC1B,QAAI,WAAW,cAAc;AACzB,aAAO,EAAE,UAAU,QAAQ,QAAQ,oDAA+C,QAAQ,UAAU;AAAA,IACxG;AACA,WAAO,EAAE,UAAU,UAAU,QAAQ,+BAA+B,QAAQ,UAAU;AAAA,EAC1F;AACA,MAAI,cAAc,QAAQ;AACtB,WAAO,EAAE,UAAU,QAAQ,QAAQ,2BAA2B,QAAQ,UAAU;AAAA,EACpF;AAGA,SAAO;AAAA,IACH,UAAU;AAAA,IACV,QAAQ,2BAA2B,SAAS;AAAA,IAC5C;AAAA,IACA;AAAA,EACJ;AACJ;AAIA,IAAI,cAAc;AAClB,SAAS,eAAqB;AAC1B,MAAI,YAAa;AACjB,gBAAc;AACd,SAAO;AAAA,IACH;AAAA,IACA;AAAA,EACJ;AACJ;AAGO,SAAS,oBAA0B;AACtC,gBAAc;AAClB;AAQO,SAAS,WAAW,QAAuC;AAC9D,SAAO,OAAO,aAAa;AAC/B;AAQO,SAAS,iBAAiB,UAAkB,QAAsC;AACrF,SAAO,YAAY,OAAO,QAAQ,SAAS,QAAQ,SAAS,OAAO,aAAa,SAAS,WAAW,OAAO,MAAM,KAAK,OAAO,MAAM;AACvI;","names":[]}
@@ -9,7 +9,7 @@ import { compressContext } from "./contextCompressor.js";
9
9
  const COMPONENT = "Context";
10
10
  function calculateBudget(maxContextTokens, systemPrompt, toolDefinitionsCount) {
11
11
  const systemTokens = estimateTokens(systemPrompt);
12
- const toolTokens = toolDefinitionsCount * 120;
12
+ const toolTokens = toolDefinitionsCount * 250;
13
13
  const reserveForResponse = 2e3;
14
14
  return {
15
15
  maxTokens: maxContextTokens,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/agent/contextManager.ts"],"sourcesContent":["/**\n * TITAN — Smart Context Manager\n * Intelligent context window management that none of the competitors do well.\n *\n * Problems this solves:\n * - Auto-GPT wastes tokens on irrelevant history (high cost)\n * - CrewAI has prompt sprawl across agents (unpredictable cost)\n * - Open Interpreter has no context management at all\n *\n * TITAN's approach:\n * - Automatic summarization of old conversation history\n * - Priority-based context allocation (recent > relevant > old)\n * - Token budget tracking and enforcement\n * - Smart truncation that preserves tool call context\n */\nimport logger from '../utils/logger.js';\nimport type { ChatMessage } from '../providers/base.js';\nimport { estimateTokens } from '../utils/tokens.js';\nexport { estimateTokens };\nimport { flushMemoryBeforeCompaction } from '../memory/graph.js';\nimport { getRagContext } from '../memory/vectors.js';\nimport { getPlugins } from '../plugins/registry.js';\nimport { runAssemble, runCompact } from '../plugins/contextEngine.js';\nimport { compressContext, type StructuredSummary } from './contextCompressor.js';\n\nconst COMPONENT = 'Context';\n\ninterface ContextBudget {\n maxTokens: number;\n systemPromptTokens: number;\n toolDefinitionTokens: number;\n remainingForHistory: number;\n}\n\n\n\n/** Calculate the context budget */\nexport function calculateBudget(\n maxContextTokens: number,\n systemPrompt: string,\n toolDefinitionsCount: number,\n): ContextBudget {\n const systemTokens = estimateTokens(systemPrompt);\n const toolTokens = toolDefinitionsCount * 120; // ~120 tokens per tool definition\n const reserveForResponse = 2000; // Reserve for completion\n\n return {\n maxTokens: maxContextTokens,\n systemPromptTokens: systemTokens,\n toolDefinitionTokens: toolTokens,\n remainingForHistory: Math.max(0, maxContextTokens - systemTokens - toolTokens - reserveForResponse),\n };\n}\n\n/** Summarize a batch of messages into a single summary message */\nexport function summarizeMessages(messages: ChatMessage[]): ChatMessage {\n const userMessages = messages.filter((m) => m.role === 'user').map((m) => m.content).filter(Boolean);\n const assistantMessages = messages.filter((m) => m.role === 'assistant').map((m) => m.content).filter(Boolean);\n const toolMessages = messages.filter((m) => m.role === 'tool').length;\n\n const summary = [\n `[Earlier conversation summary — ${messages.length} messages, ${toolMessages} tool calls]`,\n userMessages.length > 0 ? `User discussed: ${userMessages.slice(-3).map((m) => m.slice(0, 80)).join('; ')}` : '',\n assistantMessages.length > 0 ? `Assistant actions: ${assistantMessages.slice(-2).map((m) => m.slice(0, 80)).join('; ')}` : '',\n ].filter(Boolean).join('\\n');\n\n return { role: 'system', content: summary };\n}\n\n/**\n * Compress verbose tool results to save context window space.\n * Keeps the last 5 tool results at full fidelity, summarizes older ones.\n */\nfunction compressToolResults(messages: ChatMessage[]): ChatMessage[] {\n // Count tool messages from the end to find the cutoff\n let toolCount = 0;\n const toolIndices: number[] = [];\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].role === 'tool') {\n toolCount++;\n toolIndices.push(i);\n }\n }\n\n // If 5 or fewer tool results, nothing to compress\n if (toolCount <= 5) return messages;\n\n // Indices of tool messages to keep at full fidelity (last 5)\n const keepFullSet = new Set(toolIndices.slice(0, 5));\n\n return messages.map((msg, i) => {\n if (msg.role !== 'tool' || keepFullSet.has(i)) return msg;\n const content = msg.content || '';\n if (content.length <= 500) return msg;\n\n // Compress: keep first 150 chars + success/error status\n const isError = content.toLowerCase().includes('error:');\n const summary = `[${msg.name || 'tool'}: ${isError ? 'FAILED' : 'OK'}] ${content.slice(0, 150)}... [${content.length} chars compressed]`;\n return { ...msg, content: summary };\n });\n}\n\n/** Persistent structured summary for iterative context compression */\nlet currentSummary: StructuredSummary | null = null;\n\n/**\n * TITAN pattern: MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES\n * Disables compaction after 3 consecutive failures per session to prevent\n * wasted API calls (This class of bug can waste 250K+ API calls/day).\n */\nlet consecutiveCompactFailures = 0;\nconst MAX_CONSECUTIVE_COMPACT_FAILURES = 3;\n\n/** Reset compact failure counter (call on new session) */\nexport function resetCompactFailures(): void {\n consecutiveCompactFailures = 0;\n}\n\n/** Get the current structured summary (for external access) */\nexport function getStructuredSummary(): StructuredSummary | null {\n return currentSummary;\n}\n\n/** Set the structured summary (e.g., from agent loop state) */\nexport function setStructuredSummary(summary: StructuredSummary | null): void {\n currentSummary = summary;\n}\n\n/**\n * Smart context builder — fits messages within token budget.\n * Uses the 5-phase compression pipeline (Hermes-inspired):\n * 1. Tool output pruning (no LLM call)\n * 2. Head protection (system + first 3 messages)\n * 3. Tail protection (last N messages, 5% of budget)\n * 4. Structured middle summary\n * 5. Iterative summary updates\n */\nexport function buildSmartContext(\n messages: ChatMessage[],\n tokenBudget: number,\n): ChatMessage[] {\n if (messages.length === 0) return [];\n\n // TITAN pattern: skip compaction after consecutive failures\n if (consecutiveCompactFailures >= MAX_CONSECUTIVE_COMPACT_FAILURES) {\n logger.warn(COMPONENT, `Compaction disabled after ${consecutiveCompactFailures} consecutive failures — returning raw messages`);\n return messages;\n }\n\n let result;\n try {\n result = compressContext(messages, tokenBudget, currentSummary);\n consecutiveCompactFailures = 0; // Reset on success\n } catch (err) {\n consecutiveCompactFailures++;\n logger.warn(COMPONENT, `Compaction failed (${consecutiveCompactFailures}/${MAX_CONSECUTIVE_COMPACT_FAILURES}): ${(err as Error).message}`);\n return messages; // Return uncompressed on failure\n }\n\n // Store summary for iterative updates on next compression\n if (result.summary) {\n currentSummary = result.summary;\n }\n\n if (result.savedTokens > 0) {\n logger.debug(COMPONENT, `Smart context: ${messages.length} → ${result.messages.length} messages, saved ~${result.savedTokens} tokens`);\n }\n\n return result.messages;\n}\n\n/**\n * Force context compaction (used by /compact command).\n * Uses the 5-phase pipeline with an aggressive budget to maximize compression.\n */\nexport function forceCompactContext(\n messages: ChatMessage[],\n): { messages: ChatMessage[]; savedTokens: number } {\n if (messages.length <= 4) {\n return { messages, savedTokens: 0 };\n }\n\n // Flush important context to graph memory before discarding (fire-and-forget)\n const toFlush = messages.filter(m => m.role !== 'system');\n flushMemoryBeforeCompaction(toFlush).catch((err) =>\n logger.warn(COMPONENT, `Memory flush before compaction failed: ${(err as Error).message}`),\n );\n\n // Aggressive budget: 4000 tokens forces maximum compression\n const result = compressContext(messages, 4000, currentSummary);\n\n if (result.summary) {\n currentSummary = result.summary;\n }\n\n logger.info(COMPONENT, `Force compacted: ${messages.length} → ${result.messages.length} messages, saved ~${result.savedTokens} tokens`);\n return { messages: result.messages, savedTokens: result.savedTokens };\n}\n\n/** Get context window stats */\nexport function getContextStats(messages: ChatMessage[]): {\n messageCount: number;\n estimatedTokens: number;\n userMessages: number;\n assistantMessages: number;\n toolCalls: number;\n} {\n let tokens = 0;\n let userMsgs = 0;\n let assistantMsgs = 0;\n let toolCalls = 0;\n\n for (const m of messages) {\n tokens += estimateTokens(m.content || '');\n if (m.role === 'user') userMsgs++;\n if (m.role === 'assistant') assistantMsgs++;\n if (m.toolCalls) toolCalls += m.toolCalls.length;\n }\n\n return {\n messageCount: messages.length,\n estimatedTokens: tokens,\n userMessages: userMsgs,\n assistantMessages: assistantMsgs,\n toolCalls,\n };\n}\n\n/**\n * Inject RAG context into messages before the agent turn.\n * Queries the RAG vector store with the latest user message and prepends\n * relevant chunks as a system message.\n */\nexport async function injectRagContext(\n messages: ChatMessage[],\n topK: number = 3,\n): Promise<ChatMessage[]> {\n // Find the last user message\n const lastUserMsg = [...messages].reverse().find(m => m.role === 'user');\n if (!lastUserMsg?.content) return messages;\n\n try {\n const ragContext = await getRagContext(lastUserMsg.content, topK);\n if (!ragContext) return messages;\n\n logger.debug(COMPONENT, `Injecting RAG context (${ragContext.length} chars) for query: \"${lastUserMsg.content.slice(0, 80)}\"`);\n\n const ragMessage: ChatMessage = {\n role: 'system',\n content: `[Relevant knowledge from ingested documents]\\n${ragContext}`,\n };\n\n // Insert RAG context before the last user message\n const result = [...messages];\n const lastUserIndex = result.lastIndexOf(lastUserMsg);\n if (lastUserIndex >= 0) {\n result.splice(lastUserIndex, 0, ragMessage);\n } else {\n result.push(ragMessage);\n }\n return result;\n } catch (e) {\n logger.debug(COMPONENT, `RAG context injection failed: ${(e as Error).message}`);\n return messages;\n }\n}\n\n/**\n * Assemble context with plugin hooks.\n * Runs RAG injection first (built-in), then all registered plugins.\n */\nexport async function assembleContextWithPlugins(\n messages: ChatMessage[],\n userMessage: string,\n ragTopK: number = 3,\n): Promise<ChatMessage[]> {\n // Built-in RAG injection as first step\n let result = await injectRagContext(messages, ragTopK);\n\n // Run registered plugin assemble hooks\n const plugins = getPlugins();\n if (plugins.length > 0) {\n result = await runAssemble(plugins, result, userMessage);\n }\n\n return result;\n}\n\n/**\n * Compact context with plugin hooks.\n * Runs built-in smart context first, then all registered plugins.\n */\nexport async function compactContextWithPlugins(\n messages: ChatMessage[],\n maxTokens: number,\n): Promise<ChatMessage[]> {\n // Built-in smart context compaction\n let result = buildSmartContext(messages, maxTokens);\n\n // Run registered plugin compact hooks\n const plugins = getPlugins();\n if (plugins.length > 0) {\n result = await runCompact(plugins, result, maxTokens);\n }\n\n return result;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/agent/contextManager.ts"],"sourcesContent":["/**\n * TITAN — Smart Context Manager\n * Intelligent context window management that none of the competitors do well.\n *\n * Problems this solves:\n * - Auto-GPT wastes tokens on irrelevant history (high cost)\n * - CrewAI has prompt sprawl across agents (unpredictable cost)\n * - Open Interpreter has no context management at all\n *\n * TITAN's approach:\n * - Automatic summarization of old conversation history\n * - Priority-based context allocation (recent > relevant > old)\n * - Token budget tracking and enforcement\n * - Smart truncation that preserves tool call context\n */\nimport logger from '../utils/logger.js';\nimport type { ChatMessage } from '../providers/base.js';\nimport { estimateTokens } from '../utils/tokens.js';\nexport { estimateTokens };\nimport { flushMemoryBeforeCompaction } from '../memory/graph.js';\nimport { getRagContext } from '../memory/vectors.js';\nimport { getPlugins } from '../plugins/registry.js';\nimport { runAssemble, runCompact } from '../plugins/contextEngine.js';\nimport { compressContext, type StructuredSummary } from './contextCompressor.js';\n\nconst COMPONENT = 'Context';\n\ninterface ContextBudget {\n maxTokens: number;\n systemPromptTokens: number;\n toolDefinitionTokens: number;\n remainingForHistory: number;\n}\n\n\n\n/** Calculate the context budget */\nexport function calculateBudget(\n maxContextTokens: number,\n systemPrompt: string,\n toolDefinitionsCount: number,\n): ContextBudget {\n const systemTokens = estimateTokens(systemPrompt);\n const toolTokens = toolDefinitionsCount * 250; // measured avg 887 chars (~250 tok) per definition — 120 undercounted 4x and blew small contexts\n const reserveForResponse = 2000; // Reserve for completion\n\n return {\n maxTokens: maxContextTokens,\n systemPromptTokens: systemTokens,\n toolDefinitionTokens: toolTokens,\n remainingForHistory: Math.max(0, maxContextTokens - systemTokens - toolTokens - reserveForResponse),\n };\n}\n\n/** Summarize a batch of messages into a single summary message */\nexport function summarizeMessages(messages: ChatMessage[]): ChatMessage {\n const userMessages = messages.filter((m) => m.role === 'user').map((m) => m.content).filter(Boolean);\n const assistantMessages = messages.filter((m) => m.role === 'assistant').map((m) => m.content).filter(Boolean);\n const toolMessages = messages.filter((m) => m.role === 'tool').length;\n\n const summary = [\n `[Earlier conversation summary — ${messages.length} messages, ${toolMessages} tool calls]`,\n userMessages.length > 0 ? `User discussed: ${userMessages.slice(-3).map((m) => m.slice(0, 80)).join('; ')}` : '',\n assistantMessages.length > 0 ? `Assistant actions: ${assistantMessages.slice(-2).map((m) => m.slice(0, 80)).join('; ')}` : '',\n ].filter(Boolean).join('\\n');\n\n return { role: 'system', content: summary };\n}\n\n/**\n * Compress verbose tool results to save context window space.\n * Keeps the last 5 tool results at full fidelity, summarizes older ones.\n */\nfunction compressToolResults(messages: ChatMessage[]): ChatMessage[] {\n // Count tool messages from the end to find the cutoff\n let toolCount = 0;\n const toolIndices: number[] = [];\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].role === 'tool') {\n toolCount++;\n toolIndices.push(i);\n }\n }\n\n // If 5 or fewer tool results, nothing to compress\n if (toolCount <= 5) return messages;\n\n // Indices of tool messages to keep at full fidelity (last 5)\n const keepFullSet = new Set(toolIndices.slice(0, 5));\n\n return messages.map((msg, i) => {\n if (msg.role !== 'tool' || keepFullSet.has(i)) return msg;\n const content = msg.content || '';\n if (content.length <= 500) return msg;\n\n // Compress: keep first 150 chars + success/error status\n const isError = content.toLowerCase().includes('error:');\n const summary = `[${msg.name || 'tool'}: ${isError ? 'FAILED' : 'OK'}] ${content.slice(0, 150)}... [${content.length} chars compressed]`;\n return { ...msg, content: summary };\n });\n}\n\n/** Persistent structured summary for iterative context compression */\nlet currentSummary: StructuredSummary | null = null;\n\n/**\n * TITAN pattern: MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES\n * Disables compaction after 3 consecutive failures per session to prevent\n * wasted API calls (This class of bug can waste 250K+ API calls/day).\n */\nlet consecutiveCompactFailures = 0;\nconst MAX_CONSECUTIVE_COMPACT_FAILURES = 3;\n\n/** Reset compact failure counter (call on new session) */\nexport function resetCompactFailures(): void {\n consecutiveCompactFailures = 0;\n}\n\n/** Get the current structured summary (for external access) */\nexport function getStructuredSummary(): StructuredSummary | null {\n return currentSummary;\n}\n\n/** Set the structured summary (e.g., from agent loop state) */\nexport function setStructuredSummary(summary: StructuredSummary | null): void {\n currentSummary = summary;\n}\n\n/**\n * Smart context builder — fits messages within token budget.\n * Uses the 5-phase compression pipeline (Hermes-inspired):\n * 1. Tool output pruning (no LLM call)\n * 2. Head protection (system + first 3 messages)\n * 3. Tail protection (last N messages, 5% of budget)\n * 4. Structured middle summary\n * 5. Iterative summary updates\n */\nexport function buildSmartContext(\n messages: ChatMessage[],\n tokenBudget: number,\n): ChatMessage[] {\n if (messages.length === 0) return [];\n\n // TITAN pattern: skip compaction after consecutive failures\n if (consecutiveCompactFailures >= MAX_CONSECUTIVE_COMPACT_FAILURES) {\n logger.warn(COMPONENT, `Compaction disabled after ${consecutiveCompactFailures} consecutive failures — returning raw messages`);\n return messages;\n }\n\n let result;\n try {\n result = compressContext(messages, tokenBudget, currentSummary);\n consecutiveCompactFailures = 0; // Reset on success\n } catch (err) {\n consecutiveCompactFailures++;\n logger.warn(COMPONENT, `Compaction failed (${consecutiveCompactFailures}/${MAX_CONSECUTIVE_COMPACT_FAILURES}): ${(err as Error).message}`);\n return messages; // Return uncompressed on failure\n }\n\n // Store summary for iterative updates on next compression\n if (result.summary) {\n currentSummary = result.summary;\n }\n\n if (result.savedTokens > 0) {\n logger.debug(COMPONENT, `Smart context: ${messages.length} → ${result.messages.length} messages, saved ~${result.savedTokens} tokens`);\n }\n\n return result.messages;\n}\n\n/**\n * Force context compaction (used by /compact command).\n * Uses the 5-phase pipeline with an aggressive budget to maximize compression.\n */\nexport function forceCompactContext(\n messages: ChatMessage[],\n): { messages: ChatMessage[]; savedTokens: number } {\n if (messages.length <= 4) {\n return { messages, savedTokens: 0 };\n }\n\n // Flush important context to graph memory before discarding (fire-and-forget)\n const toFlush = messages.filter(m => m.role !== 'system');\n flushMemoryBeforeCompaction(toFlush).catch((err) =>\n logger.warn(COMPONENT, `Memory flush before compaction failed: ${(err as Error).message}`),\n );\n\n // Aggressive budget: 4000 tokens forces maximum compression\n const result = compressContext(messages, 4000, currentSummary);\n\n if (result.summary) {\n currentSummary = result.summary;\n }\n\n logger.info(COMPONENT, `Force compacted: ${messages.length} → ${result.messages.length} messages, saved ~${result.savedTokens} tokens`);\n return { messages: result.messages, savedTokens: result.savedTokens };\n}\n\n/** Get context window stats */\nexport function getContextStats(messages: ChatMessage[]): {\n messageCount: number;\n estimatedTokens: number;\n userMessages: number;\n assistantMessages: number;\n toolCalls: number;\n} {\n let tokens = 0;\n let userMsgs = 0;\n let assistantMsgs = 0;\n let toolCalls = 0;\n\n for (const m of messages) {\n tokens += estimateTokens(m.content || '');\n if (m.role === 'user') userMsgs++;\n if (m.role === 'assistant') assistantMsgs++;\n if (m.toolCalls) toolCalls += m.toolCalls.length;\n }\n\n return {\n messageCount: messages.length,\n estimatedTokens: tokens,\n userMessages: userMsgs,\n assistantMessages: assistantMsgs,\n toolCalls,\n };\n}\n\n/**\n * Inject RAG context into messages before the agent turn.\n * Queries the RAG vector store with the latest user message and prepends\n * relevant chunks as a system message.\n */\nexport async function injectRagContext(\n messages: ChatMessage[],\n topK: number = 3,\n): Promise<ChatMessage[]> {\n // Find the last user message\n const lastUserMsg = [...messages].reverse().find(m => m.role === 'user');\n if (!lastUserMsg?.content) return messages;\n\n try {\n const ragContext = await getRagContext(lastUserMsg.content, topK);\n if (!ragContext) return messages;\n\n logger.debug(COMPONENT, `Injecting RAG context (${ragContext.length} chars) for query: \"${lastUserMsg.content.slice(0, 80)}\"`);\n\n const ragMessage: ChatMessage = {\n role: 'system',\n content: `[Relevant knowledge from ingested documents]\\n${ragContext}`,\n };\n\n // Insert RAG context before the last user message\n const result = [...messages];\n const lastUserIndex = result.lastIndexOf(lastUserMsg);\n if (lastUserIndex >= 0) {\n result.splice(lastUserIndex, 0, ragMessage);\n } else {\n result.push(ragMessage);\n }\n return result;\n } catch (e) {\n logger.debug(COMPONENT, `RAG context injection failed: ${(e as Error).message}`);\n return messages;\n }\n}\n\n/**\n * Assemble context with plugin hooks.\n * Runs RAG injection first (built-in), then all registered plugins.\n */\nexport async function assembleContextWithPlugins(\n messages: ChatMessage[],\n userMessage: string,\n ragTopK: number = 3,\n): Promise<ChatMessage[]> {\n // Built-in RAG injection as first step\n let result = await injectRagContext(messages, ragTopK);\n\n // Run registered plugin assemble hooks\n const plugins = getPlugins();\n if (plugins.length > 0) {\n result = await runAssemble(plugins, result, userMessage);\n }\n\n return result;\n}\n\n/**\n * Compact context with plugin hooks.\n * Runs built-in smart context first, then all registered plugins.\n */\nexport async function compactContextWithPlugins(\n messages: ChatMessage[],\n maxTokens: number,\n): Promise<ChatMessage[]> {\n // Built-in smart context compaction\n let result = buildSmartContext(messages, maxTokens);\n\n // Run registered plugin compact hooks\n const plugins = getPlugins();\n if (plugins.length > 0) {\n result = await runCompact(plugins, result, maxTokens);\n }\n\n return result;\n}\n"],"mappings":"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","names":[]}
@@ -817,6 +817,7 @@ ${spawn.artifacts.map((a) => ` - [${a.type}] ${a.ref}${a.description ? ` \u2014
817
817
  state.phase = "iterating";
818
818
  }
819
819
  }
820
+ const __internal_tickVerifying = tickVerifying;
820
821
  async function tickReporting(goal, state) {
821
822
  const durationMs = Date.now() - new Date(state.startedAt).getTime();
822
823
  const specialistsUsed = [...new Set(
@@ -1366,6 +1367,7 @@ function _resetDriverStateForTests(goalId) {
1366
1367
  }
1367
1368
  export {
1368
1369
  SAME_BLOCK_TWICE_WINDOW_MS,
1370
+ __internal_tickVerifying,
1369
1371
  _resetDriverStateForTests,
1370
1372
  cancelDriver,
1371
1373
  composeApprovalGuidance,