0xkobold 0.0.6 → 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 (120) 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/perennial-memory-extension.js +10 -2
  65. package/dist/src/extensions/core/perennial-memory-extension.js.map +1 -1
  66. package/dist/src/extensions/core/persona-loader-extension.js +61 -129
  67. package/dist/src/extensions/core/persona-loader-extension.js.map +1 -1
  68. package/dist/src/extensions/core/websearch-enhanced-extension.js +705 -0
  69. package/dist/src/extensions/core/websearch-enhanced-extension.js.map +1 -0
  70. package/dist/src/extensions/core/websearch-v2-extension.js +303 -0
  71. package/dist/src/extensions/core/websearch-v2-extension.js.map +1 -0
  72. package/dist/src/gateway/discord-bot.js +185 -0
  73. package/dist/src/gateway/discord-bot.js.map +1 -0
  74. package/dist/src/gateway/index.js +10 -350
  75. package/dist/src/gateway/index.js.map +1 -1
  76. package/dist/src/gateway/server.js +325 -0
  77. package/dist/src/gateway/server.js.map +1 -0
  78. package/dist/src/gateway/websocket-server.js +142 -0
  79. package/dist/src/gateway/websocket-server.js.map +1 -0
  80. package/dist/src/heartbeat/checkin.js +185 -0
  81. package/dist/src/heartbeat/checkin.js.map +1 -0
  82. package/dist/src/heartbeat/index.js +5 -0
  83. package/dist/src/heartbeat/index.js.map +1 -0
  84. package/dist/src/heartbeat/notifications.js +216 -0
  85. package/dist/src/heartbeat/notifications.js.map +1 -0
  86. package/dist/src/heartbeat/scheduler.js +284 -0
  87. package/dist/src/heartbeat/scheduler.js.map +1 -0
  88. package/dist/src/index.js +21 -3
  89. package/dist/src/index.js.map +1 -1
  90. package/dist/src/mode/auto-detector.js +211 -0
  91. package/dist/src/mode/auto-detector.js.map +1 -0
  92. package/dist/src/mode/index.js +3 -0
  93. package/dist/src/mode/index.js.map +1 -0
  94. package/dist/src/mode/natural-switcher.js +123 -0
  95. package/dist/src/mode/natural-switcher.js.map +1 -0
  96. package/dist/src/skills/builtin/api-worker.js +88 -0
  97. package/dist/src/skills/builtin/api-worker.js.map +1 -0
  98. package/dist/src/skills/builtin/nextjs-worker.js +55 -0
  99. package/dist/src/skills/builtin/nextjs-worker.js.map +1 -0
  100. package/dist/src/skills/builtin/real-workers.js +166 -0
  101. package/dist/src/skills/builtin/real-workers.js.map +1 -0
  102. package/dist/src/skills/builtin/sql-worker.js +61 -0
  103. package/dist/src/skills/builtin/sql-worker.js.map +1 -0
  104. package/dist/src/skills/builtin/test-worker.js +79 -0
  105. package/dist/src/skills/builtin/test-worker.js.map +1 -0
  106. package/dist/src/skills/builtin/web-research.js +77 -0
  107. package/dist/src/skills/builtin/web-research.js.map +1 -0
  108. package/dist/src/skills/framework.js +250 -0
  109. package/dist/src/skills/framework.js.map +1 -0
  110. package/dist/src/skills/index.js +10 -10
  111. package/dist/src/skills/index.js.map +1 -1
  112. package/dist/src/streaming/block-streamer.js +172 -0
  113. package/dist/src/streaming/block-streamer.js.map +1 -0
  114. package/dist/src/streaming/index.js +2 -0
  115. package/dist/src/streaming/index.js.map +1 -0
  116. package/dist/src/workspace/index.js +2 -0
  117. package/dist/src/workspace/index.js.map +1 -0
  118. package/dist/src/workspace/manager.js +181 -0
  119. package/dist/src/workspace/manager.js.map +1 -0
  120. package/package.json +3 -2
