opencode-harness-kit 0.6.0 → 0.6.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/CHANGELOG.md +0 -2
- package/README.md +10 -6
- package/bin/oc-harness.mjs +11 -3
- package/dist/index.js +15 -3
- package/eval/ab.mjs +1 -1
- package/package.json +1 -1
- package/profiles/fleet-all.json +10 -10
- package/profiles/fleet-safe.json +16 -16
- package/profiles/flint-40b-free.json +50 -0
- package/profiles/index.json +39 -23
- package/profiles/mimo-v2.6-flash-free.json +2 -4
- package/retention.yml +17 -8
- package/src/health.js +12 -3
- package/profiles/minimax-m3.1-flash-free.json +0 -50
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -107,7 +107,7 @@ about your prompts.
|
|
|
107
107
|
|
|
108
108
|
| lane | job | model | measured |
|
|
109
109
|
|---|---|---|---|
|
|
110
|
-
| `build` | write and verify the change |
|
|
110
|
+
| `build` | write and verify the change | Flint 40B Free | 6.9 s |
|
|
111
111
|
| `plan` | turn a request into a plan | Beam | **6.1 s** |
|
|
112
112
|
| `reviewer` | read a change in two passes | Nemotron 3 Ultra | 7.8 s (34 s cold) |
|
|
113
113
|
| `locate` | find where something lives | Nemotron 3.5 Lightning | 6.9 s |
|
|
@@ -116,13 +116,14 @@ about your prompts.
|
|
|
116
116
|
| `doc` | read a long document or a spec | GLM 5.3 Flash | 7.4 s |
|
|
117
117
|
| `schema` | produce JSON or a JSON schema | DeepSeek V4.1 Flash | 10.7 s |
|
|
118
118
|
| `sweep` | sweep a lot of code mechanically | Nemotron 3.5 Super VL | 8.4 s |
|
|
119
|
-
| `longform` | read a megabyte, or write alternatives |
|
|
119
|
+
| `longform` | read a megabyte, or write alternatives | Flint 40B Free | 6.9 s |
|
|
120
120
|
|
|
121
121
|
`longform` used to run on `longcat-2.5-preview-free`, and the provider
|
|
122
122
|
withdrew it. A withdrawn model is not a lane, it is a hole in a lane: the
|
|
123
|
-
route falls to the next rung of the same chain,
|
|
124
|
-
|
|
125
|
-
|
|
123
|
+
route falls to the next rung of the same chain, where MiniMax then flint
|
|
124
|
+
carried the lane - flint is the model that replaced MiniMax on the tier, and
|
|
125
|
+
the only one left with the context the lane exists for. The `measured`
|
|
126
|
+
column for that lane is therefore flint's, not either withdrawn model's.
|
|
126
127
|
|
|
127
128
|
The `measured` column is the median of five one-line requests to that model
|
|
128
129
|
on 2026-10-21 - the same prompt for every model, from the process start, so
|
|
@@ -243,7 +244,7 @@ it. One file covers ten jobs either way.
|
|
|
243
244
|
|---|---|---|---|---|
|
|
244
245
|
| `fleet-safe` (default) | 10 | 200,000 | `max` | zero-retention |
|
|
245
246
|
| `fleet-all` | 10 | 160,000 | `max` | **may train** |
|
|
246
|
-
| `
|
|
247
|
+
| `flint-40b-free` | 5 | 262,144 | `max` | **may train** |
|
|
247
248
|
| `beam-free` | 5 | 1,048,576 | `max` | retained |
|
|
248
249
|
| `deepseek-v4.1-flash-free` | 5 | 200,000 | `max` | zero-retention |
|
|
249
250
|
| `glm-5.3-flash-free` | 5 | 200,000 | `max` | zero-retention |
|
|
@@ -252,6 +253,7 @@ it. One file covers ten jobs either way.
|
|
|
252
253
|
| `nemotron-3.5-lightning-free` | 5 | 262,144 | — | **may train** |
|
|
253
254
|
| `mimo-v2.6-flash-free` | 5 | 200,000 | — | **may train** |
|
|
254
255
|
| `big-pickle` | 5 | 160,000 | — | **may train** |
|
|
256
|
+
| `flint-40b-free` | 5 | 262,144 | `max` | **may train** |
|
|
255
257
|
|
|
256
258
|
The five-lane profiles run everything on one model, which is the right shape
|
|
257
259
|
when you want one route and want to know exactly which one.
|
|
@@ -282,6 +284,8 @@ withdrawn, and one of them was the **default** at the time:
|
|
|
282
284
|
| `deepseek-v4-flash-free` | Withdrawn within a month. Replaced by `deepseek-v4.1-flash-free`. |
|
|
283
285
|
| `muse-spark-1.3-contributor-free` | A Meta contributor route whose provider was permitted to train on prompts. The paid route is still in the catalogue. |
|
|
284
286
|
| `mimo-v2.5-free` | Observed alive for one day. Replaced by `mimo-v2.6-flash-free`. |
|
|
287
|
+
| `longcat-2.5-preview-free` | Was the `longform` lane's primary in both fleets, so when it was pulled every lane fell back a rung, and the one profile built only for that model was retired. |
|
|
288
|
+
| `minimax-m3.1-flash-free` | Deprecated by the provider and replaced on the tier by `flint-40b-free`, which is the build and `longform` lane today. |
|
|
285
289
|
|
|
286
290
|
The full list, with a reason for each, is in
|
|
287
291
|
[`profiles/index.json`](profiles/index.json).
|
package/bin/oc-harness.mjs
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
// The point of the kit: switching models is a data edit, not a code change.
|
|
13
13
|
// Everything model-specific lives in profiles/<id>.json.
|
|
14
14
|
|
|
15
|
-
import { chmodSync, copyFileSync, mkdirSync, readFileSync, writeFileSync, existsSync, rmSync, symlinkSync, readdirSync, readlinkSync, realpathSync, lstatSync, appendFileSync } from "node:fs"
|
|
15
|
+
import { chmodSync, copyFileSync, mkdirSync, readFileSync, writeFileSync, existsSync, rmSync, symlinkSync, readdirSync, readlinkSync, realpathSync, lstatSync, appendFileSync, renameSync, unlinkSync } from "node:fs"
|
|
16
16
|
import { homedir } from "node:os"
|
|
17
17
|
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path"
|
|
18
18
|
import { execFileSync } from "node:child_process"
|
|
@@ -1539,7 +1539,7 @@ async function cmdUse(id) {
|
|
|
1539
1539
|
|
|
1540
1540
|
mkdirSync(dirname(CONFIG_FILE), { recursive: true })
|
|
1541
1541
|
if (existsSync(CONFIG_FILE)) {
|
|
1542
|
-
// The config is the user's file once written. The backup is unconditional:
|
|
1542
|
+
// The config is the user's file once written. The backup is unconditional:
|
|
1543
1543
|
// `--yes` skips the question, it does not skip the safety net. Gating the
|
|
1544
1544
|
// backup on `--yes` meant the one path that overwrites without asking was
|
|
1545
1545
|
// also the one path with nothing to fall back to.
|
|
@@ -1560,7 +1560,15 @@ async function cmdUse(id) {
|
|
|
1560
1560
|
stamp(` existing config backed up to ${join(BACKUP_DIR, kept)}`),
|
|
1561
1561
|
)
|
|
1562
1562
|
}
|
|
1563
|
-
|
|
1563
|
+
// Write atomically to avoid truncating/corrupting the config on crash.
|
|
1564
|
+
const tmp = `${CONFIG_FILE}.${process.pid}.${Date.now()}.tmp`
|
|
1565
|
+
try {
|
|
1566
|
+
writeFileSync(tmp, out)
|
|
1567
|
+
renameSync(tmp, CONFIG_FILE)
|
|
1568
|
+
} catch (err) {
|
|
1569
|
+
try { unlinkSync(tmp) } catch {}
|
|
1570
|
+
throw err
|
|
1571
|
+
}
|
|
1564
1572
|
console.log(`\n ${green("✓")} wrote ${CONFIG_FILE}`)
|
|
1565
1573
|
summary(p)
|
|
1566
1574
|
console.log(`\n ${stamp("verify with: opencode debug config")}\n`)
|
package/dist/index.js
CHANGED
|
@@ -1932,7 +1932,7 @@ function utilityModel(p) {
|
|
|
1932
1932
|
}
|
|
1933
1933
|
|
|
1934
1934
|
// src/health.js
|
|
1935
|
-
import { existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync } from "node:fs";
|
|
1935
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync3, renameSync as renameSync2, unlinkSync, writeFileSync } from "node:fs";
|
|
1936
1936
|
import { join as join7 } from "node:path";
|
|
1937
1937
|
var DEFAULT_WINDOW_MS = 24 * 60 * 60 * 1e3;
|
|
1938
1938
|
function spentWindowMs() {
|
|
@@ -1983,9 +1983,21 @@ function readHealth(dir) {
|
|
|
1983
1983
|
}
|
|
1984
1984
|
function writeHealth(dir, health) {
|
|
1985
1985
|
try {
|
|
1986
|
-
|
|
1986
|
+
const spaceDir = join7(dir, ".space");
|
|
1987
|
+
if (!existsSync5(spaceDir)) mkdirSync2(spaceDir, { recursive: true });
|
|
1987
1988
|
const pruned = { ...health ?? {}, unhealthy: liveUnhealthy(health) };
|
|
1988
|
-
|
|
1989
|
+
const file = healthPath(dir);
|
|
1990
|
+
const tmp = `${file}.${process.pid}.${Date.now()}.tmp`;
|
|
1991
|
+
try {
|
|
1992
|
+
writeFileSync(tmp, JSON.stringify(pruned, null, 2));
|
|
1993
|
+
renameSync2(tmp, file);
|
|
1994
|
+
} catch (err) {
|
|
1995
|
+
try {
|
|
1996
|
+
unlinkSync(tmp);
|
|
1997
|
+
} catch {
|
|
1998
|
+
}
|
|
1999
|
+
throw err;
|
|
2000
|
+
}
|
|
1989
2001
|
} catch {
|
|
1990
2002
|
}
|
|
1991
2003
|
}
|
package/eval/ab.mjs
CHANGED
|
@@ -750,7 +750,7 @@ console.log("")
|
|
|
750
750
|
console.log(` ${"metric (median)".padEnd(16)} ${"kit on".padStart(10)} ${"kit off".padStart(10)}`)
|
|
751
751
|
console.log(` ${"-".repeat(16)} ${"-".repeat(10)} ${"-".repeat(10)}`)
|
|
752
752
|
for (const [label, a, b] of rows) {
|
|
753
|
-
console.log(` ${label.padEnd(16)} ${String(a).padStart(10)} ${String(b).padStart(10)}`)
|
|
753
|
+
console.log(` ${String(label).padEnd(16)} ${String(a).padStart(10)} ${String(b).padStart(10)}`)
|
|
754
754
|
}
|
|
755
755
|
|
|
756
756
|
if (jobs.length > 1) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-harness-kit",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Harness kit for OpenCode: capability profiles, a fleet of job lanes with one free model each, role-based reasoning effort, context pruning, and measured baselines.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://github.com/pham-canh/opencode-harness-kit#readme",
|
package/profiles/fleet-all.json
CHANGED
|
@@ -3,15 +3,15 @@
|
|
|
3
3
|
"id": "fleet-all",
|
|
4
4
|
"title": "Ten jobs, every free model, one of them may train",
|
|
5
5
|
"provider": "opencode",
|
|
6
|
-
"model": "
|
|
7
|
-
"family":
|
|
6
|
+
"model": "flint-40b-free",
|
|
7
|
+
"family": "flint",
|
|
8
8
|
"verified": "2026-10-22",
|
|
9
9
|
"retention": "may-train",
|
|
10
10
|
"maxRetention": "may-train",
|
|
11
11
|
"notes": "Every lane gets the model built for it: beam plans, Nemotron 3 Ultra reviews, Lightning sweeps, MiMo sees, GLM audits, Super VL reasons with the effort turned off. Five of the ten providers state that collected data may be used to improve the model, or log the session, so the profile as a whole is may-train and the generated config says so in its header. Install it for public or throwaway repositories.",
|
|
12
12
|
"limits": {
|
|
13
|
-
"context":
|
|
14
|
-
"output":
|
|
13
|
+
"context": 262144,
|
|
14
|
+
"output": 65536
|
|
15
15
|
},
|
|
16
16
|
"supports": {
|
|
17
17
|
"reasoning": true,
|
|
@@ -49,9 +49,9 @@
|
|
|
49
49
|
},
|
|
50
50
|
"roleModels": {
|
|
51
51
|
"build": {
|
|
52
|
-
"model": "
|
|
52
|
+
"model": "flint-40b-free",
|
|
53
53
|
"chain": [
|
|
54
|
-
"
|
|
54
|
+
"flint-40b-free",
|
|
55
55
|
"deepseek-v4.1-flash-free"
|
|
56
56
|
]
|
|
57
57
|
},
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
"model": "mimo-v2.6-flash-free",
|
|
91
91
|
"chain": [
|
|
92
92
|
"mimo-v2.6-flash-free",
|
|
93
|
-
"
|
|
93
|
+
"deepseek-v4.1-flash-free"
|
|
94
94
|
]
|
|
95
95
|
},
|
|
96
96
|
"doc": {
|
|
@@ -116,9 +116,9 @@
|
|
|
116
116
|
]
|
|
117
117
|
},
|
|
118
118
|
"longform": {
|
|
119
|
-
"model": "
|
|
119
|
+
"model": "flint-40b-free",
|
|
120
120
|
"chain": [
|
|
121
|
-
"
|
|
121
|
+
"flint-40b-free",
|
|
122
122
|
"beam-free"
|
|
123
123
|
]
|
|
124
124
|
}
|
|
@@ -130,7 +130,7 @@
|
|
|
130
130
|
"keepUserMessages": true
|
|
131
131
|
},
|
|
132
132
|
"fallback": [
|
|
133
|
-
"
|
|
133
|
+
"flint-40b-free",
|
|
134
134
|
"deepseek-v4.1-flash-free"
|
|
135
135
|
]
|
|
136
136
|
}
|
package/profiles/fleet-safe.json
CHANGED
|
@@ -3,15 +3,15 @@
|
|
|
3
3
|
"id": "fleet-safe",
|
|
4
4
|
"title": "Ten jobs, zero-retention models only",
|
|
5
5
|
"provider": "opencode",
|
|
6
|
-
"model": "
|
|
7
|
-
"family":
|
|
6
|
+
"model": "deepseek-v4.1-flash-free",
|
|
7
|
+
"family": "deepseek",
|
|
8
8
|
"verified": "2026-10-22",
|
|
9
9
|
"retention": "zero-retention",
|
|
10
10
|
"maxRetention": "zero-retention",
|
|
11
|
-
"notes": "The default. Every lane resolves to a model whose provider states a zero-retention policy: no training, nothing kept. The cost is that six of the ten jobs run on a second-choice model - the planner loses beam (30-day retention) and the reviewer loses Nemotron 3 Ultra - so this is the floor, not the ceiling. The chains are ordered within the ceiling rather than copied from `fleet-all`: `locate` takes deepseek because it publishes a `low` effort level that longcat does not, and `vision` takes
|
|
11
|
+
"notes": "The default. Every lane resolves to a model whose provider states a zero-retention policy: no training, nothing kept. The cost is that six of the ten jobs run on a second-choice model - the planner loses beam (30-day retention) and the reviewer loses Nemotron 3 Ultra - so this is the floor, not the ceiling. The chains are ordered within the ceiling rather than copied from `fleet-all`: `locate` takes deepseek because it publishes a `low` effort level that longcat does not, and `vision` takes deepseek because it is the zero-retention route the provider kept for image reads. `fleet-all` gives every lane the model built for it.",
|
|
12
12
|
"limits": {
|
|
13
|
-
"context":
|
|
14
|
-
"output":
|
|
13
|
+
"context": 200000,
|
|
14
|
+
"output": 32000
|
|
15
15
|
},
|
|
16
16
|
"supports": {
|
|
17
17
|
"reasoning": true,
|
|
@@ -49,10 +49,10 @@
|
|
|
49
49
|
},
|
|
50
50
|
"roleModels": {
|
|
51
51
|
"build": {
|
|
52
|
-
"model": "
|
|
52
|
+
"model": "deepseek-v4.1-flash-free",
|
|
53
53
|
"chain": [
|
|
54
|
-
"
|
|
55
|
-
"
|
|
54
|
+
"deepseek-v4.1-flash-free",
|
|
55
|
+
"glm-5.3-flash-free"
|
|
56
56
|
]
|
|
57
57
|
},
|
|
58
58
|
"plan": {
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"model": "deepseek-v4.1-flash-free",
|
|
74
74
|
"chain": [
|
|
75
75
|
"deepseek-v4.1-flash-free",
|
|
76
|
-
"
|
|
76
|
+
"glm-5.3-flash-free"
|
|
77
77
|
]
|
|
78
78
|
},
|
|
79
79
|
"verify": {
|
|
@@ -84,10 +84,10 @@
|
|
|
84
84
|
]
|
|
85
85
|
},
|
|
86
86
|
"vision": {
|
|
87
|
-
"model": "
|
|
87
|
+
"model": "deepseek-v4.1-flash-free",
|
|
88
88
|
"chain": [
|
|
89
|
-
"
|
|
90
|
-
"
|
|
89
|
+
"deepseek-v4.1-flash-free",
|
|
90
|
+
"glm-5.3-flash-free"
|
|
91
91
|
]
|
|
92
92
|
},
|
|
93
93
|
"doc": {
|
|
@@ -108,14 +108,14 @@
|
|
|
108
108
|
"model": "deepseek-v4.1-flash-free",
|
|
109
109
|
"chain": [
|
|
110
110
|
"deepseek-v4.1-flash-free",
|
|
111
|
-
"
|
|
111
|
+
"glm-5.3-flash-free"
|
|
112
112
|
]
|
|
113
113
|
},
|
|
114
114
|
"longform": {
|
|
115
|
-
"model": "
|
|
115
|
+
"model": "deepseek-v4.1-flash-free",
|
|
116
116
|
"chain": [
|
|
117
|
-
"
|
|
118
|
-
"
|
|
117
|
+
"deepseek-v4.1-flash-free",
|
|
118
|
+
"glm-5.3-flash-free"
|
|
119
119
|
]
|
|
120
120
|
}
|
|
121
121
|
},
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$comment": "Metadata read from models.dev on 2026-10-23 and confirmed by a live call the same day. No latency figure is claimed: one call that answered is not a measurement. Regenerate the capability fields with `oc-harness refresh flint-40b-free`.",
|
|
3
|
+
"id": "flint-40b-free",
|
|
4
|
+
"title": "Flint 40B Free",
|
|
5
|
+
"provider": "opencode",
|
|
6
|
+
"model": "flint-40b-free",
|
|
7
|
+
"family": "flint",
|
|
8
|
+
"verified": "2026-10-23",
|
|
9
|
+
"retention": "may-train",
|
|
10
|
+
"notes": "An open-weight mixture of experts, 40B total with about 2.5B active, built for coding agents. Small enough to serve locally, and the weights are published, so the same model can be pointed at a local runtime instead of the free tier. 262k context and a 64k output cap, the full effort ladder, tool calls and structured output; it does not read images. Zen keeps prompts for 30 days and may train on them during the free period.",
|
|
11
|
+
"limits": {
|
|
12
|
+
"context": 262144,
|
|
13
|
+
"output": 65536
|
|
14
|
+
},
|
|
15
|
+
"supports": {
|
|
16
|
+
"reasoning": true,
|
|
17
|
+
"temperature": true,
|
|
18
|
+
"toolCall": true,
|
|
19
|
+
"structuredOutput": true,
|
|
20
|
+
"attachment": false
|
|
21
|
+
},
|
|
22
|
+
"effort": {
|
|
23
|
+
"levels": [
|
|
24
|
+
"low",
|
|
25
|
+
"medium",
|
|
26
|
+
"high",
|
|
27
|
+
"xhigh",
|
|
28
|
+
"max"
|
|
29
|
+
],
|
|
30
|
+
"default": "max",
|
|
31
|
+
"reserveShare": 0.12
|
|
32
|
+
},
|
|
33
|
+
"roles": {
|
|
34
|
+
"plan": "max",
|
|
35
|
+
"build": "max",
|
|
36
|
+
"reviewer": "max",
|
|
37
|
+
"locate": "low",
|
|
38
|
+
"verify": "low"
|
|
39
|
+
},
|
|
40
|
+
"prune": {
|
|
41
|
+
"enabled": true,
|
|
42
|
+
"keepRecentToolCalls": 6,
|
|
43
|
+
"keepRecentTurns": 3,
|
|
44
|
+
"keepUserMessages": true
|
|
45
|
+
},
|
|
46
|
+
"fallback": [
|
|
47
|
+
"deepseek-v4.1-flash-free",
|
|
48
|
+
"nemotron-3.5-lightning-free"
|
|
49
|
+
]
|
|
50
|
+
}
|
package/profiles/index.json
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
"$comment": "Profiles verified against live provider metadata. `retention` must come from retention.yml; a model missing there cannot enter this list. The default is a fleet, because a fleet is the point: ten jobs, ten models, one session. `context` is the input cap the config can actually use: the narrowest lane model's on a fleet, the model's own on a single-model profile. `oc-harness list` recomputes it from the profile rather than trusting this copy.",
|
|
3
3
|
"default": "fleet-safe",
|
|
4
4
|
"profiles": [
|
|
5
|
+
{
|
|
6
|
+
"id": "beam-free",
|
|
7
|
+
"file": "profiles/beam-free.json",
|
|
8
|
+
"title": "Beam Free",
|
|
9
|
+
"retention": "retained",
|
|
10
|
+
"free": true,
|
|
11
|
+
"topEffort": "max",
|
|
12
|
+
"context": 1048576,
|
|
13
|
+
"default": false,
|
|
14
|
+
"note": "Text only, freshest knowledge on the tier, fastest measured route. Keeps prompts for 30 days, so it is not zero-retention."
|
|
15
|
+
},
|
|
5
16
|
{
|
|
6
17
|
"id": "fleet-safe",
|
|
7
18
|
"file": "profiles/fleet-safe.json",
|
|
@@ -24,28 +35,6 @@
|
|
|
24
35
|
"default": false,
|
|
25
36
|
"note": "Every lane gets the model built for it. Five of the ten providers may use the data to improve the model, so the whole profile is may-train."
|
|
26
37
|
},
|
|
27
|
-
{
|
|
28
|
-
"id": "minimax-m3.1-flash-free",
|
|
29
|
-
"file": "profiles/minimax-m3.1-flash-free.json",
|
|
30
|
-
"title": "MiniMax M3.1 Flash Free",
|
|
31
|
-
"retention": "zero-retention",
|
|
32
|
-
"free": true,
|
|
33
|
-
"topEffort": "max",
|
|
34
|
-
"context": 1000000,
|
|
35
|
-
"default": false,
|
|
36
|
-
"note": "512k output tokens, the widest of any free route, and the fastest measured image reader at 7.7s."
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
"id": "beam-free",
|
|
40
|
-
"file": "profiles/beam-free.json",
|
|
41
|
-
"title": "Beam Free",
|
|
42
|
-
"retention": "retained",
|
|
43
|
-
"free": true,
|
|
44
|
-
"topEffort": "max",
|
|
45
|
-
"context": 1048576,
|
|
46
|
-
"default": false,
|
|
47
|
-
"note": "Text only, freshest knowledge on the tier, fastest measured route. Keeps prompts for 30 days, so it is not zero-retention."
|
|
48
|
-
},
|
|
49
38
|
{
|
|
50
39
|
"id": "deepseek-v4.1-flash-free",
|
|
51
40
|
"file": "profiles/deepseek-v4.1-flash-free.json",
|
|
@@ -112,6 +101,17 @@
|
|
|
112
101
|
"default": false,
|
|
113
102
|
"note": "Reads images correctly, at 19.2s - the slowest lane on the tier. Publishes audio input too, but OpenCode will not read a binary file, so that path is unreachable today."
|
|
114
103
|
},
|
|
104
|
+
{
|
|
105
|
+
"id": "flint-40b-free",
|
|
106
|
+
"file": "profiles/flint-40b-free.json",
|
|
107
|
+
"title": "Flint 40B Free",
|
|
108
|
+
"retention": "may-train",
|
|
109
|
+
"free": true,
|
|
110
|
+
"topEffort": "max",
|
|
111
|
+
"context": 262144,
|
|
112
|
+
"default": false,
|
|
113
|
+
"note": "Open-weight MoE with about 2.5B active parameters for local coding agents. Knowledge cutoff 2026-06, no image input. May train on prompts during its free period."
|
|
114
|
+
},
|
|
115
115
|
{
|
|
116
116
|
"id": "big-pickle",
|
|
117
117
|
"file": "profiles/big-pickle.json",
|
|
@@ -122,6 +122,17 @@
|
|
|
122
122
|
"context": 160000,
|
|
123
123
|
"default": false,
|
|
124
124
|
"note": "Stealth model, no public identity, no effort levels, no image input. The provider may train on it during its free period."
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"id": "flint-40b-free",
|
|
128
|
+
"file": "profiles/flint-40b-free.json",
|
|
129
|
+
"title": "Flint 40B Free",
|
|
130
|
+
"retention": "may-train",
|
|
131
|
+
"free": true,
|
|
132
|
+
"topEffort": "max",
|
|
133
|
+
"context": 262144,
|
|
134
|
+
"default": false,
|
|
135
|
+
"note": "Open-weight MoE, 40B total with about 2.5B active, built for coding agents and small enough to serve locally. Full effort ladder, 262k context, 64k output, no image input."
|
|
125
136
|
}
|
|
126
137
|
],
|
|
127
138
|
"excluded": [],
|
|
@@ -149,6 +160,11 @@
|
|
|
149
160
|
{
|
|
150
161
|
"id": "longcat-2.5-preview-free",
|
|
151
162
|
"reason": "Withdrawn from the provider. A preview endpoint, so it could be pulled without a rename - and it was: models.dev still carries the record and marks it deprecated. It was the longform lane's primary in both fleets, so every lane fell back to its second rung, and the profile named only this model had nothing left to fall back to and was retired."
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"id": "minimax-m3.1-flash-free",
|
|
166
|
+
"reason": "Deprecated by provider. Replaced on the tier by flint-40b-free for the lanes that ran it."
|
|
152
167
|
}
|
|
153
|
-
]
|
|
168
|
+
],
|
|
169
|
+
"active": []
|
|
154
170
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"provider": "opencode",
|
|
6
6
|
"model": "mimo-v2.6-flash-free",
|
|
7
7
|
"family": "mimo",
|
|
8
|
-
"verified": "2026-10-
|
|
8
|
+
"verified": "2026-10-23",
|
|
9
9
|
"retention": "may-train",
|
|
10
10
|
"notes": "Xiaomi. The only free model that publishes audio input, and it read an image correctly in a live call, at 19.2s average - the slowest lane on the tier, and slower than minimax on the same picture. OpenCode 1.19 refuses to read a binary file at all, so the audio path is not reachable through the harness today; the vision path is. No effort levels, so no variant is written.",
|
|
11
11
|
"limits": {
|
|
@@ -37,7 +37,5 @@
|
|
|
37
37
|
"keepRecentTurns": 3,
|
|
38
38
|
"keepUserMessages": true
|
|
39
39
|
},
|
|
40
|
-
"fallback": [
|
|
41
|
-
"minimax-m3.1-flash-free"
|
|
42
|
-
]
|
|
40
|
+
"fallback": []
|
|
43
41
|
}
|
package/retention.yml
CHANGED
|
@@ -27,14 +27,6 @@ models:
|
|
|
27
27
|
# --- Zero-retention: the provider states a zero-retention policy and does
|
|
28
28
|
# not train on your data. ---
|
|
29
29
|
|
|
30
|
-
opencode/minimax-m3.1-flash-free:
|
|
31
|
-
retention: zero-retention
|
|
32
|
-
note: >-
|
|
33
|
-
"Its provider follows a zero-retention policy and does not use your data
|
|
34
|
-
for model training." Free for a limited time.
|
|
35
|
-
verified: 2026-10-19
|
|
36
|
-
source: https://opencode.ai/docs/zen
|
|
37
|
-
|
|
38
30
|
opencode/glm-5.3-flash-free:
|
|
39
31
|
retention: zero-retention
|
|
40
32
|
note: >-
|
|
@@ -74,6 +66,15 @@ models:
|
|
|
74
66
|
verified: 2026-10-19
|
|
75
67
|
source: https://opencode.ai/docs/zen
|
|
76
68
|
|
|
69
|
+
opencode/flint-40b-free:
|
|
70
|
+
retention: may-train
|
|
71
|
+
note: >-
|
|
72
|
+
"During its free period, collected data may be used to improve the
|
|
73
|
+
model. Data is retained for 30 days." The weights are open, so the same
|
|
74
|
+
model can be served locally instead of through the free tier.
|
|
75
|
+
verified: 2026-10-23
|
|
76
|
+
source: https://opencode.ai/docs/zen
|
|
77
|
+
|
|
77
78
|
opencode/mimo-v2.6-flash-free:
|
|
78
79
|
retention: may-train
|
|
79
80
|
note: >-
|
|
@@ -109,6 +110,14 @@ models:
|
|
|
109
110
|
verified: 2026-10-19
|
|
110
111
|
source: https://opencode.ai/docs/zen
|
|
111
112
|
|
|
113
|
+
opencode/flint-40b-free:
|
|
114
|
+
retention: may-train
|
|
115
|
+
note: >-
|
|
116
|
+
Free trial endpoint on opencode zen; treated as may-train until terms
|
|
117
|
+
state otherwise.
|
|
118
|
+
verified: 2026-10-22
|
|
119
|
+
source: https://opencode.ai/docs/zen
|
|
120
|
+
|
|
112
121
|
# --- Paid routes, kept because the catalog still serves them and a profile
|
|
113
122
|
# may be pointed at one. ---
|
|
114
123
|
|
package/src/health.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
// Plain JS with JSDoc types, like the rest of src/: the CLI and the tests run
|
|
13
13
|
// under plain node, and the plugin loads .ts.
|
|
14
14
|
|
|
15
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"
|
|
15
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs"
|
|
16
16
|
import { join } from "node:path"
|
|
17
17
|
|
|
18
18
|
/**
|
|
@@ -158,9 +158,18 @@ export function readHealth(dir) {
|
|
|
158
158
|
*/
|
|
159
159
|
export function writeHealth(dir, health) {
|
|
160
160
|
try {
|
|
161
|
-
|
|
161
|
+
const spaceDir = join(dir, ".space")
|
|
162
|
+
if (!existsSync(spaceDir)) mkdirSync(spaceDir, { recursive: true })
|
|
162
163
|
const pruned = { ...(health ?? {}), unhealthy: liveUnhealthy(health) }
|
|
163
|
-
|
|
164
|
+
const file = healthPath(dir)
|
|
165
|
+
const tmp = `${file}.${process.pid}.${Date.now()}.tmp`
|
|
166
|
+
try {
|
|
167
|
+
writeFileSync(tmp, JSON.stringify(pruned, null, 2))
|
|
168
|
+
renameSync(tmp, file)
|
|
169
|
+
} catch (err) {
|
|
170
|
+
try { unlinkSync(tmp) } catch {}
|
|
171
|
+
throw err
|
|
172
|
+
}
|
|
164
173
|
} catch {
|
|
165
174
|
// Best effort. A health file that cannot be written means no failover,
|
|
166
175
|
// and failing to write it must not break the session.
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$comment": "Metadata verified against models.dev on 2026-10-19 and confirmed by a live call the same day. Regenerate the capability fields with `oc-harness refresh minimax-m3.1-flash-free`.",
|
|
3
|
-
"id": "minimax-m3.1-flash-free",
|
|
4
|
-
"title": "MiniMax M3.1 Flash Free",
|
|
5
|
-
"provider": "opencode",
|
|
6
|
-
"model": "minimax-m3.1-flash-free",
|
|
7
|
-
"family": "minimax",
|
|
8
|
-
"verified": "2026-10-22",
|
|
9
|
-
"retention": "zero-retention",
|
|
10
|
-
"notes": "Flagship coding and agent model on the free tier: 512k output tokens, the widest of any free route, and the fastest measured image reader at 7.7s. Tool calls are stable. It does not support temperature, and models.dev publishes no structured_output flag for it, so JSON output is requested in the prompt rather than negotiated with the API. Measured at 3.1s for a one-word reply.",
|
|
11
|
-
"limits": {
|
|
12
|
-
"context": 1000000,
|
|
13
|
-
"output": 512000
|
|
14
|
-
},
|
|
15
|
-
"supports": {
|
|
16
|
-
"reasoning": true,
|
|
17
|
-
"temperature": true,
|
|
18
|
-
"toolCall": true,
|
|
19
|
-
"structuredOutput": false,
|
|
20
|
-
"attachment": true
|
|
21
|
-
},
|
|
22
|
-
"effort": {
|
|
23
|
-
"levels": [
|
|
24
|
-
"low",
|
|
25
|
-
"medium",
|
|
26
|
-
"high",
|
|
27
|
-
"xhigh",
|
|
28
|
-
"max"
|
|
29
|
-
],
|
|
30
|
-
"default": "max",
|
|
31
|
-
"reserveShare": 0.12
|
|
32
|
-
},
|
|
33
|
-
"roles": {
|
|
34
|
-
"plan": "max",
|
|
35
|
-
"build": "max",
|
|
36
|
-
"reviewer": "max",
|
|
37
|
-
"locate": "low",
|
|
38
|
-
"verify": "low"
|
|
39
|
-
},
|
|
40
|
-
"prune": {
|
|
41
|
-
"enabled": true,
|
|
42
|
-
"keepRecentToolCalls": 6,
|
|
43
|
-
"keepRecentTurns": 3,
|
|
44
|
-
"keepUserMessages": true
|
|
45
|
-
},
|
|
46
|
-
"fallback": [
|
|
47
|
-
"deepseek-v4.1-flash-free",
|
|
48
|
-
"glm-5.3-flash-free"
|
|
49
|
-
]
|
|
50
|
-
}
|