morpheus-cli 0.9.22 → 0.9.23

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 (48) hide show
  1. package/dist/channels/discord.js +5 -0
  2. package/dist/channels/telegram.js +5 -0
  3. package/dist/http/routers/display.js +5 -0
  4. package/dist/runtime/audit/repository.js +69 -1
  5. package/dist/runtime/chronos/worker.js +2 -0
  6. package/dist/runtime/display.js +32 -0
  7. package/dist/runtime/memory/sati/service.js +5 -0
  8. package/dist/runtime/oracle.js +5 -0
  9. package/dist/runtime/providers/factory.js +14 -2
  10. package/dist/runtime/smiths/delegator.js +3 -0
  11. package/dist/runtime/subagents/devkit-instrument.js +5 -0
  12. package/dist/runtime/subagents/link/link.js +120 -77
  13. package/dist/runtime/subagents/trinity/trinity.js +64 -34
  14. package/dist/runtime/tools/factory.js +6 -2
  15. package/dist/ui/assets/{AuditDashboard-z3OBbJ8I.js → AuditDashboard-ClqEr7jg.js} +1 -1
  16. package/dist/ui/assets/{Chat-aFz9FjrD.js → Chat-BwxZJphx.js} +1 -1
  17. package/dist/ui/assets/{Chronos-MP_NCj2A.js → Chronos-BafOMteb.js} +1 -1
  18. package/dist/ui/assets/{ConfirmationModal-B3gHIVKY.js → ConfirmationModal-DU0AwhXD.js} +1 -1
  19. package/dist/ui/assets/{Dashboard-OyZXnj44.js → Dashboard-DvJb72Xe.js} +174 -174
  20. package/dist/ui/assets/{DeleteConfirmationModal-D8QsQzwP.js → DeleteConfirmationModal-FSWLK6-I.js} +1 -1
  21. package/dist/ui/assets/{Documents-B8g_yv4f.js → Documents-D73CeGkW.js} +1 -1
  22. package/dist/ui/assets/{Logs-BWufAtHa.js → Logs-BrFWnLIL.js} +1 -1
  23. package/dist/ui/assets/{MCPManager-lLoGEyBy.js → MCPManager-_L2Yo-uY.js} +1 -1
  24. package/dist/ui/assets/{ModelPricing-CuYIUwXt.js → ModelPricing-CyXMdxJD.js} +1 -1
  25. package/dist/ui/assets/{Notifications-nI--fmYx.js → Notifications-BpHokTLS.js} +1 -1
  26. package/dist/ui/assets/{SatiMemories-DO3JDQBi.js → SatiMemories-CfSTgr9V.js} +1 -1
  27. package/dist/ui/assets/{SessionAudit-BWtJRkj1.js → SessionAudit-pOWRgJtc.js} +1 -1
  28. package/dist/ui/assets/{Settings-CblauAVd.js → Settings-CPDXAk18.js} +1 -1
  29. package/dist/ui/assets/{Skills-Dw6G5c8W.js → Skills-GIkCxMS3.js} +1 -1
  30. package/dist/ui/assets/{Smiths-B6-CnRMv.js → Smiths-ZcHXcrMt.js} +1 -1
  31. package/dist/ui/assets/{Tasks-DzUyw5z3.js → Tasks-DJ6R3d4f.js} +1 -1
  32. package/dist/ui/assets/{TrinityDatabases-DCjdwnLH.js → TrinityDatabases-CnRAkDuu.js} +1 -1
  33. package/dist/ui/assets/{UsageStats-VajzjndO.js → UsageStats-Bl7bs4ay.js} +1 -1
  34. package/dist/ui/assets/{WebhookManager-BbfMCiy-.js → WebhookManager-CEjjk4tx.js} +1 -1
  35. package/dist/ui/assets/{agents-CN_AKX_I.js → agents-DO69pNM1.js} +1 -1
  36. package/dist/ui/assets/{audit-M-5UGwoK.js → audit-CP5fC4m8.js} +1 -1
  37. package/dist/ui/assets/{chronos-mZ0RIvh4.js → chronos-DPhK718h.js} +1 -1
  38. package/dist/ui/assets/{config-7LGRnJ26.js → config-OLGQFNJL.js} +1 -1
  39. package/dist/ui/assets/{index-Db1XEN8v.js → index-B9ePr-vB.js} +2 -2
  40. package/dist/ui/assets/index-D_0tPLCk.css +1 -0
  41. package/dist/ui/assets/{mcp-YiYC-9IH.js → mcp-BeBznKtK.js} +1 -1
  42. package/dist/ui/assets/{skills-dc6Xqqhb.js → skills-wEUxSGB3.js} +1 -1
  43. package/dist/ui/assets/{stats-BzqxCDuj.js → stats-KMbKDMJ-.js} +1 -1
  44. package/dist/ui/assets/{useCurrency-CEc5edm2.js → useCurrency-Bgg-7MTE.js} +1 -1
  45. package/dist/ui/index.html +2 -2
  46. package/dist/ui/sw.js +1 -1
  47. package/package.json +1 -1
  48. package/dist/ui/assets/index-Bko2TlZY.css +0 -1