@@ -0,0 +1,333 @@
1
+ /**
2
+ * Autonomous Subagent Extension - v0.2.1
3
+ *
4
+ * Enables main agents to automatically use subagents based on task analysis.
5
+ * No explicit /implement command needed - just say "use subagents" or the agent
6
+ * automatically decides when delegation is appropriate.
7
+ *
8
+ * Features:
9
+ * - Task complexity analysis
10
+ * - Automatic delegation decisions
11
+ * - Multi-strategy execution modes
12
+ * - User-controlled autonomy levels
13
+ *
14
+ * @version 0.2.1
15
+ */
16
+ import { Type } from "@sinclair/typebox";
17
+ let autonomyConfig = {
18
+ mode: "medium",
19
+ maxParallelAgents: 4,
20
+ taskThreshold: 10,
21
+ };
22
+ function analyzeTask(task) {
23
+ const taskLower = task.toLowerCase();
24
+ const words = task.split(/\s+/).length;
25
+ // Keywords indicating complexity
26
+ const simpleKeywords = ["fix", "update", "change", "add", "remove"];
27
+ const mediumKeywords = ["implement", "create", "build", "refactor", "migrate"];
28
+ const complexKeywords = [
29
+ "system",
30
+ "architecture",
31
+ "redesign",
32
+ "framework",
33
+ "platform",
34
+ "microservices",
35
+ "distributed",
36
+ ];
37
+ // File count indicators
38
+ const filePatterns = task.match(/\b\w+\.(ts|js|tsx|jsx|py|rs|go)\b/g) || [];
39
+ const specificFiles = filePatterns.length;
40
+ // Calculate complexity score
41
+ let score = 0;
42
+ if (words < 15)
43
+ score += 1;
44
+ else if (words < 50)
45
+ score += 2;
46
+ else
47
+ score += 3;
48
+ simpleKeywords.forEach((k) => { if (taskLower.includes(k))
49
+ score += 1; });
50
+ mediumKeywords.forEach((k) => { if (taskLower.includes(k))
51
+ score += 2; });
52
+ complexKeywords.forEach((k) => { if (taskLower.includes(k))
53
+ score += 3; });
54
+ // Specific files mentioned reduce complexity (more defined scope)
55
+ if (specificFiles > 0 && specificFiles <= 3)
56
+ score = Math.min(score, 4);
57
+ if (specificFiles > 3)
58
+ score += 1;
59
+ // Determine complexity
60
+ let complexity;
61
+ if (score <= 5)
62
+ complexity = "simple";
63
+ else if (score <= 10)
64
+ complexity = "medium";
65
+ else
66
+ complexity = "complex";
67
+ // Determine strategy
68
+ let estimatedFiles = specificFiles || (complexity === "simple" ? 1 : complexity === "medium" ? 3 : 5);
69
+ const requiresResearch = complexity !== "simple" && !specificFiles;
70
+ const requiresPlanning = complexity === "complex" || (complexity === "medium" && words > 30);
71
+ const strategies = {
72
+ simple: "Execute directly - no subagents needed",
73
+ medium: "Use scout + worker workflow",
74
+ complex: "Full workflow: scout → planner → workers → reviewer",
75
+ };
76
+ return {
77
+ complexity,
78
+ estimatedFiles,
79
+ requiresResearch,
80
+ requiresPlanning,
81
+ suggestedStrategy: strategies[complexity],
82
+ confidence: Math.min(0.9, 0.5 + score / 20),
83
+ };
84
+ }
85
+ // Delegation strategies
86
+ async function executeStrategy(task, analysis, ctx) {
87
+ const { complexity } = analysis;
88
+ switch (autonomyConfig.mode) {
89
+ case "off":
90
+ return "Autonomy is disabled. Use explicit /implement command.";
91
+ case "simple":
92
+ // Only use subagents for complex tasks
93
+ if (complexity !== "complex") {
94
+ return `Task complexity: ${complexity}. Not using subagents (simple mode).`;
95
+ }
96
+ break;
97
+ case "medium":
98
+ // Use subagents for medium and complex
99
+ if (complexity === "simple") {
100
+ return `Task complexity: ${complexity}. Not using subagents.`;
101
+ }
102
+ break;
103
+ case "always":
104
+ // Always use subagents regardless of complexity
105
+ break;
106
+ case "complex":
107
+ default:
108
+ // Only use subagents for complex
109
+ if (complexity !== "complex") {
110
+ return `Task complexity: ${complexity}. Not using subagents (only complex tasks).`;
111
+ }
112
+ }
113
+ // Execute based on complexity
114
+ ctx.ui.notify(`🤖 Autonomous delegation: ${complexity} task. ${analysis.suggestedStrategy}`, "info");
115
+ if (complexity === "medium") {
116
+ // Medium: Scout + Worker
117
+ ctx.ui.notify("Spawning scout + worker...", "info");
118
+ // In real implementation, these would call subagent_spawn
119
+ return `
120
+ **Autonomous Delegation (Medium Complexity)**
121
+
122
+ Strategy: Scout → Worker
123
+
124
+ 1. **Scout** - Finds relevant code
125
+ 2. **Worker** - Implements based on findings
126
+
127
+ Task: "${task}"
128
+
129
+ *Estimated: ${analysis.estimatedFiles} files*
130
+ *Confidence: ${Math.round(analysis.confidence * 100)}%*
131
+
132
+ ---
133
+
134
+ Would you like me to:
135
+ - A) Execute with subagents now
136
+ - B) Show detailed plan first
137
+ - C) Handle manually (no subagents)
138
+ `;
139
+ }
140
+ if (complexity === "complex") {
141
+ // Complex: Full workflow
142
+ ctx.ui.notify("Spawning full workflow...", "info");
143
+ return `
144
+ **Autonomous Delegation (Complex Task)**
145
+
146
+ Strategy: Scout → Planner → Workers → Reviewer
147
+
148
+ 1. **Scout** - Comprehensive reconnaissance
149
+ 2. **Planner** - Creates implementation plan
150
+ 3. **Workers** - Parallel implementation (up to ${autonomyConfig.maxParallelAgents})
151
+ 4. **Reviewer** - Code review of all changes
152
+
153
+ Task: "${task}"
154
+
155
+ *Estimated: ${analysis.estimatedFiles}+ files*
156
+ *Requires planning: ${analysis.requiresPlanning ? "Yes" : "No"}*
157
+ *Confidence: ${Math.round(analysis.confidence * 100)}%*
158
+
159
+ ---
160
+
161
+ Would you like me to:
162
+ - A) Launch full autonomous workflow
163
+ - B) Create detailed breakdown first
164
+ - C) Simpler approach (scout + worker only)
165
+ `;
166
+ }
167
+ return "Unknown complexity";
168
+ }
169
+ export default async function autonomousSubagentExtension(pi) {
170
+ console.log("[AutonomousSubagent] Extension loaded");
171
+ // Register tool for analysis (used by agent or accessible directly)
172
+ pi.registerTool({
173
+ name: "analyze_task",
174
+ label: "Analyze Task Complexity",
175
+ description: "Analyze task complexity and suggest delegation strategy",
176
+ parameters: Type.Object({
177
+ task: Type.String({ description: "Task to analyze" }),
178
+ }),
179
+ async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
180
+ const task = params.task;
181
+ const analysis = analyzeTask(task);
182
+ return {
183
+ content: [
184
+ {
185
+ type: "text",
186
+ text: `**Task Analysis:**
187
+
188
+ **Task:** ${task}
189
+
190
+ **Complexity:** ${analysis.complexity}
191
+ **Estimated Files:** ${analysis.estimatedFiles}
192
+ **Requires Research:** ${analysis.requiresResearch ? "Yes" : "No"}
193
+ **Requires Planning:** ${analysis.requiresPlanning ? "Yes" : "No"}
194
+ **Confidence:** ${Math.round(analysis.confidence * 100)}%
195
+
196
+ **Suggested Strategy:**
197
+ ${analysis.suggestedStrategy}
198
+
199
+ **Recommendation:**
200
+ ${analysis.complexity === "simple"
201
+ ? "Handle directly without subagents."
202
+ : analysis.complexity === "medium"
203
+ ? "Use /implement or delegate to scout + worker."
204
+ : "Consider full workflow with planner and multiple workers."}`,
205
+ },
206
+ ],
207
+ details: analysis,
208
+ };
209
+ },
210
+ });
211
+ // TOOL: autonomous_delegation
212
+ pi.registerTool({
213
+ name: "autonomous_delegation",
214
+ label: "Autonomous Task Delegation",
215
+ description: "Automatically delegate task to appropriate subagents based on analysis",
216
+ parameters: Type.Object({
217
+ task: Type.String({ description: "Task to delegate" }),
218
+ mode: Type.Optional(Type.String({
219
+ description: "Override autonomy mode (simple/medium/complex/always)",
220
+ })),
221
+ dry_run: Type.Optional(Type.Boolean({
222
+ description: "Show plan without executing",
223
+ default: false,
224
+ })),
225
+ }),
226
+ async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
227
+ const task = params.task;
228
+ // Override mode if specified
229
+ if (params.mode) {
230
+ autonomyConfig.mode = params.mode;
231
+ }
232
+ const analysis = analyzeTask(task);
233
+ // Execute strategy (or dry run)
234
+ const result = params.dry_run
235
+ ? `**DRY RUN - Delegation Plan**
236
+
237
+ Task: "${task}"
238
+
239
+ Analysis:
240
+ - Complexity: ${analysis.complexity}
241
+ - Strategy: ${analysis.suggestedStrategy}
242
+ - Estimated files: ${analysis.estimatedFiles}
243
+ - Autonomy mode: ${autonomyConfig.mode}
244
+
245
+ Would execute: ${analysis.complexity === "simple"
246
+ ? "Direct execution (no subagents)"
247
+ : analysis.complexity === "medium"
248
+ ? "Scout → Worker"
249
+ : "Full workflow"}`
250
+ : await executeStrategy(task, analysis, ctx);
251
+ return {
252
+ content: [{ type: "text", text: result }],
253
+ details: { analysis, executed: !params.dry_run, dry_run: !!params.dry_run },
254
+ };
255
+ },
256
+ });
257
+ // COMMAND: /autonomous-toggle
258
+ pi.registerCommand("autonomous-toggle", {
259
+ description: "Toggle autonomous subagent mode",
260
+ handler: async (args, ctx) => {
261
+ const mode = args.trim();
262
+ if (mode) {
263
+ if (["off", "simple", "medium", "complex", "always"].includes(mode)) {
264
+ autonomyConfig.mode = mode;
265
+ ctx.ui.notify(`✅ Autonomous mode set to: ${mode}`, "info");
266
+ }
267
+ else {
268
+ ctx.ui.notify("❌ Invalid mode. Use: off, simple, medium, complex, always", "error");
269
+ }
270
+ }
271
+ else {
272
+ // Toggle
273
+ autonomyConfig.mode =
274
+ autonomyConfig.mode === "off" ? "medium" : "off";
275
+ ctx.ui.notify(`🔄 Autonomous mode: ${autonomyConfig.mode === "off" ? "OFF" : "ON"} (${autonomyConfig.mode})`, "info");
276
+ }
277
+ },
278
+ });
279
+ // COMMAND: /autonomous-status
280
+ pi.registerCommand("autonomous-status", {
281
+ description: "Show autonomous subagent status",
282
+ handler: async (_args, ctx) => {
283
+ ctx.ui.notify(`🤖 Autonomous Mode: ${autonomyConfig.mode}\nMax agents: ${autonomyConfig.maxParallelAgents}`, "info");
284
+ },
285
+ });
286
+ // COMMAND: /delegation-plan
287
+ pi.registerCommand("delegation-plan", {
288
+ description: "Show delegation plan for a task: /delegation-plan <task>",
289
+ handler: async (args, ctx) => {
290
+ if (!args.trim()) {
291
+ ctx.ui.notify("❌ Usage: /delegation-plan <task description>", "error");
292
+ return;
293
+ }
294
+ const analysis = analyzeTask(args);
295
+ ctx.ui.notify(`**Delegation Plan:**
296
+ Task: ${args}
297
+ Complexity: ${analysis.complexity}
298
+ Strategy: ${analysis.suggestedStrategy}
299
+ Confidence: ${Math.round(analysis.confidence * 100)}%`, "info");
300
+ },
301
+ });
302
+ // COMMAND: /implement (enhanced with auto-detection)
303
+ pi.registerCommand("implement", {
304
+ description: "Implement with auto-delegation. Says what it will do first.",
305
+ handler: async (args, ctx) => {
306
+ if (!args.trim()) {
307
+ ctx.ui.notify("❌ Usage: /implement <feature description>", "error");
308
+ return;
309
+ }
310
+ const analysis = analyzeTask(args);
311
+ // Show analysis
312
+ ctx.ui.notify(`🤖 Analyzing: "${args}"
313
+ Complexity: ${analysis.complexity}
314
+ Strategy: ${analysis.suggestedStrategy}
315
+ Confidence: ${Math.round(analysis.confidence * 100)}%`, "info");
316
+ // If simple, just do it
317
+ if (analysis.complexity === "simple" &&
318
+ autonomyConfig.mode !== "always") {
319
+ ctx.ui.notify("Task is simple. Handle directly without subagents.", "info");
320
+ return;
321
+ }
322
+ // Otherwise, execute strategy
323
+ const result = await executeStrategy(args, analysis, ctx);
324
+ ctx.ui.notify(result, "info");
325
+ },
326
+ });
327
+ // Notify mode on startup
328
+ console.log(`[AutonomousSubagent] Mode: ${autonomyConfig.mode}, Max agents: ${autonomyConfig.maxParallelAgents}`);
329
+ console.log(`[AutonomousSubagent] Agent will automatically use subagents for ${autonomyConfig.mode === "off"
330
+ ? "no"
331
+ : autonomyConfig.mode} tasks`);
332
+ }
333
+ //# sourceMappingURL=autonomous-subagent-extension.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autonomous-subagent-extension.js","sourceRoot":"","sources":["../../../../src/extensions/core/autonomous-subagent-extension.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,323 @@
1
+ /**
2
+ * Agent Lifecycle Extension - v0.2.0
3
+ *
4
+ * Manages main agent process lifecycle:
5
+ * - Start/stop/restart agents
6
+ * - Process management and monitoring
7
+ * - State persistence
8
+ *
9
+ * Each main agent runs as a separate pi-coding-agent process
10
+ * with its own workspace and configuration.
11
+ *
12
+ * @version 0.2.0
13
+ */
14
+ import { Type } from "@sinclair/typebox";
15
+ import { spawn } from "node:child_process";
16
+ import * as fs from "node:fs/promises";
17
+ import * as path from "node:path";
18
+ import { homedir } from "node:os";
19
+ const runningAgents = new Map();
20
+ const AGENTS_DIR = path.join(homedir(), ".0xkobold", "agents");
21
+ const STATE_FILE = path.join(homedir(), ".0xkobold", "agent-state.json");
22
+ // Load persisted state
23
+ async function loadState() {
24
+ try {
25
+ const content = await fs.readFile(STATE_FILE, "utf-8");
26
+ return JSON.parse(content);
27
+ }
28
+ catch {
29
+ return {};
30
+ }
31
+ }
32
+ // Save state
33
+ async function saveState() {
34
+ const state = {};
35
+ for (const [name, agent] of runningAgents) {
36
+ state[name] = {
37
+ pid: agent.pid,
38
+ startedAt: agent.startedAt.toISOString(),
39
+ status: agent.status,
40
+ };
41
+ }
42
+ await fs.writeFile(STATE_FILE, JSON.stringify(state, null, 2));
43
+ }
44
+ // Start a main agent
45
+ async function startAgent(name, ctx) {
46
+ if (runningAgents.has(name)) {
47
+ return { success: false, error: "Agent already running" };
48
+ }
49
+ const agentDir = path.join(AGENTS_DIR, name);
50
+ const workspaceDir = path.join(agentDir, "workspace");
51
+ const logsDir = path.join(agentDir, "logs");
52
+ // Ensure logs directory exists
53
+ await fs.mkdir(logsDir, { recursive: true });
54
+ // Generate unique port for this agent's gateway
55
+ const port = 18790 + runningAgents.size + 1;
56
+ // Build environment
57
+ const env = {
58
+ ...process.env,
59
+ KOBOLD_AGENT_NAME: name,
60
+ KOBOLD_AGENT_MODE: "main",
61
+ KOBOLD_WORKSPACE: workspaceDir,
62
+ PI_CODING_AGENT_DIR: agentDir,
63
+ // Gateway config
64
+ GATEWAY_PORT: port.toString(),
65
+ GATEWAY_HOST: "127.0.0.1",
66
+ };
67
+ // Spawn the agent process
68
+ const logFile = path.join(logsDir, "agent.log");
69
+ return new Promise((resolve) => {
70
+ const child = spawn("bun", ["run", "src/cli/index.ts", "--local"], {
71
+ cwd: process.cwd(),
72
+ env,
73
+ stdio: ["ignore", "pipe", "pipe"],
74
+ detached: true, // Allows process to run independently
75
+ });
76
+ if (!child.pid) {
77
+ resolve({ success: false, error: "Failed to spawn process" });
78
+ return;
79
+ }
80
+ const agentProcess = {
81
+ name,
82
+ process: child,
83
+ pid: child.pid,
84
+ startedAt: new Date(),
85
+ status: "starting",
86
+ port,
87
+ };
88
+ runningAgents.set(name, agentProcess);
89
+ // Handle stdout
90
+ let buffer = "";
91
+ child.stdout?.on("data", (data) => {
92
+ const text = data.toString();
93
+ buffer += text;
94
+ // Check for ready signal
95
+ if (text.includes("🐉 0xKobold starting") || text.includes("Extension loaded")) {
96
+ agentProcess.status = "running";
97
+ saveState();
98
+ }
99
+ // Log to file
100
+ fs.appendFile(logFile, `[${new Date().toISOString()}] ${text}`).catch(() => { });
101
+ });
102
+ // Handle stderr
103
+ child.stderr?.on("data", (data) => {
104
+ const text = data.toString();
105
+ fs.appendFile(logFile, `[${new Date().toISOString()}] ERROR: ${text}`).catch(() => { });
106
+ });
107
+ // Handle process exit
108
+ child.on("exit", (code) => {
109
+ runningAgents.delete(name);
110
+ saveState();
111
+ if (code !== 0 && code !== null) {
112
+ console.log(`[AgentLifecycle] Agent ${name} exited with code ${code}`);
113
+ }
114
+ });
115
+ // Wait for startup or timeout
116
+ const checkInterval = setInterval(() => {
117
+ if (agentProcess.status === "running") {
118
+ clearInterval(checkInterval);
119
+ clearTimeout(timeout);
120
+ resolve({ success: true, pid: child.pid });
121
+ }
122
+ }, 100);
123
+ const timeout = setTimeout(() => {
124
+ clearInterval(checkInterval);
125
+ if (agentProcess.status === "starting") {
126
+ agentProcess.status = "error";
127
+ agentProcess.lastError = "Startup timeout";
128
+ resolve({ success: false, error: "Agent startup timeout (30s)" });
129
+ }
130
+ }, 30000);
131
+ });
132
+ }
133
+ // Stop a main agent
134
+ async function stopAgent(name) {
135
+ const agent = runningAgents.get(name);
136
+ if (!agent) {
137
+ return { success: false, error: "Agent not running" };
138
+ }
139
+ // Graceful shutdown
140
+ agent.process.kill("SIGTERM");
141
+ // Wait for exit or force kill
142
+ return new Promise((resolve) => {
143
+ const timeout = setTimeout(() => {
144
+ // Force kill if still running
145
+ agent.process.kill("SIGKILL");
146
+ runningAgents.delete(name);
147
+ saveState();
148
+ resolve({ success: true });
149
+ }, 5000);
150
+ agent.process.on("exit", () => {
151
+ clearTimeout(timeout);
152
+ runningAgents.delete(name);
153
+ saveState();
154
+ resolve({ success: true });
155
+ });
156
+ });
157
+ }
158
+ export default async function agentLifecycleExtension(pi) {
159
+ console.log("[AgentLifecycle] Extension loaded");
160
+ // Load persisted state
161
+ const state = await loadState();
162
+ console.log(`[AgentLifecycle] Loaded state for ${Object.keys(state).length} agents`);
163
+ // TOOL: agent_start
164
+ pi.registerTool({
165
+ name: "agent_start",
166
+ label: "Start Main Agent",
167
+ description: "Start a main agent as a background process",
168
+ parameters: Type.Object({
169
+ name: Type.String({ description: "Agent name" }),
170
+ }),
171
+ async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
172
+ const name = params.name;
173
+ ctx.ui.notify(`🚀 Starting agent: ${name}...`, "info");
174
+ const result = await startAgent(name, ctx);
175
+ if (result.success) {
176
+ ctx.ui.notify(`✅ Agent ${name} started (PID: ${result.pid})`, "info");
177
+ return {
178
+ content: [{
179
+ type: "text",
180
+ text: `✅ Agent '${name}' started\nPID: ${result.pid}\nPort: ${runningAgents.get(name)?.port}`,
181
+ }],
182
+ details: { name, pid: result.pid, status: "running" },
183
+ };
184
+ }
185
+ else {
186
+ ctx.ui.notify(`❌ Failed to start ${name}: ${result.error}`, "error");
187
+ return {
188
+ content: [{ type: "text", text: `❌ Failed: ${result.error}` }],
189
+ details: { error: result.error },
190
+ };
191
+ }
192
+ },
193
+ });
194
+ // TOOL: agent_stop
195
+ pi.registerTool({
196
+ name: "agent_stop",
197
+ label: "Stop Main Agent",
198
+ description: "Stop a running main agent",
199
+ parameters: Type.Object({
200
+ name: Type.String({ description: "Agent name" }),
201
+ }),
202
+ async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
203
+ const name = params.name;
204
+ ctx.ui.notify(`🛑 Stopping agent: ${name}...`, "info");
205
+ const result = await stopAgent(name);
206
+ if (result.success) {
207
+ ctx.ui.notify(`✅ Agent ${name} stopped`, "info");
208
+ return {
209
+ content: [{ type: "text", text: `✅ Agent '${name}' stopped` }],
210
+ details: { name, status: "stopped" },
211
+ };
212
+ }
213
+ else {
214
+ return {
215
+ content: [{ type: "text", text: `❌ Failed: ${result.error}` }],
216
+ details: { error: result.error },
217
+ };
218
+ }
219
+ },
220
+ });
221
+ // TOOL: agent_status
222
+ pi.registerTool({
223
+ name: "agent_status",
224
+ label: "Get Agent Status",
225
+ description: "Get status of a main agent",
226
+ parameters: Type.Object({
227
+ name: Type.Optional(Type.String({ description: "Agent name (omit for all)" })),
228
+ }),
229
+ async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
230
+ if (params.name) {
231
+ const agent = runningAgents.get(params.name);
232
+ if (!agent) {
233
+ return {
234
+ content: [{ type: "text", text: `Agent '${params.name}' is not running` }],
235
+ details: { name: params.name, status: "stopped", agents: undefined },
236
+ };
237
+ }
238
+ return {
239
+ content: [{
240
+ type: "text",
241
+ text: `Agent: ${agent.name}\nStatus: ${agent.status}\nPID: ${agent.pid}\nStarted: ${agent.startedAt.toISOString()}`,
242
+ }],
243
+ details: {
244
+ name: agent.name,
245
+ status: agent.status,
246
+ pid: agent.pid,
247
+ startedAt: agent.startedAt.toISOString(),
248
+ agents: undefined
249
+ },
250
+ };
251
+ }
252
+ // All agents
253
+ const list = Array.from(runningAgents.entries()).map(([name, info]) => ({
254
+ name,
255
+ status: info.status,
256
+ pid: info.pid,
257
+ uptime: Date.now() - info.startedAt.getTime(),
258
+ }));
259
+ return {
260
+ content: [{
261
+ type: "text",
262
+ text: `${list.length} agents running:\n\n${list.map(a => `- ${a.name}: ${a.status} (PID: ${a.pid})`).join('\n')}`,
263
+ }],
264
+ details: { name: undefined, status: undefined, agents: list },
265
+ };
266
+ },
267
+ });
268
+ // COMMAND: /agent-start
269
+ pi.registerCommand("agent-start", {
270
+ description: "Start a main agent: /agent-start <name>",
271
+ handler: async (args, ctx) => {
272
+ const name = args.trim();
273
+ if (!name) {
274
+ ctx.ui.notify("❌ Usage: /agent-start <name>", "error");
275
+ return;
276
+ }
277
+ await startAgent(name, ctx);
278
+ },
279
+ });
280
+ // COMMAND: /agent-stop
281
+ pi.registerCommand("agent-stop", {
282
+ description: "Stop a main agent: /agent-stop <name>",
283
+ handler: async (args, ctx) => {
284
+ const name = args.trim();
285
+ if (!name) {
286
+ ctx.ui.notify("❌ Usage: /agent-stop <name>", "error");
287
+ return;
288
+ }
289
+ await stopAgent(name);
290
+ },
291
+ });
292
+ // COMMAND: /agent-status
293
+ pi.registerCommand("agent-status", {
294
+ description: "Check agent status: /agent-status [name]",
295
+ handler: async (args, ctx) => {
296
+ const name = args.trim();
297
+ if (name) {
298
+ const agent = runningAgents.get(name);
299
+ if (agent) {
300
+ const uptime = Math.floor((Date.now() - agent.startedAt.getTime()) / 1000);
301
+ ctx.ui.notify(`${name}: ${agent.status} (PID: ${agent.pid}, uptime: ${uptime}s)`, agent.status === "running" ? "info" : "warning");
302
+ }
303
+ else {
304
+ ctx.ui.notify(`${name}: not running`, "info");
305
+ }
306
+ }
307
+ else {
308
+ const count = runningAgents.size;
309
+ ctx.ui.notify(`${count} agents running`, "info");
310
+ }
311
+ },
312
+ });
313
+ // Cleanup on shutdown
314
+ process.on("SIGTERM", async () => {
315
+ console.log("[AgentLifecycle] Shutting down agents...");
316
+ for (const [name, agent] of runningAgents) {
317
+ agent.process.kill("SIGTERM");
318
+ }
319
+ await saveState();
320
+ });
321
+ console.log("[AgentLifecycle] Ready");
322
+ }
323
+ //# sourceMappingURL=agent-lifecycle-extension.js.map