titan-agent 5.2.0 → 5.3.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 (112) hide show
  1. package/README.md +38 -8
  2. package/dist/eval/harness.js +49 -0
  3. package/dist/eval/harness.js.map +1 -1
  4. package/dist/eval/parity.js +148 -0
  5. package/dist/eval/parity.js.map +1 -0
  6. package/dist/eval/record.js +96 -0
  7. package/dist/eval/record.js.map +1 -0
  8. package/dist/gateway/metrics.js +20 -1
  9. package/dist/gateway/metrics.js.map +1 -1
  10. package/dist/gateway/server.js +5 -1
  11. package/dist/gateway/server.js.map +1 -1
  12. package/dist/utils/constants.js +1 -1
  13. package/dist/utils/constants.js.map +1 -1
  14. package/dist/utils/safety.js +31 -1
  15. package/dist/utils/safety.js.map +1 -1
  16. package/package.json +5 -1
  17. package/scripts/eval-gate.sh +189 -0
  18. package/scripts/eval-record.ts +133 -0
  19. package/ui/dist/assets/{AuditPanel-DLy0WJQZ.js → AuditPanel-C31LRHZX.js} +1 -1
  20. package/ui/dist/assets/{AutonomyPanel-DjFAQGns.js → AutonomyPanel-CxQU72ZY.js} +1 -1
  21. package/ui/dist/assets/{AutopilotPanel-nBluaHA4.js → AutopilotPanel-D4FnBwJm.js} +1 -1
  22. package/ui/dist/assets/{AutoresearchPanel-BDy8y_Cs.js → AutoresearchPanel-BYHXZ9AO.js} +1 -1
  23. package/ui/dist/assets/{BackupPanel-B_Fv2pJA.js → BackupPanel-C4CQKf2P.js} +1 -1
  24. package/ui/dist/assets/{BrowserPanel-DOCT3-Rq.js → BrowserPanel-C-OFYyLm.js} +1 -1
  25. package/ui/dist/assets/{CPAgents-CpkHf0b8.js → CPAgents-CvkZDm_3.js} +1 -1
  26. package/ui/dist/assets/{CPDashboard-CnMd6qNK.js → CPDashboard-JmBLBbj7.js} +1 -1
  27. package/ui/dist/assets/{CPFiles-BDRjJpYl.js → CPFiles-BDToRw0a.js} +1 -1
  28. package/ui/dist/assets/{CPGoals-2DrwHk62.js → CPGoals-Dh9qJNWa.js} +1 -1
  29. package/ui/dist/assets/{CPInbox-C6l2o4FD.js → CPInbox-B6iaIbNG.js} +1 -1
  30. package/ui/dist/assets/{CPSocial-Cea6NptR.js → CPSocial-CsFrwZRC.js} +1 -1
  31. package/ui/dist/assets/{ChannelsPanel-5EhhyXeg.js → ChannelsPanel-D-S4ktFn.js} +1 -1
  32. package/ui/dist/assets/{CheckpointsPanel-BVt2oEUe.js → CheckpointsPanel-D-sP9ZuS.js} +1 -1
  33. package/ui/dist/assets/{CommandPostHub-PXKE62DN.js → CommandPostHub-BhlNyeDH.js} +3 -3
  34. package/ui/dist/assets/{CronPanel-lAsoKavq.js → CronPanel-Bf3rV7N2.js} +1 -1
  35. package/ui/dist/assets/{DaemonPanel-xt08Rs10.js → DaemonPanel-GGBWjTG2.js} +1 -1
  36. package/ui/dist/assets/{DataTable-BHOu7fZP.js → DataTable-D2Px4o6f.js} +1 -1
  37. package/ui/dist/assets/{EmptyState-Dk7BBthD.js → EmptyState-DH6-Jy6A.js} +1 -1
  38. package/ui/dist/assets/EvalHarnessPanel-Cz9dRg61.js +2 -0
  39. package/ui/dist/assets/{EvalPanel-D9rDf1bk.js → EvalPanel-CdjxzHlJ.js} +1 -1
  40. package/ui/dist/assets/{FilesPanel-CNrDLmix.js → FilesPanel-Dz8TFydL.js} +1 -1
  41. package/ui/dist/assets/{FleetPanel-DP_ji0AE.js → FleetPanel-CWwWWTD4.js} +1 -1
  42. package/ui/dist/assets/{HomelabPanel-B4bCsrBw.js → HomelabPanel-C7VBV7AC.js} +1 -1
  43. package/ui/dist/assets/{InfraView-C5OYx_9s.js → InfraView-B1TgXARJ.js} +2 -2
  44. package/ui/dist/assets/{InlineEditableField-DyBCbIoN.js → InlineEditableField-DOJNOL8m.js} +1 -1
  45. package/ui/dist/assets/{Input-DWnbv1Yh.js → Input-BgyHgQ3D.js} +1 -1
  46. package/ui/dist/assets/{IntegrationsPanel-DsB6hjvE.js → IntegrationsPanel-O26b4nhv.js} +1 -1
  47. package/ui/dist/assets/{IntelligenceView-PIFGvIg_.js → IntelligenceView-DUhTQ8f_.js} +2 -2
  48. package/ui/dist/assets/{LearningPanel-D_S4HFX5.js → LearningPanel-DX5S9ovg.js} +1 -1
  49. package/ui/dist/assets/{LogsPanel-BnWNREPX.js → LogsPanel-DdeTnATQ.js} +1 -1
  50. package/ui/dist/assets/{McpPanel-CIMxZ2Am.js → McpPanel-BpXWrP1a.js} +1 -1
  51. package/ui/dist/assets/{MemoryGraphPanel-DD7x4rrm.js → MemoryGraphPanel-CNkZmTUy.js} +1 -1
  52. package/ui/dist/assets/{MemoryWikiPanel-BPPVAH0b.js → MemoryWikiPanel-o4L8Df-n.js} +1 -1
  53. package/ui/dist/assets/{MeshPanel-CiuwR3oV.js → MeshPanel-DMBQJFCC.js} +1 -1
  54. package/ui/dist/assets/{NvidiaPanel-DVntoRrH.js → NvidiaPanel-C8P-tJFG.js} +1 -1
  55. package/ui/dist/assets/{OrganismPanel-pqIKtHrW.js → OrganismPanel-CcfHDWDk.js} +1 -1
  56. package/ui/dist/assets/OverviewPanel-BSotI1Zv.js +1 -0
  57. package/ui/dist/assets/{PageHeader-CF75km05.js → PageHeader-DPJuAgJk.js} +1 -1
  58. package/ui/dist/assets/{PaperclipPanel-CwN5-cKg.js → PaperclipPanel-aXoXUjo6.js} +1 -1
  59. package/ui/dist/assets/{PersonasPanel-ClC_TTGX.js → PersonasPanel-DdPZxz2C.js} +1 -1
  60. package/ui/dist/assets/{RecipesPanel-Di2l-eOe.js → RecipesPanel-D7qffXQN.js} +1 -1
  61. package/ui/dist/assets/{SecurityPanel-DjC4pXGM.js → SecurityPanel-BDRK5el7.js} +1 -1
  62. package/ui/dist/assets/{SelfImprovePanel-CNpCp5N4.js → SelfImprovePanel-oYiMwFnA.js} +1 -1
  63. package/ui/dist/assets/{SelfProposalsPanel-BJL6Fjxo.js → SelfProposalsPanel-DOpNU_rr.js} +1 -1
  64. package/ui/dist/assets/{SessionsPanel-EAGKDQp0.js → SessionsPanel-eRbM3D9P.js} +1 -1
  65. package/ui/dist/assets/{SessionsTab-tc0njI15.js → SessionsTab-Jq3UKQCI.js} +1 -1
  66. package/ui/dist/assets/{SettingsPanel-BdSGImIa.js → SettingsPanel-DBIvKUYY.js} +1 -1
  67. package/ui/dist/assets/{SettingsView-DQB64bjy.js → SettingsView-yfSY4OLt.js} +2 -2
  68. package/ui/dist/assets/{SkeletonLoader-P8SFCyGi.js → SkeletonLoader-D1d-Gyyg.js} +1 -1
  69. package/ui/dist/assets/{SkillsPanel-lDMl_8da.js → SkillsPanel-bubl9nag.js} +1 -1
  70. package/ui/dist/assets/{SomaView-BG7YvBu2.js → SomaView-D3aFL8Tw.js} +1 -1
  71. package/ui/dist/assets/{StatCard-Cv2u-yqA.js → StatCard-CEVFsz7t.js} +1 -1
  72. package/ui/dist/assets/{StatusBadge-JJeoEdCm.js → StatusBadge-DxeA9LNd.js} +1 -1
  73. package/ui/dist/assets/{TeamsPanel-D-iCyyYd.js → TeamsPanel-D6IJJIR_.js} +1 -1
  74. package/ui/dist/assets/{TelemetryPanel-DHNFyCwn.js → TelemetryPanel-SMPebdjQ.js} +1 -1
  75. package/ui/dist/assets/{TitanCanvas-BhurNMK3.js → TitanCanvas-BQU1yxqf.js} +3 -3
  76. package/ui/dist/assets/ToolsView-DgP4uRPr.js +2 -0
  77. package/ui/dist/assets/{Tooltip-D4IeQDJL.js → Tooltip-CNPQr7IO.js} +1 -1
  78. package/ui/dist/assets/{TraceViewer-CMd-Wi0z.js → TraceViewer-BbISy_ET.js} +1 -1
  79. package/ui/dist/assets/{TrainingPanel-CLtiBq2h.js → TrainingPanel-BdCHcv6t.js} +1 -1
  80. package/ui/dist/assets/{VoiceOverlay-BXPVdnJc.js → VoiceOverlay-l6yoasVz.js} +1 -1
  81. package/ui/dist/assets/{VramPanel-DjuwGUzA.js → VramPanel-XLhmen92.js} +1 -1
  82. package/ui/dist/assets/{WatchView-B7sDnMpl.js → WatchView-Bt-lNNWJ.js} +1 -1
  83. package/ui/dist/assets/{WorkTab-B5nQ4Y7A.js → WorkTab-IG-F6Qll.js} +1 -1
  84. package/ui/dist/assets/{WorkflowsPanel-2z0TeXyR.js → WorkflowsPanel-DsMpnwLK.js} +1 -1
  85. package/ui/dist/assets/{arrow-left-BKOkzkae.js → arrow-left-C_H9Z2Tm.js} +1 -1
  86. package/ui/dist/assets/{chart-column-D39PCk17.js → chart-column-rR6tb72l.js} +1 -1
  87. package/ui/dist/assets/{circle-check-big-CMz0QouP.js → circle-check-big-B1hMwau0.js} +1 -1
  88. package/ui/dist/assets/{dollar-sign-Bu8fZOQl.js → dollar-sign-DhYwsTnR.js} +1 -1
  89. package/ui/dist/assets/{download-vvx6zJ-U.js → download-UDDcAlZC.js} +1 -1
  90. package/ui/dist/assets/{eye-off-BPXFIzlW.js → eye-off-Cx0M_VQb.js} +1 -1
  91. package/ui/dist/assets/{funnel-Bqns-i8I.js → funnel-B7YvM1ei.js} +1 -1
  92. package/ui/dist/assets/{git-branch-CdmeqL8d.js → git-branch-BhTBN3J6.js} +1 -1
  93. package/ui/dist/assets/index-D0RJ8701.css +1 -0
  94. package/ui/dist/assets/{index-C6oarzis.js → index-D7Clon2u.js} +2 -2
  95. package/ui/dist/assets/layers-B6jDzitD.js +6 -0
  96. package/ui/dist/assets/{legacy-DFIaZTiF.js → legacy-av079XKu.js} +1 -1
  97. package/ui/dist/assets/{lightbulb-DOL6Q-iP.js → lightbulb-DRuQ3Chf.js} +1 -1
  98. package/ui/dist/assets/{pause-B0XymOnS.js → pause-DqkRWPB_.js} +1 -1
  99. package/ui/dist/assets/{play-Dwp2l5HG.js → play-hUyR3CVS.js} +1 -1
  100. package/ui/dist/assets/{plug-DRlTjWqQ.js → plug-CvpyjJt_.js} +1 -1
  101. package/ui/dist/assets/{proxy-sXxWK7WF.js → proxy-Cc5bR828.js} +1 -1
  102. package/ui/dist/assets/{square-yh0jffQZ.js → square-CdiC0J8Z.js} +1 -1
  103. package/ui/dist/assets/{target-GxtNG2RW.js → target-DemL8_0v.js} +1 -1
  104. package/ui/dist/assets/{toggle-right-CYQd_Ux1.js → toggle-right-Dsk892k5.js} +1 -1
  105. package/ui/dist/assets/{trash-2-B4jp_pAQ.js → trash-2-Byj4OvKB.js} +1 -1
  106. package/ui/dist/assets/{trending-up-B26tNhFP.js → trending-up-Dh_CffGX.js} +1 -1
  107. package/ui/dist/assets/{trophy-Bf3ZeSeb.js → trophy-DDr2AePx.js} +1 -1
  108. package/ui/dist/index.html +2 -2
  109. package/ui/dist/assets/EvalHarnessPanel-CJv8CUDy.js +0 -1
  110. package/ui/dist/assets/OverviewPanel-gqYRhmpF.js +0 -6
  111. package/ui/dist/assets/ToolsView-C8sWxLny.js +0 -2
  112. package/ui/dist/assets/index-DsFoD9SP.css +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/gateway/metrics.ts"],"sourcesContent":["/**\n * TITAN — Prometheus Metrics Engine\n * Zero-dependency metrics collection with Prometheus text exposition format.\n */\n\n// ── Metric Types ─────────────────────────────────────────────────────\n\ntype Labels = Record<string, string>;\n\nfunction labelsKey(labels?: Labels): string {\n if (!labels || Object.keys(labels).length === 0) return '';\n return Object.entries(labels).sort(([a], [b]) => a.localeCompare(b))\n .map(([k, v]) => `${k}=\"${v}\"`).join(',');\n}\n\nexport class Counter {\n readonly name: string;\n readonly help: string;\n private values = new Map<string, number>();\n\n constructor(name: string, help: string) {\n this.name = name;\n this.help = help;\n }\n\n increment(labels?: Labels, amount = 1): void {\n const key = labelsKey(labels);\n this.values.set(key, (this.values.get(key) || 0) + amount);\n }\n\n get(labels?: Labels): number {\n return this.values.get(labelsKey(labels)) || 0;\n }\n\n serialize(): string {\n const lines: string[] = [\n `# HELP ${this.name} ${this.help}`,\n `# TYPE ${this.name} counter`,\n ];\n if (this.values.size === 0) {\n lines.push(`${this.name} 0`);\n } else {\n for (const [key, val] of this.values) {\n const lbl = key ? `{${key}}` : '';\n lines.push(`${this.name}${lbl} ${val}`);\n }\n }\n return lines.join('\\n');\n }\n\n /** Get all label combinations and their values */\n getAll(): Array<{ labels: Labels; value: number }> {\n const result: Array<{ labels: Labels; value: number }> = [];\n for (const [key, value] of this.values) {\n const labels: Labels = {};\n if (key) {\n for (const pair of key.split(',')) {\n const [k, v] = pair.split('=');\n labels[k] = v.replace(/\"/g, '');\n }\n }\n result.push({ labels, value });\n }\n return result;\n }\n}\n\nconst DEFAULT_BUCKETS = [0.01, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10];\n\nexport class Histogram {\n readonly name: string;\n readonly help: string;\n readonly buckets: number[];\n // key → { bucketCounts, sum, count }\n private data = new Map<string, { bucketCounts: number[]; sum: number; count: number }>();\n\n constructor(name: string, help: string, buckets = DEFAULT_BUCKETS) {\n this.name = name;\n this.help = help;\n this.buckets = [...buckets].sort((a, b) => a - b);\n }\n\n observe(value: number, labels?: Labels): void {\n const key = labelsKey(labels);\n let entry = this.data.get(key);\n if (!entry) {\n entry = { bucketCounts: new Array(this.buckets.length).fill(0), sum: 0, count: 0 };\n this.data.set(key, entry);\n }\n entry.sum += value;\n entry.count++;\n for (let i = 0; i < this.buckets.length; i++) {\n if (value <= this.buckets[i]) {\n entry.bucketCounts[i]++;\n break;\n }\n }\n }\n\n get(labels?: Labels): { sum: number; count: number; buckets: Record<string, number> } {\n const key = labelsKey(labels);\n const entry = this.data.get(key);\n if (!entry) return { sum: 0, count: 0, buckets: {} };\n const buckets: Record<string, number> = {};\n let cumulative = 0;\n for (let i = 0; i < this.buckets.length; i++) {\n cumulative += entry.bucketCounts[i];\n buckets[String(this.buckets[i])] = cumulative;\n }\n buckets['+Inf'] = entry.count;\n return { sum: entry.sum, count: entry.count, buckets };\n }\n\n serialize(): string {\n const lines: string[] = [\n `# HELP ${this.name} ${this.help}`,\n `# TYPE ${this.name} histogram`,\n ];\n if (this.data.size === 0) {\n // Emit empty histogram\n for (const b of this.buckets) {\n lines.push(`${this.name}_bucket{le=\"${b}\"} 0`);\n }\n lines.push(`${this.name}_bucket{le=\"+Inf\"} 0`);\n lines.push(`${this.name}_sum 0`);\n lines.push(`${this.name}_count 0`);\n } else {\n for (const [key, entry] of this.data) {\n const baseLabels = key ? `${key},` : '';\n let cumulative = 0;\n for (let i = 0; i < this.buckets.length; i++) {\n cumulative += entry.bucketCounts[i];\n lines.push(`${this.name}_bucket{${baseLabels}le=\"${this.buckets[i]}\"} ${cumulative}`);\n }\n lines.push(`${this.name}_bucket{${baseLabels}le=\"+Inf\"} ${entry.count}`);\n const lbl = key ? `{${key}}` : '';\n lines.push(`${this.name}_sum${lbl} ${entry.sum}`);\n lines.push(`${this.name}_count${lbl} ${entry.count}`);\n }\n }\n return lines.join('\\n');\n }\n}\n\nexport class Gauge {\n readonly name: string;\n readonly help: string;\n private values = new Map<string, number>();\n\n constructor(name: string, help: string) {\n this.name = name;\n this.help = help;\n }\n\n set(value: number, labels?: Labels): void {\n this.values.set(labelsKey(labels), value);\n }\n\n inc(labels?: Labels, amount = 1): void {\n const key = labelsKey(labels);\n this.values.set(key, (this.values.get(key) || 0) + amount);\n }\n\n dec(labels?: Labels, amount = 1): void {\n const key = labelsKey(labels);\n this.values.set(key, (this.values.get(key) || 0) - amount);\n }\n\n get(labels?: Labels): number {\n return this.values.get(labelsKey(labels)) || 0;\n }\n\n serialize(): string {\n const lines: string[] = [\n `# HELP ${this.name} ${this.help}`,\n `# TYPE ${this.name} gauge`,\n ];\n if (this.values.size === 0) {\n lines.push(`${this.name} 0`);\n } else {\n for (const [key, val] of this.values) {\n const lbl = key ? `{${key}}` : '';\n lines.push(`${this.name}${lbl} ${val}`);\n }\n }\n return lines.join('\\n');\n }\n}\n\n// ── Pre-defined TITAN Metrics ────────────────────────────────────────\n\nexport const titanRequestsTotal = new Counter(\n 'titan_requests_total',\n 'Total number of requests handled',\n);\n\nexport const titanRequestDuration = new Histogram(\n 'titan_request_duration_seconds',\n 'Request duration in seconds',\n);\n\nexport const titanTokensTotal = new Counter(\n 'titan_tokens_total',\n 'Total tokens consumed',\n);\n\nexport const titanErrorsTotal = new Counter(\n 'titan_errors_total',\n 'Total errors encountered',\n);\n\nexport const titanActiveSessions = new Gauge(\n 'titan_active_sessions',\n 'Number of currently active sessions',\n);\n\nexport const titanToolCallsTotal = new Counter(\n 'titan_tool_calls_total',\n 'Total tool invocations',\n);\n\nexport const titanModelRequestsTotal = new Counter(\n 'titan_model_requests_total',\n 'Total model requests by model and provider',\n);\n\n// ── Registry & Serialization ─────────────────────────────────────────\n\nconst allMetrics = [\n titanRequestsTotal,\n titanRequestDuration,\n titanTokensTotal,\n titanErrorsTotal,\n titanActiveSessions,\n titanToolCallsTotal,\n titanModelRequestsTotal,\n];\n\nexport function serializePrometheus(): string {\n return allMetrics.map(m => m.serialize()).join('\\n\\n') + '\\n';\n}\n\n/** JSON summary for the dashboard telemetry panel */\nexport function getMetricsSummary(): {\n totalRequests: number;\n avgLatencyMs: number;\n topTools: Array<{ tool: string; count: number }>;\n errorRate: number;\n totalErrors: number;\n /**\n * Token counts. The dashboard displays `.total`; `.prompt` + `.completion`\n * are kept for per-bucket breakdowns and Prometheus label parity.\n */\n totalTokens: { prompt: number; completion: number; total: number };\n} {\n // Total requests\n let totalRequests = 0;\n for (const entry of titanRequestsTotal.getAll()) {\n totalRequests += entry.value;\n }\n\n // Average latency\n const duration = titanRequestDuration.get();\n const avgLatencyMs = duration.count > 0 ? (duration.sum / duration.count) * 1000 : 0;\n\n // Top 5 tools by usage\n const toolEntries = titanToolCallsTotal.getAll()\n .map(e => ({ tool: e.labels['tool'] || 'unknown', count: e.value }))\n .sort((a, b) => b.count - a.count)\n .slice(0, 5);\n\n // Error rate\n let totalErrors = 0;\n for (const entry of titanErrorsTotal.getAll()) {\n totalErrors += entry.value;\n }\n const errorRate = totalRequests > 0 ? totalErrors / totalRequests : 0;\n\n // Tokens\n const promptTokens = titanTokensTotal.get({ type: 'prompt' });\n const completionTokens = titanTokensTotal.get({ type: 'completion' });\n\n return {\n totalRequests,\n avgLatencyMs: Math.round(avgLatencyMs * 100) / 100,\n topTools: toolEntries,\n errorRate: Math.round(errorRate * 10000) / 10000,\n totalErrors,\n totalTokens: { prompt: promptTokens, completion: completionTokens, total: promptTokens + completionTokens },\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/gateway/metrics.ts"],"sourcesContent":["/**\n * TITAN — Prometheus Metrics Engine\n * Zero-dependency metrics collection with Prometheus text exposition format.\n */\n\n// ── Metric Types ─────────────────────────────────────────────────────\n\ntype Labels = Record<string, string>;\n\nfunction labelsKey(labels?: Labels): string {\n if (!labels || Object.keys(labels).length === 0) return '';\n return Object.entries(labels).sort(([a], [b]) => a.localeCompare(b))\n .map(([k, v]) => `${k}=\"${v}\"`).join(',');\n}\n\nexport class Counter {\n readonly name: string;\n readonly help: string;\n private values = new Map<string, number>();\n\n constructor(name: string, help: string) {\n this.name = name;\n this.help = help;\n }\n\n increment(labels?: Labels, amount = 1): void {\n const key = labelsKey(labels);\n this.values.set(key, (this.values.get(key) || 0) + amount);\n }\n\n get(labels?: Labels): number {\n return this.values.get(labelsKey(labels)) || 0;\n }\n\n serialize(): string {\n const lines: string[] = [\n `# HELP ${this.name} ${this.help}`,\n `# TYPE ${this.name} counter`,\n ];\n if (this.values.size === 0) {\n lines.push(`${this.name} 0`);\n } else {\n for (const [key, val] of this.values) {\n const lbl = key ? `{${key}}` : '';\n lines.push(`${this.name}${lbl} ${val}`);\n }\n }\n return lines.join('\\n');\n }\n\n /** Get all label combinations and their values */\n getAll(): Array<{ labels: Labels; value: number }> {\n const result: Array<{ labels: Labels; value: number }> = [];\n for (const [key, value] of this.values) {\n const labels: Labels = {};\n if (key) {\n for (const pair of key.split(',')) {\n const [k, v] = pair.split('=');\n labels[k] = v.replace(/\"/g, '');\n }\n }\n result.push({ labels, value });\n }\n return result;\n }\n}\n\nconst DEFAULT_BUCKETS = [0.01, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10];\n\nexport class Histogram {\n readonly name: string;\n readonly help: string;\n readonly buckets: number[];\n // key → { bucketCounts, sum, count }\n private data = new Map<string, { bucketCounts: number[]; sum: number; count: number }>();\n\n constructor(name: string, help: string, buckets = DEFAULT_BUCKETS) {\n this.name = name;\n this.help = help;\n this.buckets = [...buckets].sort((a, b) => a - b);\n }\n\n observe(value: number, labels?: Labels): void {\n const key = labelsKey(labels);\n let entry = this.data.get(key);\n if (!entry) {\n entry = { bucketCounts: new Array(this.buckets.length).fill(0), sum: 0, count: 0 };\n this.data.set(key, entry);\n }\n entry.sum += value;\n entry.count++;\n for (let i = 0; i < this.buckets.length; i++) {\n if (value <= this.buckets[i]) {\n entry.bucketCounts[i]++;\n break;\n }\n }\n }\n\n get(labels?: Labels): { sum: number; count: number; buckets: Record<string, number> } {\n const key = labelsKey(labels);\n const entry = this.data.get(key);\n if (!entry) return { sum: 0, count: 0, buckets: {} };\n const buckets: Record<string, number> = {};\n let cumulative = 0;\n for (let i = 0; i < this.buckets.length; i++) {\n cumulative += entry.bucketCounts[i];\n buckets[String(this.buckets[i])] = cumulative;\n }\n buckets['+Inf'] = entry.count;\n return { sum: entry.sum, count: entry.count, buckets };\n }\n\n serialize(): string {\n const lines: string[] = [\n `# HELP ${this.name} ${this.help}`,\n `# TYPE ${this.name} histogram`,\n ];\n if (this.data.size === 0) {\n // Emit empty histogram\n for (const b of this.buckets) {\n lines.push(`${this.name}_bucket{le=\"${b}\"} 0`);\n }\n lines.push(`${this.name}_bucket{le=\"+Inf\"} 0`);\n lines.push(`${this.name}_sum 0`);\n lines.push(`${this.name}_count 0`);\n } else {\n for (const [key, entry] of this.data) {\n const baseLabels = key ? `${key},` : '';\n let cumulative = 0;\n for (let i = 0; i < this.buckets.length; i++) {\n cumulative += entry.bucketCounts[i];\n lines.push(`${this.name}_bucket{${baseLabels}le=\"${this.buckets[i]}\"} ${cumulative}`);\n }\n lines.push(`${this.name}_bucket{${baseLabels}le=\"+Inf\"} ${entry.count}`);\n const lbl = key ? `{${key}}` : '';\n lines.push(`${this.name}_sum${lbl} ${entry.sum}`);\n lines.push(`${this.name}_count${lbl} ${entry.count}`);\n }\n }\n return lines.join('\\n');\n }\n}\n\nexport class Gauge {\n readonly name: string;\n readonly help: string;\n private values = new Map<string, number>();\n\n constructor(name: string, help: string) {\n this.name = name;\n this.help = help;\n }\n\n set(value: number, labels?: Labels): void {\n this.values.set(labelsKey(labels), value);\n }\n\n inc(labels?: Labels, amount = 1): void {\n const key = labelsKey(labels);\n this.values.set(key, (this.values.get(key) || 0) + amount);\n }\n\n dec(labels?: Labels, amount = 1): void {\n const key = labelsKey(labels);\n this.values.set(key, (this.values.get(key) || 0) - amount);\n }\n\n get(labels?: Labels): number {\n return this.values.get(labelsKey(labels)) || 0;\n }\n\n serialize(): string {\n const lines: string[] = [\n `# HELP ${this.name} ${this.help}`,\n `# TYPE ${this.name} gauge`,\n ];\n if (this.values.size === 0) {\n lines.push(`${this.name} 0`);\n } else {\n for (const [key, val] of this.values) {\n const lbl = key ? `{${key}}` : '';\n lines.push(`${this.name}${lbl} ${val}`);\n }\n }\n return lines.join('\\n');\n }\n}\n\n// ── Pre-defined TITAN Metrics ────────────────────────────────────────\n\nexport const titanRequestsTotal = new Counter(\n 'titan_requests_total',\n 'Total number of requests handled',\n);\n\nexport const titanRequestDuration = new Histogram(\n 'titan_request_duration_seconds',\n 'Request duration in seconds',\n);\n\nexport const titanTokensTotal = new Counter(\n 'titan_tokens_total',\n 'Total tokens consumed',\n);\n\nexport const titanErrorsTotal = new Counter(\n 'titan_errors_total',\n 'Total errors encountered',\n);\n\nexport const titanActiveSessions = new Gauge(\n 'titan_active_sessions',\n 'Number of currently active sessions',\n);\n\nexport const titanToolCallsTotal = new Counter(\n 'titan_tool_calls_total',\n 'Total tool invocations',\n);\n\nexport const titanModelRequestsTotal = new Counter(\n 'titan_model_requests_total',\n 'Total model requests by model and provider',\n);\n\n/**\n * Eval-suite pass rate, 0–100, labelled by suite name. Updated by the\n * /api/eval/run endpoint after each run completes. Lets ops graph\n * regressions over time and alert when a suite drops below threshold.\n *\n * Use the helper `recordEvalSuiteResult(suite, passed, total)` instead of\n * touching this gauge directly so the rate calc + zero-total guard stay\n * in one place.\n */\nexport const titanEvalPassRate = new Gauge(\n 'titan_eval_pass_rate',\n 'Pass rate (0-100) of the most recent eval suite run, labelled by suite',\n);\n\n/** Total eval cases executed, labelled by suite. Counter so a graph\n * shows whether the suite is actually being exercised. */\nexport const titanEvalCasesTotal = new Counter(\n 'titan_eval_cases_total',\n 'Total eval cases executed, by suite and outcome',\n);\n\n/**\n * Record the outcome of an eval suite run on the metrics gauges + counter.\n * Safe to call with `total=0` (gauge stays at 0, no divide-by-zero).\n */\nexport function recordEvalSuiteResult(suite: string, passed: number, total: number): void {\n const rate = total > 0 ? Math.round((passed / total) * 100) : 0;\n titanEvalPassRate.set(rate, { suite });\n titanEvalCasesTotal.increment({ suite, outcome: 'passed' }, passed);\n titanEvalCasesTotal.increment({ suite, outcome: 'failed' }, Math.max(0, total - passed));\n}\n\n// ── Registry & Serialization ─────────────────────────────────────────\n\nconst allMetrics = [\n titanRequestsTotal,\n titanRequestDuration,\n titanTokensTotal,\n titanErrorsTotal,\n titanActiveSessions,\n titanToolCallsTotal,\n titanModelRequestsTotal,\n titanEvalPassRate,\n titanEvalCasesTotal,\n];\n\nexport function serializePrometheus(): string {\n return allMetrics.map(m => m.serialize()).join('\\n\\n') + '\\n';\n}\n\n/** JSON summary for the dashboard telemetry panel */\nexport function getMetricsSummary(): {\n totalRequests: number;\n avgLatencyMs: number;\n topTools: Array<{ tool: string; count: number }>;\n errorRate: number;\n totalErrors: number;\n /**\n * Token counts. The dashboard displays `.total`; `.prompt` + `.completion`\n * are kept for per-bucket breakdowns and Prometheus label parity.\n */\n totalTokens: { prompt: number; completion: number; total: number };\n} {\n // Total requests\n let totalRequests = 0;\n for (const entry of titanRequestsTotal.getAll()) {\n totalRequests += entry.value;\n }\n\n // Average latency\n const duration = titanRequestDuration.get();\n const avgLatencyMs = duration.count > 0 ? (duration.sum / duration.count) * 1000 : 0;\n\n // Top 5 tools by usage\n const toolEntries = titanToolCallsTotal.getAll()\n .map(e => ({ tool: e.labels['tool'] || 'unknown', count: e.value }))\n .sort((a, b) => b.count - a.count)\n .slice(0, 5);\n\n // Error rate\n let totalErrors = 0;\n for (const entry of titanErrorsTotal.getAll()) {\n totalErrors += entry.value;\n }\n const errorRate = totalRequests > 0 ? totalErrors / totalRequests : 0;\n\n // Tokens\n const promptTokens = titanTokensTotal.get({ type: 'prompt' });\n const completionTokens = titanTokensTotal.get({ type: 'completion' });\n\n return {\n totalRequests,\n avgLatencyMs: Math.round(avgLatencyMs * 100) / 100,\n topTools: toolEntries,\n errorRate: Math.round(errorRate * 10000) / 10000,\n totalErrors,\n totalTokens: { prompt: promptTokens, completion: completionTokens, total: promptTokens + completionTokens },\n };\n}\n"],"mappings":";AASA,SAAS,UAAU,QAAyB;AAC1C,MAAI,CAAC,UAAU,OAAO,KAAK,MAAM,EAAE,WAAW,EAAG,QAAO;AACxD,SAAO,OAAO,QAAQ,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,EAChE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,GAAG;AAC5C;AAEO,MAAM,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,EACD,SAAS,oBAAI,IAAoB;AAAA,EAEzC,YAAY,MAAc,MAAc;AACtC,SAAK,OAAO;AACZ,SAAK,OAAO;AAAA,EACd;AAAA,EAEA,UAAU,QAAiB,SAAS,GAAS;AAC3C,UAAM,MAAM,UAAU,MAAM;AAC5B,SAAK,OAAO,IAAI,MAAM,KAAK,OAAO,IAAI,GAAG,KAAK,KAAK,MAAM;AAAA,EAC3D;AAAA,EAEA,IAAI,QAAyB;AAC3B,WAAO,KAAK,OAAO,IAAI,UAAU,MAAM,CAAC,KAAK;AAAA,EAC/C;AAAA,EAEA,YAAoB;AAClB,UAAM,QAAkB;AAAA,MACtB,UAAU,KAAK,IAAI,IAAI,KAAK,IAAI;AAAA,MAChC,UAAU,KAAK,IAAI;AAAA,IACrB;AACA,QAAI,KAAK,OAAO,SAAS,GAAG;AAC1B,YAAM,KAAK,GAAG,KAAK,IAAI,IAAI;AAAA,IAC7B,OAAO;AACL,iBAAW,CAAC,KAAK,GAAG,KAAK,KAAK,QAAQ;AACpC,cAAM,MAAM,MAAM,IAAI,GAAG,MAAM;AAC/B,cAAM,KAAK,GAAG,KAAK,IAAI,GAAG,GAAG,IAAI,GAAG,EAAE;AAAA,MACxC;AAAA,IACF;AACA,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AAAA;AAAA,EAGA,SAAmD;AACjD,UAAM,SAAmD,CAAC;AAC1D,eAAW,CAAC,KAAK,KAAK,KAAK,KAAK,QAAQ;AACtC,YAAM,SAAiB,CAAC;AACxB,UAAI,KAAK;AACP,mBAAW,QAAQ,IAAI,MAAM,GAAG,GAAG;AACjC,gBAAM,CAAC,GAAG,CAAC,IAAI,KAAK,MAAM,GAAG;AAC7B,iBAAO,CAAC,IAAI,EAAE,QAAQ,MAAM,EAAE;AAAA,QAChC;AAAA,MACF;AACA,aAAO,KAAK,EAAE,QAAQ,MAAM,CAAC;AAAA,IAC/B;AACA,WAAO;AAAA,EACT;AACF;AAEA,MAAM,kBAAkB,CAAC,MAAM,MAAM,KAAK,MAAM,KAAK,GAAG,KAAK,GAAG,EAAE;AAE3D,MAAM,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAED,OAAO,oBAAI,IAAoE;AAAA,EAEvF,YAAY,MAAc,MAAc,UAAU,iBAAiB;AACjE,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,SAAK,UAAU,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AAAA,EAClD;AAAA,EAEA,QAAQ,OAAe,QAAuB;AAC5C,UAAM,MAAM,UAAU,MAAM;AAC5B,QAAI,QAAQ,KAAK,KAAK,IAAI,GAAG;AAC7B,QAAI,CAAC,OAAO;AACV,cAAQ,EAAE,cAAc,IAAI,MAAM,KAAK,QAAQ,MAAM,EAAE,KAAK,CAAC,GAAG,KAAK,GAAG,OAAO,EAAE;AACjF,WAAK,KAAK,IAAI,KAAK,KAAK;AAAA,IAC1B;AACA,UAAM,OAAO;AACb,UAAM;AACN,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,QAAQ,KAAK;AAC5C,UAAI,SAAS,KAAK,QAAQ,CAAC,GAAG;AAC5B,cAAM,aAAa,CAAC;AACpB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,IAAI,QAAkF;AACpF,UAAM,MAAM,UAAU,MAAM;AAC5B,UAAM,QAAQ,KAAK,KAAK,IAAI,GAAG;AAC/B,QAAI,CAAC,MAAO,QAAO,EAAE,KAAK,GAAG,OAAO,GAAG,SAAS,CAAC,EAAE;AACnD,UAAM,UAAkC,CAAC;AACzC,QAAI,aAAa;AACjB,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,QAAQ,KAAK;AAC5C,oBAAc,MAAM,aAAa,CAAC;AAClC,cAAQ,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI;AAAA,IACrC;AACA,YAAQ,MAAM,IAAI,MAAM;AACxB,WAAO,EAAE,KAAK,MAAM,KAAK,OAAO,MAAM,OAAO,QAAQ;AAAA,EACvD;AAAA,EAEA,YAAoB;AAClB,UAAM,QAAkB;AAAA,MACtB,UAAU,KAAK,IAAI,IAAI,KAAK,IAAI;AAAA,MAChC,UAAU,KAAK,IAAI;AAAA,IACrB;AACA,QAAI,KAAK,KAAK,SAAS,GAAG;AAExB,iBAAW,KAAK,KAAK,SAAS;AAC5B,cAAM,KAAK,GAAG,KAAK,IAAI,eAAe,CAAC,MAAM;AAAA,MAC/C;AACA,YAAM,KAAK,GAAG,KAAK,IAAI,sBAAsB;AAC7C,YAAM,KAAK,GAAG,KAAK,IAAI,QAAQ;AAC/B,YAAM,KAAK,GAAG,KAAK,IAAI,UAAU;AAAA,IACnC,OAAO;AACL,iBAAW,CAAC,KAAK,KAAK,KAAK,KAAK,MAAM;AACpC,cAAM,aAAa,MAAM,GAAG,GAAG,MAAM;AACrC,YAAI,aAAa;AACjB,iBAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,QAAQ,KAAK;AAC5C,wBAAc,MAAM,aAAa,CAAC;AAClC,gBAAM,KAAK,GAAG,KAAK,IAAI,WAAW,UAAU,OAAO,KAAK,QAAQ,CAAC,CAAC,MAAM,UAAU,EAAE;AAAA,QACtF;AACA,cAAM,KAAK,GAAG,KAAK,IAAI,WAAW,UAAU,cAAc,MAAM,KAAK,EAAE;AACvE,cAAM,MAAM,MAAM,IAAI,GAAG,MAAM;AAC/B,cAAM,KAAK,GAAG,KAAK,IAAI,OAAO,GAAG,IAAI,MAAM,GAAG,EAAE;AAChD,cAAM,KAAK,GAAG,KAAK,IAAI,SAAS,GAAG,IAAI,MAAM,KAAK,EAAE;AAAA,MACtD;AAAA,IACF;AACA,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AACF;AAEO,MAAM,MAAM;AAAA,EACR;AAAA,EACA;AAAA,EACD,SAAS,oBAAI,IAAoB;AAAA,EAEzC,YAAY,MAAc,MAAc;AACtC,SAAK,OAAO;AACZ,SAAK,OAAO;AAAA,EACd;AAAA,EAEA,IAAI,OAAe,QAAuB;AACxC,SAAK,OAAO,IAAI,UAAU,MAAM,GAAG,KAAK;AAAA,EAC1C;AAAA,EAEA,IAAI,QAAiB,SAAS,GAAS;AACrC,UAAM,MAAM,UAAU,MAAM;AAC5B,SAAK,OAAO,IAAI,MAAM,KAAK,OAAO,IAAI,GAAG,KAAK,KAAK,MAAM;AAAA,EAC3D;AAAA,EAEA,IAAI,QAAiB,SAAS,GAAS;AACrC,UAAM,MAAM,UAAU,MAAM;AAC5B,SAAK,OAAO,IAAI,MAAM,KAAK,OAAO,IAAI,GAAG,KAAK,KAAK,MAAM;AAAA,EAC3D;AAAA,EAEA,IAAI,QAAyB;AAC3B,WAAO,KAAK,OAAO,IAAI,UAAU,MAAM,CAAC,KAAK;AAAA,EAC/C;AAAA,EAEA,YAAoB;AAClB,UAAM,QAAkB;AAAA,MACtB,UAAU,KAAK,IAAI,IAAI,KAAK,IAAI;AAAA,MAChC,UAAU,KAAK,IAAI;AAAA,IACrB;AACA,QAAI,KAAK,OAAO,SAAS,GAAG;AAC1B,YAAM,KAAK,GAAG,KAAK,IAAI,IAAI;AAAA,IAC7B,OAAO;AACL,iBAAW,CAAC,KAAK,GAAG,KAAK,KAAK,QAAQ;AACpC,cAAM,MAAM,MAAM,IAAI,GAAG,MAAM;AAC/B,cAAM,KAAK,GAAG,KAAK,IAAI,GAAG,GAAG,IAAI,GAAG,EAAE;AAAA,MACxC;AAAA,IACF;AACA,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AACF;AAIO,MAAM,qBAAqB,IAAI;AAAA,EACpC;AAAA,EACA;AACF;AAEO,MAAM,uBAAuB,IAAI;AAAA,EACtC;AAAA,EACA;AACF;AAEO,MAAM,mBAAmB,IAAI;AAAA,EAClC;AAAA,EACA;AACF;AAEO,MAAM,mBAAmB,IAAI;AAAA,EAClC;AAAA,EACA;AACF;AAEO,MAAM,sBAAsB,IAAI;AAAA,EACrC;AAAA,EACA;AACF;AAEO,MAAM,sBAAsB,IAAI;AAAA,EACrC;AAAA,EACA;AACF;AAEO,MAAM,0BAA0B,IAAI;AAAA,EACzC;AAAA,EACA;AACF;AAWO,MAAM,oBAAoB,IAAI;AAAA,EACnC;AAAA,EACA;AACF;AAIO,MAAM,sBAAsB,IAAI;AAAA,EACrC;AAAA,EACA;AACF;AAMO,SAAS,sBAAsB,OAAe,QAAgB,OAAqB;AACxF,QAAM,OAAO,QAAQ,IAAI,KAAK,MAAO,SAAS,QAAS,GAAG,IAAI;AAC9D,oBAAkB,IAAI,MAAM,EAAE,MAAM,CAAC;AACrC,sBAAoB,UAAU,EAAE,OAAO,SAAS,SAAS,GAAG,MAAM;AAClE,sBAAoB,UAAU,EAAE,OAAO,SAAS,SAAS,GAAG,KAAK,IAAI,GAAG,QAAQ,MAAM,CAAC;AACzF;AAIA,MAAM,aAAa;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,SAAS,sBAA8B;AAC5C,SAAO,WAAW,IAAI,OAAK,EAAE,UAAU,CAAC,EAAE,KAAK,MAAM,IAAI;AAC3D;AAGO,SAAS,oBAWd;AAEA,MAAI,gBAAgB;AACpB,aAAW,SAAS,mBAAmB,OAAO,GAAG;AAC/C,qBAAiB,MAAM;AAAA,EACzB;AAGA,QAAM,WAAW,qBAAqB,IAAI;AAC1C,QAAM,eAAe,SAAS,QAAQ,IAAK,SAAS,MAAM,SAAS,QAAS,MAAO;AAGnF,QAAM,cAAc,oBAAoB,OAAO,EAC5C,IAAI,QAAM,EAAE,MAAM,EAAE,OAAO,MAAM,KAAK,WAAW,OAAO,EAAE,MAAM,EAAE,EAClE,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,EAChC,MAAM,GAAG,CAAC;AAGb,MAAI,cAAc;AAClB,aAAW,SAAS,iBAAiB,OAAO,GAAG;AAC7C,mBAAe,MAAM;AAAA,EACvB;AACA,QAAM,YAAY,gBAAgB,IAAI,cAAc,gBAAgB;AAGpE,QAAM,eAAe,iBAAiB,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5D,QAAM,mBAAmB,iBAAiB,IAAI,EAAE,MAAM,aAAa,CAAC;AAEpE,SAAO;AAAA,IACL;AAAA,IACA,cAAc,KAAK,MAAM,eAAe,GAAG,IAAI;AAAA,IAC/C,UAAU;AAAA,IACV,WAAW,KAAK,MAAM,YAAY,GAAK,IAAI;AAAA,IAC3C;AAAA,IACA,aAAa,EAAE,QAAQ,cAAc,YAAY,kBAAkB,OAAO,eAAe,iBAAiB;AAAA,EAC5G;AACF;","names":[]}
