@phi-code-admin/phi-code 0.58.6 → 0.58.8
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/extensions/phi/orchestrator.ts +73 -10
- package/package.json +1 -1
|
@@ -144,6 +144,12 @@ export default function orchestratorExtension(pi: ExtensionAPI) {
|
|
|
144
144
|
task: TaskDef,
|
|
145
145
|
agentDefs: Map<string, AgentDef>,
|
|
146
146
|
cwd: string,
|
|
147
|
+
sharedContext: {
|
|
148
|
+
projectTitle: string;
|
|
149
|
+
projectDescription: string;
|
|
150
|
+
specSummary: string;
|
|
151
|
+
completedTasks: Array<{ index: number; title: string; agent: string; output: string }>;
|
|
152
|
+
},
|
|
147
153
|
timeoutMs: number = 300000,
|
|
148
154
|
): Promise<TaskResult> {
|
|
149
155
|
return new Promise((resolve) => {
|
|
@@ -153,11 +159,42 @@ export default function orchestratorExtension(pi: ExtensionAPI) {
|
|
|
153
159
|
const phiBin = findPhiBinary();
|
|
154
160
|
const startTime = Date.now();
|
|
155
161
|
|
|
156
|
-
|
|
162
|
+
// Build prompt with shared context
|
|
163
|
+
let taskPrompt = "";
|
|
164
|
+
|
|
165
|
+
// Inject shared project context (lightweight, always included)
|
|
166
|
+
taskPrompt += `# Project Context\n\n`;
|
|
167
|
+
taskPrompt += `**Project:** ${sharedContext.projectTitle}\n`;
|
|
168
|
+
taskPrompt += `**Description:** ${sharedContext.projectDescription}\n\n`;
|
|
169
|
+
|
|
170
|
+
if (sharedContext.specSummary) {
|
|
171
|
+
taskPrompt += `## Specification Summary\n${sharedContext.specSummary}\n\n`;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Inject results from dependency tasks (only the ones this task depends on)
|
|
175
|
+
const deps = task.dependencies || [];
|
|
176
|
+
if (deps.length > 0) {
|
|
177
|
+
const depResults = sharedContext.completedTasks.filter(ct => deps.includes(ct.index));
|
|
178
|
+
if (depResults.length > 0) {
|
|
179
|
+
taskPrompt += `## Previous Task Results (your dependencies)\n\n`;
|
|
180
|
+
for (const dep of depResults) {
|
|
181
|
+
const truncatedOutput = dep.output.length > 1500 ? dep.output.slice(0, 1500) + "\n...(truncated)" : dep.output;
|
|
182
|
+
taskPrompt += `### Task ${dep.index}: ${dep.title} [${dep.agent}]\n\`\`\`\n${truncatedOutput}\n\`\`\`\n\n`;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// The actual task
|
|
188
|
+
taskPrompt += `---\n\n# Your Task\n\n**${task.title}**\n\n${task.description}`;
|
|
157
189
|
if (task.subtasks && task.subtasks.length > 0) {
|
|
158
|
-
taskPrompt += "\n\
|
|
190
|
+
taskPrompt += "\n\n## Sub-tasks\n" + task.subtasks.map((st, i) => `${i + 1}. ${st}`).join("\n");
|
|
159
191
|
}
|
|
160
|
-
taskPrompt +=
|
|
192
|
+
taskPrompt += `\n\n---\n\n## Instructions\n`;
|
|
193
|
+
taskPrompt += `- You are an isolated agent with your own context. Work independently.\n`;
|
|
194
|
+
taskPrompt += `- Use the project context and dependency results above to inform your work.\n`;
|
|
195
|
+
taskPrompt += `- Follow the output format defined in your system prompt.\n`;
|
|
196
|
+
taskPrompt += `- Be precise. Reference specific file paths and line numbers.\n`;
|
|
197
|
+
taskPrompt += `- Report exactly what you did, what worked, and what didn't.\n`;
|
|
161
198
|
|
|
162
199
|
const args: string[] = [];
|
|
163
200
|
if (phiBin === "npx") args.push("@phi-code-admin/phi-code");
|
|
@@ -199,17 +236,25 @@ export default function orchestratorExtension(pi: ExtensionAPI) {
|
|
|
199
236
|
tasks: TaskDef[],
|
|
200
237
|
todoFile: string,
|
|
201
238
|
notify: (msg: string, type: "info" | "error" | "warning") => void,
|
|
239
|
+
projectContext?: { title: string; description: string; specSummary: string },
|
|
202
240
|
): Promise<{ results: TaskResult[]; progressFile: string }> {
|
|
203
241
|
const agentDefs = loadAgentDefs();
|
|
204
242
|
const progressFile = todoFile.replace("todo-", "progress-");
|
|
205
243
|
const progressPath = join(plansDir, progressFile);
|
|
206
244
|
let progress = `# Progress: ${todoFile}\n\n`;
|
|
207
245
|
progress += `**Started:** ${new Date().toLocaleString()}\n`;
|
|
208
|
-
progress += `**Tasks:** ${tasks.length}\n**Mode:** parallel (dependency-aware)\n\n`;
|
|
246
|
+
progress += `**Tasks:** ${tasks.length}\n**Mode:** parallel (dependency-aware, shared context)\n\n`;
|
|
209
247
|
await writeFile(progressPath, progress, "utf-8");
|
|
210
248
|
|
|
249
|
+
// Shared context for sub-agents
|
|
250
|
+
const sharedContext = {
|
|
251
|
+
projectTitle: projectContext?.title || "Project",
|
|
252
|
+
projectDescription: projectContext?.description || "",
|
|
253
|
+
specSummary: projectContext?.specSummary || "",
|
|
254
|
+
completedTasks: [] as Array<{ index: number; title: string; agent: string; output: string }>,
|
|
255
|
+
};
|
|
256
|
+
|
|
211
257
|
// Build dependency graph
|
|
212
|
-
// Task indices are 1-based in the plan files
|
|
213
258
|
const completed = new Set<number>();
|
|
214
259
|
const failed = new Set<number>();
|
|
215
260
|
const results: TaskResult[] = [];
|
|
@@ -268,22 +313,29 @@ export default function orchestratorExtension(pi: ExtensionAPI) {
|
|
|
268
313
|
notify(`⏳ Task ${idx + 1}: **${t.title}** [${t.agent || "code"}]`, "info");
|
|
269
314
|
}
|
|
270
315
|
|
|
271
|
-
// Launch all ready tasks simultaneously
|
|
316
|
+
// Launch all ready tasks simultaneously (each gets shared context)
|
|
272
317
|
const promises = readyIndices.map(async (idx) => {
|
|
273
318
|
const task = tasks[idx];
|
|
274
|
-
const result = await executeTask(task, agentDefs, process.cwd());
|
|
319
|
+
const result = await executeTask(task, agentDefs, process.cwd(), sharedContext);
|
|
275
320
|
result.taskIndex = idx + 1;
|
|
276
321
|
return result;
|
|
277
322
|
});
|
|
278
323
|
|
|
279
324
|
const waveResults = await Promise.all(promises);
|
|
280
325
|
|
|
281
|
-
// Process results
|
|
326
|
+
// Process results and feed into shared context for next wave
|
|
282
327
|
for (const result of waveResults) {
|
|
283
328
|
results.push(result);
|
|
284
329
|
|
|
285
330
|
if (result.status === "success") {
|
|
286
331
|
completed.add(result.taskIndex);
|
|
332
|
+
// Add to shared context so dependent tasks can see this result
|
|
333
|
+
sharedContext.completedTasks.push({
|
|
334
|
+
index: result.taskIndex,
|
|
335
|
+
title: result.title,
|
|
336
|
+
agent: result.agent,
|
|
337
|
+
output: result.output,
|
|
338
|
+
});
|
|
287
339
|
} else {
|
|
288
340
|
failed.add(result.taskIndex);
|
|
289
341
|
}
|
|
@@ -402,7 +454,7 @@ export default function orchestratorExtension(pi: ExtensionAPI) {
|
|
|
402
454
|
promptSnippet: "Plan + execute projects in parallel waves. Each sub-agent gets isolated context + model. Use prompt-architect patterns for structured task descriptions.",
|
|
403
455
|
promptGuidelines: [
|
|
404
456
|
"When asked to plan or build a project: analyze the request thoroughly, then call the orchestrate tool. It plans AND executes automatically.",
|
|
405
|
-
"CRITICAL: Each task description must be SELF-CONTAINED. The sub-agent has NO
|
|
457
|
+
"CRITICAL: Each task description must be SELF-CONTAINED. The sub-agent has NO access to this conversation. It receives: (1) project context (title, description, spec summary) automatically, (2) outputs from its dependency tasks automatically, (3) your task description. So include specific details: file paths, expected behavior, code patterns, success criteria. Don't repeat the project description — that's injected automatically.",
|
|
406
458
|
"Structure each task description using the prompt-architect pattern: [CONTEXT] what exists and why → [TASK] what to do specifically → [FORMAT] expected output → [CONSTRAINTS] rules and limitations.",
|
|
407
459
|
"Assign agent types strategically: 'explore' (read-only analysis, codebase understanding), 'plan' (architecture, design decisions), 'code' (implementation, file creation/modification), 'test' (write + run tests, validate behavior), 'review' (security audit, quality check, read-only).",
|
|
408
460
|
"Set dependencies to maximize parallelism: tasks without dependencies run simultaneously in the same wave. Only add dependencies when a task truly needs another task's output.",
|
|
@@ -459,7 +511,18 @@ export default function orchestratorExtension(pi: ExtensionAPI) {
|
|
|
459
511
|
notify(`📋 Plan created: **${p.title}** (${p.tasks.length} tasks)\nNow executing with sub-agents...`, "info");
|
|
460
512
|
|
|
461
513
|
// Auto-execute all tasks
|
|
462
|
-
|
|
514
|
+
// Build spec summary for shared context
|
|
515
|
+
const specSummary = [
|
|
516
|
+
`Goals: ${p.goals.join("; ")}`,
|
|
517
|
+
`Requirements: ${p.requirements.join("; ")}`,
|
|
518
|
+
p.architecture?.length ? `Architecture: ${p.architecture.join("; ")}` : "",
|
|
519
|
+
p.constraints?.length ? `Constraints: ${p.constraints.join("; ")}` : "",
|
|
520
|
+
].filter(Boolean).join("\n");
|
|
521
|
+
|
|
522
|
+
const { results, progressFile } = await executePlan(
|
|
523
|
+
p.tasks, todoFile, notify,
|
|
524
|
+
{ title: p.title, description: p.description, specSummary },
|
|
525
|
+
);
|
|
463
526
|
|
|
464
527
|
const succeeded = results.filter(r => r.status === "success").length;
|
|
465
528
|
const failed = results.filter(r => r.status === "error").length;
|