@ikieaneh/opencode-kit 0.6.1 → 0.6.3

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.
@@ -73,33 +73,38 @@ const resolveConfigPath = (projectDir, relPath) => {
73
73
 
74
74
  // --- Auto-init contract.json if missing ---
75
75
  const ensureContract = (projectDir) => {
76
- const homeDir = os.homedir();
77
- const globalDir = path.join(homeDir, '.config/opencode-kit');
78
- const contractPath = path.join(projectDir, '.opencode', 'orchestration', 'contract.json');
79
-
80
- // Already exists — nothing to do
81
- if (fs.existsSync(contractPath)) return contractPath;
82
-
83
- // Check global config first
84
- const globalContract = path.join(globalDir, 'orchestration', 'contract.json');
85
- if (fs.existsSync(globalContract)) {
86
- fs.mkdirSync(path.dirname(contractPath), { recursive: true });
87
- fs.copyFileSync(globalContract, contractPath);
88
- log('info', `Auto-initialized contract from global config: ${contractPath}`);
89
- return contractPath;
90
- }
76
+ try {
77
+ const homeDir = os.homedir();
78
+ const globalDir = path.join(homeDir, '.config/opencode-kit');
79
+ const contractPath = path.join(projectDir, '.opencode', 'orchestration', 'contract.json');
80
+
81
+ // Already exists — nothing to do
82
+ if (fs.existsSync(contractPath)) return contractPath;
83
+
84
+ // Check global config first
85
+ const globalContract = path.join(globalDir, 'orchestration', 'contract.json');
86
+ if (fs.existsSync(globalContract)) {
87
+ fs.mkdirSync(path.dirname(contractPath), { recursive: true });
88
+ fs.copyFileSync(globalContract, contractPath);
89
+ log('info', `Auto-initialized contract from global config: ${contractPath}`);
90
+ return contractPath;
91
+ }
91
92
 
92
- // Scaffold from plugin template
93
- const templatePath = path.join(TEMPLATES_DIR, 'contract.json');
94
- if (fs.existsSync(templatePath)) {
95
- fs.mkdirSync(path.dirname(contractPath), { recursive: true });
96
- fs.copyFileSync(templatePath, contractPath);
97
- log('info', `Auto-initialized contract from plugin template: ${contractPath}`);
98
- return contractPath;
99
- }
93
+ // Scaffold from plugin template
94
+ const templatePath = path.join(TEMPLATES_DIR, 'contract.json');
95
+ if (fs.existsSync(templatePath)) {
96
+ fs.mkdirSync(path.dirname(contractPath), { recursive: true });
97
+ fs.copyFileSync(templatePath, contractPath);
98
+ log('info', `Auto-initialized contract from plugin template: ${contractPath}`);
99
+ return contractPath;
100
+ }
100
101
 
101
- log('warn', 'Could not auto-initialize contract — no template found');
102
- return null;
102
+ log('warn', 'Could not auto-initialize contract — no template found');
103
+ return null;
104
+ } catch (err) {
105
+ log('error', `Failed to auto-init contract: ${err.message}`);
106
+ return null;
107
+ }
103
108
  };
104
109
 
105
110
  // --- Load bootstrap content (cached) ---
@@ -160,86 +165,98 @@ export const OpencodeKitPlugin = async ({ client, directory }) => {
160
165
  ensureContract(projectDir);
161
166
 
162
167
  // Ensure global config directory exists
163
- fs.mkdirSync(path.join(globalConfigDir, 'orchestration'), { recursive: true });
164
- fs.mkdirSync(path.join(globalConfigDir, 'rules'), { recursive: true });
168
+ try {
169
+ fs.mkdirSync(path.join(globalConfigDir, 'orchestration'), { recursive: true });
170
+ fs.mkdirSync(path.join(globalConfigDir, 'rules'), { recursive: true });
171
+ } catch (err) {
172
+ log('warn', `Failed to create global config dirs: ${err.message}`);
173
+ }
165
174
 
166
175
  return {
167
176
  // Skill resolution order (first match wins):
168
177
  // 1. .opencode/skills/<name>/ (user project — highest priority)
169
178
  // 2. plugin skills/<name>/ (opencode-kit defaults — fallback)
170
179
  config: async (config) => {
171
- config.skills = config.skills || {};
172
- config.skills.paths = config.skills.paths || [];
173
-
174
- // Detect if other plugins might conflict with opencode-kit's system prompt
175
- if (config.plugins && Array.isArray(config.plugins)) {
176
- const kitIndex = config.plugins.findIndex(p =>
177
- typeof p === 'string' && p.includes('opencode-kit')
178
- );
179
- if (kitIndex > 0) {
180
- const firstPlugin = config.plugins[0];
181
- log('warn', `Plugin ordering conflict: opencode-kit should be FIRST, but found '${firstPlugin}' at position 0 and opencode-kit at position ${kitIndex}`);
180
+ try {
181
+ config.skills = config.skills || {};
182
+ config.skills.paths = config.skills.paths || [];
183
+
184
+ // Detect if other plugins might conflict with opencode-kit's system prompt
185
+ if (config.plugins && Array.isArray(config.plugins)) {
186
+ const kitIndex = config.plugins.findIndex(p =>
187
+ typeof p === 'string' && p.includes('opencode-kit')
188
+ );
189
+ if (kitIndex > 0) {
190
+ const firstPlugin = config.plugins[0];
191
+ log('warn', `Plugin ordering conflict: opencode-kit should be FIRST, but found '${firstPlugin}' at position 0 and opencode-kit at position ${kitIndex}`);
192
+ }
182
193
  }
183
- }
184
194
 
185
- // Register user project skills FIRST (higher priority)
186
- const userSkillsDir = path.join(projectDir, '.opencode/skills');
187
- if (fs.existsSync(userSkillsDir) && !config.skills.paths.includes(userSkillsDir)) {
188
- config.skills.paths.push(userSkillsDir);
189
- log('info', `Registered user skills: ${userSkillsDir}`);
190
- }
195
+ // Register user project skills FIRST (higher priority)
196
+ const userSkillsDir = path.join(projectDir, '.opencode/skills');
197
+ if (fs.existsSync(userSkillsDir) && !config.skills.paths.includes(userSkillsDir)) {
198
+ config.skills.paths.push(userSkillsDir);
199
+ log('info', `Registered user skills: ${userSkillsDir}`);
200
+ }
191
201
 
192
- // Register plugin skills SECOND (fallback)
193
- if (!config.skills.paths.includes(SKILLS_DIR)) {
194
- config.skills.paths.push(SKILLS_DIR);
195
- log('info', `Registered plugin skills: ${SKILLS_DIR}`);
196
- }
202
+ // Register plugin skills SECOND (fallback)
203
+ if (!config.skills.paths.includes(SKILLS_DIR)) {
204
+ config.skills.paths.push(SKILLS_DIR);
205
+ log('info', `Registered plugin skills: ${SKILLS_DIR}`);
206
+ }
197
207
 
198
- // Register global config skills path
199
- if (!config.skills.paths.includes(globalConfigDir)) {
200
- if (fs.existsSync(globalConfigDir)) {
201
- config.skills.paths.push(globalConfigDir);
208
+ // Register global config skills path
209
+ if (!config.skills.paths.includes(globalConfigDir)) {
210
+ if (fs.existsSync(globalConfigDir)) {
211
+ config.skills.paths.push(globalConfigDir);
212
+ }
202
213
  }
203
- }
204
214
 
205
- // Provide default contract key hint for agents
206
- config.contractKey = contractKey;
215
+ // Provide default contract key hint for agents
216
+ config.contractKey = contractKey;
217
+ } catch (err) {
218
+ log('error', `config hook failed: ${err.message}`);
219
+ }
207
220
  },
208
221
 
209
222
  'experimental.chat.messages.transform': async (_input, output) => {
210
- const bootstrap = getBootstrapContent();
211
- if (!bootstrap || !output.messages.length) return;
212
-
213
- // Check contract for rule_overrides and inject them into bootstrap
214
- const contractPath = path.join(projectDir, '.opencode', 'orchestration', 'contract.json');
215
- let finalBootstrap = bootstrap;
216
- if (fs.existsSync(contractPath)) {
217
- try {
218
- const contractRaw = fs.readFileSync(contractPath, 'utf8');
219
- const contract = JSON.parse(contractRaw);
220
- if (contract.validation && contract.validation.rule_overrides) {
221
- const overrides = contract.validation.rule_overrides;
222
- const overrideKeys = Object.keys(overrides);
223
- if (overrideKeys.length > 0) {
224
- const overrideText = overrideKeys
225
- .map(id => ` - ${id}: action → ${overrides[id]}`)
226
- .join('\n');
227
- finalBootstrap = bootstrap + `\n## Rule Overrides (from contract)\n\nThe following rule severities have been overridden:\n${overrideText}\n`;
223
+ try {
224
+ const bootstrap = getBootstrapContent();
225
+ if (!bootstrap || !output.messages.length) return;
226
+
227
+ // Check contract for rule_overrides and inject them into bootstrap
228
+ const contractPath = path.join(projectDir, '.opencode', 'orchestration', 'contract.json');
229
+ let finalBootstrap = bootstrap;
230
+ if (fs.existsSync(contractPath)) {
231
+ try {
232
+ const contractRaw = fs.readFileSync(contractPath, 'utf8');
233
+ const contract = JSON.parse(contractRaw);
234
+ if (contract.validation && contract.validation.rule_overrides) {
235
+ const overrides = contract.validation.rule_overrides;
236
+ const overrideKeys = Object.keys(overrides);
237
+ if (overrideKeys.length > 0) {
238
+ const overrideText = overrideKeys
239
+ .map(id => ` - ${id}: action → ${overrides[id]}`)
240
+ .join('\n');
241
+ finalBootstrap = bootstrap + `\n## Rule Overrides (from contract)\n\nThe following rule severities have been overridden:\n${overrideText}\n`;
242
+ }
228
243
  }
244
+ } catch (err) {
245
+ log('warn', `Failed to parse contract for rule_overrides: ${err.message}`);
229
246
  }
230
- } catch (err) {
231
- log('warn', `Failed to parse contract for rule_overrides: ${err.message}`);
232
247
  }
233
- }
234
248
 
235
- const firstUser = output.messages.find(m => m.info.role === 'user');
236
- if (!firstUser || !firstUser.parts.length) return;
249
+ const firstUser = output.messages.find(m => m.info.role === 'user');
250
+ if (!firstUser || !firstUser.parts.length) return;
237
251
 
238
- // Guard: skip if already injected
239
- if (firstUser.parts.some(p => p.type === 'text' && p.text.includes('opencode-kit'))) return;
252
+ // Guard: skip if already injected
253
+ if (firstUser.parts.some(p => p.type === 'text' && p.text.includes('opencode-kit'))) return;
240
254
 
241
- const ref = firstUser.parts[0];
242
- firstUser.parts.unshift({ ...ref, type: 'text', text: finalBootstrap });
255
+ const ref = firstUser.parts[0];
256
+ firstUser.parts.unshift({ ...ref, type: 'text', text: finalBootstrap });
257
+ } catch (err) {
258
+ log('error', `messages.transform hook failed: ${err.message}`);
259
+ }
243
260
  }
244
261
  };
245
262
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ikieaneh/opencode-kit",
3
- "version": "0.6.1",
3
+ "version": "0.6.3",
4
4
  "description": "Standardized OpenCode orchestration framework — contract-based, rules-enforced, zero-touch agent workflow. Install as plugin.",
5
5
  "license": "MIT",
6
6
  "author": "RizkiRachman",
@@ -16,12 +16,13 @@
16
16
  },
17
17
  "files": [
18
18
  ".opencode/plugins/",
19
- ".claude-plugin/",
20
- "src/",
21
- "rules/",
22
19
  "templates/",
23
20
  "skills/",
24
- "docs/"
21
+ "rules/",
22
+ "src/cli.js",
23
+ "src/init.sh",
24
+ "LICENSE",
25
+ "README.md"
25
26
  ],
26
27
  "publishConfig": {
27
28
  "access": "public"
@@ -42,8 +43,9 @@
42
43
  "url": "git+https://github.com/RizkiRachman/opencode-kit.git"
43
44
  },
44
45
  "scripts": {
45
- "lint": "eslint src/ test/",
46
- "format": "prettier --check src/ test/"
46
+ "postinstall": "git config core.hooksPath .githooks 2>/dev/null || true",
47
+ "lint": "shellcheck src/*.sh rules/*.sh 2>/dev/null || true",
48
+ "format": "echo 'Formatting: not configured yet'"
47
49
  },
48
50
  "bugs": {
49
51
  "url": "https://github.com/RizkiRachman/opencode-kit/issues"
package/src/init.sh CHANGED
@@ -83,8 +83,8 @@ if [ -d ".opencode" ]; then
83
83
  echo " ✅ Backed up to $BACKUP"
84
84
  else
85
85
  echo ""
86
- echo -e "${YELLOW}⚠️ .opencode/ already exists. Use --force to overwrite (backup + clean scaffold).${NC}"
87
- echo " Missing files will be added. Existing files will NOT be overwritten."
86
+ echo -e "${YELLOW}⚠️ .opencode/ already exists. Use --force to re-scaffold (backup + clean).${NC}"
87
+ echo " Skipping existing .opencode/ preserved."
88
88
  fi
89
89
  fi
90
90
 
@@ -3,6 +3,7 @@
3
3
  "title": "opencode-kit Plugin Config",
4
4
  "description": "Configuration schema for @ikieaneh/opencode-kit plugin. Add to your opencode.json to enable orchestration agents.",
5
5
  "type": "object",
6
+ "additionalProperties": false,
6
7
  "properties": {
7
8
  "plugin": {
8
9
  "type": "array",
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "version": "0.1.0",
3
+ "template_version": "0.6.2",
3
4
  "description": "Superpowers & MCP registry for opencode-kit",
4
5
  "plugins": ["superpowers"],
5
6
  "mcps": ["gitnexus", "graphify", "lean-ctx", "context7"],
@@ -1,23 +0,0 @@
1
- {
2
- "name": "opencode-kit",
3
- "description": "Standardized orchestration framework — contract-based, rules-enforced, zero-touch agent workflow",
4
- "version": "0.6.1",
5
- "author": {
6
- "name": "Rizki Rachman",
7
- "url": "https://github.com/RizkiRachman"
8
- },
9
- "homepage": "https://github.com/RizkiRachman/opencode-kit",
10
- "repository": "https://github.com/RizkiRachman/opencode-kit",
11
- "license": "MIT",
12
- "keywords": [
13
- "opencode",
14
- "opencode-plugin",
15
- "orchestration",
16
- "workflow",
17
- "agents",
18
- "enforcement",
19
- "contract",
20
- "scoring",
21
- "adr"
22
- ]
23
- }
@@ -1,123 +0,0 @@
1
- # Quickstart: Using opencode-kit as a Plugin
2
-
3
- This guide creates a new project from scratch with opencode-kit as an OpenCode plugin.
4
-
5
- ## Step 1: Create a project
6
-
7
- ```sh
8
- mkdir my-agent-project
9
- cd my-agent-project
10
- git init
11
- ```
12
-
13
- ## Step 2: Install the plugin
14
-
15
- ```sh
16
- npm install @ikieaneh/opencode-kit
17
- ```
18
-
19
- ## Step 3: Configure OpenCode
20
-
21
- Create `opencode.json`:
22
-
23
- ```json
24
- {
25
- "model": "your-model",
26
- "plugin": [
27
- "@ikieaneh/opencode-kit",
28
- "superpowers"
29
- ],
30
- "agent": {
31
- "orchestrator": {
32
- "model": "your-model",
33
- "skills": [
34
- "orchestration-template",
35
- "scoring-pipeline",
36
- "verification-before-completion"
37
- ],
38
- "steps": 50,
39
- "fallback_models": ["your-fallback-model"]
40
- },
41
- "planner": {
42
- "model": "your-model",
43
- "skills": ["brainstorming", "writing-plans", "system-analyst"],
44
- "steps": 80,
45
- "fallback_models": ["your-fallback-model"]
46
- },
47
- "task-manager": {
48
- "model": "your-model",
49
- "skills": ["subagent-driven-development", "executing-plans", "test-driven-development"],
50
- "steps": 100,
51
- "fallback_models": ["your-fallback-model"]
52
- },
53
- "code-reviewer": {
54
- "model": "your-model",
55
- "skills": ["qa-expert", "security-expert"],
56
- "steps": 80,
57
- "fallback_models": ["your-fallback-model"]
58
- },
59
- "explorer": {
60
- "model": "your-model",
61
- "steps": 30,
62
- "tools": { "postgres_*": false, "memory_*": false, "context7_*": false }
63
- },
64
- "librarian": {
65
- "model": "your-model",
66
- "steps": 30,
67
- "tools": { "postgres_*": false, "memory_*": false, "graphify_*": false }
68
- },
69
- "leaner": {
70
- "model": "your-model",
71
- "skills": ["verification-before-completion", "qa-expert"]
72
- }
73
- }
74
- }
75
- ```
76
-
77
- ## Step 4: Start working
78
-
79
- Open the project in OpenCode. The plugin auto-loads:
80
-
81
- 1. 8 skills registered automatically
82
- 2. Orchestration contract injected into every session
83
- 3. Pre-flight enforcement active (branch check, contract load)
84
- 4. Scoring pipeline available after every delegation
85
- 5. ADR generator for architectural decisions
86
- 6. Telemetry tracking elapsed time per phase
87
-
88
- ## Step 5: Set a goal
89
-
90
- Edit `.opencode/orchestration/contract.json`:
91
-
92
- ```json
93
- {
94
- "state": "INIT",
95
- "requirements": {
96
- "goal": "Add user authentication with JWT",
97
- "acceptance_criteria": ["Users can register", "Users can login", "Tokens expire after 24h"]
98
- }
99
- }
100
- ```
101
-
102
- ## Step 6: Workflow runs itself
103
-
104
- ```
105
- INIT → PLAN → PLAN_SCORED → EXECUTE → EXECUTE_SCORED → REVIEW → REVIEW_SCORED → COMPLETE
106
- ```
107
-
108
- Each phase transition requires score ≥ 70. Score < 50 → BLOCKED.
109
-
110
- ## What you get
111
-
112
- | Feature | Provider |
113
- |---------|----------|
114
- | Contract protocol | orchestration-template skill |
115
- | Scoring pipeline | scoring-pipeline skill |
116
- | ADR records | adr-generator skill |
117
- | QA standards | qa-expert skill |
118
- | Impact analysis | system-analyst skill |
119
- | Token optimization | token-optimize skill |
120
- | Verification gates | verification-before-completion skill |
121
- | Post-task learning | learner skill |
122
- | Telemetry | src/telemetry.sh |
123
- | Rules enforcement | rules.json + validation.sh |
@@ -1,108 +0,0 @@
1
- # Extension Skill Template
2
-
3
- Create project-specific skills in `.opencode/skills/` to extend opencode-kit.
4
-
5
- ## Resolution Order
6
-
7
- 1. `.opencode/skills/<name>/SKILL.md` — user project skill (highest priority)
8
- 2. `node_modules/@ikieaneh/opencode-kit/skills/<name>/SKILL.md` — plugin skill (fallback)
9
-
10
- If a user skill and plugin skill have the **same name**, the user's version takes priority.
11
-
12
- ## Example: Java/Spring Conventions
13
-
14
- Create `.opencode/skills/java-conventions/SKILL.md`:
15
-
16
- ```markdown
17
- ---
18
- description: Java 21 + Spring Boot 3.4 conventions for this project.
19
- ---
20
-
21
- # Java Conventions
22
-
23
- ## Build & Test
24
-
25
- | Command | Action |
26
- |---------|--------|
27
- | `mvn spotless:apply` | Format (Google Java Style) |
28
- | `mvn test` | ArchUnit + unit tests |
29
- | `mvn verify` | SpotBugs + PMD CPD |
30
-
31
- ## Hexagonal Architecture
32
-
33
- ```
34
- application/ → domain model, ports, services (no Spring/JPA)
35
- infrastructure/ → web adapters, persistence, events
36
- ```
37
-
38
- ## Writing Order
39
-
40
- Port → Service → Mapper → Adapter → Constants → Events → Tests
41
-
42
- ## Naming Rules
43
-
44
- | Concern | Suffix | Example |
45
- |---------|--------|---------|
46
- | API DTO | none | `Product` |
47
- | Domain Model | `Domain` | `ProductDomain` |
48
- | JPA Entity | `Entity` | `ProductEntity` |
49
-
50
- ## ArchUnit Rules (7)
51
-
52
- 1. domainMustNotDependOnInfrastructure
53
- 2. domainModelsMustNotHaveJpaAnnotations
54
- 3. portsMustNotReturnOptional
55
- 4. entitiesMustNotUseJpaRelationshipAnnotations
56
- 5. layeredArchitectureShouldRespectHexagonalBoundaries
57
- 6. domainServicesMustBeAnnotatedWithService
58
- 7. repositoryAdaptersMustBeAnnotatedWithComponent
59
- ```
60
-
61
- ## Example: Python/Django Conventions
62
-
63
- Create `.opencode/skills/python-conventions/SKILL.md`:
64
-
65
- ```markdown
66
- ---
67
- description: Django REST Framework conventions for this project.
68
- ---
69
-
70
- # Python Conventions
71
-
72
- ## Build & Test
73
-
74
- | Command | Action |
75
- |---------|--------|
76
- | `black .` | Format code |
77
- | `ruff check .` | Lint |
78
- | `pytest` | Run tests |
79
- | `mypy .` | Type check |
80
-
81
- ## Architecture
82
-
83
- Apps follow clean architecture:
84
- - `models/` — domain models with business logic
85
- - `serializers/` — input/output validation
86
- - `views/` — HTTP handlers (thin)
87
- - `services/` — business logic layer
88
- - `tests/` — mirrors app structure
89
- ```
90
-
91
- ## How to Load
92
-
93
- In `opencode.json`, add to any agent's skills array:
94
-
95
- ```json
96
- {
97
- "agent": {
98
- "task-manager": {
99
- "skills": [
100
- "verification-before-completion",
101
- "java-conventions"
102
- ]
103
- }
104
- }
105
- }
106
- ```
107
-
108
- Or load it ad-hoc with: `/skill java-conventions`
@@ -1,117 +0,0 @@
1
- # Model Provider Configurations
2
-
3
- Add these to your `opencode.json` to configure AI models for opencode-kit agents.
4
-
5
- ## DeepSeek (via Sumopod)
6
-
7
- ```json
8
- {
9
- "model": "sumopod/deepseek-v4-flash",
10
- "provider": {
11
- "sumopod": {
12
- "npm": "@ai-sdk/openai-compatible",
13
- "name": "Sumopod AI",
14
- "options": {
15
- "baseURL": "https://ai.sumopod.com/v1",
16
- "apiKey": "sk-your-key"
17
- },
18
- "models": {
19
- "deepseek-v4-flash": {
20
- "name": "DeepSeek V4 Flash",
21
- "options": {
22
- "reasoningEffort": "high",
23
- "textVerbosity": "low"
24
- }
25
- }
26
- }
27
- }
28
- }
29
- }
30
- ```
31
-
32
- ## OpenAI
33
-
34
- ```json
35
- {
36
- "model": "gpt-4o",
37
- "provider": {
38
- "openai": {
39
- "npm": "@ai-sdk/openai",
40
- "models": {
41
- "gpt-4o": { "name": "GPT-4o" },
42
- "gpt-4o-mini": { "name": "GPT-4o Mini" }
43
- }
44
- }
45
- }
46
- }
47
- ```
48
-
49
- ## Anthropic (Claude)
50
-
51
- ```json
52
- {
53
- "model": "claude-sonnet-4-20250514",
54
- "provider": {
55
- "anthropic": {
56
- "npm": "@ai-sdk/anthropic",
57
- "models": {
58
- "claude-sonnet-4-20250514": { "name": "Claude Sonnet 4" },
59
- "claude-haiku-3-5-20241022": { "name": "Claude Haiku 3.5" }
60
- }
61
- }
62
- }
63
- }
64
- ```
65
-
66
- ## Google (Gemini)
67
-
68
- ```json
69
- {
70
- "model": "gemini-2.5-flash",
71
- "provider": {
72
- "google": {
73
- "npm": "@ai-sdk/google",
74
- "models": {
75
- "gemini-2.5-flash": { "name": "Gemini 2.5 Flash" },
76
- "gemini-2.5-pro": { "name": "Gemini 2.5 Pro" }
77
- }
78
- }
79
- }
80
- }
81
- ```
82
-
83
- ## Agent Assignment Strategy
84
-
85
- Use **cheaper models** for simple agents, **better models** for complex reasoning:
86
-
87
- | Agent | Recommended Model | Why |
88
- |-------|------------------|-----|
89
- | orchestrator | Cheaper (orchestration, not deep thinking) | Delegates most work |
90
- | planner | Better (architecture, impact analysis) | Needs deep reasoning |
91
- | task-manager | Better (implementation, code quality) | Needs to write correct code |
92
- | code-reviewer | Better (security, edge cases) | Needs sharp analysis |
93
- | explorer | Cheaper (just searches) | Simple grep/glob |
94
- | librarian | Cheaper (fetches docs) | Simple fetch operations |
95
- | learner | Cheaper (analysis after the fact) | Post-processing only |
96
- | fixer | Cheaper (bounded edits) | Well-defined scope |
97
-
98
- Example with mixed models:
99
-
100
- ```json
101
- {
102
- "agent": {
103
- "orchestrator": {
104
- "model": "sumopod/deepseek-v4-flash",
105
- "fallback_models": ["gpt-4o-mini"]
106
- },
107
- "planner": {
108
- "model": "gpt-4o",
109
- "fallback_models": ["sumopod/deepseek-v4-flash"]
110
- },
111
- "task-manager": {
112
- "model": "gpt-4o",
113
- "fallback_models": ["sumopod/deepseek-v4-flash"]
114
- }
115
- }
116
- }
117
- ```