@@ -45,7 +45,7 @@ import { TITAN_VERSION, TITAN_NAME, TITAN_LOGS_DIR, TITAN_HOME } from "../utils/
45
45
  import { collectSystemProfile, recordStartupAnalytics, startHeartbeatAnalytics } from "../analytics/collector.js";
46
46
  import { getUpdateInfo } from "../utils/updater.js";
47
47
  import { getMissionControlHTML } from "./dashboard.js";
48
- import { serializePrometheus, getMetricsSummary, titanRequestsTotal, titanRequestDuration, titanErrorsTotal, titanActiveSessions, titanToolCallsTotal, titanTokensTotal, titanModelRequestsTotal } from "./metrics.js";
48
+ import { serializePrometheus, getMetricsSummary, titanRequestsTotal, titanRequestDuration, titanErrorsTotal, titanActiveSessions, titanToolCallsTotal, titanTokensTotal, titanModelRequestsTotal, recordEvalSuiteResult } from "./metrics.js";
49
49
  import { initSlashCommands, handleSlashCommand } from "./slashCommands.js";
50
50
  import { initMcpServers, listMcpServers, addMcpServer, removeMcpServer, setMcpServerEnabled, getMcpStatus, BUILTIN_PRESETS } from "../mcp/registry.js";
51
51
  import { connectMcpServer, testMcpServer } from "../mcp/client.js";
@@ -2354,6 +2354,10 @@ _____widget
2354
2354
  return;
2355
2355
  }
2356
2356
  const result = await runEvalSuite(suite, cases, agentCall);
2357
+ try {
2358
+ recordEvalSuiteResult(suite, result.passed, result.total);
2359
+ } catch {
2360
+ }
2357
2361
  res.json(result);
2358
2362
  } catch (e) {
2359
2363
  logger.error(COMPONENT, `Endpoint error: ${e.message}`);