devloom 1.1.0 → 1.2.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.
- package/GUIDE.md +26 -2
- package/README.md +26 -0
- package/agents/devloom-developer-flash.md +4 -0
- package/agents/devloom-developer-senior.md +4 -0
- package/agents/devloom-developer.md +4 -0
- package/agents/devloom-documenter-flash.md +4 -0
- package/agents/devloom-documenter.md +4 -0
- package/agents/devloom-orchestrator.md +4 -0
- package/agents/devloom-planner-flash.md +4 -0
- package/agents/devloom-planner-senior.md +4 -0
- package/agents/devloom-planner.md +4 -0
- package/agents/devloom-qa-flash.md +4 -0
- package/agents/devloom-qa.md +4 -0
- package/agents/devloom-security-senior.md +4 -0
- package/agents/devloom-security.md +4 -0
- package/agents/devloom-verifier.md +4 -0
- package/agents/devloom-vision.md +4 -0
- package/agents/devloom-visual-critic.md +4 -0
- package/agents/devloom-visual-director.md +4 -0
- package/commands/devloom-agents.md +1 -1
- package/commands/devloom-deepseek-mimo.md +11 -0
- package/package.json +1 -1
- package/postinstall.mjs +8 -4
- package/protocol/model-routing.md +10 -1
- package/scripts/briefing.mjs +192 -0
- package/scripts/model-capabilities.mjs +25 -0
- package/scripts/plugin-cache.mjs +5 -5
- package/scripts/profile.mjs +69 -5
package/GUIDE.md
CHANGED
|
@@ -29,7 +29,7 @@ and skill files to your OpenCode global config directory:
|
|
|
29
29
|
| OS | Config directory |
|
|
30
30
|
|---|---|
|
|
31
31
|
| Linux | `~/.config/opencode/` |
|
|
32
|
-
| macOS |
|
|
32
|
+
| macOS | `~/.config/opencode/` |
|
|
33
33
|
| Windows | `%APPDATA%\opencode\` |
|
|
34
34
|
|
|
35
35
|
Expected output:
|
|
@@ -58,7 +58,7 @@ Installing commands (17 total):
|
|
|
58
58
|
- /devloom, /devloom-init, /devloom-status, /devloom-resume
|
|
59
59
|
- /devloom-save, /devloom-agents
|
|
60
60
|
- /devloom-go, /devloom-go-economy, /devloom-go-flash, /devloom-deepseek
|
|
61
|
-
- /devloom-mimo, /devloom-free, /devloom-auto
|
|
61
|
+
- /devloom-mimo, /devloom-deepseek-mimo, /devloom-free, /devloom-auto
|
|
62
62
|
- /devloom-plan, /devloom-context, /devloom-loop, /devloom-loop-status
|
|
63
63
|
|
|
64
64
|
Installing skills (21 total):
|
|
@@ -128,6 +128,7 @@ Start OpenCode and open the command palette by typing `/`:
|
|
|
128
128
|
/devloom-go-economy → Switch to Go economy profile
|
|
129
129
|
/devloom-go-flash → Switch to Go flash profile (cheapest paid)
|
|
130
130
|
/devloom-mimo → Switch to the MiMo V2.6 Flash profile (multimodal all-role stack)
|
|
131
|
+
/devloom-deepseek-mimo → Switch to the hybrid profile (DeepSeek V4.1 general, MiMo V2.6 visual)
|
|
131
132
|
/devloom-free → Switch to free-tier profile
|
|
132
133
|
/devloom-auto → Auto-detect best profile for your environment
|
|
133
134
|
/devloom-loop → Start/stop loop engineering patterns
|
|
@@ -176,6 +177,7 @@ DevLoom provides model profiles that trade off quality vs cost:
|
|
|
176
177
|
| `deepseek` | DeepSeek-only stack | Go (paid) |
|
|
177
178
|
| `glm` | GLM-only stack | Go (paid) |
|
|
178
179
|
| `go-flash` | Maximum throughput, minimum cost | Go (paid) |
|
|
180
|
+
| `deepseek-mimo` | Fast general work (DeepSeek V4.1), MiMo V2.6 for graphical/complex roles | Go (paid) |
|
|
179
181
|
| `mimo` | Multimodal all-role stack incl. vision | Go/MiMo |
|
|
180
182
|
| `free` | Zero-cost experimentation | Free |
|
|
181
183
|
|
|
@@ -604,6 +606,28 @@ without starting a weave:
|
|
|
604
606
|
|
|
605
607
|
---
|
|
606
608
|
|
|
609
|
+
## Incremental Briefing (token savings)
|
|
610
|
+
|
|
611
|
+
Sub-agents must not re-read the same files on every dispatch. DevLoom solves
|
|
612
|
+
this with a per-ticket briefing plus change-based invalidation:
|
|
613
|
+
|
|
614
|
+
- **Ticket start:** the orchestrator runs `briefing.mjs init <ticket>` and
|
|
615
|
+
writes `.opencode/devloom/context/briefing.md` ONCE (goal, constraints,
|
|
616
|
+
file map with `file:line` refs, decisions).
|
|
617
|
+
- **Every `task()` prompt** starts with `Read .opencode/devloom/context/briefing.md
|
|
618
|
+
first — do not re-discover` — sub-agents start from the map instead of
|
|
619
|
+
scanning the repo. A stable prompt prefix also gets provider prompt-caching.
|
|
620
|
+
- **Before each later dispatch:** `briefing.mjs changed` prints only the paths
|
|
621
|
+
whose content fingerprints differ from the last anchor (sha256, recorded at
|
|
622
|
+
`init`/`touch` — works inside or outside git and never re-flags a file that
|
|
623
|
+
was already re-read). The orchestrator re-reads ONLY those, patches the
|
|
624
|
+
briefing, runs `briefing.mjs touch`, and dispatches. Unchanged files are
|
|
625
|
+
never re-read.
|
|
626
|
+
|
|
627
|
+
Script discovery uses the same fallback chain as `profile.mjs`:
|
|
628
|
+
`~/.config/opencode/commands/briefing.mjs` → `~/.config/opencode/devloom-scripts/briefing.mjs`
|
|
629
|
+
→ `scripts/briefing.mjs`.
|
|
630
|
+
|
|
607
631
|
## Visual Pipeline
|
|
608
632
|
|
|
609
633
|
For substantial graphical work, DevLoom routes through an extra visual loop:
|
package/README.md
CHANGED
|
@@ -114,6 +114,18 @@ npm install -g devloom
|
|
|
114
114
|
npm install -g https://github.com/nsrau/devloom.git
|
|
115
115
|
```
|
|
116
116
|
|
|
117
|
+
**From GitHub Packages** (mirror `@nsrau/devloom`):
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
# ~/.npmrc
|
|
121
|
+
@nsrau:registry=https://npm.pkg.github.com
|
|
122
|
+
//npm.pkg.github.com/:_authToken=<TOKEN> # PAT/granular token with read:packages
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
npm install -g @nsrau/devloom
|
|
127
|
+
```
|
|
128
|
+
|
|
117
129
|
**From source:**
|
|
118
130
|
|
|
119
131
|
```bash
|
|
@@ -349,6 +361,7 @@ maps every agent to a specific model optimized for its role.
|
|
|
349
361
|
| **free** | Good | Zero | Evaluation, learning, hobby projects |
|
|
350
362
|
| **glm** | High | Lower | GLM-only stack |
|
|
351
363
|
| **mimo** | High | Low/Fast | MiMo V2.6 multimodal all-role stack |
|
|
364
|
+
| **deepseek-mimo** | High | Fast | DeepSeek V4.1 general + MiMo V2.6 graphical/complex hybrid |
|
|
352
365
|
|
|
353
366
|
### go profile (max quality)
|
|
354
367
|
|
|
@@ -482,6 +495,18 @@ same-family fallback such as `mimo-v2.6-pro` is allowed but always reported
|
|
|
482
495
|
under "Fallbacks applied"). Tier overrides are locked for `mimo` (like
|
|
483
496
|
`go-flash` and `free`). Switch with `/devloom-mimo` (`profile.mjs set mimo`).
|
|
484
497
|
|
|
498
|
+
### deepseek-mimo profile (hybrid)
|
|
499
|
+
|
|
500
|
+
Fast everyday work on DeepSeek V4.1, graphical/complex work on MiMo V2.6.
|
|
501
|
+
The 7 general roles (orchestrator, planner, developer, qa, verifier, security,
|
|
502
|
+
documenter) resolve to `opencode-go/deepseek-v4.1-flash`; vision,
|
|
503
|
+
visual-director, and visual-critic resolve through the
|
|
504
|
+
`mimo/mimo-v2.6-flash` → `xiaomi/mimo-v2.6-flash` → `opencode-go/mimo-v2.6-flash`
|
|
505
|
+
chain. Both chains resolve strictly — if either finds nothing the profile exits
|
|
506
|
+
code 1 with the attempted candidates, never an unrelated substitution. Tier
|
|
507
|
+
overrides are allowed (deepseek pattern). Switch with
|
|
508
|
+
`/devloom-deepseek-mimo` (`profile.mjs set deepseek-mimo`).
|
|
509
|
+
|
|
485
510
|
### Model-routing table (go)
|
|
486
511
|
|
|
487
512
|
Each of the 10 agents is assigned a model optimized for its role:
|
|
@@ -553,6 +578,7 @@ source first so the cache never receives stale compiled code.
|
|
|
553
578
|
variants are hidden for every profile. The variants stay registered so
|
|
554
579
|
orchestrator `task()` routing keeps working; they are simply not listed.
|
|
555
580
|
- Switching profiles (`/devloom-go`, `/devloom-go-flash`, `/devloom-mimo`,
|
|
581
|
+
`/devloom-deepseek-mimo`,
|
|
556
582
|
`/devloom-free`, ...)
|
|
557
583
|
updates the installed agent files immediately; restart opencode to see the
|
|
558
584
|
updated profile and models in the sidebar.
|
|
@@ -6,12 +6,16 @@ permission:
|
|
|
6
6
|
edit: allow
|
|
7
7
|
bash: allow
|
|
8
8
|
task: deny
|
|
9
|
+
external_directory:
|
|
10
|
+
"~/.config/opencode/**": allow
|
|
9
11
|
---
|
|
10
12
|
|
|
11
13
|
# DevLoom Developer Flash
|
|
12
14
|
|
|
13
15
|
ENGLISH ONLY: All output MUST be in English. Never use any other language.
|
|
14
16
|
|
|
17
|
+
BEFORE SCANNING: if `.opencode/devloom/context/briefing.md` exists, read it FIRST and start from its file map — never re-read files it already summarizes.
|
|
18
|
+
|
|
15
19
|
COMPLIANCE: Follow the RULES below + your skill LOAD. No rule may be skipped.
|
|
16
20
|
RULES: EN | SOLID+TDD+CleanArch | tests+regr required | doing<=1 | FILES: use .opencode/devloom/.tmp/ | peer-review for high-risk | degrade on 2x failure
|
|
17
21
|
LOAD: ~/.config/opencode/skills/build/development.md|~/.config/opencode/skills/build/simplify.md
|
|
@@ -6,12 +6,16 @@ permission:
|
|
|
6
6
|
edit: allow
|
|
7
7
|
bash: allow
|
|
8
8
|
task: deny
|
|
9
|
+
external_directory:
|
|
10
|
+
"~/.config/opencode/**": allow
|
|
9
11
|
---
|
|
10
12
|
|
|
11
13
|
# DevLoom Developer Senior
|
|
12
14
|
|
|
13
15
|
ENGLISH ONLY: All output MUST be in English. Never use any other language.
|
|
14
16
|
|
|
17
|
+
BEFORE SCANNING: if `.opencode/devloom/context/briefing.md` exists, read it FIRST and start from its file map — never re-read files it already summarizes.
|
|
18
|
+
|
|
15
19
|
COMPLIANCE: Follow the RULES below + your skill LOAD. No rule may be skipped.
|
|
16
20
|
RULES: EN | SOLID+TDD+CleanArch | tests+regr required | doing<=1 | FILES: use .opencode/devloom/.tmp/ | peer-review for high-risk | degrade on 2x failure
|
|
17
21
|
LOAD: ~/.config/opencode/skills/build/development.md|~/.config/opencode/skills/build/simplify.md
|
|
@@ -6,12 +6,16 @@ permission:
|
|
|
6
6
|
edit: allow
|
|
7
7
|
bash: allow
|
|
8
8
|
task: deny
|
|
9
|
+
external_directory:
|
|
10
|
+
"~/.config/opencode/**": allow
|
|
9
11
|
---
|
|
10
12
|
|
|
11
13
|
# DevLoom Developer
|
|
12
14
|
|
|
13
15
|
ENGLISH ONLY: All output MUST be in English. Never use any other language.
|
|
14
16
|
|
|
17
|
+
BEFORE SCANNING: if `.opencode/devloom/context/briefing.md` exists, read it FIRST and start from its file map — never re-read files it already summarizes.
|
|
18
|
+
|
|
15
19
|
COMPLIANCE: Follow the RULES below + your skill LOAD. No rule may be skipped.
|
|
16
20
|
RULES: EN | SOLID+TDD+CleanArch | tests+regr required | doing<=1 | FILES: use .opencode/devloom/.tmp/ | peer-review for high-risk | degrade on 2x failure
|
|
17
21
|
LOAD: ~/.config/opencode/skills/build/development.md|~/.config/opencode/skills/build/simplify.md
|
|
@@ -6,12 +6,16 @@ permission:
|
|
|
6
6
|
edit: allow
|
|
7
7
|
bash: allow
|
|
8
8
|
task: deny
|
|
9
|
+
external_directory:
|
|
10
|
+
"~/.config/opencode/**": allow
|
|
9
11
|
---
|
|
10
12
|
|
|
11
13
|
# DevLoom Documenter Flash
|
|
12
14
|
|
|
13
15
|
ENGLISH ONLY: All output MUST be in English. Never use any other language.
|
|
14
16
|
|
|
17
|
+
BEFORE SCANNING: if `.opencode/devloom/context/briefing.md` exists, read it FIRST and start from its file map — never re-read files it already summarizes.
|
|
18
|
+
|
|
15
19
|
COMPLIANCE: Follow the RULES below + your skill LOAD. No rule may be skipped.
|
|
16
20
|
RULES: EN | SOLID+TDD+CleanArch | tests+regr required | doing<=1 | FILES: use .opencode/devloom/.tmp/ | peer-review for high-risk | degrade on 2x failure
|
|
17
21
|
LOAD: ~/.config/opencode/skills/ship/documentation.md
|
|
@@ -6,12 +6,16 @@ permission:
|
|
|
6
6
|
edit: allow
|
|
7
7
|
bash: allow
|
|
8
8
|
task: deny
|
|
9
|
+
external_directory:
|
|
10
|
+
"~/.config/opencode/**": allow
|
|
9
11
|
---
|
|
10
12
|
|
|
11
13
|
# DevLoom Documenter
|
|
12
14
|
|
|
13
15
|
ENGLISH ONLY: All output MUST be in English. Never use any other language.
|
|
14
16
|
|
|
17
|
+
BEFORE SCANNING: if `.opencode/devloom/context/briefing.md` exists, read it FIRST and start from its file map — never re-read files it already summarizes.
|
|
18
|
+
|
|
15
19
|
COMPLIANCE: Follow the RULES below + your skill LOAD. No rule may be skipped.
|
|
16
20
|
RULES: EN | SOLID+TDD+CleanArch | tests+regr required | doing<=1 | FILES: use .opencode/devloom/.tmp/ | peer-review for high-risk | degrade on 2x failure
|
|
17
21
|
LOAD: ~/.config/opencode/skills/ship/documentation.md
|
|
@@ -12,6 +12,8 @@ permission:
|
|
|
12
12
|
bash: allow
|
|
13
13
|
glob: allow
|
|
14
14
|
grep: allow
|
|
15
|
+
external_directory:
|
|
16
|
+
"~/.config/opencode/**": allow
|
|
15
17
|
---
|
|
16
18
|
|
|
17
19
|
# DevLoom Orchestrator
|
|
@@ -103,6 +105,8 @@ TIER DEGRADATION: If a sub-agent fails twice consecutively (timeout, rate-limit,
|
|
|
103
105
|
|
|
104
106
|
ARCHITECTURE ATLAS: Before delegating to any sub-agent, check if `.opencode/devloom/context/atlas.md` exists. If it does, pass the `ATLAS:` section to sub-agents so they understand the codebase structure without scanning files. The atlas is auto-generated by the plugin.
|
|
105
107
|
|
|
108
|
+
INCREMENTAL BRIEFING (never re-read unchanged files): On ticket start, locate `briefing.mjs` with the profile.mjs fallback chain (`~/.config/opencode/commands/briefing.mjs`, else `~/.config/opencode/devloom-scripts/briefing.mjs`, else `scripts/briefing.mjs`) and run `init <ticket>`, then write `.opencode/devloom/context/briefing.md` ONCE (goal, constraints, file map with file:line refs, decisions) — read each file only while building it. Start EVERY task() prompt with: `Read .opencode/devloom/context/briefing.md first — do not re-discover; read other files only for code-level detail beyond it.` Before each subsequent dispatch run `changed`: re-read ONLY the printed paths, patch the briefing, run `touch`, then dispatch. Files not listed must never be re-read; pass the briefing path (not file contents) to keep prompts stable for provider prompt-caching.
|
|
109
|
+
|
|
106
110
|
VISUAL PIPELINE (UI work with VISUAL_REQUIRED=true only):
|
|
107
111
|
1. visual-director FIRST: `task(subagent_type: "devloom-visual-director", ...)` — emits a `DESIGN_FILE` markdown block (tokens: colors, type, spacing, layout, motion, components).
|
|
108
112
|
2. PERSIST DESIGN: you write the DESIGN_FILE body to `.opencode/devloom/context/design.md` (bash is allowed for this persistence). Pass that file's content as `DESIGN_CONTRACT:` to planner (if planning) and to every developer/critic delegation in the chain.
|
|
@@ -6,12 +6,16 @@ permission:
|
|
|
6
6
|
edit: allow
|
|
7
7
|
bash: allow
|
|
8
8
|
task: deny
|
|
9
|
+
external_directory:
|
|
10
|
+
"~/.config/opencode/**": allow
|
|
9
11
|
---
|
|
10
12
|
|
|
11
13
|
# DevLoom Planner Flash
|
|
12
14
|
|
|
13
15
|
ENGLISH ONLY: All output MUST be in English. Never use any other language.
|
|
14
16
|
|
|
17
|
+
BEFORE SCANNING: if `.opencode/devloom/context/briefing.md` exists, read it FIRST and start from its file map — never re-read files it already summarizes.
|
|
18
|
+
|
|
15
19
|
COMPLIANCE: Follow the RULES below + your skill LOAD. No rule may be skipped.
|
|
16
20
|
RULES: EN | SOLID+TDD+CleanArch | tests+regr required | doing<=1 | FILES: use .opencode/devloom/.tmp/ | peer-review for high-risk | degrade on 2x failure
|
|
17
21
|
LOAD: ~/.config/opencode/skills/plan/planning.md|~/.config/opencode/skills/plan/verification-planning.md
|
|
@@ -6,12 +6,16 @@ permission:
|
|
|
6
6
|
edit: allow
|
|
7
7
|
bash: allow
|
|
8
8
|
task: deny
|
|
9
|
+
external_directory:
|
|
10
|
+
"~/.config/opencode/**": allow
|
|
9
11
|
---
|
|
10
12
|
|
|
11
13
|
# DevLoom Planner Senior
|
|
12
14
|
|
|
13
15
|
ENGLISH ONLY: All output MUST be in English. Never use any other language.
|
|
14
16
|
|
|
17
|
+
BEFORE SCANNING: if `.opencode/devloom/context/briefing.md` exists, read it FIRST and start from its file map — never re-read files it already summarizes.
|
|
18
|
+
|
|
15
19
|
COMPLIANCE: Follow the RULES below + your skill LOAD. No rule may be skipped.
|
|
16
20
|
RULES: EN | SOLID+TDD+CleanArch | tests+regr required | doing<=1 | FILES: use .opencode/devloom/.tmp/ | peer-review for high-risk | degrade on 2x failure
|
|
17
21
|
LOAD: ~/.config/opencode/skills/plan/planning.md|~/.config/opencode/skills/plan/verification-planning.md
|
|
@@ -6,12 +6,16 @@ permission:
|
|
|
6
6
|
edit: allow
|
|
7
7
|
bash: allow
|
|
8
8
|
task: deny
|
|
9
|
+
external_directory:
|
|
10
|
+
"~/.config/opencode/**": allow
|
|
9
11
|
---
|
|
10
12
|
|
|
11
13
|
# DevLoom Planner
|
|
12
14
|
|
|
13
15
|
ENGLISH ONLY: All output MUST be in English. Never use any other language.
|
|
14
16
|
|
|
17
|
+
BEFORE SCANNING: if `.opencode/devloom/context/briefing.md` exists, read it FIRST and start from its file map — never re-read files it already summarizes.
|
|
18
|
+
|
|
15
19
|
COMPLIANCE: Follow the RULES below + your skill LOAD. No rule may be skipped.
|
|
16
20
|
RULES: EN | SOLID+TDD+CleanArch | tests+regr required | doing<=1 | FILES: use .opencode/devloom/.tmp/ | peer-review for high-risk | degrade on 2x failure
|
|
17
21
|
LOAD: ~/.config/opencode/skills/plan/planning.md|~/.config/opencode/skills/plan/verification-planning.md
|
|
@@ -6,12 +6,16 @@ permission:
|
|
|
6
6
|
edit: allow
|
|
7
7
|
bash: allow
|
|
8
8
|
task: deny
|
|
9
|
+
external_directory:
|
|
10
|
+
"~/.config/opencode/**": allow
|
|
9
11
|
---
|
|
10
12
|
|
|
11
13
|
# DevLoom QA Flash
|
|
12
14
|
|
|
13
15
|
ENGLISH ONLY: All output MUST be in English. Never use any other language.
|
|
14
16
|
|
|
17
|
+
BEFORE SCANNING: if `.opencode/devloom/context/briefing.md` exists, read it FIRST and start from its file map — never re-read files it already summarizes.
|
|
18
|
+
|
|
15
19
|
COMPLIANCE: Follow the RULES below + your skill LOAD. No rule may be skipped.
|
|
16
20
|
RULES: EN | SOLID+TDD+CleanArch | tests+regr required | doing<=1 | FILES: use .opencode/devloom/.tmp/ | peer-review for high-risk | degrade on 2x failure
|
|
17
21
|
LOAD: ~/.config/opencode/skills/verify/quality-assurance.md|~/.config/opencode/skills/build/simplify.md
|
package/agents/devloom-qa.md
CHANGED
|
@@ -6,12 +6,16 @@ permission:
|
|
|
6
6
|
edit: allow
|
|
7
7
|
bash: allow
|
|
8
8
|
task: deny
|
|
9
|
+
external_directory:
|
|
10
|
+
"~/.config/opencode/**": allow
|
|
9
11
|
---
|
|
10
12
|
|
|
11
13
|
# DevLoom QA
|
|
12
14
|
|
|
13
15
|
ENGLISH ONLY: All output MUST be in English. Never use any other language.
|
|
14
16
|
|
|
17
|
+
BEFORE SCANNING: if `.opencode/devloom/context/briefing.md` exists, read it FIRST and start from its file map — never re-read files it already summarizes.
|
|
18
|
+
|
|
15
19
|
COMPLIANCE: Follow the RULES below + your skill LOAD. No rule may be skipped.
|
|
16
20
|
RULES: EN | SOLID+TDD+CleanArch | tests+regr required | doing<=1 | FILES: use .opencode/devloom/.tmp/ | peer-review for high-risk | degrade on 2x failure
|
|
17
21
|
LOAD: ~/.config/opencode/skills/verify/quality-assurance.md|~/.config/opencode/skills/build/simplify.md
|
|
@@ -6,12 +6,16 @@ permission:
|
|
|
6
6
|
edit: allow
|
|
7
7
|
bash: allow
|
|
8
8
|
task: deny
|
|
9
|
+
external_directory:
|
|
10
|
+
"~/.config/opencode/**": allow
|
|
9
11
|
---
|
|
10
12
|
|
|
11
13
|
# DevLoom Security Senior
|
|
12
14
|
|
|
13
15
|
ENGLISH ONLY: All output MUST be in English. Never use any other language.
|
|
14
16
|
|
|
17
|
+
BEFORE SCANNING: if `.opencode/devloom/context/briefing.md` exists, read it FIRST and start from its file map — never re-read files it already summarizes.
|
|
18
|
+
|
|
15
19
|
COMPLIANCE: Follow the RULES below + your skill LOAD. No rule may be skipped.
|
|
16
20
|
RULES: EN | SOLID+TDD+CleanArch | tests+regr required | doing<=1 | FILES: use .opencode/devloom/.tmp/ | peer-review for high-risk | degrade on 2x failure
|
|
17
21
|
LOAD: ~/.config/opencode/skills/review/security-review.md
|
|
@@ -6,12 +6,16 @@ permission:
|
|
|
6
6
|
edit: allow
|
|
7
7
|
bash: allow
|
|
8
8
|
task: deny
|
|
9
|
+
external_directory:
|
|
10
|
+
"~/.config/opencode/**": allow
|
|
9
11
|
---
|
|
10
12
|
|
|
11
13
|
# DevLoom Security
|
|
12
14
|
|
|
13
15
|
ENGLISH ONLY: All output MUST be in English. Never use any other language.
|
|
14
16
|
|
|
17
|
+
BEFORE SCANNING: if `.opencode/devloom/context/briefing.md` exists, read it FIRST and start from its file map — never re-read files it already summarizes.
|
|
18
|
+
|
|
15
19
|
COMPLIANCE: Follow the RULES below + your skill LOAD. No rule may be skipped.
|
|
16
20
|
RULES: EN | SOLID+TDD+CleanArch | tests+regr required | doing<=1 | FILES: use .opencode/devloom/.tmp/ | peer-review for high-risk | degrade on 2x failure
|
|
17
21
|
LOAD: ~/.config/opencode/skills/review/security-review.md
|
|
@@ -6,12 +6,16 @@ permission:
|
|
|
6
6
|
edit: allow
|
|
7
7
|
bash: allow
|
|
8
8
|
task: deny
|
|
9
|
+
external_directory:
|
|
10
|
+
"~/.config/opencode/**": allow
|
|
9
11
|
---
|
|
10
12
|
|
|
11
13
|
# DevLoom Verifier
|
|
12
14
|
|
|
13
15
|
ENGLISH ONLY: All output MUST be in English. Never use any other language.
|
|
14
16
|
|
|
17
|
+
BEFORE SCANNING: if `.opencode/devloom/context/briefing.md` exists, read it FIRST and start from its file map — never re-read files it already summarizes.
|
|
18
|
+
|
|
15
19
|
COMPLIANCE: Follow the RULES below + your skill LOAD. No rule may be skipped.
|
|
16
20
|
RULES: EN | SOLID+TDD+CleanArch | tests+regr required | doing<=1 | FILES: use .opencode/devloom/.tmp/ | peer-review for high-risk | degrade on 2x failure
|
|
17
21
|
LOAD: ~/.config/opencode/skills/verify/app-verification.md
|
package/agents/devloom-vision.md
CHANGED
|
@@ -12,12 +12,16 @@ permission:
|
|
|
12
12
|
grep: deny
|
|
13
13
|
webfetch: deny
|
|
14
14
|
task: deny
|
|
15
|
+
external_directory:
|
|
16
|
+
"~/.config/opencode/**": allow
|
|
15
17
|
---
|
|
16
18
|
|
|
17
19
|
# DevLoom Vision
|
|
18
20
|
|
|
19
21
|
ENGLISH ONLY: All output MUST be in English. Never use any other language.
|
|
20
22
|
|
|
23
|
+
BEFORE SCANNING: if `.opencode/devloom/context/briefing.md` exists, read it FIRST and start from its file map — never re-read files it already summarizes.
|
|
24
|
+
|
|
21
25
|
## ROLE — STRICT
|
|
22
26
|
|
|
23
27
|
You are a **read-only image description machine**. Your ONLY job:
|
|
@@ -12,12 +12,16 @@ permission:
|
|
|
12
12
|
grep: deny
|
|
13
13
|
webfetch: deny
|
|
14
14
|
task: deny
|
|
15
|
+
external_directory:
|
|
16
|
+
"~/.config/opencode/**": allow
|
|
15
17
|
---
|
|
16
18
|
|
|
17
19
|
# DevLoom Visual Critic
|
|
18
20
|
|
|
19
21
|
ENGLISH ONLY: All output MUST be in English. Never use any other language.
|
|
20
22
|
|
|
23
|
+
BEFORE SCANNING: if `.opencode/devloom/context/briefing.md` exists, read it FIRST and start from its file map — never re-read files it already summarizes.
|
|
24
|
+
|
|
21
25
|
## ROLE — STRICT
|
|
22
26
|
|
|
23
27
|
You are an INDEPENDENT visual judge. You are READ-ONLY. You receive a brief, the design memory, screenshots/rendered state, viewport info, and the user goal. You produce visual judgment — nothing else.
|
|
@@ -12,12 +12,16 @@ permission:
|
|
|
12
12
|
patch: deny
|
|
13
13
|
webfetch: deny
|
|
14
14
|
task: deny
|
|
15
|
+
external_directory:
|
|
16
|
+
"~/.config/opencode/**": allow
|
|
15
17
|
---
|
|
16
18
|
|
|
17
19
|
# DevLoom Visual Director
|
|
18
20
|
|
|
19
21
|
ENGLISH ONLY: All output MUST be in English. Never use any other language.
|
|
20
22
|
|
|
23
|
+
BEFORE SCANNING: if `.opencode/devloom/context/briefing.md` exists, read it FIRST and start from its file map — never re-read files it already summarizes.
|
|
24
|
+
|
|
21
25
|
## ROLE — STRICT
|
|
22
26
|
|
|
23
27
|
You make VISUAL DECISIONS. You are READ-ONLY regarding application implementation. You may inspect requirements, plans, project code, existing design systems, screenshots, design references, and project context — you must NOT implement, edit, or create any file, and must NOT run shell commands.
|
|
@@ -44,6 +44,6 @@ node "$PROFILE_MJS" current 2>&1
|
|
|
44
44
|
- `@devloom-visual-director` — ask for UI visual direction / a design brief
|
|
45
45
|
- `@devloom-visual-critic` — ask for an independent screenshot critique
|
|
46
46
|
|
|
47
|
-
Switch profiles: `/devloom-go`, `/devloom-go-economy`, `/devloom-free`, `/devloom-mimo`
|
|
47
|
+
Switch profiles: `/devloom-go`, `/devloom-go-economy`, `/devloom-free`, `/devloom-mimo`, `/devloom-deepseek-mimo`
|
|
48
48
|
|
|
49
49
|
After switching profiles, restart opencode (or continue with `opencode --continue`) to see the updated profile and agents in the sidebar. If the sidebar does not reflect the current DevLoom code, run `/devloom-refresh`.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "DevLoom DeepSeek+MiMo: fast general roles on DeepSeek V4.1, graphical/complex roles on MiMo V2.6"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# DevLoom DeepSeek+MiMo
|
|
6
|
+
|
|
7
|
+
Switch DevLoom to the hybrid profile: the 7 general roles (orchestrator, planner, developer, qa, verifier, security, documenter) resolve to DeepSeek V4.1 Flash for fast everyday work; the graphical/complex roles (vision, visual-director, visual-critic) resolve to the MiMo V2.6 Flash candidate chain (`mimo/mimo-v2.6-flash` → `xiaomi/mimo-v2.6-flash` → `opencode-go/mimo-v2.6-flash`), against `opencode models`. DeepSeek chain: `opencode-go/deepseek-v4.1-flash`.
|
|
8
|
+
|
|
9
|
+
!`PM="$HOME/.config/opencode/commands/profile.mjs"; [ -f "$PM" ] || PM="$HOME/.config/opencode/devloom-scripts/profile.mjs"; [ -f "$PM" ] || { echo "profile.mjs not found - reinstall DevLoom"; exit 1; }; node "$PM" set deepseek-mimo 2>&1; node "$PM" current 2>&1`
|
|
10
|
+
|
|
11
|
+
If either chain resolves to nothing the profile is NOT activated and the attempted candidates are printed — fail fast, no unrelated substitution. On success: profile applied — restart opencode (or continue with `opencode --continue`) to see the updated profile and agents in the sidebar.
|
package/package.json
CHANGED
package/postinstall.mjs
CHANGED
|
@@ -11,9 +11,8 @@ export function getConfigDir(_platform = platform(), _homedir = homedir()) {
|
|
|
11
11
|
if (_platform === "win32") {
|
|
12
12
|
return resolve(process.env.APPDATA ?? _homedir, "opencode")
|
|
13
13
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
14
|
+
// OpenCode resolves its global config from the XDG path on macOS too
|
|
15
|
+
// (~/.config/opencode), not ~/Library/Application Support.
|
|
17
16
|
return resolve(
|
|
18
17
|
process.env.XDG_CONFIG_HOME ?? join(_homedir, ".config"),
|
|
19
18
|
"opencode"
|
|
@@ -148,7 +147,7 @@ const AGENTS = [
|
|
|
148
147
|
"devloom-documenter-flash",
|
|
149
148
|
]
|
|
150
149
|
|
|
151
|
-
const COMMANDS = ["devloom", "devloom-status", "devloom-resume", "devloom-init", "devloom-save", "devloom-auto", "devloom-go", "devloom-go-economy", "devloom-go-flash", "devloom-deepseek", "devloom-free", "devloom-mimo", "devloom-plan", "devloom-context", "devloom-agents", "devloom-refresh"]
|
|
150
|
+
const COMMANDS = ["devloom", "devloom-status", "devloom-resume", "devloom-init", "devloom-save", "devloom-auto", "devloom-go", "devloom-go-economy", "devloom-go-flash", "devloom-deepseek", "devloom-free", "devloom-mimo", "devloom-deepseek-mimo", "devloom-plan", "devloom-context", "devloom-agents", "devloom-refresh"]
|
|
152
151
|
|
|
153
152
|
const SCRIPTS_DIR = resolve(CONFIG_DIR, "devloom-scripts")
|
|
154
153
|
|
|
@@ -200,6 +199,11 @@ function main() {
|
|
|
200
199
|
resolve(COMMANDS_DIR, "model-capabilities.mjs"),
|
|
201
200
|
"Model capabilities helper"
|
|
202
201
|
)
|
|
202
|
+
installFile(
|
|
203
|
+
resolve(__dirname, "scripts", "briefing.mjs"),
|
|
204
|
+
resolve(COMMANDS_DIR, "briefing.mjs"),
|
|
205
|
+
"Briefing change tracker"
|
|
206
|
+
)
|
|
203
207
|
installFile(
|
|
204
208
|
resolve(__dirname, "scripts", "plugin-cache.mjs"),
|
|
205
209
|
resolve(COMMANDS_DIR, "plugin-cache.mjs"),
|
|
@@ -95,6 +95,15 @@ A single multimodal stack: every role — including vision, visual-director, and
|
|
|
95
95
|
|---|---|
|
|
96
96
|
| all 10 roles | resolved MiMo V2.6 Flash candidate |
|
|
97
97
|
|
|
98
|
+
### deepseek-mimo (hybrid, tier unlocked)
|
|
99
|
+
|
|
100
|
+
Fast everyday work on DeepSeek V4.1 Flash; graphical/complex work on MiMo V2.6 Flash. The 7 general roles (orchestrator, planner, developer, qa, verifier, security, documenter) resolve to `opencode-go/deepseek-v4.1-flash`; vision, visual-director, and visual-critic resolve through the `MIMO_V26_FLASH_CANDIDATES` chain. Both chains resolve strictly against `opencode models` — if either finds nothing the profile exits code 1 with the attempted candidates, never an unrelated substitution. Activate with `/devloom-deepseek-mimo`.
|
|
101
|
+
|
|
102
|
+
| Role | Model |
|
|
103
|
+
|---|---|
|
|
104
|
+
| 7 general roles | opencode-go/deepseek-v4.1-flash |
|
|
105
|
+
| vision, visual-director, visual-critic | resolved MiMo V2.6 Flash candidate |
|
|
106
|
+
|
|
98
107
|
## Model Guidance
|
|
99
108
|
|
|
100
109
|
### When to Use GLM 5.2
|
|
@@ -157,7 +166,7 @@ In `.opencode/devloom/project/config.json`:
|
|
|
157
166
|
}
|
|
158
167
|
```
|
|
159
168
|
|
|
160
|
-
Valid values: `"go"`, `"go-economy"`, `"deepseek"`, `"go-flash"`, `"free"`, `"mimo"`.
|
|
169
|
+
Valid values: `"go"`, `"go-economy"`, `"deepseek"`, `"go-flash"`, `"free"`, `"mimo"`, `"deepseek-mimo"`.
|
|
161
170
|
|
|
162
171
|
### Overrides
|
|
163
172
|
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Incremental briefing tracker: answers "what changed since the briefing was
|
|
3
|
+
// written?" so orchestrator/sub-agents re-read ONLY modified files.
|
|
4
|
+
//
|
|
5
|
+
// Signal: sha256 content fingerprints recorded at init/touch — the same
|
|
6
|
+
// content-addressed idea as git, but immune to commit/uncommitted state (a
|
|
7
|
+
// file already re-read after `touch` never reappears until it truly changes).
|
|
8
|
+
// The git baseCommit is kept for provenance/status only.
|
|
9
|
+
//
|
|
10
|
+
// Commands:
|
|
11
|
+
// briefing.mjs init <ticket> create briefing.md stub + record fingerprints
|
|
12
|
+
// briefing.mjs changed print changed paths (one per line), exit 0
|
|
13
|
+
// briefing.mjs touch re-anchor after the briefing was patched
|
|
14
|
+
// briefing.mjs status show ticket/base/counters
|
|
15
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync } from "fs"
|
|
16
|
+
import { execSync } from "child_process"
|
|
17
|
+
import { resolve, dirname, join, relative, sep } from "path"
|
|
18
|
+
import { fileURLToPath } from "url"
|
|
19
|
+
import { createHash } from "crypto"
|
|
20
|
+
|
|
21
|
+
const DIR = ".opencode/devloom/context"
|
|
22
|
+
export const BRIEFING_MD = `${DIR}/briefing.md`
|
|
23
|
+
export const BRIEFING_JSON = `${DIR}/briefing.json`
|
|
24
|
+
|
|
25
|
+
const EXCLUDE_DIRS = new Set([
|
|
26
|
+
"node_modules", ".git", "dist", ".angular", ".next", "build", "coverage",
|
|
27
|
+
"logs", ".tmp", "tmp", ".opencode", ".idea", ".vscode",
|
|
28
|
+
])
|
|
29
|
+
const EXCLUDE_FILES = /^(package-lock\.json|pnpm-lock\.yaml|yarn\.lock|\.DS_Store|.*\.log)$/
|
|
30
|
+
|
|
31
|
+
export function walkFiles(root = process.cwd()) {
|
|
32
|
+
const out = []
|
|
33
|
+
const stack = [root]
|
|
34
|
+
while (stack.length > 0) {
|
|
35
|
+
const dir = stack.pop()
|
|
36
|
+
let entries = []
|
|
37
|
+
try {
|
|
38
|
+
entries = readdirSync(dir, { withFileTypes: true })
|
|
39
|
+
} catch {
|
|
40
|
+
continue
|
|
41
|
+
}
|
|
42
|
+
for (const entry of entries) {
|
|
43
|
+
if (entry.name.startsWith(".") && entry.isDirectory() && entry.name !== ".ai") continue
|
|
44
|
+
const full = join(dir, entry.name)
|
|
45
|
+
if (entry.isDirectory()) {
|
|
46
|
+
if (!EXCLUDE_DIRS.has(entry.name)) stack.push(full)
|
|
47
|
+
continue
|
|
48
|
+
}
|
|
49
|
+
if (!entry.isFile() || EXCLUDE_FILES.test(entry.name)) continue
|
|
50
|
+
const rel = relative(root, full).split(sep).join("/")
|
|
51
|
+
out.push(rel)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return out.sort()
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function hashFile(rel, root = process.cwd()) {
|
|
58
|
+
try {
|
|
59
|
+
const data = readFileSync(join(root, rel))
|
|
60
|
+
return createHash("sha256").update(data).digest("hex").slice(0, 12)
|
|
61
|
+
} catch {
|
|
62
|
+
return null
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function computeHashes(paths, root = process.cwd()) {
|
|
67
|
+
const files = {}
|
|
68
|
+
for (const p of paths) files[p] = hashFile(p, root)
|
|
69
|
+
return files
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function diffHashes(previous, paths, root = process.cwd()) {
|
|
73
|
+
const changed = []
|
|
74
|
+
const prev = previous || {}
|
|
75
|
+
for (const p of paths) {
|
|
76
|
+
if (prev[p] !== hashFile(p, root)) changed.push(p)
|
|
77
|
+
}
|
|
78
|
+
for (const p of Object.keys(prev)) {
|
|
79
|
+
if (!paths.includes(p) && prev[p] !== null) changed.push(p)
|
|
80
|
+
}
|
|
81
|
+
return [...new Set(changed)].sort()
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function run(cmd, cwd = process.cwd()) {
|
|
85
|
+
try {
|
|
86
|
+
return execSync(cmd, { cwd, encoding: "utf8", timeout: 15000 }).trim()
|
|
87
|
+
} catch {
|
|
88
|
+
return null
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function gitAvailable(cwd = process.cwd()) {
|
|
93
|
+
return run("git rev-parse --is-inside-work-tree", cwd) === "true"
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function gitHead(cwd = process.cwd()) {
|
|
97
|
+
const out = run("git rev-parse HEAD", cwd)
|
|
98
|
+
return out && !out.includes("fatal") ? out : null
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function readJson() {
|
|
102
|
+
try {
|
|
103
|
+
return JSON.parse(readFileSync(BRIEFING_JSON, "utf8"))
|
|
104
|
+
} catch {
|
|
105
|
+
return null
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function writeJson(data) {
|
|
110
|
+
mkdirSync(DIR, { recursive: true })
|
|
111
|
+
writeFileSync(BRIEFING_JSON, JSON.stringify(data, null, 2) + "\n")
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function init(ticket = "ticket") {
|
|
115
|
+
mkdirSync(DIR, { recursive: true })
|
|
116
|
+
const paths = walkFiles()
|
|
117
|
+
const useGit = gitAvailable()
|
|
118
|
+
const data = {
|
|
119
|
+
ticket,
|
|
120
|
+
baseCommit: useGit ? gitHead() : null,
|
|
121
|
+
files: computeHashes(paths),
|
|
122
|
+
updatedAt: new Date().toISOString(),
|
|
123
|
+
}
|
|
124
|
+
writeJson(data)
|
|
125
|
+
if (!existsSync(BRIEFING_MD)) {
|
|
126
|
+
writeFileSync(
|
|
127
|
+
BRIEFING_MD,
|
|
128
|
+
`# Briefing — ${ticket}\n` +
|
|
129
|
+
`> Created: ${data.updatedAt}\n` +
|
|
130
|
+
`> Refresh rule: run \`briefing.mjs changed\`, re-read ONLY those paths, patch this file, then \`briefing.mjs touch\`.\n` +
|
|
131
|
+
`> Every task() prompt starts with: "Read .opencode/devloom/context/briefing.md first — do not re-discover."\n\n` +
|
|
132
|
+
`## Goal\n\n## Constraints\n\n## File map\n\n## Decisions\n`
|
|
133
|
+
)
|
|
134
|
+
}
|
|
135
|
+
return data
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function changed() {
|
|
139
|
+
const data = readJson()
|
|
140
|
+
if (!data) return []
|
|
141
|
+
return diffHashes(data.files, walkFiles())
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function touch() {
|
|
145
|
+
const data = readJson() || init("ticket")
|
|
146
|
+
const paths = walkFiles()
|
|
147
|
+
data.baseCommit = gitAvailable() ? gitHead() : null
|
|
148
|
+
data.files = computeHashes(paths)
|
|
149
|
+
data.updatedAt = new Date().toISOString()
|
|
150
|
+
writeJson(data)
|
|
151
|
+
return data
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export function status() {
|
|
155
|
+
const data = readJson()
|
|
156
|
+
if (!data) {
|
|
157
|
+
console.log("No briefing recorded. Run: briefing.mjs init <ticket>")
|
|
158
|
+
return
|
|
159
|
+
}
|
|
160
|
+
console.log(`Ticket: ${data.ticket}`)
|
|
161
|
+
console.log(`Base commit: ${data.baseCommit || "(no git)"}`)
|
|
162
|
+
console.log(`Tracked files: ${Object.keys(data.files).length}`)
|
|
163
|
+
console.log(`Updated: ${data.updatedAt}`)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function main() {
|
|
167
|
+
const args = process.argv.slice(2)
|
|
168
|
+
const command = args[0] || ""
|
|
169
|
+
switch (command) {
|
|
170
|
+
case "init":
|
|
171
|
+
init(args[1] || "ticket")
|
|
172
|
+
console.log(`Briefing initialized${args[1] ? ` for ${args[1]}` : ""}: ${BRIEFING_MD}`)
|
|
173
|
+
break
|
|
174
|
+
case "changed": {
|
|
175
|
+
const paths = changed()
|
|
176
|
+
for (const p of paths) console.log(p)
|
|
177
|
+
break
|
|
178
|
+
}
|
|
179
|
+
case "touch":
|
|
180
|
+
touch()
|
|
181
|
+
console.log("Briefing anchors refreshed.")
|
|
182
|
+
break
|
|
183
|
+
case "status":
|
|
184
|
+
status()
|
|
185
|
+
break
|
|
186
|
+
default:
|
|
187
|
+
console.log("Usage: briefing.mjs <init <ticket>|changed|touch|status>")
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const isMain = process.argv[1] ? fileURLToPath(import.meta.url) === resolve(process.argv[1]) : false
|
|
192
|
+
if (isMain) main()
|
|
@@ -35,11 +35,36 @@ export const MODEL_FAMILIES = {
|
|
|
35
35
|
verification: "high",
|
|
36
36
|
},
|
|
37
37
|
},
|
|
38
|
+
deepseekV41Flash: {
|
|
39
|
+
id: "deepseekV41Flash",
|
|
40
|
+
label: "DeepSeek V4.1 Flash",
|
|
41
|
+
// Fast lane for general roles. Only verified ids enter the chain; the
|
|
42
|
+
// family pattern still discovers same-family variants at resolution time.
|
|
43
|
+
candidates: [
|
|
44
|
+
"opencode-go/deepseek-v4.1-flash",
|
|
45
|
+
],
|
|
46
|
+
familyPattern: /(^|\/)deepseek-v4\.1/i,
|
|
47
|
+
capabilities: {
|
|
48
|
+
vision: false,
|
|
49
|
+
multimodal: false,
|
|
50
|
+
coding: "high",
|
|
51
|
+
reasoning: "high",
|
|
52
|
+
toolUse: true,
|
|
53
|
+
longContext: true,
|
|
54
|
+
speed: "fast",
|
|
55
|
+
costClass: "low",
|
|
56
|
+
orchestration: true,
|
|
57
|
+
verification: "high",
|
|
58
|
+
},
|
|
59
|
+
},
|
|
38
60
|
}
|
|
39
61
|
|
|
40
62
|
/** MiMo V2.6 Flash candidate chain (re-exported for profile manager + tests). */
|
|
41
63
|
export const MIMO_V26_FLASH_CANDIDATES = MODEL_FAMILIES.mimoV26Flash.candidates
|
|
42
64
|
|
|
65
|
+
/** DeepSeek V4.1 Flash candidate chain (general/fast roles). */
|
|
66
|
+
export const DEEPSEEK_V41_FLASH_CANDIDATES = MODEL_FAMILIES.deepseekV41Flash.candidates
|
|
67
|
+
|
|
43
68
|
/**
|
|
44
69
|
* Vision-capable fallbacks used when a vision-required role (vision,
|
|
45
70
|
* visual-critic) resolves to a text-only model. Ordered by existing DevLoom
|
package/scripts/plugin-cache.mjs
CHANGED
|
@@ -20,12 +20,12 @@ export function getOpenCodeCacheDir(_platform = platform(), _homedir = homedir()
|
|
|
20
20
|
return resolve(_env.LOCALAPPDATA ?? _homedir, "cache", "opencode")
|
|
21
21
|
}
|
|
22
22
|
if (_platform === "darwin") {
|
|
23
|
+
const xdg = resolve(_env.XDG_CACHE_HOME ?? join(_homedir, ".cache"), "opencode")
|
|
23
24
|
const lib = resolve(_homedir, "Library", "Caches", "opencode")
|
|
24
|
-
|
|
25
|
-
//
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return lib
|
|
25
|
+
// OpenCode uses the XDG cache path on macOS too; only fall back to the
|
|
26
|
+
// Library path when that is the one present on disk (older builds).
|
|
27
|
+
if (!existsSync(xdg) && existsSync(lib)) return lib
|
|
28
|
+
return xdg
|
|
29
29
|
}
|
|
30
30
|
return resolve(_env.XDG_CACHE_HOME ?? join(_homedir, ".cache"), "opencode")
|
|
31
31
|
}
|
package/scripts/profile.mjs
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
modelMeetsRole,
|
|
17
17
|
roleRequiresVision,
|
|
18
18
|
MIMO_V26_FLASH_CANDIDATES,
|
|
19
|
+
DEEPSEEK_V41_FLASH_CANDIDATES,
|
|
19
20
|
MODEL_FAMILIES,
|
|
20
21
|
VISION_FALLBACK_CANDIDATES,
|
|
21
22
|
} from "./model-capabilities.mjs"
|
|
@@ -30,6 +31,7 @@ export {
|
|
|
30
31
|
modelMeetsRole,
|
|
31
32
|
roleRequiresVision,
|
|
32
33
|
MIMO_V26_FLASH_CANDIDATES,
|
|
34
|
+
DEEPSEEK_V41_FLASH_CANDIDATES,
|
|
33
35
|
MODEL_FAMILIES,
|
|
34
36
|
VISION_FALLBACK_CANDIDATES,
|
|
35
37
|
}
|
|
@@ -255,6 +257,35 @@ function containsKey(obj, key) {
|
|
|
255
257
|
return Object.prototype.hasOwnProperty.call(obj, key)
|
|
256
258
|
}
|
|
257
259
|
|
|
260
|
+
// Strict family resolution used by `deepseek-mimo`: resolves a candidate chain
|
|
261
|
+
// against the live catalog and FAILS FAST with diagnostics when nothing
|
|
262
|
+
// matches. Never substitutes unrelated models — a blocked dispatch is worse
|
|
263
|
+
// than a clear exit the user can act on.
|
|
264
|
+
function resolveStrictCandidate(label, candidates, available, familyPattern, profileName) {
|
|
265
|
+
const resolved = resolveModelCandidate(candidates, available, { familyPattern })
|
|
266
|
+
if (!resolved.model) {
|
|
267
|
+
console.error(`${label} is not available in this environment.`)
|
|
268
|
+
console.error("")
|
|
269
|
+
console.error("Attempted candidates:")
|
|
270
|
+
for (const candidate of resolved.attempted) {
|
|
271
|
+
console.error(` ${candidate} (not found)`)
|
|
272
|
+
}
|
|
273
|
+
const compatible = familyPattern ? available.filter((m) => familyPattern.test(m)) : []
|
|
274
|
+
console.error("")
|
|
275
|
+
if (compatible.length > 0) {
|
|
276
|
+
console.error(`Available compatible ${label} models:`)
|
|
277
|
+
for (const m of compatible) console.error(` ${m}`)
|
|
278
|
+
} else {
|
|
279
|
+
console.error(`No compatible ${label} models are available. Run: opencode models`)
|
|
280
|
+
}
|
|
281
|
+
console.error("")
|
|
282
|
+
console.error(`The ${profileName} profile was NOT activated. No unrelated models were substituted.`)
|
|
283
|
+
console.error("Valid profiles: auto, go, go-economy, deepseek, glm, go-flash, mimo, deepseek-mimo, free")
|
|
284
|
+
process.exit(1)
|
|
285
|
+
}
|
|
286
|
+
return resolved
|
|
287
|
+
}
|
|
288
|
+
|
|
258
289
|
export function applyFallbacks(models, unavailable, available) {
|
|
259
290
|
const result = { ...models }
|
|
260
291
|
const fallbacks = {}
|
|
@@ -367,7 +398,7 @@ export function cmdSet(profileName) {
|
|
|
367
398
|
const available = detectAvailableModels()
|
|
368
399
|
const hasGo = hasGoModels(available)
|
|
369
400
|
|
|
370
|
-
if ((profileName === "go" || profileName === "go-economy" || profileName === "deepseek" || profileName === "glm" || profileName === "go-flash") && !hasGo) {
|
|
401
|
+
if ((profileName === "go" || profileName === "go-economy" || profileName === "deepseek" || profileName === "glm" || profileName === "go-flash" || profileName === "deepseek-mimo") && !hasGo) {
|
|
371
402
|
console.error("No OpenCode Go models detected. Run: opencode /connect to add OpenCode Go.")
|
|
372
403
|
console.error("Fall back to: /devloom-auto or /devloom-free")
|
|
373
404
|
process.exit(1)
|
|
@@ -450,7 +481,7 @@ export function cmdSet(profileName) {
|
|
|
450
481
|
}
|
|
451
482
|
console.error("")
|
|
452
483
|
console.error("The mimo profile was NOT activated. No unrelated models were substituted.")
|
|
453
|
-
console.error("Valid profiles: auto, go, go-economy, deepseek, glm, go-flash, mimo, free")
|
|
484
|
+
console.error("Valid profiles: auto, go, go-economy, deepseek, glm, go-flash, mimo, deepseek-mimo, free")
|
|
454
485
|
process.exit(1)
|
|
455
486
|
}
|
|
456
487
|
models = Object.fromEntries(ALL_AGENTS.map((agent) => [agent, resolved.model]))
|
|
@@ -463,6 +494,39 @@ export function cmdSet(profileName) {
|
|
|
463
494
|
}
|
|
464
495
|
}
|
|
465
496
|
}
|
|
497
|
+
} else if (profileName === "deepseek-mimo") {
|
|
498
|
+
// Hybrid: DeepSeek V4.1 Flash is the fast lane for the 7 general roles;
|
|
499
|
+
// MiMo V2.6 Flash serves the graphical/complex visual roles. Both chains
|
|
500
|
+
// resolve strictly — exit 1 with diagnostics instead of substituting.
|
|
501
|
+
const deepseekResolved = resolveStrictCandidate(
|
|
502
|
+
"DeepSeek V4.1 Flash",
|
|
503
|
+
DEEPSEEK_V41_FLASH_CANDIDATES,
|
|
504
|
+
available,
|
|
505
|
+
MODEL_FAMILIES.deepseekV41Flash.familyPattern,
|
|
506
|
+
"deepseek-mimo"
|
|
507
|
+
)
|
|
508
|
+
const mimoResolved = resolveStrictCandidate(
|
|
509
|
+
"MiMo V2.6 Flash",
|
|
510
|
+
MIMO_V26_FLASH_CANDIDATES,
|
|
511
|
+
available,
|
|
512
|
+
MODEL_FAMILIES.mimoV26Flash.familyPattern,
|
|
513
|
+
"deepseek-mimo"
|
|
514
|
+
)
|
|
515
|
+
const visualRoles = new Set(["vision", "visual-director", "visual-critic"])
|
|
516
|
+
models = Object.fromEntries(
|
|
517
|
+
ALL_AGENTS.map((agent) => [agent, visualRoles.has(agent) ? mimoResolved.model : deepseekResolved.model])
|
|
518
|
+
)
|
|
519
|
+
const recordChainFallback = (agent, resolved, chainLabel) => {
|
|
520
|
+
if (resolved.exact) return
|
|
521
|
+
fallbacks[agent] = {
|
|
522
|
+
from: `${chainLabel} (candidate chain)`,
|
|
523
|
+
to: resolved.model,
|
|
524
|
+
reason: "family fallback",
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
for (const agent of ALL_AGENTS) {
|
|
528
|
+
recordChainFallback(agent, visualRoles.has(agent) ? mimoResolved : deepseekResolved, visualRoles.has(agent) ? "mimo-v2.6-flash" : "deepseek-v4.1-flash")
|
|
529
|
+
}
|
|
466
530
|
} else if (profileName === "auto") {
|
|
467
531
|
if (hasGo) {
|
|
468
532
|
models = { ...PROFILES["go-flash"] }
|
|
@@ -479,7 +543,7 @@ export function cmdSet(profileName) {
|
|
|
479
543
|
}
|
|
480
544
|
} else {
|
|
481
545
|
console.error("Unknown profile:", profileName)
|
|
482
|
-
console.error("Valid profiles: auto, go, go-economy, deepseek, glm, go-flash, mimo, free")
|
|
546
|
+
console.error("Valid profiles: auto, go, go-economy, deepseek, glm, go-flash, mimo, deepseek-mimo, free")
|
|
483
547
|
process.exit(1)
|
|
484
548
|
}
|
|
485
549
|
|
|
@@ -648,7 +712,7 @@ function main() {
|
|
|
648
712
|
|
|
649
713
|
switch (command) {
|
|
650
714
|
case "set":
|
|
651
|
-
if (!args[1]) { console.error("Usage: devloom profile set <auto|go|go-economy|deepseek|glm|go-flash|mimo|free>"); process.exit(1) }
|
|
715
|
+
if (!args[1]) { console.error("Usage: devloom profile set <auto|go|go-economy|deepseek|glm|go-flash|mimo|deepseek-mimo|free>"); process.exit(1) }
|
|
652
716
|
cmdSet(args[1])
|
|
653
717
|
console.log(`DevLoom profile changed to: ${args[1]}`)
|
|
654
718
|
if (args[1] !== "free") {
|
|
@@ -678,7 +742,7 @@ function main() {
|
|
|
678
742
|
console.log("DevLoom Profile Manager")
|
|
679
743
|
console.log("")
|
|
680
744
|
console.log("Commands:")
|
|
681
|
-
console.log(" devloom profile set <auto|go|go-economy|deepseek|glm|go-flash|mimo|free>")
|
|
745
|
+
console.log(" devloom profile set <auto|go|go-economy|deepseek|glm|go-flash|mimo|deepseek-mimo|free>")
|
|
682
746
|
console.log(" devloom profile tier <senior|standard>")
|
|
683
747
|
console.log(" devloom profile current")
|
|
684
748
|
console.log(" devloom profile validate")
|