opencode-swarm-plugin 0.32.0 → 0.33.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.
@@ -38,6 +38,15 @@ export declare const SUBTASK_PROMPT = "You are a swarm agent working on a subtas
38
38
  * Supports {error_context} placeholder for retry prompts.
39
39
  */
40
40
  export declare const SUBTASK_PROMPT_V2 = "You are a swarm agent working on: **{subtask_title}**\n\n## [IDENTITY]\nAgent: (assigned at spawn)\nCell: {bead_id}\nEpic: {epic_id}\n\n## [TASK]\n{subtask_description}\n\n## [FILES]\nReserved (exclusive):\n{file_list}\n\nOnly modify these files. Need others? Message the coordinator.\n\n## [CONTEXT]\n{shared_context}\n\n{compressed_context}\n\n{error_context}\n\n## [MANDATORY SURVIVAL CHECKLIST]\n\n**CRITICAL: Follow this checklist IN ORDER. Each step builds on the previous.**\n\n### Step 1: Initialize Coordination (REQUIRED - DO THIS FIRST)\n```\nswarmmail_init(project_path=\"{project_path}\", task_description=\"{bead_id}: {subtask_title}\")\n```\n\n**This registers you with the coordination system and enables:**\n- File reservation tracking\n- Inter-agent communication\n- Progress monitoring\n- Conflict detection\n\n**If you skip this step, your work will not be tracked and swarm_complete will fail.**\n\n### Step 2: \uD83E\uDDE0 Query Past Learnings (MANDATORY - BEFORE starting work)\n\n**\u26A0\uFE0F CRITICAL: ALWAYS query semantic memory BEFORE writing ANY code.**\n\n```\nsemantic-memory_find(query=\"<keywords from your task>\", limit=5, expand=true)\n```\n\n**Why this is MANDATORY:**\n- Past agents may have already solved your exact problem\n- Avoids repeating mistakes that wasted 30+ minutes before\n- Discovers project-specific patterns and gotchas\n- Finds known workarounds for tool/library quirks\n\n**Search Query Examples by Task Type:**\n\n- **Bug fix**: Use exact error message or \"<symptom> <component>\"\n- **New feature**: Search \"<domain concept> implementation pattern\"\n- **Refactor**: Query \"<pattern name> migration approach\"\n- **Integration**: Look for \"<library name> gotchas configuration\"\n- **Testing**: Find \"testing <component type> characterization tests\"\n- **Performance**: Search \"<technology> performance optimization\"\n\n**BEFORE you start coding:**\n1. Run semantic-memory_find with keywords from your task\n2. Read the results with expand=true for full content\n3. Check if any memory solves your problem or warns of pitfalls\n4. Adjust your approach based on past learnings\n\n**If you skip this step, you WILL waste time solving already-solved problems.**\n\n### Step 3: Load Relevant Skills (if available)\n```\nskills_list() # See what skills exist\nskills_use(name=\"<relevant-skill>\", context=\"<your task>\") # Load skill\n```\n\n**Common skill triggers:**\n- Writing tests? \u2192 `skills_use(name=\"testing-patterns\")`\n- Breaking dependencies? \u2192 `skills_use(name=\"testing-patterns\")`\n- Multi-agent coordination? \u2192 `skills_use(name=\"swarm-coordination\")`\n- Building a CLI? \u2192 `skills_use(name=\"cli-builder\")`\n\n### Step 4: Reserve Your Files (YOU reserve, not coordinator)\n```\nswarmmail_reserve(\n paths=[{file_list}],\n reason=\"{bead_id}: {subtask_title}\",\n exclusive=true\n)\n```\n\n**Workers reserve their own files.** This prevents edit conflicts with other agents.\n\n### Step 5: Do the Work (TDD MANDATORY)\n\n**Follow RED \u2192 GREEN \u2192 REFACTOR. No exceptions.**\n\n1. **RED**: Write a failing test that describes the expected behavior\n - Test MUST fail before you write implementation\n - If test passes immediately, your test is wrong\n \n2. **GREEN**: Write minimal code to make the test pass\n - Don't over-engineer - just make it green\n - Hardcode if needed, refactor later\n \n3. **REFACTOR**: Clean up while tests stay green\n - Run tests after every change\n - If tests break, undo and try again\n\n```bash\n# Run tests continuously\nbun test <your-test-file> --watch\n```\n\n**Why TDD?**\n- Catches bugs before they exist\n- Documents expected behavior\n- Enables fearless refactoring\n- Proves your code works\n\n### Step 6: Report Progress at Milestones\n```\nswarm_progress(\n project_key=\"{project_path}\",\n agent_name=\"<your-agent-name>\",\n bead_id=\"{bead_id}\",\n status=\"in_progress\",\n progress_percent=25, # or 50, 75\n message=\"<what you just completed>\"\n)\n```\n\n**Report at 25%, 50%, 75% completion.** This:\n- Triggers auto-checkpoint (saves context)\n- Keeps coordinator informed\n- Prevents silent failures\n\n### Step 7: Manual Checkpoint BEFORE Risky Operations\n```\nswarm_checkpoint(\n project_key=\"{project_path}\",\n agent_name=\"<your-agent-name>\",\n bead_id=\"{bead_id}\"\n)\n```\n\n**Call BEFORE:**\n- Large refactors\n- File deletions\n- Breaking API changes\n- Anything that might fail catastrophically\n\n**Checkpoints preserve context so you can recover if things go wrong.**\n\n### Step 8: \uD83D\uDCBE STORE YOUR LEARNINGS (if you discovered something)\n\n**If you learned it the hard way, STORE IT so the next agent doesn't have to.**\n\n```\nsemantic-memory_store(\n information=\"<what you learned, WHY it matters, how to apply it>\",\n tags=\"<domain, tech-stack, pattern-type>\"\n)\n```\n\n**MANDATORY Storage Triggers - Store when you:**\n- \uD83D\uDC1B **Solved a tricky bug** (>15min debugging) - include root cause + solution\n- \uD83D\uDCA1 **Discovered a project-specific pattern** - domain rules, business logic quirks\n- \u26A0\uFE0F **Found a tool/library gotcha** - API quirks, version-specific bugs, workarounds\n- \uD83D\uDEAB **Tried an approach that failed** - anti-patterns to avoid, why it didn't work\n- \uD83C\uDFD7\uFE0F **Made an architectural decision** - reasoning, alternatives considered, tradeoffs\n\n**What Makes a GOOD Memory:**\n\n\u2705 **GOOD** (actionable, explains WHY):\n```\n\"OAuth refresh tokens need 5min buffer before expiry to avoid race conditions.\nWithout buffer, token refresh can fail mid-request if expiry happens between\ncheck and use. Implemented with: if (expiresAt - Date.now() < 300000) refresh()\"\n```\n\n\u274C **BAD** (generic, no context):\n```\n\"Fixed the auth bug by adding a null check\"\n```\n\n**What NOT to Store:**\n- Generic knowledge that's in official documentation\n- Implementation details that change frequently\n- Vague descriptions without context (\"fixed the thing\")\n\n**The WHY matters more than the WHAT.** Future agents need context to apply your learning.\n\n### Step 9: Complete (REQUIRED - releases reservations)\n```\nswarm_complete(\n project_key=\"{project_path}\",\n agent_name=\"<your-agent-name>\",\n bead_id=\"{bead_id}\",\n summary=\"<what you accomplished>\",\n files_touched=[\"list\", \"of\", \"files\"]\n)\n```\n\n**This automatically:**\n- Runs UBS bug scan\n- Releases file reservations\n- Records learning signals\n- Notifies coordinator\n\n**DO NOT manually close the cell with hive_close.** Use swarm_complete.\n\n## [SWARM MAIL COMMUNICATION]\n\n### Check Inbox Regularly\n```\nswarmmail_inbox() # Check for coordinator messages\nswarmmail_read_message(message_id=N) # Read specific message\n```\n\n### When Blocked\n```\nswarmmail_send(\n to=[\"coordinator\"],\n subject=\"BLOCKED: {bead_id}\",\n body=\"<blocker description, what you need>\",\n importance=\"high\",\n thread_id=\"{epic_id}\"\n)\nhive_update(id=\"{bead_id}\", status=\"blocked\")\n```\n\n### Report Issues to Other Agents\n```\nswarmmail_send(\n to=[\"OtherAgent\", \"coordinator\"],\n subject=\"Issue in {bead_id}\",\n body=\"<describe problem, don't fix their code>\",\n thread_id=\"{epic_id}\"\n)\n```\n\n### Manual Release (if needed)\n```\nswarmmail_release() # Manually release reservations\n```\n\n**Note:** `swarm_complete` automatically releases reservations. Only use manual release if aborting work.\n\n## [OTHER TOOLS]\n### Hive - You Have Autonomy to File Issues\nYou can create new cells against this epic when you discover:\n- **Bugs**: Found a bug while working? File it.\n- **Tech debt**: Spotted something that needs cleanup? File it.\n- **Follow-up work**: Task needs more work than scoped? File a follow-up.\n- **Dependencies**: Need something from another agent? File and link it.\n\n```\nhive_create(\n title=\"<descriptive title>\",\n type=\"bug\", # or \"task\", \"chore\"\n priority=2,\n parent_id=\"{epic_id}\", # Links to this epic\n description=\"Found while working on {bead_id}: <details>\"\n)\n```\n\n**Don't silently ignore issues.** File them so they get tracked and addressed.\n\nOther cell operations:\n- hive_update(id, status) - Mark blocked if stuck\n- hive_query(status=\"open\") - See what else needs work\n\n### Skills\n- skills_list() - Discover available skills\n- skills_use(name) - Activate skill for specialized guidance\n- skills_create(name) - Create new skill (if you found a reusable pattern)\n\n## [CRITICAL REQUIREMENTS]\n\n**NON-NEGOTIABLE:**\n1. Step 1 (swarmmail_init) MUST be first - do it before anything else\n2. \uD83E\uDDE0 Step 2 (semantic-memory_find) MUST happen BEFORE starting work - query first, code second\n3. Step 4 (swarmmail_reserve) - YOU reserve files, not coordinator\n4. Step 6 (swarm_progress) - Report at milestones, don't work silently\n5. \uD83D\uDCBE Step 8 (semantic-memory_store) - If you learned something hard, STORE IT\n6. Step 9 (swarm_complete) - Use this to close, NOT hive_close\n\n**If you skip these steps:**\n- Your work won't be tracked (swarm_complete will fail)\n- \uD83D\uDD04 You'll waste time repeating already-solved problems (no semantic memory query)\n- Edit conflicts with other agents (no file reservation)\n- Lost work if you crash (no checkpoints)\n- \uD83D\uDD04 Future agents repeat YOUR mistakes (no learnings stored)\n\n**Memory is the swarm's collective intelligence. Query it. Feed it.**\n\nBegin now.";
