Additive change — existing code paths still run via inline fallbacks. Prepares core for per-module extractions in PR #3 onward. Four registries added with empty defaults: - delivery action handlers (delivery.ts) - router inbound gate (router.ts) - response dispatcher (index.ts) - MCP tool self-registration (container/agent-runner/src/mcp-tools/server.ts) Default modules moved to src/modules/ for signaling: - src/modules/typing/ (extracted from delivery.ts) - src/modules/mount-security/ (moved from src/mount-security.ts) Both are imported directly by core — no hook, no registry. Removal requires editing core imports. Migrator now keys applied rows by name (uniqueness) so module migrations can pick arbitrary version numbers. Stored version column is auto-assigned as an applied-order sequence. sqlite_master guards added around core calls into module-owned tables (user_roles, agent_destinations, pending_questions). No-ops today; load-bearing after the owning modules are extracted. MODULE-HOOK markers placed at scheduling's two skill-edit sites (host-sweep.ts recurrence call, poll-loop.ts pre-task gate). PR #4 replaces the marked blocks when scheduling moves to its module. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
67 lines
2.1 KiB
TypeScript
67 lines
2.1 KiB
TypeScript
/**
|
|
* Agent management MCP tools: create_agent.
|
|
*
|
|
* send_to_agent was removed — sending to another agent is now just
|
|
* send_message(to="agent-name") since agents and channels share the
|
|
* unified destinations namespace.
|
|
*
|
|
* create_agent is admin-only. Non-admin containers never see this tool
|
|
* (see mcp-tools/index.ts). The host re-checks permission on receive.
|
|
*/
|
|
import { writeMessageOut } from '../db/messages-out.js';
|
|
import { registerTools } from './server.js';
|
|
import type { McpToolDefinition } from './types.js';
|
|
|
|
function log(msg: string): void {
|
|
console.error(`[mcp-tools] ${msg}`);
|
|
}
|
|
|
|
function generateId(): string {
|
|
return `msg-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
}
|
|
|
|
function ok(text: string) {
|
|
return { content: [{ type: 'text' as const, text }] };
|
|
}
|
|
|
|
function err(text: string) {
|
|
return { content: [{ type: 'text' as const, text: `Error: ${text}` }], isError: true };
|
|
}
|
|
|
|
export const createAgent: McpToolDefinition = {
|
|
tool: {
|
|
name: 'create_agent',
|
|
description:
|
|
'Create a long-lived companion sub-agent (research assistant, task manager, specialist) — the name becomes your destination for it. Admin-only. Fire-and-forget.',
|
|
inputSchema: {
|
|
type: 'object' as const,
|
|
properties: {
|
|
name: { type: 'string', description: 'Human-readable name (also becomes your destination name for this agent)' },
|
|
instructions: { type: 'string', description: 'CLAUDE.md content for the new agent (personality, role, instructions)' },
|
|
},
|
|
required: ['name'],
|
|
},
|
|
},
|
|
async handler(args) {
|
|
const name = args.name as string;
|
|
if (!name) return err('name is required');
|
|
|
|
const requestId = generateId();
|
|
writeMessageOut({
|
|
id: requestId,
|
|
kind: 'system',
|
|
content: JSON.stringify({
|
|
action: 'create_agent',
|
|
requestId,
|
|
name,
|
|
instructions: (args.instructions as string) || null,
|
|
}),
|
|
});
|
|
|
|
log(`create_agent: ${requestId} → "${name}"`);
|
|
return ok(`Creating agent "${name}". You will be notified when it is ready.`);
|
|
},
|
|
};
|
|
|
|
registerTools([createAgent]);
|