89 lines
2.8 KiB
TypeScript
89 lines
2.8 KiB
TypeScript
import { createInterface } from 'node:readline';
|
|
import { Command } from 'commander';
|
|
import pc from 'picocolors';
|
|
import { AgentLoop } from '../agent/loop.ts';
|
|
import { MessageBus } from '../bus/queue.ts';
|
|
import { makeProvider } from '../provider/index.ts';
|
|
import type { Config } from '../config/types.ts';
|
|
|
|
export function agentCommand(program: Command, config: Config, workspace: string): void {
|
|
program
|
|
.command('agent')
|
|
.description('Run the agent interactively or send a single message.')
|
|
.option('-c, --config <path>', 'Path to config.json')
|
|
.option('-m, --message <text>', 'Single message to process (non-interactive)')
|
|
.option('-M, --model <model>', 'Model override')
|
|
.action(async (opts: { config?: string; message?: string; model?: string }) => {
|
|
console.info(pc.magenta(`workspace path: ${workspace}`));
|
|
|
|
const model = opts.model ?? config.agent.model;
|
|
const provider = makeProvider(
|
|
config.providers,
|
|
model,
|
|
config.agent.maxTokens,
|
|
config.agent.temperature,
|
|
);
|
|
const bus = new MessageBus();
|
|
|
|
const agentLoop = new AgentLoop({
|
|
bus,
|
|
provider,
|
|
workspace,
|
|
model,
|
|
maxIterations: config.agent.maxToolIterations,
|
|
contextWindowTokens: config.agent.contextWindowTokens,
|
|
braveApiKey: config.tools.web.braveApiKey,
|
|
webProxy: config.tools.web.proxy,
|
|
execConfig: config.tools.exec,
|
|
restrictToWorkspace: config.tools.restrictToWorkspace,
|
|
});
|
|
|
|
// Single-shot mode
|
|
if (opts.message) {
|
|
const result = await agentLoop.processDirect(opts.message);
|
|
console.log(result);
|
|
return;
|
|
}
|
|
|
|
// Interactive mode
|
|
console.info(pc.green('nanobot interactive mode. Type your message, Ctrl+C to exit.'));
|
|
|
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
|
|
const promptUser = () => {
|
|
rl.question(pc.cyan('You: '), async (input) => {
|
|
const text = input.trim();
|
|
if (!text) {
|
|
promptUser();
|
|
return;
|
|
}
|
|
|
|
const onProgress = async (content: string, opts?: { toolHint?: boolean }) => {
|
|
if (opts?.toolHint) {
|
|
process.stdout.write(pc.dim(` [${content}]\n`));
|
|
} else {
|
|
process.stdout.write(pc.dim(` ${content}\n`));
|
|
}
|
|
};
|
|
|
|
const result = await agentLoop.processDirect(
|
|
text,
|
|
'cli:interactive',
|
|
'cli',
|
|
'interactive',
|
|
onProgress,
|
|
);
|
|
console.log(pc.bold('Bot:'), result);
|
|
promptUser();
|
|
});
|
|
};
|
|
|
|
rl.on('close', () => {
|
|
agentLoop.stop();
|
|
process.exit(0);
|
|
});
|
|
|
|
promptUser();
|
|
});
|
|
}
|