41
+ /**
42
+ * Researcher prompt template for documentation discovery
43
+ *
44
+ * Spawned BEFORE decomposition to gather technology documentation.
45
+ * Researchers receive an EXPLICIT list of technologies to research from the coordinator.
46
+ * They dynamically discover WHAT TOOLS are available to fetch docs.
47
+ * Output: condensed summary for shared_context + detailed findings in semantic-memory.
48
+ */
49
+ export declare const RESEARCHER_PROMPT = "You are a swarm researcher gathering documentation for: **{research_id}**\n\n## [IDENTITY]\nAgent: (assigned at spawn)\nResearch Task: {research_id}\nEpic: {epic_id}\n\n## [MISSION]\nGather comprehensive documentation for the specified technologies to inform task decomposition.\n\n**COORDINATOR PROVIDED THESE TECHNOLOGIES TO RESEARCH:**\n{tech_stack}\n\nYou do NOT discover what to research - the coordinator already decided that.\nYou DO discover what TOOLS are available to fetch documentation.\n\n## [OUTPUT MODE]\n{check_upgrades}\n\n## [WORKFLOW]\n\n### Step 1: Initialize (MANDATORY FIRST)\n```\nswarmmail_init(project_path=\"{project_path}\", task_description=\"{research_id}: Documentation research\")\n```\n\n### Step 2: Discover Available Documentation Tools\nCheck what's available for fetching docs:\n- **next-devtools**: `nextjs_docs` for Next.js documentation\n- **context7**: Library documentation lookup (`use context7` in prompts)\n- **fetch**: General web fetching for official docs sites\n- **pdf-brain**: Internal knowledge base search\n\n**Don't assume** - check which tools exist in your environment.\n\n### Step 3: Read Installed Versions\nFor each technology in the tech stack:\n1. Check package.json (or equivalent) for installed version\n2. Record exact version numbers\n3. Note any version constraints (^, ~, etc.)\n\n### Step 4: Fetch Documentation\nFor EACH technology in the list:\n- Use the most appropriate tool (Next.js \u2192 nextjs_docs, libraries \u2192 context7, others \u2192 fetch)\n- Fetch documentation for the INSTALLED version (not latest, unless --check-upgrades)\n- Focus on: API changes, breaking changes, migration guides, best practices\n- Extract key patterns, gotchas, and compatibility notes\n\n**If --check-upgrades mode:**\n- ALSO fetch docs for the LATEST version\n- Compare installed vs latest\n- Note breaking changes, new features, migration complexity\n\n### Step 5: Store Detailed Findings\nFor EACH technology, store in semantic-memory:\n```\nsemantic-memory_store(\n information=\"<technology-name> <version>: <key patterns, gotchas, API changes, compatibility notes>\",\n tags=\"research, <tech-name>, documentation, {epic_id}\"\n)\n```\n\n**Why store individually?** Future agents can search by technology name.\n\n### Step 6: Broadcast Summary\nSend condensed findings to coordinator:\n```\nswarmmail_send(\n to=[\"coordinator\"],\n subject=\"Research Complete: {research_id}\",\n body=\"<brief summary - see semantic-memory for details>\",\n thread_id=\"{epic_id}\"\n)\n```\n\n### Step 7: Return Structured Output\nOutput JSON with:\n```json\n{\n \"technologies\": [\n {\n \"name\": \"string\",\n \"installed_version\": \"string\",\n \"latest_version\": \"string | null\", // Only if --check-upgrades\n \"key_patterns\": [\"string\"],\n \"gotchas\": [\"string\"],\n \"breaking_changes\": [\"string\"], // Only if --check-upgrades\n \"memory_id\": \"string\" // ID of semantic-memory entry\n }\n ],\n \"summary\": \"string\" // Condensed summary for shared_context\n}\n```\n\n## [CRITICAL REQUIREMENTS]\n\n**NON-NEGOTIABLE:**\n1. Step 1 (swarmmail_init) MUST be first\n2. Research ONLY the technologies the coordinator specified\n3. Fetch docs for INSTALLED versions (unless --check-upgrades)\n4. Store detailed findings in semantic-memory (one per technology)\n5. Return condensed summary for coordinator (full details in memory)\n6. Use appropriate doc tools (nextjs_docs for Next.js, context7 for libraries, etc.)\n\n**Output goes TWO places:**\n- **semantic-memory**: Detailed findings (searchable by future agents)\n- **Return JSON**: Condensed summary (for coordinator's shared_context)\n\nBegin research now.";
41
50
  /**
42
51
  * Coordinator post-worker checklist - MANDATORY review loop
43
52
  *
@@ -51,6 +60,16 @@ export declare const COORDINATOR_POST_WORKER_CHECKLIST = "\n## \u26A0\uFE0F MAND
51
60
  * Agents use this to assess their work quality before marking complete.
52
61
  */
