0xkobold 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/HEARTBEAT.md +66 -32
  2. package/README.md +220 -1
  3. package/dist/package.json +3 -2
  4. package/dist/src/agent/bootstrap-loader.js +138 -0
  5. package/dist/src/agent/bootstrap-loader.js.map +1 -0
  6. package/dist/src/agent/context-pruning.js +279 -0
  7. package/dist/src/agent/context-pruning.js.map +1 -0
  8. package/dist/src/agent/dynamic-personality.js +211 -0
  9. package/dist/src/agent/dynamic-personality.js.map +1 -0
  10. package/dist/src/agent/embedded-runner.js +79 -0
  11. package/dist/src/agent/embedded-runner.js.map +1 -0
  12. package/dist/src/agent/index.js +16 -0
  13. package/dist/src/agent/index.js.map +1 -0
  14. package/dist/src/agent/system-prompt.js +84 -0
  15. package/dist/src/agent/system-prompt.js.map +1 -0
  16. package/dist/src/agent/task-router.js +194 -0
  17. package/dist/src/agent/task-router.js.map +1 -0
  18. package/dist/src/agent/tools/index.js +2 -0
  19. package/dist/src/agent/tools/index.js.map +1 -0
  20. package/dist/src/agent/tools/spawn-agent.js +200 -0
  21. package/dist/src/agent/tools/spawn-agent.js.map +1 -0
  22. package/dist/src/agent/types/definitions.js +317 -0
  23. package/dist/src/agent/types/definitions.js.map +1 -0
  24. package/dist/src/agent/types/index.js +2 -0
  25. package/dist/src/agent/types/index.js.map +1 -0
  26. package/dist/src/agent/user-profile.js +300 -0
  27. package/dist/src/agent/user-profile.js.map +1 -0
  28. package/dist/src/agents/task-router.js +194 -0
  29. package/dist/src/agents/task-router.js.map +1 -0
  30. package/dist/src/agents/tools/index.js +2 -0
  31. package/dist/src/agents/tools/index.js.map +1 -0
  32. package/dist/src/agents/tools/spawn-agent.js +200 -0
  33. package/dist/src/agents/tools/spawn-agent.js.map +1 -0
  34. package/dist/src/agents/types/definitions.js +317 -0
  35. package/dist/src/agents/types/definitions.js.map +1 -0
  36. package/dist/src/agents/types/index.js +2 -0
  37. package/dist/src/agents/types/index.js.map +1 -0
  38. package/dist/src/cli/commands/embedded.js +36 -0
  39. package/dist/src/cli/commands/embedded.js.map +1 -0
  40. package/dist/src/cli/commands/gateway.js +127 -166
  41. package/dist/src/cli/commands/gateway.js.map +1 -1
  42. package/dist/src/cli/program-fixed.js +1 -0
  43. package/dist/src/cli/program-fixed.js.map +1 -0
  44. package/dist/src/cli/program.js +10 -29
  45. package/dist/src/cli/program.js.map +1 -1
  46. package/dist/src/extensions/core/agent-lifecycle-extension.js +323 -0
  47. package/dist/src/extensions/core/agent-lifecycle-extension.js.map +1 -0
  48. package/dist/src/extensions/core/agent-orchestrator-extension.js +642 -0
  49. package/dist/src/extensions/core/agent-orchestrator-extension.js.map +1 -0
  50. package/dist/src/extensions/core/agent-workspace-extension.js +174 -0
  51. package/dist/src/extensions/core/agent-workspace-extension.js.map +1 -0
  52. package/dist/src/extensions/core/autonomous-executor-extension.js +145 -0
  53. package/dist/src/extensions/core/autonomous-executor-extension.js.map +1 -0
  54. package/dist/src/extensions/core/autonomous-subagent-extension.js +333 -0
  55. package/dist/src/extensions/core/autonomous-subagent-extension.js.map +1 -0
  56. package/dist/src/extensions/core/deprecated/agent-lifecycle-extension.js +323 -0
  57. package/dist/src/extensions/core/deprecated/agent-lifecycle-extension.js.map +1 -0
  58. package/dist/src/extensions/core/deprecated/autonomous-subagent-extension.js +333 -0
  59. package/dist/src/extensions/core/deprecated/autonomous-subagent-extension.js.map +1 -0
  60. package/dist/src/extensions/core/deprecated/subagent-extension.js +647 -0
  61. package/dist/src/extensions/core/deprecated/subagent-extension.js.map +1 -0
  62. package/dist/src/extensions/core/mode-manager-extension.js +11 -0
  63. package/dist/src/extensions/core/mode-manager-extension.js.map +1 -1
  64. package/dist/src/extensions/core/persona-loader-extension.js +61 -129
  65. package/dist/src/extensions/core/persona-loader-extension.js.map +1 -1
  66. package/dist/src/extensions/core/websearch-enhanced-extension.js +705 -0
  67. package/dist/src/extensions/core/websearch-enhanced-extension.js.map +1 -0
  68. package/dist/src/extensions/core/websearch-v2-extension.js +303 -0
  69. package/dist/src/extensions/core/websearch-v2-extension.js.map +1 -0
  70. package/dist/src/gateway/discord-bot.js +185 -0
  71. package/dist/src/gateway/discord-bot.js.map +1 -0
  72. package/dist/src/gateway/index.js +10 -350
  73. package/dist/src/gateway/index.js.map +1 -1
  74. package/dist/src/gateway/server.js +325 -0
  75. package/dist/src/gateway/server.js.map +1 -0
  76. package/dist/src/gateway/websocket-server.js +142 -0
  77. package/dist/src/gateway/websocket-server.js.map +1 -0
  78. package/dist/src/heartbeat/checkin.js +185 -0
  79. package/dist/src/heartbeat/checkin.js.map +1 -0
  80. package/dist/src/heartbeat/index.js +5 -0
  81. package/dist/src/heartbeat/index.js.map +1 -0
  82. package/dist/src/heartbeat/notifications.js +216 -0
  83. package/dist/src/heartbeat/notifications.js.map +1 -0
  84. package/dist/src/heartbeat/scheduler.js +284 -0
  85. package/dist/src/heartbeat/scheduler.js.map +1 -0
  86. package/dist/src/index.js +21 -3
  87. package/dist/src/index.js.map +1 -1
  88. package/dist/src/mode/auto-detector.js +211 -0
  89. package/dist/src/mode/auto-detector.js.map +1 -0
  90. package/dist/src/mode/index.js +3 -0
  91. package/dist/src/mode/index.js.map +1 -0
  92. package/dist/src/mode/natural-switcher.js +123 -0
  93. package/dist/src/mode/natural-switcher.js.map +1 -0
  94. package/dist/src/skills/builtin/api-worker.js +88 -0
  95. package/dist/src/skills/builtin/api-worker.js.map +1 -0
  96. package/dist/src/skills/builtin/nextjs-worker.js +55 -0
  97. package/dist/src/skills/builtin/nextjs-worker.js.map +1 -0
  98. package/dist/src/skills/builtin/real-workers.js +166 -0
  99. package/dist/src/skills/builtin/real-workers.js.map +1 -0
  100. package/dist/src/skills/builtin/sql-worker.js +61 -0
  101. package/dist/src/skills/builtin/sql-worker.js.map +1 -0
  102. package/dist/src/skills/builtin/test-worker.js +79 -0
  103. package/dist/src/skills/builtin/test-worker.js.map +1 -0
  104. package/dist/src/skills/builtin/web-research.js +77 -0
  105. package/dist/src/skills/builtin/web-research.js.map +1 -0
  106. package/dist/src/skills/framework.js +250 -0
  107. package/dist/src/skills/framework.js.map +1 -0
  108. package/dist/src/skills/index.js +10 -10
  109. package/dist/src/skills/index.js.map +1 -1
  110. package/dist/src/streaming/block-streamer.js +172 -0
  111. package/dist/src/streaming/block-streamer.js.map +1 -0
  112. package/dist/src/streaming/index.js +2 -0
  113. package/dist/src/streaming/index.js.map +1 -0
  114. package/dist/src/workspace/index.js +2 -0
  115. package/dist/src/workspace/index.js.map +1 -0
  116. package/dist/src/workspace/manager.js +181 -0
  117. package/dist/src/workspace/manager.js.map +1 -0
  118. package/package.json +3 -2