@@ -89,6 +89,7 @@ export class Link {
89
89
  const search = this.search;
90
90
  const repository = this.repository;
91
91
  const agentConfig = this.agentConfig;
92
+ const display = DisplayManager.getInstance();
92
93
  const searchTool = new DynamicStructuredTool({
93
94
  name: 'link_search_documents',
94
95
  description: 'Search ALL indexed user documents using hybrid vector + keyword search. Returns the most relevant document chunks for a given query. Use this for broad searches when you don\'t know which document contains the answer.',
@@ -97,16 +98,22 @@ export class Link {
97
98
  limit: z.number().optional().describe('Maximum number of results to return (default: max_results from config)'),
98
99
  }),
99
100
  func: async ({ query, limit }) => {
100
- const maxResults = limit ?? agentConfig.max_results;
101
- const threshold = agentConfig.score_threshold;
102
- const results = await search.search(query, maxResults, threshold);
103
- if (results.length === 0) {
104
- return `No relevant documents found for query: "${query}"`;
101
+ display.startActivity('link', 'Searching documents...');
102
+ try {
103
+ const maxResults = limit ?? agentConfig.max_results;
104
+ const threshold = agentConfig.score_threshold;
105
+ const results = await search.search(query, maxResults, threshold);
106
+ if (results.length === 0) {
107
+ return `No relevant documents found for query: "${query}"`;
108
+ }
109
+ const formatted = results
110
+ .map((r, i) => `[${i + 1}] Source: ${r.filename} (chunk ${r.position}, score: ${r.score.toFixed(3)})\n${r.content}`)
111
+ .join('\n\n---\n\n');
112
+ return `Found ${results.length} relevant passages:\n\n${formatted}`;
113
+ }
114
+ finally {
115
+ display.endActivity('link', true);
105
116
  }
106
- const formatted = results
107
- .map((r, i) => `[${i + 1}] Source: ${r.filename} (chunk ${r.position}, score: ${r.score.toFixed(3)})\n${r.content}`)
108
- .join('\n\n---\n\n');
109
- return `Found ${results.length} relevant passages:\n\n${formatted}`;
110
117
  },
111
118
  });
112
119
  const listDocumentsTool = new DynamicStructuredTool({
@@ -116,21 +123,27 @@ export class Link {
116
123
  name_filter: z.string().optional().describe('Optional partial filename to filter by (case-insensitive). E.g. "CV", "contrato", "readme"'),
117
124
  }),
118
125
  func: async ({ name_filter }) => {
119
- const docs = repository.listDocuments('indexed');
120
- if (docs.length === 0) {
121
- return 'No indexed documents found.';
122
- }
123
- let filtered = docs;
124
- if (name_filter) {
125
- const lower = name_filter.toLowerCase();
126
- filtered = docs.filter(d => d.filename.toLowerCase().includes(lower));
126
+ display.startActivity('link', 'Listing documents...');
127
+ try {
128
+ const docs = repository.listDocuments('indexed');
129
+ if (docs.length === 0) {
130
+ return 'No indexed documents found.';
131
+ }
132
+ let filtered = docs;
133
+ if (name_filter) {
134
+ const lower = name_filter.toLowerCase();
135
+ filtered = docs.filter(d => d.filename.toLowerCase().includes(lower));
136
+ }
137
+ if (filtered.length === 0) {
138
+ const allNames = docs.map(d => `- ${d.filename}`).join('\n');
139
+ return `No documents matching "${name_filter}". Available documents:\n${allNames}`;
140
+ }
141
+ const lines = filtered.map(d => `- [${d.id}] ${d.filename} (${d.chunk_count} chunks)`);
142
+ return `Found ${filtered.length} document(s):\n${lines.join('\n')}`;
127
143
  }
128
- if (filtered.length === 0) {
129
- const allNames = docs.map(d => `- ${d.filename}`).join('\n');
130
- return `No documents matching "${name_filter}". Available documents:\n${allNames}`;
144
+ finally {
145
+ display.endActivity('link', true);
131
146
  }
132
- const lines = filtered.map(d => `- [${d.id}] ${d.filename} (${d.chunk_count} chunks)`);
133
- return `Found ${filtered.length} document(s):\n${lines.join('\n')}`;
134
147
  },
135
148
  });
136
149
  const searchInDocumentTool = new DynamicStructuredTool({
@@ -142,20 +155,26 @@ export class Link {
142
155
  limit: z.number().optional().describe('Maximum number of results (default: max_results from config)'),
143
156
  }),
144
157
  func: async ({ document_id, query, limit }) => {
145
- const doc = repository.getDocument(document_id);
146
- if (!doc) {
147
- return `Document not found: ${document_id}`;
158
+ display.startActivity('link', 'Searching in document...');
159
+ try {
160
+ const doc = repository.getDocument(document_id);
161
+ if (!doc) {
162
+ return `Document not found: ${document_id}`;
163
+ }
164
+ const maxResults = limit ?? agentConfig.max_results;
165
+ const threshold = agentConfig.score_threshold;
166
+ const results = await search.searchInDocument(query, document_id, maxResults, threshold);
167
+ if (results.length === 0) {
168
+ return `No relevant passages found in "${doc.filename}" for query: "${query}"`;
169
+ }
170
+ const formatted = results
171
+ .map((r, i) => `[${i + 1}] (chunk ${r.position}, score: ${r.score.toFixed(3)})\n${r.content}`)
172
+ .join('\n\n---\n\n');
173
+ return `Found ${results.length} passages in "${doc.filename}":\n\n${formatted}`;
148
174
  }
149
- const maxResults = limit ?? agentConfig.max_results;
150
- const threshold = agentConfig.score_threshold;
151
- const results = await search.searchInDocument(query, document_id, maxResults, threshold);
152
- if (results.length === 0) {
153
- return `No relevant passages found in "${doc.filename}" for query: "${query}"`;
175
+ finally {
176
+ display.endActivity('link', true);
154
177
  }
155
- const formatted = results
156
- .map((r, i) => `[${i + 1}] (chunk ${r.position}, score: ${r.score.toFixed(3)})\n${r.content}`)
157
- .join('\n\n---\n\n');
158
- return `Found ${results.length} passages in "${doc.filename}":\n\n${formatted}`;
159
178
  },
160
179
  });
161
180
  // Tool: Summarize entire document via LLM
@@ -167,19 +186,25 @@ export class Link {
167
186
  max_chunks: z.number().optional().describe('Maximum number of chunks to include in summary (default: 50)'),
168
187
  }),
169
188
  func: async ({ document_id, max_chunks }) => {
170
- const doc = repository.getDocument(document_id);
171
- if (!doc) {
172
- return `Document not found: ${document_id}`;
189
+ display.startActivity('link', 'Summarizing document...');
190
+ try {
191
+ const doc = repository.getDocument(document_id);
192
+ if (!doc) {
193
+ return `Document not found: ${document_id}`;
194
+ }
195
+ const chunks = repository.getChunksByDocument(document_id);
196
+ if (chunks.length === 0) {
197
+ return `Document "${doc.filename}" has no indexed chunks.`;
198
+ }
199
+ const limit = max_chunks ?? 50;
200
+ const chunksToSummarize = chunks.slice(0, limit);
201
+ const content = chunksToSummarize.map(c => c.content).join('\n\n---\n\n');
202
+ // Return the content for LLM to summarize - the ReactAgent will handle the summarization
203
+ return `Document: ${doc.filename}\nTotal chunks: ${chunks.length}\nChunks to summarize: ${chunksToSummarize.length}\n\nContent:\n${content}`;
173
204
  }
174
- const chunks = repository.getChunksByDocument(document_id);
175
- if (chunks.length === 0) {
176
- return `Document "${doc.filename}" has no indexed chunks.`;
205
+ finally {
206
+ display.endActivity('link', true);
177
207
  }
178
- const limit = max_chunks ?? 50;
179
- const chunksToSummarize = chunks.slice(0, limit);
180
- const content = chunksToSummarize.map(c => c.content).join('\n\n---\n\n');
181
- // Return the content for LLM to summarize - the ReactAgent will handle the summarization
182
- return `Document: ${doc.filename}\nTotal chunks: ${chunks.length}\nChunks to summarize: ${chunksToSummarize.length}\n\nContent:\n${content}`;
183
208
  },
184
209
  });
185
210
  // Tool: Summarize specific chunk via LLM
@@ -191,16 +216,22 @@ export class Link {
191
216
  position: z.number().describe('The chunk position to summarize (1-based)'),
192
217
  }),
193
218
  func: async ({ document_id, position }) => {
194
- const doc = repository.getDocument(document_id);
195
- if (!doc) {
196
- return `Document not found: ${document_id}`;
219
+ display.startActivity('link', 'Summarizing chunk...');
220
+ try {
221
+ const doc = repository.getDocument(document_id);
222
+ if (!doc) {
223
+ return `Document not found: ${document_id}`;
224
+ }
225
+ const chunks = repository.getChunksByDocument(document_id);
226
+ const chunk = chunks.find(c => c.position === position);
227
+ if (!chunk) {
228
+ return `Chunk not found: position ${position}. Document "${doc.filename}" has ${chunks.length} chunks.`;
229
+ }
230
+ return `Document: ${doc.filename}\nChunk position: ${position}\n\nContent:\n${chunk.content}`;
197
231
  }
198
- const chunks = repository.getChunksByDocument(document_id);
199
- const chunk = chunks.find(c => c.position === position);
200
- if (!chunk) {
201
- return `Chunk not found: position ${position}. Document "${doc.filename}" has ${chunks.length} chunks.`;
232
+ finally {
233
+ display.endActivity('link', true);
202
234
  }
203
- return `Document: ${doc.filename}\nChunk position: ${position}\n\nContent:\n${chunk.content}`;
204
235
  },
205
236
  });
206
237
  // Tool: Extract key points from document
@@ -212,18 +243,24 @@ export class Link {
212
243
  max_chunks: z.number().optional().describe('Maximum number of chunks to analyze (default: 50)'),
213
244
  }),