53
62
  export declare const EVALUATION_PROMPT = "Evaluate the work completed for this subtask.\n\n## Subtask\n**Cell ID**: {bead_id}\n**Title**: {subtask_title}\n\n## Files Modified\n{files_touched}\n\n## Evaluation Criteria\n\nFor each criterion, assess passed/failed and provide brief feedback:\n\n1. **type_safe**: Code compiles without TypeScript errors\n2. **no_bugs**: No obvious bugs, edge cases handled\n3. **patterns**: Follows existing codebase patterns and conventions\n4. **readable**: Code is clear and maintainable\n\n## Response Format\n\n```json\n{\n \"passed\": boolean, // Overall pass/fail\n \"criteria\": {\n \"type_safe\": { \"passed\": boolean, \"feedback\": string },\n \"no_bugs\": { \"passed\": boolean, \"feedback\": string },\n \"patterns\": { \"passed\": boolean, \"feedback\": string },\n \"readable\": { \"passed\": boolean, \"feedback\": string }\n },\n \"overall_feedback\": string,\n \"retry_suggestion\": string | null // If failed, what to fix\n}\n```\n\nIf any criterion fails, the overall evaluation fails and retry_suggestion \nshould describe what needs to be fixed.";
63
+ /**
64
+ * Format the researcher prompt for a documentation research task
65
+ */
66
+ export declare function formatResearcherPrompt(params: {
67
+ research_id: string;
68
+ epic_id: string;
69
+ tech_stack: string[];
70
+ project_path: string;
71
+ check_upgrades: boolean;
72
+ }): string;
54
73
  /**
55
74
  * Format the V2 subtask prompt for a specific agent
56
75
  */
