pi-subagents 0.10.0 → 0.11.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/CHANGELOG.md +9 -0
- package/README.md +16 -3
- package/chain-clarify.ts +16 -4
- package/chain-execution.ts +30 -0
- package/index.ts +144 -12
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.11.0] - 2026-02-23
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- **Background mode toggle in clarify TUI**: Press `b` to toggle background/async execution for any mode (single, parallel, chain). Shows `[b]g:ON` in footer when enabled. Previously async execution required programmatic `clarify: false, async: true` — now users can interactively choose background mode after previewing/editing parameters.
|
|
9
|
+
- **`--bg` flag for slash commands**: `/run scout "task" --bg`, `/chain scout "task" -> planner --bg`, `/parallel scout "a" -> scout "b" --bg` now run in background without needing the TUI.
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
- Task edits in clarify TUI were lost when launching in background mode if no other behavior (model, output, reads) was modified. The async handoff now always applies the edited template.
|
|
13
|
+
|
|
5
14
|
## [0.10.0] - 2026-02-23
|
|
6
15
|
|
|
7
16
|
### Added
|
package/README.md
CHANGED
|
@@ -162,6 +162,18 @@ Append `[key=value,...]` to any agent name to override its defaults:
|
|
|
162
162
|
|
|
163
163
|
Set `output=false`, `reads=false`, or `skills=false` to explicitly disable.
|
|
164
164
|
|
|
165
|
+
### Background Execution
|
|
166
|
+
|
|
167
|
+
Add `--bg` at the end of any slash command to run in the background:
|
|
168
|
+
|
|
169
|
+
```
|
|
170
|
+
/run scout "full security audit of the codebase" --bg
|
|
171
|
+
/chain scout "analyze auth system" -> planner "design refactor plan" -> worker --bg
|
|
172
|
+
/parallel scout "scan frontend" -> scout "scan backend" -> scout "scan infra" --bg
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Background tasks run asynchronously and notify you when complete. Check status with `subagent_status`.
|
|
176
|
+
|
|
165
177
|
## Agents Manager
|
|
166
178
|
|
|
167
179
|
Press **Ctrl+Shift+A** or type `/agents` to open the Agents Manager overlay — a TUI for browsing, viewing, editing, creating, and launching agents and chains.
|
|
@@ -271,9 +283,9 @@ Chains can be created from the Agents Manager template picker ("Blank Chain"), o
|
|
|
271
283
|
|------|---------------|-------|
|
|
272
284
|
| Single | Yes | `{ agent, task }` - agents with `output` write to temp dir |
|
|
273
285
|
| Chain | Yes | `{ chain: [{agent, task}...] }` with `{task}`, `{previous}`, `{chain_dir}` variables |
|
|
274
|
-
| Parallel |
|
|
286
|
+
| Parallel | Yes | `{ tasks: [{agent, task}...] }` - via TUI toggle or converted to chain for async |
|
|
275
287
|
|
|
276
|
-
|
|
288
|
+
All modes support background/async execution. For programmatic async, use `clarify: false, async: true`. For interactive async, use `clarify: true` and press `b` in the TUI to toggle background mode before running. Chains with parallel steps (`{ parallel: [...] }`) run concurrently with configurable `concurrency` and `failFast` options.
|
|
277
289
|
|
|
278
290
|
**Clarify TUI for single/parallel:**
|
|
279
291
|
|
|
@@ -290,13 +302,14 @@ Single and parallel modes also support the clarify TUI for previewing/editing pa
|
|
|
290
302
|
**Clarification TUI keybindings:**
|
|
291
303
|
|
|
292
304
|
*Navigation mode:*
|
|
293
|
-
- `Enter` - Run
|
|
305
|
+
- `Enter` - Run (foreground) or launch in background if `b` is toggled on
|
|
294
306
|
- `Esc` - Cancel
|
|
295
307
|
- `↑↓` - Navigate between steps/tasks (parallel, chain)
|
|
296
308
|
- `e` - Edit task/template (all modes)
|
|
297
309
|
- `m` - Select model (all modes)
|
|
298
310
|
- `t` - Select thinking level (all modes)
|
|
299
311
|
- `s` - Select skills (all modes)
|
|
312
|
+
- `b` - Toggle background/async execution (all modes) — shows `[b]g:ON` when enabled
|
|
300
313
|
- `w` - Edit writes/output file (single, chain only)
|
|
301
314
|
- `r` - Edit reads list (chain only)
|
|
302
315
|
- `p` - Toggle progress tracking (chain only)
|
package/chain-clarify.ts
CHANGED
|
@@ -42,6 +42,8 @@ export interface ChainClarifyResult {
|
|
|
42
42
|
templates: string[];
|
|
43
43
|
/** User-modified behavior overrides per step (undefined = no changes) */
|
|
44
44
|
behaviorOverrides: (BehaviorOverride | undefined)[];
|
|
45
|
+
/** User requested background/async execution */
|
|
46
|
+
runInBackground?: boolean;
|
|
45
47
|
}
|
|
46
48
|
|
|
47
49
|
type EditMode = "template" | "output" | "reads" | "model" | "thinking" | "skills";
|
|
@@ -88,6 +90,8 @@ export class ChainClarifyComponent implements Component {
|
|
|
88
90
|
private saveMessageTimer: ReturnType<typeof setTimeout> | null = null;
|
|
89
91
|
private saveChainNameState: TextEditorState = createEditorState();
|
|
90
92
|
private savingChain = false;
|
|
93
|
+
/** Run in background (async) mode */
|
|
94
|
+
private runInBackground = false;
|
|
91
95
|
|
|
92
96
|
constructor(
|
|
93
97
|
private tui: TUI,
|
|
@@ -463,7 +467,7 @@ export class ChainClarifyComponent implements Component {
|
|
|
463
467
|
for (let i = 0; i < this.agentConfigs.length; i++) {
|
|
464
468
|
overrides.push(this.behaviorOverrides.get(i));
|
|
465
469
|
}
|
|
466
|
-
this.done({ confirmed: true, templates: this.templates, behaviorOverrides: overrides });
|
|
470
|
+
this.done({ confirmed: true, templates: this.templates, behaviorOverrides: overrides, runInBackground: this.runInBackground });
|
|
467
471
|
return;
|
|
468
472
|
}
|
|
469
473
|
|
|
@@ -539,6 +543,13 @@ export class ChainClarifyComponent implements Component {
|
|
|
539
543
|
return;
|
|
540
544
|
}
|
|
541
545
|
|
|
546
|
+
// 'b' to toggle background/async execution (all modes)
|
|
547
|
+
if (data === "b") {
|
|
548
|
+
this.runInBackground = !this.runInBackground;
|
|
549
|
+
this.tui.requestRender();
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
|
|
542
553
|
if (data === "S") {
|
|
543
554
|
this.saveOverridesToAgent();
|
|
544
555
|
return;
|
|
@@ -1179,13 +1190,14 @@ export class ChainClarifyComponent implements Component {
|
|
|
1179
1190
|
|
|
1180
1191
|
/** Get footer text based on mode */
|
|
1181
1192
|
private getFooterText(): string {
|
|
1193
|
+
const bgLabel = this.runInBackground ? '[b]g:ON' : '[b]g';
|
|
1182
1194
|
switch (this.mode) {
|
|
1183
1195
|
case 'single':
|
|
1184
|
-
return
|
|
1196
|
+
return ` [Enter] Run • [Esc] Cancel • e m t w s ${bgLabel} S `;
|
|
1185
1197
|
case 'parallel':
|
|
1186
|
-
return
|
|
1198
|
+
return ` [Enter] Run • [Esc] Cancel • e m t s ${bgLabel} S • ↑↓ Nav `;
|
|
1187
1199
|
case 'chain':
|
|
1188
|
-
return
|
|
1200
|
+
return ` [Enter] Run • [Esc] Cancel • e m t w r p s ${bgLabel} S W • ↑↓ Nav `;
|
|
1189
1201
|
}
|
|
1190
1202
|
}
|
|
1191
1203
|
|
package/chain-execution.ts
CHANGED
|
@@ -83,6 +83,11 @@ export interface ChainExecutionResult {
|
|
|
83
83
|
content: Array<{ type: "text"; text: string }>;
|
|
84
84
|
details: Details;
|
|
85
85
|
isError?: boolean;
|
|
86
|
+
/** User requested async execution via TUI - caller should dispatch to executeAsyncChain */
|
|
87
|
+
requestedAsync?: {
|
|
88
|
+
chain: ChainStep[];
|
|
89
|
+
chainSkills: string[];
|
|
90
|
+
};
|
|
86
91
|
}
|
|
87
92
|
|
|
88
93
|
/**
|
|
@@ -210,6 +215,31 @@ export async function executeChain(params: ChainExecutionParams): Promise<ChainE
|
|
|
210
215
|
details: { mode: "chain", results: [] },
|
|
211
216
|
};
|
|
212
217
|
}
|
|
218
|
+
|
|
219
|
+
// User requested background execution - return early so caller can dispatch to async
|
|
220
|
+
if (result.runInBackground) {
|
|
221
|
+
removeChainDir(chainDir); // Will be recreated by async runner
|
|
222
|
+
// Apply TUI edits (templates + behavior overrides) to chain steps
|
|
223
|
+
const updatedChain = chainSteps.map((step, i) => {
|
|
224
|
+
if (isParallelStep(step)) return step; // Parallel steps unchanged (TUI skipped for parallel chains)
|
|
225
|
+
const override = result.behaviorOverrides[i];
|
|
226
|
+
return {
|
|
227
|
+
...step,
|
|
228
|
+
task: result.templates[i] as string, // Always use edited template
|
|
229
|
+
...(override?.model ? { model: override.model } : {}),
|
|
230
|
+
...(override?.output !== undefined ? { output: override.output } : {}),
|
|
231
|
+
...(override?.reads !== undefined ? { reads: override.reads } : {}),
|
|
232
|
+
...(override?.progress !== undefined ? { progress: override.progress } : {}),
|
|
233
|
+
...(override?.skills !== undefined ? { skill: override.skills } : {}),
|
|
234
|
+
};
|
|
235
|
+
});
|
|
236
|
+
return {
|
|
237
|
+
content: [{ type: "text", text: "Launching in background..." }],
|
|
238
|
+
details: { mode: "chain", results: [] },
|
|
239
|
+
requestedAsync: { chain: updatedChain as ChainStep[], chainSkills },
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
|
|
213
243
|
// Update templates from TUI result
|
|
214
244
|
templates = result.templates;
|
|
215
245
|
// Store behavior overrides from TUI (used below in sequential step execution)
|
package/index.ts
CHANGED
|
@@ -451,7 +451,7 @@ MANAGEMENT (use action field — omit agent/task/chain/tasks):
|
|
|
451
451
|
const normalized = normalizeSkillInput(params.skill);
|
|
452
452
|
const chainSkills = normalized === false ? [] : (normalized ?? []);
|
|
453
453
|
// Use extracted chain execution module
|
|
454
|
-
|
|
454
|
+
const chainResult = await executeChain({
|
|
455
455
|
chain: params.chain as ChainStep[],
|
|
456
456
|
task: params.task,
|
|
457
457
|
agents,
|
|
@@ -469,6 +469,33 @@ MANAGEMENT (use action field — omit agent/task/chain/tasks):
|
|
|
469
469
|
chainSkills,
|
|
470
470
|
chainDir: params.chainDir,
|
|
471
471
|
});
|
|
472
|
+
|
|
473
|
+
// User requested async via TUI - dispatch to async executor
|
|
474
|
+
if (chainResult.requestedAsync) {
|
|
475
|
+
if (!isAsyncAvailable()) {
|
|
476
|
+
return {
|
|
477
|
+
content: [{ type: "text", text: "Background mode requires jiti for TypeScript execution but it could not be found." }],
|
|
478
|
+
isError: true,
|
|
479
|
+
details: { mode: "chain" as const, results: [] },
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
const id = randomUUID();
|
|
483
|
+
const asyncCtx = { pi, cwd: ctx.cwd, currentSessionId: currentSessionId! };
|
|
484
|
+
return executeAsyncChain(id, {
|
|
485
|
+
chain: chainResult.requestedAsync.chain,
|
|
486
|
+
agents,
|
|
487
|
+
ctx: asyncCtx,
|
|
488
|
+
cwd: params.cwd,
|
|
489
|
+
maxOutput: params.maxOutput,
|
|
490
|
+
artifactsDir: artifactConfig.enabled ? artifactsDir : undefined,
|
|
491
|
+
artifactConfig,
|
|
492
|
+
shareEnabled,
|
|
493
|
+
sessionRoot,
|
|
494
|
+
chainSkills: chainResult.requestedAsync.chainSkills,
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
return chainResult;
|
|
472
499
|
}
|
|
473
500
|
|
|
474
501
|
if (hasTasks && params.tasks) {
|
|
@@ -545,6 +572,39 @@ MANAGEMENT (use action field — omit agent/task/chain/tasks):
|
|
|
545
572
|
if (override?.model) modelOverrides[i] = override.model;
|
|
546
573
|
if (override?.skills !== undefined) skillOverrides[i] = override.skills;
|
|
547
574
|
}
|
|
575
|
+
|
|
576
|
+
// User requested background execution
|
|
577
|
+
if (result.runInBackground) {
|
|
578
|
+
if (!isAsyncAvailable()) {
|
|
579
|
+
return {
|
|
580
|
+
content: [{ type: "text", text: "Background mode requires jiti for TypeScript execution but it could not be found." }],
|
|
581
|
+
isError: true,
|
|
582
|
+
details: { mode: "parallel" as const, results: [] },
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
const id = randomUUID();
|
|
586
|
+
const asyncCtx = { pi, cwd: ctx.cwd, currentSessionId: currentSessionId! };
|
|
587
|
+
// Convert parallel tasks to a chain with a single parallel step
|
|
588
|
+
const parallelTasks = params.tasks!.map((t, i) => ({
|
|
589
|
+
agent: t.agent,
|
|
590
|
+
task: tasks[i],
|
|
591
|
+
cwd: t.cwd,
|
|
592
|
+
...(modelOverrides[i] ? { model: modelOverrides[i] } : {}),
|
|
593
|
+
...(skillOverrides[i] !== undefined ? { skill: skillOverrides[i] } : {}),
|
|
594
|
+
}));
|
|
595
|
+
return executeAsyncChain(id, {
|
|
596
|
+
chain: [{ parallel: parallelTasks }],
|
|
597
|
+
agents,
|
|
598
|
+
ctx: asyncCtx,
|
|
599
|
+
cwd: params.cwd,
|
|
600
|
+
maxOutput: params.maxOutput,
|
|
601
|
+
artifactsDir: artifactConfig.enabled ? artifactsDir : undefined,
|
|
602
|
+
artifactConfig,
|
|
603
|
+
shareEnabled,
|
|
604
|
+
sessionRoot,
|
|
605
|
+
chainSkills: [],
|
|
606
|
+
});
|
|
607
|
+
}
|
|
548
608
|
}
|
|
549
609
|
|
|
550
610
|
// Execute with overrides (tasks array has same length as params.tasks)
|
|
@@ -691,6 +751,33 @@ MANAGEMENT (use action field — omit agent/task/chain/tasks):
|
|
|
691
751
|
if (override?.model) modelOverride = override.model;
|
|
692
752
|
if (override?.output !== undefined) effectiveOutput = override.output;
|
|
693
753
|
if (override?.skills !== undefined) skillOverride = override.skills;
|
|
754
|
+
|
|
755
|
+
// User requested background execution
|
|
756
|
+
if (result.runInBackground) {
|
|
757
|
+
if (!isAsyncAvailable()) {
|
|
758
|
+
return {
|
|
759
|
+
content: [{ type: "text", text: "Background mode requires jiti for TypeScript execution but it could not be found." }],
|
|
760
|
+
isError: true,
|
|
761
|
+
details: { mode: "single" as const, results: [] },
|
|
762
|
+
};
|
|
763
|
+
}
|
|
764
|
+
const id = randomUUID();
|
|
765
|
+
const asyncCtx = { pi, cwd: ctx.cwd, currentSessionId: currentSessionId! };
|
|
766
|
+
return executeAsyncSingle(id, {
|
|
767
|
+
agent: params.agent!,
|
|
768
|
+
task,
|
|
769
|
+
agentConfig,
|
|
770
|
+
ctx: asyncCtx,
|
|
771
|
+
cwd: params.cwd,
|
|
772
|
+
maxOutput: params.maxOutput,
|
|
773
|
+
artifactsDir: artifactConfig.enabled ? artifactsDir : undefined,
|
|
774
|
+
artifactConfig,
|
|
775
|
+
shareEnabled,
|
|
776
|
+
sessionRoot,
|
|
777
|
+
skills: skillOverride === false ? [] : skillOverride,
|
|
778
|
+
output: effectiveOutput,
|
|
779
|
+
});
|
|
780
|
+
}
|
|
694
781
|
}
|
|
695
782
|
|
|
696
783
|
const cleanTask = task;
|
|
@@ -921,6 +1008,15 @@ MANAGEMENT (use action field — omit agent/task/chain/tasks):
|
|
|
921
1008
|
return { name: token.slice(0, bracket), config: parseInlineConfig(token.slice(bracket + 1, end !== -1 ? end : undefined)) };
|
|
922
1009
|
};
|
|
923
1010
|
|
|
1011
|
+
/** Extract --bg flag from end of args, return cleaned args and whether flag was present */
|
|
1012
|
+
const extractBgFlag = (args: string): { args: string; bg: boolean } => {
|
|
1013
|
+
// Only match --bg at the very end to avoid false positives in quoted strings
|
|
1014
|
+
if (args.endsWith(" --bg") || args === "--bg") {
|
|
1015
|
+
return { args: args.slice(0, args.length - (args === "--bg" ? 4 : 5)).trim(), bg: true };
|
|
1016
|
+
}
|
|
1017
|
+
return { args, bg: false };
|
|
1018
|
+
};
|
|
1019
|
+
|
|
924
1020
|
const setupDirectRun = (ctx: ExtensionContext) => {
|
|
925
1021
|
const runId = randomUUID().slice(0, 8);
|
|
926
1022
|
const sessionRoot = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagent-session-"));
|
|
@@ -980,7 +1076,35 @@ MANAGEMENT (use action field — omit agent/task/chain/tasks):
|
|
|
980
1076
|
...(i === 0 ? { task: result.task } : {}),
|
|
981
1077
|
}));
|
|
982
1078
|
executeChain({ chain, task: result.task, agents, ctx, ...exec, clarify: true })
|
|
983
|
-
.then((r) =>
|
|
1079
|
+
.then((r) => {
|
|
1080
|
+
// User requested async via TUI - dispatch to async executor
|
|
1081
|
+
if (r.requestedAsync) {
|
|
1082
|
+
if (!isAsyncAvailable()) {
|
|
1083
|
+
pi.sendUserMessage("Background mode requires jiti for TypeScript execution but it could not be found.");
|
|
1084
|
+
return;
|
|
1085
|
+
}
|
|
1086
|
+
const id = randomUUID();
|
|
1087
|
+
const asyncCtx = { pi, cwd: ctx.cwd, currentSessionId: ctx.sessionManager.getSessionId() ?? id };
|
|
1088
|
+
const sessionRoot = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagent-session-"));
|
|
1089
|
+
executeAsyncChain(id, {
|
|
1090
|
+
chain: r.requestedAsync.chain,
|
|
1091
|
+
agents,
|
|
1092
|
+
ctx: asyncCtx,
|
|
1093
|
+
maxOutput: undefined,
|
|
1094
|
+
artifactsDir: exec.artifactsDir,
|
|
1095
|
+
artifactConfig: exec.artifactConfig,
|
|
1096
|
+
shareEnabled: false,
|
|
1097
|
+
sessionRoot,
|
|
1098
|
+
chainSkills: r.requestedAsync.chainSkills,
|
|
1099
|
+
}).then((asyncResult) => {
|
|
1100
|
+
pi.sendUserMessage(asyncResult.content[0]?.text || "(launched in background)");
|
|
1101
|
+
}).catch((err) => {
|
|
1102
|
+
pi.sendUserMessage(`Async launch failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1103
|
+
});
|
|
1104
|
+
return;
|
|
1105
|
+
}
|
|
1106
|
+
pi.sendUserMessage(r.content[0]?.text || "(no output)");
|
|
1107
|
+
})
|
|
984
1108
|
.catch((err) => pi.sendUserMessage(`Chain failed: ${err instanceof Error ? err.message : String(err)}`));
|
|
985
1109
|
return;
|
|
986
1110
|
}
|
|
@@ -1017,15 +1141,16 @@ MANAGEMENT (use action field — omit agent/task/chain/tasks):
|
|
|
1017
1141
|
});
|
|
1018
1142
|
|
|
1019
1143
|
pi.registerCommand("run", {
|
|
1020
|
-
description: "Run a subagent directly: /run agent[output=file] task",
|
|
1144
|
+
description: "Run a subagent directly: /run agent[output=file] task [--bg]",
|
|
1021
1145
|
getArgumentCompletions: makeAgentCompletions(false),
|
|
1022
1146
|
handler: async (args, ctx) => {
|
|
1023
|
-
const
|
|
1147
|
+
const { args: cleanedArgs, bg } = extractBgFlag(args);
|
|
1148
|
+
const input = cleanedArgs.trim();
|
|
1024
1149
|
const firstSpace = input.indexOf(" ");
|
|
1025
|
-
if (firstSpace === -1) { ctx.ui.notify("Usage: /run <agent> <task>", "error"); return; }
|
|
1150
|
+
if (firstSpace === -1) { ctx.ui.notify("Usage: /run <agent> <task> [--bg]", "error"); return; }
|
|
1026
1151
|
const { name: agentName, config: inline } = parseAgentToken(input.slice(0, firstSpace));
|
|
1027
1152
|
const task = input.slice(firstSpace + 1).trim();
|
|
1028
|
-
if (!task) { ctx.ui.notify("Usage: /run <agent> <task>", "error"); return; }
|
|
1153
|
+
if (!task) { ctx.ui.notify("Usage: /run <agent> <task> [--bg]", "error"); return; }
|
|
1029
1154
|
|
|
1030
1155
|
const agents = discoverAgents(baseCwd, "both").agents;
|
|
1031
1156
|
if (!agents.find((a) => a.name === agentName)) { ctx.ui.notify(`Unknown agent: ${agentName}`, "error"); return; }
|
|
@@ -1038,6 +1163,7 @@ MANAGEMENT (use action field — omit agent/task/chain/tasks):
|
|
|
1038
1163
|
if (inline.output !== undefined) params.output = inline.output;
|
|
1039
1164
|
if (inline.skill !== undefined) params.skill = inline.skill;
|
|
1040
1165
|
if (inline.model) params.model = inline.model;
|
|
1166
|
+
if (bg) params.async = true;
|
|
1041
1167
|
pi.sendUserMessage(`Call the subagent tool with these exact parameters: ${JSON.stringify({ ...params, agentScope: "both" })}`);
|
|
1042
1168
|
},
|
|
1043
1169
|
});
|
|
@@ -1115,10 +1241,11 @@ MANAGEMENT (use action field — omit agent/task/chain/tasks):
|
|
|
1115
1241
|
};
|
|
1116
1242
|
|
|
1117
1243
|
pi.registerCommand("chain", {
|
|
1118
|
-
description: "Run agents in sequence: /chain scout \"
|
|
1244
|
+
description: "Run agents in sequence: /chain scout \"task\" -> planner [--bg]",
|
|
1119
1245
|
getArgumentCompletions: makeAgentCompletions(true),
|
|
1120
1246
|
handler: async (args, ctx) => {
|
|
1121
|
-
const
|
|
1247
|
+
const { args: cleanedArgs, bg } = extractBgFlag(args);
|
|
1248
|
+
const parsed = parseAgentArgs(cleanedArgs, "chain", ctx);
|
|
1122
1249
|
if (!parsed) return;
|
|
1123
1250
|
const chain = parsed.steps.map(({ name, config, task: stepTask }, i) => ({
|
|
1124
1251
|
agent: name,
|
|
@@ -1129,15 +1256,18 @@ MANAGEMENT (use action field — omit agent/task/chain/tasks):
|
|
|
1129
1256
|
...(config.skill !== undefined ? { skill: config.skill } : {}),
|
|
1130
1257
|
...(config.progress !== undefined ? { progress: config.progress } : {}),
|
|
1131
1258
|
}));
|
|
1132
|
-
|
|
1259
|
+
const params: Record<string, unknown> = { chain, task: parsed.task, clarify: false, agentScope: "both" };
|
|
1260
|
+
if (bg) params.async = true;
|
|
1261
|
+
pi.sendUserMessage(`Call the subagent tool with these exact parameters: ${JSON.stringify(params)}`);
|
|
1133
1262
|
},
|
|
1134
1263
|
});
|
|
1135
1264
|
|
|
1136
1265
|
pi.registerCommand("parallel", {
|
|
1137
|
-
description: "Run agents in parallel: /parallel scout \"
|
|
1266
|
+
description: "Run agents in parallel: /parallel scout \"task1\" -> reviewer \"task2\" [--bg]",
|
|
1138
1267
|
getArgumentCompletions: makeAgentCompletions(true),
|
|
1139
1268
|
handler: async (args, ctx) => {
|
|
1140
|
-
const
|
|
1269
|
+
const { args: cleanedArgs, bg } = extractBgFlag(args);
|
|
1270
|
+
const parsed = parseAgentArgs(cleanedArgs, "parallel", ctx);
|
|
1141
1271
|
if (!parsed) return;
|
|
1142
1272
|
if (parsed.steps.length > MAX_PARALLEL) { ctx.ui.notify(`Max ${MAX_PARALLEL} parallel tasks`, "error"); return; }
|
|
1143
1273
|
const tasks = parsed.steps.map(({ name, config, task: stepTask }) => ({
|
|
@@ -1149,7 +1279,9 @@ MANAGEMENT (use action field — omit agent/task/chain/tasks):
|
|
|
1149
1279
|
...(config.skill !== undefined ? { skill: config.skill } : {}),
|
|
1150
1280
|
...(config.progress !== undefined ? { progress: config.progress } : {}),
|
|
1151
1281
|
}));
|
|
1152
|
-
|
|
1282
|
+
const params: Record<string, unknown> = { chain: [{ parallel: tasks }], task: parsed.task, clarify: false, agentScope: "both" };
|
|
1283
|
+
if (bg) params.async = true;
|
|
1284
|
+
pi.sendUserMessage(`Call the subagent tool with these exact parameters: ${JSON.stringify(params)}`);
|
|
1153
1285
|
},
|
|
1154
1286
|
});
|
|
1155
1287
|
|
package/package.json
CHANGED