morpheus-cli 0.9.40 → 0.9.50

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 (54) hide show
  1. package/dist/channels/discord.js +1 -1
  2. package/dist/channels/telegram.js +1 -1
  3. package/dist/config/manager.js +3 -3
  4. package/dist/config/schemas.js +2 -2
  5. package/dist/runtime/__tests__/manual_start_verify.js +1 -1
  6. package/dist/runtime/__tests__/telephonist-tts.test.js +2 -2
  7. package/dist/runtime/hot-reload.js +5 -0
  8. package/dist/runtime/memory/sqlite.js +20 -5
  9. package/dist/runtime/migration.js +45 -0
  10. package/dist/runtime/oracle.js +3 -0
  11. package/dist/runtime/subagents/apoc.js +2 -2
  12. package/dist/runtime/subagents/link/link.js +2 -2
  13. package/dist/runtime/subagents/neo.js +5 -3
  14. package/dist/runtime/subagents/registry.js +8 -8
  15. package/dist/runtime/subagents/trinity/trinity.js +2 -2
  16. package/dist/runtime/subagents/utils.js +2 -0
  17. package/dist/runtime/telephonist.js +6 -6
  18. package/dist/runtime/tools/factory.js +50 -34
  19. package/dist/types/config.js +2 -2
  20. package/dist/ui/assets/{AuditDashboard-EvtKjy5H.js → AuditDashboard-CPzQrzFj.js} +1 -1
  21. package/dist/ui/assets/{Chat-yptierPt.js → Chat-Dp4qy6Gs.js} +4 -4
  22. package/dist/ui/assets/{Chronos-BA77MYbp.js → Chronos-CyhR9ccX.js} +1 -1
  23. package/dist/ui/assets/{ConfirmationModal-NOZr-ipQ.js → ConfirmationModal-CNhiVVl3.js} +1 -1
  24. package/dist/ui/assets/{Dashboard-ly1MJiB4.js → Dashboard-DkNBsaWw.js} +1 -1
  25. package/dist/ui/assets/{DeleteConfirmationModal-2HMraacH.js → DeleteConfirmationModal-Dy9tnt_b.js} +1 -1
  26. package/dist/ui/assets/{Documents-C31fAm0Z.js → Documents-DRrqTxAm.js} +1 -1
  27. package/dist/ui/assets/{Logs-BiajoLAB.js → Logs-BQ4f2Gfo.js} +1 -1
  28. package/dist/ui/assets/{MCPManager-DS9jfiZT.js → MCPManager-BWar71tN.js} +1 -1
  29. package/dist/ui/assets/{ModelPresets-CxhKcalw.js → ModelPresets-CPKQqVTG.js} +1 -1
  30. package/dist/ui/assets/{ModelPricing-CN8flHnP.js → ModelPricing-DWP3iAO7.js} +1 -1
  31. package/dist/ui/assets/{Notifications-BfP1_CM3.js → Notifications-BYx4ua0g.js} +1 -1
  32. package/dist/ui/assets/{SatiMemories-Bk4_ubo7.js → SatiMemories-BpHdwM0A.js} +1 -1
  33. package/dist/ui/assets/{SessionAudit-D3E6QSQw.js → SessionAudit-CCbPOKy9.js} +1 -1
  34. package/dist/ui/assets/{Settings-3VBK8muv.js → Settings-B5InwiHP.js} +3 -3
  35. package/dist/ui/assets/{Skills-Dp0_GwiW.js → Skills-DtGzD8Qw.js} +1 -1
  36. package/dist/ui/assets/{Smiths-COTgI2R4.js → Smiths-CNtqkAFS.js} +1 -1
  37. package/dist/ui/assets/{Tasks-COe4lIJ7.js → Tasks-BTVcCY9w.js} +1 -1
  38. package/dist/ui/assets/{TrinityDatabases-BEU4mmyW.js → TrinityDatabases-1JLYBExa.js} +1 -1
  39. package/dist/ui/assets/{UsageStats-BTmDeG2V.js → UsageStats-DLm3pFj2.js} +1 -1
  40. package/dist/ui/assets/{WebhookManager-FQVyKyW-.js → WebhookManager-Cp0c6m9t.js} +1 -1
  41. package/dist/ui/assets/{agents-B6e9N0QI.js → agents-D54KZHoX.js} +1 -1
  42. package/dist/ui/assets/{audit-giQG2WRk.js → audit-C3PRWFnZ.js} +1 -1
  43. package/dist/ui/assets/{chronos-sweaRcNj.js → chronos-BDSY9T_M.js} +1 -1
  44. package/dist/ui/assets/{config-CbUdj76n.js → config-DZGSjv5e.js} +1 -1
  45. package/dist/ui/assets/{index-CRPT77Yo.css → index-Bn2nGQ5z.css} +1 -1
  46. package/dist/ui/assets/{index-yu2c4ry1.js → index-C_cF6S2J.js} +2 -2
  47. package/dist/ui/assets/{mcp-v64BBpUk.js → mcp-Bho7XEgS.js} +1 -1
  48. package/dist/ui/assets/{modelPresets-BaNh-gxn.js → modelPresets-DP4danw2.js} +1 -1
  49. package/dist/ui/assets/{skills-ClRXBlVt.js → skills-CaMm4Xe8.js} +1 -1
  50. package/dist/ui/assets/{stats-nI-89hEX.js → stats-BDnmqrhn.js} +1 -1
  51. package/dist/ui/assets/{useCurrency-D5An8I2f.js → useCurrency-Bkd-Hd8n.js} +1 -1
  52. package/dist/ui/index.html +2 -2
  53. package/dist/ui/sw.js +1 -1
  54. package/package.json +1 -1
