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.
- package/HEARTBEAT.md +66 -32
- package/README.md +220 -1
- package/dist/package.json +3 -2
- package/dist/src/agent/bootstrap-loader.js +138 -0
- package/dist/src/agent/bootstrap-loader.js.map +1 -0
- package/dist/src/agent/context-pruning.js +279 -0
- package/dist/src/agent/context-pruning.js.map +1 -0
- package/dist/src/agent/dynamic-personality.js +211 -0
- package/dist/src/agent/dynamic-personality.js.map +1 -0
- package/dist/src/agent/embedded-runner.js +79 -0
- package/dist/src/agent/embedded-runner.js.map +1 -0
- package/dist/src/agent/index.js +16 -0
- package/dist/src/agent/index.js.map +1 -0
- package/dist/src/agent/system-prompt.js +84 -0
- package/dist/src/agent/system-prompt.js.map +1 -0
- package/dist/src/agent/task-router.js +194 -0
- package/dist/src/agent/task-router.js.map +1 -0
- package/dist/src/agent/tools/index.js +2 -0
- package/dist/src/agent/tools/index.js.map +1 -0
- package/dist/src/agent/tools/spawn-agent.js +200 -0
- package/dist/src/agent/tools/spawn-agent.js.map +1 -0
- package/dist/src/agent/types/definitions.js +317 -0
- package/dist/src/agent/types/definitions.js.map +1 -0
- package/dist/src/agent/types/index.js +2 -0
- package/dist/src/agent/types/index.js.map +1 -0
- package/dist/src/agent/user-profile.js +300 -0
- package/dist/src/agent/user-profile.js.map +1 -0
- package/dist/src/agents/task-router.js +194 -0
- package/dist/src/agents/task-router.js.map +1 -0
- package/dist/src/agents/tools/index.js +2 -0
- package/dist/src/agents/tools/index.js.map +1 -0
- package/dist/src/agents/tools/spawn-agent.js +200 -0
- package/dist/src/agents/tools/spawn-agent.js.map +1 -0
- package/dist/src/agents/types/definitions.js +317 -0
- package/dist/src/agents/types/definitions.js.map +1 -0
- package/dist/src/agents/types/index.js +2 -0
- package/dist/src/agents/types/index.js.map +1 -0
- package/dist/src/cli/commands/embedded.js +36 -0
- package/dist/src/cli/commands/embedded.js.map +1 -0
- package/dist/src/cli/commands/gateway.js +127 -166
- package/dist/src/cli/commands/gateway.js.map +1 -1
- package/dist/src/cli/program-fixed.js +1 -0
- package/dist/src/cli/program-fixed.js.map +1 -0
- package/dist/src/cli/program.js +10 -29
- package/dist/src/cli/program.js.map +1 -1
- package/dist/src/extensions/core/agent-lifecycle-extension.js +323 -0
- package/dist/src/extensions/core/agent-lifecycle-extension.js.map +1 -0
- package/dist/src/extensions/core/agent-orchestrator-extension.js +642 -0
- package/dist/src/extensions/core/agent-orchestrator-extension.js.map +1 -0
- package/dist/src/extensions/core/agent-workspace-extension.js +174 -0
- package/dist/src/extensions/core/agent-workspace-extension.js.map +1 -0
- package/dist/src/extensions/core/autonomous-executor-extension.js +145 -0
- package/dist/src/extensions/core/autonomous-executor-extension.js.map +1 -0
- package/dist/src/extensions/core/autonomous-subagent-extension.js +333 -0
- package/dist/src/extensions/core/autonomous-subagent-extension.js.map +1 -0
- package/dist/src/extensions/core/deprecated/agent-lifecycle-extension.js +323 -0
- package/dist/src/extensions/core/deprecated/agent-lifecycle-extension.js.map +1 -0
- package/dist/src/extensions/core/deprecated/autonomous-subagent-extension.js +333 -0
- package/dist/src/extensions/core/deprecated/autonomous-subagent-extension.js.map +1 -0
- package/dist/src/extensions/core/deprecated/subagent-extension.js +647 -0
- package/dist/src/extensions/core/deprecated/subagent-extension.js.map +1 -0
- package/dist/src/extensions/core/mode-manager-extension.js +11 -0
- package/dist/src/extensions/core/mode-manager-extension.js.map +1 -1
- package/dist/src/extensions/core/perennial-memory-extension.js +10 -2
- package/dist/src/extensions/core/perennial-memory-extension.js.map +1 -1
- package/dist/src/extensions/core/persona-loader-extension.js +61 -129
- package/dist/src/extensions/core/persona-loader-extension.js.map +1 -1
- package/dist/src/extensions/core/websearch-enhanced-extension.js +705 -0
- package/dist/src/extensions/core/websearch-enhanced-extension.js.map +1 -0
- package/dist/src/extensions/core/websearch-v2-extension.js +303 -0
- package/dist/src/extensions/core/websearch-v2-extension.js.map +1 -0
- package/dist/src/gateway/discord-bot.js +185 -0
- package/dist/src/gateway/discord-bot.js.map +1 -0
- package/dist/src/gateway/index.js +10 -350
- package/dist/src/gateway/index.js.map +1 -1
- package/dist/src/gateway/server.js +325 -0
- package/dist/src/gateway/server.js.map +1 -0
- package/dist/src/gateway/websocket-server.js +142 -0
- package/dist/src/gateway/websocket-server.js.map +1 -0
- package/dist/src/heartbeat/checkin.js +185 -0
- package/dist/src/heartbeat/checkin.js.map +1 -0
- package/dist/src/heartbeat/index.js +5 -0
- package/dist/src/heartbeat/index.js.map +1 -0
- package/dist/src/heartbeat/notifications.js +216 -0
- package/dist/src/heartbeat/notifications.js.map +1 -0
- package/dist/src/heartbeat/scheduler.js +284 -0
- package/dist/src/heartbeat/scheduler.js.map +1 -0
- package/dist/src/index.js +21 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/mode/auto-detector.js +211 -0
- package/dist/src/mode/auto-detector.js.map +1 -0
- package/dist/src/mode/index.js +3 -0
- package/dist/src/mode/index.js.map +1 -0
- package/dist/src/mode/natural-switcher.js +123 -0
- package/dist/src/mode/natural-switcher.js.map +1 -0
- package/dist/src/skills/builtin/api-worker.js +88 -0
- package/dist/src/skills/builtin/api-worker.js.map +1 -0
- package/dist/src/skills/builtin/nextjs-worker.js +55 -0
- package/dist/src/skills/builtin/nextjs-worker.js.map +1 -0
- package/dist/src/skills/builtin/real-workers.js +166 -0
- package/dist/src/skills/builtin/real-workers.js.map +1 -0
- package/dist/src/skills/builtin/sql-worker.js +61 -0
- package/dist/src/skills/builtin/sql-worker.js.map +1 -0
- package/dist/src/skills/builtin/test-worker.js +79 -0
- package/dist/src/skills/builtin/test-worker.js.map +1 -0
- package/dist/src/skills/builtin/web-research.js +77 -0
- package/dist/src/skills/builtin/web-research.js.map +1 -0
- package/dist/src/skills/framework.js +250 -0
- package/dist/src/skills/framework.js.map +1 -0
- package/dist/src/skills/index.js +10 -10
- package/dist/src/skills/index.js.map +1 -1
- package/dist/src/streaming/block-streamer.js +172 -0
- package/dist/src/streaming/block-streamer.js.map +1 -0
- package/dist/src/streaming/index.js +2 -0
- package/dist/src/streaming/index.js.map +1 -0
- package/dist/src/workspace/index.js +2 -0
- package/dist/src/workspace/index.js.map +1 -0
- package/dist/src/workspace/manager.js +181 -0
- package/dist/src/workspace/manager.js.map +1 -0
- 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
|