@grec0/memory-bank-mcp 0.2.4 → 0.2.6
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.
|
@@ -474,6 +474,76 @@ export class AgentBoardSqlite {
|
|
|
474
474
|
return lines.join('\n');
|
|
475
475
|
}
|
|
476
476
|
}
|
|
477
|
+
/**
|
|
478
|
+
* Save an orchestrator routing decision to the database
|
|
479
|
+
*/
|
|
480
|
+
export function saveOrchestratorLog(log) {
|
|
481
|
+
const db = databaseManager.getConnection();
|
|
482
|
+
const result = db.prepare(`
|
|
483
|
+
INSERT INTO orchestrator_logs (
|
|
484
|
+
project_id, task_description, action, my_responsibilities,
|
|
485
|
+
delegations, suggested_imports, architecture_notes,
|
|
486
|
+
searches_performed, warning, success, model_used
|
|
487
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
488
|
+
`).run(log.projectId, log.taskDescription, log.action, JSON.stringify(log.myResponsibilities), JSON.stringify(log.delegations), JSON.stringify(log.suggestedImports), log.architectureNotes, JSON.stringify(log.searchesPerformed || []), log.warning || null, log.success ? 1 : 0, log.modelUsed);
|
|
489
|
+
// Flush for external readers (VSCode extension)
|
|
490
|
+
databaseManager.flushForExternalReaders();
|
|
491
|
+
console.error(`[Orchestrator] Saved routing log (ID: ${result.lastInsertRowid})`);
|
|
492
|
+
return result.lastInsertRowid;
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* Get orchestrator logs for a project
|
|
496
|
+
*/
|
|
497
|
+
export function getOrchestratorLogs(projectId, limit = 50) {
|
|
498
|
+
const db = databaseManager.getConnection();
|
|
499
|
+
let query = `
|
|
500
|
+
SELECT * FROM orchestrator_logs
|
|
501
|
+
${projectId ? 'WHERE project_id = ?' : ''}
|
|
502
|
+
ORDER BY timestamp DESC
|
|
503
|
+
LIMIT ?
|
|
504
|
+
`;
|
|
505
|
+
const params = projectId ? [projectId, limit] : [limit];
|
|
506
|
+
const rows = db.prepare(query).all(...params);
|
|
507
|
+
return rows.map(row => ({
|
|
508
|
+
id: row.id,
|
|
509
|
+
projectId: row.project_id,
|
|
510
|
+
taskDescription: row.task_description,
|
|
511
|
+
action: row.action,
|
|
512
|
+
myResponsibilities: JSON.parse(row.my_responsibilities || '[]'),
|
|
513
|
+
delegations: JSON.parse(row.delegations || '[]'),
|
|
514
|
+
suggestedImports: JSON.parse(row.suggested_imports || '[]'),
|
|
515
|
+
architectureNotes: row.architecture_notes,
|
|
516
|
+
searchesPerformed: JSON.parse(row.searches_performed || '[]'),
|
|
517
|
+
warning: row.warning,
|
|
518
|
+
success: row.success === 1,
|
|
519
|
+
modelUsed: row.model_used,
|
|
520
|
+
timestamp: row.timestamp,
|
|
521
|
+
}));
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* Get a single orchestrator log by ID
|
|
525
|
+
*/
|
|
526
|
+
export function getOrchestratorLogById(id) {
|
|
527
|
+
const db = databaseManager.getConnection();
|
|
528
|
+
const row = db.prepare(`SELECT * FROM orchestrator_logs WHERE id = ?`).get(id);
|
|
529
|
+
if (!row)
|
|
530
|
+
return null;
|
|
531
|
+
return {
|
|
532
|
+
id: row.id,
|
|
533
|
+
projectId: row.project_id,
|
|
534
|
+
taskDescription: row.task_description,
|
|
535
|
+
action: row.action,
|
|
536
|
+
myResponsibilities: JSON.parse(row.my_responsibilities || '[]'),
|
|
537
|
+
delegations: JSON.parse(row.delegations || '[]'),
|
|
538
|
+
suggestedImports: JSON.parse(row.suggested_imports || '[]'),
|
|
539
|
+
architectureNotes: row.architecture_notes,
|
|
540
|
+
searchesPerformed: JSON.parse(row.searches_performed || '[]'),
|
|
541
|
+
warning: row.warning,
|
|
542
|
+
success: row.success === 1,
|
|
543
|
+
modelUsed: row.model_used,
|
|
544
|
+
timestamp: row.timestamp,
|
|
545
|
+
};
|
|
546
|
+
}
|
|
477
547
|
// ============================================================================
|
|
478
548
|
// Cleanup utilities
|
|
479
549
|
// ============================================================================
|
package/dist/common/database.js
CHANGED
|
@@ -7,7 +7,7 @@ import Database from 'better-sqlite3';
|
|
|
7
7
|
import * as path from 'path';
|
|
8
8
|
import * as os from 'os';
|
|
9
9
|
import * as fs from 'fs';
|
|
10
|
-
const SCHEMA_VERSION =
|
|
10
|
+
const SCHEMA_VERSION = 2; // v2: Added orchestrator_logs table
|
|
11
11
|
/**
|
|
12
12
|
* SQL Schema for Agent Board
|
|
13
13
|
*/
|
|
@@ -90,6 +90,27 @@ CREATE TABLE IF NOT EXISTS messages (
|
|
|
90
90
|
CREATE INDEX IF NOT EXISTS idx_messages_project ON messages(project_id);
|
|
91
91
|
CREATE INDEX IF NOT EXISTS idx_messages_time ON messages(timestamp);
|
|
92
92
|
|
|
93
|
+
-- Orchestrator Logs: Route task decisions and searches
|
|
94
|
+
CREATE TABLE IF NOT EXISTS orchestrator_logs (
|
|
95
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
96
|
+
project_id TEXT NOT NULL, -- Project that requested the routing
|
|
97
|
+
task_description TEXT NOT NULL, -- Original task description
|
|
98
|
+
action TEXT NOT NULL, -- proceed, delegate, mixed
|
|
99
|
+
my_responsibilities TEXT, -- JSON array of responsibilities
|
|
100
|
+
delegations TEXT, -- JSON array of delegations
|
|
101
|
+
suggested_imports TEXT, -- JSON array of imports
|
|
102
|
+
architecture_notes TEXT, -- Explanation from orchestrator
|
|
103
|
+
searches_performed TEXT, -- JSON array of searches done
|
|
104
|
+
warning TEXT, -- Any warnings
|
|
105
|
+
success INTEGER NOT NULL DEFAULT 1, -- 1=success, 0=failure
|
|
106
|
+
model_used TEXT, -- Model used for routing
|
|
107
|
+
timestamp TEXT NOT NULL DEFAULT (datetime('now'))
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
CREATE INDEX IF NOT EXISTS idx_orchestrator_project ON orchestrator_logs(project_id);
|
|
111
|
+
CREATE INDEX IF NOT EXISTS idx_orchestrator_time ON orchestrator_logs(timestamp);
|
|
112
|
+
CREATE INDEX IF NOT EXISTS idx_orchestrator_action ON orchestrator_logs(action);
|
|
113
|
+
|
|
93
114
|
-- Schema versioning for future migrations
|
|
94
115
|
CREATE TABLE IF NOT EXISTS schema_version (
|
|
95
116
|
version INTEGER PRIMARY KEY,
|
|
@@ -159,10 +180,8 @@ class DatabaseManager {
|
|
|
159
180
|
console.error(`[Database] Migrating schema from v${currentVersion} to v${SCHEMA_VERSION}`);
|
|
160
181
|
// Run schema creation (IF NOT EXISTS makes it safe)
|
|
161
182
|
this.db.exec(SCHEMA_SQL);
|
|
162
|
-
// Record schema version
|
|
163
|
-
|
|
164
|
-
this.db.prepare('INSERT OR REPLACE INTO schema_version (version) VALUES (?)').run(SCHEMA_VERSION);
|
|
165
|
-
}
|
|
183
|
+
// Record/update schema version
|
|
184
|
+
this.db.prepare('INSERT OR REPLACE INTO schema_version (version) VALUES (?)').run(SCHEMA_VERSION);
|
|
166
185
|
console.error(`[Database] Schema initialized at v${SCHEMA_VERSION}`);
|
|
167
186
|
}
|
|
168
187
|
}
|
package/dist/common/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Version of the MCP Kanban server
|
|
2
|
-
export const VERSION = "0.2.
|
|
2
|
+
export const VERSION = "0.2.5";
|
package/dist/tools/routeTask.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import OpenAI from "openai";
|
|
10
10
|
import { RegistryManager } from "../common/registryManager.js";
|
|
11
11
|
import { searchMemory } from "./searchMemory.js";
|
|
12
|
+
import { saveOrchestratorLog } from "../common/agentBoardSqlite.js";
|
|
12
13
|
/**
|
|
13
14
|
* Builds a context string describing all projects and their responsibilities
|
|
14
15
|
*/
|
|
@@ -226,15 +227,15 @@ export async function routeTaskTool(params, indexManager) {
|
|
|
226
227
|
warning: 'AI routing unavailable. Proceeding without validation.',
|
|
227
228
|
};
|
|
228
229
|
}
|
|
230
|
+
// Model used for routing (needed for logging both success and error cases)
|
|
231
|
+
const model = process.env.MEMORYBANK_ROUTING_MODEL || "gpt-4o";
|
|
229
232
|
try {
|
|
230
233
|
const client = new OpenAI({ apiKey });
|
|
231
234
|
const prompt = ROUTING_PROMPT
|
|
232
235
|
.replace('{projectsContext}', projectsContext)
|
|
233
236
|
.replace('{currentProject}', projectId)
|
|
234
237
|
.replace('{taskDescription}', taskDescription);
|
|
235
|
-
console.error(`Calling AI orchestrator with tool access...`);
|
|
236
|
-
// Use chat completions with function calling
|
|
237
|
-
const model = process.env.MEMORYBANK_ROUTING_MODEL || "gpt-4o";
|
|
238
|
+
console.error(`Calling AI orchestrator with tool access (${model})...`);
|
|
238
239
|
// Initialize conversation
|
|
239
240
|
const messages = [
|
|
240
241
|
{
|
|
@@ -306,7 +307,7 @@ export async function routeTaskTool(params, indexManager) {
|
|
|
306
307
|
const jsonMatch = finalResponse.match(/\{[\s\S]*\}/);
|
|
307
308
|
if (!jsonMatch) {
|
|
308
309
|
console.error(`Failed to parse orchestrator response`);
|
|
309
|
-
|
|
310
|
+
const parseErrorResult = {
|
|
310
311
|
success: false,
|
|
311
312
|
action: 'proceed',
|
|
312
313
|
myResponsibilities: [],
|
|
@@ -315,6 +316,26 @@ export async function routeTaskTool(params, indexManager) {
|
|
|
315
316
|
architectureNotes: 'Failed to parse AI response.',
|
|
316
317
|
warning: 'Orchestrator analysis failed. Review task manually.',
|
|
317
318
|
};
|
|
319
|
+
// Persist parse failure
|
|
320
|
+
try {
|
|
321
|
+
saveOrchestratorLog({
|
|
322
|
+
projectId: params.projectId,
|
|
323
|
+
taskDescription: params.taskDescription,
|
|
324
|
+
action: 'proceed',
|
|
325
|
+
myResponsibilities: [],
|
|
326
|
+
delegations: [],
|
|
327
|
+
suggestedImports: [],
|
|
328
|
+
architectureNotes: parseErrorResult.architectureNotes,
|
|
329
|
+
searchesPerformed: [],
|
|
330
|
+
warning: parseErrorResult.warning,
|
|
331
|
+
success: false,
|
|
332
|
+
modelUsed: model,
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
catch (persistError) {
|
|
336
|
+
console.error(`Warning: Failed to persist parse error log: ${persistError.message}`);
|
|
337
|
+
}
|
|
338
|
+
return parseErrorResult;
|
|
318
339
|
}
|
|
319
340
|
const result = JSON.parse(jsonMatch[0]);
|
|
320
341
|
console.error(`\nOrchestrator Decision:`);
|
|
@@ -330,7 +351,7 @@ export async function routeTaskTool(params, indexManager) {
|
|
|
330
351
|
console.error(` → ${d.targetProject}: ${d.taskTitle}`);
|
|
331
352
|
}
|
|
332
353
|
}
|
|
333
|
-
|
|
354
|
+
const routeResult = {
|
|
334
355
|
success: true,
|
|
335
356
|
action: result.action || 'proceed',
|
|
336
357
|
myResponsibilities: result.myResponsibilities || [],
|
|
@@ -339,10 +360,30 @@ export async function routeTaskTool(params, indexManager) {
|
|
|
339
360
|
architectureNotes: result.architectureNotes || '',
|
|
340
361
|
warning: result.warning,
|
|
341
362
|
};
|
|
363
|
+
// Persist to SQLite for extension visualization
|
|
364
|
+
try {
|
|
365
|
+
saveOrchestratorLog({
|
|
366
|
+
projectId: params.projectId,
|
|
367
|
+
taskDescription: params.taskDescription,
|
|
368
|
+
action: routeResult.action,
|
|
369
|
+
myResponsibilities: routeResult.myResponsibilities,
|
|
370
|
+
delegations: routeResult.delegations,
|
|
371
|
+
suggestedImports: routeResult.suggestedImports,
|
|
372
|
+
architectureNotes: routeResult.architectureNotes,
|
|
373
|
+
searchesPerformed: result.searchesPerformed || [],
|
|
374
|
+
warning: routeResult.warning,
|
|
375
|
+
success: true,
|
|
376
|
+
modelUsed: model,
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
catch (persistError) {
|
|
380
|
+
console.error(`Warning: Failed to persist orchestrator log: ${persistError.message}`);
|
|
381
|
+
}
|
|
382
|
+
return routeResult;
|
|
342
383
|
}
|
|
343
384
|
catch (error) {
|
|
344
385
|
console.error(`Error in task routing: ${error.message}`);
|
|
345
|
-
|
|
386
|
+
const errorResult = {
|
|
346
387
|
success: false,
|
|
347
388
|
action: 'proceed',
|
|
348
389
|
myResponsibilities: [],
|
|
@@ -351,6 +392,26 @@ export async function routeTaskTool(params, indexManager) {
|
|
|
351
392
|
architectureNotes: `Error analyzing task: ${error.message}`,
|
|
352
393
|
warning: 'Orchestrator failed. Review task distribution manually.',
|
|
353
394
|
};
|
|
395
|
+
// Persist failed attempts too
|
|
396
|
+
try {
|
|
397
|
+
saveOrchestratorLog({
|
|
398
|
+
projectId: params.projectId,
|
|
399
|
+
taskDescription: params.taskDescription,
|
|
400
|
+
action: 'proceed',
|
|
401
|
+
myResponsibilities: [],
|
|
402
|
+
delegations: [],
|
|
403
|
+
suggestedImports: [],
|
|
404
|
+
architectureNotes: errorResult.architectureNotes,
|
|
405
|
+
searchesPerformed: [],
|
|
406
|
+
warning: errorResult.warning,
|
|
407
|
+
success: false,
|
|
408
|
+
modelUsed: model,
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
catch (persistError) {
|
|
412
|
+
console.error(`Warning: Failed to persist error log: ${persistError.message}`);
|
|
413
|
+
}
|
|
414
|
+
return errorResult;
|
|
354
415
|
}
|
|
355
416
|
}
|
|
356
417
|
/**
|