214
245
  func: async ({ document_id, max_chunks }) => {
215
- const doc = repository.getDocument(document_id);
216
- if (!doc) {
217
- return `Document not found: ${document_id}`;
246
+ display.startActivity('link', 'Extracting key points...');
247
+ try {
248
+ const doc = repository.getDocument(document_id);
249
+ if (!doc) {
250
+ return `Document not found: ${document_id}`;
251
+ }
252
+ const chunks = repository.getChunksByDocument(document_id);
253
+ if (chunks.length === 0) {
254
+ return `Document "${doc.filename}" has no indexed chunks.`;
255
+ }
256
+ const limit = max_chunks ?? 1000;
257
+ const chunksToAnalyze = chunks.slice(0, limit);
258
+ const content = chunksToAnalyze.map(c => c.content).join('\n\n---\n\n');
259
+ return `Document: ${doc.filename}\nTotal chunks: ${chunks.length}\nChunks to analyze: ${chunksToAnalyze.length}\n\nContent:\n${content}`;
218
260
  }
219
- const chunks = repository.getChunksByDocument(document_id);
220
- if (chunks.length === 0) {
221
- return `Document "${doc.filename}" has no indexed chunks.`;
261
+ finally {
262
+ display.endActivity('link', true);
222
263
  }
223
- const limit = max_chunks ?? 1000;
224
- const chunksToAnalyze = chunks.slice(0, limit);
225
- const content = chunksToAnalyze.map(c => c.content).join('\n\n---\n\n');
226
- return `Document: ${doc.filename}\nTotal chunks: ${chunks.length}\nChunks to analyze: ${chunksToAnalyze.length}\n\nContent:\n${content}`;
227
264
  },
228
265
  });
