flake-update-20260505
  1/**
  2 * Orchestrator Mode Extension
  3 *
  4 * A simple mode that transforms the main agent into an orchestrator.
  5 * When enabled, only the subagent tool is available and the system prompt
  6 * is updated to focus on coordination and delegation.
  7 *
  8 * Features:
  9 * - /orc command to toggle orchestrator mode
 10 * - In orc mode: only subagent tool available
 11 * - System prompt modified to focus on orchestration
 12 * - Orange status indicator when active
 13 *
 14 * Usage:
 15 * 1. Use /orc to toggle orchestrator mode on/off
 16 * 2. Or start with --orc flag
 17 */
 18
 19import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent";
 20
 21// Tools available in orchestrator mode - subagent for delegation, subagent_status for async monitoring
 22const ORC_MODE_TOOLS = ["subagent", "subagent_status"];
 23
 24// Store the original tools to restore them when disabling orc mode
 25let savedTools: string[] | null = null;
 26
 27export default function orcModeExtension(pi: ExtensionAPI) {
 28	let orcModeEnabled = false;
 29
 30	// Register --orc CLI flag
 31	pi.registerFlag("orc", {
 32		description: "Start in orchestrator mode (coordinator-only)",
 33		type: "boolean",
 34		default: false,
 35	});
 36
 37	// Helper to update status displays
 38	function updateStatus(ctx: ExtensionContext) {
 39		if (orcModeEnabled) {
 40			ctx.ui.setStatus("orc-mode", ctx.ui.theme.fg("warning", "🎭 ORC"));
 41			ctx.ui.setWidget("orc-mode", [
 42				ctx.ui.theme.fg("warning", "🎭 Orchestrator mode active"),
 43				ctx.ui.theme.fg("muted", "Only subagent tool available"),
 44				ctx.ui.theme.fg("dim", "Use /orc to disable"),
 45			]);
 46		} else {
 47			ctx.ui.setStatus("orc-mode", undefined);
 48			ctx.ui.setWidget("orc-mode", undefined);
 49		}
 50	}
 51
 52	function enableOrcMode(ctx: ExtensionContext) {
 53		if (orcModeEnabled) return;
 54
 55		// Save current tools before switching
 56		savedTools = pi.getActiveTools();
 57		orcModeEnabled = true;
 58		pi.setActiveTools(ORC_MODE_TOOLS);
 59		ctx.ui.notify("🎭 Orchestrator mode enabled. Only subagent tool available.");
 60		updateStatus(ctx);
 61		persistState();
 62	}
 63
 64	function disableOrcMode(ctx: ExtensionContext) {
 65		if (!orcModeEnabled) return;
 66
 67		orcModeEnabled = false;
 68		// Restore original tools or use defaults
 69		if (savedTools && savedTools.length > 0) {
 70			pi.setActiveTools(savedTools);
 71		} else {
 72			// Fallback to standard tools
 73			pi.setActiveTools(["read", "bash", "edit", "write", "subagent"]);
 74		}
 75		savedTools = null;
 76		ctx.ui.notify("Orchestrator mode disabled. Full tool access restored.");
 77		updateStatus(ctx);
 78		persistState();
 79	}
 80
 81	function toggleOrcMode(ctx: ExtensionContext) {
 82		if (orcModeEnabled) {
 83			disableOrcMode(ctx);
 84		} else {
 85			enableOrcMode(ctx);
 86		}
 87	}
 88
 89	function persistState() {
 90		pi.appendEntry("orc-mode-state", {
 91			enabled: orcModeEnabled,
 92			savedTools,
 93		});
 94	}
 95
 96	// Register /orc command
 97	pi.registerCommand("orc", {
 98		description: "Toggle orchestrator mode (only subagent tool available)",
 99		handler: async (_args, ctx) => {
100			toggleOrcMode(ctx);
101		},
102	});
103
104	// Modify system prompt when orc mode is active
105	pi.on("before_agent_start", async (event) => {
106		if (!orcModeEnabled) return;
107
108		const orcSystemPrompt = `${event.systemPrompt}
109
110## ORCHESTRATOR MODE
111
112You are operating as an **orchestrator**. Your primary role is to coordinate, plan, and delegate work—not to implement directly.
113
114### Your Tools
115You only have access to the **subagent** tool. Use it to delegate all work:
116- **scout**: Fast codebase recon, find files, return compressed context for handoff
117- **planner**: Create implementation plans from context and requirements
118- **worker**: General-purpose subagent with full capabilities for implementation
119- **reviewer**: Code review specialist for quality and security analysis
120- **oracle**: Deep analysis, debugging, and architecture decisions
121
122### Subagent Modes
123
124**Single agent:**
125\`\`\`typescript
126{ agent: "explorer", task: "Find all auth-related files" }
127\`\`\`
128
129**Parallel tasks** (independent work):
130\`\`\`typescript
131{ tasks: [
132  { agent: "explorer", task: "Find frontend modules" },
133  { agent: "explorer", task: "Find backend modules" }
134]}
135\`\`\`
136
137**Chain** (sequential pipeline with \`{previous}\` carrying output forward):
138\`\`\`typescript
139{ chain: [
140  { agent: "explorer", task: "Gather context for auth refactor" },
141  { agent: "oracle", task: "Analyze and plan based on {previous}" },
142  { agent: "operator" },  // defaults to {previous}
143  { agent: "oracle", task: "Review changes from {previous}" }
144]}
145\`\`\`
146
147**Chain with parallel fan-out/fan-in:**
148\`\`\`typescript
149{ chain: [
150  { agent: "explorer", task: "Find all service modules" },
151  { parallel: [
152    { agent: "operator", task: "Refactor auth service from {previous}" },
153    { agent: "operator", task: "Refactor user service from {previous}" }
154  ]},
155  { agent: "oracle", task: "Review all changes from {previous}" }
156]}
157\`\`\`
158
159### Chain Variables
160- \`{task}\` - Original task from first step
161- \`{previous}\` - Output from prior step (or aggregated parallel outputs)
162- \`{chain_dir}\` - Shared artifacts directory for inter-step files
163
164### Workflow
1651. **Analyze** the user's request
1662. **Plan** the approach (break into steps if complex)
1673. **Delegate** each task to the appropriate subagent
1684. **Synthesize** results and report back
169
170### Guidelines
171- Always use subagent to delegate work
172- For complex multi-step tasks, use chain mode
173- For independent tasks, use parallel mode
174- Use parallel-in-chain for fan-out/fan-in patterns
175- Provide clear, specific task descriptions to subagents
176- After subagents complete, summarize findings or confirm changes`;
177
178		return { systemPrompt: orcSystemPrompt };
179	});
180
181	// Initialize state on session start
182	pi.on("session_start", async (_event, ctx) => {
183		// Check CLI flag
184		if (pi.getFlag("orc") === true) {
185			// Defer enabling to let other extensions initialize first
186			setTimeout(() => {
187				if (!orcModeEnabled) {
188					enableOrcMode(ctx);
189				}
190			}, 0);
191			return;
192		}
193
194		// Restore state from session
195		const entries = ctx.sessionManager.getEntries();
196		const stateEntry = entries
197			.filter((e: { type: string; customType?: string }) => e.type === "custom" && e.customType === "orc-mode-state")
198			.pop() as { data?: { enabled: boolean; savedTools?: string[] | null } } | undefined;
199
200		if (stateEntry?.data) {
201			if (stateEntry.data.enabled) {
202				savedTools = stateEntry.data.savedTools ?? null;
203				orcModeEnabled = true;
204				pi.setActiveTools(ORC_MODE_TOOLS);
205			}
206		}
207
208		updateStatus(ctx);
209	});
210}