Files
BridgeSwarm/native-host/capabilities/agent.js
T
snxraven 1a4a934e27
CI / Build & Test (push) Successful in 27m11s
Updates QVAC
2026-09-03 17:29:52 -04:00

264 lines
8.8 KiB
JavaScript

/**
* Grok-class agent capability pack (ACP-shaped events over NMH).
*/
const sandbox = require('../agent/sandbox.js');
const sessions = require('../agent/sessions.js');
const loop = require('../agent/loop.js');
const mcp = require('../agent/mcp.js');
const customTools = require('../agent/custom-tools.js');
const toolSet = require('../agent/tool-set.js');
const qvacEngine = require('../qvac/engine.js');
function makeJobId(prefix) {
return prefix + '_' + Date.now() + '_' + Math.random().toString(36).slice(2, 10);
}
function refuseDisabled(ctx) {
if (qvacEngine.isUserEnabled()) return false;
ctx.reply({ ok: false, error: qvacEngine.disabledError().message });
return true;
}
function normalizePermDecision(p) {
p = p || {};
if (p.decision === 'always' || p.always === true) return 'always';
if (p.decision === 'deny' || p.allow === false) return 'deny';
if (p.decision === 'allow' || p.allow === true) return 'allow';
return 'deny';
}
function createAgentPack() {
const commands = {
async setGrants(ctx) {
sandbox.setGrants(ctx.payload || {});
ctx.reply({ ok: true, roots: sandbox.listGrantedRoots() });
},
async create(ctx) {
if (refuseDisabled(ctx)) return;
const p = ctx.payload || {};
const origin = p._origin || '';
const hostWorkspace = toolSet.parseHostWorkspace(p);
let cwd;
let workspaceLabel;
if (!hostWorkspace) {
workspaceLabel = String(p.workspace || p.cwd || 'page').slice(0, 200);
if (!workspaceLabel || workspaceLabel === 'default') workspaceLabel = 'page';
cwd = workspaceLabel;
} else {
cwd = p.cwd && p.cwd !== 'default' ? sandbox.resolvePath(origin, p.cwd) : sandbox.defaultCwd(origin);
workspaceLabel = cwd;
}
const summary = sessions.create({
origin,
cwd,
workspace: workspaceLabel,
hostWorkspace,
builtinTools: p.builtinTools === false ? false : Array.isArray(p.builtinTools) ? p.builtinTools : undefined,
model: p.model || 'qwen3.5-4b',
title: p.title || 'New session',
sessionId: p.sessionId,
goal: p.goal ? require('../agent/goal.js').create(p.goal, { verify: p.verify !== false }) : null,
planMode: p.planMode
? { state: p.planMode === true || p.planMode === 'active' ? 'active' : 'inactive', planPath: 'plan.md' }
: undefined,
});
customTools.setSession(summary.id, { hostWorkspace });
if (p.tools) {
try {
customTools.register(summary.id, p.tools);
summary.customTools = customTools.list(summary.id);
sessions.saveSummary(summary);
} catch (err) {
ctx.reply({ ok: false, error: err.message });
return;
}
}
ctx.reply({
ok: true,
sessionId: summary.id,
cwd: summary.cwd,
workspace: summary.workspace,
hostWorkspace,
model: summary.model,
tools: customTools.list(summary.id),
});
},
async load(ctx) {
if (refuseDisabled(ctx)) return;
try {
const s = sessions.load(ctx.payload.sessionId);
customTools.setSession(s.id, { hostWorkspace: s.hostWorkspace !== false });
if (Array.isArray(s.customTools) && s.customTools.length) {
try {
customTools.register(s.id, s.customTools);
} catch (_) {}
}
ctx.reply({ ok: true, session: s });
} catch (err) {
ctx.reply({ ok: false, error: err.message });
}
},
async list(ctx) {
ctx.reply({ ok: true, sessions: sessions.list() });
},
async prompt(ctx) {
if (refuseDisabled(ctx)) return;
const { payload, reply, emit } = ctx;
const jobId = payload.jobId || makeJobId('prompt');
let session;
try {
session = sessions.load(payload.sessionId);
customTools.setSession(session.id, { hostWorkspace: session.hostWorkspace !== false });
if (Array.isArray(session.customTools) && session.customTools.length && !customTools.list(session.id).length) {
try {
customTools.register(session.id, session.customTools);
} catch (_) {}
}
} catch (err) {
reply({ ok: false, error: err.message });
return;
}
reply({ ok: true, jobId, sessionId: session.id, streaming: true, status: 'started' });
loop.markLive(session.id);
try {
const result = await loop.runTurn({
session,
userText: payload.text || payload.prompt || '',
emit,
jobId,
payload,
planMode: payload.planMode,
});
emit('cap-end', { pack: 'agent', jobId, sessionId: session.id, ...result });
} catch (err) {
emit('cap-error', { pack: 'agent', jobId, sessionId: session.id, message: err.message });
} finally {
loop.finishLive(session.id);
}
},
async cancel(ctx) {
if (refuseDisabled(ctx)) return;
loop.cancel(ctx.payload && ctx.payload.sessionId);
ctx.reply({ ok: true });
},
async permission(ctx) {
if (refuseDisabled(ctx)) return;
const p = ctx.payload || {};
loop.resolvePermission(p.jobId, p.toolCallId, normalizePermDecision(p));
ctx.reply({ ok: true });
},
async planDecision(ctx) {
if (refuseDisabled(ctx)) return;
const p = ctx.payload || {};
loop.resolvePlanDecision(p.sessionId, p.decision === 'approve' || p.approve === true ? 'approve' : 'reject');
ctx.reply({ ok: true });
},
async answer(ctx) {
if (refuseDisabled(ctx)) return;
const p = ctx.payload || {};
loop.resolveAsk(p.jobId, p.toolCallId, p.choice != null ? p.choice : p.answer);
ctx.reply({ ok: true });
},
async registerTools(ctx) {
if (refuseDisabled(ctx)) return;
try {
const p = ctx.payload || {};
try {
const s = sessions.load(p.sessionId);
customTools.setSession(s.id, { hostWorkspace: s.hostWorkspace !== false });
} catch (_) {}
const listed = customTools.register(p.sessionId, p.tools || p.tool || []);
try {
const s = sessions.load(p.sessionId);
s.customTools = listed;
sessions.saveSummary(s);
} catch (_) {}
ctx.reply({ ok: true, tools: listed });
} catch (err) {
ctx.reply({ ok: false, error: err.message });
}
},
async unregisterTools(ctx) {
if (refuseDisabled(ctx)) return;
const p = ctx.payload || {};
ctx.reply({ ok: true, tools: customTools.unregister(p.sessionId, p.name) });
},
async listTools(ctx) {
if (refuseDisabled(ctx)) return;
const p = ctx.payload || {};
ctx.reply({ ok: true, tools: customTools.list(p.sessionId) });
},
async toolResult(ctx) {
if (refuseDisabled(ctx)) return;
const p = ctx.payload || {};
const ok = loop.resolveCustomResult(p.jobId, p.toolCallId, {
result: p.result,
error: p.error,
});
ctx.reply({ ok: true, resolved: ok });
},
async mcpRegister(ctx) {
if (refuseDisabled(ctx)) return;
try {
const servers = await mcp.register(ctx.payload || {}, ctx.payload || {});
ctx.reply({ ok: true, servers });
} catch (err) {
ctx.reply({ ok: false, error: err.message });
}
},
async mcpList(ctx) {
if (refuseDisabled(ctx)) return;
ctx.reply({ ok: true, servers: mcp.list() });
},
async mcpUnregister(ctx) {
if (refuseDisabled(ctx)) return;
ctx.reply({ ok: true, servers: mcp.unregister(ctx.payload && ctx.payload.id) });
},
async destroy(ctx) {
const id = ctx.payload && ctx.payload.sessionId;
if (!id) {
ctx.reply({ ok: false, error: 'sessionId required' });
return;
}
loop.cancel(id);
loop.forget(id);
customTools.clear(id);
const removed = sessions.remove(id);
if (!loop.isLive() && !loop.isWaiting() && typeof qvacEngine.idleSoon === 'function') {
qvacEngine.idleSoon(15000);
}
ctx.reply({ ok: true, removed: !!removed, sessionId: id });
},
async status(ctx) {
ctx.reply({
ok: true,
enabled: qvacEngine.isUserEnabled(),
sessionCount: sessions.list().length,
liveCount: loop.liveCount(),
modelLoaded: !!(qvacEngine.getLoaded() && qvacEngine.getLoaded().modelId),
grantedRoots: sandbox.listGrantedRoots(),
mcpCount: mcp.count(),
});
},
};
return {
id: 'agent',
commands,
getPublicStatus() {
return {
enabled: qvacEngine.isUserEnabled(),
sessionCount: sessions.list().length,
liveCount: loop.liveCount(),
modelLoaded: !!(qvacEngine.getLoaded() && qvacEngine.getLoaded().modelId),
grantedRoots: sandbox.listGrantedRoots(),
mcpCount: mcp.count(),
};
},
cleanup() {},
};
}
module.exports = { createAgentPack };