229
266
  // Tool: Find differences between two documents
@@ -235,22 +272,28 @@ export class Link {
235
272
  document_id_b: z.string().describe('Second document ID to compare'),
236
273
  }),
237
274
  func: async ({ document_id_a, document_id_b }) => {
238
- const docA = repository.getDocument(document_id_a);
239
- const docB = repository.getDocument(document_id_b);
240
- if (!docA) {
241
- return `Document not found: ${document_id_a}`;
242
- }
243
- if (!docB) {
244
- return `Document not found: ${document_id_b}`;
275
+ display.startActivity('link', 'Comparing documents...');
276
+ try {
277
+ const docA = repository.getDocument(document_id_a);
278
+ const docB = repository.getDocument(document_id_b);
279
+ if (!docA) {
280
+ return `Document not found: ${document_id_a}`;
281
+ }
282
+ if (!docB) {
283
+ return `Document not found: ${document_id_b}`;
284
+ }
285
+ if (document_id_a === document_id_b) {
286
+ return 'Os documentos são idênticos (mesmo documento informado duas vezes).';
287
+ }
288
+ const chunksA = repository.getChunksByDocument(document_id_a);
289
+ const chunksB = repository.getChunksByDocument(document_id_b);
290
+ const contentA = chunksA.map(c => c.content).join('\n\n---\n\n');
291
+ const contentB = chunksB.map(c => c.content).join('\n\n---\n\n');
292
+ return `Document A: ${docA.filename} (${chunksA.length} chunks)\nDocument B: ${docB.filename} (${chunksB.length} chunks)\n\n--- Document A Content ---\n${contentA}\n\n--- Document B Content ---\n${contentB}`;
245
293
  }
246
- if (document_id_a === document_id_b) {
247
- return 'Os documentos são idênticos (mesmo documento informado duas vezes).';
294
+ finally {
295
+ display.endActivity('link', true);
248
296
  }
249
- const chunksA = repository.getChunksByDocument(document_id_a);
250
- const chunksB = repository.getChunksByDocument(document_id_b);
251
- const contentA = chunksA.map(c => c.content).join('\n\n---\n\n');
252
- const contentB = chunksB.map(c => c.content).join('\n\n---\n\n');
253
- return `Document A: ${docA.filename} (${chunksA.length} chunks)\nDocument B: ${docB.filename} (${chunksB.length} chunks)\n\n--- Document A Content ---\n${contentA}\n\n--- Document B Content ---\n${contentB}`;
254
297
  },
255
298
  });
