opencode-swarm-plugin 0.17.1 → 0.19.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.
@@ -0,0 +1,756 @@
1
+ /**
2
+ * Swarm Prompts Module - Prompt templates and generation
3
+ *
4
+ * Provides all prompt templates used for swarm coordination:
5
+ * - Decomposition prompts (basic and strategy-specific)
6
+ * - Subtask agent prompts (V1 and V2)
7
+ * - Evaluation prompts
8
+ *
9
+ * Key responsibilities:
10
+ * - Prompt template definitions
11
+ * - Prompt formatting/generation tools
12
+ * - Template parameter substitution
13
+ */
14
+
15
+ import { tool } from "@opencode-ai/plugin";
16
+
17
+ // ============================================================================
18
+ // Prompt Templates
19
+ // ============================================================================
20
+
21
+ /**
22
+ * Prompt for decomposing a task into parallelizable subtasks.
23
+ *
24
+ * Used by swarm_decompose to instruct the agent on how to break down work.
25
+ * The agent responds with a BeadTree that gets validated.
26
+ */
27
+ export const DECOMPOSITION_PROMPT = `You are decomposing a task into parallelizable subtasks for a swarm of agents.
28
+
29
+ ## Task
30
+ {task}
31
+
32
+ {context_section}
33
+
34
+ ## MANDATORY: Beads Issue Tracking
35
+
36
+ **Every subtask MUST become a bead.** This is non-negotiable.
37
+
38
+ After decomposition, the coordinator will:
39
+ 1. Create an epic bead for the overall task
40
+ 2. Create child beads for each subtask
41
+ 3. Track progress through bead status updates
42
+ 4. Close beads with summaries when complete
43
+
44
+ Agents MUST update their bead status as they work. No silent progress.
45
+
46
+ ## Requirements
47
+
48
+ 1. **Break into 2-{max_subtasks} independent subtasks** that can run in parallel
49
+ 2. **Assign files** - each subtask must specify which files it will modify
50
+ 3. **No file overlap** - files cannot appear in multiple subtasks (they get exclusive locks)
51
+ 4. **Order by dependency** - if subtask B needs subtask A's output, A must come first in the array
52
+ 5. **Estimate complexity** - 1 (trivial) to 5 (complex)
53
+ 6. **Plan aggressively** - break down more than you think necessary, smaller is better
54
+
55
+ ## Response Format
56
+
57
+ Respond with a JSON object matching this schema:
58
+
59
+ \`\`\`typescript
60
+ {
61
+ epic: {
62
+ title: string, // Epic title for the beads tracker
63
+ description?: string // Brief description of the overall goal
64
+ },
65
+ subtasks: [
66
+ {
67
+ title: string, // What this subtask accomplishes
68
+ description?: string, // Detailed instructions for the agent
69
+ files: string[], // Files this subtask will modify (globs allowed)
70
+ dependencies: number[], // Indices of subtasks this depends on (0-indexed)
71
+ estimated_complexity: 1-5 // Effort estimate
72
+ },
73
+ // ... more subtasks
74
+ ]
75
+ }
76
+ \`\`\`
77
+
78
+ ## Guidelines
79
+
80
+ - **Plan aggressively** - when in doubt, split further. 3 small tasks > 1 medium task
81
+ - **Prefer smaller, focused subtasks** over large complex ones
82
+ - **Include test files** in the same subtask as the code they test
83
+ - **Consider shared types** - if multiple files share types, handle that first
84
+ - **Think about imports** - changes to exported APIs affect downstream files
85
+ - **Explicit > implicit** - spell out what each subtask should do, don't assume
86
+
87
+ ## File Assignment Examples
88
+
89
+ - Schema change: \`["src/schemas/user.ts", "src/schemas/index.ts"]\`
90
+ - Component + test: \`["src/components/Button.tsx", "src/components/Button.test.tsx"]\`
91
+ - API route: \`["src/app/api/users/route.ts"]\`
92
+
93
+ Now decompose the task:`;
94
+
95
+ /**
96
+ * Strategy-specific decomposition prompt template
97
+ */
98
+ export const STRATEGY_DECOMPOSITION_PROMPT = `You are decomposing a task into parallelizable subtasks for a swarm of agents.
99
+
100
+ ## Task
101
+ {task}
102
+
103
+ {strategy_guidelines}
104
+
105
+ {context_section}
106
+
107
+ {cass_history}
108
+
109
+ {skills_context}
110
+
111
+ ## MANDATORY: Beads Issue Tracking
112
+
113
+ **Every subtask MUST become a bead.** This is non-negotiable.
114
+
115
+ After decomposition, the coordinator will:
116
+ 1. Create an epic bead for the overall task
117
+ 2. Create child beads for each subtask
118
+ 3. Track progress through bead status updates
119
+ 4. Close beads with summaries when complete
120
+
121
+ Agents MUST update their bead status as they work. No silent progress.
122
+
123
+ ## Requirements
124
+
125
+ 1. **Break into 2-{max_subtasks} independent subtasks** that can run in parallel
126
+ 2. **Assign files** - each subtask must specify which files it will modify
127
+ 3. **No file overlap** - files cannot appear in multiple subtasks (they get exclusive locks)
128
+ 4. **Order by dependency** - if subtask B needs subtask A's output, A must come first in the array
129
+ 5. **Estimate complexity** - 1 (trivial) to 5 (complex)
130
+ 6. **Plan aggressively** - break down more than you think necessary, smaller is better
131
+
132
+ ## Response Format
133
+
134
+ Respond with a JSON object matching this schema:
135
+
136
+ \`\`\`typescript
137
+ {
138
+ epic: {
139
+ title: string, // Epic title for the beads tracker
140
+ description?: string // Brief description of the overall goal
141
+ },
142
+ subtasks: [
143
+ {
144
+ title: string, // What this subtask accomplishes
145
+ description?: string, // Detailed instructions for the agent
146
+ files: string[], // Files this subtask will modify (globs allowed)
147
+ dependencies: number[], // Indices of subtasks this depends on (0-indexed)
148
+ estimated_complexity: 1-5 // Effort estimate
149
+ },
150
+ // ... more subtasks
151
+ ]
152
+ }
153
+ \`\`\`
154
+
155
+ Now decompose the task:`;
156
+
157
+ /**
158
+ * Prompt template for spawned subtask agents.
159
+ *
160
+ * Each agent receives this prompt with their specific subtask details filled in.
161
+ * The prompt establishes context, constraints, and expectations.
162
+ */
163
+ export const SUBTASK_PROMPT = `You are a swarm agent working on a subtask of a larger epic.
164
+
165
+ ## Your Identity
166
+ - **Agent Name**: {agent_name}
167
+ - **Bead ID**: {bead_id}
168
+ - **Epic ID**: {epic_id}
169
+
170
+ ## Your Subtask
171
+ **Title**: {subtask_title}
172
+
173
+ {subtask_description}
174
+
175
+ ## File Scope
176
+ You have exclusive reservations for these files:
177
+ {file_list}
178
+
179
+ **CRITICAL**: Only modify files in your reservation. If you need to modify other files,
180
+ send a message to the coordinator requesting the change.
181
+
182
+ ## Shared Context
183
+ {shared_context}
184
+
185
+ ## MANDATORY: Beads Tracking
186
+
187
+ You MUST keep your bead updated as you work:
188
+
189
+ 1. **Your bead is already in_progress** - don't change this unless blocked
190
+ 2. **If blocked**: \`bd update {bead_id} --status blocked\` and message coordinator
191
+ 3. **When done**: Use \`swarm_complete\` - it closes your bead automatically
192
+ 4. **Discovered issues**: Create new beads with \`bd create "issue" -t bug\`
193
+
194
+ **Never work silently.** Your bead status is how the swarm tracks progress.
195
+
196
+ ## MANDATORY: Swarm Mail Communication
197
+
198
+ You MUST communicate with other agents:
199
+
200
+ 1. **Report progress** every significant milestone (not just at the end)
201
+ 2. **Ask questions** if requirements are unclear - don't guess
202
+ 3. **Announce blockers** immediately - don't spin trying to fix alone
203
+ 4. **Coordinate on shared concerns** - if you see something affecting other agents, say so
204
+
205
+ Use Swarm Mail for all communication:
206
+ \`\`\`
207
+ swarmmail_send(
208
+ to: ["coordinator" or specific agent],
209
+ subject: "Brief subject",
210
+ body: "Message content",
211
+ thread_id: "{epic_id}"
212
+ )
213
+ \`\`\`
214
+
215
+ ## Coordination Protocol
216
+
217
+ 1. **Start**: Your bead is already marked in_progress
218
+ 2. **Progress**: Use swarm_progress to report status updates
219
+ 3. **Blocked**: Report immediately via Swarm Mail - don't spin
220
+ 4. **Complete**: Use swarm_complete when done - it handles:
221
+ - Closing your bead with a summary
222
+ - Releasing file reservations
223
+ - Notifying the coordinator
224
+
225
+ ## Self-Evaluation
226
+
227
+ Before calling swarm_complete, evaluate your work:
228
+ - Type safety: Does it compile without errors?
229
+ - No obvious bugs: Did you handle edge cases?
230
+ - Follows patterns: Does it match existing code style?
231
+ - Readable: Would another developer understand it?
232
+
233
+ If evaluation fails, fix the issues before completing.
234
+
235
+ ## Planning Your Work
236
+
237
+ Before writing code:
238
+ 1. **Read the files** you're assigned to understand current state
239
+ 2. **Plan your approach** - what changes, in what order?
240
+ 3. **Identify risks** - what could go wrong? What dependencies?
241
+ 4. **Communicate your plan** via Swarm Mail if non-trivial
242
+
243
+ Begin work on your subtask now.`;
244
+
245
+ /**
246
+ * Streamlined subtask prompt (V2) - uses Swarm Mail and beads
247
+ *
248
+ * This is a cleaner version of SUBTASK_PROMPT that's easier to parse.
249
+ * Agents MUST use Swarm Mail for communication and beads for tracking.
250
+ *
251
+ * Supports {error_context} placeholder for retry prompts.
252
+ */
253
+ export const SUBTASK_PROMPT_V2 = `You are a swarm agent working on: **{subtask_title}**
254
+
255
+ ## [IDENTITY]
256
+ Agent: (assigned at spawn)
257
+ Bead: {bead_id}
258
+ Epic: {epic_id}
259
+
260
+ ## [TASK]
261
+ {subtask_description}
262
+
263
+ ## [FILES]
264
+ Reserved (exclusive):
265
+ {file_list}
266
+
267
+ Only modify these files. Need others? Message the coordinator.
268
+
269
+ ## [CONTEXT]
270
+ {shared_context}
271
+
272
+ {compressed_context}
273
+
274
+ {error_context}
275
+
276
+ ## [MANDATORY: SWARM MAIL]
277
+
278
+ **YOU MUST USE SWARM MAIL FOR ALL COORDINATION.** This is non-negotiable.
279
+
280
+ ### Initialize FIRST (before any work)
281
+ \`\`\`
282
+ swarmmail_init(project_path="$PWD", task_description="{subtask_title}")
283
+ \`\`\`
284
+
285
+ ### Reserve Files (if not already reserved by coordinator)
286
+ \`\`\`
287
+ swarmmail_reserve(paths=[...files...], reason="{bead_id}: {subtask_title}")
288
+ \`\`\`
289
+
290
+ ### Check Inbox Regularly
291
+ \`\`\`
292
+ swarmmail_inbox() # Check for coordinator messages
293
+ swarmmail_read_message(message_id=N) # Read specific message
294
+ \`\`\`
295
+
296
+ ### Report Progress (REQUIRED - don't work silently)
297
+ \`\`\`
298
+ swarmmail_send(
299
+ to=["coordinator"],
300
+ subject="Progress: {bead_id}",
301
+ body="<what you did, blockers, questions>",
302
+ thread_id="{epic_id}"
303
+ )
304
+ \`\`\`
305
+
306
+ ### When Blocked
307
+ \`\`\`
308
+ swarmmail_send(
309
+ to=["coordinator"],
310
+ subject="BLOCKED: {bead_id}",
311
+ body="<blocker description, what you need>",
312
+ importance="high",
313
+ thread_id="{epic_id}"
314
+ )
315
+ beads_update(id="{bead_id}", status="blocked")
316
+ \`\`\`
317
+
318
+ ### Release Files When Done
319
+ \`\`\`
320
+ swarmmail_release() # Or let swarm_complete handle it
321
+ \`\`\`
322
+
323
+ ## [OTHER TOOLS]
324
+ ### Beads
325
+ - beads_update(id, status) - Mark blocked if stuck
326
+ - beads_create(title, type) - Log new bugs found
327
+
328
+ ### Skills (if available)
329
+ - skills_list() - Discover available skills
330
+ - skills_use(name) - Activate skill for specialized guidance
331
+
332
+ ### Completion (REQUIRED)
333
+ - swarm_complete(project_key, agent_name, bead_id, summary, files_touched)
334
+
335
+ ## [LEARNING]
336
+ As you work, note reusable patterns, best practices, or domain insights:
337
+ - If you discover something that would help future agents, consider creating a skill
338
+ - Use skills_create to codify patterns for the project
339
+ - Good skills have clear "when to use" descriptions with actionable instructions
340
+ - Skills make swarms smarter over time
341
+
342
+ ## [WORKFLOW]
343
+ 1. **swarmmail_init** - Initialize session FIRST
344
+ 2. Read assigned files
345
+ 3. Implement changes
346
+ 4. **swarmmail_send** - Report progress to coordinator
347
+ 5. Verify (typecheck)
348
+ 6. **swarm_complete** - Mark done, release reservations
349
+
350
+ **CRITICAL: Never work silently. Send progress updates via swarmmail_send every significant milestone.**
351
+
352
+ Begin now.`;
353
+
354
+ /**
355
+ * Prompt for self-evaluation before completing a subtask.
356
+ *
357
+ * Agents use this to assess their work quality before marking complete.
358
+ */
359
+ export const EVALUATION_PROMPT = `Evaluate the work completed for this subtask.
360
+
361
+ ## Subtask
362
+ **Bead ID**: {bead_id}
363
+ **Title**: {subtask_title}
364
+
365
+ ## Files Modified
366
+ {files_touched}
367
+
368
+ ## Evaluation Criteria
369
+
370
+ For each criterion, assess passed/failed and provide brief feedback:
371
+
372
+ 1. **type_safe**: Code compiles without TypeScript errors
373
+ 2. **no_bugs**: No obvious bugs, edge cases handled
374
+ 3. **patterns**: Follows existing codebase patterns and conventions
375
+ 4. **readable**: Code is clear and maintainable
376
+
377
+ ## Response Format
378
+
379
+ \`\`\`json
380
+ {
381
+ "passed": boolean, // Overall pass/fail
382
+ "criteria": {
383
+ "type_safe": { "passed": boolean, "feedback": string },
384
+ "no_bugs": { "passed": boolean, "feedback": string },
385
+ "patterns": { "passed": boolean, "feedback": string },
386
+ "readable": { "passed": boolean, "feedback": string }
387
+ },
388
+ "overall_feedback": string,
389
+ "retry_suggestion": string | null // If failed, what to fix
390
+ }
391
+ \`\`\`
392
+
393
+ If any criterion fails, the overall evaluation fails and retry_suggestion
394
+ should describe what needs to be fixed.`;
395
+
396
+ // ============================================================================
397
+ // Helper Functions
398
+ // ============================================================================
399
+
400
+ /**
401
+ * Format the V2 subtask prompt for a specific agent
402
+ */
403
+ export function formatSubtaskPromptV2(params: {
404
+ bead_id: string;
405
+ epic_id: string;
406
+ subtask_title: string;
407
+ subtask_description: string;
408
+ files: string[];
409
+ shared_context?: string;
410
+ compressed_context?: string;
411
+ error_context?: string;
412
+ }): string {
413
+ const fileList =
414
+ params.files.length > 0
415
+ ? params.files.map((f) => `- \`${f}\``).join("\n")
416
+ : "(no specific files - use judgment)";
417
+
418
+ const compressedSection = params.compressed_context
419
+ ? params.compressed_context
420
+ : "";
421
+
422
+ const errorSection = params.error_context ? params.error_context : "";
423
+
424
+ return SUBTASK_PROMPT_V2.replace(/{bead_id}/g, params.bead_id)
425
+ .replace(/{epic_id}/g, params.epic_id)
426
+ .replace("{subtask_title}", params.subtask_title)
427
+ .replace(
428
+ "{subtask_description}",
429
+ params.subtask_description || "(see title)",
430
+ )
431
+ .replace("{file_list}", fileList)
432
+ .replace("{shared_context}", params.shared_context || "(none)")
433
+ .replace("{compressed_context}", compressedSection)
434
+ .replace("{error_context}", errorSection);
435
+ }
436
+
437
+ /**
438
+ * Format the subtask prompt for a specific agent
439
+ */
440
+ export function formatSubtaskPrompt(params: {
441
+ agent_name: string;
442
+ bead_id: string;
443
+ epic_id: string;
444
+ subtask_title: string;
445
+ subtask_description: string;
446
+ files: string[];
447
+ shared_context?: string;
448
+ }): string {
449
+ const fileList = params.files.map((f) => `- \`${f}\``).join("\n");
450
+
451
+ return SUBTASK_PROMPT.replace("{agent_name}", params.agent_name)
452
+ .replace("{bead_id}", params.bead_id)
453
+ .replace(/{epic_id}/g, params.epic_id)
454
+ .replace("{subtask_title}", params.subtask_title)
455
+ .replace("{subtask_description}", params.subtask_description || "(none)")
456
+ .replace("{file_list}", fileList || "(no files assigned)")
457
+ .replace("{shared_context}", params.shared_context || "(none)");
458
+ }
459
+
460
+ /**
461
+ * Format the evaluation prompt
462
+ */
463
+ export function formatEvaluationPrompt(params: {
464
+ bead_id: string;
465
+ subtask_title: string;
466
+ files_touched: string[];
467
+ }): string {
468
+ const filesList = params.files_touched.map((f) => `- \`${f}\``).join("\n");
469
+
470
+ return EVALUATION_PROMPT.replace("{bead_id}", params.bead_id)
471
+ .replace("{subtask_title}", params.subtask_title)
472
+ .replace("{files_touched}", filesList || "(no files recorded)");
473
+ }
474
+
475
+ // ============================================================================
476
+ // Tool Definitions
477
+ // ============================================================================
478
+
479
+ /**
480
+ * Generate subtask prompt for a spawned agent
481
+ */
482
+ export const swarm_subtask_prompt = tool({
483
+ description: "Generate the prompt for a spawned subtask agent",
484
+ args: {
485
+ agent_name: tool.schema.string().describe("Agent Mail name for the agent"),
486
+ bead_id: tool.schema.string().describe("Subtask bead ID"),
487
+ epic_id: tool.schema.string().describe("Epic bead ID"),
488
+ subtask_title: tool.schema.string().describe("Subtask title"),
489
+ subtask_description: tool.schema
490
+ .string()
491
+ .optional()
492
+ .describe("Detailed subtask instructions"),
493
+ files: tool.schema
494
+ .array(tool.schema.string())
495
+ .describe("Files assigned to this subtask"),
496
+ shared_context: tool.schema
497
+ .string()
498
+ .optional()
499
+ .describe("Context shared across all agents"),
500
+ },
501
+ async execute(args) {
502
+ const prompt = formatSubtaskPrompt({
503
+ agent_name: args.agent_name,
504
+ bead_id: args.bead_id,
505
+ epic_id: args.epic_id,
506
+ subtask_title: args.subtask_title,
507
+ subtask_description: args.subtask_description || "",
508
+ files: args.files,
509
+ shared_context: args.shared_context,
510
+ });
511
+
512
+ return prompt;
513
+ },
514
+ });
515
+
516
+ /**
517
+ * Prepare a subtask for spawning with Task tool (V2 prompt)
518
+ *
519
+ * Generates a streamlined prompt that tells agents to USE Agent Mail and beads.
520
+ * Returns JSON that can be directly used with Task tool.
521
+ */
522
+ export const swarm_spawn_subtask = tool({
523
+ description:
524
+ "Prepare a subtask for spawning. Returns prompt with Agent Mail/beads instructions.",
525
+ args: {
526
+ bead_id: tool.schema.string().describe("Subtask bead ID"),
527
+ epic_id: tool.schema.string().describe("Parent epic bead ID"),
528
+ subtask_title: tool.schema.string().describe("Subtask title"),
529
+ subtask_description: tool.schema
530
+ .string()
531
+ .optional()
532
+ .describe("Detailed subtask instructions"),
533
+ files: tool.schema
534
+ .array(tool.schema.string())
535
+ .describe("Files assigned to this subtask"),
536
+ shared_context: tool.schema
537
+ .string()
538
+ .optional()
539
+ .describe("Context shared across all agents"),
540
+ },
541
+ async execute(args) {
542
+ const prompt = formatSubtaskPromptV2({
543
+ bead_id: args.bead_id,
544
+ epic_id: args.epic_id,
545
+ subtask_title: args.subtask_title,
546
+ subtask_description: args.subtask_description || "",
547
+ files: args.files,
548
+ shared_context: args.shared_context,
549
+ });
550
+
551
+ return JSON.stringify(
552
+ {
553
+ prompt,
554
+ bead_id: args.bead_id,
555
+ epic_id: args.epic_id,
556
+ files: args.files,
557
+ },
558
+ null,
559
+ 2,
560
+ );
561
+ },
562
+ });
563
+
564
+ /**
565
+ * Generate self-evaluation prompt
566
+ */
567
+ export const swarm_evaluation_prompt = tool({
568
+ description: "Generate self-evaluation prompt for a completed subtask",
569
+ args: {
570
+ bead_id: tool.schema.string().describe("Subtask bead ID"),
571
+ subtask_title: tool.schema.string().describe("Subtask title"),
572
+ files_touched: tool.schema
573
+ .array(tool.schema.string())
574
+ .describe("Files that were modified"),
575
+ },
576
+ async execute(args) {
577
+ const prompt = formatEvaluationPrompt({
578
+ bead_id: args.bead_id,
579
+ subtask_title: args.subtask_title,
580
+ files_touched: args.files_touched,
581
+ });
582
+
583
+ return JSON.stringify(
584
+ {
585
+ prompt,
586
+ expected_schema: "Evaluation",
587
+ schema_hint: {
588
+ passed: "boolean",
589
+ criteria: {
590
+ type_safe: { passed: "boolean", feedback: "string" },
591
+ no_bugs: { passed: "boolean", feedback: "string" },
592
+ patterns: { passed: "boolean", feedback: "string" },
593
+ readable: { passed: "boolean", feedback: "string" },
594
+ },
595
+ overall_feedback: "string",
596
+ retry_suggestion: "string | null",
597
+ },
598
+ },
599
+ null,
600
+ 2,
601
+ );
602
+ },
603
+ });
604
+
605
+ /**
606
+ * Generate a strategy-specific planning prompt
607
+ *
608
+ * Higher-level than swarm_decompose - includes strategy selection and guidelines.
609
+ * Use this when you want the full planning experience with strategy-specific advice.
610
+ */
611
+ export const swarm_plan_prompt = tool({
612
+ description:
613
+ "Generate strategy-specific decomposition prompt. Auto-selects strategy or uses provided one. Queries CASS for similar tasks.",
614
+ args: {
615
+ task: tool.schema.string().min(1).describe("Task description to decompose"),
616
+ strategy: tool.schema
617
+ .enum(["file-based", "feature-based", "risk-based", "auto"])
618
+ .optional()
619
+ .describe("Decomposition strategy (default: auto-detect)"),
620
+ max_subtasks: tool.schema
621
+ .number()
622
+ .int()
623
+ .min(2)
624
+ .max(10)
625
+ .default(5)
626
+ .describe("Maximum number of subtasks (default: 5)"),
627
+ context: tool.schema
628
+ .string()
629
+ .optional()
630
+ .describe("Additional context (codebase info, constraints, etc.)"),
631
+ query_cass: tool.schema
632
+ .boolean()
633
+ .optional()
634
+ .describe("Query CASS for similar past tasks (default: true)"),
635
+ cass_limit: tool.schema
636
+ .number()
637
+ .int()
638
+ .min(1)
639
+ .max(10)
640
+ .optional()
641
+ .describe("Max CASS results to include (default: 3)"),
642
+ include_skills: tool.schema
643
+ .boolean()
644
+ .optional()
645
+ .describe("Include available skills in context (default: true)"),
646
+ },
647
+ async execute(args) {
648
+ // Import needed modules dynamically
649
+ const { selectStrategy, formatStrategyGuidelines, STRATEGIES } =
650
+ await import("./swarm-strategies");
651
+ const { formatMemoryQueryForDecomposition } = await import("./learning");
652
+ const { listSkills, getSkillsContextForSwarm, findRelevantSkills } =
653
+ await import("./skills");
654
+
655
+ // Select strategy
656
+ type StrategyName =
657
+ | "file-based"
658
+ | "feature-based"
659
+ | "risk-based"
660
+ | "research-based";
661
+ let selectedStrategy: StrategyName;
662
+ let strategyReasoning: string;
663
+
664
+ if (args.strategy && args.strategy !== "auto") {
665
+ selectedStrategy = args.strategy as StrategyName;
666
+ strategyReasoning = `User-specified strategy: ${selectedStrategy}`;
667
+ } else {
668
+ const selection = selectStrategy(args.task);
669
+ selectedStrategy = selection.strategy;
670
+ strategyReasoning = selection.reasoning;
671
+ }
672
+
673
+ // Fetch skills context
674
+ let skillsContext = "";
675
+ let skillsInfo: { included: boolean; count?: number; relevant?: string[] } =
676
+ {
677
+ included: false,
678
+ };
679
+
680
+ if (args.include_skills !== false) {
681
+ const allSkills = await listSkills();
682
+ if (allSkills.length > 0) {
683
+ skillsContext = await getSkillsContextForSwarm();
684
+ const relevantSkills = await findRelevantSkills(args.task);
685
+ skillsInfo = {
686
+ included: true,
687
+ count: allSkills.length,
688
+ relevant: relevantSkills,
689
+ };
690
+
691
+ // Add suggestion for relevant skills
692
+ if (relevantSkills.length > 0) {
693
+ skillsContext += `\n\n**Suggested skills for this task**: ${relevantSkills.join(", ")}`;
694
+ }
695
+ }
696
+ }
697
+
698
+ // Format strategy guidelines
699
+ const strategyGuidelines = formatStrategyGuidelines(selectedStrategy);
700
+
701
+ // Combine user context
702
+ const contextSection = args.context
703
+ ? `## Additional Context\n${args.context}`
704
+ : "## Additional Context\n(none provided)";
705
+
706
+ // Build the prompt (without CASS - we'll let the module handle that)
707
+ const prompt = STRATEGY_DECOMPOSITION_PROMPT.replace("{task}", args.task)
708
+ .replace("{strategy_guidelines}", strategyGuidelines)
709
+ .replace("{context_section}", contextSection)
710
+ .replace("{cass_history}", "") // Empty for now
711
+ .replace("{skills_context}", skillsContext || "")
712
+ .replace("{max_subtasks}", (args.max_subtasks ?? 5).toString());
713
+
714
+ return JSON.stringify(
715
+ {
716
+ prompt,
717
+ strategy: {
718
+ selected: selectedStrategy,
719
+ reasoning: strategyReasoning,
720
+ guidelines:
721
+ STRATEGIES[selectedStrategy as keyof typeof STRATEGIES].guidelines,
722
+ anti_patterns:
723
+ STRATEGIES[selectedStrategy as keyof typeof STRATEGIES]
724
+ .antiPatterns,
725
+ },
726
+ expected_schema: "BeadTree",
727
+ schema_hint: {
728
+ epic: { title: "string", description: "string?" },
729
+ subtasks: [
730
+ {
731
+ title: "string",
732
+ description: "string?",
733
+ files: "string[]",
734
+ dependencies: "number[]",
735
+ estimated_complexity: "1-5",
736
+ },
737
+ ],
738
+ },
739
+ validation_note:
740
+ "Parse agent response as JSON and validate with swarm_validate_decomposition",
741
+ skills: skillsInfo,
742
+ // Add semantic-memory query instruction
743
+ memory_query: formatMemoryQueryForDecomposition(args.task, 3),
744
+ },
745
+ null,
746
+ 2,
747
+ );
748
+ },
749
+ });
750
+
751
+ export const promptTools = {
752
+ swarm_subtask_prompt,
753
+ swarm_spawn_subtask,
754
+ swarm_evaluation_prompt,
755
+ swarm_plan_prompt,
756
+ };