opencode-swarm 3.0.0 → 3.1.1

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/README.md CHANGED
@@ -245,6 +245,59 @@ Swarm lets you mix models strategically:
245
245
 
246
246
  ---
247
247
 
248
+ ## Multiple Swarms
249
+
250
+ Run different model configurations simultaneously. Perfect for:
251
+ - **Cloud vs Local**: Premium cloud models for critical work, local models for quick tasks
252
+ - **Fast vs Quality**: Quick iterations with fast models, careful work with expensive ones
253
+ - **Cost Tiers**: Cheap models for exploration, premium for implementation
254
+
255
+ ### Configuration
256
+
257
+ ```json
258
+ {
259
+ "swarms": {
260
+ "cloud": {
261
+ "name": "Cloud",
262
+ "agents": {
263
+ "architect": { "model": "anthropic/claude-sonnet-4-5" },
264
+ "coder": { "model": "anthropic/claude-sonnet-4-5" },
265
+ "_sme": { "model": "google/gemini-2.0-flash" },
266
+ "_qa": { "model": "openai/gpt-4o" }
267
+ }
268
+ },
269
+ "local": {
270
+ "name": "Local",
271
+ "agents": {
272
+ "architect": { "model": "ollama/qwen2.5:32b" },
273
+ "coder": { "model": "ollama/qwen2.5:32b" },
274
+ "_sme": { "model": "ollama/qwen2.5:14b" },
275
+ "_qa": { "model": "ollama/qwen2.5:14b" }
276
+ }
277
+ }
278
+ }
279
+ }
280
+ ```
281
+
282
+ ### What Gets Created
283
+
284
+ | Swarm | Agents |
285
+ |-------|--------|
286
+ | `cloud` (default) | `architect`, `explorer`, `coder`, `sme_*`, etc. |
287
+ | `local` | `local_architect`, `local_explorer`, `local_coder`, `local_sme_*`, etc. |
288
+
289
+ The first swarm (or one named "default") creates unprefixed agents. Additional swarms prefix all agent names.
290
+
291
+ ### Usage
292
+
293
+ In OpenCode, you'll see multiple architects to choose from:
294
+ - `architect` - Cloud swarm (default)
295
+ - `local_architect` - Local swarm
296
+
297
+ Each architect automatically delegates to its own swarm's agents.
298
+
299
+ ---
300
+
248
301
  ## Installation
249
302
 
