titan-agent 7.0.0 → 7.2.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 (343) hide show
  1. package/README.md +54 -2
  2. package/dist/agent/agent.js +55 -10
  3. package/dist/agent/agent.js.map +1 -1
  4. package/dist/agent/contextManager.js +1 -1
  5. package/dist/agent/contextManager.js.map +1 -1
  6. package/dist/agent/honestyGuard.js +66 -0
  7. package/dist/agent/honestyGuard.js.map +1 -0
  8. package/dist/agent/selfCritique.js +101 -0
  9. package/dist/agent/selfCritique.js.map +1 -0
  10. package/dist/agent/toolSearch.js +9 -2
  11. package/dist/agent/toolSearch.js.map +1 -1
  12. package/dist/agent/trajectoryLogger.js +19 -2
  13. package/dist/agent/trajectoryLogger.js.map +1 -1
  14. package/dist/analytics/collector.js +1 -1
  15. package/dist/analytics/collector.js.map +1 -1
  16. package/dist/config/schema.js +32 -0
  17. package/dist/config/schema.js.map +1 -1
  18. package/dist/eval/harness.js +4 -1
  19. package/dist/eval/harness.js.map +1 -1
  20. package/dist/gateway/server.js +24 -8
  21. package/dist/gateway/server.js.map +1 -1
  22. package/dist/gateway/slashCommands.js +31 -0
  23. package/dist/gateway/slashCommands.js.map +1 -1
  24. package/dist/mcp/agentTools.js +135 -0
  25. package/dist/mcp/agentTools.js.map +1 -0
  26. package/dist/mcp/server.js +19 -2
  27. package/dist/mcp/server.js.map +1 -1
  28. package/dist/memory/graph.js +2 -0
  29. package/dist/memory/graph.js.map +1 -1
  30. package/dist/providers/errorTaxonomy.js +4 -0
  31. package/dist/providers/errorTaxonomy.js.map +1 -1
  32. package/dist/providers/moa.js +151 -0
  33. package/dist/providers/moa.js.map +1 -0
  34. package/dist/providers/modelCapabilities.js +65 -2
  35. package/dist/providers/modelCapabilities.js.map +1 -1
  36. package/dist/providers/ollama.js +1 -0
  37. package/dist/providers/ollama.js.map +1 -1
  38. package/dist/providers/openai_compat.js +14 -2
  39. package/dist/providers/openai_compat.js.map +1 -1
  40. package/dist/providers/router.js +3 -1
  41. package/dist/providers/router.js.map +1 -1
  42. package/dist/utils/benchMode.js +8 -0
  43. package/dist/utils/benchMode.js.map +1 -0
  44. package/dist/utils/constants.js +1 -1
  45. package/dist/utils/constants.js.map +1 -1
  46. package/package.json +26 -26
  47. package/ui/dist/assets/AboutYouMemory-57X5SqHQ.js +1 -0
  48. package/ui/dist/assets/AuditPanel-AyB8ciLZ.js +1 -0
  49. package/ui/dist/assets/AutonomyPanel-wmVPr-n3.js +1 -0
  50. package/ui/dist/assets/AutopilotPanel-CbLy4lJP.js +1 -0
  51. package/ui/dist/assets/AutoresearchPanel-DxRO1rBF.js +1 -0
  52. package/ui/dist/assets/BackupPanel-BUh9rQ-3.js +1 -0
  53. package/ui/dist/assets/BrowserPanel-OqKwGrIL.js +1 -0
  54. package/ui/dist/assets/CPActivity-DGfS7EY3.js +1 -0
  55. package/ui/dist/assets/CPAgentDetail-p0Kvzhhb.js +1 -0
  56. package/ui/dist/assets/CPAgents-B6wSSQZM.js +1 -0
  57. package/ui/dist/assets/CPApprovals-CYv9Do0i.js +1 -0
  58. package/ui/dist/assets/CPCosts-Dx6Q71rN.js +1 -0
  59. package/ui/dist/assets/CPDashboard-DA8-tE-l.js +1 -0
  60. package/ui/dist/assets/CPFiles-BJ49tzai.js +1 -0
  61. package/ui/dist/assets/CPGoals-h0dKL5V_.js +1 -0
  62. package/ui/dist/assets/CPInbox-CDvefgNH.js +1 -0
  63. package/ui/dist/assets/CPIssueDetail-CnmLzzDD.js +1 -0
  64. package/ui/dist/assets/CPIssues-DknAIMyl.js +1 -0
  65. package/ui/dist/assets/CPLayout-C2nqgkmY.js +2 -0
  66. package/ui/dist/assets/CPOrg-tDbHFphX.js +1 -0
  67. package/ui/dist/assets/CPRuns-UlrIURqG.js +1 -0
  68. package/ui/dist/assets/CPSocial-B-gHgvEw.js +1 -0
  69. package/ui/dist/assets/CPVoice-CJy938ZF.js +1 -0
  70. package/ui/dist/assets/ChannelsPanel-DLbxg1zO.js +1 -0
  71. package/ui/dist/assets/CheckpointsPanel-BB6TT0aE.js +1 -0
  72. package/ui/dist/assets/CommandPostHub-fIslwU_t.js +2 -0
  73. package/ui/dist/assets/ConfirmDialog-6hcNjmAh.js +9 -0
  74. package/ui/dist/assets/CronPanel-DLpw3Y25.js +1 -0
  75. package/ui/dist/assets/DataTable-KVqtDzvP.js +1 -0
  76. package/ui/dist/assets/DreamPanel-lcMXpbEb.js +5 -0
  77. package/ui/dist/assets/EmptyState-D-Dg8B8r.js +1 -0
  78. package/ui/dist/assets/EvalHarnessPanel-BKzRiiQw.js +2 -0
  79. package/ui/dist/assets/EvalPanel-Dtodacmj.js +1 -0
  80. package/ui/dist/assets/FileViewer-DjcVKkO2.js +60 -0
  81. package/ui/dist/assets/FilesPanel-BI90Pplh.js +1 -0
  82. package/ui/dist/assets/FleetPanel-tr0wjAwr.js +1 -0
  83. package/ui/dist/assets/HomelabPanel-m8vMm5rE.js +1 -0
  84. package/ui/dist/assets/InfraView-3WriJnyE.js +2 -0
  85. package/ui/dist/assets/IntegrationsPanel-BmL70fOw.js +1 -0
  86. package/ui/dist/assets/IntelligenceView-BGVxCKD3.js +2 -0
  87. package/ui/dist/assets/LearningPanel-CrYLQ6eV.js +1 -0
  88. package/ui/dist/assets/LiveStudio-CnW3eZYF.js +2 -0
  89. package/ui/dist/assets/LogsPanel-DbShr4Ic.js +1 -0
  90. package/ui/dist/assets/McpPanel-uMYEsPI4.js +1 -0
  91. package/ui/dist/assets/MemoryGraphPanel-C7-Z8f0v.js +1 -0
  92. package/ui/dist/assets/MemoryTaxonomyPanel-KrxN8U1G.js +1 -0
  93. package/ui/dist/assets/MemoryWikiPanel-DI3q6IHC.js +1 -0
  94. package/ui/dist/assets/MeshPanel-D4-g2tlu.js +1 -0
  95. package/ui/dist/assets/MissionCanvas-D8cjakJe.js +61 -0
  96. package/ui/dist/assets/MissionChat-BvqCUf1E.js +3 -0
  97. package/ui/dist/assets/MissionLibrary-CZoJQ9WD.js +1 -0
  98. package/ui/dist/assets/MissionStart-CXCq-_AD.js +1 -0
  99. package/ui/dist/assets/NvidiaPanel-BfI1K5Pg.js +1 -0
  100. package/ui/dist/assets/OrganismPanel-B7Gm9pP-.js +1 -0
  101. package/ui/dist/assets/OverviewPanel-B9tKWRK2.js +1 -0
  102. package/ui/dist/assets/PageHeader-CH85uoZG.js +1 -0
  103. package/ui/dist/assets/PersonaProfilesPanel-BPi8fl-U.js +3 -0
  104. package/ui/dist/assets/PersonasPanel-Dwr7sycT.js +1 -0
  105. package/ui/dist/assets/PhoneDeskPanel-D7qc6wUI.js +1 -0
  106. package/ui/dist/assets/RecipesPanel-DcqPWRSU.js +1 -0
  107. package/ui/dist/assets/SecurityPanel-Bv_B9Ahf.js +1 -0
  108. package/ui/dist/assets/SelfImprovePanel-Ca4rGwEG.js +1 -0
  109. package/ui/dist/assets/SelfProposalsPanel-DteMSASq.js +1 -0
  110. package/ui/dist/assets/SessionsPanel-BdbbKTbL.js +1 -0
  111. package/ui/dist/assets/SessionsTab-BJipiVJs.js +1 -0
  112. package/ui/dist/assets/SettingsPanel-mV7ykOCc.js +1 -0
  113. package/ui/dist/assets/SettingsView-Bu_wYTT5.js +2 -0
  114. package/ui/dist/assets/SkeletonLoader-9H7QWa9E.js +1 -0
  115. package/ui/dist/assets/SkillsPanel-CHwX2kDR.js +1 -0
  116. package/ui/dist/assets/SomaView-Bpsm4ZW7.js +5 -0
  117. package/ui/dist/assets/SomaView-Dghh9om4.css +1 -0
  118. package/ui/dist/assets/StatCard-wmSgMAM3.js +1 -0
  119. package/ui/dist/assets/TeamsPanel-XJiHxdDX.js +1 -0
  120. package/ui/dist/assets/TelemetryPanel-_pmGVxpO.js +1 -0
  121. package/ui/dist/assets/TitanCanvas-Cb7KG80W.css +1 -0
  122. package/ui/dist/assets/TitanCanvas-CmLy7p2N.js +883 -0
  123. package/ui/dist/assets/ToolsView-PHizHZBx.js +2 -0
  124. package/ui/dist/assets/TraceViewer-CYAzIcfB.js +1 -0
  125. package/ui/dist/assets/TracesPanel-CRSN_dzK.js +1 -0
  126. package/ui/dist/assets/TrainingPanel-B9rcuMsV.js +1 -0
  127. package/ui/dist/assets/VoiceOverlay-BL_ns1ZA.js +7 -0
  128. package/ui/dist/assets/VramPanel-BNPQ06_9.js +1 -0
  129. package/ui/dist/assets/WatchView-BgAkNnur.js +13 -0
  130. package/ui/dist/assets/WorkTab-RRpPpEOg.js +1 -0
  131. package/ui/dist/assets/WorkflowBuilderPanel-BPHIH8pf.js +1 -0
  132. package/ui/dist/assets/WorkflowsPanel-DqtmT0NB.js +1 -0
  133. package/ui/dist/assets/approvalHeadline-BRg3ReTi.js +1 -0
  134. package/ui/dist/assets/archive-DcK9HrbE.js +1 -0
  135. package/ui/dist/assets/arrow-left-4c2FnES1.js +1 -0
  136. package/ui/dist/assets/book-open-Ds_yciQm.js +1 -0
  137. package/ui/dist/assets/bot-CWDCc265.js +1 -0
  138. package/ui/dist/assets/chart-column-hhZMdCgB.js +1 -0
  139. package/ui/dist/assets/chevron-right-A_pvnRh_.js +1 -0
  140. package/ui/dist/assets/circle-check-big-C-JUM7wb.js +1 -0
  141. package/ui/dist/assets/circle-stop-yZuG9ZAE.js +1 -0
  142. package/ui/dist/assets/clipboard-list-C2HUEjZc.js +1 -0
  143. package/ui/dist/assets/clock-DSPgndSD.js +1 -0
  144. package/ui/dist/assets/clsx-CjueKrWZ.js +1 -0
  145. package/ui/dist/assets/createLucideIcon-qnlrxww7.js +1 -0
  146. package/ui/dist/assets/database-C1SgHa8T.js +1 -0
  147. package/ui/dist/assets/dollar-sign-D9siqK91.js +1 -0
  148. package/ui/dist/assets/download-CJZWQNfV.js +1 -0
  149. package/ui/dist/assets/external-link-CpQLWKKE.js +1 -0
  150. package/ui/dist/assets/file-text-BbGTi-Po.js +1 -0
  151. package/ui/dist/assets/flask-conical-B1YVft4E.js +1 -0
  152. package/ui/dist/assets/folder-EbR-w2Mq.js +1 -0
  153. package/ui/dist/assets/funnel-D2Dkn8Pf.js +1 -0
  154. package/ui/dist/assets/git-branch-CQ2yNSzU.js +1 -0
  155. package/ui/dist/assets/git-pull-request-BxL5wlGX.js +1 -0
  156. package/ui/dist/assets/index-Cz8190xO.css +2 -0
  157. package/ui/dist/assets/index-WI-E4I3h.js +243 -0
  158. package/ui/dist/assets/jsx-runtime-B15e6lOy.js +1 -0
  159. package/ui/dist/assets/layers-BPu5SRjI.js +1 -0
  160. package/ui/dist/assets/legacy-BIzifT-t.js +3 -0
  161. package/ui/dist/assets/lightbulb-BY7CpMte.js +1 -0
  162. package/ui/dist/assets/link-VDQkrGJw.js +1 -0
  163. package/ui/dist/assets/list-todo-DfnNUV_T.js +1 -0
  164. package/ui/dist/assets/message-square-BpzrINHz.js +1 -0
  165. package/ui/dist/assets/mic-De6oZFaV.js +1 -0
  166. package/ui/dist/assets/missions-y-qg_f9b.js +1 -0
  167. package/ui/dist/assets/network-CM7y1ats.js +1 -0
  168. package/ui/dist/assets/pause-C4TDJSfA.js +1 -0
  169. package/ui/dist/assets/pencil-Dd_vzHE-.js +1 -0
  170. package/ui/dist/assets/play-9WxZWVHA.js +1 -0
  171. package/ui/dist/assets/plug-Dm25Wbrc.js +1 -0
  172. package/ui/dist/assets/plus-CHryCIkk.js +1 -0
  173. package/ui/dist/assets/radio-D-XnoAVu.js +1 -0
  174. package/ui/dist/assets/refresh-cw-Disd5wRB.js +1 -0
  175. package/ui/dist/assets/rotate-ccw-Cw1T2W1T.js +1 -0
  176. package/ui/dist/assets/save-DP7oNar2.js +1 -0
  177. package/ui/dist/assets/search-aNVcX-nv.js +1 -0
  178. package/ui/dist/assets/send-D7iQD57b.js +1 -0
  179. package/ui/dist/assets/server-DFfeYjoM.js +1 -0
  180. package/ui/dist/assets/settings-5NWXzgyY.js +1 -0
  181. package/ui/dist/assets/shared-DLz_Jtg3.js +1 -0
  182. package/ui/dist/assets/shield-check-Cd50jCAn.js +1 -0
  183. package/ui/dist/assets/square-DlcoJ1ZM.js +1 -0
  184. package/ui/dist/assets/terminal-DgFz2Vsf.js +1 -0
  185. package/ui/dist/assets/test-tube-BimtS92_.js +1 -0
  186. package/ui/dist/assets/toggle-right-BMaR-sfT.js +1 -0
  187. package/ui/dist/assets/trash-2-CwUv7ww1.js +1 -0
  188. package/ui/dist/assets/trending-up-Ba9TwEow.js +1 -0
  189. package/ui/dist/assets/trophy-Gfv1QC45.js +1 -0
  190. package/ui/dist/assets/volume-2-BVlfVl2U.js +1 -0
  191. package/ui/dist/assets/wifi-off-CWLeusSV.js +1 -0
  192. package/ui/dist/assets/zoom-out-DeggJ7RM.js +1 -0
  193. package/ui/dist/index.html +4 -2
  194. package/ui/dist/sw.js +1 -1
  195. package/ui/dist/assets/AboutYouMemory-CZKEOd_O.js +0 -11
  196. package/ui/dist/assets/AuditPanel-Bu71N5Er.js +0 -1
  197. package/ui/dist/assets/AutonomyPanel-DB-39dX4.js +0 -11
  198. package/ui/dist/assets/AutopilotPanel-Cj8oKxWv.js +0 -1
  199. package/ui/dist/assets/AutoresearchPanel-3s8pjm6Z.js +0 -6
  200. package/ui/dist/assets/BackupPanel-EUQJMJE7.js +0 -1
  201. package/ui/dist/assets/BrowserPanel-Beo4F5Ar.js +0 -6
  202. package/ui/dist/assets/Button-MdXmb4_n.js +0 -1
  203. package/ui/dist/assets/CPActivity-B1Se9VVc.js +0 -1
  204. package/ui/dist/assets/CPAgentDetail-BYji6tT8.js +0 -1
  205. package/ui/dist/assets/CPAgents-BSUKucTe.js +0 -1
  206. package/ui/dist/assets/CPApprovals-B4v0em6e.js +0 -1
  207. package/ui/dist/assets/CPCosts-9ikh61Kv.js +0 -1
  208. package/ui/dist/assets/CPDashboard-sOok2T5v.js +0 -1
  209. package/ui/dist/assets/CPFiles-DB2nY5JE.js +0 -1
  210. package/ui/dist/assets/CPGoals-8Z1yOY8e.js +0 -1
  211. package/ui/dist/assets/CPInbox-Cq6-UY8F.js +0 -11
  212. package/ui/dist/assets/CPIssueDetail-NAGfmJg8.js +0 -1
  213. package/ui/dist/assets/CPIssues-BzX6Rckx.js +0 -1
  214. package/ui/dist/assets/CPLayout-BcRM6QSg.js +0 -2
  215. package/ui/dist/assets/CPOrg-B7DQ4UQP.js +0 -1
  216. package/ui/dist/assets/CPRuns-D-cpPw_M.js +0 -1
  217. package/ui/dist/assets/CPSocial-DshtmcK0.js +0 -11
  218. package/ui/dist/assets/CPVoice-DfXRnQVU.js +0 -1
  219. package/ui/dist/assets/ChannelsPanel-BnaTOeyf.js +0 -1
  220. package/ui/dist/assets/CheckpointsPanel-C62naE4U.js +0 -1
  221. package/ui/dist/assets/CommandPostHub-B_L1CAss.js +0 -24
  222. package/ui/dist/assets/ConfirmDialog-VErHWAbo.js +0 -1
  223. package/ui/dist/assets/CronPanel-BwMrrZ5d.js +0 -1
  224. package/ui/dist/assets/DataTable-BCqSUuN7.js +0 -1
  225. package/ui/dist/assets/DreamPanel-BNAcCLBB.js +0 -15
  226. package/ui/dist/assets/EmptyState-D9kQf1PX.js +0 -1
  227. package/ui/dist/assets/EvalHarnessPanel-BaMLdBNm.js +0 -2
  228. package/ui/dist/assets/EvalPanel-CW-SSjtg.js +0 -1
  229. package/ui/dist/assets/FileViewer-BL00nsd7.js +0 -61
  230. package/ui/dist/assets/FilesPanel-CeC6YUSd.js +0 -16
  231. package/ui/dist/assets/FleetPanel-EyWF7l3W.js +0 -1
  232. package/ui/dist/assets/HomelabPanel-BRfKRYe7.js +0 -6
  233. package/ui/dist/assets/InfraView-Jmqhg_Yc.js +0 -2
  234. package/ui/dist/assets/InlineEditableField-DgMrLDj1.js +0 -1
  235. package/ui/dist/assets/Input-CBTwa_Iw.js +0 -1
  236. package/ui/dist/assets/IntegrationsPanel-DQL-7Ec6.js +0 -1
  237. package/ui/dist/assets/IntelligenceView-DxD78qfP.js +0 -2
  238. package/ui/dist/assets/LearningPanel-C_JzSbJU.js +0 -1
  239. package/ui/dist/assets/LiveStudio-Db5yeaWo.js +0 -7
  240. package/ui/dist/assets/LogsPanel-CpinKwaZ.js +0 -1
  241. package/ui/dist/assets/McpPanel-D-MqN_f-.js +0 -1
  242. package/ui/dist/assets/MemoryGraphPanel-BnD5jRqf.js +0 -1
  243. package/ui/dist/assets/MemoryTaxonomyPanel-BBI202dd.js +0 -6
  244. package/ui/dist/assets/MemoryWikiPanel-Dn3XZHL0.js +0 -6
  245. package/ui/dist/assets/MeshPanel-C-mRJpr0.js +0 -11
  246. package/ui/dist/assets/MissionCanvas-CbZW83Ch.js +0 -72
  247. package/ui/dist/assets/MissionChat-Bs75jPAD.js +0 -7
  248. package/ui/dist/assets/MissionLibrary-BxQ6SxPe.js +0 -5
  249. package/ui/dist/assets/MissionStart-CBuBPasl.js +0 -1
  250. package/ui/dist/assets/Modal-ybPGvlQs.js +0 -9
  251. package/ui/dist/assets/NvidiaPanel-DdG13OX4.js +0 -1
  252. package/ui/dist/assets/OrganismPanel-xZWUJKyr.js +0 -1
  253. package/ui/dist/assets/OverviewPanel-B45ZYhJV.js +0 -1
  254. package/ui/dist/assets/PageHeader-DdrbS1aq.js +0 -1
  255. package/ui/dist/assets/PersonaProfilesPanel-CKER-EU5.js +0 -8
  256. package/ui/dist/assets/PersonasPanel-CMMQ3nh3.js +0 -1
  257. package/ui/dist/assets/PhoneDeskPanel-Bw_Y-cVE.js +0 -11
  258. package/ui/dist/assets/RecipesPanel-DzMcxpJJ.js +0 -1
  259. package/ui/dist/assets/SecurityPanel-BCq3Fzbr.js +0 -1
  260. package/ui/dist/assets/SelfImprovePanel-YE3hT8jK.js +0 -1
  261. package/ui/dist/assets/SelfProposalsPanel-DXuqBM6p.js +0 -1
  262. package/ui/dist/assets/SessionsPanel-DORz5goR.js +0 -1
  263. package/ui/dist/assets/SessionsTab-qYHDOuC8.js +0 -1
  264. package/ui/dist/assets/SettingsPanel-BbwPu1i7.js +0 -1
  265. package/ui/dist/assets/SettingsView-zgqkDDBJ.js +0 -2
  266. package/ui/dist/assets/SkeletonLoader-r6OGXaU9.js +0 -1
  267. package/ui/dist/assets/SkillsPanel-BjEOBMRo.js +0 -11
  268. package/ui/dist/assets/SomaView-BtCkeWfZ.css +0 -1
  269. package/ui/dist/assets/SomaView-DLzApZVW.js +0 -5
  270. package/ui/dist/assets/StatCard-DLq8aBps.js +0 -1
  271. package/ui/dist/assets/StatusBadge-BqlvIbdj.js +0 -1
  272. package/ui/dist/assets/Tabs-DdUThlp1.js +0 -1
  273. package/ui/dist/assets/TeamsPanel-uIIKoU7I.js +0 -1
  274. package/ui/dist/assets/TelemetryPanel-dVr3yQQr.js +0 -1
  275. package/ui/dist/assets/TitanCanvas-BfitWg9R.css +0 -1
  276. package/ui/dist/assets/TitanCanvas-xHAJqwG2.js +0 -945
  277. package/ui/dist/assets/ToolsView-CG1mZdiy.js +0 -2
  278. package/ui/dist/assets/Tooltip-C2tXJcrN.js +0 -6
  279. package/ui/dist/assets/TraceViewer-BIMD_Osr.js +0 -1
  280. package/ui/dist/assets/TracesPanel-nMUiyMj5.js +0 -1
  281. package/ui/dist/assets/TrainingPanel-CT5R4HWm.js +0 -1
  282. package/ui/dist/assets/VoiceOverlay-Br4QnCtw.js +0 -17
  283. package/ui/dist/assets/VramPanel-CdnJYytg.js +0 -1
  284. package/ui/dist/assets/WatchView-TNU6Ns1Q.js +0 -13
  285. package/ui/dist/assets/WorkTab-wTlX_UKP.js +0 -1
  286. package/ui/dist/assets/WorkflowBuilderPanel-CDpVt5ux.js +0 -6
  287. package/ui/dist/assets/WorkflowsPanel-zsFqsLdn.js +0 -11
  288. package/ui/dist/assets/approvalHeadline-DB9SgR-9.js +0 -1
  289. package/ui/dist/assets/archive-Bh689DNg.js +0 -6
  290. package/ui/dist/assets/arrow-left-WkVYLm80.js +0 -6
  291. package/ui/dist/assets/book-open-ohEXgUsS.js +0 -6
  292. package/ui/dist/assets/bot-DvEcyQcD.js +0 -6
  293. package/ui/dist/assets/chart-column-w3goFd5f.js +0 -6
  294. package/ui/dist/assets/check-CuRYh4Zh.js +0 -6
  295. package/ui/dist/assets/chevron-right-DbLSHmff.js +0 -6
  296. package/ui/dist/assets/circle-check-big-Bkba568b.js +0 -6
  297. package/ui/dist/assets/circle-stop-Bx2ohEg8.js +0 -6
  298. package/ui/dist/assets/clipboard-list-Dj9tORnu.js +0 -6
  299. package/ui/dist/assets/clock-JyQAYy6X.js +0 -6
  300. package/ui/dist/assets/clsx-B-dksMZM.js +0 -1
  301. package/ui/dist/assets/dollar-sign-XxwPAA2a.js +0 -6
  302. package/ui/dist/assets/download-D1izVEOL.js +0 -6
  303. package/ui/dist/assets/external-link-DZ_rZsIt.js +0 -6
  304. package/ui/dist/assets/file-text-Cfawu8Bs.js +0 -6
  305. package/ui/dist/assets/flask-conical-Ql8QxhgY.js +0 -6
  306. package/ui/dist/assets/folder-DAdIw-Pb.js +0 -6
  307. package/ui/dist/assets/funnel-FycfZcXo.js +0 -6
  308. package/ui/dist/assets/git-branch-C2qrhGGu.js +0 -6
  309. package/ui/dist/assets/index-Cml2x9pA.js +0 -507
  310. package/ui/dist/assets/index-yWybhcfI.css +0 -1
  311. package/ui/dist/assets/layers-yzjtGlHB.js +0 -6
  312. package/ui/dist/assets/legacy-D21WSMF1.js +0 -3
  313. package/ui/dist/assets/lightbulb-BZJNK69S.js +0 -6
  314. package/ui/dist/assets/link-CnFkBkaY.js +0 -6
  315. package/ui/dist/assets/list-todo-BlgfQHup.js +0 -6
  316. package/ui/dist/assets/message-square-CRsG9u6_.js +0 -6
  317. package/ui/dist/assets/mic-B32RHc7Y.js +0 -6
  318. package/ui/dist/assets/missions-1iw8Z2_0.js +0 -1
  319. package/ui/dist/assets/network-C9RXQGrV.js +0 -6
  320. package/ui/dist/assets/pause-BT1Bc2q3.js +0 -6
  321. package/ui/dist/assets/pencil-BK5IU6o0.js +0 -6
  322. package/ui/dist/assets/play-Cl1nC_gc.js +0 -6
  323. package/ui/dist/assets/plug-DvcpOalj.js +0 -6
  324. package/ui/dist/assets/plus-Dpo1qfrl.js +0 -6
  325. package/ui/dist/assets/radio-C5c9IyqX.js +0 -6
  326. package/ui/dist/assets/refresh-cw-C-iZkzuS.js +0 -6
  327. package/ui/dist/assets/rotate-ccw-qzrB3SNw.js +0 -6
  328. package/ui/dist/assets/save-DwR9wQVu.js +0 -6
  329. package/ui/dist/assets/search-D10l0m3-.js +0 -6
  330. package/ui/dist/assets/send-DtXGsaFW.js +0 -6
  331. package/ui/dist/assets/server-BzisF3LL.js +0 -6
  332. package/ui/dist/assets/settings-Dbwd1_-c.js +0 -6
  333. package/ui/dist/assets/shield-check-CXlDJyAW.js +0 -6
  334. package/ui/dist/assets/square-BBC-JKzY.js +0 -11
  335. package/ui/dist/assets/terminal-DaBIlWEM.js +0 -6
  336. package/ui/dist/assets/test-tube-CDATRD5t.js +0 -11
  337. package/ui/dist/assets/toggle-right-DTmrC5RD.js +0 -11
  338. package/ui/dist/assets/trash-2-CTeyjxD_.js +0 -6
  339. package/ui/dist/assets/trending-up-CXPRjRV4.js +0 -6
  340. package/ui/dist/assets/trophy-DbVdXRtU.js +0 -6
  341. package/ui/dist/assets/volume-2-DYDBmm3M.js +0 -6
  342. package/ui/dist/assets/wifi-off-BBuIGbiP.js +0 -6
  343. package/ui/dist/assets/zoom-out-D47_pRAO.js +0 -16