@@ -0,0 +1,642 @@
1
+ /**
2
+ * Unified Agent Orchestration Extension - v0.2.0
3
+ *
4
+ * Provides a single, coherent API for all agent operations.
5
+ *
6
+ * Hierarchy:
7
+ * Orchestrator (1) → Main Agents (N) → Subagents (M)
8
+ *
9
+ * Replaces:
10
+ * - agent_spawn (agent-registry) - DEPRECATED
11
+ * - subagent_spawn (subagent-extension) - DEPRECATED
12
+ * - agent_start/stop (agent-lifecycle) - INTEGRATED
13
+ *
14
+ * New unified API:
15
+ * - agent_orchestrate() - Single tool for all operations
16
+ * - /agent command family - Simplified CLI
17
+ * - /autonomous - Delegation control
18
+ *
19
+ * @version 0.2.0
20
+ * @deprecated Use agent_orchestrate instead of agent_spawn/subagent_spawn
21
+ */
22
+ import { Type } from "@sinclair/typebox";
23
+ import { spawn } from "node:child_process";
24
+ import * as fs from "node:fs/promises";
25
+ import * as path from "node:path";
26
+ import { homedir } from "node:os";
27
+ import { existsSync } from "node:fs";
28
+ // Constants
29
+ const ORCHESTRATOR_VERSION = "0.2.0";
30
+ const AGENTS_DIR = path.join(homedir(), ".0xkobold", "agents");
31
+ const STATE_FILE = path.join(homedir(), ".0xkobold", "orchestrator-state.json");
32
+ const MAX_PARALLEL_SUBAGENTS = 8;
33
+ const MAX_CONCURRENT_SUBAGENTS = 4;
34
+ // State management
35
+ const mainAgents = new Map();
36
+ const subagentAgents = new Map();
37
+ let autonomyMode = "medium";
38
+ // Initialize subagent definitions
39
+ function loadBuiltinSubagents() {
40
+ const agents = new Map();
41
+ const definitions = [
42
+ {
43
+ name: "scout",
44
+ description: "Fast codebase reconnaissance",
45
+ tools: ["read", "search", "list"],
46
+ model: "qwen2.5-coder:14b",
47
+ systemPrompt: `You are a fast reconnaissance agent. Find relevant code quickly and return compressed summaries (max 500 tokens). Be concise. Focus on facts.`,
48
+ scope: "builtin",
49
+ },
50
+ {
51
+ name: "planner",
52
+ description: "Creates implementation plans",
53
+ tools: ["read", "search", "list"],
54
+ model: "qwen2.5-coder:14b",
55
+ systemPrompt: `You are a planning specialist. Analyze requirements and create step-by-step implementation plans with specific file paths.`,
56
+ scope: "builtin",
57
+ },
58
+ {
59
+ name: "worker",
60
+ description: "Full implementation agent",
61
+ tools: ["read", "write", "edit", "search", "shell"],
62
+ model: "qwen2.5-coder:14b",
63
+ systemPrompt: `You are an implementation specialist. Write clean, well-tested code following existing patterns. Verify changes work.`,
64
+ scope: "builtin",
65
+ },
66
+ {
67
+ name: "reviewer",
68
+ description: "Code review specialist",
69
+ tools: ["read", "search", "shell"],
70
+ model: "qwen2.5-coder:14b",
71
+ systemPrompt: `You are a code review specialist. Identify bugs, security issues, and style violations. Provide specific line-by-line feedback.`,
72
+ scope: "builtin",
73
+ },
74
+ ];
75
+ for (const agent of definitions) {
76
+ agents.set(agent.name, agent);
77
+ }
78
+ return agents;
79
+ }
80
+ // Task analysis for autonomous delegation
81
+ function analyzeTask(task) {
82
+ const taskLower = task.toLowerCase();
83
+ const words = task.split(/\s+/).length;
84
+ const simpleKeywords = ["fix", "update", "change", "add", "remove", "typo"];
85
+ const mediumKeywords = ["implement", "create", "build", "refactor", "migrate", "add feature"];
86
+ const complexKeywords = ["system", "architecture", "redesign", "framework", "platform", "microservices"];
87
+ const filePatterns = task.match(/\b\w+\.(ts|js|tsx|jsx|py|rs|go)\b/g) || [];
88
+ const specificFiles = filePatterns.length;
89
+ let score = 0;
90
+ if (words < 15)
91
+ score += 1;
92
+ else if (words < 50)
93
+ score += 2;
94
+ else
95
+ score += 3;
96
+ simpleKeywords.forEach(k => { if (taskLower.includes(k))
97
+ score += 1; });
98
+ mediumKeywords.forEach(k => { if (taskLower.includes(k))
99
+ score += 2; });
100
+ complexKeywords.forEach(k => { if (taskLower.includes(k))
101
+ score += 3; });
102
+ if (specificFiles > 0 && specificFiles <= 3)
103
+ score = Math.min(score, 4);
104
+ if (specificFiles > 3)
105
+ score += 1;
106
+ let complexity;
107
+ if (score <= 5)
108
+ complexity = "simple";
109
+ else if (score <= 10)
110
+ complexity = "medium";
111
+ else
112
+ complexity = "complex";
113
+ const strategies = {
114
+ simple: "Execute directly",
115
+ medium: "Scout → Worker",
116
+ complex: "Scout → Planner → Workers → Reviewer",
117
+ };
118
+ return {
119
+ complexity,
120
+ estimatedFiles: specificFiles || (complexity === "simple" ? 1 : complexity === "medium" ? 3 : 5),
121
+ requiresResearch: complexity !== "simple" && !specificFiles,
122
+ requiresPlanning: complexity === "complex" || (complexity === "medium" && words > 30),
123
+ suggestedStrategy: strategies[complexity],
124
+ confidence: Math.min(0.9, 0.5 + score / 20),
125
+ };
126
+ }
127
+ // Main agent lifecycle
128
+ async function startMainAgent(name, ctx) {
129
+ if (mainAgents.has(name)) {
130
+ return { success: false, error: "Agent already running" };
131
+ }
132
+ // Load config
133
+ const configPath = path.join(AGENTS_DIR, name, "config.json");
134
+ if (!existsSync(configPath)) {
135
+ return { success: false, error: `Agent config not found: ${configPath}` };
136
+ }
137
+ let config;
138
+ try {
139
+ const content = await fs.readFile(configPath, "utf-8");
140
+ config = JSON.parse(content);
141
+ }
142
+ catch (error) {
143
+ return { success: false, error: `Failed to load config: ${error}` };
144
+ }
145
+ const agentDir = path.join(AGENTS_DIR, name);
146
+ const workspaceDir = path.join(agentDir, "workspace");
147
+ const logsDir = path.join(agentDir, "logs");
148
+ await fs.mkdir(logsDir, { recursive: true });
149
+ const port = 18790 + mainAgents.size + 1;
150
+ const logFile = path.join(logsDir, "agent.log");
151
+ return new Promise((resolve) => {
152
+ const child = spawn("bun", ["run", "src/cli/index.ts", "--local"], {
153
+ cwd: process.cwd(),
154
+ env: {
155
+ ...process.env,
156
+ KOBOLD_AGENT_NAME: name,
157
+ KOBOLD_AGENT_MODE: "main",
158
+ KOBOLD_WORKSPACE: workspaceDir,
159
+ PI_CODING_AGENT_DIR: agentDir,
160
+ GATEWAY_PORT: port.toString(),
161
+ GATEWAY_HOST: "127.0.0.1",
162
+ },
163
+ stdio: ["ignore", "pipe", "pipe"],
164
+ detached: true,
165
+ });
166
+ if (!child.pid) {
167
+ resolve({ success: false, error: "Failed to spawn process" });
168
+ return;
169
+ }
170
+ const agentProcess = {
171
+ name,
172
+ process: child,
173
+ pid: child.pid,
174
+ startedAt: new Date(),
175
+ status: "starting",
176
+ port,
177
+ config,
178
+ };
179
+ mainAgents.set(name, agentProcess);
180
+ child.stdout?.on("data", (data) => {
181
+ const text = data.toString();
182
+ if (text.includes("🐉 0xKobold starting") || text.includes("Extension loaded")) {
183
+ agentProcess.status = "running";
184
+ }
185
+ fs.appendFile(logFile, `[${new Date().toISOString()}] ${text}`).catch(() => { });
186
+ });
187
+ child.stderr?.on("data", (data) => {
188
+ fs.appendFile(logFile, `[${new Date().toISOString()}] ERROR: ${data.toString()}`).catch(() => { });
189
+ });
190
+ child.on("exit", (code) => {
191
+ mainAgents.delete(name);
192
+ if (code !== 0 && code !== null) {
193
+ console.log(`[Orchestrator] Agent ${name} exited with code ${code}`);
194
+ }
195
+ });
196
+ const checkInterval = setInterval(() => {
197
+ if (agentProcess.status === "running") {
198
+ clearInterval(checkInterval);
199
+ clearTimeout(timeout);
200
+ resolve({ success: true, pid: child.pid });
201
+ }
202
+ }, 100);
203
+ const timeout = setTimeout(() => {
204
+ clearInterval(checkInterval);
205
+ if (agentProcess.status === "starting") {
206
+ agentProcess.status = "error";
207
+ agentProcess.lastError = "Startup timeout";
208
+ resolve({ success: false, error: "Agent startup timeout (30s)" });
209
+ }
210
+ }, 30000);
211
+ });
212
+ }
213
+ async function stopMainAgent(name) {
214
+ const agent = mainAgents.get(name);
215
+ if (!agent) {
216
+ return { success: false, error: "Agent not running" };
217
+ }
218
+ agent.process.kill("SIGTERM");
219
+ return new Promise((resolve) => {
220
+ const timeout = setTimeout(() => {
221
+ agent.process.kill("SIGKILL");
222
+ mainAgents.delete(name);
223
+ resolve({ success: true });
224
+ }, 5000);
225
+ agent.process.on("exit", () => {
226
+ clearTimeout(timeout);
227
+ mainAgents.delete(name);
228
+ resolve({ success: true });
229
+ });
230
+ });
231
+ }
232
+ // Subagent spawning
233
+ async function spawnSubagent(agentName, task, ctx) {
234
+ const startTime = Date.now();
235
+ const agentConfig = subagentAgents.get(agentName);
236
+ if (!agentConfig) {
237
+ return {
238
+ agent: agentName,
239
+ task,
240
+ exitCode: 1,
241
+ output: "",
242
+ error: `Subagent '${agentName}' not found`,
243
+ duration: 0,
244
+ };
245
+ }
246
+ return new Promise((resolve) => {
247
+ const args = [
248
+ "run",
249
+ "src/cli/index.ts",
250
+ "--command",
251
+ `agent:${agentConfig.name}`,
252
+ "--task",
253
+ task,
254
+ ];
255
+ const child = spawn("bun", args, {
256
+ cwd: process.cwd(),
257
+ env: {
258
+ ...process.env,
259
+ KOBOLD_SUBAGENT: "true",
260
+ KOBOLD_AGENT_MODEL: agentConfig.model,
261
+ KOBOLD_AGENT_TOOLS: agentConfig.tools.join(","),
262
+ },
263
+ stdio: ["ignore", "pipe", "pipe"],
264
+ });
265
+ let output = "";
266
+ let error = "";
267
+ child.stdout?.on("data", (data) => {
268
+ output += data.toString();
269
+ });
270
+ child.stderr?.on("data", (data) => {
271
+ error += data.toString();
272
+ });
273
+ child.on("close", (code) => {
274
+ resolve({
275
+ agent: agentConfig.name,
276
+ task,
277
+ exitCode: code || 0,
278
+ output: output.trim(),
279
+ error: error.trim() || undefined,
280
+ duration: Date.now() - startTime,
281
+ });
282
+ });
283
+ setTimeout(() => {
284
+ child.kill("SIGTERM");
285
+ }, 5 * 60 * 1000);
286
+ });
287
+ }
288
+ export default async function unifiedOrchestratorExtension(pi) {
289
+ console.log(`[Orchestrator] v${ORCHESTRATOR_VERSION} loaded`);
290
+ // Initialize
291
+ await fs.mkdir(AGENTS_DIR, { recursive: true });
292
+ subagentAgents.clear();
293
+ for (const [k, v] of loadBuiltinSubagents()) {
294
+ subagentAgents.set(k, v);
295
+ }
296
+ // ============================================================================
297
+ // UNIFIED TOOL: agent_orchestrate
298
+ // ============================================================================
299
+ pi.registerTool({
300
+ name: "agent_orchestrate",
301
+ label: "Unified Agent Orchestration",
302
+ description: "Single API for all agent operations: spawn main agents, spawn subagents, check status, auto-delegate tasks",
303
+ parameters: Type.Object({
304
+ operation: Type.String({
305
+ description: "Operation type: spawn_main, spawn_subagent, list, status, stop, analyze, delegate",
306
+ }),
307
+ // Main agent config
308
+ mainAgent: Type.Optional(Type.String({ description: "Main agent name" })),
309
+ // Subagent config
310
+ subagent: Type.Optional(Type.String({ description: "Subagent type (scout, planner, worker, reviewer)" })),
311
+ task: Type.Optional(Type.String({ description: "Task description" })),
312
+ // Delegation
313
+ autoDelegate: Type.Optional(Type.Boolean({ description: "Auto-analyze and delegate task", default: false })),
314
+ strategy: Type.Optional(Type.String({ description: "Delegation strategy: simple, medium, complex", default: "medium" })),
315
+ }),
316
+ async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
317
+ const operation = params.operation;
318
+ switch (operation) {
319
+ case "spawn_main": {
320
+ const name = params.mainAgent;
321
+ if (!name) {
322
+ return { content: [{ type: "text", text: "❌ mainAgent required" }], details: { error: "missing_name" } };
323
+ }
324
+ const result = await startMainAgent(name, ctx);
325
+ if (result.success) {
326
+ return {
327
+ content: [{ type: "text", text: `✅ Main agent '${name}' started (PID: ${result.pid})` }],
328
+ details: { name, pid: result.pid, status: "running" },
329
+ };
330
+ }
331
+ else {
332
+ return {
333
+ content: [{ type: "text", text: `❌ Failed: ${result.error}` }],
334
+ details: { error: result.error },
335
+ };
336
+ }
337
+ }
338
+ case "spawn_subagent": {
339
+ const agent = params.subagent;
340
+ const task = params.task;
341
+ if (!agent || !task) {
342
+ return { content: [{ type: "text", text: "❌ subagent and task required" }], details: { error: "missing_params" } };
343
+ }
344
+ ctx.ui.notify(`🚀 Spawning ${agent} for task...`, "info");
345
+ const result = await spawnSubagent(agent, task, ctx);
346
+ const status = result.exitCode === 0 ? "✅" : "❌";
347
+ return {
348
+ content: [{
349
+ type: "text",
350
+ text: `${status} ${result.agent} complete (${result.duration}ms)\n\n${result.output}`,
351
+ }],
352
+ details: result,
353
+ };
354
+ }
355
+ case "list": {
356
+ const mainList = Array.from(mainAgents.entries()).map(([name, info]) => ({
357
+ type: "main",
358
+ name,
359
+ status: info.status,
360
+ pid: info.pid,
361
+ }));
362
+ const subList = Array.from(subagentAgents.keys()).map(name => ({
363
+ type: "subagent",
364
+ name,
365
+ scope: subagentAgents.get(name)?.scope,
366
+ }));
367
+ return {
368
+ content: [{
369
+ type: "text",
370
+ text: `Main Agents (${mainList.length}):\n${mainList.map(a => `- ${a.name}: ${a.status}`).join("\n")}\n\nSubagents (${subList.length}):\n${subList.map(a => `- ${a.name}`).join("\n")}`,
371
+ }],
372
+ details: { main: mainList, subagents: subList },
373
+ };
374
+ }
375
+ case "status": {
376
+ const name = params.mainAgent;
377
+ if (name) {
378
+ const agent = mainAgents.get(name);
379
+ if (!agent) {
380
+ return { content: [{ type: "text", text: `Agent '${name}' not running` }], details: { name, status: "stopped" } };
381
+ }
382
+ return {
383
+ content: [{
384
+ type: "text",
385
+ text: `Agent: ${agent.name}\nStatus: ${agent.status}\nPID: ${agent.pid}\nStarted: ${agent.startedAt.toISOString()}`,
386
+ }],
387
+ details: { name: agent.name, status: agent.status, pid: agent.pid, startedAt: agent.startedAt },
388
+ };
389
+ }
390
+ const list = Array.from(mainAgents.entries()).map(([name, info]) => ({ name, status: info.status, pid: info.pid }));
391
+ return {
392
+ content: [{ type: "text", text: `${list.length} main agents running` }],
393
+ details: { agents: list },
394
+ };
395
+ }
396
+ case "stop": {
397
+ const name = params.mainAgent;
398
+ if (!name) {
399
+ return { content: [{ type: "text", text: "❌ mainAgent required" }], details: { error: "missing_name" } };
400
+ }
401
+ const result = await stopMainAgent(name);
402
+ return {
403
+ content: [{ type: "text", text: result.success ? `✅ Agent '${name}' stopped` : `❌ Failed: ${result.error}` }],
404
+ details: { name, success: result.success },
405
+ };
406
+ }
407
+ case "analyze": {
408
+ const task = params.task;
409
+ if (!task) {
410
+ return { content: [{ type: "text", text: "❌ task required" }], details: { error: "missing_task" } };
411
+ }
412
+ const analysis = analyzeTask(task);
413
+ return {
414
+ content: [{
415
+ type: "text",
416
+ text: `**Task Analysis**\n\nTask: ${task}\nComplexity: ${analysis.complexity}\nStrategy: ${analysis.suggestedStrategy}\nConfidence: ${Math.round(analysis.confidence * 100)}%`,
417
+ }],
418
+ details: analysis,
419
+ };
420
+ }
421
+ case "delegate": {
422
+ const task = params.task;
423
+ const strategy = params.strategy || autonomyMode;
424
+ if (!task) {
425
+ return { content: [{ type: "text", text: "❌ task required" }], details: { error: "missing_task" } };
426
+ }
427
+ const analysis = analyzeTask(task);
428
+ // Check if we should delegate based on strategy
429
+ let shouldDelegate = false;
430
+ switch (strategy) {
431
+ case "always":
432
+ shouldDelegate = true;
433
+ break;
434
+ case "complex":
435
+ shouldDelegate = analysis.complexity === "complex";
436
+ break;
437
+ case "medium":
438
+ shouldDelegate = analysis.complexity !== "simple";
439
+ break;
440
+ case "simple":
441
+ shouldDelegate = analysis.complexity === "complex";
442
+ break;
443
+ case "off":
444
+ shouldDelegate = false;
445
+ break;
446
+ }
447
+ if (!shouldDelegate) {
448
+ return {
449
+ content: [{ type: "text", text: `Task complexity: ${analysis.complexity}. Strategy '${strategy}' says handle directly.` }],
450
+ details: { analysis, delegated: false },
451
+ };
452
+ }
453
+ ctx.ui.notify(`🤖 Delegating: ${analysis.suggestedStrategy}`, "info");
454
+ // Execute delegation workflow
455
+ let result = `**Autonomous Delegation**\n\nTask: ${task}\nComplexity: ${analysis.complexity}\nStrategy: ${analysis.suggestedStrategy}\n\n`;
456
+ if (analysis.complexity === "medium") {
457
+ result += "1. Spawn scout for reconnaissance\n2. Spawn worker for implementation\n\n✅ Delegation plan ready";
458
+ }
459
+ else if (analysis.complexity === "complex") {
460
+ result += "1. Scout → finds relevant code\n2. Planner → creates implementation plan\n3. Workers → implement components\n4. Reviewer → reviews all changes\n\n✅ Full workflow ready";
461
+ }
462
+ return {
463
+ content: [{ type: "text", text: result }],
464
+ details: { analysis, delegated: true, strategy },
465
+ };
466
+ }
467
+ default:
468
+ return {
469
+ content: [{ type: "text", text: `❌ Unknown operation: ${operation}` }],
470
+ details: { error: "unknown_operation", valid: ["spawn_main", "spawn_subagent", "list", "status", "stop", "analyze", "delegate"] },
471
+ };
472
+ }
473
+ },
474
+ });
475
+ // ============================================================================
476
+ // UNIFIED COMMANDS: /agent family
477
+ // ============================================================================
478
+ // /agent create <name>
479
+ pi.registerCommand("agent-create", {
480
+ description: "Create new main agent workspace: /agent-create <name>",
481
+ handler: async (args, ctx) => {
482
+ const name = args.trim();
483
+ if (!name) {
484
+ ctx.ui.notify("❌ Usage: /agent-create <name>", "error");
485
+ return;
486
+ }
487
+ const agentDir = path.join(AGENTS_DIR, name);
488
+ if (existsSync(agentDir)) {
489
+ ctx.ui.notify(`❌ Agent '${name}' already exists`, "error");
490
+ return;
491
+ }
492
+ // Create structure
493
+ await fs.mkdir(path.join(agentDir, "workspace"), { recursive: true });
494
+ await fs.mkdir(path.join(agentDir, "memory"), { recursive: true });
495
+ await fs.mkdir(path.join(agentDir, "logs"), { recursive: true });
496
+ await fs.mkdir(path.join(agentDir, "agents"), { recursive: true });
497
+ // Create config
498
+ const config = {
499
+ name,
500
+ description: `Main agent for ${name}`,
501
+ version: "1.0.0",
502
+ enabled: true,
503
+ autoStart: false,
504
+ workspace: { path: path.join(agentDir, "workspace") },
505
+ activation: { manual: true },
506
+ model: { provider: "ollama", model: "qwen2.5-coder:14b" },
507
+ capabilities: ["read", "write", "edit", "search", "shell"],
508
+ memory: { enabled: true },
509
+ };
510
+ await fs.writeFile(path.join(agentDir, "config.json"), JSON.stringify(config, null, 2));
511
+ ctx.ui.notify(`✅ Created main agent: ${name}`, "info");
512
+ },
513
+ });
514
+ // /agent start <name>
515
+ pi.registerCommand("agent-start", {
516
+ description: "Start main agent: /agent-start <name>",
517
+ handler: async (args, ctx) => {
518
+ const name = args.trim();
519
+ if (!name) {
520
+ ctx.ui.notify("❌ Usage: /agent-start <name>", "error");
521
+ return;
522
+ }
523
+ ctx.ui.notify(`🚀 Starting ${name}...`, "info");
524
+ const result = await startMainAgent(name, ctx);
525
+ if (result.success) {
526
+ ctx.ui.notify(`✅ Agent ${name} running (PID: ${result.pid})`, "info");
527
+ }
528
+ else {
529
+ ctx.ui.notify(`❌ Failed: ${result.error}`, "error");
530
+ }
531
+ },
532
+ });
533
+ // /agent stop <name>
534
+ pi.registerCommand("agent-stop", {
535
+ description: "Stop main agent: /agent-stop <name>",
536
+ handler: async (args, ctx) => {
537
+ const name = args.trim();
538
+ if (!name) {
539
+ ctx.ui.notify("❌ Usage: /agent-stop <name>", "error");
540
+ return;
541
+ }
542
+ ctx.ui.notify(`🛑 Stopping ${name}...`, "info");
543
+ const result = await stopMainAgent(name);
544
+ ctx.ui.notify(result.success ? `✅ Agent ${name} stopped` : `❌ ${result.error}`, result.success ? "info" : "error");
545
+ },
546
+ });
547
+ // /agent status [name]
548
+ pi.registerCommand("agent-status", {
549
+ description: "Check agent status: /agent-status [name]",
550
+ handler: async (args, ctx) => {
551
+ const name = args.trim();
552
+ if (name) {
553
+ const agent = mainAgents.get(name);
554
+ if (agent) {
555
+ const uptime = Math.floor((Date.now() - agent.startedAt.getTime()) / 1000);
556
+ ctx.ui.notify(`${name}: ${agent.status} (${uptime}s uptime)`, "info");
557
+ }
558
+ else {
559
+ ctx.ui.notify(`${name}: stopped`, "info");
560
+ }
561
+ }
562
+ else {
563
+ const count = mainAgents.size;
564
+ const list = Array.from(mainAgents.keys()).join(", ");
565
+ ctx.ui.notify(`${count} agents: ${list || "none"}`, "info");
566
+ }
567
+ },
568
+ });
569
+ // /agent spawn <type> <task>
570
+ pi.registerCommand("agent-spawn", {
571
+ description: "Spawn subagent: /agent-spawn <scout|planner|worker|reviewer> <task>",
572
+ handler: async (args, ctx) => {
573
+ const parts = args.trim().split(/\s+/);
574
+ const agentType = parts[0];
575
+ const task = parts.slice(1).join(" ");
576
+ if (!agentType || !task) {
577
+ ctx.ui.notify("❌ Usage: /agent-spawn <type> <task>", "error");
578
+ return;
579
+ }
580
+ if (!subagentAgents.has(agentType)) {
581
+ ctx.ui.notify(`❌ Unknown subagent: ${agentType}`, "error");
582
+ return;
583
+ }
584
+ ctx.ui.notify(`🚀 Spawning ${agentType}...`, "info");
585
+ const result = await spawnSubagent(agentType, task, ctx);
586
+ if (result.exitCode === 0) {
587
+ ctx.ui.notify(`✅ ${agentType} complete`, "info");
588
+ }
589
+ else {
590
+ ctx.ui.notify(`❌ ${agentType} failed`, "error");
591
+ }
592
+ },
593
+ });
594
+ // /agents
595
+ pi.registerCommand("agents", {
596
+ description: "List all agents (main and subagents)",
597
+ handler: async (_args, ctx) => {
598
+ const mainList = Array.from(mainAgents.keys()).map(name => {
599
+ const a = mainAgents.get(name);
600
+ return `- ${name}: ${a?.status}`;
601
+ }).join("\n") || "None running";
602
+ const subList = Array.from(subagentAgents.keys()).join(", ");
603
+ ctx.ui.notify(`Main: ${mainList}\n\nSubagents: ${subList}`, "info");
604
+ },
605
+ });
606
+ // ============================================================================
607
+ // AUTONOMOUS DELEGATION COMMANDS
608
+ // ============================================================================
609
+ // /autonomous [mode]
610
+ pi.registerCommand("autonomous", {
611
+ description: "Control autonomous delegation: /autonomous [off|simple|medium|complex|always]",
612
+ handler: async (args, ctx) => {
613
+ const mode = args.trim();
614
+ if (mode && ["off", "simple", "medium", "complex", "always"].includes(mode)) {
615
+ autonomyMode = mode;
616
+ ctx.ui.notify(`✅ Autonomous mode: ${mode}`, "info");
617
+ }
618
+ else if (args.trim()) {
619
+ ctx.ui.notify("❌ Invalid mode. Use: off, simple, medium, complex, always", "error");
620
+ }
621
+ else {
622
+ ctx.ui.notify(`🔄 Autonomous mode: ${autonomyMode}`, "info");
623
+ }
624
+ },
625
+ });
626
+ // /analyze <task>
627
+ pi.registerCommand("analyze", {
628
+ description: "Analyze task complexity: /analyze <task description>",
629
+ handler: async (args, ctx) => {
630
+ if (!args.trim()) {
631
+ ctx.ui.notify("❌ Usage: /analyze <task>", "error");
632
+ return;
633
+ }
634
+ const analysis = analyzeTask(args);
635
+ ctx.ui.notify(`Complexity: ${analysis.complexity}\nStrategy: ${analysis.suggestedStrategy}\nConfidence: ${Math.round(analysis.confidence * 100)}%`, "info");
636
+ },
637
+ });
638
+ console.log(`[Orchestrator] Ready with ${mainAgents.size} main agents, ${subagentAgents.size} subagents`);
639
+ console.log("[Orchestrator] Use /agent commands or agent_orchestrate tool");
640
+ console.log("[Orchestrator] ⚠️ agent_spawn and subagent_spawn are deprecated, use agent_orchestrate");
641
+ }
642
+ //# sourceMappingURL=agent-orchestrator-extension.js.map