256
299
  return [listDocumentsTool, searchTool, searchInDocumentTool, summarizeDocumentTool, summarizeChunkTool, extractKeyPointsTool, findDifferencesTool];
@@ -83,41 +83,54 @@ export class Trinity {
83
83
  }
84
84
  buildTrinityTools() {
85
85
  const registry = DatabaseRegistry.getInstance();
86
+ const display = DisplayManager.getInstance();
86
87
  const listDatabases = tool(async () => {
87
- const dbs = registry.listDatabases();
88
- if (dbs.length === 0)
89
- return 'No databases registered.';
90
- return dbs.map((db) => {
91
- const schema = db.schema_json
92
- ? JSON.parse(db.schema_json)
93
- : null;
94
- let schemaSummary = 'schema not loaded';
95
- if (schema) {
96
- if (schema.databases) {
97
- const totalTables = schema.databases.reduce((acc, d) => acc + d.tables.length, 0);
98
- schemaSummary = `${schema.databases.length} databases, ${totalTables} tables total`;
99
- }
100
- else {
101
- schemaSummary = schema.tables?.map((t) => t.name).join(', ') || 'no tables';
88
+ display.startActivity('trinit', 'Listing databases...');
89
+ try {
90
+ const dbs = registry.listDatabases();
91
+ if (dbs.length === 0)
92
+ return 'No databases registered.';
93
+ return dbs.map((db) => {
94
+ const schema = db.schema_json
95
+ ? JSON.parse(db.schema_json)
96
+ : null;
97
+ let schemaSummary = 'schema not loaded';
98
+ if (schema) {
99
+ if (schema.databases) {
100
+ const totalTables = schema.databases.reduce((acc, d) => acc + d.tables.length, 0);
101
+ schemaSummary = `${schema.databases.length} databases, ${totalTables} tables total`;
102
+ }
103
+ else {
104
+ schemaSummary = schema.tables?.map((t) => t.name).join(', ') || 'no tables';
105
+ }
102
106
  }
103
- }
104
- const updatedAt = db.schema_updated_at
105
- ? new Date(db.schema_updated_at).toISOString()
106
- : 'never';
107
- return `[${db.id}] ${db.name} (${db.type}) — ${schemaSummary} — schema updated: ${updatedAt}`;
108
- }).join('\n');
107
+ const updatedAt = db.schema_updated_at
108
+ ? new Date(db.schema_updated_at).toISOString()
109
+ : 'never';
110
+ return `[${db.id}] ${db.name} (${db.type}) — ${schemaSummary} — schema updated: ${updatedAt}`;
111
+ }).join('\n');
112
+ }
113
+ finally {
114
+ display.endActivity('trinit', true);
115
+ }
109
116
  }, {
110
117
  name: 'trinity_list_databases',
111
118
  description: 'List all registered databases with their name, type, and schema summary.',
112
119
  schema: z.object({}),
113
120
  });
114
121
  const getSchema = tool(async ({ database_id }) => {
115
- const db = registry.getDatabase(database_id);
116
- if (!db)
117
- return `Database with id ${database_id} not found.`;
118
- if (!db.schema_json)
119
- return `No schema cached for database "${db.name}". Use trinity_refresh_schema first.`;
120
- return `Schema for "${db.name}" (${db.type}):\n${db.schema_json}`;
122
+ display.startActivity('trinit', 'Getting database schema...');
123
+ try {
124
+ const db = registry.getDatabase(database_id);
125
+ if (!db)
126
+ return `Database with id ${database_id} not found.`;
127
+ if (!db.schema_json)
128
+ return `No schema cached for database "${db.name}". Use trinity_refresh_schema first.`;
129
+ return `Schema for "${db.name}" (${db.type}):\n${db.schema_json}`;
130
+ }
131
+ finally {
132
+ display.endActivity('trinit', true);
133
+ }
121
134
  }, {
122
135
  name: 'trinity_get_schema',
123
136
  description: 'Get the full cached schema of a registered database by its id.',
@@ -126,9 +139,12 @@ export class Trinity {
126
139
  }),
127
140
  });
128
141
  const refreshSchema = tool(async ({ database_id }) => {
142
+ display.startActivity('trinit', 'Refreshing database schema...');
129
143
  const db = registry.getDatabase(database_id);
130
- if (!db)
144
+ if (!db) {
145
+ display.endActivity('trinit', false);
131
146
  return `Database with id ${database_id} not found.`;
147
+ }
132
148
  try {
133
149
  const schema = await introspectSchema(db);
134
150
  registry.updateSchema(database_id, JSON.stringify(schema, null, 2));
@@ -140,8 +156,12 @@ export class Trinity {
140
156
  return `Schema refreshed for "${db.name}". Tables: ${schema.tables.map((t) => t.name).join(', ')}`;
141
157
  }
142
158
  catch (err) {
159
+ display.endActivity('trinit', false);
143
160
  return `Failed to refresh schema for "${db.name}": ${err.message}`;
144
161
  }
162
+ finally {
163
+ display.endActivity('trinit', true);
164
+ }
145
165
  }, {
146
166
  name: 'trinity_refresh_schema',
147
167
  description: 'Re-introspect and update the cached schema for a registered database.',
@@ -150,18 +170,23 @@ export class Trinity {
150
170
  }),
151
171
  });
152
172
  const testConnectionTool = tool(async ({ database_id }) => {
153
- const db = registry.getDatabase(database_id);
154
- if (!db)
155
- return `Database with id ${database_id} not found.`;
173
+ display.startActivity('trinit', 'Testing database connection...');
156
174
  try {
175
+ const db = registry.getDatabase(database_id);
176
+ if (!db)
177
+ return `Database with id ${database_id} not found.`;
157
178
  const ok = await testConnection(db);
158
179
  return ok
159
180
  ? `Connection to "${db.name}" (${db.type}) successful.`
160
181
  : `Connection to "${db.name}" (${db.type}) failed.`;
161
182
  }
162
183
  catch (err) {
184
+ display.endActivity('trinit', false);
163
185
  return `Connection test failed: ${err.message}`;
164
186
  }
187
+ finally {
188
+ display.endActivity('trinit', true);
189
+ }
165
190
  }, {
166
191
  name: 'trinity_test_connection',
167
192
  description: 'Test connectivity to a registered database.',
@@ -170,10 +195,11 @@ export class Trinity {
170
195
  }),
171
196
  });
