morpheus-cli 0.9.13 → 0.9.22
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/README.md +48 -17
- package/dist/channels/discord.js +93 -6
- package/dist/channels/telegram.js +109 -9
- package/dist/cli/commands/start.js +15 -0
- package/dist/config/manager.js +20 -1
- package/dist/config/paths.js +4 -0
- package/dist/config/schemas.js +15 -0
- package/dist/http/api.js +5 -1
- package/dist/http/middleware/auth.js +2 -1
- package/dist/http/routers/danger.js +4 -5
- package/dist/http/routers/display.js +33 -0
- package/dist/http/routers/link.js +2 -2
- package/dist/runtime/__tests__/telephonist-tts.test.js +84 -0
- package/dist/runtime/adapters/AuditRepositoryAdapter.js +6 -0
- package/dist/runtime/adapters/ChannelNotifierAdapter.js +9 -0
- package/dist/runtime/adapters/LangChainProviderAdapter.js +9 -0
- package/dist/runtime/adapters/SQLiteChatHistoryAdapter.js +15 -0
- package/dist/runtime/adapters/SQLiteTaskEnqueuerAdapter.js +6 -0
- package/dist/runtime/adapters/index.js +5 -0
- package/dist/runtime/audit/repository.js +6 -2
- package/dist/runtime/chronos/repository.js +2 -2
- package/dist/runtime/container.js +50 -0
- package/dist/runtime/display.js +17 -2
- package/dist/runtime/hot-reload.js +6 -9
- package/dist/runtime/memory/backfill-embeddings.js +2 -3
- package/dist/runtime/memory/sati/repository.js +3 -3
- package/dist/runtime/memory/sqlite.js +3 -3
- package/dist/runtime/memory/trinity-db.js +2 -2
- package/dist/runtime/ports/IAuditEmitter.js +1 -0
- package/dist/runtime/ports/IChatHistory.js +1 -0
- package/dist/runtime/ports/ILLMProviderFactory.js +1 -0
- package/dist/runtime/ports/INotifier.js +1 -0
- package/dist/runtime/ports/ITaskEnqueuer.js +1 -0
- package/dist/runtime/ports/index.js +1 -0
- package/dist/runtime/providers/factory.js +8 -52
- package/dist/runtime/providers/strategies.js +66 -0
- package/dist/runtime/setup/repository.js +2 -2
- package/dist/runtime/subagents/apoc.js +2 -2
- package/dist/runtime/subagents/link/link.js +2 -2
- package/dist/runtime/subagents/link/repository.js +2 -2
- package/dist/runtime/subagents/link/worker.js +3 -3
- package/dist/runtime/subagents/neo.js +2 -2
- package/dist/runtime/subagents/trinity/trinity.js +2 -2
- package/dist/runtime/tasks/repository.js +2 -2
- package/dist/runtime/telephonist.js +160 -0
- package/dist/runtime/tools/delegation-utils.js +5 -7
- package/dist/runtime/tools/morpheus-tools.js +6 -7
- package/dist/runtime/tools/smith-tool.js +5 -7
- package/dist/runtime/webhooks/repository.js +2 -2
- package/dist/types/config.js +6 -0
- package/dist/ui/assets/AuditDashboard-z3OBbJ8I.js +1 -0
- package/dist/ui/assets/{Chat-UVoDlqqM.js → Chat-aFz9FjrD.js} +7 -7
- package/dist/ui/assets/{Chronos-Dfs_pOsc.js → Chronos-MP_NCj2A.js} +1 -1
- package/dist/ui/assets/{ConfirmationModal-BBIjVef7.js → ConfirmationModal-B3gHIVKY.js} +1 -1
- package/dist/ui/assets/Dashboard-OyZXnj44.js +4120 -0
- package/dist/ui/assets/{DeleteConfirmationModal-Du85q5u2.js → DeleteConfirmationModal-D8QsQzwP.js} +1 -1
- package/dist/ui/assets/{Documents-DguILrI8.js → Documents-B8g_yv4f.js} +1 -1
- package/dist/ui/assets/{Logs-BDup2FET.js → Logs-BWufAtHa.js} +1 -1
- package/dist/ui/assets/{MCPManager-WBdh1rum.js → MCPManager-lLoGEyBy.js} +1 -1
- package/dist/ui/assets/ModelPricing-CuYIUwXt.js +1 -0
- package/dist/ui/assets/Notifications-nI--fmYx.js +1 -0
- package/dist/ui/assets/{Pagination-BHZKk42X.js → Pagination-D4ShqUKO.js} +1 -1
- package/dist/ui/assets/SatiMemories-DO3JDQBi.js +1 -0
- package/dist/ui/assets/{SelectInput-KVLsnfra.js → SelectInput-BPDcd3y7.js} +1 -1
- package/dist/ui/assets/SessionAudit-BWtJRkj1.js +9 -0
- package/dist/ui/assets/Settings-CblauAVd.js +49 -0
- package/dist/ui/assets/Skills-Dw6G5c8W.js +7 -0
- package/dist/ui/assets/Smiths-B6-CnRMv.js +1 -0
- package/dist/ui/assets/Switch-C7TxLq0E.js +1 -0
- package/dist/ui/assets/Tasks-DzUyw5z3.js +1 -0
- package/dist/ui/assets/{TrinityDatabases-DYHJunk7.js → TrinityDatabases-DCjdwnLH.js} +1 -1
- package/dist/ui/assets/{UsageStats-BpGXaHgW.js → UsageStats-VajzjndO.js} +1 -1
- package/dist/ui/assets/{WebhookManager-D2muhYy9.js → WebhookManager-BbfMCiy-.js} +2 -2
- package/dist/ui/assets/{agents-CgqJea9n.js → agents-CN_AKX_I.js} +1 -1
- package/dist/ui/assets/{audit-Dc3YW0-4.js → audit-M-5UGwoK.js} +1 -1
- package/dist/ui/assets/{chronos-CZvGhZQB.js → chronos-mZ0RIvh4.js} +1 -1
- package/dist/ui/assets/config-7LGRnJ26.js +1 -0
- package/dist/ui/assets/index-Bko2TlZY.css +1 -0
- package/dist/ui/assets/{index-Bta9YXEm.js → index-Db1XEN8v.js} +3 -3
- package/dist/ui/assets/{mcp-vIffcwd6.js → mcp-YiYC-9IH.js} +1 -1
- package/dist/ui/assets/{skills-wANsorUj.js → skills-dc6Xqqhb.js} +1 -1
- package/dist/ui/assets/{stats-xnlA4NwX.js → stats-BzqxCDuj.js} +1 -1
- package/dist/ui/assets/useCurrency-CEc5edm2.js +1 -0
- package/dist/ui/assets/vendor-icons-DE7PWdkN.js +1 -0
- package/dist/ui/assets/vendor-utils-BIYveU_1.js +39 -0
- package/dist/ui/index.html +4 -4
- package/dist/ui/sw.js +1 -1
- package/package.json +1 -1
- package/dist/ui/assets/AuditDashboard-BVyKnpVm.js +0 -1
- package/dist/ui/assets/Dashboard-BdSQDB14.js +0 -1
- package/dist/ui/assets/ModelPricing-BQPw0r6z.js +0 -1
- package/dist/ui/assets/Notifications-BslO2Ect.js +0 -1
- package/dist/ui/assets/SatiMemories-DzaLaZ6M.js +0 -1
- package/dist/ui/assets/SessionAudit-CBDThjBi.js +0 -9
- package/dist/ui/assets/Settings-JPTCA7C7.js +0 -49
- package/dist/ui/assets/Skills-BnDg1HCb.js +0 -7
- package/dist/ui/assets/Smiths-DR6g_o3D.js +0 -1
- package/dist/ui/assets/Tasks-BuoNCvI-.js +0 -1
- package/dist/ui/assets/config-pKL8Y4V9.js +0 -1
- package/dist/ui/assets/index-Cjli-AD7.css +0 -1
- package/dist/ui/assets/vendor-icons-NHF9HNeN.js +0 -1
- package/dist/ui/assets/vendor-utils-D4NnWbOU.js +0 -39
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { homedir } from 'os';
|
|
2
|
-
import path from 'path';
|
|
3
1
|
import fs from 'fs-extra';
|
|
4
2
|
import fsSync from 'fs';
|
|
3
|
+
import path from 'path';
|
|
5
4
|
import { LinkRepository } from './repository.js';
|
|
6
5
|
import { LinkSearch } from './search.js';
|
|
7
6
|
import { hashFile, processDocument, isSupportedFormat } from './chunker.js';
|
|
8
7
|
import { EmbeddingService } from '../../memory/embedding.service.js';
|
|
9
8
|
import { ConfigManager } from '../../../config/manager.js';
|
|
10
9
|
import { DisplayManager } from '../../display.js';
|
|
10
|
+
import { PATHS } from '../../../config/paths.js';
|
|
11
11
|
/**
|
|
12
12
|
* LinkWorker - Background worker for document indexing
|
|
13
13
|
*
|
|
@@ -26,7 +26,7 @@ export class LinkWorker {
|
|
|
26
26
|
constructor() {
|
|
27
27
|
this.repository = LinkRepository.getInstance();
|
|
28
28
|
this.search = LinkSearch.getInstance();
|
|
29
|
-
this.docsPath =
|
|
29
|
+
this.docsPath = PATHS.docs;
|
|
30
30
|
}
|
|
31
31
|
static getInstance() {
|
|
32
32
|
if (!LinkWorker.instance) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { HumanMessage, SystemMessage, AIMessage } from "@langchain/core/messages";
|
|
2
2
|
import { ConfigManager } from "../../config/manager.js";
|
|
3
|
-
import {
|
|
3
|
+
import { ServiceContainer, SERVICE_KEYS } from "../container.js";
|
|
4
4
|
import { ProviderError } from "../errors.js";
|
|
5
5
|
import { DisplayManager } from "../display.js";
|
|
6
6
|
import { Construtor } from "../tools/factory.js";
|
|
@@ -101,7 +101,7 @@ export class Neo {
|
|
|
101
101
|
}
|
|
102
102
|
this.display.log(`Neo initialized with ${tools.length} tools (personality: ${personality}).`, { source: "Neo" });
|
|
103
103
|
try {
|
|
104
|
-
this.agent = await
|
|
104
|
+
this.agent = await ServiceContainer.get(SERVICE_KEYS.providerFactory).create(neoConfig, tools);
|
|
105
105
|
}
|
|
106
106
|
catch (err) {
|
|
107
107
|
throw new ProviderError(neoConfig.provider, err, "Neo subagent initialization failed");
|
|
@@ -2,7 +2,7 @@ import { HumanMessage, SystemMessage, AIMessage } from "@langchain/core/messages
|
|
|
2
2
|
import { tool } from "@langchain/core/tools";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { ConfigManager } from "../../../config/manager.js";
|
|
5
|
-
import {
|
|
5
|
+
import { ServiceContainer, SERVICE_KEYS } from "../../container.js";
|
|
6
6
|
import { ProviderError } from "../../errors.js";
|
|
7
7
|
import { DisplayManager } from "../../display.js";
|
|
8
8
|
import { DatabaseRegistry } from "../../memory/trinity-db.js";
|
|
@@ -204,7 +204,7 @@ export class Trinity {
|
|
|
204
204
|
const tools = this.buildTrinityTools();
|
|
205
205
|
this.display.log(`Trinity initialized with ${tools.length} tools (personality: ${personality}).`, { source: 'Trinity' });
|
|
206
206
|
try {
|
|
207
|
-
this.agent = await
|
|
207
|
+
this.agent = await ServiceContainer.get(SERVICE_KEYS.providerFactory).createBare(trinityConfig, tools);
|
|
208
208
|
}
|
|
209
209
|
catch (err) {
|
|
210
210
|
throw new ProviderError(trinityConfig.provider, err, 'Trinity subagent initialization failed');
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import Database from 'better-sqlite3';
|
|
2
2
|
import fs from 'fs-extra';
|
|
3
3
|
import path from 'path';
|
|
4
|
-
import { homedir } from 'os';
|
|
5
4
|
import { randomUUID } from 'crypto';
|
|
5
|
+
import { PATHS } from '../../config/paths.js';
|
|
6
6
|
export class TaskRepository {
|
|
7
7
|
static instance = null;
|
|
8
8
|
db;
|
|
9
9
|
constructor() {
|
|
10
|
-
const dbPath =
|
|
10
|
+
const dbPath = PATHS.shortMemoryDb;
|
|
11
11
|
fs.ensureDirSync(path.dirname(dbPath));
|
|
12
12
|
this.db = new Database(dbPath, { timeout: 5000 });
|
|
13
13
|
this.db.pragma('journal_mode = WAL');
|
|
@@ -2,6 +2,9 @@ import { GoogleGenAI } from '@google/genai';
|
|
|
2
2
|
import OpenAI from 'openai';
|
|
3
3
|
import { OpenRouter } from '@openrouter/sdk';
|
|
4
4
|
import fs from 'fs';
|
|
5
|
+
import fsExtra from 'fs-extra';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import os from 'os';
|
|
5
8
|
import { parseFile } from 'music-metadata';
|
|
6
9
|
/**
|
|
7
10
|
* Returns the actual audio duration in seconds by parsing the file header.
|
|
@@ -25,6 +28,7 @@ async function getAudioDurationSeconds(filePath) {
|
|
|
25
28
|
return 0;
|
|
26
29
|
}
|
|
27
30
|
}
|
|
31
|
+
export const TTS_MAX_CHARS = 4096;
|
|
28
32
|
class GeminiTelephonist {
|
|
29
33
|
model;
|
|
30
34
|
constructor(model) {
|
|
@@ -187,6 +191,162 @@ export function createTelephonist(config) {
|
|
|
187
191
|
throw new Error(`Unsupported audio provider: '${config.provider}'. Supported: google, openai, openrouter, ollama.`);
|
|
188
192
|
}
|
|
189
193
|
}
|
|
194
|
+
// ─── TTS Implementations ─────────────────────────────────────────────────────
|
|
195
|
+
function truncateForTts(text) {
|
|
196
|
+
if (text.length <= TTS_MAX_CHARS)
|
|
197
|
+
return text;
|
|
198
|
+
console.warn(`[Telephonist] TTS input truncated from ${text.length} to ${TTS_MAX_CHARS} chars.`);
|
|
199
|
+
return text.slice(0, TTS_MAX_CHARS);
|
|
200
|
+
}
|
|
201
|
+
function mimeTypeToExt(mimeType) {
|
|
202
|
+
if (mimeType.includes('ogg'))
|
|
203
|
+
return '.ogg';
|
|
204
|
+
if (mimeType.includes('mp3') || mimeType.includes('mpeg'))
|
|
205
|
+
return '.mp3';
|
|
206
|
+
if (mimeType.includes('wav'))
|
|
207
|
+
return '.wav';
|
|
208
|
+
if (mimeType.includes('aac'))
|
|
209
|
+
return '.aac';
|
|
210
|
+
return '.audio';
|
|
211
|
+
}
|
|
212
|
+
async function writeTempAudio(buffer, ext) {
|
|
213
|
+
const filePath = path.join(os.tmpdir(), `morpheus-tts-${Date.now()}${ext}`);
|
|
214
|
+
await fsExtra.writeFile(filePath, buffer);
|
|
215
|
+
return filePath;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Wraps raw PCM data in a WAV container header.
|
|
219
|
+
* Gemini TTS returns audio/pcm at 24000Hz, 16-bit, mono.
|
|
220
|
+
*/
|
|
221
|
+
function pcmToWav(pcmBuffer, sampleRate = 24000, channels = 1, bitDepth = 16) {
|
|
222
|
+
const header = Buffer.alloc(44);
|
|
223
|
+
const dataSize = pcmBuffer.length;
|
|
224
|
+
const byteRate = sampleRate * channels * (bitDepth / 8);
|
|
225
|
+
const blockAlign = channels * (bitDepth / 8);
|
|
226
|
+
header.write('RIFF', 0);
|
|
227
|
+
header.writeUInt32LE(36 + dataSize, 4);
|
|
228
|
+
header.write('WAVE', 8);
|
|
229
|
+
header.write('fmt ', 12);
|
|
230
|
+
header.writeUInt32LE(16, 16); // PCM chunk size
|
|
231
|
+
header.writeUInt16LE(1, 20); // PCM format
|
|
232
|
+
header.writeUInt16LE(channels, 22);
|
|
233
|
+
header.writeUInt32LE(sampleRate, 24);
|
|
234
|
+
header.writeUInt32LE(byteRate, 28);
|
|
235
|
+
header.writeUInt16LE(blockAlign, 32);
|
|
236
|
+
header.writeUInt16LE(bitDepth, 34);
|
|
237
|
+
header.write('data', 36);
|
|
238
|
+
header.writeUInt32LE(dataSize, 40);
|
|
239
|
+
return Buffer.concat([header, pcmBuffer]);
|
|
240
|
+
}
|
|
241
|
+
class OpenAITtsTelephonist {
|
|
242
|
+
model;
|
|
243
|
+
defaultVoice;
|
|
244
|
+
constructor(model, defaultVoice) {
|
|
245
|
+
this.model = model;
|
|
246
|
+
this.defaultVoice = defaultVoice;
|
|
247
|
+
}
|
|
248
|
+
async transcribe() {
|
|
249
|
+
throw new Error('OpenAITtsTelephonist does not support transcription.');
|
|
250
|
+
}
|
|
251
|
+
async synthesize(text, apiKey, voice, stylePrompt) {
|
|
252
|
+
const client = new OpenAI({ apiKey });
|
|
253
|
+
const raw = stylePrompt ? `${stylePrompt}: ${text}` : text;
|
|
254
|
+
const input = truncateForTts(raw);
|
|
255
|
+
const response = await client.audio.speech.create({
|
|
256
|
+
model: this.model,
|
|
257
|
+
voice: (voice || this.defaultVoice),
|
|
258
|
+
input,
|
|
259
|
+
response_format: 'mp3',
|
|
260
|
+
});
|
|
261
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
262
|
+
const filePath = await writeTempAudio(buffer, '.mp3');
|
|
263
|
+
return {
|
|
264
|
+
filePath,
|
|
265
|
+
mimeType: 'audio/mpeg',
|
|
266
|
+
usage: {
|
|
267
|
+
input_tokens: 0,
|
|
268
|
+
output_tokens: 0,
|
|
269
|
+
total_tokens: 0,
|
|
270
|
+
audio_duration_seconds: 0,
|
|
271
|
+
},
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
class GeminiTtsTelephonist {
|
|
276
|
+
model;
|
|
277
|
+
defaultVoice;
|
|
278
|
+
constructor(model, defaultVoice) {
|
|
279
|
+
this.model = model;
|
|
280
|
+
this.defaultVoice = defaultVoice;
|
|
281
|
+
}
|
|
282
|
+
async transcribe() {
|
|
283
|
+
throw new Error('GeminiTtsTelephonist does not support transcription.');
|
|
284
|
+
}
|
|
285
|
+
async synthesize(text, apiKey, voice, stylePrompt) {
|
|
286
|
+
const ai = new GoogleGenAI({ apiKey });
|
|
287
|
+
const raw = stylePrompt ? `${stylePrompt}: ${text}` : text;
|
|
288
|
+
const input = truncateForTts(raw);
|
|
289
|
+
const response = await ai.models.generateContent({
|
|
290
|
+
model: this.model,
|
|
291
|
+
contents: [{ role: 'user', parts: [{ text: input }] }],
|
|
292
|
+
config: {
|
|
293
|
+
responseModalities: ['AUDIO'],
|
|
294
|
+
speechConfig: {
|
|
295
|
+
voiceConfig: {
|
|
296
|
+
prebuiltVoiceConfig: { voiceName: voice || this.defaultVoice },
|
|
297
|
+
},
|
|
298
|
+
},
|
|
299
|
+
},
|
|
300
|
+
});
|
|
301
|
+
const audioPart = response.candidates?.[0]?.content?.parts?.find((p) => p.inlineData?.mimeType?.startsWith('audio/'));
|
|
302
|
+
if (!audioPart?.inlineData?.data) {
|
|
303
|
+
throw new Error('Gemini TTS: no audio data in response');
|
|
304
|
+
}
|
|
305
|
+
const rawMimeType = audioPart.inlineData.mimeType ?? 'audio/pcm';
|
|
306
|
+
const rawBuffer = Buffer.from(audioPart.inlineData.data, 'base64');
|
|
307
|
+
let mimeType = rawMimeType;
|
|
308
|
+
let buffer;
|
|
309
|
+
// Gemini returns raw PCM — wrap it in a WAV container
|
|
310
|
+
if (rawMimeType.includes('pcm') || rawMimeType.includes('l16')) {
|
|
311
|
+
// Parse sample rate from mimeType params e.g. "audio/pcm;rate=24000"
|
|
312
|
+
const rateMatch = rawMimeType.match(/rate=(\d+)/i);
|
|
313
|
+
const sampleRate = rateMatch ? parseInt(rateMatch[1], 10) : 24000;
|
|
314
|
+
buffer = pcmToWav(rawBuffer, sampleRate);
|
|
315
|
+
mimeType = 'audio/wav';
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
buffer = rawBuffer;
|
|
319
|
+
}
|
|
320
|
+
const ext = mimeTypeToExt(mimeType);
|
|
321
|
+
const filePath = await writeTempAudio(buffer, ext);
|
|
322
|
+
const usage = response.usageMetadata;
|
|
323
|
+
return {
|
|
324
|
+
filePath,
|
|
325
|
+
mimeType,
|
|
326
|
+
usage: {
|
|
327
|
+
input_tokens: usage?.promptTokenCount ?? 0,
|
|
328
|
+
output_tokens: usage?.candidatesTokenCount ?? 0,
|
|
329
|
+
total_tokens: usage?.totalTokenCount ?? 0,
|
|
330
|
+
audio_duration_seconds: 0,
|
|
331
|
+
},
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Factory that creates an ITelephonist with TTS (synthesize) support.
|
|
337
|
+
* Supports providers: openai, google.
|
|
338
|
+
*/
|
|
339
|
+
export function createTtsTelephonist(config) {
|
|
340
|
+
switch (config.provider) {
|
|
341
|
+
case 'openai':
|
|
342
|
+
return new OpenAITtsTelephonist(config.model, config.voice);
|
|
343
|
+
case 'google':
|
|
344
|
+
return new GeminiTtsTelephonist(config.model, config.voice);
|
|
345
|
+
default:
|
|
346
|
+
throw new Error(`Unsupported TTS provider: '${config.provider}'. Supported: openai, google.`);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
// ─── Legacy export for backward compatibility ─────────────────────────────────
|
|
190
350
|
// Legacy export for backward compatibility
|
|
191
351
|
export class Telephonist {
|
|
192
352
|
delegate;
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { tool } from "@langchain/core/tools";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
import { TaskRepository } from "../tasks/repository.js";
|
|
4
3
|
import { TaskRequestContext } from "../tasks/context.js";
|
|
5
4
|
import { compositeDelegationError, isLikelyCompositeDelegationTask } from "./delegation-guard.js";
|
|
6
5
|
import { DisplayManager } from "../display.js";
|
|
7
|
-
import {
|
|
8
|
-
import { AuditRepository } from "../audit/repository.js";
|
|
6
|
+
import { ServiceContainer, SERVICE_KEYS } from "../container.js";
|
|
9
7
|
/**
|
|
10
8
|
* Factory that builds a delegation StructuredTool for Apoc/Neo/Trinity.
|
|
11
9
|
* Handles: composite guard, sync branch (notify→execute→audit→increment),
|
|
@@ -33,7 +31,8 @@ export function buildDelegationTool(opts) {
|
|
|
33
31
|
const ctx = TaskRequestContext.get();
|
|
34
32
|
const sessionId = ctx?.session_id ?? "default";
|
|
35
33
|
if (ctx?.origin_channel && ctx.origin_user_id && ctx.origin_channel !== 'api' && ctx.origin_channel !== 'ui') {
|
|
36
|
-
|
|
34
|
+
ServiceContainer.get(SERVICE_KEYS.notifier)
|
|
35
|
+
.sendToUser(ctx.origin_channel, ctx.origin_user_id, notifyText)
|
|
37
36
|
.catch(() => { });
|
|
38
37
|
}
|
|
39
38
|
try {
|
|
@@ -41,7 +40,7 @@ export function buildDelegationTool(opts) {
|
|
|
41
40
|
TaskRequestContext.incrementSyncDelegation();
|
|
42
41
|
display.log(`${agentLabel} sync execution completed.`, { source, level: "info" });
|
|
43
42
|
if (result.usage) {
|
|
44
|
-
|
|
43
|
+
ServiceContainer.get(SERVICE_KEYS.auditEmitter).emit({
|
|
45
44
|
session_id: sessionId,
|
|
46
45
|
event_type: 'llm_call',
|
|
47
46
|
agent: auditAgent,
|
|
@@ -76,8 +75,7 @@ export function buildDelegationTool(opts) {
|
|
|
76
75
|
return "Delegation limit reached for this user turn. Split the request or wait for current tasks.";
|
|
77
76
|
}
|
|
78
77
|
const ctx = TaskRequestContext.get();
|
|
79
|
-
const
|
|
80
|
-
const created = repository.createTask({
|
|
78
|
+
const created = ServiceContainer.get(SERVICE_KEYS.taskEnqueuer).enqueue({
|
|
81
79
|
agent: agentKey,
|
|
82
80
|
input: task,
|
|
83
81
|
context: context ?? null,
|
|
@@ -2,14 +2,13 @@ import { tool } from "@langchain/core/tools";
|
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { ConfigManager } from "../../config/manager.js";
|
|
4
4
|
import { promises as fsPromises } from "fs";
|
|
5
|
-
import path from "path";
|
|
6
|
-
import { homedir } from "os";
|
|
7
5
|
import Database from "better-sqlite3";
|
|
6
|
+
import { PATHS } from "../../config/paths.js";
|
|
8
7
|
import { TaskRepository } from "../tasks/repository.js";
|
|
9
8
|
import { TaskRequestContext } from "../tasks/context.js";
|
|
10
9
|
import { isEnvVarSet } from "../../config/precedence.js";
|
|
11
10
|
// ─── Shared ───────────────────────────────────────────────────────────────────
|
|
12
|
-
const shortMemoryDbPath =
|
|
11
|
+
const shortMemoryDbPath = PATHS.shortMemoryDb;
|
|
13
12
|
/**
|
|
14
13
|
* Map of config paths to their corresponding environment variable names.
|
|
15
14
|
* Used to check if a config field is being overridden by an env var.
|
|
@@ -145,7 +144,7 @@ export const DiagnosticTool = tool(async () => {
|
|
|
145
144
|
try {
|
|
146
145
|
const timestamp = new Date().toISOString();
|
|
147
146
|
const components = {};
|
|
148
|
-
const morpheusRoot =
|
|
147
|
+
const morpheusRoot = PATHS.root;
|
|
149
148
|
// Configuration
|
|
150
149
|
try {
|
|
151
150
|
const configManager = ConfigManager.getInstance();
|
|
@@ -198,7 +197,7 @@ export const DiagnosticTool = tool(async () => {
|
|
|
198
197
|
}
|
|
199
198
|
// Short-term memory DB
|
|
200
199
|
try {
|
|
201
|
-
const dbPath =
|
|
200
|
+
const dbPath = PATHS.shortMemoryDb;
|
|
202
201
|
await fsPromises.access(dbPath);
|
|
203
202
|
const stat = await fsPromises.stat(dbPath);
|
|
204
203
|
components.shortMemoryDb = {
|
|
@@ -216,7 +215,7 @@ export const DiagnosticTool = tool(async () => {
|
|
|
216
215
|
}
|
|
217
216
|
// Sati long-term memory DB
|
|
218
217
|
try {
|
|
219
|
-
const satiDbPath =
|
|
218
|
+
const satiDbPath = PATHS.satiDb;
|
|
220
219
|
await fsPromises.access(satiDbPath);
|
|
221
220
|
const stat = await fsPromises.stat(satiDbPath);
|
|
222
221
|
components.satiMemoryDb = {
|
|
@@ -266,7 +265,7 @@ export const DiagnosticTool = tool(async () => {
|
|
|
266
265
|
};
|
|
267
266
|
// Logs directory
|
|
268
267
|
try {
|
|
269
|
-
const logsDir =
|
|
268
|
+
const logsDir = PATHS.logs;
|
|
270
269
|
await fsPromises.access(logsDir);
|
|
271
270
|
components.logs = {
|
|
272
271
|
status: "healthy",
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { tool } from "@langchain/core/tools";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
import { TaskRepository } from "../tasks/repository.js";
|
|
4
3
|
import { TaskRequestContext } from "../tasks/context.js";
|
|
5
4
|
import { DisplayManager } from "../display.js";
|
|
6
5
|
import { ConfigManager } from "../../config/manager.js";
|
|
7
6
|
import { SmithDelegator } from "../smiths/delegator.js";
|
|
8
7
|
import { SmithRegistry } from "../smiths/registry.js";
|
|
9
|
-
import {
|
|
10
|
-
import { AuditRepository } from "../audit/repository.js";
|
|
8
|
+
import { ServiceContainer, SERVICE_KEYS } from "../container.js";
|
|
11
9
|
/**
|
|
12
10
|
* Returns true when Smiths are configured in sync mode (inline execution).
|
|
13
11
|
*/
|
|
@@ -43,7 +41,8 @@ export const SmithDelegateTool = tool(async ({ smith, task, context }) => {
|
|
|
43
41
|
const sessionId = ctx?.session_id ?? 'default';
|
|
44
42
|
// Notify originating channel
|
|
45
43
|
if (ctx?.origin_channel && ctx.origin_user_id && ctx.origin_channel !== 'api' && ctx.origin_channel !== 'ui') {
|
|
46
|
-
|
|
44
|
+
ServiceContainer.get(SERVICE_KEYS.notifier)
|
|
45
|
+
.sendToUser(ctx.origin_channel, ctx.origin_user_id, `🕶️ Smith '${smith}' is executing your request...`)
|
|
47
46
|
.catch(() => { });
|
|
48
47
|
}
|
|
49
48
|
try {
|
|
@@ -55,7 +54,7 @@ export const SmithDelegateTool = tool(async ({ smith, task, context }) => {
|
|
|
55
54
|
level: "info",
|
|
56
55
|
});
|
|
57
56
|
if (result.usage) {
|
|
58
|
-
|
|
57
|
+
ServiceContainer.get(SERVICE_KEYS.auditEmitter).emit({
|
|
59
58
|
session_id: sessionId,
|
|
60
59
|
event_type: 'llm_call',
|
|
61
60
|
agent: 'smith',
|
|
@@ -96,8 +95,7 @@ export const SmithDelegateTool = tool(async ({ smith, task, context }) => {
|
|
|
96
95
|
return "Delegation limit reached for this user turn. Split the request or wait for current tasks.";
|
|
97
96
|
}
|
|
98
97
|
const ctx = TaskRequestContext.get();
|
|
99
|
-
const
|
|
100
|
-
const created = repository.createTask({
|
|
98
|
+
const created = ServiceContainer.get(SERVICE_KEYS.taskEnqueuer).enqueue({
|
|
101
99
|
agent: "smith",
|
|
102
100
|
input: task,
|
|
103
101
|
context: context ? JSON.stringify({ smith_name: smith, context }) : JSON.stringify({ smith_name: smith }),
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import Database from 'better-sqlite3';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import { homedir } from 'os';
|
|
4
3
|
import fs from 'fs-extra';
|
|
5
4
|
import { randomUUID } from 'crypto';
|
|
5
|
+
import { PATHS } from '../../config/paths.js';
|
|
6
6
|
export class WebhookRepository {
|
|
7
7
|
static instance = null;
|
|
8
8
|
db;
|
|
9
9
|
constructor() {
|
|
10
|
-
const dbPath =
|
|
10
|
+
const dbPath = PATHS.shortMemoryDb;
|
|
11
11
|
fs.ensureDirSync(path.dirname(dbPath));
|
|
12
12
|
this.db = new Database(dbPath, { timeout: 5000 });
|
|
13
13
|
this.db.pragma('journal_mode = WAL');
|
package/dist/types/config.js
CHANGED
|
@@ -14,6 +14,12 @@ export const DEFAULT_CONFIG = {
|
|
|
14
14
|
enabled: true,
|
|
15
15
|
maxDurationSeconds: 300,
|
|
16
16
|
supportedMimeTypes: ['audio/ogg', 'audio/mp3', 'audio/mpeg', 'audio/wav'],
|
|
17
|
+
tts: {
|
|
18
|
+
enabled: false,
|
|
19
|
+
provider: 'google',
|
|
20
|
+
model: 'gemini-2.5-flash-preview-tts',
|
|
21
|
+
voice: 'Kore',
|
|
22
|
+
},
|
|
17
23
|
},
|
|
18
24
|
memory: {
|
|
19
25
|
limit: 100
|
|
@@ -0,0 +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};
|