@@ -331,7 +331,7 @@ export class DiscordAdapter {
331
331
  this.display.startActivity('telephonist', 'Synthesizing TTS...');
332
332
  const ttsApiKey = getUsableApiKey(ttsConfig.apiKey) ||
333
333
  getUsableApiKey(config.audio.apiKey) ||
334
- (config.llm.provider === (ttsConfig.provider === 'google' ? 'gemini' : ttsConfig.provider)
334
+ (config.llm.provider === ttsConfig.provider
335
335
  ? getUsableApiKey(config.llm.api_key) : undefined);
336
336
  const ttsResult = await this.ttsTelephonist.synthesize(response, ttsApiKey || '', ttsConfig.voice, ttsConfig.style_prompt);
337
337
  ttsFilePath = ttsResult.filePath;
@@ -1921,7 +1921,7 @@ How can I assist you today?`;
1921
1921
  this.display.startActivity('telephonist', 'Synthesizing TTS...');
1922
1922
  const ttsApiKey = getUsableApiKey(ttsConfig.apiKey) ||
1923
1923
  getUsableApiKey(config.audio.apiKey) ||
1924
- (config.llm.provider === (ttsConfig.provider === 'google' ? 'gemini' : ttsConfig.provider)
1924
+ (config.llm.provider === ttsConfig.provider
1925
1925
  ? getUsableApiKey(config.llm.api_key) : undefined);
1926
1926
  const ttsResult = await this.ttsTelephonist.synthesize(response, ttsApiKey || '', ttsConfig.voice, ttsConfig.style_prompt);
1927
1927
  ttsFilePath = ttsResult.filePath;
@@ -282,13 +282,13 @@ export class ConfigManager {
282
282
  }
283
283
  // Apply precedence to audio config
284
284
  const audioProvider = resolveString('MORPHEUS_AUDIO_PROVIDER', config.audio.provider, DEFAULT_CONFIG.audio.provider);
285
- // AudioProvider uses 'google' but resolveApiKey expects LLMProvider which uses 'gemini'
286
- const audioProviderForKey = (audioProvider === 'google' ? 'gemini' : audioProvider);
285
+ // AudioProvider uses 'gemini' which maps to LLMProvider 'gemini' (already compatible)
286
+ const audioProviderForKey = audioProvider;
287
287
  // TTS config
288
288
  const ttsDefaults = DEFAULT_CONFIG.audio.tts;
289
289
  const ttsCfg = config.audio.tts;
290
290
  const ttsProvider = resolveString('MORPHEUS_AUDIO_TTS_PROVIDER', ttsCfg?.provider, ttsDefaults.provider);
291
- const ttsProviderForKey = (ttsProvider === 'google' ? 'gemini' : ttsProvider);
291
+ const ttsProviderForKey = ttsProvider;
292
292
  const ttsConfig = {
293
293
  enabled: resolveBoolean('MORPHEUS_AUDIO_TTS_ENABLED', ttsCfg?.enabled, ttsDefaults.enabled),
294
294
  provider: ttsProvider,
@@ -2,14 +2,14 @@ import { z } from 'zod';
2
2
  import { DEFAULT_CONFIG } from '../types/config.js';
3
3
  export const TtsConfigSchema = z.object({
4
4
  enabled: z.boolean().default(false),
5
- provider: z.enum(['openai', 'google']).default('google'),
5
+ provider: z.enum(['openai', 'gemini']).default('gemini'),
6
6
  model: z.string().min(1).default('gemini-2.5-flash-preview-tts'),
7
7
  voice: z.string().min(1).default('Kore'),
8
8
  apiKey: z.string().optional(),
9
9
  style_prompt: z.string().optional(),
10
10
  });
11
11
  export const AudioConfigSchema = z.object({
12
- provider: z.enum(['google', 'openai', 'openrouter', 'ollama']).default(DEFAULT_CONFIG.audio.provider),
12
+ provider: z.enum(['gemini', 'openai', 'openrouter', 'ollama']).default(DEFAULT_CONFIG.audio.provider),
13
13
  model: z.string().min(1).default(DEFAULT_CONFIG.audio.model),
14
14
  enabled: z.boolean().default(DEFAULT_CONFIG.audio.enabled),
15
15
  apiKey: z.string().optional(),
@@ -12,7 +12,7 @@ const mockConfig = {
12
12
  ui: { enabled: false, port: 3333 },
13
13
  logging: { enabled: false, level: 'info', retention: '1d' },
14
14
  audio: {
15
- provider: 'google',
15
+ provider: 'gemini',
16
16
  model: 'gemini-2.5-flash-lite',
17
17
  enabled: false,
18
18
  maxDurationSeconds: 60,
@@ -12,10 +12,10 @@ describe('createTtsTelephonist', () => {
12
12
  expect(telephonist).toBeDefined();
13
13
  expect(typeof telephonist.synthesize).toBe('function');
14
14
  });
15
- it('returns an instance with synthesize() for google provider', () => {
15
+ it('returns an instance with synthesize() for gemini provider', () => {
16
16
  const telephonist = createTtsTelephonist({
17
17
  enabled: true,
18
- provider: 'google',
18
+ provider: 'gemini',
19
19
  model: 'gemini-2.5-flash',
20
20
  voice: 'Kore',
21
21
  });
@@ -9,6 +9,7 @@ import { ConfigManager } from '../config/manager.js';
9
9
  import { DisplayManager } from './display.js';
10
10
  import { SubagentRegistry } from './subagents/registry.js';
11
11
  import { SkillRegistry } from './skills/index.js';
12
+ import { SQLiteChatMessageHistory } from './memory/sqlite.js';
12
13
  let currentOracle = null;
13
14
  /**
14
15
  * Register the current Oracle instance for hot-reload.
@@ -51,6 +52,10 @@ export async function hotReloadConfig() {
51
52
  const agentNames = SubagentRegistry.getAll().map(r => r.label);
52
53
  reinitialized.push(...agentNames);
53
54
  display.log(`Subagents reloaded: ${agentNames.join(', ')}`, { source: 'HotReload', level: 'info' });
55
+ // 4. Clear message cache to prevent stale tool_calls causing Gemini 400 errors
56
+ // This ensures the next chat() call re-fetches from DB with proper sanitization
57
+ SQLiteChatMessageHistory.clearCache();
58
+ display.log('Message cache cleared', { source: 'HotReload', level: 'info' });
54
59
  return {
55
60
  success: true,
56
61
  reinitialized,
@@ -39,6 +39,10 @@ export class SQLiteChatMessageHistory extends BaseListChatMessageHistory {
39
39
  static invalidateCacheForSession(sessionId) {
40
40
  SQLiteChatMessageHistory._cache.delete(sessionId);
41
41
  }
42
+ /** Clear the entire message cache. Called during hot-reload to prevent stale tool_calls. */
43
+ static clearCache() {
44
+ SQLiteChatMessageHistory._cache.clear();
45
+ }
42
46
  /** Prepend new messages (newest-first order) to an existing cache entry. */
43
47
  static _appendToCache(sessionId, newMessages) {
44
48
  if (!sessionId || newMessages.length === 0)
@@ -201,11 +205,11 @@ export class SQLiteChatMessageHistory extends BaseListChatMessageHistory {
201
205
  ('openai', 'gpt-3.5-turbo', 0.5, 1.5),
202
206
  ('openai', 'o1', 15.0, 60.0),
203
207
  ('openai', 'o1-mini', 3.0, 12.0),
204
- ('google', 'gemini-2.5-flash', 0.15, 0.6),
205
- ('google', 'gemini-2.5-flash-lite', 0.075, 0.3),
206
- ('google', 'gemini-2.0-flash', 0.1, 0.4),
207
- ('google', 'gemini-1.5-pro', 1.25, 5.0),
208
- ('google', 'gemini-1.5-flash', 0.075, 0.3);
208
+ ('gemini', 'gemini-2.5-flash', 0.15, 0.6),
209
+ ('gemini', 'gemini-2.5-flash-lite', 0.075, 0.3),
210
+ ('gemini', 'gemini-2.0-flash', 0.1, 0.4),
211
+ ('gemini', 'gemini-1.5-pro', 1.25, 5.0),
212
+ ('gemini', 'gemini-1.5-flash', 0.075, 0.3);
209
213
 
210
214
  CREATE TABLE IF NOT EXISTS model_presets (
211
215
  id TEXT PRIMARY KEY,
@@ -281,6 +285,17 @@ export class SQLiteChatMessageHistory extends BaseListChatMessageHistory {
281
285
  catch (error) {
282
286
  console.warn(`[SQLite] model_pricing migration failed: ${error}`);
283
287
  }
288
+ // Migration: rename 'google' provider to 'gemini' for consistency
289
+ // This ensures existing model_pricing records work with the unified 'gemini' provider
290
+ try {
291
+ const result = this.db.prepare("UPDATE model_pricing SET provider = 'gemini' WHERE provider = 'google'").run();
292
+ if (result.changes > 0) {
293
+ console.log(`[SQLite] Migrated ${result.changes} model_pricing records from 'google' to 'gemini'`);
294
+ }
295
+ }
296
+ catch (error) {
297
+ console.warn(`[SQLite] google->gemini migration failed: ${error}`);
298
+ }
284
299
  // Ensure model_presets table exists for databases created before this feature
285
300
  try {
286
301
  this.db.exec(`
@@ -29,6 +29,8 @@ export async function migrateConfigFile() {
29
29
  await migrateContextWindow();
30
30
  // Migrate santi -> sati
31
31
  await migrateSantiToSati();
32
+ // Migrate google -> gemini in audio and tts providers
33
+ await migrateGoogleToGemini();
32
34
  }
33
35
  /**
34
36
  * Migrates memory.limit to llm.context_window
@@ -118,3 +120,46 @@ async function migrateSantiToSati() {
118
120
  });
119
121
  }
120
122
  }
123
+ /**
124
+ * Migrates audio.provider and audio.tts.provider from 'google' to 'gemini'
125
+ * Ensures consistency across the system (LLMs and audio use 'gemini' as provider)
126
+ */
127
+ async function migrateGoogleToGemini() {
128
+ const display = DisplayManager.getInstance();
129
+ const configPath = PATHS.config;
130
+ try {
131
+ if (!await fs.pathExists(configPath)) {
132
+ return;
133
+ }
134
+ const configContent = await fs.readFile(configPath, 'utf8');
135
+ const config = yaml.load(configContent);
136
+ // Check if migration is needed
137
+ const needsMigration = config?.audio?.provider === 'google' ||
138
+ config?.audio?.tts?.provider === 'google';
139
+ if (!needsMigration) {
140
+ return;
141
+ }
142
+ // Create backup before migration
143
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
144
+ const backupPath = `${configPath}.backup-${timestamp}`;
145
+ await fs.copy(configPath, backupPath);
146
+ display.log(`Created config backup: ${backupPath}`, { source: 'Migration', level: 'info' });
147
+ // Perform migration
148
+ if (config?.audio?.provider === 'google') {
149
+ config.audio.provider = 'gemini';
150
+ }
151
+ if (config?.audio?.tts?.provider === 'google') {
152
+ config.audio.tts.provider = 'gemini';
153
+ }
154
+ // Write migrated config
155
+ const migratedYaml = yaml.dump(config);
156
+ await fs.writeFile(configPath, migratedYaml, 'utf8');
157
+ display.log('Migrated audio providers: google → gemini', { source: 'Migration', level: 'info' });
158
+ }
159
+ catch (error) {
160
+ display.log(`Config migration (google->gemini) failed: ${error.message}`, {
161
+ source: 'Migration',
162
+ level: 'warning'
163
+ });
164
+ }
165
+ }
@@ -765,5 +765,8 @@ Use it to inform your response and tool selection (if needed), but do not assume
765
765
  ]);
766
766
  await SubagentRegistry.reloadAll();
767
767
  this.display.log(`Oracle and subagent tools reloaded`, { source: 'Oracle' });
768
+ // Clear message cache to prevent stale tool_calls from causing Gemini 400 errors
769
+ SQLiteChatMessageHistory.clearCache();
770
+ this.display.log(`Message cache cleared after tool reload`, { source: 'Oracle' });
768
771
  }
769
772
  }
@@ -73,8 +73,8 @@ Use this tool when the user asks for ANY of the following:
73
73
  delegateToolName: 'apoc_delegate', emoji: '🧑‍🔬', color: 'amber',
74
74
  description: 'Filesystem, shell & browser',
75
75
  colorClass: 'text-amber-600 dark:text-amber-400',
76
- bgClass: 'bg-amber-50 dark:bg-amber-900/10',
77
- badgeClass: 'bg-amber-100 text-amber-700 dark:bg-amber-900/40 dark:text-amber-300',
76
+ bgClass: 'bg-amber-50 dark:bg-amber-900/30',
77
+ badgeClass: 'bg-amber-100 text-amber-700 dark:bg-amber-800 dark:text-amber-200',
78
78
  instance: Apoc.instance,
79
79
  hasDynamicDescription: true,
80
80
  isMultiInstance: false,