@@ -155,6 +174,29 @@ export declare const swarm_spawn_subtask: {
155
174
  model?: string | undefined;
156
175
  }, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
157
176
  };
177
+ /**
178
+ * Prepare a researcher task for spawning with Task tool
179
+ *
180
+ * Generates a prompt that tells the researcher to fetch documentation for specific technologies.
181
+ * Returns JSON that can be directly used with Task tool.
182
+ */
183
+ export declare const swarm_spawn_researcher: {
184
+ description: string;
185
+ args: {
186
+ research_id: import("zod").ZodString;
187
+ epic_id: import("zod").ZodString;
188
+ tech_stack: import("zod").ZodArray<import("zod").ZodString>;
189
+ project_path: import("zod").ZodString;
190
+ check_upgrades: import("zod").ZodOptional<import("zod").ZodBoolean>;
191
+ };
192
+ execute(args: {
193
+ research_id: string;
194
+ epic_id: string;
195
+ tech_stack: string[];
196
+ project_path: string;
197
+ check_upgrades?: boolean | undefined;
198
+ }, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
199
+ };
158
200
  /**
159
201
  * Generate self-evaluation prompt
160
202
  */
@@ -260,6 +302,23 @@ export declare const promptTools: {
260
302
  model?: string | undefined;
261
303
  }, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
262
304
  };
