feat(04-04): add agent CLI commands
- Replace placeholder agent command with proper subcommands - Add agent spawn command with --name, --task, --cwd options - Add agent stop command to stop running agents - Add agent list command to show all agents - Add agent get command for detailed agent info - Add agent resume command for waiting agents - Add agent result command to get execution results - All commands use tRPC client for type-safe communication
This commit is contained in:
135
src/cli/index.ts
135
src/cli/index.ts
@@ -97,11 +97,138 @@ export function createCli(serverHandler?: (port?: number) => Promise<void>): Com
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
program
|
// Agent command group
|
||||||
|
const agentCommand = program
|
||||||
.command('agent')
|
.command('agent')
|
||||||
.description('Manage agents')
|
.description('Manage agents');
|
||||||
.action(() => {
|
|
||||||
console.log('cw agent: not implemented');
|
// cw agent spawn --name <name> --task <taskId> <prompt>
|
||||||
|
agentCommand
|
||||||
|
.command('spawn <prompt>')
|
||||||
|
.description('Spawn a new agent to work on a task')
|
||||||
|
.requiredOption('--name <name>', 'Human-readable name for the agent (e.g., gastown)')
|
||||||
|
.requiredOption('--task <taskId>', 'Task ID to assign to agent')
|
||||||
|
.option('--cwd <path>', 'Working directory for agent')
|
||||||
|
.action(async (prompt: string, options: { name: string; task: string; cwd?: string }) => {
|
||||||
|
try {
|
||||||
|
const client = createDefaultTrpcClient();
|
||||||
|
const agent = await client.spawnAgent.mutate({
|
||||||
|
name: options.name,
|
||||||
|
taskId: options.task,
|
||||||
|
prompt,
|
||||||
|
cwd: options.cwd,
|
||||||
|
});
|
||||||
|
console.log(`Agent '${agent.name}' spawned`);
|
||||||
|
console.log(` ID: ${agent.id}`);
|
||||||
|
console.log(` Task: ${agent.taskId}`);
|
||||||
|
console.log(` Status: ${agent.status}`);
|
||||||
|
console.log(` Worktree: ${agent.worktreeId}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to spawn agent:', (error as Error).message);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// cw agent stop <name>
|
||||||
|
agentCommand
|
||||||
|
.command('stop <name>')
|
||||||
|
.description('Stop a running agent by name')
|
||||||
|
.action(async (name: string) => {
|
||||||
|
try {
|
||||||
|
const client = createDefaultTrpcClient();
|
||||||
|
const result = await client.stopAgent.mutate({ name });
|
||||||
|
console.log(`Agent '${result.name}' stopped`);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to stop agent:', (error as Error).message);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// cw agent list
|
||||||
|
agentCommand
|
||||||
|
.command('list')
|
||||||
|
.description('List all agents')
|
||||||
|
.action(async () => {
|
||||||
|
try {
|
||||||
|
const client = createDefaultTrpcClient();
|
||||||
|
const agents = await client.listAgents.query();
|
||||||
|
if (agents.length === 0) {
|
||||||
|
console.log('No agents found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log('Agents:');
|
||||||
|
for (const agent of agents) {
|
||||||
|
const status = agent.status === 'waiting_for_input' ? 'WAITING' : agent.status.toUpperCase();
|
||||||
|
console.log(` ${agent.name} [${status}] - ${agent.taskId}`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to list agents:', (error as Error).message);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// cw agent get <name>
|
||||||
|
agentCommand
|
||||||
|
.command('get <name>')
|
||||||
|
.description('Get agent details by name')
|
||||||
|
.action(async (name: string) => {
|
||||||
|
try {
|
||||||
|
const client = createDefaultTrpcClient();
|
||||||
|
const agent = await client.getAgent.query({ name });
|
||||||
|
if (!agent) {
|
||||||
|
console.log(`Agent '${name}' not found`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(`Agent: ${agent.name}`);
|
||||||
|
console.log(` ID: ${agent.id}`);
|
||||||
|
console.log(` Task: ${agent.taskId}`);
|
||||||
|
console.log(` Session: ${agent.sessionId ?? '(none)'}`);
|
||||||
|
console.log(` Worktree: ${agent.worktreeId}`);
|
||||||
|
console.log(` Status: ${agent.status}`);
|
||||||
|
console.log(` Created: ${agent.createdAt}`);
|
||||||
|
console.log(` Updated: ${agent.updatedAt}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to get agent:', (error as Error).message);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// cw agent resume <name> <response>
|
||||||
|
agentCommand
|
||||||
|
.command('resume <name> <response>')
|
||||||
|
.description('Resume an agent that is waiting for input')
|
||||||
|
.action(async (name: string, response: string) => {
|
||||||
|
try {
|
||||||
|
const client = createDefaultTrpcClient();
|
||||||
|
const result = await client.resumeAgent.mutate({ name, prompt: response });
|
||||||
|
console.log(`Agent '${result.name}' resumed`);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to resume agent:', (error as Error).message);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// cw agent result <name>
|
||||||
|
agentCommand
|
||||||
|
.command('result <name>')
|
||||||
|
.description('Get agent execution result')
|
||||||
|
.action(async (name: string) => {
|
||||||
|
try {
|
||||||
|
const client = createDefaultTrpcClient();
|
||||||
|
const result = await client.getAgentResult.query({ name });
|
||||||
|
if (!result) {
|
||||||
|
console.log('No result available (agent may still be running)');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(`Result: ${result.success ? 'SUCCESS' : 'FAILED'}`);
|
||||||
|
console.log(` Message: ${result.message}`);
|
||||||
|
if (result.filesModified?.length) {
|
||||||
|
console.log(` Files modified: ${result.filesModified.join(', ')}`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to get result:', (error as Error).message);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
program
|
program
|
||||||
|
|||||||
Reference in New Issue
Block a user