250
303
  ```bash
@@ -8,7 +8,6 @@ export type { AgentDefinition } from './architect';
8
8
  export declare function createAgents(config?: PluginConfig): AgentDefinition[];
9
9
  /**
10
10
  * Get agent configurations formatted for the OpenCode SDK.
11
- * Converts agent definitions to SDK config format and applies mode metadata.
12
11
  */
13
12
  export declare function getAgentConfigs(config?: PluginConfig): Record<string, SDKAgentConfig>;
14
13
  export { createArchitectAgent } from './architect';
@@ -1,5 +1,5 @@
1
1
  export { ALL_AGENT_NAMES, ALL_SUBAGENT_NAMES, CATEGORY_PREFIXES, DEFAULT_MODELS, DOMAIN_PATTERNS, ORCHESTRATOR_NAME, PIPELINE_AGENTS, QA_AGENTS, SME_AGENTS, domainToAgentName, isQAAgent, isSMEAgent, isSubagent, } from './constants';
2
2
  export type { AgentName, PipelineAgentName, QAAgentName, SMEAgentName, } from './constants';
3
- export { AgentOverrideConfigSchema, PluginConfigSchema, } from './schema';
4
- export type { AgentOverrideConfig, PluginConfig, } from './schema';
3
+ export { AgentOverrideConfigSchema, PluginConfigSchema, SwarmConfigSchema, } from './schema';
4
+ export type { AgentOverrideConfig, PluginConfig, SwarmConfig, } from './schema';
5
5
  export { loadAgentPrompt, loadPluginConfig, } from './loader';
@@ -5,12 +5,29 @@ export declare const AgentOverrideConfigSchema: z.ZodObject<{
5
5
  disabled: z.ZodOptional<z.ZodBoolean>;
6
6
  }, z.core.$strip>;
7
7
  export type AgentOverrideConfig = z.infer<typeof AgentOverrideConfigSchema>;
8
+ export declare const SwarmConfigSchema: z.ZodObject<{
9
+ name: z.ZodOptional<z.ZodString>;
10
+ agents: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
11
+ model: z.ZodOptional<z.ZodString>;
12
+ temperature: z.ZodOptional<z.ZodNumber>;
13
+ disabled: z.ZodOptional<z.ZodBoolean>;
14
+ }, z.core.$strip>>>;
15
+ }, z.core.$strip>;
16
+ export type SwarmConfig = z.infer<typeof SwarmConfigSchema>;
8
17
  export declare const PluginConfigSchema: z.ZodObject<{
9
18
  agents: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
10
19
  model: z.ZodOptional<z.ZodString>;
11
20
  temperature: z.ZodOptional<z.ZodNumber>;
12
21
  disabled: z.ZodOptional<z.ZodBoolean>;
13
22
  }, z.core.$strip>>>;
23
+ swarms: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
24
+ name: z.ZodOptional<z.ZodString>;
25
+ agents: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
26
+ model: z.ZodOptional<z.ZodString>;
27
+ temperature: z.ZodOptional<z.ZodNumber>;
28
+ disabled: z.ZodOptional<z.ZodBoolean>;
29
+ }, z.core.$strip>>>;
30
+ }, z.core.$strip>>>;
14
31
  max_iterations: z.ZodDefault<z.ZodNumber>;
15
32
  multi_domain_sme: z.ZodDefault<z.ZodBoolean>;
16
33
  auto_detect_domains: z.ZodDefault<z.ZodBoolean>;
package/dist/index.js CHANGED
@@ -213,9 +213,6 @@ function isSMEAgent(name) {
213
213
  function isQAAgent(name) {
214
214
  return QA_AGENTS.includes(name);
215
215
  }
216
- function isSubagent(name) {
217
- return ALL_SUBAGENT_NAMES.includes(name);
218
- }
219
216
  // node_modules/zod/v4/classic/external.js
220
217
  var exports_external = {};
221
218
  __export(exports_external, {
@@ -13754,8 +13751,13 @@ var AgentOverrideConfigSchema = exports_external.object({
13754
13751
  temperature: exports_external.number().min(0).max(2).optional(),
13755
13752
  disabled: exports_external.boolean().optional()
13756
13753
  });
13754
+ var SwarmConfigSchema = exports_external.object({
13755
+ name: exports_external.string().optional(),
13756
+ agents: exports_external.record(exports_external.string(), AgentOverrideConfigSchema).optional()
13757
+ });
13757
13758
  var PluginConfigSchema = exports_external.object({
13758
13759
  agents: exports_external.record(exports_external.string(), AgentOverrideConfigSchema).optional(),
13760
+ swarms: exports_external.record(exports_external.string(), SwarmConfigSchema).optional(),
13759
13761
  max_iterations: exports_external.number().min(1).max(10).default(5),
13760
13762
  multi_domain_sme: exports_external.boolean().default(true),
13761
13763
  auto_detect_domains: exports_external.boolean().default(true),
@@ -13846,47 +13848,36 @@ function loadAgentPrompt(agentName) {
13846
13848
  return result;
13847
13849
  }
13848
13850
  // src/agents/architect.ts
13849
- var ARCHITECT_PROMPT = `You are Architect - an AI orchestrator that coordinates specialist LLM agents to deliver production-quality code through structured, phased execution.
13851
+ var ARCHITECT_PROMPT = `You are Architect - the orchestrator of a multi-agent coding swarm.
13850
13852
 
13851
- **CRITICAL: YOU ARE ORCHESTRATING OTHER LLMs**
13852
- The agents you delegate to are separate LLM instances, typically smaller/faster models. They cannot read your mind or infer context. Your delegations must be:
13853
- - **Explicit**: State exactly what you want, not what you assume they know
13854
- - **Structured**: Use clear sections, numbered steps, specific file paths
13855
- - **Constrained**: Tell them what NOT to do to prevent scope creep
13856
- - **Self-contained**: Include all context they need in the delegation message
13853
+ ## HOW TO DELEGATE
13857
13854
 
13858
- **CRITICAL: SERIAL EXECUTION ONLY**
13859
- You MUST call agents ONE AT A TIME. After each delegation:
13860
- 1. Send to ONE agent
13861
- 2. STOP and wait for response
13862
- 3. Only then proceed to next agent
13863
- NEVER delegate to multiple agents in the same message.
13855
+ To delegate, mention the agent with @ and provide instructions:
13856
+ "Scanning codebase via @explorer..."
13857
+ "Consulting @sme_powershell for module patterns..."
13858
+ "Implementing via @coder..."
13859
+
13860
+ **You MUST delegate to agents. Do not implement code yourself unless delegation fails.**
13864
13861
 
13865
13862
  ---
13866
13863
 
13867
- ## AGENTS
13864
+ ## YOUR AGENTS
13865
+
13866
+ **Discovery:**
13867
+ @explorer - Scans codebase, returns structure/languages/key files
13868
13868
 
13869
- @explorer - Fast codebase discovery and summarization
13870
- @sme_windows - Windows OS, registry, services, WMI/CIM
13871
- @sme_powershell - PowerShell scripting, cmdlets, modules
13872
- @sme_python - Python ecosystem, libraries, patterns
13873
- @sme_oracle - Oracle Database, SQL/PLSQL
13874
- @sme_network - TCP/IP, firewalls, DNS, TLS
13875
- @sme_security - STIG, hardening, CVE, PKI
13876
- @sme_linux - Linux, systemd, package management
13877
- @sme_vmware - vSphere, ESXi, PowerCLI
13878
- @sme_azure - Azure, Entra ID, ARM/Bicep
13879
- @sme_active_directory - AD, LDAP, Group Policy, Kerberos
13880
- @sme_ui_ux - UI/UX design, accessibility
13881
- @sme_web - Flutter, React, Vue, Angular, JS/TS, HTML/CSS
13882
- @sme_database - SQL Server, PostgreSQL, MySQL, MongoDB, Redis
13883
- @sme_devops - Docker, Kubernetes, CI/CD, Terraform
13884
- @sme_api - REST, GraphQL, OAuth, JWT
13869
+ **Domain Experts (SMEs) - Advisory only, cannot write code:**
13870
+ @sme_windows @sme_powershell @sme_python @sme_oracle @sme_network
13871
+ @sme_security @sme_linux @sme_vmware @sme_azure @sme_active_directory
13872
+ @sme_ui_ux @sme_web @sme_database @sme_devops @sme_api
13885
13873
 
13886
- @coder - Implementation specialist
13887
- @security_reviewer - Security vulnerability assessment
13888
- @auditor - Code correctness verification
13889
- @test_engineer - Test case generation
13874
+ **Implementation:**
13875
+ @coder - Writes code (ONE task at a time)
13876
+ @test_engineer - Generates tests
13877
+
13878
+ **Quality Assurance - Review only, cannot write code:**
13879
+ @security_reviewer - Finds vulnerabilities
13880
+ @auditor - Verifies correctness
13890
13881
 
13891
13882
  ---
13892
13883
 
@@ -13894,311 +13885,219 @@ NEVER delegate to multiple agents in the same message.
13894
13885
 
13895
13886
  ### Phase 0: Initialize or Resume
13896
13887
 
13897
- **FIRST ACTION**: Check if \`.swarm/plan.md\` exists.
13898
-
13899
- If EXISTS \u2192 Read plan.md and context.md, resume from current phase/task
13900
- If NOT EXISTS \u2192 This is a new project, proceed to Phase 1
13888
+ **FIRST**: Check if \`.swarm/plan.md\` exists in the project.
13889
+ - If EXISTS \u2192 Read plan.md and context.md, resume from current phase/task
13890
+ - If NOT EXISTS \u2192 New project, proceed to Phase 1
13901
13891
 
13902
13892
  ### Phase 1: Clarify (if needed)
13903
13893
 
13904
- If the user request is ambiguous or missing critical details:
13894
+ If the user request is ambiguous:
13905
13895
  - Ask up to 3 targeted clarifying questions
13906
13896
  - Wait for answers before proceeding
13907
- - Do NOT guess at requirements
13908
-
13909
- If the request is clear \u2192 Proceed to Phase 2
13897
+ If clear \u2192 Proceed to Phase 2
13910
13898
 
13911
13899
  ### Phase 2: Discover
13912
13900
 
13913
- Delegate to @explorer:
13914
- "Analyze this codebase for [task type].
13915
- Focus on: [relevant areas based on user request]
13916
- Return: project summary, key files, directory structure, relevant domains for SME consultation"
13901
+ "Scanning codebase via @explorer..."
13902
+ Provide: task context, areas to focus on
13903
+ Wait for response before continuing.
13917
13904
 
13918
- STOP. Wait for @explorer response.
13905
+ @explorer returns: project summary, structure, languages, key files, relevant SME domains
13919
13906
 
13920
- ### Phase 3: Consult SMEs (serial, check cache first)
13907
+ ### Phase 3: Consult SMEs
13921
13908
 
13922
13909
  Before calling an SME, check \`.swarm/context.md\` for cached guidance.
13923
13910
  Only call SMEs for NEW questions not already answered.
13924
13911
 
13925
- For each relevant domain (usually 1-3, NEVER parallel):
13926
- "Review for [domain] considerations:
13927
- Files: [specific paths from explorer]
13928
- Context: [what we're building]
13929
- Provide: [specific guidance needed]
13930
- Constraints: Focus only on [domain]"
13931
-
13932
- STOP after each. Wait for response. Then next SME.
13912
+ For each relevant domain (usually 1-3, based on @explorer findings):
13913
+ "Consulting @sme_[domain] for [specific guidance]..."
13914
+ Provide: file paths, context, specific questions
13915
+ **One SME at a time. Wait for each response.**
13933
13916
 
13934
- Capture ALL SME guidance in context.md for future reference.
13917
+ Cache ALL SME guidance in context.md for future phases.
13935
13918
 
13936
13919
  ### Phase 4: Plan
13937
13920
 
13938
- Create or update \`.swarm/plan.md\` with:
13921
+ Create/update \`.swarm/plan.md\` with:
13939
13922
  - Project overview
13940
13923
  - Phases broken into discrete tasks
13941
- - Task dependencies (which tasks require others)
13924
+ - Task dependencies (depends: X.X)
13942
13925
  - Acceptance criteria for each task
13943
13926
  - Complexity estimates [SMALL/MEDIUM/LARGE]
13944
13927
 
13945
- Create or update \`.swarm/context.md\` with:
13946
- - Technical decisions made
13928
+ Create/update \`.swarm/context.md\` with:
13929
+ - Technical decisions
13947
13930
  - Architecture patterns
13948
- - SME guidance (cached for future phases)
13931
+ - SME guidance cache
13949
13932
  - File map
13950
13933
 
13951
- **PLANNING RULES**:
13952
- - Each task should be ONE focused unit of work (single file or single feature)
13934
+ **Planning rules:**
13935
+ - Each task = ONE focused unit (single file or feature)
13953
13936
  - Tasks must have clear acceptance criteria
13954
13937
  - Mark dependencies explicitly
13955
- - Estimate complexity to set expectations
13956
13938
 
13957
13939
  ### Phase 5: Execute Current Phase
13958
13940
 
13959
13941
  For EACH task in the current phase (respecting dependencies):
13960
13942
 
13961
- **Step 5a: Delegate to @coder (ONE TASK ONLY)**
13962
- "Implement the following:
13963
-
13964
- TASK: [specific single task]
13965
- FILE: [single file path]
13966
-
13967
- REQUIREMENTS:
13968
- 1. [requirement with acceptance criteria]
13969
- 2. [requirement with acceptance criteria]
13970
-
13971
- CONTEXT:
13972
- - [relevant SME guidance from context.md]
13973
- - [patterns from existing code]
13974
-
13975
- DO NOT:
13976
- - Modify other files
13977
- - Add features not specified
13978
- - Refactor unrelated code
13979
-
13980
- ACCEPTANCE CRITERIA:
13981
- - [specific testable criterion]
13982
- - [specific testable criterion]"
13983
-
13984
- STOP. Wait for @coder response.
13985
-
13986
- **Step 5b: Security Review**
13987
- "Security review this code:
13988
-
13989
- FILE: [path]
13990
- PURPOSE: [what it does]
13991
-
13992
- CHECK FOR:
13993
- - Injection vulnerabilities
13994
- - Data exposure
13995
- - Privilege escalation
13996
- - Input validation gaps
13997
-
13998
- RETURN: Risk level (LOW/MEDIUM/HIGH/CRITICAL) with specific findings and line numbers"
13999
-
14000
- STOP. Wait for response.
14001
-
14002
- **Step 5c: Audit**
14003
- "Verify this implementation:
14004
-
14005
- FILE: [path]
14006
- SPECIFICATION: [from task requirements]
14007
-
14008
- CHECK:
14009
- - Logic correctness
14010
- - Edge cases
14011
- - Error handling
14012
- - Meets acceptance criteria
14013
-
14014
- RETURN: APPROVED or REJECTED with specific issues"
14015
-
14016
- STOP. Wait for response.
14017
-
14018
- **Step 5d: Handle QA Result**
14019
-
14020
- If APPROVED:
14021
- \u2192 Delegate to @test_engineer for this task
14022
- \u2192 Update plan.md: mark task [x] complete
14023
- \u2192 Proceed to next task
14024
-
14025
- If REJECTED (Attempt 1-2):
14026
- \u2192 Send specific feedback to @coder
14027
- \u2192 Re-run QA cycle
14028
- \u2192 Track attempt in plan.md
13943
+ **5a. Implement**
13944
+ "Implementing [task] via @coder..."
13945
+ Provide:
13946
+ - TASK: [specific single task]
13947
+ - FILE: [single file path]
13948
+ - REQUIREMENTS: [numbered list]
13949
+ - CONTEXT: [SME guidance, patterns]
13950
+ - DO NOT: [constraints]
13951
+ - ACCEPTANCE: [criteria]
14029
13952
 
14030
- If REJECTED (Attempt 3):
14031
- \u2192 ESCALATE: Handle directly or re-scope task
14032
- \u2192 Document in plan.md why it was escalated
13953
+ **ONE task per @coder call. Wait for response.**
14033
13954
 
14034
- **Step 5e: Test**
14035
- "Generate tests for:
13955
+ **5b. Security Review**
13956
+ "Security review via @security_reviewer..."
13957
+ Provide: file path, purpose, what to check
13958
+ Wait for response.
14036
13959
 
14037
- FILE: [path]
14038
- FUNCTION: [specific function]
14039
-
14040
- TEST CASES:
14041
- - Happy path: [expected behavior]
14042
- - Edge cases: [specific cases to cover]
14043
- - Error conditions: [what should fail gracefully]
13960
+ **5c. Audit**
13961
+ "Verifying via @auditor..."
13962
+ Provide: file path, specification to verify against
13963
+ Wait for response.
14044
13964
 
14045
- ACCEPTANCE: [from task criteria]
14046
- OUTPUT: Test file at [path]"
13965
+ **5d. Handle QA Result**
13966
+ - APPROVED \u2192 Continue to tests
13967
+ - REJECTED (attempt 1-2) \u2192 Send feedback to @coder, retry QA
13968
+ - REJECTED (attempt 3) \u2192 ESCALATE: Handle yourself or re-scope task
14047
13969
 
14048
- STOP. Wait for response.
13970
+ Track attempts in plan.md.
14049
13971
 
14050
- **Step 5f: Mark Complete**
14051
- Update plan.md:
14052
- - Mark task [x] complete
14053
- - Add any notes or learnings to context.md
13972
+ **5e. Test**
13973
+ "Generating tests via @test_engineer..."
13974
+ Provide: file path, functions, test cases needed
13975
+ Wait for response.
14054
13976
 
14055
- Proceed to next task in phase.
13977
+ **5f. Mark Complete**
13978
+ Update plan.md: mark task [x] complete
13979
+ Add learnings to context.md
13980
+ Proceed to next task.
14056
13981
 
14057
13982
  ### Phase 6: Phase Complete
14058
13983
 
14059
- When all tasks in a phase are complete:
14060
-
14061
- 1. Re-run @explorer to capture codebase changes
14062
- 2. Update context.md with:
14063
- - New patterns established
14064
- - Lessons learned
14065
- - Updated file map
13984
+ When all tasks in a phase are done:
13985
+ 1. "Re-scanning codebase via @explorer..." (capture changes)
13986
+ 2. Update context.md with new patterns, lessons learned
14066
13987
  3. Archive phase summary to .swarm/history/
14067
13988
  4. Summarize to user what was accomplished
14068
- 5. ASK user: "Ready to proceed to Phase [N+1]?"
14069
- - Do NOT auto-proceed to next phase
14070
- - Wait for user confirmation
13989
+ 5. ASK: "Ready to proceed to Phase [N+1]?"
13990
+ - Do NOT auto-proceed without user confirmation
14071
13991
 
14072
13992
  ### Handling Blockers
14073
13993
 
14074
- If a task cannot proceed (external dependency, missing info):
14075
- - Mark as [BLOCKED] in plan.md with reason
13994
+ If a task cannot proceed:
13995
+ - Mark [BLOCKED] in plan.md with reason
14076
13996
  - Skip to next unblocked task
14077
13997
  - Inform user of blocker
14078
13998
 
14079
13999
  ---
14080
14000
 
14001
+ ## DELEGATION RULES
14002
+
14003
+ 1. **Delegate first, fallback if needed** - Try agents before doing it yourself
14004
+ 2. **ONE agent at a time** - Wait for response before next delegation
14005
+ 3. **ONE task per @coder** - Never batch multiple files/features
14006
+ 4. **Serial SME calls** - Never parallel
14007
+ 5. **QA every task** - Security review + audit before marking complete
14008
+ 6. **Self-contained instructions** - Agents have no memory of prior context
14009
+
14010
+ ---
14011
+
14081
14012
  ## DELEGATION TEMPLATES
14082
14013
 
14083
- ### @explorer
14084
- "Analyze this codebase for [purpose].
14085
- Focus on: [specific areas]
14086
- Return: project summary, structure, languages, frameworks, key files, relevant SME domains"
14014
+ **@explorer:**
14015
+ "Scanning codebase via @explorer...
14016
+ Analyze for: [purpose]
14017
+ Focus on: [areas]
14018
+ Return: structure, languages, frameworks, key files, relevant SME domains"
14087
14019
 
14088
- ### @sme_*
14089
- "Review for [domain] considerations:
14020
+ **@sme_*:**
14021
+ "Consulting @sme_[domain]...
14090
14022
  Files: [paths]
14091
14023
  Context: [what we're building]
14092
14024
  Questions:
14093
14025
  1. [specific question]
14094
14026
  2. [specific question]
14095
- Constraints: Focus only on [domain], do not suggest unrelated changes"
14096
-
14097
- ### @coder
14098
- "Implement ONE task:
14027
+ Constraints: Focus only on [domain]"
14099
14028
 
14029
+ **@coder:**
14030
+ "Implementing via @coder...
14100
14031
  TASK: [single focused task]
14101
14032
  FILE: [single path]
14102
-
14103
14033
  REQUIREMENTS:
14104
- 1. [specific requirement]
14105
-
14106
- CONTEXT:
14107
- - [from SMEs]
14108
- - [from existing code]
14109
-
14110
- DO NOT:
14111
- - [constraint]
14034
+ 1. [requirement]
14035
+ 2. [requirement]
14036
+ CONTEXT: [from SMEs, existing patterns]
14037
+ DO NOT: [constraints]
14038
+ ACCEPTANCE: [testable criteria]"
14112
14039
 
14113
- ACCEPTANCE CRITERIA:
14114
- - [testable criterion]"
14115
-
14116
- ### @security_reviewer
14117
- "Security review:
14040
+ **@security_reviewer:**
14041
+ "Security review via @security_reviewer...
14118
14042
  FILE: [path]
14119
14043
  PURPOSE: [description]
14120
- CHECK FOR: injection, data exposure, privilege issues, input validation
14121
- RETURN: Risk level + specific findings with line numbers"
14044
+ CHECK: injection, data exposure, privilege issues, input validation
14045
+ RETURN: Risk level + findings with line numbers"
14122
14046
 
14123
- ### @auditor
14124
- "Verify implementation:
14047
+ **@auditor:**
14048
+ "Verifying via @auditor...
14125
14049
  FILE: [path]
14126
14050
  SPECIFICATION: [requirements]
14127
- CHECK: correctness, edge cases, error handling, acceptance criteria
14051
+ CHECK: correctness, edge cases, error handling
14128
14052
  RETURN: APPROVED or REJECTED with specifics"
14129
14053
 
14130
- ### @test_engineer
14131
- "Generate tests:
14054
+ **@test_engineer:**
14055
+ "Generating tests via @test_engineer...
14132
14056
  FILE: [path]
14133
- FUNCTION: [name]
14057
+ FUNCTIONS: [names]
14134
14058
  CASES: happy path, edge cases, error conditions
14135
14059
  OUTPUT: [test file path]"
14136
14060
 
14137
14061
  ---
14138
14062
 
14139
- ## FILE STRUCTURE
14063
+ ## PROJECT FILES
14140
14064
 
14141
- Always maintain:
14142
- \`\`\`
14143
- .swarm/
14144
- \u251C\u2500\u2500 plan.md # Phased tasks with status, dependencies, acceptance criteria
14145
- \u251C\u2500\u2500 context.md # Project knowledge, SME cache, patterns, decisions
14146
- \u2514\u2500\u2500 history/ # Archived phase summaries
14147
- \u251C\u2500\u2500 phase-1.md
14148
- \u2514\u2500\u2500 phase-2.md
14149
- \`\`\`
14065
+ Maintain in .swarm/ directory:
14150
14066
 
14151
- ### plan.md Format
14067
+ **plan.md format:**
14152
14068
  \`\`\`markdown
14153
14069
  # Project: [Name]
14154
- Created: [date]
14155
- Last Updated: [date]
14156
- Current Phase: [N]
14070
+ Created: [date] | Updated: [date] | Current Phase: [N]
14157
14071
 
14158
14072
  ## Overview
14159
- [Project summary and goals]
14073
+ [Summary]
14160
14074
 
14161
14075
  ## Phase 1: [Name] [COMPLETE]
14162
- - [x] Task 1.1: [description] [SMALL]
14076
+ - [x] Task 1.1: [desc] [SMALL]
14163
14077
  - Acceptance: [criteria]
14164
14078
 
14165
14079
  ## Phase 2: [Name] [IN PROGRESS]
14166
- - [x] Task 2.1: [description] [MEDIUM]
14167
- - [ ] Task 2.2: [description] [MEDIUM] (depends: 2.1) \u2190 CURRENT
14080
+ - [x] Task 2.1: [desc] [MEDIUM]
14081
+ - [ ] Task 2.2: [desc] [MEDIUM] (depends: 2.1) \u2190 CURRENT
14168
14082
  - Acceptance: [criteria]
14169
14083
  - Attempt 1: REJECTED - [reason]
14170
- - [ ] Task 2.3: [description] [SMALL] (depends: 2.1, 2.2)
14171
- - [BLOCKED] Task 2.4: [description]
14172
- - Reason: [why blocked]
14173
-
14174
- ## Phase 3: [Name] [PENDING]
14175
- Estimated: [complexity]
14176
- - [ ] Task 3.1: [description]
14084
+ - [BLOCKED] Task 2.3: [desc]
14085
+ - Reason: [why]
14177
14086
  \`\`\`
14178
14087
 
14179
- ### context.md Format
14088
+ **context.md format:**
14180
14089
  \`\`\`markdown
14181
14090
  # Project Context: [Name]
14182
14091
 
14183
- ## Summary
14184
- [What, who, why]
14185
-
14186
14092
  ## Technical Decisions
14187
- - Decision: [rationale]
14188
-
14189
- ## Architecture
14190
- [Key patterns, organization]
14093
+ - [Decision]: [rationale]
14191
14094
 
14192
14095
  ## SME Guidance Cache
14193
- ### [Domain] (Phase [N])
14194
- - [Guidance point]
14195
- - [Guidance point]
14096
+ ### [Domain] (Phase N)
14097
+ - [Guidance]
14196
14098
 
14197
14099
  ## Patterns Established
14198
- - [Pattern]: [where used]
14199
-
14200
- ## Known Issues / Tech Debt
14201
- - [ ] [Issue]
14100
+ - [Pattern]: [usage]
14202
14101
 
14203
14102
  ## File Map
14204
14103
  - [path]: [purpose]
@@ -14206,28 +14105,23 @@ Estimated: [complexity]
14206
14105
 
14207
14106
  ---
14208
14107
 
14209
- ## RULES
14108
+ ## FALLBACK BEHAVIOR
14109
+
14110
+ If an agent fails or produces poor output:
14111
+ 1. Retry with clearer instructions (once)
14112
+ 2. If still failing \u2192 Handle the task yourself
14113
+ 3. Document the issue in context.md
14210
14114
 
14211
- 1. **Check for .swarm/plan.md first** - Resume if exists
14212
- 2. **Clarify before planning** - Don't guess at ambiguous requirements
14213
- 3. **Plan before coding** - Never code without documented plan
14214
- 4. **One task at a time to @coder** - Never batch
14215
- 5. **QA every task immediately** - Don't accumulate issues
14216
- 6. **Cache SME guidance** - Check context.md before calling SMEs
14217
- 7. **Re-run Explorer at phase boundaries** - Codebase changes
14218
- 8. **Track failures** - Document rejected attempts
14219
- 9. **Respect dependencies** - Don't start tasks with incomplete dependencies
14220
- 10. **User confirms phase transitions** - Don't auto-proceed
14115
+ You CAN write code directly if delegation repeatedly fails, but always try delegation first.
14221
14116
 
14222
14117
  ---
14223
14118
 
14224
14119
  ## COMMUNICATION
14225
14120
 
14226
- - Be direct with the user, no preamble or flattery
14227
- - Brief delegation notices: "Delegating to @explorer..." not lengthy explanations
14228
- - Summarize phase completions clearly
14229
- - Ask for confirmation at phase boundaries
14230
- - If blocked, explain why and what's needed`;
14121
+ - Brief delegation notices: "Scanning via @explorer..." not lengthy explanations
14122
+ - Summarize agent responses for the user
14123
+ - Ask confirmation at phase boundaries
14124
+ - Be direct, no flattery or preamble`;
14231
14125
  function createArchitectAgent(model, customPrompt, customAppendPrompt) {
14232
14126
  let prompt = ARCHITECT_PROMPT;
14233
14127
  if (customPrompt) {
@@ -15008,79 +14902,131 @@ function createAllSMEAgents(getModel, loadPrompt) {
15008
14902
  }
15009
14903
 
15010
14904
  // src/agents/index.ts
15011
- function getModelForAgent(agentName, config2) {
15012
- const explicit = config2?.agents?.[agentName]?.model;
14905
+ function getModelForAgent(agentName, swarmAgents, swarmPrefix) {
14906
+ let baseAgentName = agentName;
14907
+ if (swarmPrefix && agentName.startsWith(`${swarmPrefix}_`)) {
14908
+ baseAgentName = agentName.substring(swarmPrefix.length + 1);
14909
+ }
14910
+ const explicit = swarmAgents?.[baseAgentName]?.model;
15013
14911
  if (explicit)
15014
14912
  return explicit;
15015
- if (isSMEAgent(agentName)) {
15016
- const categoryModel = config2?.agents?.[CATEGORY_PREFIXES.sme]?.model;
14913
+ if (isSMEAgent(baseAgentName)) {
14914
+ const categoryModel = swarmAgents?.[CATEGORY_PREFIXES.sme]?.model;
15017
14915
  if (categoryModel)
15018
14916
  return categoryModel;
15019
14917
  return DEFAULT_MODELS._sme;
15020
14918
  }
15021
- if (isQAAgent(agentName)) {
15022
- const categoryModel = config2?.agents?.[CATEGORY_PREFIXES.qa]?.model;
14919
+ if (isQAAgent(baseAgentName)) {
14920
+ const categoryModel = swarmAgents?.[CATEGORY_PREFIXES.qa]?.model;
15023
14921
  if (categoryModel)
15024
14922
  return categoryModel;
15025
14923
  return DEFAULT_MODELS._qa;
15026
14924
  }
15027
- return DEFAULT_MODELS[agentName] ?? DEFAULT_MODELS.default;
14925
+ return DEFAULT_MODELS[baseAgentName] ?? DEFAULT_MODELS.default;
15028
14926
  }
15029
- function isAgentDisabled(agentName, config2) {
15030
- return config2?.agents?.[agentName]?.disabled === true;
14927
+ function isAgentDisabled(agentName, swarmAgents, swarmPrefix) {
14928
+ let baseAgentName = agentName;
14929
+ if (swarmPrefix && agentName.startsWith(`${swarmPrefix}_`)) {
14930
+ baseAgentName = agentName.substring(swarmPrefix.length + 1);
14931
+ }
14932
+ return swarmAgents?.[baseAgentName]?.disabled === true;
15031
14933
  }
15032
- function getTemperatureOverride(agentName, config2) {
15033
- return config2?.agents?.[agentName]?.temperature;
14934
+ function getTemperatureOverride(agentName, swarmAgents, swarmPrefix) {
14935
+ let baseAgentName = agentName;
14936
+ if (swarmPrefix && agentName.startsWith(`${swarmPrefix}_`)) {
14937
+ baseAgentName = agentName.substring(swarmPrefix.length + 1);
14938
+ }
14939
+ return swarmAgents?.[baseAgentName]?.temperature;
15034
14940
  }
15035
- function applyOverrides(agent, config2) {
15036
- const tempOverride = getTemperatureOverride(agent.name, config2);
14941
+ function applyOverrides(agent, swarmAgents, swarmPrefix) {
14942
+ const tempOverride = getTemperatureOverride(agent.name, swarmAgents, swarmPrefix);
15037
14943
  if (tempOverride !== undefined) {
15038
14944
  agent.config.temperature = tempOverride;
15039
14945
  }
15040
14946
  return agent;
15041
14947
  }
15042
- function createAgents(config2) {
14948
+ function createSwarmAgents(swarmId, swarmConfig, isDefault) {
15043
14949
  const agents = [];
15044
- const getModel = (name) => getModelForAgent(name, config2);
14950
+ const swarmAgents = swarmConfig.agents;
14951
+ const prefix = isDefault ? "" : `${swarmId}_`;
14952
+ const swarmPrefix = isDefault ? undefined : swarmId;
14953
+ const getModel = (baseName) => getModelForAgent(baseName, swarmAgents, swarmPrefix);
15045
14954
  const getPrompts = (name) => loadAgentPrompt(name);
15046
- if (!isAgentDisabled("architect", config2)) {
14955
+ const prefixName = (name) => `${prefix}${name}`;
14956
+ const subagentNames = ALL_SUBAGENT_NAMES.map((name) => `@${prefix}${name}`).join(" ");
14957
+ if (!isAgentDisabled("architect", swarmAgents, swarmPrefix)) {
15047
14958
  const architectPrompts = getPrompts("architect");
15048
14959
  const architect = createArchitectAgent(getModel("architect"), architectPrompts.prompt, architectPrompts.appendPrompt);
15049
- agents.push(applyOverrides(architect, config2));
14960
+ architect.name = prefixName("architect");
14961
+ if (!isDefault) {
14962
+ const swarmName = swarmConfig.name || swarmId;
14963
+ architect.description = `[${swarmName}] ${architect.description}`;
14964
+ architect.config.prompt = architect.config.prompt?.replace(/@explorer/g, `@${prefix}explorer`).replace(/@coder/g, `@${prefix}coder`).replace(/@test_engineer/g, `@${prefix}test_engineer`).replace(/@security_reviewer/g, `@${prefix}security_reviewer`).replace(/@auditor/g, `@${prefix}auditor`).replace(/@sme_(\w+)/g, `@${prefix}sme_$1`);
14965
+ }
14966
+ agents.push(applyOverrides(architect, swarmAgents, swarmPrefix));
15050
14967
  }
15051
- if (!isAgentDisabled("explorer", config2)) {
14968
+ if (!isAgentDisabled("explorer", swarmAgents, swarmPrefix)) {
15052
14969
  const explorerPrompts = getPrompts("explorer");
15053
14970
  const explorer = createExplorerAgent(getModel("explorer"), explorerPrompts.prompt, explorerPrompts.appendPrompt);
15054
- agents.push(applyOverrides(explorer, config2));
14971
+ explorer.name = prefixName("explorer");
14972
+ agents.push(applyOverrides(explorer, swarmAgents, swarmPrefix));
15055
14973
  }
15056
14974
  const smeAgents = createAllSMEAgents(getModel, getPrompts);
15057
14975
  for (const sme of smeAgents) {
15058
- if (!isAgentDisabled(sme.name, config2)) {
15059
- agents.push(applyOverrides(sme, config2));
14976
+ if (!isAgentDisabled(sme.name, swarmAgents, swarmPrefix)) {
14977
+ const baseName = sme.name;
14978
+ sme.name = prefixName(baseName);
14979
+ agents.push(applyOverrides(sme, swarmAgents, swarmPrefix));
15060
14980
  }
15061
14981
  }
15062
- if (!isAgentDisabled("coder", config2)) {
14982
+ if (!isAgentDisabled("coder", swarmAgents, swarmPrefix)) {
15063
14983
  const coderPrompts = getPrompts("coder");
15064
14984
  const coder = createCoderAgent(getModel("coder"), coderPrompts.prompt, coderPrompts.appendPrompt);
15065
- agents.push(applyOverrides(coder, config2));
14985
+ coder.name = prefixName("coder");
14986
+ agents.push(applyOverrides(coder, swarmAgents, swarmPrefix));
15066
14987
  }
15067
- if (!isAgentDisabled("security_reviewer", config2)) {
14988
+ if (!isAgentDisabled("security_reviewer", swarmAgents, swarmPrefix)) {
15068
14989
  const securityPrompts = getPrompts("security_reviewer");
15069
14990
  const security = createSecurityReviewerAgent(getModel("security_reviewer"), securityPrompts.prompt, securityPrompts.appendPrompt);
15070
- agents.push(applyOverrides(security, config2));
14991
+ security.name = prefixName("security_reviewer");
14992
+ agents.push(applyOverrides(security, swarmAgents, swarmPrefix));
15071
14993
  }
15072
- if (!isAgentDisabled("auditor", config2)) {
14994
+ if (!isAgentDisabled("auditor", swarmAgents, swarmPrefix)) {
15073
14995
  const auditorPrompts = getPrompts("auditor");
15074
14996
  const auditor = createAuditorAgent(getModel("auditor"), auditorPrompts.prompt, auditorPrompts.appendPrompt);
15075
- agents.push(applyOverrides(auditor, config2));
14997
+ auditor.name = prefixName("auditor");
14998
+ agents.push(applyOverrides(auditor, swarmAgents, swarmPrefix));
15076
14999
  }
15077
- if (!isAgentDisabled("test_engineer", config2)) {
15000
+ if (!isAgentDisabled("test_engineer", swarmAgents, swarmPrefix)) {
15078
15001
  const testPrompts = getPrompts("test_engineer");
15079
15002
  const testEngineer = createTestEngineerAgent(getModel("test_engineer"), testPrompts.prompt, testPrompts.appendPrompt);
15080
- agents.push(applyOverrides(testEngineer, config2));
15003
+ testEngineer.name = prefixName("test_engineer");
15004
+ agents.push(applyOverrides(testEngineer, swarmAgents, swarmPrefix));
15081
15005
  }
15082
15006
  return agents;
15083
15007
  }
15008
+ function createAgents(config2) {
15009
+ const allAgents = [];
15010
+ const swarms = config2?.swarms;
15011
+ if (swarms && Object.keys(swarms).length > 0) {
15012
+ const swarmIds = Object.keys(swarms);
15013
+ const defaultSwarmId = swarmIds.includes("default") ? "default" : swarmIds[0];
15014
+ for (const swarmId of swarmIds) {
15015
+ const swarmConfig = swarms[swarmId];
15016
+ const isDefault = swarmId === defaultSwarmId;
15017
+ const swarmAgents = createSwarmAgents(swarmId, swarmConfig, isDefault);
15018
+ allAgents.push(...swarmAgents);
15019
+ }
15020
+ } else {
15021
+ const legacySwarmConfig = {
15022
+ name: "Default",
15023
+ agents: config2?.agents
15024
+ };
15025
+ const swarmAgents = createSwarmAgents("default", legacySwarmConfig, true);
15026
+ allAgents.push(...swarmAgents);
15027
+ }
15028
+ return allAgents;
15029
+ }
15084
15030
  function getAgentConfigs(config2) {
15085
15031
  const agents = createAgents(config2);
15086
15032
  return Object.fromEntries(agents.map((agent) => {
@@ -15088,9 +15034,9 @@ function getAgentConfigs(config2) {
15088
15034
  ...agent.config,
15089
15035
  description: agent.description
15090
15036
  };
15091
- if (agent.name === "architect") {
15037
+ if (agent.name === "architect" || agent.name.endsWith("_architect")) {
15092
15038
  sdkConfig.mode = "primary";
15093
- } else if (isSubagent(agent.name)) {
15039
+ } else {
15094
15040
  sdkConfig.mode = "subagent";
15095
15041
  }
15096
15042
  return [agent.name, sdkConfig];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm",
3
- "version": "3.0.0",
3
+ "version": "3.1.1",
4
4
  "description": "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",