morpheus-cli 0.9.31 → 0.9.33
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.
- package/dist/runtime/memory/sati/service.js +13 -3
- package/dist/runtime/memory/sqlite.js +66 -1
- package/dist/runtime/oracle.js +18 -7
- package/dist/runtime/tasks/event-bus.js +11 -0
- package/dist/runtime/tasks/notifier.js +57 -31
- package/dist/runtime/tasks/repository.js +21 -0
- package/dist/runtime/tasks/worker.js +11 -7
- package/dist/ui/assets/{AuditDashboard-tH9QZTl4.js → AuditDashboard-rap15I-4.js} +1 -1
- package/dist/ui/assets/Chat-CnuRZFBT.js +41 -0
- package/dist/ui/assets/{Chronos-CWwHYdBl.js → Chronos-C81_HP6e.js} +1 -1
- package/dist/ui/assets/{ConfirmationModal-CxvFe-We.js → ConfirmationModal-CT_v8cAi.js} +1 -1
- package/dist/ui/assets/{Dashboard-CNNMxl53.js → Dashboard-0VfNJ9BZ.js} +1 -1
- package/dist/ui/assets/{DeleteConfirmationModal-AqGQSh1X.js → DeleteConfirmationModal-P2foiqon.js} +1 -1
- package/dist/ui/assets/{Documents-BfRYOK88.js → Documents-C8UfbcGD.js} +1 -1
- package/dist/ui/assets/{Logs-DhFo4cio.js → Logs-qdsCW9u9.js} +1 -1
- package/dist/ui/assets/{MCPManager-BMhxbhni.js → MCPManager-CaZLnrKz.js} +1 -1
- package/dist/ui/assets/{ModelPricing-Dvl0R_HR.js → ModelPricing-C73OfGhc.js} +1 -1
- package/dist/ui/assets/{Notifications-CawvBid4.js → Notifications-CwqeagwF.js} +1 -1
- package/dist/ui/assets/{Pagination-D4ShqUKO.js → Pagination-3P6KG-u6.js} +1 -1
- package/dist/ui/assets/{SatiMemories-yyVrJGdc.js → SatiMemories-CVhOdyAk.js} +1 -1
- package/dist/ui/assets/{SessionAudit-joq0ntdJ.js → SessionAudit-Cykp4Sv_.js} +2 -2
- package/dist/ui/assets/{Settings-B6SMPn41.js → Settings-DnyG6tDx.js} +1 -1
- package/dist/ui/assets/{Skills-B5yhTHyn.js → Skills-B6io4GZh.js} +1 -1
- package/dist/ui/assets/{Smiths-Dug63YED.js → Smiths-XoDzX1K0.js} +1 -1
- package/dist/ui/assets/{Tasks-D8HPLkg0.js → Tasks-vui0C_76.js} +1 -1
- package/dist/ui/assets/{TrinityDatabases-D0qEKmwJ.js → TrinityDatabases-Dp71dyUn.js} +1 -1
- package/dist/ui/assets/{UsageStats-CHWALN70.js → UsageStats-Dz4LXfr4.js} +1 -1
- package/dist/ui/assets/{WebhookManager-T2ef90p8.js → WebhookManager-CC4Mbo2v.js} +1 -1
- package/dist/ui/assets/{agents-BVnfnJ1X.js → agents-DV1oGA7P.js} +1 -1
- package/dist/ui/assets/{audit-BErc_ye8.js → audit-DnegNntR.js} +1 -1
- package/dist/ui/assets/{chronos-CAv__H3B.js → chronos-BDlP8kzg.js} +1 -1
- package/dist/ui/assets/{config-CPFW7PTY.js → config-BhjCL4aM.js} +1 -1
- package/dist/ui/assets/{index-BvsF1a9j.js → index-C3qfojVn.js} +3 -3
- package/dist/ui/assets/{mcp-BaHwY4DW.js → mcp-uYhIyjyx.js} +1 -1
- package/dist/ui/assets/{skills-lbjIRO8d.js → skills-_9hplz7d.js} +1 -1
- package/dist/ui/assets/{stats-C8KAfpHO.js → stats-BwaWi9yN.js} +1 -1
- package/dist/ui/assets/{useCurrency-Ch0lsvGj.js → useCurrency-RBarItCC.js} +1 -1
- package/dist/ui/assets/{vendor-icons-DE7PWdkN.js → vendor-icons-tocJCdt5.js} +1 -1
- package/dist/ui/index.html +2 -2
- package/dist/ui/sw.js +1 -1
- package/package.json +1 -1
- package/dist/ui/assets/Chat-Cd0uYF8g.js +0 -41
|
@@ -12,6 +12,8 @@ const display = DisplayManager.getInstance();
|
|
|
12
12
|
export class SatiService {
|
|
13
13
|
repository;
|
|
14
14
|
static instance;
|
|
15
|
+
cachedAgent = null;
|
|
16
|
+
cachedAgentConfigKey = null;
|
|
15
17
|
constructor() {
|
|
16
18
|
this.repository = SatiRepository.getInstance();
|
|
17
19
|
}
|
|
@@ -59,9 +61,17 @@ export class SatiService {
|
|
|
59
61
|
const satiConfig = ConfigManager.getInstance().getSatiConfig();
|
|
60
62
|
if (!satiConfig)
|
|
61
63
|
return;
|
|
62
|
-
//
|
|
63
|
-
|
|
64
|
-
|
|
64
|
+
// Reuse cached agent when config hasn't changed to avoid per-call overhead
|
|
65
|
+
const configKey = `${satiConfig.provider}:${satiConfig.model}`;
|
|
66
|
+
let agent;
|
|
67
|
+
if (this.cachedAgent && this.cachedAgentConfigKey === configKey) {
|
|
68
|
+
agent = this.cachedAgent;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
agent = await ProviderFactory.create(satiConfig, []);
|
|
72
|
+
this.cachedAgent = agent;
|
|
73
|
+
this.cachedAgentConfigKey = configKey;
|
|
74
|
+
}
|
|
65
75
|
// Get existing memories for context (Simulated "Working Memory" or full list if small)
|
|
66
76
|
const allMemories = this.repository.getAllMemories();
|
|
67
77
|
// Map conversation to strict types and sanitize
|
|
@@ -10,6 +10,48 @@ export class SQLiteChatMessageHistory extends BaseListChatMessageHistory {
|
|
|
10
10
|
lc_namespace = ["langchain", "stores", "message", "sqlite"];
|
|
11
11
|
display = DisplayManager.getInstance();
|
|
12
12
|
static migrationDone = false; // run migrations only once per process
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// In-memory message cache — eliminates repeated SQLite reads for active sessions
|
|
15
|
+
// Key: sessionId Value: { messages (DESC order, newest first), touchedAt, limit }
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
static _cache = new Map();
|
|
18
|
+
static _CACHE_MAX_SESSIONS = 50;
|
|
19
|
+
static _CACHE_TTL_MS = 30 * 60 * 1000; // 30 minutes
|
|
20
|
+
/** Populate or replace a cache entry, evicting LRU if over capacity. */
|
|
21
|
+
static _setCacheEntry(sessionId, messages, limit) {
|
|
22
|
+
if (!sessionId)
|
|
23
|
+
return;
|
|
24
|
+
if (SQLiteChatMessageHistory._cache.size >= SQLiteChatMessageHistory._CACHE_MAX_SESSIONS) {
|
|
25
|
+
let oldestKey = '';
|
|
26
|
+
let oldestTime = Infinity;
|
|
27
|
+
for (const [k, v] of SQLiteChatMessageHistory._cache) {
|
|
28
|
+
if (v.touchedAt < oldestTime) {
|
|
29
|
+
oldestTime = v.touchedAt;
|
|
30
|
+
oldestKey = k;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (oldestKey)
|
|
34
|
+
SQLiteChatMessageHistory._cache.delete(oldestKey);
|
|
35
|
+
}
|
|
36
|
+
SQLiteChatMessageHistory._cache.set(sessionId, { messages: [...messages], touchedAt: Date.now(), limit });
|
|
37
|
+
}
|
|
38
|
+
/** Remove a session from the cache (used on clear()). */
|
|
39
|
+
static invalidateCacheForSession(sessionId) {
|
|
40
|
+
SQLiteChatMessageHistory._cache.delete(sessionId);
|
|
41
|
+
}
|
|
42
|
+
/** Prepend new messages (newest-first order) to an existing cache entry. */
|
|
43
|
+
static _appendToCache(sessionId, newMessages) {
|
|
44
|
+
if (!sessionId || newMessages.length === 0)
|
|
45
|
+
return;
|
|
46
|
+
const entry = SQLiteChatMessageHistory._cache.get(sessionId);
|
|
47
|
+
if (!entry)
|
|
48
|
+
return; // session not cached — will be populated on next read
|
|
49
|
+
// newMessages is in chronological order (oldest first); reverse so newest goes first
|
|
50
|
+
const newestFirst = [...newMessages].reverse();
|
|
51
|
+
const merged = [...newestFirst, ...entry.messages];
|
|
52
|
+
entry.messages = merged.slice(0, entry.limit);
|
|
53
|
+
entry.touchedAt = Date.now();
|
|
54
|
+
}
|
|
13
55
|
db;
|
|
14
56
|
sessionId;
|
|
15
57
|
limit;
|
|
@@ -281,6 +323,21 @@ export class SQLiteChatMessageHistory extends BaseListChatMessageHistory {
|
|
|
281
323
|
*/
|
|
282
324
|
async getMessages() {
|
|
283
325
|
try {
|
|
326
|
+
// -----------------------------------------------------------------------
|
|
327
|
+
// Cache fast-path: return cached messages if session is warm and not stale
|
|
328
|
+
// -----------------------------------------------------------------------
|
|
329
|
+
if (this.sessionId) {
|
|
330
|
+
const cached = SQLiteChatMessageHistory._cache.get(this.sessionId);
|
|
331
|
+
if (cached) {
|
|
332
|
+
const isStale = Date.now() - cached.touchedAt > SQLiteChatMessageHistory._CACHE_TTL_MS;
|
|
333
|
+
if (!isStale) {
|
|
334
|
+
cached.touchedAt = Date.now();
|
|
335
|
+
return [...cached.messages]; // defensive copy
|
|
336
|
+
}
|
|
337
|
+
// Stale — evict and fall through to DB
|
|
338
|
+
SQLiteChatMessageHistory._cache.delete(this.sessionId);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
284
341
|
// Fetch new columns
|
|
285
342
|
const stmt = this.db.prepare(`SELECT type, content, input_tokens, output_tokens, total_tokens, cache_read_tokens, provider, model
|
|
286
343
|
FROM messages
|
|
@@ -358,7 +415,10 @@ export class SQLiteChatMessageHistory extends BaseListChatMessageHistory {
|
|
|
358
415
|
// Messages are in DESC order (newest first) here — orphans appear at the tail.
|
|
359
416
|
// Remove trailing ToolMessages and AIMessages with tool_calls that have no
|
|
360
417
|
// matching ToolMessage response (i.e. incomplete tool-call groups at the boundary).
|
|
361
|
-
|
|
418
|
+
const result = this.sanitizeMessageWindow(mapped);
|
|
419
|
+
// Populate cache for subsequent reads in this session
|
|
420
|
+
SQLiteChatMessageHistory._setCacheEntry(this.sessionId, result, this.limit ?? 100);
|
|
421
|
+
return result;
|
|
362
422
|
}
|
|
363
423
|
catch (error) {
|
|
364
424
|
// Check if it's a database lock error
|
|
@@ -459,6 +519,8 @@ export class SQLiteChatMessageHistory extends BaseListChatMessageHistory {
|
|
|
459
519
|
}
|
|
460
520
|
const stmt = this.db.prepare("INSERT INTO messages (session_id, type, content, created_at, input_tokens, output_tokens, total_tokens, cache_read_tokens, provider, model, audio_duration_seconds, agent, duration_ms, source) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
461
521
|
stmt.run(this.sessionId, type, finalContent, Date.now(), inputTokens, outputTokens, totalTokens, cacheReadTokens, provider, model, audioDurationSeconds, agent, durationMs, source);
|
|
522
|
+
// Update in-memory cache so the next getMessages() call is a cache hit
|
|
523
|
+
SQLiteChatMessageHistory._appendToCache(this.sessionId, [message]);
|
|
462
524
|
// Verificar se a sessão tem título e definir automaticamente se necessário
|
|
463
525
|
await this.setSessionTitleIfNeeded();
|
|
464
526
|
}
|
|
@@ -517,6 +579,8 @@ export class SQLiteChatMessageHistory extends BaseListChatMessageHistory {
|
|
|
517
579
|
});
|
|
518
580
|
try {
|
|
519
581
|
insertAll(messages);
|
|
582
|
+
// Update in-memory cache so the next getMessages() call is a cache hit
|
|
583
|
+
SQLiteChatMessageHistory._appendToCache(this.sessionId, messages);
|
|
520
584
|
await this.setSessionTitleIfNeeded();
|
|
521
585
|
}
|
|
522
586
|
catch (error) {
|
|
@@ -743,6 +807,7 @@ export class SQLiteChatMessageHistory extends BaseListChatMessageHistory {
|
|
|
743
807
|
try {
|
|
744
808
|
const stmt = this.db.prepare("DELETE FROM messages WHERE session_id = ?");
|
|
745
809
|
stmt.run(this.sessionId);
|
|
810
|
+
SQLiteChatMessageHistory._cache.delete(this.sessionId);
|
|
746
811
|
}
|
|
747
812
|
catch (error) {
|
|
748
813
|
// Check for database lock errors
|
package/dist/runtime/oracle.js
CHANGED
|
@@ -19,7 +19,7 @@ import { SetupRepository } from './setup/repository.js';
|
|
|
19
19
|
import { buildSetupTool } from './tools/setup-tool.js';
|
|
20
20
|
import { SmithDelegator } from "./smiths/delegator.js";
|
|
21
21
|
import { PATHS } from "../config/paths.js";
|
|
22
|
-
import {
|
|
22
|
+
import { writeFile } from "fs/promises";
|
|
23
23
|
export class Oracle {
|
|
24
24
|
provider;
|
|
25
25
|
config;
|
|
@@ -200,6 +200,13 @@ export class Oracle {
|
|
|
200
200
|
this.registerSmithIfEnabled();
|
|
201
201
|
// Refresh dynamic tool catalogs so delegate descriptions contain runtime info.
|
|
202
202
|
await SubagentRegistry.refreshAllCatalogs();
|
|
203
|
+
// Eagerly initialize subagents so first delegation doesn't pay init cost.
|
|
204
|
+
await Promise.allSettled([
|
|
205
|
+
Apoc.getInstance().initialize(),
|
|
206
|
+
Neo.getInstance().initialize(),
|
|
207
|
+
Trinity.getInstance().initialize(),
|
|
208
|
+
Link.getInstance().initialize(),
|
|
209
|
+
]);
|
|
203
210
|
// Initialize setup repository (creates table if needed)
|
|
204
211
|
SetupRepository.getInstance();
|
|
205
212
|
const coreTools = [
|
|
@@ -459,10 +466,7 @@ ${SkillRegistry.getInstance().getSystemPromptSection()}
|
|
|
459
466
|
${SmithRegistry.getInstance().getSystemPromptSection()}
|
|
460
467
|
`);
|
|
461
468
|
//save the system prompt on ~/.morpheus/system_prompt.txt for debugging and prompt engineering purposes
|
|
462
|
-
|
|
463
|
-
writeFileSync(`${PATHS.root}/system_prompt.txt`, String(systemMessage.content), 'utf-8');
|
|
464
|
-
}
|
|
465
|
-
catch { }
|
|
469
|
+
writeFile(`${PATHS.root}/system_prompt.txt`, String(systemMessage.content), 'utf-8').catch(() => { });
|
|
466
470
|
// Resolve the authoritative session ID for this call.
|
|
467
471
|
// Priority: explicit taskContext > current history instance > fallback.
|
|
468
472
|
const currentSessionId = taskContext?.session_id
|
|
@@ -482,13 +486,20 @@ ${SmithRegistry.getInstance().getSystemPromptSection()}
|
|
|
482
486
|
// Load existing history from database in reverse order (most recent first)
|
|
483
487
|
let previousMessages = await callHistory.getMessages();
|
|
484
488
|
previousMessages = previousMessages.reverse();
|
|
485
|
-
// Sati Middleware: Retrieval
|
|
489
|
+
// Sati Middleware: Retrieval (with 3s timeout to avoid blocking the response)
|
|
486
490
|
let memoryMessage = null;
|
|
487
491
|
try {
|
|
488
|
-
|
|
492
|
+
const satiTimeout = new Promise((resolve) => setTimeout(() => resolve(null), 3000));
|
|
493
|
+
memoryMessage = await Promise.race([
|
|
494
|
+
this.satiMiddleware.beforeAgent(message, previousMessages, currentSessionId),
|
|
495
|
+
satiTimeout,
|
|
496
|
+
]);
|
|
489
497
|
if (memoryMessage) {
|
|
490
498
|
this.display.log('Sati memory retrieved.', { source: 'Sati' });
|
|
491
499
|
}
|
|
500
|
+
else if (memoryMessage === null) {
|
|
501
|
+
// Could be timeout or no memories found — either way, proceed
|
|
502
|
+
}
|
|
492
503
|
}
|
|
493
504
|
catch (e) {
|
|
494
505
|
// Fail open - do not disrupt main flow
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
/**
|
|
3
|
+
* Singleton event bus for task lifecycle events.
|
|
4
|
+
* Emitted by TaskWorker, consumed by TaskNotifier for immediate dispatch.
|
|
5
|
+
*
|
|
6
|
+
* Events:
|
|
7
|
+
* 'task:ready' (taskId: string) — task is completed/failed/cancelled and ready to notify
|
|
8
|
+
*/
|
|
9
|
+
class TaskEventBus extends EventEmitter {
|
|
10
|
+
}
|
|
11
|
+
export const taskEventBus = new TaskEventBus();
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { DisplayManager } from '../display.js';
|
|
2
2
|
import { TaskDispatcher } from './dispatcher.js';
|
|
3
3
|
import { TaskRepository } from './repository.js';
|
|
4
|
+
import { taskEventBus } from './event-bus.js';
|
|
4
5
|
export class TaskNotifier {
|
|
5
|
-
pollIntervalMs;
|
|
6
6
|
maxAttempts;
|
|
7
7
|
staleSendingMs;
|
|
8
|
-
|
|
8
|
+
recoveryPollMs;
|
|
9
9
|
repository = TaskRepository.getInstance();
|
|
10
10
|
display = DisplayManager.getInstance();
|
|
11
11
|
timer = null;
|
|
12
|
-
|
|
12
|
+
inFlight = new Set(); // task IDs currently being dispatched
|
|
13
13
|
constructor(opts) {
|
|
14
|
-
this.pollIntervalMs = opts?.pollIntervalMs ?? 1200;
|
|
15
14
|
this.maxAttempts = opts?.maxAttempts ?? 5;
|
|
16
15
|
this.staleSendingMs = opts?.staleSendingMs ?? 30_000;
|
|
17
|
-
|
|
16
|
+
// Slow poll only for orphan recovery (process restarts, crash scenarios)
|
|
17
|
+
this.recoveryPollMs = opts?.recoveryPollMs ?? 30_000;
|
|
18
18
|
}
|
|
19
19
|
start() {
|
|
20
20
|
if (this.timer)
|
|
@@ -26,43 +26,69 @@ export class TaskNotifier {
|
|
|
26
26
|
level: 'warning',
|
|
27
27
|
});
|
|
28
28
|
}
|
|
29
|
+
// Primary path: event-driven — fires immediately when TaskWorker completes a task
|
|
30
|
+
taskEventBus.on('task:ready', (taskId) => {
|
|
31
|
+
this.dispatchById(taskId);
|
|
32
|
+
});
|
|
33
|
+
// Fallback path: slow poll for orphaned tasks (e.g. completed before notifier started,
|
|
34
|
+
// or process restarted mid-notification)
|
|
29
35
|
this.timer = setInterval(() => {
|
|
30
|
-
void this.
|
|
31
|
-
}, this.
|
|
32
|
-
this.display.log('Task notifier started.', { source: 'TaskNotifier' });
|
|
36
|
+
void this.recoveryTick();
|
|
37
|
+
}, this.recoveryPollMs);
|
|
38
|
+
this.display.log('Task notifier started (event-driven + 30s recovery poll).', { source: 'TaskNotifier' });
|
|
33
39
|
}
|
|
34
40
|
stop() {
|
|
41
|
+
taskEventBus.removeAllListeners('task:ready');
|
|
35
42
|
if (this.timer) {
|
|
36
43
|
clearInterval(this.timer);
|
|
37
44
|
this.timer = null;
|
|
38
|
-
this.display.log('Task notifier stopped.', { source: 'TaskNotifier' });
|
|
39
45
|
}
|
|
46
|
+
this.display.log('Task notifier stopped.', { source: 'TaskNotifier' });
|
|
40
47
|
}
|
|
41
|
-
|
|
42
|
-
|
|
48
|
+
/**
|
|
49
|
+
* Event-driven dispatch: called immediately when a task is marked complete/failed.
|
|
50
|
+
* Uses claimNotificationById to atomically claim — prevents double-dispatch with recovery poll.
|
|
51
|
+
*/
|
|
52
|
+
dispatchById(taskId) {
|
|
53
|
+
if (this.inFlight.has(taskId))
|
|
43
54
|
return;
|
|
44
|
-
this.
|
|
45
|
-
|
|
46
|
-
|
|
55
|
+
this.inFlight.add(taskId);
|
|
56
|
+
const task = this.repository.claimNotificationById(taskId);
|
|
57
|
+
if (!task) {
|
|
58
|
+
// Already claimed by recovery poll or another path
|
|
59
|
+
this.inFlight.delete(taskId);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
void this.dispatch(task).finally(() => this.inFlight.delete(taskId));
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Fallback recovery: picks up any orphaned completed tasks not yet notified.
|
|
66
|
+
*/
|
|
67
|
+
async recoveryTick() {
|
|
68
|
+
// Drain all pending orphans in one recovery sweep
|
|
69
|
+
while (true) {
|
|
70
|
+
const task = this.repository.claimNextNotificationCandidate(0);
|
|
47
71
|
if (!task)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
catch (err) {
|
|
54
|
-
const latest = this.repository.getTaskById(task.id);
|
|
55
|
-
const attempts = (latest?.notify_attempts ?? 0) + 1;
|
|
56
|
-
const retry = attempts < this.maxAttempts;
|
|
57
|
-
this.repository.markNotificationFailed(task.id, err?.message ?? String(err), retry);
|
|
58
|
-
this.display.log(`Task notification failed (${task.id}): ${err?.message ?? err}`, {
|
|
59
|
-
source: 'TaskNotifier',
|
|
60
|
-
level: retry ? 'warning' : 'error',
|
|
61
|
-
});
|
|
62
|
-
}
|
|
72
|
+
break;
|
|
73
|
+
if (this.inFlight.has(task.id))
|
|
74
|
+
break; // already being dispatched via event
|
|
75
|
+
await this.dispatch(task);
|
|
63
76
|
}
|
|
64
|
-
|
|
65
|
-
|
|
77
|
+
}
|
|
78
|
+
async dispatch(task) {
|
|
79
|
+
try {
|
|
80
|
+
await TaskDispatcher.onTaskFinished(task);
|
|
81
|
+
this.repository.markNotificationSent(task.id);
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
const latest = this.repository.getTaskById(task.id);
|
|
85
|
+
const attempts = (latest?.notify_attempts ?? 0) + 1;
|
|
86
|
+
const retry = attempts < this.maxAttempts;
|
|
87
|
+
this.repository.markNotificationFailed(task.id, err?.message ?? String(err), retry);
|
|
88
|
+
this.display.log(`Task notification failed (${task.id}): ${err?.message ?? err}`, {
|
|
89
|
+
source: 'TaskNotifier',
|
|
90
|
+
level: retry ? 'warning' : 'error',
|
|
91
|
+
});
|
|
66
92
|
}
|
|
67
93
|
}
|
|
68
94
|
}
|
|
@@ -393,6 +393,27 @@ export class TaskRepository {
|
|
|
393
393
|
`).run(now, now, now - staleMs);
|
|
394
394
|
return result.changes;
|
|
395
395
|
}
|
|
396
|
+
/**
|
|
397
|
+
* Atomically claim a specific task for notification by ID.
|
|
398
|
+
* Returns the task record if successfully claimed, null if already claimed or not eligible.
|
|
399
|
+
*/
|
|
400
|
+
claimNotificationById(taskId) {
|
|
401
|
+
const tx = this.db.transaction(() => {
|
|
402
|
+
const changed = this.db.prepare(`
|
|
403
|
+
UPDATE tasks
|
|
404
|
+
SET notify_status = 'sending',
|
|
405
|
+
notify_last_error = NULL,
|
|
406
|
+
updated_at = ?
|
|
407
|
+
WHERE id = ?
|
|
408
|
+
AND status IN ('completed', 'failed', 'cancelled')
|
|
409
|
+
AND notify_status = 'pending'
|
|
410
|
+
`).run(Date.now(), taskId);
|
|
411
|
+
if (changed.changes === 0)
|
|
412
|
+
return null;
|
|
413
|
+
return this.getTaskById(taskId);
|
|
414
|
+
});
|
|
415
|
+
return tx();
|
|
416
|
+
}
|
|
396
417
|
claimNextNotificationCandidate(minFinishedAgeMs = 0) {
|
|
397
418
|
const now = Date.now();
|
|
398
419
|
const tx = this.db.transaction(() => {
|
|
@@ -3,6 +3,7 @@ import { DisplayManager } from '../display.js';
|
|
|
3
3
|
import { SubagentRegistry } from '../subagents/registry.js';
|
|
4
4
|
import { TaskRepository } from './repository.js';
|
|
5
5
|
import { AuditRepository } from '../audit/repository.js';
|
|
6
|
+
import { taskEventBus } from './event-bus.js';
|
|
6
7
|
export class TaskWorker {
|
|
7
8
|
workerId;
|
|
8
9
|
pollIntervalMs;
|
|
@@ -38,13 +39,14 @@ export class TaskWorker {
|
|
|
38
39
|
}
|
|
39
40
|
}
|
|
40
41
|
tick() {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
// Claim as many tasks as concurrency allows per tick
|
|
43
|
+
while (this.activeTasks.size < this.maxConcurrent) {
|
|
44
|
+
const task = this.repository.claimNextPending(this.workerId);
|
|
45
|
+
if (!task)
|
|
46
|
+
break;
|
|
47
|
+
this.activeTasks.add(task.id);
|
|
48
|
+
this.executeTask(task).finally(() => this.activeTasks.delete(task.id));
|
|
49
|
+
}
|
|
48
50
|
}
|
|
49
51
|
async executeTask(task) {
|
|
50
52
|
const audit = AuditRepository.getInstance();
|
|
@@ -94,6 +96,7 @@ export class TaskWorker {
|
|
|
94
96
|
});
|
|
95
97
|
}
|
|
96
98
|
this.display.log(`Task completed: ${task.id}`, { source: 'TaskWorker', level: 'success' });
|
|
99
|
+
taskEventBus.emit('task:ready', task.id);
|
|
97
100
|
}
|
|
98
101
|
catch (err) {
|
|
99
102
|
const latest = this.repository.getTaskById(task.id);
|
|
@@ -116,6 +119,7 @@ export class TaskWorker {
|
|
|
116
119
|
metadata: { error: errorMessage },
|
|
117
120
|
});
|
|
118
121
|
this.display.log(`Task failed: ${task.id} (${errorMessage})`, { source: 'TaskWorker', level: 'error' });
|
|
122
|
+
taskEventBus.emit('task:ready', task.id);
|
|
119
123
|
}
|
|
120
124
|
}
|
|
121
125
|
}
|
|
@@ -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-BErc_ye8.js";import{u as R}from"./agents-BVnfnJ1X.js";import{u as O}from"./useCurrency-Ch0lsvGj.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-BvsF1a9j.js";import"./config-CPFW7PTY.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-DnegNntR.js";import{u as R}from"./agents-DV1oGA7P.js";import{u as F}from"./useCurrency-RBarItCC.js";import{Y as _,V as O,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,Q as A,r as P,ak as H}from"./vendor-icons-tocJCdt5.js";import"./vendor-utils-BIYveU_1.js";import"./index-C3qfojVn.js";import"./config-BhjCL4aM.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 Q={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})},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 Z({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}=F();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(O,{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 ${Y[t]??"text-gray-400"}`,children:Q[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(Z,{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};
|