@@ -64,8 +64,8 @@ export class Link {
64
64
  delegateToolName: 'link_delegate', emoji: '🕵️‍♂️', color: 'indigo',
65
65
  description: 'Document search & RAG',
66
66
  colorClass: 'text-indigo-600 dark:text-indigo-400',
67
- bgClass: 'bg-indigo-50 dark:bg-indigo-900/10',
68
- badgeClass: 'bg-indigo-100 text-indigo-700 dark:bg-indigo-900/40 dark:text-indigo-300',
67
+ bgClass: 'bg-indigo-50 dark:bg-indigo-900/30',
68
+ badgeClass: 'bg-indigo-100 text-indigo-700 dark:bg-indigo-800 dark:text-indigo-200',
69
69
  instance: Link.instance,
70
70
  hasDynamicDescription: true,
71
71
  isMultiInstance: false,
@@ -67,8 +67,8 @@ export class Neo {
67
67
  delegateToolName: 'neo_delegate', emoji: '🥷', color: 'violet',
68
68
  description: 'MCP tool orchestration',
69
69
  colorClass: 'text-violet-600 dark:text-violet-400',
70
- bgClass: 'bg-violet-50 dark:bg-violet-900/10',
71
- badgeClass: 'bg-purple-100 text-purple-700 dark:bg-purple-900/40 dark:text-purple-300',
70
+ bgClass: 'bg-violet-50 dark:bg-violet-900/30',
71
+ badgeClass: 'bg-purple-100 text-purple-700 dark:bg-purple-800 dark:text-purple-200',
72
72
  instance: Neo.instance,
73
73
  hasDynamicDescription: true,
74
74
  isMultiInstance: false,
@@ -161,8 +161,10 @@ ${context ? `Context:\n${context}` : ""}
161
161
  const stepCount = response.messages.filter((m) => m instanceof AIMessage).length;
162
162
  const targetSession = sessionId ?? Neo.currentSessionId ?? "neo";
163
163
  await persistAgentMessage('neo', content, neoConfig, targetSession, rawUsage, durationMs);
164
+ // MCP tools are already audited inline by instrumentMcpTool (with timing + args/result).
165
+ // Only emit audit events here for internal Morpheus tools (not MCP tools).
164
166
  emitToolAuditEvents(response.messages.slice(inputCount), targetSession, 'neo', {
165
- defaultEventType: 'mcp_tool',
167
+ defaultEventType: undefined, // skip MCP tools — audited by instrumentMcpTool
166
168
  internalToolNames: MORPHEUS_TOOL_NAMES,
167
169
  });
168
170
  this.display.log("Neo task completed.", { source: "Neo" });
@@ -8,32 +8,32 @@ export const SYSTEM_AGENTS = [
8
8
  delegateToolName: '', emoji: '🔮', color: 'blue',
9
9
  description: 'Root orchestrator',
10
10
  colorClass: 'text-blue-600 dark:text-blue-400',
11
- bgClass: 'bg-blue-50 dark:bg-blue-900/10',
12
- badgeClass: 'bg-blue-100 text-blue-700 dark:bg-blue-900/40 dark:text-blue-300',
11
+ bgClass: 'bg-blue-50 dark:bg-blue-900/30',
12
+ badgeClass: 'bg-blue-100 text-blue-700 dark:bg-blue-800 dark:text-blue-200',
13
13
  },
14
14
  {
15
15
  agentKey: 'chronos', auditAgent: 'chronos', label: 'Chronos',
16
16
  delegateToolName: '', emoji: '⏰', color: 'orange',
17
17
  description: 'Temporal scheduler',
18
18
  colorClass: 'text-orange-600 dark:text-orange-400',
19
- bgClass: 'bg-orange-50 dark:bg-orange-900/10',
20
- badgeClass: 'bg-orange-100 text-orange-700 dark:bg-orange-900/40 dark:text-orange-300',
19
+ bgClass: 'bg-orange-50 dark:bg-orange-900/30',
20
+ badgeClass: 'bg-orange-100 text-orange-700 dark:bg-orange-800 dark:text-orange-200',
21
21
  },
22
22
  {
23
23
  agentKey: 'sati', auditAgent: 'sati', label: 'Sati',
24
24
  delegateToolName: '', emoji: '🧠', color: 'emerald',
25
25
  description: 'Long-term memory',
26
26
  colorClass: 'text-emerald-600 dark:text-emerald-400',
27
- bgClass: 'bg-emerald-50 dark:bg-emerald-900/10',
28
- badgeClass: 'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/40 dark:text-emerald-300',
27
+ bgClass: 'bg-emerald-50 dark:bg-emerald-900/30',
28
+ badgeClass: 'bg-emerald-100 text-emerald-700 dark:bg-emerald-800 dark:text-emerald-200',
29
29
  },
30
30
  {
31
31
  agentKey: 'telephonist', auditAgent: 'telephonist', label: 'Telephonist',
32
32
  delegateToolName: '', emoji: '📞', color: 'rose',
33
33
  description: 'Audio transcription',
34
34
  colorClass: 'text-rose-600 dark:text-rose-400',
35
- bgClass: 'bg-rose-50 dark:bg-rose-900/10',
36
- badgeClass: 'bg-rose-100 text-rose-700 dark:bg-rose-900/40 dark:text-rose-300',
35
+ bgClass: 'bg-rose-50 dark:bg-rose-900/30',
36
+ badgeClass: 'bg-rose-100 text-rose-700 dark:bg-rose-800 dark:text-rose-200',
37
37
  },
38
38
  ];
39
39
  /**
@@ -58,8 +58,8 @@ export class Trinity {
58
58
  delegateToolName: 'trinity_delegate', emoji: '👩‍💻', color: 'teal',
59
59
  description: 'Database specialist',
60
60
  colorClass: 'text-teal-600 dark:text-teal-400',
61
- bgClass: 'bg-teal-50 dark:bg-teal-900/10',
62
- badgeClass: 'bg-teal-100 text-teal-700 dark:bg-teal-900/40 dark:text-teal-300',
61
+ bgClass: 'bg-teal-50 dark:bg-teal-900/30',
62
+ badgeClass: 'bg-teal-100 text-teal-700 dark:bg-teal-800 dark:text-teal-200',
63
63
  instance: Trinity.instance,
64
64
  hasDynamicDescription: true,
65
65
  isMultiInstance: false,
@@ -55,6 +55,8 @@ export function emitToolAuditEvents(messages, sessionId, agent, opts) {
55
55
  const result = tc.id ? toolResults.get(tc.id) : undefined;
56
56
  const isError = typeof result === 'string' && /^error:/i.test(result.trim());
57
57
  const eventType = internalToolNames?.has(tc.name) ? 'tool_call' : defaultEventType;
58
+ if (!eventType)
59
+ continue; // no event type assigned — caller opted out for this tool
58
60
  const meta = {};
59
61
  if (tc.args && Object.keys(tc.args).length > 0)
60
62
  meta.args = tc.args;
@@ -170,14 +170,14 @@ class OpenRouterTelephonist {
170
170
  * based on the audio provider configuration.
171
171
  *
172
172
  * Supported providers:
173
- * - google: Google Gemini (native audio file upload)
173
+ * - gemini: Google Gemini (native audio file upload)
174
174
  * - openai: OpenAI Whisper API (/audio/transcriptions)
175
175
  * - openrouter: OpenRouter SDK with input_audio (multimodal models)
176
176
  * - ollama: Ollama local Whisper via OpenAI-compatible endpoint
177
177
  */
178
178
  export function createTelephonist(config) {
179
179
  switch (config.provider) {
180
- case 'google':
180
+ case 'gemini':
181
181
  return new GeminiTelephonist(config.model);
182
182
  case 'openai':
183
183
  return new WhisperTelephonist(config.model);
@@ -188,7 +188,7 @@ export function createTelephonist(config) {
188
188
  // Requires a Whisper model loaded: `ollama pull whisper`
189
189
  return new WhisperTelephonist(config.model, (config.base_url || 'http://localhost:11434') + '/v1');
190
190
  default:
191
- throw new Error(`Unsupported audio provider: '${config.provider}'. Supported: google, openai, openrouter, ollama.`);
191
+ throw new Error(`Unsupported audio provider: '${config.provider}'. Supported: gemini, openai, openrouter, ollama.`);
192
192
  }
193
193
  }
194
194
  // ─── TTS Implementations ─────────────────────────────────────────────────────
@@ -334,16 +334,16 @@ class GeminiTtsTelephonist {
334
334
  }
335
335
  /**
336
336
  * Factory that creates an ITelephonist with TTS (synthesize) support.
337
- * Supports providers: openai, google.
337
+ * Supports providers: openai, gemini.
338
338
  */
339
339
  export function createTtsTelephonist(config) {
340
340
  switch (config.provider) {
341
341
  case 'openai':
342
342
  return new OpenAITtsTelephonist(config.model, config.voice);
343
- case 'google':
343
+ case 'gemini':
344
344
  return new GeminiTtsTelephonist(config.model, config.voice);
345
345
  default:
346
- throw new Error(`Unsupported TTS provider: '${config.provider}'. Supported: openai, google.`);
346
+ throw new Error(`Unsupported TTS provider: '${config.provider}'. Supported: openai, gemini.`);
347
347
  }
348
348
  }
349
349
  // ─── Legacy export for backward compatibility ─────────────────────────────────
@@ -3,40 +3,56 @@ import { MCPToolCache } from "./cache.js";
3
3
  import { AuditRepository } from "../audit/repository.js";
4
4
  const display = DisplayManager.getInstance();
5
5
  function instrumentMcpTool(tool, serverName, getSessionId) {
6
- const original = tool._call.bind(tool);
7
- tool._call = async function (input, runManager) {
8
- const startMs = Date.now();
9
- const sessionId = getSessionId() ?? 'unknown';
10
- const toolName = `${serverName}/${tool.name}`;
11
- display.startActivity('neo', `MCP tool: ${tool.name}`);
12
- try {
13
- const result = await original(input, runManager);
14
- AuditRepository.getInstance().insert({
15
- session_id: sessionId,
16
- event_type: 'mcp_tool',
17
- agent: 'neo',
18
- tool_name: toolName,
19
- duration_ms: Date.now() - startMs,
20
- status: 'success',
21
- });
22
- display.endActivity('neo', true);
23
- return result;
24
- }
25
- catch (err) {
26
- display.endActivity('neo', false);
27
- AuditRepository.getInstance().insert({
28
- session_id: sessionId,
29
- event_type: 'mcp_tool',
30
- agent: 'neo',
31
- tool_name: toolName,
32
- duration_ms: Date.now() - startMs,
33
- status: 'error',
34
- metadata: { error: err?.message ?? String(err) },
35
- });
36
- throw err;
37
- }
38
- };
39
- return tool;
6
+ // Use a Proxy instead of mutating the cached tool object.
7
+ // Mutating _call directly on the cached object accumulates wrappers across sessions,
8
+ // causing N audit events per tool call after N Neo invocations.
9
+ const toolName = `${serverName}/${tool.name}`;
10
+ return new Proxy(tool, {
11
+ get(target, prop) {
12
+ if (prop === '_call') {
13
+ return async function (input, runManager) {
14
+ const startMs = Date.now();
15
+ const sessionId = getSessionId() ?? 'unknown';
16
+ display.startActivity('neo', `MCP tool: ${tool.name}`);
17
+ try {
18
+ const result = await target._call(input, runManager);
19
+ const meta = {};
20
+ if (input && Object.keys(input).length > 0)
21
+ meta.args = input;
22
+ if (result !== undefined) {
23
+ const resultStr = typeof result === 'string' ? result : JSON.stringify(result);
24
+ meta.result = resultStr.length > 500 ? resultStr.slice(0, 500) + '…' : resultStr;
25
+ }
26
+ AuditRepository.getInstance().insert({
27
+ session_id: sessionId,
28
+ event_type: 'mcp_tool',
29
+ agent: 'neo',
30
+ tool_name: toolName,
31
+ duration_ms: Date.now() - startMs,
32
+ status: 'success',
33
+ metadata: Object.keys(meta).length > 0 ? meta : undefined,
34
+ });
35
+ display.endActivity('neo', true);
36
+ return result;
37
+ }
38
+ catch (err) {
39
+ display.endActivity('neo', false);
40
+ AuditRepository.getInstance().insert({
41
+ session_id: sessionId,
42
+ event_type: 'mcp_tool',
43
+ agent: 'neo',
44
+ tool_name: toolName,
45
+ duration_ms: Date.now() - startMs,
46
+ status: 'error',
47
+ metadata: { error: err?.message ?? String(err) },
48
+ });
49
+ throw err;
50
+ }
51
+ };
52
+ }
53
+ return target[prop];
54
+ },
55
+ });
40
56
  }
41
57
  export class Construtor {
42
58
  /**
@@ -9,14 +9,14 @@ export const DEFAULT_CONFIG = {
9
9
  retention: '14d',
10
10
  },
11
11
  audio: {
12
- provider: 'google',
12
+ provider: 'gemini',
13
13
  model: 'gemini-2.5-flash-lite',
14
14
  enabled: true,
15
15
  maxDurationSeconds: 300,
16
16
  supportedMimeTypes: ['audio/ogg', 'audio/mp3', 'audio/mpeg', 'audio/wav'],
17
17
  tts: {
18
18
  enabled: false,
19
- provider: 'google',
19
+ provider: 'gemini',
20
20
  model: 'gemini-2.5-flash-preview-tts',
21
21
  voice: 'Kore',
22
22
  },
@@ -1 +1 @@
1
- import{j as e,m as o}from"./vendor-motion-C3CZ8ZlO.js";import{L as E,r as B}from"./vendor-react-DikRIOlj.js";import{a as D}from"./audit-giQG2WRk.js";import{u as R}from"./agents-B6e9N0QI.js";import{u as O}from"./useCurrency-D5An8I2f.js";import{Z as _,Y as F,h as L,i as U,aw as v,J as j,p as N,A as z,g as w,aA as W,l as I,O as S,aB as P,U as A,s as V,an as H}from"./vendor-icons-LSkmAkBj.js";import"./vendor-utils-BIYveU_1.js";import"./index-yu2c4ry1.js";import"./config-CbUdj76n.js";function m(r){return r>=1e6?`${(r/1e6).toFixed(1)}M`:r>=1e3?`${(r/1e3).toFixed(1)}k`:String(r)}function k(r){if(r<1e3)return`${r}ms`;if(r<6e4)return`${(r/1e3).toFixed(1)}s`;const i=Math.floor(r/6e4),l=Math.floor(r%6e4/1e3);return`${i}m ${l}s`}function G(r){return r?new Date(r).toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"}):"—"}function T(r,i){return i?`${Math.round(r/i*100)}%`:"0%"}function J({data:r,fmtCost:i}){const[l,d]=B.useState(null);if(!r.length)return e.jsx("p",{className:"text-xs text-gray-400 dark:text-matrix-secondary/50 py-4",children:"No activity in the last 30 days."});const s=Math.max(...r.map(a=>a.eventCount),1);return e.jsx("div",{className:"flex items-end gap-0.5 h-24 w-full relative",children:r.map((a,g)=>{const y=Math.max(4,Math.round(a.eventCount/s*88)),p=l===g;return e.jsxs("div",{className:"flex-1 flex flex-col items-center justify-end group",onMouseEnter:()=>d(g),onMouseLeave:()=>d(null),children:[p&&e.jsxs("div",{className:"absolute -top-10 left-1/2 -translate-x-1/2 z-10 bg-gray-900 dark:bg-zinc-800 text-white text-[10px] rounded px-2 py-1 whitespace-nowrap pointer-events-none shadow-lg",children:[a.date,": ",a.eventCount," events · ",i(a.estimatedCostUsd)]}),e.jsx("div",{style:{height:y},className:`w-full rounded-t transition-colors ${p?"bg-blue-500 dark:bg-matrix-highlight":"bg-blue-300/70 dark:bg-matrix-highlight/40 group-hover:bg-blue-400 dark:group-hover:bg-matrix-highlight/60"}`})]},a.date)})})}function h({icon:r,label:i,value:l,sub:d,color:s="blue"}){const a={blue:"bg-blue-50 dark:bg-blue-900/20 text-blue-600 dark:text-blue-400 border-blue-200 dark:border-blue-800/40",green:"bg-green-50 dark:bg-green-900/20 text-green-600 dark:text-matrix-highlight border-green-200 dark:border-green-800/40",amber:"bg-amber-50 dark:bg-amber-900/20 text-amber-600 dark:text-amber-400 border-amber-200 dark:border-amber-800/40",purple:"bg-purple-50 dark:bg-purple-900/20 text-purple-600 dark:text-purple-400 border-purple-200 dark:border-purple-800/40",rose:"bg-rose-50 dark:bg-rose-900/20 text-rose-600 dark:text-rose-400 border-rose-200 dark:border-rose-800/40",teal:"bg-teal-50 dark:bg-teal-900/20 text-teal-600 dark:text-teal-400 border-teal-200 dark:border-teal-800/40"};return e.jsxs("div",{className:`rounded-lg border p-4 flex gap-3 items-start ${a[s]}`,children:[e.jsx("div",{className:"mt-0.5 flex-shrink-0",children:r}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("p",{className:"text-xs font-medium opacity-70 uppercase tracking-wider mb-0.5",children:i}),e.jsx("p",{className:"text-xl font-bold font-mono leading-tight",children:l}),d&&e.jsx("div",{className:"text-[11px] opacity-60 mt-0.5 leading-snug",children:d})]})]})}function x({title:r,icon:i,children:l}){return e.jsxs("div",{className:"rounded-lg border border-gray-200 dark:border-matrix-primary overflow-hidden bg-white dark:bg-zinc-900 shadow-sm",children:[e.jsxs("div",{className:"px-4 py-3 bg-gray-50 dark:bg-zinc-900 border-b border-gray-200 dark:border-matrix-primary flex items-center gap-2",children:[e.jsx("span",{className:"text-gray-500 dark:text-matrix-secondary/70",children:i}),e.jsx("h2",{className:"text-sm font-semibold text-gray-700 dark:text-matrix-secondary uppercase tracking-wider",children:r})]}),e.jsx("div",{className:"p-4",children:l})]})}function M({agent:r}){const{getByKey:i}=R(),l=i(r);return e.jsxs("span",{className:`inline-flex items-center gap-1 text-[11px] font-semibold px-1.5 py-0.5 rounded ${l.badgeClass}`,children:[l.emoji," ",r.toUpperCase()]})}function Z({status:r}){const i={active:"bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-matrix-highlight",paused:"bg-gray-100 text-gray-600 dark:bg-zinc-800 dark:text-matrix-secondary",archived:"bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-300",deleted:"bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400",unknown:"bg-gray-100 text-gray-500 dark:bg-zinc-800 dark:text-matrix-secondary/60"};return e.jsx("span",{className:`text-[10px] font-semibold uppercase px-1.5 py-0.5 rounded ${i[r]??i.unknown}`,children:r})}const K={llm_call:e.jsx(v,{size:13}),tool_call:e.jsx(j,{size:13}),mcp_tool:e.jsxs("svg",{width:"13",height:"13",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[e.jsx("path",{d:"M3.49994 11.7501L11.6717 3.57855C12.7762 2.47398 14.5672 2.47398 15.6717 3.57855C16.7762 4.68312 16.7762 6.47398 15.6717 7.57855M15.6717 7.57855L9.49994 13.7501M15.6717 7.57855C16.7762 6.47398 18.5672 6.47398 19.6717 7.57855C20.7762 8.68312 20.7762 10.474 19.6717 11.5785L12.7072 18.543C12.3167 18.9335 12.3167 19.5667 12.7072 19.9572L13.9999 21.2499",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"}),e.jsx("path",{d:"M17.4999 9.74921L11.3282 15.921C10.2237 17.0255 8.43272 17.0255 7.32823 15.921C6.22373 14.8164 6.22373 13.0255 7.32823 11.921L13.4999 5.74939",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})]}),memory_recovery:e.jsx(N,{size:13}),memory_persist:e.jsx(N,{size:13}),telephonist:e.jsx(A,{size:13}),skill_loaded:e.jsx(S,{size:13}),chronos_job:e.jsx(w,{size:13}),task_created:e.jsx(H,{size:13}),task_completed:e.jsx(V,{size:13})},Y={llm_call:"text-blue-500 dark:text-blue-400",tool_call:"text-amber-500 dark:text-amber-400",mcp_tool:"text-purple-500 dark:text-purple-400",memory_recovery:"text-emerald-500 dark:text-emerald-400",memory_persist:"text-violet-500 dark:text-violet-400",telephonist:"text-rose-500 dark:text-rose-400",skill_loaded:"text-teal-500 dark:text-teal-400",chronos_job:"text-orange-500 dark:text-orange-400",task_created:"text-gray-500 dark:text-matrix-secondary",task_completed:"text-green-600 dark:text-matrix-highlight"};function q({eventType:r}){return r==="mcp_tool"?e.jsx("span",{className:"flex-shrink-0 text-purple-500 dark:text-purple-400",children:e.jsxs("svg",{width:"13",height:"13",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[e.jsx("path",{d:"M3.49994 11.7501L11.6717 3.57855C12.7762 2.47398 14.5672 2.47398 15.6717 3.57855C16.7762 4.68312 16.7762 6.47398 15.6717 7.57855M15.6717 7.57855L9.49994 13.7501M15.6717 7.57855C16.7762 6.47398 18.5672 6.47398 19.6717 7.57855C20.7762 8.68312 20.7762 10.474 19.6717 11.5785L12.7072 18.543C12.3167 18.9335 12.3167 19.5667 12.7072 19.9572L13.9999 21.2499",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"}),e.jsx("path",{d:"M17.4999 9.74921L11.3282 15.921C10.2237 17.0255 8.43272 17.0255 7.32823 15.921C6.22373 14.8164 6.22373 13.0255 7.32823 11.921L13.4999 5.74939",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})]})}):e.jsx(j,{size:13,className:"flex-shrink-0 text-amber-500 dark:text-amber-400"})}const Q={llm_call:"bg-blue-400 dark:bg-blue-500",tool_call:"bg-amber-400 dark:bg-amber-500",mcp_tool:"bg-purple-400 dark:bg-purple-500",memory_recovery:"bg-emerald-400 dark:bg-emerald-500",memory_persist:"bg-violet-400 dark:bg-violet-500",telephonist:"bg-rose-400 dark:bg-rose-500",skill_loaded:"bg-teal-400 dark:bg-teal-500",chronos_job:"bg-orange-400 dark:bg-orange-500",task_created:"bg-gray-300 dark:bg-matrix-secondary/50",task_completed:"bg-green-400 dark:bg-matrix-highlight/70"},X={hidden:{opacity:0},show:{opacity:1,transition:{staggerChildren:.04}}},c={hidden:{opacity:0,y:12},show:{opacity:1,y:0}},oe=()=>{const{data:r,isLoading:i,mutate:l}=D(),{fmtCost:d}=O();if(i)return e.jsxs("div",{className:"flex items-center justify-center h-64 gap-3 text-gray-400 dark:text-matrix-secondary",children:[e.jsx(_,{size:20,className:"animate-spin"}),e.jsx("span",{className:"text-sm font-mono",children:"Loading audit data…"})]});if(!r)return e.jsxs("div",{className:"flex flex-col items-center justify-center h-64 gap-2 text-gray-400 dark:text-matrix-secondary",children:[e.jsx(F,{size:24}),e.jsx("span",{className:"text-sm",children:"Failed to load audit data."})]});const{sessions:s,totals:a,byAgent:g,byModel:y,topTools:p,recentSessions:f,dailyActivity:b}=r,C=[["llm_call",a.llmCallCount],["tool_call",a.toolCallCount],["mcp_tool",a.mcpToolCount],["memory_recovery",a.memoryRecoveryCount],["memory_persist",a.memoryPersistCount],["telephonist",a.telephonistCount],["skill_loaded",a.skillCount],["chronos_job",a.chronosJobCount],["task_created",a.taskCreatedCount],["task_completed",a.taskCompletedCount]].filter(([,t])=>t>0).sort((t,n)=>n[1]-t[1]),$=Math.max(...C.map(([,t])=>t),1);return e.jsxs(o.div,{variants:X,initial:"hidden",animate:"show",className:"space-y-6",children:[e.jsxs(o.div,{variants:c,className:"flex items-center justify-between flex-wrap gap-3",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-10 h-10 rounded-lg bg-blue-500/10 dark:bg-blue-500/20 border border-blue-200 dark:border-blue-800/40 flex items-center justify-center",children:e.jsx(L,{className:"w-5 h-5 text-blue-600 dark:text-blue-400"})}),e.jsxs("div",{children:[e.jsx("h1",{className:"text-xl font-bold text-gray-900 dark:text-matrix-highlight",children:"Global Audit"}),e.jsxs("p",{className:"text-sm text-gray-500 dark:text-matrix-secondary/60 mt-0.5",children:[s.withAudit," sessions with audit data · ",a.totalEventCount.toLocaleString()," events total"]})]})]}),e.jsxs("button",{onClick:()=>l(),className:"flex items-center gap-2 px-3 py-2 rounded-lg border border-gray-200 dark:border-matrix-primary text-sm text-gray-500 dark:text-matrix-secondary hover:bg-gray-50 dark:hover:bg-zinc-900 transition-colors",children:[e.jsx(_,{size:14})," Refresh"]})]}),e.jsxs(o.div,{variants:c,className:"grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-3",children:[e.jsx(h,{icon:e.jsx(U,{size:16}),label:"Total Cost",value:d(a.estimatedCostUsd),color:"green"}),e.jsx(h,{icon:e.jsx(v,{size:16}),label:"LLM Calls",value:a.llmCallCount.toLocaleString(),color:"blue"}),e.jsx(h,{icon:e.jsx(j,{size:16}),label:"Tool Calls",value:(a.toolCallCount+a.mcpToolCount).toLocaleString(),sub:e.jsxs(e.Fragment,{children:[e.jsxs("span",{children:[a.toolCallCount," native"]}),e.jsx("br",{}),e.jsxs("span",{children:[a.mcpToolCount," MCP"]})]}),color:"amber"}),e.jsx(h,{icon:e.jsx(N,{size:16}),label:"Memory Hits",value:a.memoryRecoveryCount.toLocaleString(),color:"teal"}),e.jsx(h,{icon:e.jsx(z,{size:16}),label:"Total Tokens",value:m(a.totalInputTokens+a.totalOutputTokens),sub:e.jsxs(e.Fragment,{children:[e.jsxs("span",{children:["↑",m(a.totalInputTokens)," in"]}),e.jsx("br",{}),e.jsxs("span",{children:["↓",m(a.totalOutputTokens)," out"]})]}),color:"purple"}),e.jsx(h,{icon:e.jsx(w,{size:16}),label:"Total Time",value:k(a.totalDurationMs),color:"rose"})]}),e.jsxs(o.div,{variants:c,className:"grid grid-cols-1 md:grid-cols-2 gap-6",children:[e.jsxs(x,{title:"Sessions",icon:e.jsx(W,{size:14}),children:[e.jsx("div",{className:"grid grid-cols-2 gap-3 mb-4",children:[{label:"Total",value:s.total,cls:"text-gray-700 dark:text-matrix-secondary"},{label:"With Audit",value:s.withAudit,cls:"text-blue-600 dark:text-blue-400"},{label:"Active",value:s.active,cls:"text-green-600 dark:text-matrix-highlight"},{label:"Paused",value:s.paused,cls:"text-gray-500 dark:text-matrix-secondary"},{label:"Archived",value:s.archived,cls:"text-amber-600 dark:text-amber-400"},{label:"Deleted",value:s.deleted,cls:"text-red-500 dark:text-red-400"}].map(({label:t,value:n,cls:u})=>e.jsxs("div",{className:"flex flex-col",children:[e.jsx("span",{className:"text-[10px] uppercase tracking-widest text-gray-400 dark:text-matrix-secondary/50",children:t}),e.jsx("span",{className:`text-2xl font-bold font-mono ${u}`,children:n})]},t))}),s.total>0&&e.jsxs("div",{className:"h-2 rounded-full overflow-hidden flex gap-px",children:[s.active>0&&e.jsx("div",{className:"bg-green-400 dark:bg-matrix-highlight/70",style:{flex:s.active}}),s.paused>0&&e.jsx("div",{className:"bg-gray-300 dark:bg-matrix-primary/50",style:{flex:s.paused}}),s.archived>0&&e.jsx("div",{className:"bg-amber-400 dark:bg-amber-500/70",style:{flex:s.archived}}),s.deleted>0&&e.jsx("div",{className:"bg-red-400 dark:bg-red-500/70",style:{flex:s.deleted}})]})]}),e.jsxs(x,{title:"Activity — Last 30 Days",icon:e.jsx(I,{size:14}),children:[e.jsx(J,{data:b,fmtCost:d}),b.length>0&&e.jsxs("div",{className:"flex gap-4 mt-2 text-[11px] text-gray-400 dark:text-matrix-secondary/50 font-mono",children:[e.jsx("span",{children:b[0]?.date}),e.jsx("span",{className:"flex-1 text-right",children:b[b.length-1]?.date})]})]})]}),e.jsx(o.div,{variants:c,children:e.jsx(x,{title:"Events by Type",icon:e.jsx(z,{size:14}),children:e.jsx("div",{className:"space-y-2",children:C.map(([t,n])=>e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("span",{className:`flex-shrink-0 w-5 flex justify-center ${Y[t]??"text-gray-400"}`,children:K[t]}),e.jsx("span",{className:"text-xs font-mono text-gray-600 dark:text-matrix-secondary w-32 flex-shrink-0",children:t}),e.jsx("div",{className:"flex-1 h-2 bg-gray-100 dark:bg-zinc-800 rounded-full overflow-hidden",children:e.jsx("div",{className:`h-full rounded-full transition-all ${Q[t]??"bg-gray-400"}`,style:{width:T(n,$)}})}),e.jsx("span",{className:"text-xs font-mono text-gray-500 dark:text-matrix-secondary w-16 text-right",children:n.toLocaleString()}),e.jsx("span",{className:"text-[10px] text-gray-400 dark:text-matrix-secondary/50 w-10 text-right",children:T(n,a.totalEventCount)})]},t))})})}),e.jsxs(o.div,{variants:c,className:"grid grid-cols-1 lg:grid-cols-2 gap-6",children:[e.jsx(x,{title:"By Agent",icon:e.jsx(S,{size:14}),children:g.length===0?e.jsx("p",{className:"text-sm text-gray-400 dark:text-matrix-secondary/50",children:"No agent data."}):e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full text-xs font-mono",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"text-[10px] uppercase tracking-wider text-gray-400 dark:text-matrix-secondary/50 border-b border-gray-100 dark:border-matrix-primary/30",children:[e.jsx("th",{className:"pb-2 text-left",children:"Agent"}),e.jsx("th",{className:"pb-2 text-right",children:"LLM"}),e.jsx("th",{className:"pb-2 text-right",children:"Tools"}),e.jsx("th",{className:"pb-2 text-right",children:"Tokens"}),e.jsx("th",{className:"pb-2 text-right",children:"Time"}),e.jsx("th",{className:"pb-2 text-right",children:"Cost"})]})}),e.jsx("tbody",{className:"divide-y divide-gray-50 dark:divide-matrix-primary/20",children:g.map(t=>e.jsxs("tr",{className:"hover:bg-gray-50 dark:hover:bg-zinc-900/50",children:[e.jsx("td",{className:"py-1.5",children:e.jsx(M,{agent:t.agent})}),e.jsx("td",{className:"py-1.5 text-right text-gray-600 dark:text-matrix-secondary",children:t.llmCalls.toLocaleString()}),e.jsx("td",{className:"py-1.5 text-right text-gray-600 dark:text-matrix-secondary",children:t.toolCalls.toLocaleString()}),e.jsxs("td",{className:"py-1.5 text-right text-gray-500 dark:text-matrix-secondary/70",children:["↑",m(t.inputTokens)," ↓",m(t.outputTokens)]}),e.jsx("td",{className:"py-1.5 text-right text-gray-500 dark:text-matrix-secondary/70",children:k(t.totalDurationMs)}),e.jsx("td",{className:"py-1.5 text-right font-semibold text-gray-700 dark:text-matrix-secondary",children:d(t.estimatedCostUsd)})]},t.agent))})]})})}),e.jsx(x,{title:"By Model",icon:e.jsx(v,{size:14}),children:y.length===0?e.jsx("p",{className:"text-sm text-gray-400 dark:text-matrix-secondary/50",children:"No model data."}):e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full text-xs font-mono",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"text-[10px] uppercase tracking-wider text-gray-400 dark:text-matrix-secondary/50 border-b border-gray-100 dark:border-matrix-primary/30",children:[e.jsx("th",{className:"pb-2 text-left",children:"Model"}),e.jsx("th",{className:"pb-2 text-right",children:"Calls"}),e.jsx("th",{className:"pb-2 text-right",children:"In"}),e.jsx("th",{className:"pb-2 text-right",children:"Out"}),e.jsx("th",{className:"pb-2 text-right",children:"Cost"})]})}),e.jsx("tbody",{className:"divide-y divide-gray-50 dark:divide-matrix-primary/20",children:y.map(t=>e.jsxs("tr",{className:"hover:bg-gray-50 dark:hover:bg-zinc-900/50",children:[e.jsxs("td",{className:"py-1.5",children:[e.jsx("div",{className:"text-gray-700 dark:text-matrix-secondary break-all leading-tight",children:t.model}),e.jsx("div",{className:"text-[10px] text-gray-400 dark:text-matrix-secondary/40",children:t.provider})]}),e.jsx("td",{className:"py-1.5 text-right text-gray-600 dark:text-matrix-secondary",children:t.calls.toLocaleString()}),e.jsx("td",{className:"py-1.5 text-right text-gray-500 dark:text-matrix-secondary/70",children:m(t.inputTokens)}),e.jsx("td",{className:"py-1.5 text-right text-gray-500 dark:text-matrix-secondary/70",children:m(t.outputTokens)}),e.jsx("td",{className:"py-1.5 text-right font-semibold text-gray-700 dark:text-matrix-secondary",children:d(t.estimatedCostUsd)})]},`${t.provider}/${t.model}`))})]})})})]}),p.length>0&&e.jsx(o.div,{variants:c,children:e.jsx(x,{title:"Top Tools",icon:e.jsx(j,{size:14}),children:e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full text-xs font-mono",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"text-[10px] uppercase tracking-wider text-gray-400 dark:text-matrix-secondary/50 border-b border-gray-100 dark:border-matrix-primary/30",children:[e.jsx("th",{className:"pb-2 text-left",children:"Tool"}),e.jsx("th",{className:"pb-2 text-left",children:"Agent"}),e.jsx("th",{className:"pb-2 text-right",children:"Calls"}),e.jsx("th",{className:"pb-2 text-right",children:"Errors"}),e.jsx("th",{className:"pb-2 text-right",children:"Error rate"})]})}),e.jsx("tbody",{className:"divide-y divide-gray-50 dark:divide-matrix-primary/20",children:p.map((t,n)=>{const u=t.count?t.errorCount/t.count:0;return e.jsxs("tr",{className:"hover:bg-gray-50 dark:hover:bg-zinc-900/50",children:[e.jsx("td",{className:"py-1.5",children:e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx(q,{eventType:t.event_type}),e.jsx("span",{className:"text-gray-700 dark:text-matrix-secondary break-all",children:t.tool_name})]})}),e.jsx("td",{className:"py-1.5",children:t.agent?e.jsx(M,{agent:t.agent}):e.jsx("span",{className:"text-gray-400",children:"—"})}),e.jsx("td",{className:"py-1.5 text-right text-gray-600 dark:text-matrix-secondary",children:t.count.toLocaleString()}),e.jsx("td",{className:"py-1.5 text-right",children:e.jsx("span",{className:t.errorCount>0?"text-red-500 dark:text-red-400":"text-gray-400 dark:text-matrix-secondary/50",children:t.errorCount})}),e.jsx("td",{className:"py-1.5 text-right",children:e.jsx("span",{className:u>.1?"text-red-500 dark:text-red-400":u>0?"text-amber-500 dark:text-amber-400":"text-gray-400 dark:text-matrix-secondary/50",children:t.count>0?`${Math.round(u*100)}%`:"—"})})]},n)})})]})})})}),e.jsx(o.div,{variants:c,children:e.jsx(x,{title:"Recent Sessions with Audit",icon:e.jsx(L,{size:14}),children:f.length===0?e.jsx("p",{className:"text-sm text-gray-400 dark:text-matrix-secondary/50",children:"No sessions with audit data yet."}):e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full text-xs font-mono",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"text-[10px] uppercase tracking-wider text-gray-400 dark:text-matrix-secondary/50 border-b border-gray-100 dark:border-matrix-primary/30",children:[e.jsx("th",{className:"pb-2 text-left",children:"Session"}),e.jsx("th",{className:"pb-2 text-left",children:"Status"}),e.jsx("th",{className:"pb-2 text-right",children:"Events"}),e.jsx("th",{className:"pb-2 text-right",children:"LLM"}),e.jsx("th",{className:"pb-2 text-right",children:"Duration"}),e.jsx("th",{className:"pb-2 text-right",children:"Cost"}),e.jsx("th",{className:"pb-2"})]})}),e.jsx("tbody",{className:"divide-y divide-gray-50 dark:divide-matrix-primary/20",children:f.map(t=>e.jsxs("tr",{className:"hover:bg-gray-50 dark:hover:bg-zinc-900/50",children:[e.jsxs("td",{className:"py-2",children:[e.jsx("div",{className:"text-gray-700 dark:text-matrix-secondary truncate max-w-[160px]",title:t.title??t.session_id,children:t.title??e.jsxs("span",{className:"text-gray-400 dark:text-matrix-secondary/40 font-mono text-[10px]",children:[t.session_id.slice(0,12),"…"]})}),t.started_at&&e.jsx("div",{className:"text-[10px] text-gray-400 dark:text-matrix-secondary/40",children:G(t.started_at)})]}),e.jsx("td",{className:"py-2",children:e.jsx(Z,{status:t.status})}),e.jsx("td",{className:"py-2 text-right text-gray-600 dark:text-matrix-secondary",children:t.event_count.toLocaleString()}),e.jsx("td",{className:"py-2 text-right text-gray-500 dark:text-matrix-secondary/70",children:t.llmCallCount.toLocaleString()}),e.jsx("td",{className:"py-2 text-right text-gray-500 dark:text-matrix-secondary/70",children:k(t.totalDurationMs)}),e.jsx("td",{className:"py-2 text-right font-semibold text-gray-700 dark:text-matrix-secondary",children:d(t.estimatedCostUsd)}),e.jsx("td",{className:"py-2 text-right",children:e.jsx(E,{to:`/sessions/${t.session_id}/audit`,className:"inline-flex items-center gap-1 px-2 py-1 rounded border border-gray-200 dark:border-matrix-primary text-gray-400 dark:text-matrix-secondary hover:text-blue-600 dark:hover:text-matrix-highlight hover:border-blue-300 dark:hover:border-matrix-highlight/50 transition-colors",title:"View session audit",children:e.jsx(P,{size:11})})})]},t.session_id))})]})})})}),a.telephonistCount>0&&e.jsx(o.div,{variants:c,children:e.jsx(x,{title:"Audio / Telephonist",icon:e.jsx(A,{size:14}),children:e.jsxs("div",{className:"flex flex-wrap gap-8",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-[10px] uppercase tracking-widest text-gray-400 dark:text-matrix-secondary/50 mb-0.5",children:"Calls"}),e.jsx("p",{className:"text-2xl font-bold font-mono text-rose-500 dark:text-rose-400",children:a.telephonistCount.toLocaleString()})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-[10px] uppercase tracking-widest text-gray-400 dark:text-matrix-secondary/50 mb-0.5",children:"Total Audio"}),e.jsx("p",{className:"text-2xl font-bold font-mono text-rose-500 dark:text-rose-400",children:a.totalAudioSeconds<60?`${a.totalAudioSeconds.toFixed(1)}s`:`${(a.totalAudioSeconds/60).toFixed(1)}m`})]})]})})})]})};export{oe as AuditDashboard};
1
+ import{j as e,m as o}from"./vendor-motion-C3CZ8ZlO.js";import{L as E,r as B}from"./vendor-react-DikRIOlj.js";import{a as D}from"./audit-C3PRWFnZ.js";import{u as R}from"./agents-D54KZHoX.js";import{u as O}from"./useCurrency-Bkd-Hd8n.js";import{Z as _,Y as F,h as L,i as U,aw as v,J as j,p as N,A as z,g as w,aA as W,l as I,O as S,aB as P,U as A,s as V,an as H}from"./vendor-icons-LSkmAkBj.js";import"./vendor-utils-BIYveU_1.js";import"./index-C_cF6S2J.js";import"./config-DZGSjv5e.js";function m(r){return r>=1e6?`${(r/1e6).toFixed(1)}M`:r>=1e3?`${(r/1e3).toFixed(1)}k`:String(r)}function k(r){if(r<1e3)return`${r}ms`;if(r<6e4)return`${(r/1e3).toFixed(1)}s`;const i=Math.floor(r/6e4),l=Math.floor(r%6e4/1e3);return`${i}m ${l}s`}function G(r){return r?new Date(r).toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"}):"—"}function T(r,i){return i?`${Math.round(r/i*100)}%`:"0%"}function J({data:r,fmtCost:i}){const[l,d]=B.useState(null);if(!r.length)return e.jsx("p",{className:"text-xs text-gray-400 dark:text-matrix-secondary/50 py-4",children:"No activity in the last 30 days."});const s=Math.max(...r.map(a=>a.eventCount),1);return e.jsx("div",{className:"flex items-end gap-0.5 h-24 w-full relative",children:r.map((a,g)=>{const y=Math.max(4,Math.round(a.eventCount/s*88)),p=l===g;return e.jsxs("div",{className:"flex-1 flex flex-col items-center justify-end group",onMouseEnter:()=>d(g),onMouseLeave:()=>d(null),children:[p&&e.jsxs("div",{className:"absolute -top-10 left-1/2 -translate-x-1/2 z-10 bg-gray-900 dark:bg-zinc-800 text-white text-[10px] rounded px-2 py-1 whitespace-nowrap pointer-events-none shadow-lg",children:[a.date,": ",a.eventCount," events · ",i(a.estimatedCostUsd)]}),e.jsx("div",{style:{height:y},className:`w-full rounded-t transition-colors ${p?"bg-blue-500 dark:bg-matrix-highlight":"bg-blue-300/70 dark:bg-matrix-highlight/40 group-hover:bg-blue-400 dark:group-hover:bg-matrix-highlight/60"}`})]},a.date)})})}function h({icon:r,label:i,value:l,sub:d,color:s="blue"}){const a={blue:"bg-blue-50 dark:bg-blue-900/20 text-blue-600 dark:text-blue-400 border-blue-200 dark:border-blue-800/40",green:"bg-green-50 dark:bg-green-900/20 text-green-600 dark:text-matrix-highlight border-green-200 dark:border-green-800/40",amber:"bg-amber-50 dark:bg-amber-900/20 text-amber-600 dark:text-amber-400 border-amber-200 dark:border-amber-800/40",purple:"bg-purple-50 dark:bg-purple-900/20 text-purple-600 dark:text-purple-400 border-purple-200 dark:border-purple-800/40",rose:"bg-rose-50 dark:bg-rose-900/20 text-rose-600 dark:text-rose-400 border-rose-200 dark:border-rose-800/40",teal:"bg-teal-50 dark:bg-teal-900/20 text-teal-600 dark:text-teal-400 border-teal-200 dark:border-teal-800/40"};return e.jsxs("div",{className:`rounded-lg border p-4 flex gap-3 items-start ${a[s]}`,children:[e.jsx("div",{className:"mt-0.5 flex-shrink-0",children:r}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("p",{className:"text-xs font-medium opacity-70 uppercase tracking-wider mb-0.5",children:i}),e.jsx("p",{className:"text-xl font-bold font-mono leading-tight",children:l}),d&&e.jsx("div",{className:"text-[11px] opacity-60 mt-0.5 leading-snug",children:d})]})]})}function x({title:r,icon:i,children:l}){return e.jsxs("div",{className:"rounded-lg border border-gray-200 dark:border-matrix-primary overflow-hidden bg-white dark:bg-zinc-900 shadow-sm",children:[e.jsxs("div",{className:"px-4 py-3 bg-gray-50 dark:bg-zinc-900 border-b border-gray-200 dark:border-matrix-primary flex items-center gap-2",children:[e.jsx("span",{className:"text-gray-500 dark:text-matrix-secondary/70",children:i}),e.jsx("h2",{className:"text-sm font-semibold text-gray-700 dark:text-matrix-secondary uppercase tracking-wider",children:r})]}),e.jsx("div",{className:"p-4",children:l})]})}function M({agent:r}){const{getByKey:i}=R(),l=i(r);return e.jsxs("span",{className:`inline-flex items-center gap-1 text-[11px] font-semibold px-1.5 py-0.5 rounded ${l.badgeClass}`,children:[l.emoji," ",r.toUpperCase()]})}function Z({status:r}){const i={active:"bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-matrix-highlight",paused:"bg-gray-100 text-gray-600 dark:bg-zinc-800 dark:text-matrix-secondary",archived:"bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-300",deleted:"bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400",unknown:"bg-gray-100 text-gray-500 dark:bg-zinc-800 dark:text-matrix-secondary/60"};return e.jsx("span",{className:`text-[10px] font-semibold uppercase px-1.5 py-0.5 rounded ${i[r]??i.unknown}`,children:r})}const K={llm_call:e.jsx(v,{size:13}),tool_call:e.jsx(j,{size:13}),mcp_tool:e.jsxs("svg",{width:"13",height:"13",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[e.jsx("path",{d:"M3.49994 11.7501L11.6717 3.57855C12.7762 2.47398 14.5672 2.47398 15.6717 3.57855C16.7762 4.68312 16.7762 6.47398 15.6717 7.57855M15.6717 7.57855L9.49994 13.7501M15.6717 7.57855C16.7762 6.47398 18.5672 6.47398 19.6717 7.57855C20.7762 8.68312 20.7762 10.474 19.6717 11.5785L12.7072 18.543C12.3167 18.9335 12.3167 19.5667 12.7072 19.9572L13.9999 21.2499",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"}),e.jsx("path",{d:"M17.4999 9.74921L11.3282 15.921C10.2237 17.0255 8.43272 17.0255 7.32823 15.921C6.22373 14.8164 6.22373 13.0255 7.32823 11.921L13.4999 5.74939",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})]}),memory_recovery:e.jsx(N,{size:13}),memory_persist:e.jsx(N,{size:13}),telephonist:e.jsx(A,{size:13}),skill_loaded:e.jsx(S,{size:13}),chronos_job:e.jsx(w,{size:13}),task_created:e.jsx(H,{size:13}),task_completed:e.jsx(V,{size:13})},Y={llm_call:"text-blue-500 dark:text-blue-400",tool_call:"text-amber-500 dark:text-amber-400",mcp_tool:"text-purple-500 dark:text-purple-400",memory_recovery:"text-emerald-500 dark:text-emerald-400",memory_persist:"text-violet-500 dark:text-violet-400",telephonist:"text-rose-500 dark:text-rose-400",skill_loaded:"text-teal-500 dark:text-teal-400",chronos_job:"text-orange-500 dark:text-orange-400",task_created:"text-gray-500 dark:text-matrix-secondary",task_completed:"text-green-600 dark:text-matrix-highlight"};function q({eventType:r}){return r==="mcp_tool"?e.jsx("span",{className:"flex-shrink-0 text-purple-500 dark:text-purple-400",children:e.jsxs("svg",{width:"13",height:"13",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[e.jsx("path",{d:"M3.49994 11.7501L11.6717 3.57855C12.7762 2.47398 14.5672 2.47398 15.6717 3.57855C16.7762 4.68312 16.7762 6.47398 15.6717 7.57855M15.6717 7.57855L9.49994 13.7501M15.6717 7.57855C16.7762 6.47398 18.5672 6.47398 19.6717 7.57855C20.7762 8.68312 20.7762 10.474 19.6717 11.5785L12.7072 18.543C12.3167 18.9335 12.3167 19.5667 12.7072 19.9572L13.9999 21.2499",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"}),e.jsx("path",{d:"M17.4999 9.74921L11.3282 15.921C10.2237 17.0255 8.43272 17.0255 7.32823 15.921C6.22373 14.8164 6.22373 13.0255 7.32823 11.921L13.4999 5.74939",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})]})}):e.jsx(j,{size:13,className:"flex-shrink-0 text-amber-500 dark:text-amber-400"})}const Q={llm_call:"bg-blue-400 dark:bg-blue-500",tool_call:"bg-amber-400 dark:bg-amber-500",mcp_tool:"bg-purple-400 dark:bg-purple-500",memory_recovery:"bg-emerald-400 dark:bg-emerald-500",memory_persist:"bg-violet-400 dark:bg-violet-500",telephonist:"bg-rose-400 dark:bg-rose-500",skill_loaded:"bg-teal-400 dark:bg-teal-500",chronos_job:"bg-orange-400 dark:bg-orange-500",task_created:"bg-gray-300 dark:bg-matrix-secondary/50",task_completed:"bg-green-400 dark:bg-matrix-highlight/70"},X={hidden:{opacity:0},show:{opacity:1,transition:{staggerChildren:.04}}},c={hidden:{opacity:0,y:12},show:{opacity:1,y:0}},oe=()=>{const{data:r,isLoading:i,mutate:l}=D(),{fmtCost:d}=O();if(i)return e.jsxs("div",{className:"flex items-center justify-center h-64 gap-3 text-gray-400 dark:text-matrix-secondary",children:[e.jsx(_,{size:20,className:"animate-spin"}),e.jsx("span",{className:"text-sm font-mono",children:"Loading audit data…"})]});if(!r)return e.jsxs("div",{className:"flex flex-col items-center justify-center h-64 gap-2 text-gray-400 dark:text-matrix-secondary",children:[e.jsx(F,{size:24}),e.jsx("span",{className:"text-sm",children:"Failed to load audit data."})]});const{sessions:s,totals:a,byAgent:g,byModel:y,topTools:p,recentSessions:f,dailyActivity:b}=r,C=[["llm_call",a.llmCallCount],["tool_call",a.toolCallCount],["mcp_tool",a.mcpToolCount],["memory_recovery",a.memoryRecoveryCount],["memory_persist",a.memoryPersistCount],["telephonist",a.telephonistCount],["skill_loaded",a.skillCount],["chronos_job",a.chronosJobCount],["task_created",a.taskCreatedCount],["task_completed",a.taskCompletedCount]].filter(([,t])=>t>0).sort((t,n)=>n[1]-t[1]),$=Math.max(...C.map(([,t])=>t),1);return e.jsxs(o.div,{variants:X,initial:"hidden",animate:"show",className:"space-y-6",children:[e.jsxs(o.div,{variants:c,className:"flex items-center justify-between flex-wrap gap-3",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-10 h-10 rounded-lg bg-blue-500/10 dark:bg-blue-500/20 border border-blue-200 dark:border-blue-800/40 flex items-center justify-center",children:e.jsx(L,{className:"w-5 h-5 text-blue-600 dark:text-blue-400"})}),e.jsxs("div",{children:[e.jsx("h1",{className:"text-xl font-bold text-gray-900 dark:text-matrix-highlight",children:"Global Audit"}),e.jsxs("p",{className:"text-sm text-gray-500 dark:text-matrix-secondary/60 mt-0.5",children:[s.withAudit," sessions with audit data · ",a.totalEventCount.toLocaleString()," events total"]})]})]}),e.jsxs("button",{onClick:()=>l(),className:"flex items-center gap-2 px-3 py-2 rounded-lg border border-gray-200 dark:border-matrix-primary text-sm text-gray-500 dark:text-matrix-secondary hover:bg-gray-50 dark:hover:bg-zinc-900 transition-colors",children:[e.jsx(_,{size:14})," Refresh"]})]}),e.jsxs(o.div,{variants:c,className:"grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-3",children:[e.jsx(h,{icon:e.jsx(U,{size:16}),label:"Total Cost",value:d(a.estimatedCostUsd),color:"green"}),e.jsx(h,{icon:e.jsx(v,{size:16}),label:"LLM Calls",value:a.llmCallCount.toLocaleString(),color:"blue"}),e.jsx(h,{icon:e.jsx(j,{size:16}),label:"Tool Calls",value:(a.toolCallCount+a.mcpToolCount).toLocaleString(),sub:e.jsxs(e.Fragment,{children:[e.jsxs("span",{children:[a.toolCallCount," native"]}),e.jsx("br",{}),e.jsxs("span",{children:[a.mcpToolCount," MCP"]})]}),color:"amber"}),e.jsx(h,{icon:e.jsx(N,{size:16}),label:"Memory Hits",value:a.memoryRecoveryCount.toLocaleString(),color:"teal"}),e.jsx(h,{icon:e.jsx(z,{size:16}),label:"Total Tokens",value:m(a.totalInputTokens+a.totalOutputTokens),sub:e.jsxs(e.Fragment,{children:[e.jsxs("span",{children:["↑",m(a.totalInputTokens)," in"]}),e.jsx("br",{}),e.jsxs("span",{children:["↓",m(a.totalOutputTokens)," out"]})]}),color:"purple"}),e.jsx(h,{icon:e.jsx(w,{size:16}),label:"Total Time",value:k(a.totalDurationMs),color:"rose"})]}),e.jsxs(o.div,{variants:c,className:"grid grid-cols-1 md:grid-cols-2 gap-6",children:[e.jsxs(x,{title:"Sessions",icon:e.jsx(W,{size:14}),children:[e.jsx("div",{className:"grid grid-cols-2 gap-3 mb-4",children:[{label:"Total",value:s.total,cls:"text-gray-700 dark:text-matrix-secondary"},{label:"With Audit",value:s.withAudit,cls:"text-blue-600 dark:text-blue-400"},{label:"Active",value:s.active,cls:"text-green-600 dark:text-matrix-highlight"},{label:"Paused",value:s.paused,cls:"text-gray-500 dark:text-matrix-secondary"},{label:"Archived",value:s.archived,cls:"text-amber-600 dark:text-amber-400"},{label:"Deleted",value:s.deleted,cls:"text-red-500 dark:text-red-400"}].map(({label:t,value:n,cls:u})=>e.jsxs("div",{className:"flex flex-col",children:[e.jsx("span",{className:"text-[10px] uppercase tracking-widest text-gray-400 dark:text-matrix-secondary/50",children:t}),e.jsx("span",{className:`text-2xl font-bold font-mono ${u}`,children:n})]},t))}),s.total>0&&e.jsxs("div",{className:"h-2 rounded-full overflow-hidden flex gap-px",children:[s.active>0&&e.jsx("div",{className:"bg-green-400 dark:bg-matrix-highlight/70",style:{flex:s.active}}),s.paused>0&&e.jsx("div",{className:"bg-gray-300 dark:bg-matrix-primary/50",style:{flex:s.paused}}),s.archived>0&&e.jsx("div",{className:"bg-amber-400 dark:bg-amber-500/70",style:{flex:s.archived}}),s.deleted>0&&e.jsx("div",{className:"bg-red-400 dark:bg-red-500/70",style:{flex:s.deleted}})]})]}),e.jsxs(x,{title:"Activity — Last 30 Days",icon:e.jsx(I,{size:14}),children:[e.jsx(J,{data:b,fmtCost:d}),b.length>0&&e.jsxs("div",{className:"flex gap-4 mt-2 text-[11px] text-gray-400 dark:text-matrix-secondary/50 font-mono",children:[e.jsx("span",{children:b[0]?.date}),e.jsx("span",{className:"flex-1 text-right",children:b[b.length-1]?.date})]})]})]}),e.jsx(o.div,{variants:c,children:e.jsx(x,{title:"Events by Type",icon:e.jsx(z,{size:14}),children:e.jsx("div",{className:"space-y-2",children:C.map(([t,n])=>e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("span",{className:`flex-shrink-0 w-5 flex justify-center ${Y[t]??"text-gray-400"}`,children:K[t]}),e.jsx("span",{className:"text-xs font-mono text-gray-600 dark:text-matrix-secondary w-32 flex-shrink-0",children:t}),e.jsx("div",{className:"flex-1 h-2 bg-gray-100 dark:bg-zinc-800 rounded-full overflow-hidden",children:e.jsx("div",{className:`h-full rounded-full transition-all ${Q[t]??"bg-gray-400"}`,style:{width:T(n,$)}})}),e.jsx("span",{className:"text-xs font-mono text-gray-500 dark:text-matrix-secondary w-16 text-right",children:n.toLocaleString()}),e.jsx("span",{className:"text-[10px] text-gray-400 dark:text-matrix-secondary/50 w-10 text-right",children:T(n,a.totalEventCount)})]},t))})})}),e.jsxs(o.div,{variants:c,className:"grid grid-cols-1 lg:grid-cols-2 gap-6",children:[e.jsx(x,{title:"By Agent",icon:e.jsx(S,{size:14}),children:g.length===0?e.jsx("p",{className:"text-sm text-gray-400 dark:text-matrix-secondary/50",children:"No agent data."}):e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full text-xs font-mono",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"text-[10px] uppercase tracking-wider text-gray-400 dark:text-matrix-secondary/50 border-b border-gray-100 dark:border-matrix-primary/30",children:[e.jsx("th",{className:"pb-2 text-left",children:"Agent"}),e.jsx("th",{className:"pb-2 text-right",children:"LLM"}),e.jsx("th",{className:"pb-2 text-right",children:"Tools"}),e.jsx("th",{className:"pb-2 text-right",children:"Tokens"}),e.jsx("th",{className:"pb-2 text-right",children:"Time"}),e.jsx("th",{className:"pb-2 text-right",children:"Cost"})]})}),e.jsx("tbody",{className:"divide-y divide-gray-50 dark:divide-matrix-primary/20",children:g.map(t=>e.jsxs("tr",{className:"hover:bg-gray-50 dark:hover:bg-zinc-900/50",children:[e.jsx("td",{className:"py-1.5",children:e.jsx(M,{agent:t.agent})}),e.jsx("td",{className:"py-1.5 text-right text-gray-600 dark:text-matrix-secondary",children:t.llmCalls.toLocaleString()}),e.jsx("td",{className:"py-1.5 text-right text-gray-600 dark:text-matrix-secondary",children:t.toolCalls.toLocaleString()}),e.jsxs("td",{className:"py-1.5 text-right text-gray-500 dark:text-matrix-secondary/70",children:["↑",m(t.inputTokens)," ↓",m(t.outputTokens)]}),e.jsx("td",{className:"py-1.5 text-right text-gray-500 dark:text-matrix-secondary/70",children:k(t.totalDurationMs)}),e.jsx("td",{className:"py-1.5 text-right font-semibold text-gray-700 dark:text-matrix-secondary",children:d(t.estimatedCostUsd)})]},t.agent))})]})})}),e.jsx(x,{title:"By Model",icon:e.jsx(v,{size:14}),children:y.length===0?e.jsx("p",{className:"text-sm text-gray-400 dark:text-matrix-secondary/50",children:"No model data."}):e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full text-xs font-mono",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"text-[10px] uppercase tracking-wider text-gray-400 dark:text-matrix-secondary/50 border-b border-gray-100 dark:border-matrix-primary/30",children:[e.jsx("th",{className:"pb-2 text-left",children:"Model"}),e.jsx("th",{className:"pb-2 text-right",children:"Calls"}),e.jsx("th",{className:"pb-2 text-right",children:"In"}),e.jsx("th",{className:"pb-2 text-right",children:"Out"}),e.jsx("th",{className:"pb-2 text-right",children:"Cost"})]})}),e.jsx("tbody",{className:"divide-y divide-gray-50 dark:divide-matrix-primary/20",children:y.map(t=>e.jsxs("tr",{className:"hover:bg-gray-50 dark:hover:bg-zinc-900/50",children:[e.jsxs("td",{className:"py-1.5",children:[e.jsx("div",{className:"text-gray-700 dark:text-matrix-secondary break-all leading-tight",children:t.model}),e.jsx("div",{className:"text-[10px] text-gray-400 dark:text-matrix-secondary/40",children:t.provider})]}),e.jsx("td",{className:"py-1.5 text-right text-gray-600 dark:text-matrix-secondary",children:t.calls.toLocaleString()}),e.jsx("td",{className:"py-1.5 text-right text-gray-500 dark:text-matrix-secondary/70",children:m(t.inputTokens)}),e.jsx("td",{className:"py-1.5 text-right text-gray-500 dark:text-matrix-secondary/70",children:m(t.outputTokens)}),e.jsx("td",{className:"py-1.5 text-right font-semibold text-gray-700 dark:text-matrix-secondary",children:d(t.estimatedCostUsd)})]},`${t.provider}/${t.model}`))})]})})})]}),p.length>0&&e.jsx(o.div,{variants:c,children:e.jsx(x,{title:"Top Tools",icon:e.jsx(j,{size:14}),children:e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full text-xs font-mono",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"text-[10px] uppercase tracking-wider text-gray-400 dark:text-matrix-secondary/50 border-b border-gray-100 dark:border-matrix-primary/30",children:[e.jsx("th",{className:"pb-2 text-left",children:"Tool"}),e.jsx("th",{className:"pb-2 text-left",children:"Agent"}),e.jsx("th",{className:"pb-2 text-right",children:"Calls"}),e.jsx("th",{className:"pb-2 text-right",children:"Errors"}),e.jsx("th",{className:"pb-2 text-right",children:"Error rate"})]})}),e.jsx("tbody",{className:"divide-y divide-gray-50 dark:divide-matrix-primary/20",children:p.map((t,n)=>{const u=t.count?t.errorCount/t.count:0;return e.jsxs("tr",{className:"hover:bg-gray-50 dark:hover:bg-zinc-900/50",children:[e.jsx("td",{className:"py-1.5",children:e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx(q,{eventType:t.event_type}),e.jsx("span",{className:"text-gray-700 dark:text-matrix-secondary break-all",children:t.tool_name})]})}),e.jsx("td",{className:"py-1.5",children:t.agent?e.jsx(M,{agent:t.agent}):e.jsx("span",{className:"text-gray-400",children:"—"})}),e.jsx("td",{className:"py-1.5 text-right text-gray-600 dark:text-matrix-secondary",children:t.count.toLocaleString()}),e.jsx("td",{className:"py-1.5 text-right",children:e.jsx("span",{className:t.errorCount>0?"text-red-500 dark:text-red-400":"text-gray-400 dark:text-matrix-secondary/50",children:t.errorCount})}),e.jsx("td",{className:"py-1.5 text-right",children:e.jsx("span",{className:u>.1?"text-red-500 dark:text-red-400":u>0?"text-amber-500 dark:text-amber-400":"text-gray-400 dark:text-matrix-secondary/50",children:t.count>0?`${Math.round(u*100)}%`:"—"})})]},n)})})]})})})}),e.jsx(o.div,{variants:c,children:e.jsx(x,{title:"Recent Sessions with Audit",icon:e.jsx(L,{size:14}),children:f.length===0?e.jsx("p",{className:"text-sm text-gray-400 dark:text-matrix-secondary/50",children:"No sessions with audit data yet."}):e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full text-xs font-mono",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"text-[10px] uppercase tracking-wider text-gray-400 dark:text-matrix-secondary/50 border-b border-gray-100 dark:border-matrix-primary/30",children:[e.jsx("th",{className:"pb-2 text-left",children:"Session"}),e.jsx("th",{className:"pb-2 text-left",children:"Status"}),e.jsx("th",{className:"pb-2 text-right",children:"Events"}),e.jsx("th",{className:"pb-2 text-right",children:"LLM"}),e.jsx("th",{className:"pb-2 text-right",children:"Duration"}),e.jsx("th",{className:"pb-2 text-right",children:"Cost"}),e.jsx("th",{className:"pb-2"})]})}),e.jsx("tbody",{className:"divide-y divide-gray-50 dark:divide-matrix-primary/20",children:f.map(t=>e.jsxs("tr",{className:"hover:bg-gray-50 dark:hover:bg-zinc-900/50",children:[e.jsxs("td",{className:"py-2",children:[e.jsx("div",{className:"text-gray-700 dark:text-matrix-secondary truncate max-w-[160px]",title:t.title??t.session_id,children:t.title??e.jsxs("span",{className:"text-gray-400 dark:text-matrix-secondary/40 font-mono text-[10px]",children:[t.session_id.slice(0,12),"…"]})}),t.started_at&&e.jsx("div",{className:"text-[10px] text-gray-400 dark:text-matrix-secondary/40",children:G(t.started_at)})]}),e.jsx("td",{className:"py-2",children:e.jsx(Z,{status:t.status})}),e.jsx("td",{className:"py-2 text-right text-gray-600 dark:text-matrix-secondary",children:t.event_count.toLocaleString()}),e.jsx("td",{className:"py-2 text-right text-gray-500 dark:text-matrix-secondary/70",children:t.llmCallCount.toLocaleString()}),e.jsx("td",{className:"py-2 text-right text-gray-500 dark:text-matrix-secondary/70",children:k(t.totalDurationMs)}),e.jsx("td",{className:"py-2 text-right font-semibold text-gray-700 dark:text-matrix-secondary",children:d(t.estimatedCostUsd)}),e.jsx("td",{className:"py-2 text-right",children:e.jsx(E,{to:`/sessions/${t.session_id}/audit`,className:"inline-flex items-center gap-1 px-2 py-1 rounded border border-gray-200 dark:border-matrix-primary text-gray-400 dark:text-matrix-secondary hover:text-blue-600 dark:hover:text-matrix-highlight hover:border-blue-300 dark:hover:border-matrix-highlight/50 transition-colors",title:"View session audit",children:e.jsx(P,{size:11})})})]},t.session_id))})]})})})}),a.telephonistCount>0&&e.jsx(o.div,{variants:c,children:e.jsx(x,{title:"Audio / Telephonist",icon:e.jsx(A,{size:14}),children:e.jsxs("div",{className:"flex flex-wrap gap-8",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-[10px] uppercase tracking-widest text-gray-400 dark:text-matrix-secondary/50 mb-0.5",children:"Calls"}),e.jsx("p",{className:"text-2xl font-bold font-mono text-rose-500 dark:text-rose-400",children:a.telephonistCount.toLocaleString()})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-[10px] uppercase tracking-widest text-gray-400 dark:text-matrix-secondary/50 mb-0.5",children:"Total Audio"}),e.jsx("p",{className:"text-2xl font-bold font-mono text-rose-500 dark:text-rose-400",children:a.totalAudioSeconds<60?`${a.totalAudioSeconds.toFixed(1)}s`:`${(a.totalAudioSeconds/60).toFixed(1)}m`})]})]})})})]})};export{oe as AuditDashboard};