@s-berdia/opencode-router 0.0.0-stage → 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 s-berdia
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,203 @@
1
- # Temporary Holding Version
1
+ # opencode-router
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Automatic model routing for [OpenCode](https://opencode.ai) on the **Go**, **Go Plus**, and **Free** plans.
4
+
5
+ ![opencode-router demo: the scorecard gives each agent a model, and the build agent changes to the next model at 85% of its 5-hour limit](docs/router-demo.gif)
6
+
7
+ [Watch the demo in full quality (MP4, 25 seconds)](docs/router-demo.mp4?raw=true)
8
+
9
+ opencode-router gives each OpenCode agent the best model for its job and for your plan.
10
+ It records how much of your quota each model uses. When a model is near its limit, the
11
+ router moves the agent to the next model in its list. When the limit resets, the router
12
+ moves the agent back.
13
+
14
+ For full step-by-step instructions, read the [usage guide](./USAGE.md). Before you use
15
+ the router, read its [known limits](./USAGE.md#11-known-limits).
16
+
17
+ ## Features
18
+
19
+ - **One model per job.** The `plan` agent gets the most intelligent model that your plan
20
+ can supply. The `build` agent gets a fast model with a high limit. The `explore` agent and
21
+ the internal helpers (titles, summaries, compaction) get fast, low-cost models.
22
+ - **Plan-aware.** Three plan profiles: `go`, `go-plus`, and `free`. Each profile uses the
23
+ monthly allowance of each model to calculate how many tokens the model can supply in
24
+ 5 hours.
25
+ - **Automatic failover.** The `plan`, `build`, `general`, and `explore` agents each have a
26
+ ranked list of up to 4 models. The router changes to the next model before a limit is
27
+ reached, and after a rate-limit error.
28
+ - **Live apply.** The router changes the models in the running OpenCode session. You do
29
+ not have to restart OpenCode after a refresh.
30
+ - **Clear results.** A scorecard shows each model and its scores. With `--verbose`, it
31
+ also shows the source of each score.
32
+
33
+ ## Requirements
34
+
35
+ | Item | Version or condition |
36
+ | :-- | :-- |
37
+ | OpenCode | A version that supports plugins (tested with plugin API 1.19) |
38
+ | Node.js | 20 or later, on your `PATH` (the slash commands run `node`) |
39
+ | OpenCode plan | Go, Go Plus, or no subscription (free models only) |
40
+ | Model catalog | Start OpenCode one time before you install. OpenCode then writes `~/.cache/opencode/models.json`. |
41
+
42
+ ## Quick start
43
+
44
+ 1. Open your global OpenCode config file in a text editor:
45
+ - Windows: `C:\Users\<your-user-name>\.config\opencode\opencode.json`
46
+ - macOS and Linux: `~/.config/opencode/opencode.json`
47
+
48
+ If the file does not exist, make it. If you have `opencode.jsonc`, use that file.
49
+ 2. Add the plugin to the `plugin` list:
50
+
51
+ ```json
52
+ {
53
+ "$schema": "https://opencode.ai/config.json",
54
+ "plugin": ["@s-berdia/opencode-router"]
55
+ }
56
+ ```
57
+
58
+ 3. Save the file. Close OpenCode and start it again.
59
+ 4. In the OpenCode prompt, type this command and push Enter:
60
+
61
+ ```text
62
+ /refresh-routing
63
+ ```
64
+
65
+ 5. Read the scorecard. It shows the model for each agent.
66
+
67
+ The router now selects models automatically. You do not have to do more.
68
+
69
+ ## Commands
70
+
71
+ ### In OpenCode
72
+
73
+ | Command | What it does |
74
+ | :-- | :-- |
75
+ | `/refresh-routing` | Calculate the routing table again, apply it, and show the scorecard |
76
+ | `/routing-status` | Show the model in use for each agent (after failover) and its 5-hour quota use |
77
+ | `/routing-plan go-plus` | Save a plan profile (`go`, `go-plus`, or `free`) and apply it immediately |
78
+ | `/routing-eval` | Send one test prompt to the `build` models and write a report |
79
+
80
+ ### In a terminal
81
+
82
+ The package also has a command-line tool. Use it for scripts, CI, or scheduled jobs.
83
+
84
+ ```bash
85
+ npx @s-berdia/opencode-router refresh --dry-run # show the scorecard, write nothing
86
+ npx @s-berdia/opencode-router refresh --plan go # calculate and write opencode.json
87
+ npx @s-berdia/opencode-router status # models in use and quota use
88
+ npx @s-berdia/opencode-router plan go-plus # save the plan profile and rebuild
89
+ npx @s-berdia/opencode-router cat # catalog file, date, model count
90
+ npx @s-berdia/opencode-router install --scope global # write slash-command files
91
+ npx @s-berdia/opencode-router --help # all commands and options
92
+ ```
93
+
94
+ These commands work in PowerShell, CMD, Git Bash, and macOS or Linux shells.
95
+
96
+ | Option | Meaning |
97
+ | :-- | :-- |
98
+ | `--plan <go\|go-plus\|free>` | Plan profile for this run |
99
+ | `--scope <project\|global>` | Which `opencode.json` to write. Default: `project` in a project folder, else `global` |
100
+ | `--catalog <file>` | Use a different `models.json` catalog file |
101
+ | `--dry-run` | Do not write `opencode.json` |
102
+ | `--no-apply` | Write `opencode.json`, but do not send the change to a running server |
103
+ | `--json` | Print JSON, not a table |
104
+ | `--verbose` | Show the source of each score in the scorecard |
105
+
106
+ ## Configuration
107
+
108
+ The router works with no configuration. To change its behavior, make a file named
109
+ `router.config.json`:
110
+
111
+ - Global (all projects): `~/.config/opencode/router.config.json`
112
+ - One project: `<project>/.opencode/router.config.json`
113
+
114
+ Values in the project file replace values in the global file. If a file has a JSON error
115
+ or a value that is not valid, the router ignores it and shows a note in the scorecard.
116
+
117
+ ```json
118
+ {
119
+ "plan": "go",
120
+ "softThreshold": 0.85,
121
+ "privacy": { "freeModelsOk": true },
122
+ "denyModels": ["*-preview"],
123
+ "allowModels": [],
124
+ "weights": { "build": { "intelligence": 0.4, "speed": 0.25, "endurance": 0.35 } },
125
+ "scores": { "opencode-go/deepseek-v4.1-flash": { "intelligence": 82 } }
126
+ }
127
+ ```
128
+
129
+ | Key | Default | Meaning |
130
+ | :-- | :-- | :-- |
131
+ | `plan` | detected from your catalog | `go`, `go-plus`, or `free` |
132
+ | `chainDepth` | 4 for agents, 3 for helpers | Number of models in each failover list. `roles.<role>.chainDepth` wins over it |
133
+ | `softThreshold` | `0.85` | Change to the next model when 5-hour use reaches this part of the 5-hour limit (0.85 = 85%) |
134
+ | `privacy.freeModelsOk` | `true` | `false` keeps `plan`, `build`, and `general` off free models |
135
+ | `denyModels` | `[]` | Model IDs to never use. `*` and `?` wildcards are permitted |
136
+ | `allowModels` | `[]` | If not empty, use only these model IDs |
137
+ | `weights.<role>` | see `model-scores.json` | Weights for `intelligence`, `speed`, and `endurance`. Use values that add up to 1 |
138
+ | `scores.<model-id>` | see `model-scores.json` | Your own `intelligence` and `speed` values (0 to 100) |
139
+ | `roles.<role>` | see `model-scores.json` | Change `variant`, `chainDepth`, `requires`, `preferFree`, or `diversifyFamily` for one role |
140
+ | `blend` | `{ "input": 0.75, "output": 0.25, "cacheRead": 0.1 }` | Token mix used to calculate the cost of one million tokens |
141
+ | `enduranceScale` | `{ "minTokensPer5h": 0.25, "maxTokensPer5h": 40 }` | Millions of tokens per 5 hours that give an endurance score of 0 and 100 |
142
+ | `feeds` | `{ "enabled": false }` | Optional benchmark feed: `{ "enabled": true, "url": "https://...", "timeoutMs": 5000 }` |
143
+
144
+ The [usage guide](./USAGE.md#6-change-the-router-settings) has examples for each key.
145
+
146
+ ## How scoring works
147
+
148
+ ```text
149
+ score = w_intelligence * intelligence
150
+ + w_speed * speed
151
+ + w_endurance * endurance
152
+ + plan preference
153
+ - penalty for a model that has no entry in model-scores.json
154
+ ```
155
+
156
+ - **Intelligence and speed** (0 to 100) come from, in this order: your `scores`, the
157
+ benchmark feed (if enabled), and then name patterns in `model-scores.json`.
158
+ - **Endurance** (0 to 100) comes from your quota. The router divides the 5-hour allowance
159
+ (20% of the monthly allowance) by the cost of one million tokens. A free model, or a
160
+ model with no limit, gets 100.
161
+ - **Plan preference** puts the subscription models that you pay for before free models.
162
+ The `explore` agent and the internal helpers prefer free models.
163
+ - With `--verbose`, the scorecard shows the source of each score: `override` (your
164
+ `scores` or `model-scores.json`), `feed`, `cap` (from quota), `heuristic` (name pattern),
165
+ or `default` (no match).
166
+
167
+ ## Files that the router writes
168
+
169
+ | File | Contents |
170
+ | :-- | :-- |
171
+ | `~/.config/opencode/router/ledger.json` | Spend and tokens per model for 5 hours, 7 days, and 30 days |
172
+ | `~/.config/opencode/router/routing-table.json` | The last routing table |
173
+ | `~/.config/opencode/router/last-apply.json` | The result of the last live apply |
174
+ | `~/.config/opencode/router/eval-report.md` | The report of the last `/routing-eval` |
175
+ | `opencode.json` or `opencode.jsonc` (global, or the project file with `--scope project`) | `model`, `small_model`, and `agent.<role>.model` and `variant`. Comments and all other keys stay. A file with a JSON error is not changed |
176
+
177
+ If `XDG_CONFIG_HOME` is set, the router uses `$XDG_CONFIG_HOME/opencode` in place of
178
+ `~/.config/opencode`. Do not commit the `router/` folder. It contains your usage data.
179
+
180
+ ## Privacy
181
+
182
+ Models with `-free` in their name can collect your prompts for training. The scorecard
183
+ marks them `free*`. To keep your main work off these models, set
184
+ `"privacy": { "freeModelsOk": false }`. To never use them, set `"denyModels": ["*-free"]`.
185
+
186
+ ## Development
187
+
188
+ ```bash
189
+ git clone https://github.com/s-berdia/Opencode_router.git
190
+ cd Opencode_router
191
+ npm install
192
+ npm run build # compile to dist/
193
+ npm test # run the tests
194
+ npm run typecheck # check the types
195
+ ```
196
+
197
+ To use your local build in OpenCode, put the absolute path of the folder in the `plugin`
198
+ list. Example for Windows: `"plugin": ["file:///C:/code/Opencode_router"]`. Run
199
+ `npm run build` after each change, then restart OpenCode.
200
+
201
+ ## License
202
+
203
+ [MIT](./LICENSE)