@phi-code-admin/phi-code 0.61.1 ā 0.61.3
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/init.ts +38 -75
- package/extensions/phi/orchestrator.ts +82 -174
- package/package.json +1 -1
package/extensions/phi/init.ts
CHANGED
|
@@ -636,70 +636,33 @@ _Edit this file to customize Phi Code's behavior for your project._
|
|
|
636
636
|
async function manualMode(availableModels: string[], ctx: any): Promise<Record<string, { preferred: string; fallback: string }>> {
|
|
637
637
|
ctx.ui.notify("šļø Manual mode: assign a model to each task category.\n", "info");
|
|
638
638
|
|
|
639
|
-
const
|
|
640
|
-
ctx.ui.notify(`Available models:\n${modelList}\n`, "info");
|
|
639
|
+
const modelOptions = ["default (use current model)", ...availableModels];
|
|
641
640
|
const assignments: Record<string, { preferred: string; fallback: string }> = {};
|
|
642
641
|
|
|
643
642
|
for (const role of TASK_ROLES) {
|
|
644
|
-
|
|
645
|
-
const
|
|
646
|
-
`${role.label}`,
|
|
647
|
-
|
|
643
|
+
// Primary model selection
|
|
644
|
+
const chosen = await ctx.ui.select(
|
|
645
|
+
`${role.label} ā ${role.desc}`,
|
|
646
|
+
modelOptions,
|
|
648
647
|
);
|
|
648
|
+
const preferredModel = (chosen && chosen !== modelOptions[0]) ? chosen : "default";
|
|
649
649
|
|
|
650
|
-
|
|
651
|
-
const
|
|
652
|
-
|
|
653
|
-
if (trimmed) {
|
|
654
|
-
// Try as number
|
|
655
|
-
const num = parseInt(trimmed);
|
|
656
|
-
if (num >= 1 && num <= availableModels.length) {
|
|
657
|
-
chosen = availableModels[num - 1];
|
|
658
|
-
} else {
|
|
659
|
-
// Try as model name (partial match)
|
|
660
|
-
const match = availableModels.find(m => m.toLowerCase().includes(trimmed.toLowerCase()));
|
|
661
|
-
if (match) chosen = match;
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
// Fallback selection
|
|
666
|
-
const fallbackDefault = availableModels.find(m => m !== chosen) || chosen;
|
|
667
|
-
const fallbackInput = await ctx.ui.input(
|
|
650
|
+
// Fallback model selection
|
|
651
|
+
const fallbackOptions = modelOptions.filter(m => m !== chosen);
|
|
652
|
+
const fallbackChoice = await ctx.ui.select(
|
|
668
653
|
`Fallback for ${role.label}`,
|
|
669
|
-
|
|
654
|
+
fallbackOptions,
|
|
670
655
|
);
|
|
656
|
+
const fallback = (fallbackChoice && fallbackChoice !== modelOptions[0]) ? fallbackChoice : "default";
|
|
671
657
|
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
const num = parseInt((fallbackInput ?? "").trim());
|
|
675
|
-
if (num >= 1 && num <= availableModels.length) {
|
|
676
|
-
fallback = availableModels[num - 1];
|
|
677
|
-
} else {
|
|
678
|
-
const match = availableModels.find(m => m.toLowerCase().includes((fallbackInput ?? "").trim().toLowerCase()));
|
|
679
|
-
if (match) fallback = match;
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
assignments[role.key] = { preferred: chosen, fallback };
|
|
684
|
-
ctx.ui.notify(` ā
${role.label}: ${chosen} (fallback: ${fallback})`, "info");
|
|
658
|
+
assignments[role.key] = { preferred: preferredModel, fallback };
|
|
659
|
+
ctx.ui.notify(` ā
${role.label}: ${preferredModel} (fallback: ${fallback})`, "info");
|
|
685
660
|
}
|
|
686
661
|
|
|
687
662
|
// Default model
|
|
688
|
-
const
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
);
|
|
692
|
-
let defaultModel = availableModels[0];
|
|
693
|
-
if ((defaultInput ?? "").trim()) {
|
|
694
|
-
const num = parseInt((defaultInput ?? "").trim());
|
|
695
|
-
if (num >= 1 && num <= availableModels.length) {
|
|
696
|
-
defaultModel = availableModels[num - 1];
|
|
697
|
-
} else {
|
|
698
|
-
const match = availableModels.find(m => m.toLowerCase().includes((defaultInput ?? "").trim().toLowerCase()));
|
|
699
|
-
if (match) defaultModel = match;
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
assignments["default"] = { preferred: defaultModel, fallback: availableModels[0] };
|
|
663
|
+
const defaultChoice = await ctx.ui.select("Default model (for general tasks)", modelOptions);
|
|
664
|
+
let defaultModel = (defaultChoice && defaultChoice !== modelOptions[0]) ? defaultChoice : "default";
|
|
665
|
+
assignments["default"] = { preferred: defaultModel, fallback: availableModels[0] || "default" };
|
|
703
666
|
|
|
704
667
|
return assignments;
|
|
705
668
|
}
|
|
@@ -766,15 +729,20 @@ _Edit this file to customize Phi Code's behavior for your project._
|
|
|
766
729
|
ctx.ui.notify("\nā ļø No cloud API keys configured.\n", "warning");
|
|
767
730
|
}
|
|
768
731
|
|
|
769
|
-
// Always offer to add a provider
|
|
770
|
-
const
|
|
771
|
-
"
|
|
772
|
-
providers.map(
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
732
|
+
// Always offer to add a provider via select menu
|
|
733
|
+
const providerOptions = [
|
|
734
|
+
"Skip (continue with current providers)",
|
|
735
|
+
...providers.map(p => {
|
|
736
|
+
const status = p.available ? "ā
" : "ā¬";
|
|
737
|
+
const tag = p.local ? " (local)" : "";
|
|
738
|
+
return `${status} ${p.name}${tag}`;
|
|
739
|
+
}),
|
|
740
|
+
];
|
|
741
|
+
const addProvider = await ctx.ui.select("Add or change a provider?", providerOptions);
|
|
742
|
+
|
|
743
|
+
const choiceIdx = providerOptions.indexOf(addProvider ?? "");
|
|
744
|
+
if (choiceIdx > 0) { // 0 = Skip
|
|
745
|
+
const chosen = providers[choiceIdx - 1];
|
|
778
746
|
|
|
779
747
|
if (chosen.local) {
|
|
780
748
|
const port = chosen.name === "Ollama" ? 11434 : 1234;
|
|
@@ -844,19 +812,14 @@ _Edit this file to customize Phi Code's behavior for your project._
|
|
|
844
812
|
ctx.ui.notify(`\nā
**${allModels.length} models** available from ${available.length} provider(s).\n`, "info");
|
|
845
813
|
|
|
846
814
|
// 2. Choose mode
|
|
847
|
-
|
|
848
|
-
"
|
|
849
|
-
"
|
|
850
|
-
"
|
|
851
|
-
|
|
852
|
-
const
|
|
853
|
-
|
|
854
|
-
"
|
|
855
|
-
);
|
|
856
|
-
|
|
857
|
-
const modeStr = (modeInput ?? "").trim().toLowerCase();
|
|
858
|
-
const mode = modeStr.startsWith("2") || modeStr.startsWith("b") ? "benchmark"
|
|
859
|
-
: modeStr.startsWith("3") || modeStr.startsWith("m") ? "manual"
|
|
815
|
+
const modeOptions = [
|
|
816
|
+
"auto ā Use optimal defaults (instant)",
|
|
817
|
+
"benchmark ā Test models first, assign by results (10-15 min)",
|
|
818
|
+
"manual ā Choose each model yourself",
|
|
819
|
+
];
|
|
820
|
+
const modeChoice = await ctx.ui.select("Setup mode", modeOptions);
|
|
821
|
+
const mode = (modeChoice ?? "").startsWith("benchmark") ? "benchmark"
|
|
822
|
+
: (modeChoice ?? "").startsWith("manual") ? "manual"
|
|
860
823
|
: "auto";
|
|
861
824
|
|
|
862
825
|
ctx.ui.notify(`\nš Mode: **${mode}**\n`, "info");
|
|
@@ -24,7 +24,7 @@ import type { ExtensionAPI } from "phi-code";
|
|
|
24
24
|
import { writeFile, mkdir, readdir, readFile } from "node:fs/promises";
|
|
25
25
|
import { join } from "node:path";
|
|
26
26
|
import { existsSync, readFileSync } from "node:fs";
|
|
27
|
-
|
|
27
|
+
// execFile removed ā tasks now execute in-session, no subprocess
|
|
28
28
|
import { homedir } from "node:os";
|
|
29
29
|
|
|
30
30
|
// āāā Types āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
@@ -165,107 +165,55 @@ export default function orchestratorExtension(pi: ExtensionAPI) {
|
|
|
165
165
|
return "phi";
|
|
166
166
|
}
|
|
167
167
|
|
|
168
|
-
// āāā
|
|
168
|
+
// āāā Task Execution (in-session, no subprocess) āāāāāāāāāāāāāāāāā
|
|
169
169
|
|
|
170
|
-
|
|
170
|
+
/**
|
|
171
|
+
* Execute a task by sending it as a user message to the current session.
|
|
172
|
+
* The LLM handles it directly ā no subprocess spawning, no cold boot.
|
|
173
|
+
* Much faster and more reliable than spawning phi --print processes.
|
|
174
|
+
*/
|
|
175
|
+
function executeTaskInSession(
|
|
171
176
|
task: TaskDef,
|
|
172
|
-
agentDefs: Map<string, AgentDef>,
|
|
173
|
-
cwd: string,
|
|
174
177
|
sharedContext: {
|
|
175
178
|
projectTitle: string;
|
|
176
179
|
projectDescription: string;
|
|
177
180
|
specSummary: string;
|
|
178
181
|
completedTasks: Array<{ index: number; title: string; agent: string; output: string }>;
|
|
179
182
|
},
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
return new Promise((resolve) => {
|
|
183
|
-
const agentType = task.agent || "code";
|
|
184
|
-
const agentDef = agentDefs.get(agentType);
|
|
185
|
-
const model = resolveAgentModel(agentType);
|
|
186
|
-
const phiBin = findPhiBinary();
|
|
187
|
-
const startTime = Date.now();
|
|
188
|
-
|
|
189
|
-
// Build prompt with shared context
|
|
190
|
-
let taskPrompt = "";
|
|
191
|
-
|
|
192
|
-
// Inject shared project context (lightweight, always included)
|
|
193
|
-
taskPrompt += `# Project Context\n\n`;
|
|
194
|
-
taskPrompt += `**Project:** ${sharedContext.projectTitle}\n`;
|
|
195
|
-
taskPrompt += `**Description:** ${sharedContext.projectDescription}\n\n`;
|
|
196
|
-
|
|
197
|
-
if (sharedContext.specSummary) {
|
|
198
|
-
taskPrompt += `## Specification Summary\n${sharedContext.specSummary}\n\n`;
|
|
199
|
-
}
|
|
183
|
+
): { taskPrompt: string } {
|
|
184
|
+
const agentType = task.agent || "code";
|
|
200
185
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
186
|
+
// Build prompt with shared context
|
|
187
|
+
let taskPrompt = `## š§ Task: ${task.title} [${agentType}]\n\n`;
|
|
188
|
+
|
|
189
|
+
taskPrompt += `**Project:** ${sharedContext.projectTitle}\n\n`;
|
|
190
|
+
|
|
191
|
+
if (sharedContext.specSummary) {
|
|
192
|
+
taskPrompt += `**Spec:** ${sharedContext.specSummary}\n\n`;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Inject results from dependency tasks
|
|
196
|
+
const deps = task.dependencies || [];
|
|
197
|
+
if (deps.length > 0) {
|
|
198
|
+
const depResults = sharedContext.completedTasks.filter(ct => deps.includes(ct.index));
|
|
199
|
+
if (depResults.length > 0) {
|
|
200
|
+
taskPrompt += `**Previous results:**\n`;
|
|
201
|
+
for (const dep of depResults) {
|
|
202
|
+
const truncated = dep.output.length > 500 ? dep.output.slice(0, 500) + "..." : dep.output;
|
|
203
|
+
taskPrompt += `- Task ${dep.index} (${dep.title}): ${truncated}\n`;
|
|
211
204
|
}
|
|
205
|
+
taskPrompt += "\n";
|
|
212
206
|
}
|
|
207
|
+
}
|
|
213
208
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
taskPrompt += `- You are an isolated agent with your own context. Work independently.\n`;
|
|
221
|
-
taskPrompt += `- Use the project context and dependency results above to inform your work.\n`;
|
|
222
|
-
taskPrompt += `- Follow the output format defined in your system prompt.\n`;
|
|
223
|
-
taskPrompt += `- Be precise. Reference specific file paths and line numbers.\n`;
|
|
224
|
-
taskPrompt += `- Report exactly what you did, what worked, and what didn't.\n`;
|
|
225
|
-
|
|
226
|
-
const args: string[] = [];
|
|
227
|
-
|
|
228
|
-
args.push("--print");
|
|
229
|
-
if (model && model !== "default") args.push("--model", model);
|
|
230
|
-
if (agentDef?.systemPrompt) args.push("--system-prompt", agentDef.systemPrompt);
|
|
231
|
-
args.push("--no-session");
|
|
232
|
-
args.push(taskPrompt);
|
|
233
|
-
|
|
234
|
-
// Determine command: use node + cli.js for JS paths, or phi directly on Windows
|
|
235
|
-
let cmd: string;
|
|
236
|
-
let cmdArgs: string[];
|
|
237
|
-
if (phiBin.endsWith(".js")) {
|
|
238
|
-
cmd = "node";
|
|
239
|
-
cmdArgs = [phiBin, ...args];
|
|
240
|
-
} else if (phiBin === "phi") {
|
|
241
|
-
cmd = "phi";
|
|
242
|
-
cmdArgs = args;
|
|
243
|
-
} else {
|
|
244
|
-
cmd = phiBin;
|
|
245
|
-
cmdArgs = args;
|
|
246
|
-
}
|
|
209
|
+
// The actual task
|
|
210
|
+
taskPrompt += `### What to do\n\n${task.description}\n`;
|
|
211
|
+
if (task.subtasks && task.subtasks.length > 0) {
|
|
212
|
+
taskPrompt += "\n**Sub-tasks:**\n" + task.subtasks.map((st, i) => `${i + 1}. ${st}`).join("\n") + "\n";
|
|
213
|
+
}
|
|
214
|
+
taskPrompt += `\n**Instructions:** Execute this task completely. Create/edit all necessary files. Report what you did.\n`;
|
|
247
215
|
|
|
248
|
-
|
|
249
|
-
cwd,
|
|
250
|
-
timeout: timeoutMs,
|
|
251
|
-
maxBuffer: 10 * 1024 * 1024,
|
|
252
|
-
env: { ...process.env },
|
|
253
|
-
shell: process.platform === "win32", // Windows needs shell for .cmd shims
|
|
254
|
-
}, (error, stdout, stderr) => {
|
|
255
|
-
const durationMs = Date.now() - startTime;
|
|
256
|
-
if (error) {
|
|
257
|
-
resolve({
|
|
258
|
-
taskIndex: 0, title: task.title, agent: agentType,
|
|
259
|
-
status: "error", output: `Error: ${error.message}\n${stderr || ""}`.trim(), durationMs,
|
|
260
|
-
});
|
|
261
|
-
} else {
|
|
262
|
-
resolve({
|
|
263
|
-
taskIndex: 0, title: task.title, agent: agentType,
|
|
264
|
-
status: "success", output: stdout.trim(), durationMs,
|
|
265
|
-
});
|
|
266
|
-
}
|
|
267
|
-
});
|
|
268
|
-
});
|
|
216
|
+
return { taskPrompt };
|
|
269
217
|
}
|
|
270
218
|
|
|
271
219
|
// āāā Execute All Tasks (parallel with dependency resolution) āāāāā
|
|
@@ -276,12 +224,11 @@ export default function orchestratorExtension(pi: ExtensionAPI) {
|
|
|
276
224
|
notify: (msg: string, type: "info" | "error" | "warning") => void,
|
|
277
225
|
projectContext?: { title: string; description: string; specSummary: string },
|
|
278
226
|
): Promise<{ results: TaskResult[]; progressFile: string }> {
|
|
279
|
-
const agentDefs = loadAgentDefs();
|
|
280
227
|
const progressFile = todoFile.replace("todo-", "progress-");
|
|
281
228
|
const progressPath = join(plansDir, progressFile);
|
|
282
229
|
let progress = `# Progress: ${todoFile}\n\n`;
|
|
283
230
|
progress += `**Started:** ${new Date().toLocaleString()}\n`;
|
|
284
|
-
progress += `**Tasks:** ${tasks.length}\n**Mode:**
|
|
231
|
+
progress += `**Tasks:** ${tasks.length}\n**Mode:** in-session (single turn)\n\n`;
|
|
285
232
|
await writeFile(progressPath, progress, "utf-8");
|
|
286
233
|
|
|
287
234
|
// Shared context for sub-agents
|
|
@@ -328,96 +275,57 @@ export default function orchestratorExtension(pi: ExtensionAPI) {
|
|
|
328
275
|
}
|
|
329
276
|
|
|
330
277
|
const totalTasks = tasks.length;
|
|
331
|
-
let wave = 1;
|
|
332
278
|
|
|
333
|
-
|
|
334
|
-
notify(`š Executing ${totalTasks} tasks with sub-agents (parallel mode)...`, "info");
|
|
335
|
-
notify(`š Phi binary: \`${phiBinPath}\``, "info");
|
|
279
|
+
notify(`š Executing ${totalTasks} tasks in-session (no subprocess overhead)...`, "info");
|
|
336
280
|
|
|
337
|
-
//
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
const result = await executeTask(task, agentDefs, process.cwd(), sharedContext);
|
|
360
|
-
result.taskIndex = idx + 1;
|
|
361
|
-
return result;
|
|
281
|
+
// Build a single comprehensive prompt with ALL tasks
|
|
282
|
+
// The LLM executes them sequentially in the current session
|
|
283
|
+
let megaPrompt = `# š Project Plan: ${sharedContext.projectTitle}\n\n`;
|
|
284
|
+
megaPrompt += `${sharedContext.projectDescription}\n\n`;
|
|
285
|
+
if (sharedContext.specSummary) {
|
|
286
|
+
megaPrompt += `## Spec\n${sharedContext.specSummary}\n\n`;
|
|
287
|
+
}
|
|
288
|
+
megaPrompt += `## Tasks (execute ALL in order)\n\n`;
|
|
289
|
+
|
|
290
|
+
for (let i = 0; i < tasks.length; i++) {
|
|
291
|
+
const task = tasks[i];
|
|
292
|
+
const { taskPrompt } = executeTaskInSession(task, sharedContext);
|
|
293
|
+
megaPrompt += `---\n\n${taskPrompt}\n\n`;
|
|
294
|
+
|
|
295
|
+
// Mark all tasks as completed for the progress file
|
|
296
|
+
results.push({
|
|
297
|
+
taskIndex: i + 1,
|
|
298
|
+
title: task.title,
|
|
299
|
+
agent: task.agent || "code",
|
|
300
|
+
status: "success",
|
|
301
|
+
output: "(executed in-session)",
|
|
302
|
+
durationMs: 0,
|
|
362
303
|
});
|
|
363
|
-
|
|
364
|
-
const waveResults = await Promise.all(promises);
|
|
365
|
-
|
|
366
|
-
// Process results and feed into shared context for next wave
|
|
367
|
-
for (const result of waveResults) {
|
|
368
|
-
results.push(result);
|
|
369
|
-
|
|
370
|
-
if (result.status === "success") {
|
|
371
|
-
completed.add(result.taskIndex);
|
|
372
|
-
// Add to shared context so dependent tasks can see this result
|
|
373
|
-
sharedContext.completedTasks.push({
|
|
374
|
-
index: result.taskIndex,
|
|
375
|
-
title: result.title,
|
|
376
|
-
agent: result.agent,
|
|
377
|
-
output: result.output,
|
|
378
|
-
});
|
|
379
|
-
} else {
|
|
380
|
-
failed.add(result.taskIndex);
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
const icon = result.status === "success" ? "ā
" : "ā";
|
|
384
|
-
const duration = (result.durationMs / 1000).toFixed(1);
|
|
385
|
-
const outputPreview = result.output.length > 500 ? result.output.slice(0, 500) + "..." : result.output;
|
|
386
|
-
notify(`${icon} Task ${result.taskIndex}: **${result.title}** (${duration}s)\n${outputPreview}`,
|
|
387
|
-
result.status === "success" ? "info" : "error");
|
|
388
|
-
|
|
389
|
-
progress += `## Task ${result.taskIndex}: ${result.title}\n\n`;
|
|
390
|
-
progress += `- **Status:** ${result.status}\n`;
|
|
391
|
-
progress += `- **Agent:** ${result.agent}\n`;
|
|
392
|
-
progress += `- **Wave:** ${wave}\n`;
|
|
393
|
-
progress += `- **Duration:** ${duration}s\n`;
|
|
394
|
-
progress += `- **Output:**\n\n\`\`\`\n${result.output.slice(0, 3000)}\n\`\`\`\n\n`;
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
await writeFile(progressPath, progress, "utf-8");
|
|
398
|
-
wave++;
|
|
399
304
|
}
|
|
400
305
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
progress +=
|
|
410
|
-
progress +=
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
progress +=
|
|
415
|
-
progress += `- **
|
|
306
|
+
megaPrompt += `---\n\n## ā ļø Instructions\n\n`;
|
|
307
|
+
megaPrompt += `Execute ALL ${totalTasks} tasks above **sequentially**. For each task:\n`;
|
|
308
|
+
megaPrompt += `1. Create/edit the required files using your tools\n`;
|
|
309
|
+
megaPrompt += `2. Report what you did with a brief summary\n`;
|
|
310
|
+
megaPrompt += `3. Move to the next task\n\n`;
|
|
311
|
+
megaPrompt += `Do NOT skip any task. Complete the entire project in this single turn.\n`;
|
|
312
|
+
|
|
313
|
+
// Write progress
|
|
314
|
+
progress += `## Execution Mode: in-session\n\n`;
|
|
315
|
+
progress += `All ${totalTasks} tasks sent as a single prompt to the current session.\n\n`;
|
|
316
|
+
for (const r of results) {
|
|
317
|
+
progress += `- Task ${r.taskIndex}: ${r.title} [${r.agent}]\n`;
|
|
318
|
+
}
|
|
319
|
+
progress += `\n---\n\n## Summary\n\n`;
|
|
320
|
+
progress += `- **Mode:** in-session (single turn)\n`;
|
|
321
|
+
progress += `- **Tasks:** ${totalTasks}\n`;
|
|
322
|
+
progress += `- **Status:** sent to LLM\n`;
|
|
416
323
|
await writeFile(progressPath, progress, "utf-8");
|
|
417
324
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
325
|
+
// Send the mega-prompt as a user message ā LLM handles everything
|
|
326
|
+
pi.sendUserMessage(megaPrompt);
|
|
327
|
+
|
|
328
|
+
const statusParts = [`š ${totalTasks} tasks sent`];
|
|
421
329
|
|
|
422
330
|
notify(
|
|
423
331
|
`\nš **Execution complete!** (${wave - 1} waves)\n` +
|