172
197
  const executeQueryTool = tool(async ({ database_id, query, params, }) => {
173
- const db = registry.getDatabase(database_id);
174
- if (!db)
175
- return `Database with id ${database_id} not found.`;
198
+ display.startActivity('trinit', 'Executing database query...');
176
199
  try {
200
+ const db = registry.getDatabase(database_id);
201
+ if (!db)
202
+ return `Database with id ${database_id} not found.`;
177
203
  const result = await executeQuery(db, query, params);
178
204
  if (result.rows.length === 0)
179
205
  return `Query returned 0 rows. (rowCount: ${result.rowCount})`;
@@ -183,8 +209,12 @@ export class Trinity {
183
209
  return `Rows (${result.rowCount}):\n${json}${note}`;
184
210
  }
185
211
  catch (err) {
212
+ display.endActivity('trinit', false);
186
213
  return `Query execution failed: ${err.message}`;
187
214
  }
215
+ finally {
216
+ display.endActivity('trinit', true);
217
+ }
188
218
  }, {
189
219
  name: 'trinity_execute_query',
190
220
  description: 'Execute a SQL query (PostgreSQL/MySQL/SQLite) or MongoDB JSON command on a registered database. ' +
@@ -7,24 +7,28 @@ function instrumentMcpTool(tool, serverName, getSessionId) {
7
7
  tool._call = async function (input, runManager) {
8
8
  const startMs = Date.now();
9
9
  const sessionId = getSessionId() ?? 'unknown';
10
+ const toolName = `${serverName}/${tool.name}`;
11
+ display.startActivity('neo', `MCP tool: ${tool.name}`);
10
12
  try {
11
13
  const result = await original(input, runManager);
12
14
  AuditRepository.getInstance().insert({
13
15
  session_id: sessionId,
14
16
  event_type: 'mcp_tool',
15
17
  agent: 'neo',
16
- tool_name: `${serverName}/${tool.name}`,
18
+ tool_name: toolName,
17
19
  duration_ms: Date.now() - startMs,
18
20
  status: 'success',
19
21
  });
22
+ display.endActivity('neo', true);
20
23
  return result;
21
24
  }
22
25
  catch (err) {
26
+ display.endActivity('neo', false);
23
27
  AuditRepository.getInstance().insert({
24
28
  session_id: sessionId,
25
29
  event_type: 'mcp_tool',
26
30
  agent: 'neo',
27
- tool_name: `${serverName}/${tool.name}`,
31
+ tool_name: toolName,
28
32
  duration_ms: Date.now() - startMs,
29
33
  status: 'error',
30
34
  metadata: { error: err?.message ?? String(err) },
@@ -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-M-5UGwoK.js";import{u as R}from"./agents-CN_AKX_I.js";import{u as O}from"./useCurrency-CEc5edm2.js";import{Y as _,V as F,h as L,i as I,au as v,I as j,o as N,A as z,g as S,ay as U,k as W,N as w,az as V,O as A,r as P,ak as H}from"./vendor-icons-DE7PWdkN.js";import"./vendor-utils-BIYveU_1.js";import"./index-Db1XEN8v.js";import"./config-7LGRnJ26.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 K({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 Y={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(w,{size:13}),chronos_job:e.jsx(S,{size:13}),task_created:e.jsx(H,{size:13}),task_completed:e.jsx(P,{size:13})},Z={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(I,{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(S,{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(U,{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(W,{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 ${Z[t]??"text-gray-400"}`,children:Y[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(w,{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(K,{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(V,{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-CP5fC4m8.js";import{u as R}from"./agents-DO69pNM1.js";import{u as O}from"./useCurrency-Bgg-7MTE.js";import{Y as _,V as F,h as L,i as I,au as v,I as j,o as N,A as z,g as S,ay as U,k as W,N as w,az as V,O as A,r as P,ak as H}from"./vendor-icons-DE7PWdkN.js";import"./vendor-utils-BIYveU_1.js";import"./index-B9ePr-vB.js";import"./config-OLGQFNJL.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 K({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 Y={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(w,{size:13}),chronos_job:e.jsx(S,{size:13}),task_created:e.jsx(H,{size:13}),task_completed:e.jsx(P,{size:13})},Z={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(I,{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(S,{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(U,{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(W,{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 ${Z[t]??"text-gray-400"}`,children:Y[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(w,{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(K,{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(V,{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};