155 lines
4.2 KiB
JavaScript
155 lines
4.2 KiB
JavaScript
import { CodexAdapter } from './codex-adapter.js';
|
|
import { ClaudeAdapter } from './claude-adapter.js';
|
|
import { AgyAdapter } from './agy-adapter.js';
|
|
import { OpenCodeAdapter } from './opencode-adapter.js';
|
|
import { ReasonixAdapter } from './reasonix-adapter.js';
|
|
|
|
const ENGINES = {
|
|
codex: new CodexAdapter(),
|
|
claude: new ClaudeAdapter(),
|
|
agy: new AgyAdapter(),
|
|
opencode: new OpenCodeAdapter(),
|
|
reasonix: new ReasonixAdapter(),
|
|
};
|
|
|
|
export function getEngine(name) {
|
|
return ENGINES[name] || null;
|
|
}
|
|
|
|
export function getAllEngines() {
|
|
return Object.values(ENGINES);
|
|
}
|
|
|
|
export function getAvailableEngines() {
|
|
return Object.values(ENGINES).filter(e => e.available);
|
|
}
|
|
|
|
/**
|
|
* Refresh specified engines (or all if not specified).
|
|
* @param {string[]} [engineNames] - Optional list of engine names to refresh
|
|
*/
|
|
export async function refreshEngines(engineNames = null) {
|
|
const names = engineNames || Object.keys(ENGINES);
|
|
const results = {};
|
|
for (const name of names) {
|
|
const engine = ENGINES[name];
|
|
if (engine) {
|
|
try {
|
|
results[name] = await engine.refresh();
|
|
} catch (err) {
|
|
results[name] = { available: false, session_count: 0, error: err.message };
|
|
}
|
|
}
|
|
}
|
|
return results;
|
|
}
|
|
|
|
/**
|
|
* List sessions across all engines or a specific engine, sorted by created_at desc.
|
|
*/
|
|
export function listSessions({ engine = 'all', query, cwd, model, source, status, from, to, limit, offset } = {}) {
|
|
const engines = engine === 'all' ? getAllEngines() : [getEngine(engine)].filter(Boolean);
|
|
const allSessions = [];
|
|
|
|
for (const e of engines) {
|
|
if (!e.available) continue;
|
|
try {
|
|
const result = e.listSessions({ query, cwd, model, source, status, from, to, limit: null, offset: 0 });
|
|
allSessions.push(...result.sessions);
|
|
} catch (err) {
|
|
console.error(`[Registry] listSessions error for ${e.name}:`, err.message);
|
|
}
|
|
}
|
|
|
|
// Global sort by created_at desc
|
|
allSessions.sort((a, b) => (b.created_at || 0) - (a.created_at || 0));
|
|
|
|
const total = allSessions.length;
|
|
const off = offset || 0;
|
|
const lim = (limit === null || limit === undefined) ? total : Math.min(limit, 200);
|
|
return { sessions: allSessions.slice(off, off + lim), total };
|
|
}
|
|
|
|
/**
|
|
* Get a single session by engine + id.
|
|
*/
|
|
export function getSession(engine, id) {
|
|
const e = getEngine(engine);
|
|
if (!e) return null;
|
|
return e.getSession(id);
|
|
}
|
|
|
|
/**
|
|
* Get messages for a session by engine + id.
|
|
*/
|
|
export async function getSessionMessages(engine, id) {
|
|
const e = getEngine(engine);
|
|
if (!e) return [];
|
|
return await e.getMessages(id);
|
|
}
|
|
|
|
/**
|
|
* Get aggregate tool usage across engines.
|
|
*/
|
|
export function getToolUsage({ engine = 'all' } = {}) {
|
|
const engines = engine === 'all' ? getAllEngines() : [getEngine(engine)].filter(Boolean);
|
|
const allTools = [];
|
|
|
|
for (const e of engines) {
|
|
if (!e.available) continue;
|
|
const tools = e.getToolUsage();
|
|
for (const t of tools) {
|
|
// Add engine info
|
|
t.engine = e.name;
|
|
t.engine_label = e.label;
|
|
}
|
|
allTools.push(...tools);
|
|
}
|
|
|
|
// Merge same-named tools across engines
|
|
const merged = new Map();
|
|
for (const t of allTools) {
|
|
const key = t.name;
|
|
if (!merged.has(key)) {
|
|
merged.set(key, { name: key, total_calls: 0, session_count: 0, engines: [], sessions: [] });
|
|
}
|
|
const m = merged.get(key);
|
|
m.total_calls += t.total_calls;
|
|
m.session_count += t.session_count;
|
|
if (!m.engines.includes(t.engine_label)) {
|
|
m.engines.push(t.engine_label);
|
|
}
|
|
m.sessions.push(...t.sessions);
|
|
}
|
|
|
|
return Array.from(merged.values()).sort((a, b) => b.total_calls - a.total_calls);
|
|
}
|
|
|
|
/**
|
|
* Resolve a short ID prefix across all or a specific engine.
|
|
*/
|
|
export function resolvePrefix(prefix, engine = 'all') {
|
|
const engines = engine === 'all' ? getAllEngines() : [getEngine(engine)].filter(Boolean);
|
|
const allMatches = [];
|
|
for (const e of engines) {
|
|
if (!e.available) continue;
|
|
try {
|
|
allMatches.push(...e.resolvePrefix(prefix));
|
|
} catch {}
|
|
}
|
|
return { matches: allMatches };
|
|
}
|
|
|
|
/**
|
|
* Get health info for all engines.
|
|
*/
|
|
export function getAllHealth() {
|
|
const info = {};
|
|
for (const [name, engine] of Object.entries(ENGINES)) {
|
|
info[name] = engine.getHealthInfo();
|
|
}
|
|
return info;
|
|
}
|
|
|
|
export { ENGINES };
|