305
+ swarm_spawn_researcher: {
306
+ description: string;
307
+ args: {
308
+ research_id: import("zod").ZodString;
309
+ epic_id: import("zod").ZodString;
310
+ tech_stack: import("zod").ZodArray<import("zod").ZodString>;
311
+ project_path: import("zod").ZodString;
312
+ check_upgrades: import("zod").ZodOptional<import("zod").ZodBoolean>;
313
+ };
314
+ execute(args: {
315
+ research_id: string;
316
+ epic_id: string;
317
+ tech_stack: string[];
318
+ project_path: string;
319
+ check_upgrades?: boolean | undefined;
320
+ }, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
321
+ };
263
322
  swarm_evaluation_prompt: {
264
323
  description: string;
265
324
  args: {
@@ -1 +1 @@
1
- {"version":3,"file":"swarm-prompts.d.ts","sourceRoot":"","sources":["../src/swarm-prompts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AASH;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,s6EAkET,CAAC;AAEzB;;GAEG;AACH,eAAO,MAAM,6BAA6B,mxDAyDlB,CAAC;AAEzB;;;;;GAKG;AACH,eAAO,MAAM,cAAc,mkFAgFK,CAAC;AAEjC;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,mzSA0SnB,CAAC;AAEZ;;;;;GAKG;AACH,eAAO,MAAM,iCAAiC,i4CAmD7C,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,8jCAmCU,CAAC;AAMzC;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE;QACjB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;QAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;KAC5B,CAAC;CACH,GAAG,MAAM,CA2ET;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,GAAG,MAAM,CAUT;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB,GAAG,MAAM,CAMT;AAMD;;GAEG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;CAoC/B,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+F9B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;CAoClC,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;CAwI5B,CAAC;AAEH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAKvB,CAAC"}
1
+ {"version":3,"file":"swarm-prompts.d.ts","sourceRoot":"","sources":["../src/swarm-prompts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AASH;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,s6EAkET,CAAC;AAEzB;;GAEG;AACH,eAAO,MAAM,6BAA6B,mxDAyDlB,CAAC;AAEzB;;;;;GAKG;AACH,eAAO,MAAM,cAAc,mkFAgFK,CAAC;AAEjC;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,mzSA0SnB,CAAC;AAEZ;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,4pHA4GV,CAAC;AAErB;;;;;GAKG;AACH,eAAO,MAAM,iCAAiC,i4CAmD7C,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,8jCAmCU,CAAC;AAMzC;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE;IAC7C,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,OAAO,CAAC;CACzB,GAAG,MAAM,CAaT;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE;QACjB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;QAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;KAC5B,CAAC;CACH,GAAG,MAAM,CA2ET;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,GAAG,MAAM,CAUT;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB,GAAG,MAAM,CAMT;AAMD;;GAEG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;CAoC/B,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+F9B,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;CAsDjC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;CAoClC,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;CAwI5B,CAAC;AAEH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAMvB,CAAC"}
package/dist/swarm.d.ts CHANGED
@@ -360,6 +360,23 @@ export declare const swarmTools: {
360
360
  model?: string | undefined;
361
361
  }, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
362
362
  };
363
+ swarm_spawn_researcher: {
364
+ description: string;
365
+ args: {
366
+ research_id: import("zod").ZodString;
367
+ epic_id: import("zod").ZodString;
368
+ tech_stack: import("zod").ZodArray<import("zod").ZodString>;
369
+ project_path: import("zod").ZodString;
370
+ check_upgrades: import("zod").ZodOptional<import("zod").ZodBoolean>;
371
+ };
372
+ execute(args: {
373
+ research_id: string;
374
+ epic_id: string;
375
+ tech_stack: string[];
376
+ project_path: string;
377
+ check_upgrades?: boolean | undefined;
378
+ }, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
379
+ };
363
380
  swarm_evaluation_prompt: {
364
381
  description: string;
365
382
  args: {
@@ -1 +1 @@
1
- {"version":3,"file":"swarm.d.ts","sourceRoot":"","sources":["../src/swarm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AAQpC;;;GAGG;AACH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAKtB,CAAC"}
1
+ {"version":3,"file":"swarm.d.ts","sourceRoot":"","sources":["../src/swarm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AAQpC;;;GAGG;AACH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAKtB,CAAC"}
@@ -905,6 +905,252 @@ interface SwarmDetection {
905
905
  reasons: string[];
906
906
  }
907
907
 
908
+ /**
909
+ * Structured state snapshot for LLM-powered compaction
910
+ *
911
+ * This is passed to the lite model to generate a continuation prompt
912
+ * with concrete data instead of just instructions.
913
+ */
914
+ interface SwarmStateSnapshot {
915
+ sessionID: string;
916
+ detection: {
917
+ confidence: "high" | "medium" | "low" | "none";
918
+ reasons: string[];
919
+ };
920
+ epic?: {
921
+ id: string;
922
+ title: string;
923
+ status: string;
924
+ subtasks: Array<{
925
+ id: string;
926
+ title: string;
927
+ status: "open" | "in_progress" | "blocked" | "closed";
928
+ files: string[];
929
+ assignedTo?: string;
930
+ }>;
931
+ };
932
+ messages: Array<{
933
+ from: string;
934
+ to: string[];
935
+ subject: string;
936
+ body: string;
937
+ timestamp: number;
938
+ importance?: string;
939
+ }>;
940
+ reservations: Array<{
941
+ agent: string;
942
+ paths: string[];
943
+ exclusive: boolean;
944
+ expiresAt: number;
945
+ }>;
946
+ }
947
+
948
+ /**
949
+ * Query actual swarm state using spawn (like detectSwarm does)
950
+ *
951
+ * Returns structured snapshot of current state for LLM compaction.
952
+ * Shells out to swarm CLI to get real data.
953
+ */
954
+ async function querySwarmState(sessionID: string): Promise<SwarmStateSnapshot> {
955
+ try {
956
+ // Query cells via swarm CLI
957
+ const cellsResult = await new Promise<{ exitCode: number; stdout: string }>(
958
+ (resolve) => {
959
+ const proc = spawn(SWARM_CLI, ["tool", "hive_query"], {
960
+ cwd: projectDirectory,
961
+ stdio: ["ignore", "pipe", "pipe"],
962
+ });
963
+ let stdout = "";
964
+ proc.stdout.on("data", (d) => {
965
+ stdout += d;
966
+ });
967
+ proc.on("close", (exitCode) =>
968
+ resolve({ exitCode: exitCode ?? 1, stdout }),
969
+ );
970
+ },
971
+ );
972
+
973
+ const cells =
974
+ cellsResult.exitCode === 0 ? JSON.parse(cellsResult.stdout) : [];
975
+
976
+ // Find active epic (first unclosed epic with subtasks)
977
+ const openEpics = cells.filter(
978
+ (c: { type?: string; status: string }) =>
979
+ c.type === "epic" && c.status !== "closed",
980
+ );
981
+ const epic = openEpics[0];
982
+
983
+ // Get subtasks if we have an epic
984
+ const subtasks =
985
+ epic && epic.id
986
+ ? cells.filter(
987
+ (c: { parent_id?: string }) => c.parent_id === epic.id,
988
+ )
989
+ : [];
990
+
991
+ // TODO: Query swarm mail for messages and reservations
992
+ // For MVP, use empty arrays - the fallback chain handles this
993
+ const messages: SwarmStateSnapshot["messages"] = [];
994
+ const reservations: SwarmStateSnapshot["reservations"] = [];
995
+
996
+ // Run detection for confidence
997
+ const detection = await detectSwarm();
998
+
999
+ return {
1000
+ sessionID,
1001
+ detection: {
1002
+ confidence: detection.confidence,
1003
+ reasons: detection.reasons,
1004
+ },
1005
+ epic: epic
1006
+ ? {
1007
+ id: epic.id,
1008
+ title: epic.title,
1009
+ status: epic.status,
1010
+ subtasks: subtasks.map((s: {
1011
+ id: string;
1012
+ title: string;
1013
+ status: string;
1014
+ files?: string[];
1015
+ }) => ({
1016
+ id: s.id,
1017
+ title: s.title,
1018
+ status: s.status as "open" | "in_progress" | "blocked" | "closed",
1019
+ files: s.files || [],
1020
+ })),
1021
+ }
1022
+ : undefined,
1023
+ messages,
1024
+ reservations,
1025
+ };
1026
+ } catch (err) {
1027
+ // If query fails, return minimal snapshot
1028
+ const detection = await detectSwarm();
1029
+ return {
1030
+ sessionID,
1031
+ detection: {
1032
+ confidence: detection.confidence,
1033
+ reasons: detection.reasons,
1034
+ },
1035
+ messages: [],
1036
+ reservations: [],
1037
+ };
1038
+ }
1039
+ }
1040
+
1041
+ /**
1042
+ * Generate compaction prompt using LLM
1043
+ *
1044
+ * Shells out to `opencode run -m <liteModel>` with structured state.
1045
+ * Returns markdown continuation prompt or null on failure.
1046
+ *
1047
+ * Timeout: 30 seconds
1048
+ */
1049
+ async function generateCompactionPrompt(
1050
+ snapshot: SwarmStateSnapshot,
1051
+ ): Promise<string | null> {
1052
+ try {
1053
+ const liteModel =
1054
+ process.env.OPENCODE_LITE_MODEL || "claude-3-5-haiku-20241022";
1055
+
1056
+ const promptText = `You are generating a continuation prompt for a compacted swarm coordination session.
1057
+
1058
+ Analyze this swarm state and generate a structured markdown prompt that will be given to the resumed session:
1059
+
1060
+ ${JSON.stringify(snapshot, null, 2)}
1061
+
1062
+ Generate a prompt following this structure:
1063
+
1064
+ # 🐝 Swarm Continuation - [Epic Title or "Unknown"]
1065
+
1066
+ You are resuming coordination of an active swarm that was interrupted by context compaction.
1067
+
1068
+ ## Epic State
1069
+
1070
+ **ID:** [epic ID or "Unknown"]
1071
+ **Title:** [epic title or "No active epic"]
1072
+ **Status:** [X/Y subtasks complete]
1073
+ **Project:** ${projectDirectory}
1074
+
1075
+ ## Subtask Status
1076
+
1077
+ ### ✅ Completed (N)
1078
+ [List completed subtasks with IDs]
1079
+
1080
+ ### 🚧 In Progress (N)
1081
+ [List in-progress subtasks with IDs, files, agents if known]
1082
+
1083
+ ### 🚫 Blocked (N)
1084
+ [List blocked subtasks]
1085
+
1086
+ ### ⏳ Pending (N)
1087
+ [List pending subtasks]
1088
+
1089
+ ## Next Actions (IMMEDIATE)
1090
+
1091
+ [List 3-5 concrete actions with actual commands, using real IDs from the state]
1092
+
1093
+ ## Coordinator Reminders
1094
+
1095
+ - **You are the coordinator** - Don't wait for instructions, orchestrate
1096
+ - **Monitor actively** - Check messages every ~10 minutes
1097
+ - **Unblock aggressively** - Resolve dependencies immediately
1098
+ - **Review thoroughly** - 3-strike rule enforced
1099
+ - **Ship it** - When all subtasks done, close the epic
1100
+
1101
+ Keep the prompt concise but actionable. Use actual data from the snapshot, not placeholders.`;
1102
+
1103
+ const result = await new Promise<{ exitCode: number; stdout: string; stderr: string }>(
1104
+ (resolve, reject) => {
1105
+ const proc = spawn("opencode", ["run", "-m", liteModel, "--", promptText], {
1106
+ cwd: projectDirectory,
1107
+ stdio: ["ignore", "pipe", "pipe"],
1108
+ timeout: 30000, // 30 second timeout
1109
+ });
1110
+
1111
+ let stdout = "";
1112
+ let stderr = "";
1113
+
1114
+ proc.stdout.on("data", (d) => {
1115
+ stdout += d;
1116
+ });
1117
+ proc.stderr.on("data", (d) => {
1118
+ stderr += d;
1119
+ });
1120
+
1121
+ proc.on("close", (exitCode) => {
1122
+ resolve({ exitCode: exitCode ?? 1, stdout, stderr });
1123
+ });
1124
+
1125
+ proc.on("error", (err) => {
1126
+ reject(err);
1127
+ });
1128
+
1129
+ // Timeout handling
1130
+ setTimeout(() => {
1131
+ proc.kill("SIGTERM");
1132
+ reject(new Error("LLM compaction timeout (30s)"));
1133
+ }, 30000);
1134
+ },
1135
+ );
1136
+
1137
+ if (result.exitCode !== 0) {
1138
+ console.error(
1139
+ "[Swarm Compaction] opencode run failed:",
1140
+ result.stderr,
1141
+ );
1142
+ return null;
1143
+ }
1144
+
1145
+ // Extract the prompt from stdout (LLM may wrap in markdown)
1146
+ const prompt = result.stdout.trim();
1147
+ return prompt.length > 0 ? prompt : null;
1148
+ } catch (err) {
1149
+ console.error("[Swarm Compaction] LLM generation failed:", err);
1150
+ return null;
1151
+ }
1152
+ }
1153
+
908
1154
  /**
909
1155
  * Check for swarm sign - evidence a swarm passed through
910
1156
  *
@@ -1124,11 +1370,16 @@ Include this in your summary:
1124
1370
  "This is an active swarm. Check swarm_status and swarmmail_inbox immediately."
1125
1371
  `;
1126
1372
 
1127
- // Extended hooks type to include experimental compaction hook
1373
+ // Extended hooks type to include experimental compaction hook with new prompt API
1374
+ type CompactionOutput = {
1375
+ context: string[];
1376
+ prompt?: string; // NEW API from OpenCode PR #5907
1377
+ };
1378
+
1128
1379
  type ExtendedHooks = Hooks & {
1129
1380
  "experimental.session.compacting"?: (
1130
1381
  input: { sessionID: string },
1131
- output: { context: string[] },
1382
+ output: CompactionOutput,
1132
1383
  ) => Promise<void>;
1133
1384
  };
1134
1385
 
@@ -1201,23 +1452,61 @@ export const SwarmPlugin: Plugin = async (
1201
1452
  skills_execute,
1202
1453
  },
1203
1454
 
1204
- // Swarm-aware compaction hook - injects context based on detection confidence
1455
+ // Swarm-aware compaction hook with LLM-powered continuation prompts
1456
+ // Three-level fallback chain: LLM → static context → detection fallback → none
1205
1457
  "experimental.session.compacting": async (
1206
- _input: { sessionID: string },
1207
- output: { context: string[] },
1458
+ input: { sessionID: string },
1459
+ output: CompactionOutput,
1208
1460
  ) => {
1209
1461
  const detection = await detectSwarm();
1210
1462
 
1211
1463
  if (detection.confidence === "high" || detection.confidence === "medium") {
1212
- // Definite or probable swarm - inject full context
1464
+ // Definite or probable swarm - try LLM-powered compaction
1465
+ try {
1466
+ // Level 1: Query actual state
1467
+ const snapshot = await querySwarmState(input.sessionID);
1468
+
1469
+ // Level 2: Generate prompt with LLM
1470
+ const llmPrompt = await generateCompactionPrompt(snapshot);
1471
+
1472
+ if (llmPrompt) {
1473
+ // SUCCESS: Use LLM-generated prompt
1474
+ const header = `[Swarm compaction: LLM-generated, ${detection.reasons.join(", ")}]\n\n`;
1475
+
1476
+ // Progressive enhancement: use new API if available
1477
+ if ("prompt" in output) {
1478
+ output.prompt = header + llmPrompt;
1479
+ } else {
1480
+ output.context.push(header + llmPrompt);
1481
+ }
1482
+
1483
+ console.log(
1484
+ "[Swarm Compaction] Using LLM-generated continuation prompt",
1485
+ );
1486
+ return;
1487
+ }
1488
+
1489
+ // LLM failed, fall through to static prompt
1490
+ console.log(
1491
+ "[Swarm Compaction] LLM generation returned null, using static prompt",
1492
+ );
1493
+ } catch (err) {
1494
+ // LLM failed, fall through to static prompt
1495
+ console.error(
1496
+ "[Swarm Compaction] LLM generation failed, using static prompt:",
1497
+ err,
1498
+ );
1499
+ }
1500
+
1501
+ // Level 3: Fall back to static context
1213
1502
  const header = `[Swarm detected: ${detection.reasons.join(", ")}]\n\n`;
1214
1503
  output.context.push(header + SWARM_COMPACTION_CONTEXT);
1215
1504
  } else if (detection.confidence === "low") {
1216
- // Possible swarm - inject fallback detection prompt
1505
+ // Level 4: Possible swarm - inject fallback detection prompt
1217
1506
  const header = `[Possible swarm: ${detection.reasons.join(", ")}]\n\n`;
1218
1507
  output.context.push(header + SWARM_DETECTION_FALLBACK);
1219
1508
  }
1220
- // confidence === "none" - no injection, probably not a swarm
1509
+ // Level 5: confidence === "none" - no injection, probably not a swarm
1221
1510
  },
1222
1511
  };
1223
1512
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm-plugin",
3
- "version": "0.32.0",
3
+ "version": "0.33.0",
4
4
  "description": "Multi-agent swarm coordination for OpenCode with learning capabilities, beads integration, and Agent Mail",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -39,7 +39,8 @@
39
39
  "gray-matter": "^4.0.3",
40
40
  "ioredis": "^5.4.1",
41
41
  "minimatch": "^10.1.1",
42
- "swarm-mail": "1.3.0",
42
+ "swarm-mail": "1.4.0",
43
+ "yaml": "^2.8.2",
43
44
  "zod": "4.1.8"
44
45
  },
45
46
  "devDependencies": {
package/src/index.ts CHANGED
@@ -47,6 +47,8 @@ import { repoCrawlTools } from "./repo-crawl";
47
47
  import { skillsTools, setSkillsProjectDirectory } from "./skills";
48
48
  import { mandateTools } from "./mandates";
49
49
  import { memoryTools } from "./memory-tools";
50
+ import { observabilityTools } from "./observability-tools";
51
+ import { researchTools } from "./swarm-research";
50
52
  import {
51
53
  guardrailOutput,
52
54
  DEFAULT_GUARDRAIL_CONFIG,
@@ -154,7 +156,7 @@ export const SwarmPlugin: Plugin = async (
154
156
  * - mandate:file, mandate:vote, mandate:query, etc.
155
157
  * - semantic-memory:store, semantic-memory:find, semantic-memory:get, etc.
156
158
  */
157
- tool: {
159
+ tool: {
158
160
  ...hiveTools,
159
161
  ...swarmMailTools,
160
162
  ...structuredTools,
@@ -165,6 +167,8 @@ export const SwarmPlugin: Plugin = async (
165
167
  ...skillsTools,
166
168
  ...mandateTools,
167
169
  ...memoryTools,
170
+ ...observabilityTools,
171
+ ...researchTools,
168
172
  },
169
173
 
170
174
  /**
@@ -679,3 +683,23 @@ export {
679
683
  type OperationResult,
680
684
  } from "./memory-tools";
681
685
  export type { Memory, SearchResult, SearchOptions } from "swarm-mail";
686
+
687
+ /**
688
+ * Re-export swarm-research module
689
+ *
690
+ * Includes:
691
+ * - discoverDocTools - Discover available documentation tools
692
+ * - getInstalledVersions - Get installed package versions from lockfile
693
+ * - researchTools - Plugin tools for tool discovery and version detection
694
+ *
695
+ * Types:
696
+ * - DiscoveredTool - Tool discovery result interface
697
+ * - VersionInfo - Package version information
698
+ */
699
+ export {
700
+ discoverDocTools,
701
+ getInstalledVersions,
702
+ researchTools,
703
+ type DiscoveredTool,
704
+ type VersionInfo,
705
+ } from "./swarm-research";