@@ -0,0 +1,151 @@
1
+ #!/usr/bin/env node
2
+ import { LLMProvider } from "./base.js";
3
+ import { loadConfig } from "../config/config.js";
4
+ import logger from "../utils/logger.js";
5
+ const COMPONENT = "MoA";
6
+ const DEFAULT_REFERENCE_TIMEOUT_MS = 45e3;
7
+ const DEFAULT_REFERENCE_MAX_TOKENS = 1024;
8
+ const TOOL_RESULT_TRIM = 4e3;
9
+ const ADVISOR_SYSTEM_PROMPT = [
10
+ "You are a reference advisor inside a Mixture-of-Agents process. You are NOT the acting agent:",
11
+ "you cannot call tools, and the user never sees your words. Another model (the aggregator) acts",
12
+ "and answers \u2014 your output is private guidance handed to it. Give concise, concrete advice:",
13
+ "the likely best next steps, tool-use strategy, risks, and anything the aggregator might miss.",
14
+ "If the conversation references tools or systems you cannot access, advise from reasoning alone \u2014",
15
+ "never refuse for lack of access."
16
+ ].join(" ");
17
+ function trimForReference(messages) {
18
+ const out = [{ role: "system", content: ADVISOR_SYSTEM_PROMPT }];
19
+ for (const m of messages) {
20
+ if (m.role === "system") continue;
21
+ if (m.role === "tool") {
22
+ const body = (m.content || "").slice(0, TOOL_RESULT_TRIM);
23
+ out.push({ role: "user", content: `[Tool result]
24
+ ${body}` });
25
+ continue;
26
+ }
27
+ if (m.role === "assistant" && m.toolCalls?.length) {
28
+ const calls = m.toolCalls.map((tc) => `${tc.function.name}(${(tc.function.arguments || "").slice(0, 300)})`).join("; ");
29
+ out.push({ role: "assistant", content: `${m.content || ""}
30
+ [Called tools: ${calls}]`.trim() });
31
+ continue;
32
+ }
33
+ out.push({ role: m.role, content: m.content });
34
+ }
35
+ return out;
36
+ }
37
+ function buildGuidanceBlock(results) {
38
+ const blocks = results.map((r, i) => {
39
+ if (r.content) return `Reference ${i + 1} \u2014 ${r.model}:
40
+ ${r.content}`;
41
+ return `Reference ${i + 1} \u2014 ${r.model}: (unavailable: ${r.error || "no response"})`;
42
+ });
43
+ return [
44
+ "[Mixture of Agents context \u2014 private guidance from reference advisors. The user cannot see this.",
45
+ "Weigh it critically; you are the acting agent and the only voice.]",
46
+ "",
47
+ ...blocks
48
+ ].join("\n");
49
+ }
50
+ function getMoaPresets() {
51
+ try {
52
+ const cfg = loadConfig();
53
+ return cfg.moa?.presets || {};
54
+ } catch {
55
+ return {};
56
+ }
57
+ }
58
+ class MoaProvider extends LLMProvider {
59
+ name = "moa";
60
+ displayName = "Mixture of Agents";
61
+ async healthCheck() {
62
+ return Object.keys(getMoaPresets()).length > 0;
63
+ }
64
+ async listModels() {
65
+ return Object.keys(getMoaPresets()).map((p) => `moa/${p}`);
66
+ }
67
+ resolvePreset(model) {
68
+ const presets = getMoaPresets();
69
+ const name = (model || "").replace(/^moa\//, "") || "default";
70
+ const preset = presets[name];
71
+ if (!preset) throw new Error(`MoA preset "${name}" not found. Configure moa.presets.${name} in titan.json`);
72
+ if (preset.references.some((r) => r.model.startsWith("moa/"))) {
73
+ throw new Error("MoA presets cannot reference other MoA presets (recursion blocked)");
74
+ }
75
+ if (preset.aggregator.startsWith("moa/")) {
76
+ throw new Error("MoA aggregator cannot itself be a MoA preset (recursion blocked)");
77
+ }
78
+ return { name, preset };
79
+ }
80
+ /** Fan out to advisors; never throws — failures become guidance footnotes. */
81
+ async gatherGuidance(preset, messages, signal) {
82
+ const { chat } = await import("./router.js");
83
+ const trimmed = trimForReference(messages);
84
+ const tasks = preset.references.map(async (ref) => {
85
+ const started = Date.now();
86
+ const timeoutMs = ref.timeoutMs ?? DEFAULT_REFERENCE_TIMEOUT_MS;
87
+ const controller = new AbortController();
88
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
89
+ const onOuter = () => controller.abort();
90
+ signal?.addEventListener("abort", onOuter, { once: true });
91
+ try {
92
+ const res = await chat({
93
+ model: ref.model,
94
+ messages: trimmed,
95
+ maxTokens: ref.maxTokens ?? DEFAULT_REFERENCE_MAX_TOKENS,
96
+ temperature: ref.temperature,
97
+ signal: controller.signal,
98
+ noFallback: true
99
+ });
100
+ return { model: ref.model, content: res.content || null, ms: Date.now() - started };
101
+ } catch (e) {
102
+ return { model: ref.model, content: null, error: e.message.slice(0, 160), ms: Date.now() - started };
103
+ } finally {
104
+ clearTimeout(timer);
105
+ signal?.removeEventListener("abort", onOuter);
106
+ }
107
+ });
108
+ return Promise.all(tasks);
109
+ }
110
+ async prepare(options) {
111
+ const { name, preset } = this.resolvePreset(options.model);
112
+ if (preset.enabled === false) {
113
+ return { preset, name, aggregatorOptions: { ...options, model: preset.aggregator } };
114
+ }
115
+ const t0 = Date.now();
116
+ const guidance = await this.gatherGuidance(preset, options.messages, options.signal);
117
+ const ok = guidance.filter((g) => g.content).length;
118
+ logger.info(COMPONENT, `[${name}] ${ok}/${preset.references.length} advisors answered in ${Date.now() - t0}ms (${guidance.map((g) => `${g.model.split("/").pop()}:${g.ms}ms`).join(", ")})`);
119
+ try {
120
+ const { titanEvents } = await import("../agent/daemon.js");
121
+ titanEvents.emit("moa:guidance", { preset: name, advisors: guidance.map((g) => ({ model: g.model, ok: !!g.content, ms: g.ms })) });
122
+ } catch {
123
+ }
124
+ const messages = [
125
+ ...options.messages,
126
+ { role: "user", content: buildGuidanceBlock(guidance) }
127
+ ];
128
+ return {
129
+ preset,
130
+ name,
131
+ aggregatorOptions: { ...options, model: preset.aggregator, messages, maxTokens: preset.maxTokens ?? options.maxTokens }
132
+ };
133
+ }
134
+ async chat(options) {
135
+ const { chat } = await import("./router.js");
136
+ const { aggregatorOptions } = await this.prepare(options);
137
+ return chat(aggregatorOptions);
138
+ }
139
+ async *chatStream(options) {
140
+ const { chatStream } = await import("./router.js");
141
+ const { aggregatorOptions } = await this.prepare(options);
142
+ yield* chatStream(aggregatorOptions);
143
+ }
144
+ }
145
+ export {
146
+ MoaProvider,
147
+ buildGuidanceBlock,
148
+ getMoaPresets,
149
+ trimForReference
150
+ };
151
+ //# sourceMappingURL=moa.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/providers/moa.ts"],"sourcesContent":["/**\n * MoA — Mixture-of-Agents virtual provider (v7.1).\n *\n * A MoA preset = N reference \"advisors\" + 1 aggregator, exposed as a virtual\n * model (`moa/<preset>`) selectable anywhere a model is. On every chat call:\n *\n * 1. Advisors receive a TRIMMED conversation (no TITAN system prompt, no\n * tool schemas, tool results truncated) plus an advisory system prompt —\n * they advise, they never act.\n * 2. Advisors fan out in parallel with per-reference timeouts; a slow or\n * failed advisor is dropped/noted, never awaited into oblivion.\n * 3. Their labeled guidance is appended at the END of the aggregator's\n * prompt (prompt-cache prefix stays stable).\n * 4. The aggregator — the only voice — answers with the FULL tool schema\n * through the normal loop.\n *\n * TITAN's edge over the same feature elsewhere: advisors default to LOCAL\n * models spread across separate machines (a \"local council\"), so the\n * mixture costs nothing and parallelizes across GPUs; and because whole\n * agents can be advisors via MCP, the mixture isn't limited to bare models.\n */\nimport { LLMProvider, type ChatOptions, type ChatResponse, type ChatStreamChunk, type ChatMessage } from './base.js';\nimport { loadConfig } from '../config/config.js';\nimport logger from '../utils/logger.js';\n\nconst COMPONENT = 'MoA';\nconst DEFAULT_REFERENCE_TIMEOUT_MS = 45_000;\nconst DEFAULT_REFERENCE_MAX_TOKENS = 1_024;\nconst TOOL_RESULT_TRIM = 4_000;\n\nexport interface MoaReference {\n /** provider/model id, e.g. \"litellm/glm-4.7-flash\" */\n model: string;\n maxTokens?: number;\n temperature?: number;\n timeoutMs?: number;\n}\n\nexport interface MoaPreset {\n references: MoaReference[];\n /** provider/model id of the acting aggregator */\n aggregator: string;\n enabled?: boolean;\n /** Optional cap for the aggregator's output */\n maxTokens?: number;\n}\n\nconst ADVISOR_SYSTEM_PROMPT = [\n 'You are a reference advisor inside a Mixture-of-Agents process. You are NOT the acting agent:',\n 'you cannot call tools, and the user never sees your words. Another model (the aggregator) acts',\n 'and answers — your output is private guidance handed to it. Give concise, concrete advice:',\n 'the likely best next steps, tool-use strategy, risks, and anything the aggregator might miss.',\n 'If the conversation references tools or systems you cannot access, advise from reasoning alone —',\n 'never refuse for lack of access.',\n].join(' ');\n\n/** Trim the conversation for advisors: no system prompt, no tool schemas,\n * tool transcripts flattened + truncated. Exported for tests. */\nexport function trimForReference(messages: ChatMessage[]): ChatMessage[] {\n const out: ChatMessage[] = [{ role: 'system', content: ADVISOR_SYSTEM_PROMPT }];\n for (const m of messages) {\n if (m.role === 'system') continue; // TITAN's own harness prompt stays private\n if (m.role === 'tool') {\n const body = (m.content || '').slice(0, TOOL_RESULT_TRIM);\n out.push({ role: 'user', content: `[Tool result]\\n${body}` } as ChatMessage);\n continue;\n }\n if (m.role === 'assistant' && m.toolCalls?.length) {\n const calls = m.toolCalls.map(tc => `${tc.function.name}(${(tc.function.arguments || '').slice(0, 300)})`).join('; ');\n out.push({ role: 'assistant', content: `${m.content || ''}\\n[Called tools: ${calls}]`.trim() } as ChatMessage);\n continue;\n }\n out.push({ role: m.role, content: m.content } as ChatMessage);\n }\n return out;\n}\n\n/** Build the guidance block appended to the aggregator's prompt. Exported for tests. */\nexport function buildGuidanceBlock(results: Array<{ model: string; content: string | null; error?: string }>): string {\n const blocks = results.map((r, i) => {\n if (r.content) return `Reference ${i + 1} — ${r.model}:\\n${r.content}`;\n return `Reference ${i + 1} — ${r.model}: (unavailable: ${r.error || 'no response'})`;\n });\n return [\n '[Mixture of Agents context — private guidance from reference advisors. The user cannot see this.',\n 'Weigh it critically; you are the acting agent and the only voice.]',\n '',\n ...blocks,\n ].join('\\n');\n}\n\nexport function getMoaPresets(): Record<string, MoaPreset> {\n try {\n const cfg = loadConfig() as { moa?: { presets?: Record<string, MoaPreset> } };\n return cfg.moa?.presets || {};\n } catch {\n return {};\n }\n}\n\nexport class MoaProvider extends LLMProvider {\n readonly name = 'moa';\n readonly displayName = 'Mixture of Agents';\n\n async healthCheck(): Promise<boolean> {\n return Object.keys(getMoaPresets()).length > 0;\n }\n\n async listModels(): Promise<string[]> {\n return Object.keys(getMoaPresets()).map(p => `moa/${p}`);\n }\n\n private resolvePreset(model?: string): { name: string; preset: MoaPreset } {\n const presets = getMoaPresets();\n const name = (model || '').replace(/^moa\\//, '') || 'default';\n const preset = presets[name];\n if (!preset) throw new Error(`MoA preset \"${name}\" not found. Configure moa.presets.${name} in titan.json`);\n if (preset.references.some(r => r.model.startsWith('moa/'))) {\n throw new Error('MoA presets cannot reference other MoA presets (recursion blocked)');\n }\n if (preset.aggregator.startsWith('moa/')) {\n throw new Error('MoA aggregator cannot itself be a MoA preset (recursion blocked)');\n }\n return { name, preset };\n }\n\n /** Fan out to advisors; never throws — failures become guidance footnotes. */\n private async gatherGuidance(preset: MoaPreset, messages: ChatMessage[], signal?: AbortSignal):\n Promise<Array<{ model: string; content: string | null; error?: string; ms: number }>> {\n const { chat } = await import('./router.js');\n const trimmed = trimForReference(messages);\n const tasks = preset.references.map(async ref => {\n const started = Date.now();\n const timeoutMs = ref.timeoutMs ?? DEFAULT_REFERENCE_TIMEOUT_MS;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n const onOuter = () => controller.abort();\n signal?.addEventListener('abort', onOuter, { once: true });\n try {\n const res = await chat({\n model: ref.model,\n messages: trimmed,\n maxTokens: ref.maxTokens ?? DEFAULT_REFERENCE_MAX_TOKENS,\n temperature: ref.temperature,\n signal: controller.signal,\n noFallback: true,\n } as ChatOptions & { noFallback: boolean });\n return { model: ref.model, content: res.content || null, ms: Date.now() - started };\n } catch (e) {\n return { model: ref.model, content: null, error: (e as Error).message.slice(0, 160), ms: Date.now() - started };\n } finally {\n clearTimeout(timer);\n signal?.removeEventListener('abort', onOuter);\n }\n });\n return Promise.all(tasks);\n }\n\n private async prepare(options: ChatOptions): Promise<{ preset: MoaPreset; name: string; aggregatorOptions: ChatOptions }> {\n const { name, preset } = this.resolvePreset(options.model);\n if (preset.enabled === false) {\n // Preset disabled → aggregator acts alone (Hermes-compatible semantics)\n return { preset, name, aggregatorOptions: { ...options, model: preset.aggregator } };\n }\n const t0 = Date.now();\n const guidance = await this.gatherGuidance(preset, options.messages, options.signal);\n const ok = guidance.filter(g => g.content).length;\n logger.info(COMPONENT, `[${name}] ${ok}/${preset.references.length} advisors answered in ${Date.now() - t0}ms (${guidance.map(g => `${g.model.split('/').pop()}:${g.ms}ms`).join(', ')})`);\n\n // Emit an observable event for the UI (mascot/Live Studio can narrate)\n try {\n const { titanEvents } = await import('../agent/daemon.js');\n titanEvents.emit('moa:guidance', { preset: name, advisors: guidance.map(g => ({ model: g.model, ok: !!g.content, ms: g.ms })) });\n } catch { /* events are best-effort */ }\n\n // Append guidance at the END (prompt-cache prefix stays stable)\n const messages: ChatMessage[] = [\n ...options.messages,\n { role: 'user', content: buildGuidanceBlock(guidance) } as ChatMessage,\n ];\n return {\n preset, name,\n aggregatorOptions: { ...options, model: preset.aggregator, messages, maxTokens: preset.maxTokens ?? options.maxTokens },\n };\n }\n\n async chat(options: ChatOptions): Promise<ChatResponse> {\n const { chat } = await import('./router.js');\n const { aggregatorOptions } = await this.prepare(options);\n return chat(aggregatorOptions);\n }\n\n async *chatStream(options: ChatOptions): AsyncGenerator<ChatStreamChunk> {\n const { chatStream } = await import('./router.js');\n const { aggregatorOptions } = await this.prepare(options);\n yield* chatStream(aggregatorOptions);\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,5 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { loadConfig } from "../config/config.js";
3
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
4
+ import { join } from "path";
5
+ import { TITAN_HOME } from "../utils/constants.js";
3
6
  const STATIC_TABLE = {
4
7
  "anthropic/claude-sonnet-4-20250514": { contextWindow: 2e5, maxOutput: 64e3, supportsThinking: true },
5
8
  "anthropic/claude-opus-4": { contextWindow: 2e5, maxOutput: 32e3, supportsThinking: true },
@@ -36,6 +39,10 @@ const FAMILY_DEFAULTS = [
36
39
  { pattern: /minimax-m3/i, caps: { contextWindow: 1e6, maxOutput: 4e4 } },
37
40
  { pattern: /minimax/i, caps: { contextWindow: 2e5, maxOutput: 4e4 } },
38
41
  { pattern: /\bglm-5/i, caps: { contextWindow: 198e3, maxOutput: 128e3 } },
42
+ { pattern: /glm-4\.7/i, caps: { contextWindow: 198e3, maxOutput: 96e3 } },
43
+ { pattern: /qwen3-coder/i, caps: { contextWindow: 262144, maxOutput: 65536 } },
44
+ { pattern: /nemotron-nano/i, caps: { contextWindow: 131072, maxOutput: 32e3 } },
45
+ { pattern: /gemma-4/i, caps: { contextWindow: 131072, maxOutput: 32768 } },
39
46
  { pattern: /kimi-k2/i, caps: { contextWindow: 262144, maxOutput: 128e3 } },
40
47
  { pattern: /nemotron-3/i, caps: { contextWindow: 1e6, maxOutput: 32e3 } },
41
48
  { pattern: /^anthropic\//, caps: { contextWindow: 2e5, maxOutput: 8192 } },
@@ -44,9 +51,57 @@ const FAMILY_DEFAULTS = [
44
51
  { pattern: /^kimi\/|^moonshot\//, caps: { contextWindow: 262144, maxOutput: 128e3 } },
45
52
  { pattern: /^zhipu\/|^glm/, caps: { contextWindow: 198e3, maxOutput: 128e3 } },
46
53
  { pattern: /^gemini\//, caps: { contextWindow: 1e6, maxOutput: 8192 } },
54
+ { pattern: /:cloud\b/, caps: { contextWindow: 262144, maxOutput: 32768 } },
47
55
  { pattern: /^ollama\//, caps: { contextWindow: 32e3, maxOutput: 8192 } }
48
56
  ];
49
57
  const DEFAULT_FALLBACK = { contextWindow: 32e3, maxOutput: 8192 };
58
+ const LEARNED_PATH = join(TITAN_HOME, "learned-model-limits.json");
59
+ let learnedCache = null;
60
+ function readLearned() {
61
+ if (learnedCache) return learnedCache;
62
+ try {
63
+ if (existsSync(LEARNED_PATH)) {
64
+ learnedCache = JSON.parse(readFileSync(LEARNED_PATH, "utf-8"));
65
+ return learnedCache;
66
+ }
67
+ } catch {
68
+ }
69
+ learnedCache = {};
70
+ return learnedCache;
71
+ }
72
+ function recordLearnedContextWindow(model, contextWindow) {
73
+ if (!Number.isFinite(contextWindow) || contextWindow < 1024) return;
74
+ const learned = readLearned();
75
+ const existing = learned[model]?.contextWindow;
76
+ if (existing !== void 0 && existing <= contextWindow) return;
77
+ learned[model] = { contextWindow, learnedAt: (/* @__PURE__ */ new Date()).toISOString() };
78
+ try {
79
+ mkdirSync(TITAN_HOME, { recursive: true });
80
+ writeFileSync(LEARNED_PATH, JSON.stringify(learned, null, 2));
81
+ } catch {
82
+ }
83
+ }
84
+ function resetLearnedLimitsCache() {
85
+ learnedCache = null;
86
+ }
87
+ function getModelCapabilitiesEx(model) {
88
+ if (STATIC_TABLE[model]) return { caps: STATIC_TABLE[model], source: "static" };
89
+ try {
90
+ const cfg = loadConfig();
91
+ const override = cfg.providers?.modelCapabilities;
92
+ if (override?.[model]) return { caps: override[model], source: "override" };
93
+ } catch {
94
+ }
95
+ const learned = readLearned()[model];
96
+ for (const f of FAMILY_DEFAULTS) {
97
+ if (f.pattern.test(model)) {
98
+ if (learned) return { caps: { ...f.caps, contextWindow: Math.min(learned.contextWindow, f.caps.contextWindow) }, source: "learned" };
99
+ return { caps: f.caps, source: "family" };
100
+ }
101
+ }
102
+ if (learned) return { caps: { ...DEFAULT_FALLBACK, contextWindow: Math.min(learned.contextWindow, DEFAULT_FALLBACK.contextWindow) }, source: "learned" };
103
+ return { caps: DEFAULT_FALLBACK, source: "fallback" };
104
+ }
50
105
  function getModelCapabilities(model) {
51
106
  if (STATIC_TABLE[model]) return STATIC_TABLE[model];
52
107
  try {
@@ -55,9 +110,14 @@ function getModelCapabilities(model) {
55
110
  if (override?.[model]) return override[model];
56
111
  } catch {
57
112
  }
113
+ const learned = readLearned()[model];
58
114
  for (const f of FAMILY_DEFAULTS) {
59
- if (f.pattern.test(model)) return f.caps;
115
+ if (f.pattern.test(model)) {
116
+ if (learned) return { ...f.caps, contextWindow: Math.min(learned.contextWindow, f.caps.contextWindow) };
117
+ return f.caps;
118
+ }
60
119
  }
120
+ if (learned) return { ...DEFAULT_FALLBACK, contextWindow: Math.min(learned.contextWindow, DEFAULT_FALLBACK.contextWindow) };
61
121
  return DEFAULT_FALLBACK;
62
122
  }
63
123
  function clampMaxTokens(model, requested) {
@@ -67,6 +127,9 @@ function clampMaxTokens(model, requested) {
67
127
  }
68
128
  export {
69
129
  clampMaxTokens,
70
- getModelCapabilities
130
+ getModelCapabilities,
131
+ getModelCapabilitiesEx,
132
+ recordLearnedContextWindow,
133
+ resetLearnedLimitsCache
71
134
  };
72
135
  //# sourceMappingURL=modelCapabilities.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/providers/modelCapabilities.ts"],"sourcesContent":["/**\n * TITAN — Per-Model Capability Registry\n *\n * Single source of truth for output-token caps, context-window sizes,\n * and feature flags per model. Providers call clampMaxTokens() so\n * DEFAULT_MAX_TOKENS can safely be a high user-preference ceiling\n * (200 K) without causing 400s on capped providers.\n */\nimport { loadConfig } from '../config/config.js';\n\nexport interface ModelCapabilities {\n contextWindow: number;\n maxOutput: number;\n supportsThinking?: boolean;\n}\n\n// Exact-match table. Keep in alphabetical order by provider / model.\nconst STATIC_TABLE: Record<string, ModelCapabilities> = {\n 'anthropic/claude-sonnet-4-20250514': { contextWindow: 200_000, maxOutput: 64_000, supportsThinking: true },\n 'anthropic/claude-opus-4': { contextWindow: 200_000, maxOutput: 32_000, supportsThinking: true },\n 'anthropic/claude-3-5-sonnet-20241022': { contextWindow: 200_000, maxOutput: 8_192 },\n 'anthropic/claude-3-5-haiku-20241022': { contextWindow: 200_000, maxOutput: 8_192 },\n 'openai/gpt-4o': { contextWindow: 128_000, maxOutput: 16_384 },\n 'openai/gpt-4o-mini': { contextWindow: 128_000, maxOutput: 16_384 },\n 'openai/gpt-4.1': { contextWindow: 1_000_000, maxOutput: 32_768 },\n 'openai/o1': { contextWindow: 200_000, maxOutput: 100_000, supportsThinking: true },\n 'openai/o1-mini': { contextWindow: 128_000, maxOutput: 65_536, supportsThinking: true },\n 'openai/o3-mini': { contextWindow: 200_000, maxOutput: 100_000, supportsThinking: true },\n 'kimi/kimi-k2.6': { contextWindow: 262_144, maxOutput: 128_000, supportsThinking: true },\n 'moonshot/kimi-k2-0905-preview': { contextWindow: 262_144, maxOutput: 128_000 },\n 'zhipu/glm-5.1': { contextWindow: 198_000, maxOutput: 128_000 },\n 'ollama/qwen3.5:cloud': { contextWindow: 128_000, maxOutput: 32_000 },\n 'ollama/qwen3:32b': { contextWindow: 32_768, maxOutput: 8_192 },\n 'ollama/llama3.3:70b': { contextWindow: 128_000, maxOutput: 8_192 },\n 'ollama/deepseek-v3': { contextWindow: 128_000, maxOutput: 16_384 },\n 'mistral/mistral-large': { contextWindow: 128_000, maxOutput: 8_192 },\n 'gemini/gemini-2.0-flash': { contextWindow: 1_000_000, maxOutput: 8_192 },\n 'gemini/gemini-2.5-pro': { contextWindow: 2_000_000, maxOutput: 65_536, supportsThinking: true },\n 'cohere/command-r-plus': { contextWindow: 128_000, maxOutput: 4_096 },\n 'groq/llama-3.3-70b-versatile': { contextWindow: 128_000, maxOutput: 32_768 },\n};\n\n// Family heuristic for unknown specific versions.\nconst FAMILY_DEFAULTS: Array<{ pattern: RegExp; caps: ModelCapabilities }> = [\n // v7.0 — bare-id families for the 2026 agentic models. These match WITH OR\n // WITHOUT a provider prefix (substring, not anchored), so models routed\n // through the generic openai_compat provider or the local :4000 gateway\n // (e.g. \"qwen3.6-35b-a3b\", \"deepseek-v4-pro\", \"kimi-k2.6\") get their real\n // ceilings instead of the 32K/8K DEFAULT_FALLBACK (which truncates JSON).\n // Placed FIRST so they win over the broad `^ollama/` catch-all below.\n { pattern: /deepseek-v4/i, caps: { contextWindow: 128_000, maxOutput: 64_000, supportsThinking: true } },\n { pattern: /qwen3\\.(6|7)/i, caps: { contextWindow: 262_144, maxOutput: 32_768, supportsThinking: true } },\n { pattern: /minimax-m3/i, caps: { contextWindow: 1_000_000, maxOutput: 40_000 } },\n { pattern: /minimax/i, caps: { contextWindow: 200_000, maxOutput: 40_000 } },\n { pattern: /\\bglm-5/i, caps: { contextWindow: 198_000, maxOutput: 128_000 } },\n { pattern: /kimi-k2/i, caps: { contextWindow: 262_144, maxOutput: 128_000 } },\n { pattern: /nemotron-3/i, caps: { contextWindow: 1_000_000, maxOutput: 32_000 } },\n { pattern: /^anthropic\\//, caps: { contextWindow: 200_000, maxOutput: 8_192 } },\n { pattern: /^openai\\/o\\d/, caps: { contextWindow: 200_000, maxOutput: 100_000, supportsThinking: true } },\n { pattern: /^openai\\//, caps: { contextWindow: 128_000, maxOutput: 16_384 } },\n { pattern: /^kimi\\/|^moonshot\\//, caps: { contextWindow: 262_144, maxOutput: 128_000 } },\n { pattern: /^zhipu\\/|^glm/, caps: { contextWindow: 198_000, maxOutput: 128_000 } },\n { pattern: /^gemini\\//, caps: { contextWindow: 1_000_000, maxOutput: 8_192 } },\n { pattern: /^ollama\\//, caps: { contextWindow: 32_000, maxOutput: 8_192 } },\n];\n\nconst DEFAULT_FALLBACK: ModelCapabilities = { contextWindow: 32_000, maxOutput: 8_192 };\n\nexport function getModelCapabilities(model: string): ModelCapabilities {\n if (STATIC_TABLE[model]) return STATIC_TABLE[model];\n\n // Config override path\n try {\n const cfg = loadConfig();\n const override = (cfg.providers as Record<string, unknown> | undefined)?.modelCapabilities as\n Record<string, ModelCapabilities> | undefined;\n if (override?.[model]) return override[model];\n } catch { /* config not loaded yet during early boot */ }\n\n // Family fallback\n for (const f of FAMILY_DEFAULTS) {\n if (f.pattern.test(model)) return f.caps;\n }\n\n return DEFAULT_FALLBACK;\n}\n\n/**\n * Clamp a requested maxTokens to the model's actual ceiling.\n * If requested is undefined, returns the model's own maxOutput.\n * Never returns less than 1.\n */\nexport function clampMaxTokens(model: string, requested?: number): number {\n const caps = getModelCapabilities(model);\n const want = requested ?? caps.maxOutput;\n return Math.max(1, Math.min(want, caps.maxOutput));\n}\n"],"mappings":";AAQA,SAAS,kBAAkB;AAS3B,MAAM,eAAkD;AAAA,EACpD,sCAAwC,EAAE,eAAe,KAAS,WAAW,MAAQ,kBAAkB,KAAK;AAAA,EAC5G,2BAAwC,EAAE,eAAe,KAAS,WAAW,MAAQ,kBAAkB,KAAK;AAAA,EAC5G,wCAAwC,EAAE,eAAe,KAAS,WAAW,KAAM;AAAA,EACnF,uCAAwC,EAAE,eAAe,KAAS,WAAW,KAAM;AAAA,EACnF,iBAAwC,EAAE,eAAe,OAAS,WAAW,MAAO;AAAA,EACpF,sBAAwC,EAAE,eAAe,OAAS,WAAW,MAAO;AAAA,EACpF,kBAAwC,EAAE,eAAe,KAAW,WAAW,MAAO;AAAA,EACtF,aAAwC,EAAE,eAAe,KAAS,WAAW,KAAS,kBAAkB,KAAK;AAAA,EAC7G,kBAAwC,EAAE,eAAe,OAAS,WAAW,OAAQ,kBAAkB,KAAK;AAAA,EAC5G,kBAAwC,EAAE,eAAe,KAAS,WAAW,KAAS,kBAAkB,KAAK;AAAA,EAC7G,kBAAwC,EAAE,eAAe,QAAS,WAAW,OAAS,kBAAkB,KAAK;AAAA,EAC7G,iCAAwC,EAAE,eAAe,QAAS,WAAW,MAAQ;AAAA,EACrF,iBAAwC,EAAE,eAAe,OAAS,WAAW,MAAQ;AAAA,EACrF,wBAAwC,EAAE,eAAe,OAAS,WAAW,KAAO;AAAA,EACpF,oBAAwC,EAAE,eAAe,OAAS,WAAW,KAAM;AAAA,EACnF,uBAAwC,EAAE,eAAe,OAAS,WAAW,KAAM;AAAA,EACnF,sBAAwC,EAAE,eAAe,OAAS,WAAW,MAAO;AAAA,EACpF,yBAAwC,EAAE,eAAe,OAAS,WAAW,KAAM;AAAA,EACnF,2BAAwC,EAAE,eAAe,KAAW,WAAW,KAAM;AAAA,EACrF,yBAAwC,EAAE,eAAe,KAAW,WAAW,OAAQ,kBAAkB,KAAK;AAAA,EAC9G,yBAAwC,EAAE,eAAe,OAAS,WAAW,KAAM;AAAA,EACnF,gCAAwC,EAAE,eAAe,OAAS,WAAW,MAAO;AACxF;AAGA,MAAM,kBAAuE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOzE,EAAE,SAAS,gBAA+B,MAAM,EAAE,eAAe,OAAS,WAAW,MAAQ,kBAAkB,KAAK,EAAE;AAAA,EACtH,EAAE,SAAS,iBAA+B,MAAM,EAAE,eAAe,QAAS,WAAW,OAAQ,kBAAkB,KAAK,EAAE;AAAA,EACtH,EAAE,SAAS,eAA+B,MAAM,EAAE,eAAe,KAAW,WAAW,IAAO,EAAE;AAAA,EAChG,EAAE,SAAS,YAA+B,MAAM,EAAE,eAAe,KAAS,WAAW,IAAO,EAAE;AAAA,EAC9F,EAAE,SAAS,YAA+B,MAAM,EAAE,eAAe,OAAS,WAAW,MAAQ,EAAE;AAAA,EAC/F,EAAE,SAAS,YAA+B,MAAM,EAAE,eAAe,QAAS,WAAW,MAAQ,EAAE;AAAA,EAC/F,EAAE,SAAS,eAA+B,MAAM,EAAE,eAAe,KAAW,WAAW,KAAO,EAAE;AAAA,EAChG,EAAE,SAAS,gBAA+B,MAAM,EAAE,eAAe,KAAS,WAAW,KAAM,EAAE;AAAA,EAC7F,EAAE,SAAS,gBAA+B,MAAM,EAAE,eAAe,KAAS,WAAW,KAAS,kBAAkB,KAAK,EAAE;AAAA,EACvH,EAAE,SAAS,aAA+B,MAAM,EAAE,eAAe,OAAS,WAAW,MAAO,EAAE;AAAA,EAC9F,EAAE,SAAS,uBAA+B,MAAM,EAAE,eAAe,QAAS,WAAW,MAAQ,EAAE;AAAA,EAC/F,EAAE,SAAS,iBAA+B,MAAM,EAAE,eAAe,OAAS,WAAW,MAAQ,EAAE;AAAA,EAC/F,EAAE,SAAS,aAA+B,MAAM,EAAE,eAAe,KAAW,WAAW,KAAM,EAAE;AAAA,EAC/F,EAAE,SAAS,aAA+B,MAAM,EAAE,eAAe,MAAS,WAAW,KAAM,EAAE;AACjG;AAEA,MAAM,mBAAsC,EAAE,eAAe,MAAQ,WAAW,KAAM;AAE/E,SAAS,qBAAqB,OAAkC;AACnE,MAAI,aAAa,KAAK,EAAG,QAAO,aAAa,KAAK;AAGlD,MAAI;AACA,UAAM,MAAM,WAAW;AACvB,UAAM,WAAY,IAAI,WAAmD;AAEzE,QAAI,WAAW,KAAK,EAAG,QAAO,SAAS,KAAK;AAAA,EAChD,QAAQ;AAAA,EAAgD;AAGxD,aAAW,KAAK,iBAAiB;AAC7B,QAAI,EAAE,QAAQ,KAAK,KAAK,EAAG,QAAO,EAAE;AAAA,EACxC;AAEA,SAAO;AACX;AAOO,SAAS,eAAe,OAAe,WAA4B;AACtE,QAAM,OAAO,qBAAqB,KAAK;AACvC,QAAM,OAAO,aAAa,KAAK;AAC/B,SAAO,KAAK,IAAI,GAAG,KAAK,IAAI,MAAM,KAAK,SAAS,CAAC;AACrD;","names":[]}
1
+ {"version":3,"sources":["../../src/providers/modelCapabilities.ts"],"sourcesContent":["/**\n * TITAN — Per-Model Capability Registry\n *\n * Single source of truth for output-token caps, context-window sizes,\n * and feature flags per model. Providers call clampMaxTokens() so\n * DEFAULT_MAX_TOKENS can safely be a high user-preference ceiling\n * (200 K) without causing 400s on capped providers.\n */\nimport { loadConfig } from '../config/config.js';\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';\nimport { join } from 'path';\nimport { TITAN_HOME } from '../utils/constants.js';\n\nexport interface ModelCapabilities {\n contextWindow: number;\n maxOutput: number;\n supportsThinking?: boolean;\n}\n\n// Exact-match table. Keep in alphabetical order by provider / model.\nconst STATIC_TABLE: Record<string, ModelCapabilities> = {\n 'anthropic/claude-sonnet-4-20250514': { contextWindow: 200_000, maxOutput: 64_000, supportsThinking: true },\n 'anthropic/claude-opus-4': { contextWindow: 200_000, maxOutput: 32_000, supportsThinking: true },\n 'anthropic/claude-3-5-sonnet-20241022': { contextWindow: 200_000, maxOutput: 8_192 },\n 'anthropic/claude-3-5-haiku-20241022': { contextWindow: 200_000, maxOutput: 8_192 },\n 'openai/gpt-4o': { contextWindow: 128_000, maxOutput: 16_384 },\n 'openai/gpt-4o-mini': { contextWindow: 128_000, maxOutput: 16_384 },\n 'openai/gpt-4.1': { contextWindow: 1_000_000, maxOutput: 32_768 },\n 'openai/o1': { contextWindow: 200_000, maxOutput: 100_000, supportsThinking: true },\n 'openai/o1-mini': { contextWindow: 128_000, maxOutput: 65_536, supportsThinking: true },\n 'openai/o3-mini': { contextWindow: 200_000, maxOutput: 100_000, supportsThinking: true },\n 'kimi/kimi-k2.6': { contextWindow: 262_144, maxOutput: 128_000, supportsThinking: true },\n 'moonshot/kimi-k2-0905-preview': { contextWindow: 262_144, maxOutput: 128_000 },\n 'zhipu/glm-5.1': { contextWindow: 198_000, maxOutput: 128_000 },\n 'ollama/qwen3.5:cloud': { contextWindow: 128_000, maxOutput: 32_000 },\n 'ollama/qwen3:32b': { contextWindow: 32_768, maxOutput: 8_192 },\n 'ollama/llama3.3:70b': { contextWindow: 128_000, maxOutput: 8_192 },\n 'ollama/deepseek-v3': { contextWindow: 128_000, maxOutput: 16_384 },\n 'mistral/mistral-large': { contextWindow: 128_000, maxOutput: 8_192 },\n 'gemini/gemini-2.0-flash': { contextWindow: 1_000_000, maxOutput: 8_192 },\n 'gemini/gemini-2.5-pro': { contextWindow: 2_000_000, maxOutput: 65_536, supportsThinking: true },\n 'cohere/command-r-plus': { contextWindow: 128_000, maxOutput: 4_096 },\n 'groq/llama-3.3-70b-versatile': { contextWindow: 128_000, maxOutput: 32_768 },\n};\n\n// Family heuristic for unknown specific versions.\nconst FAMILY_DEFAULTS: Array<{ pattern: RegExp; caps: ModelCapabilities }> = [\n // v7.0 — bare-id families for the 2026 agentic models. These match WITH OR\n // WITHOUT a provider prefix (substring, not anchored), so models routed\n // through the generic openai_compat provider or the local :4000 gateway\n // (e.g. \"qwen3.6-35b-a3b\", \"deepseek-v4-pro\", \"kimi-k2.6\") get their real\n // ceilings instead of the 32K/8K DEFAULT_FALLBACK (which truncates JSON).\n // Placed FIRST so they win over the broad `^ollama/` catch-all below.\n { pattern: /deepseek-v4/i, caps: { contextWindow: 128_000, maxOutput: 64_000, supportsThinking: true } },\n { pattern: /qwen3\\.(6|7)/i, caps: { contextWindow: 262_144, maxOutput: 32_768, supportsThinking: true } },\n { pattern: /minimax-m3/i, caps: { contextWindow: 1_000_000, maxOutput: 40_000 } },\n { pattern: /minimax/i, caps: { contextWindow: 200_000, maxOutput: 40_000 } },\n { pattern: /\\bglm-5/i, caps: { contextWindow: 198_000, maxOutput: 128_000 } },\n { pattern: /glm-4\\.7/i, caps: { contextWindow: 198_000, maxOutput: 96_000 } },\n { pattern: /qwen3-coder/i, caps: { contextWindow: 262_144, maxOutput: 65_536 } },\n { pattern: /nemotron-nano/i, caps: { contextWindow: 131_072, maxOutput: 32_000 } },\n { pattern: /gemma-4/i, caps: { contextWindow: 131_072, maxOutput: 32_768 } },\n { pattern: /kimi-k2/i, caps: { contextWindow: 262_144, maxOutput: 128_000 } },\n { pattern: /nemotron-3/i, caps: { contextWindow: 1_000_000, maxOutput: 32_000 } },\n { pattern: /^anthropic\\//, caps: { contextWindow: 200_000, maxOutput: 8_192 } },\n { pattern: /^openai\\/o\\d/, caps: { contextWindow: 200_000, maxOutput: 100_000, supportsThinking: true } },\n { pattern: /^openai\\//, caps: { contextWindow: 128_000, maxOutput: 16_384 } },\n { pattern: /^kimi\\/|^moonshot\\//, caps: { contextWindow: 262_144, maxOutput: 128_000 } },\n { pattern: /^zhipu\\/|^glm/, caps: { contextWindow: 198_000, maxOutput: 128_000 } },\n { pattern: /^gemini\\//, caps: { contextWindow: 1_000_000, maxOutput: 8_192 } },\n { pattern: /:cloud\\b/, caps: { contextWindow: 262_144, maxOutput: 32_768 } },\n { pattern: /^ollama\\//, caps: { contextWindow: 32_000, maxOutput: 8_192 } },\n];\n\nconst DEFAULT_FALLBACK: ModelCapabilities = { contextWindow: 32_000, maxOutput: 8_192 };\n\n// ── Learned deployment limits (v7.1 \"truly model agnostic\") ──────────────\n// A model FAMILY may support 198K context, but the DEPLOYMENT in front of us\n// may be a vLLM serving 16K. When a backend 400 reveals its real ceiling\n// (parseMaxTokenLimit / context-overflow messages), we persist it here so\n// every later request — including tool-tier selection — fits the deployment\n// automatically. Config overrides still win; learning fills the gap.\nconst LEARNED_PATH = join(TITAN_HOME, 'learned-model-limits.json');\nlet learnedCache: Record<string, { contextWindow: number; learnedAt: string }> | null = null;\n\nfunction readLearned(): Record<string, { contextWindow: number; learnedAt: string }> {\n if (learnedCache) return learnedCache;\n try {\n if (existsSync(LEARNED_PATH)) {\n learnedCache = JSON.parse(readFileSync(LEARNED_PATH, 'utf-8'));\n return learnedCache!;\n }\n } catch { /* corrupt file — relearn */ }\n learnedCache = {};\n return learnedCache;\n}\n\n/** Persist a deployment's real context ceiling discovered from a backend 400. */\nexport function recordLearnedContextWindow(model: string, contextWindow: number): void {\n if (!Number.isFinite(contextWindow) || contextWindow < 1024) return;\n const learned = readLearned();\n const existing = learned[model]?.contextWindow;\n // Keep the smallest observed ceiling — a deployment can't grow mid-flight,\n // and re-serving with a bigger window is picked up by deleting the file\n // or via the config override.\n if (existing !== undefined && existing <= contextWindow) return;\n learned[model] = { contextWindow, learnedAt: new Date().toISOString() };\n try {\n mkdirSync(TITAN_HOME, { recursive: true });\n writeFileSync(LEARNED_PATH, JSON.stringify(learned, null, 2));\n } catch { /* best-effort persistence */ }\n}\n\n/** Test hook: reset the learned-limits cache. */\nexport function resetLearnedLimitsCache(): void {\n learnedCache = null;\n}\n\nexport type CapabilitySource = 'static' | 'override' | 'learned' | 'family' | 'fallback';\n\n/** Like getModelCapabilities, but reports WHERE the answer came from — a\n * 32K fallback for an unknown model is a guess, not a measurement, and\n * context-fit tool tiering must not shrink toolsets on a guess. */\nexport function getModelCapabilitiesEx(model: string): { caps: ModelCapabilities; source: CapabilitySource } {\n if (STATIC_TABLE[model]) return { caps: STATIC_TABLE[model], source: 'static' };\n try {\n const cfg = loadConfig();\n const override = (cfg.providers as Record<string, unknown> | undefined)?.modelCapabilities as\n Record<string, ModelCapabilities> | undefined;\n if (override?.[model]) return { caps: override[model], source: 'override' };\n } catch { /* early boot */ }\n const learned = readLearned()[model];\n for (const f of FAMILY_DEFAULTS) {\n if (f.pattern.test(model)) {\n if (learned) return { caps: { ...f.caps, contextWindow: Math.min(learned.contextWindow, f.caps.contextWindow) }, source: 'learned' };\n return { caps: f.caps, source: 'family' };\n }\n }\n if (learned) return { caps: { ...DEFAULT_FALLBACK, contextWindow: Math.min(learned.contextWindow, DEFAULT_FALLBACK.contextWindow) }, source: 'learned' };\n return { caps: DEFAULT_FALLBACK, source: 'fallback' };\n}\n\nexport function getModelCapabilities(model: string): ModelCapabilities {\n if (STATIC_TABLE[model]) return STATIC_TABLE[model];\n\n // Config override path\n try {\n const cfg = loadConfig();\n const override = (cfg.providers as Record<string, unknown> | undefined)?.modelCapabilities as\n Record<string, ModelCapabilities> | undefined;\n if (override?.[model]) return override[model];\n } catch { /* config not loaded yet during early boot */ }\n\n // Learned deployment ceiling (from real backend 400s) — beats the family\n // guess because it reflects the endpoint actually serving this model.\n const learned = readLearned()[model];\n\n // Family fallback\n for (const f of FAMILY_DEFAULTS) {\n if (f.pattern.test(model)) {\n if (learned) return { ...f.caps, contextWindow: Math.min(learned.contextWindow, f.caps.contextWindow) };\n return f.caps;\n }\n }\n\n if (learned) return { ...DEFAULT_FALLBACK, contextWindow: Math.min(learned.contextWindow, DEFAULT_FALLBACK.contextWindow) };\n return DEFAULT_FALLBACK;\n}\n\n/**\n * Clamp a requested maxTokens to the model's actual ceiling.\n * If requested is undefined, returns the model's own maxOutput.\n * Never returns less than 1.\n */\nexport function clampMaxTokens(model: string, requested?: number): number {\n const caps = getModelCapabilities(model);\n const want = requested ?? caps.maxOutput;\n return Math.max(1, Math.min(want, caps.maxOutput));\n}\n"],"mappings":"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","names":[]}
@@ -35,6 +35,7 @@ const CLOUD_MODEL_CTX = {
35
35
  "devstral-small-2:latest": 32768,
36
36
  // Nemotron 3 Nano — 1M native, 32K practical for local
37
37
  "nemotron-3-nano": 32768,
38
+ "nemotron-nano": 32768,
38
39
  "nemotron-3-nano:latest": 32768,
39
40
  "nemotron-3-nano:4b": 32768,
40
41
  "nemotron-3-nano:30b": 32768,