sidekick-shared 0.28.0 → 0.28.2
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 +12 -0
- package/README.md +2 -1
- package/dist/esm/modelContext.js +32 -0
- package/dist/esm/modelInfo.js +186 -0
- package/dist/esm/testing/credentialGuard.js +26 -1
- package/dist/modelContext.js +32 -0
- package/dist/modelInfo.js +186 -0
- package/dist/testing/credentialGuard.js +26 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,18 @@ All notable changes to sidekick-shared will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.28.2] - 2026-10-30
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- Add verified offline pricing and context baselines for GPT-6.1 Sol/Terra, Claude Sonnet/Haiku 5.5 (dashed and dotted), Gemini 4 Argon/3.8 Flash, DeepSeek Flash/V4 Pro (including accepted Flash aliases), and GLM-5.3/Flash/FlashX. Direct-provider IDs resolve offline too. Preserve runtime overrides and observed account limits; document standard/short-context rates, DeepSeek peak rates, and Gemini promotions. Fixes #18.
|
|
13
|
+
|
|
14
|
+
## [0.28.1] - 2026-10-18
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- **`installCredentialGuard()` keeps `promisify(execFile)` working.** The guard replaced `child_process.execFile` and `exec` without Node's `util.promisify.custom`, so `promisify(execFile)(...)` resolved to the bare stdout string and `const { stdout } = await promisify(execFile)(...)` read `undefined`. The guarded functions now carry a guarded `promisify.custom` that delegates to Node's own, so it resolves to `{ stdout, stderr }` again, rejects with an error carrying `stdout` / `stderr`, and keeps `.child`; a blocked binary on the promisified path is recorded and rejects.
|
|
19
|
+
|
|
8
20
|
## [0.28.0] - 2026-10-18
|
|
9
21
|
|
|
10
22
|
### Added
|
package/README.md
CHANGED
|
@@ -9,6 +9,7 @@ Types, parsers, providers, readers, formatters, aggregation, search, reporting,
|
|
|
9
9
|
|
|
10
10
|
## Recent additions
|
|
11
11
|
|
|
12
|
+
- **0.28.1: credential guard keeps `promisify(execFile)`** — after `installCredentialGuard()`, `promisify(execFile)` and `promisify(exec)` resolve to `{ stdout, stderr }` again (0.28.0 dropped Node's `util.promisify.custom`, so they returned the bare stdout string), and the promisified calls are guarded too.
|
|
12
13
|
- **0.28.0: ES modules, narrow entries, and new readers** — a `module` export condition gives bundlers a tree-shakable ES-module build (Node keeps CommonJS); browser-safe parsers and helpers move onto `/browser` and the provider-home helpers onto `/node`; `sidekick-shared/testing` publishes the credential guard; `providerFailureDiagnosisSchema` joins `/schemas`; prompt history reports `changed` / `progressed` / `roots` and takes `sessionRefs`; signals carry `toolCategory` and `mcpServer`; `collectUsageEvents()` takes `workspacePaths`; `createJsonlTail()` is bounded and reports resets; and Claude sessions follow `CLAUDE_CONFIG_DIR` while Codex lookups include `archived_sessions/`.
|
|
13
14
|
- **0.27.6: one usable copy per login** — Claude Code and Codex rotate refresh tokens, so a second usable copy of a login invalidates the first ("Not logged in · Please run /login"). The live account now keeps no profile-home credential, only a private backup; `syncLiveAccountState()` demotes a leftover copy (installing it first when it is newer) and reports `demoted`, `repaired`, and `journal`. Live writes pass `decideLiveClaudeWrite()` or the Codex equivalent: a switch captures the outgoing login first even with `force`, holds Claude Code's refresh lock, is journaled so the next sync finishes or rolls it back, and keeps live MCP tokens. Claude Keychain writes use Claude Code's hex method and are read back (`ClaudeCredentialWriteError`), so blobs over about 4 KB are no longer truncated. New root APIs: `readClaudeCredentialStore()`, `inspectClaudeCredentialStores()` / `repairClaudeCredentialStores()`, `inspectCodexCredentialStores()` / `repairCodexCredentialStores()`, `readClaudeCredentialLedger()`, `readStoredCodexAccount()`, `syncCodexLiveStateAsync()`, `discardAccountLogin()`, `writeAccountLauncher()`, and non-persisting health inspection (`persist: false`). `writeActiveCredentials()` now requires a config directory; `writeLauncher()`, `applyActiveClaudeToLiveHome()`, and `resolveActiveClaudeHome()` are deprecated.
|
|
14
15
|
- **0.27.5: whole-session prompt history** — `collectSessionPromptHistory()` (root and Node) returns every human prompt of each matching Claude Code or Codex session, grouped by session and read from the start with the `collectPromptHistory()` scanners, so text, scope, model and usage, and ordinals are identical. Select with `sessionIds`, `since` (file mtime), or `limit`; each session carries `startedAt` / `lastActivityAt`, `cwds`, `gitBranches`, `models`, and `complete` / `truncated` / `droppedPrompts` / `excludedRecords`. `include.replies` adds the agent's last text for each prompt, and `include.signals` adds `interrupt`, `toolRejected`, `toolError`, `compaction`, `apiError`, and `rollback` signals. Sessions that `maxSessions`, `maxTotalBytes`, the deadline, or an abort cut off are listed in `unread` instead of being returned partially.
|
|
@@ -163,7 +164,7 @@ const guard = installCredentialGuard();
|
|
|
163
164
|
afterEach(() => guard.assertNoViolations());
|
|
164
165
|
```
|
|
165
166
|
|
|
166
|
-
The guard points `HOME` (and `USERPROFILE`, `APPDATA`, `LOCALAPPDATA`) at a temp directory it removes on exit, unsets `CLAUDE_CONFIG_DIR`, `CLAUDE_SECURESTORAGE_CONFIG_DIR`, `CODEX_HOME`, and `SIDEKICK_CONFIG_DIR`, and patches the real `child_process` and `fs` modules. Spawning `security`, `claude`, or `codex` throws, writing under the real `~/.claude`, `~/.claude.json`, `~/.codex`, or `~/.config/sidekick` throws, and reads there are recorded. Production code often swallows errors, so `assertNoViolations()` reports what was recorded even when nothing threw. A `vi.mock('child_process')` factory replaces the module and bypasses the guard for that file.
|
|
167
|
+
The guard points `HOME` (and `USERPROFILE`, `APPDATA`, `LOCALAPPDATA`) at a temp directory it removes on exit, unsets `CLAUDE_CONFIG_DIR`, `CLAUDE_SECURESTORAGE_CONFIG_DIR`, `CODEX_HOME`, and `SIDEKICK_CONFIG_DIR`, and patches the real `child_process` and `fs` modules. Spawning `security`, `claude`, or `codex` throws (a promisified `execFile` or `exec` rejects instead, and otherwise keeps Node's `{ stdout, stderr }` result), writing under the real `~/.claude`, `~/.claude.json`, `~/.codex`, or `~/.config/sidekick` throws, and reads there are recorded. Production code often swallows errors, so `assertNoViolations()` reports what was recorded even when nothing threw. A `vi.mock('child_process')` factory replaces the module and bypasses the guard for that file.
|
|
167
168
|
|
|
168
169
|
### Browser / webview runtimes
|
|
169
170
|
|
package/dist/esm/modelContext.js
CHANGED
|
@@ -30,6 +30,38 @@
|
|
|
30
30
|
import { resolveModelAlias } from './modelAliases';
|
|
31
31
|
/** Known model context window sizes (in tokens); current models verified 2026-09-05. */
|
|
32
32
|
const MODEL_CONTEXT_SIZES = {
|
|
33
|
+
// Published API limits verified 2026-10-30; GLM's API documents 1M even
|
|
34
|
+
// though local weights may support more. Catalog/observed overrides win.
|
|
35
|
+
'gpt-6.1-sol': 1_050_000,
|
|
36
|
+
'openai/gpt-6.1-sol': 1_050_000,
|
|
37
|
+
'gpt-6.1-terra': 1_050_000,
|
|
38
|
+
'openai/gpt-6.1-terra': 1_050_000,
|
|
39
|
+
'claude-sonnet-5-5': 1_000_000,
|
|
40
|
+
'anthropic/claude-sonnet-5-5': 1_000_000,
|
|
41
|
+
'claude-sonnet-5.5': 1_000_000,
|
|
42
|
+
'anthropic/claude-sonnet-5.5': 1_000_000,
|
|
43
|
+
'claude-haiku-5-5': 1_000_000,
|
|
44
|
+
'anthropic/claude-haiku-5-5': 1_000_000,
|
|
45
|
+
'claude-haiku-5.5': 1_000_000,
|
|
46
|
+
'anthropic/claude-haiku-5.5': 1_000_000,
|
|
47
|
+
'gemini-4-argon': 1_048_576,
|
|
48
|
+
'gemini/gemini-4-argon': 1_048_576,
|
|
49
|
+
'gemini-3.8-flash': 1_048_576,
|
|
50
|
+
'gemini/gemini-3.8-flash': 1_048_576,
|
|
51
|
+
'deepseek-flash': 1_000_000,
|
|
52
|
+
'deepseek/deepseek-flash': 1_000_000,
|
|
53
|
+
'deepseek-v4-flash': 1_000_000,
|
|
54
|
+
'deepseek/deepseek-v4-flash': 1_000_000,
|
|
55
|
+
'deepseek-v4-flash-vision-exp': 1_000_000,
|
|
56
|
+
'deepseek/deepseek-v4-flash-vision-exp': 1_000_000,
|
|
57
|
+
'deepseek-v4-pro': 1_000_000,
|
|
58
|
+
'deepseek/deepseek-v4-pro': 1_000_000,
|
|
59
|
+
'glm-5.3': 1_000_000,
|
|
60
|
+
'zai/glm-5.3': 1_000_000,
|
|
61
|
+
'glm-5.3-flash': 1_000_000,
|
|
62
|
+
'zai/glm-5.3-flash': 1_000_000,
|
|
63
|
+
'glm-5.3-flashx': 1_000_000,
|
|
64
|
+
'zai/glm-5.3-flashx': 1_000_000,
|
|
33
65
|
// Claude — native 1M context (Fable 5+, Opus 4.6+, Sonnet 4.6+)
|
|
34
66
|
'claude-fable-5-1': 1_000_000,
|
|
35
67
|
'claude-fable-5.1': 1_000_000,
|
package/dist/esm/modelInfo.js
CHANGED
|
@@ -37,6 +37,192 @@ export { MODEL_PROVIDER_IDS } from './providerIds';
|
|
|
37
37
|
* prefix matching cannot bridge the two, so both are needed.
|
|
38
38
|
*/
|
|
39
39
|
const PRICING_TABLE = {
|
|
40
|
+
// Current coding models verified 2026-10-30. Standard short-context rates;
|
|
41
|
+
// DeepSeek uses peak rates. Gemini promotions end 2026-11-30 (Argon) and
|
|
42
|
+
// 2026-12-31 (Flash). Haiku 5.5 costs more above 100K prompt tokens.
|
|
43
|
+
// Sources and estimation limits: docs/configuration/model-resolution.md.
|
|
44
|
+
// Explicit direct-provider keys support offline OpenCode model IDs without
|
|
45
|
+
// stripping arbitrary deployment prefixes or changing alias resolution.
|
|
46
|
+
'gpt-6.1-sol': {
|
|
47
|
+
inputCostPerMillion: 2,
|
|
48
|
+
outputCostPerMillion: 10,
|
|
49
|
+
cacheWriteCostPerMillion: 2.5,
|
|
50
|
+
cacheReadCostPerMillion: 0.1,
|
|
51
|
+
},
|
|
52
|
+
'openai/gpt-6.1-sol': {
|
|
53
|
+
inputCostPerMillion: 2,
|
|
54
|
+
outputCostPerMillion: 10,
|
|
55
|
+
cacheWriteCostPerMillion: 2.5,
|
|
56
|
+
cacheReadCostPerMillion: 0.1,
|
|
57
|
+
},
|
|
58
|
+
'gpt-6.1-terra': {
|
|
59
|
+
inputCostPerMillion: 1,
|
|
60
|
+
outputCostPerMillion: 5,
|
|
61
|
+
cacheWriteCostPerMillion: 1.25,
|
|
62
|
+
cacheReadCostPerMillion: 0.05,
|
|
63
|
+
},
|
|
64
|
+
'openai/gpt-6.1-terra': {
|
|
65
|
+
inputCostPerMillion: 1,
|
|
66
|
+
outputCostPerMillion: 5,
|
|
67
|
+
cacheWriteCostPerMillion: 1.25,
|
|
68
|
+
cacheReadCostPerMillion: 0.05,
|
|
69
|
+
},
|
|
70
|
+
'claude-sonnet-5-5': {
|
|
71
|
+
inputCostPerMillion: 2,
|
|
72
|
+
outputCostPerMillion: 10,
|
|
73
|
+
cacheWriteCostPerMillion: 2.5,
|
|
74
|
+
cacheReadCostPerMillion: 0.1,
|
|
75
|
+
},
|
|
76
|
+
'anthropic/claude-sonnet-5-5': {
|
|
77
|
+
inputCostPerMillion: 2,
|
|
78
|
+
outputCostPerMillion: 10,
|
|
79
|
+
cacheWriteCostPerMillion: 2.5,
|
|
80
|
+
cacheReadCostPerMillion: 0.1,
|
|
81
|
+
},
|
|
82
|
+
'claude-sonnet-5.5': {
|
|
83
|
+
inputCostPerMillion: 2,
|
|
84
|
+
outputCostPerMillion: 10,
|
|
85
|
+
cacheWriteCostPerMillion: 2.5,
|
|
86
|
+
cacheReadCostPerMillion: 0.1,
|
|
87
|
+
},
|
|
88
|
+
'anthropic/claude-sonnet-5.5': {
|
|
89
|
+
inputCostPerMillion: 2,
|
|
90
|
+
outputCostPerMillion: 10,
|
|
91
|
+
cacheWriteCostPerMillion: 2.5,
|
|
92
|
+
cacheReadCostPerMillion: 0.1,
|
|
93
|
+
},
|
|
94
|
+
'claude-haiku-5-5': {
|
|
95
|
+
inputCostPerMillion: 0.1,
|
|
96
|
+
outputCostPerMillion: 0.5,
|
|
97
|
+
cacheWriteCostPerMillion: 0.125,
|
|
98
|
+
cacheReadCostPerMillion: 0.01,
|
|
99
|
+
},
|
|
100
|
+
'anthropic/claude-haiku-5-5': {
|
|
101
|
+
inputCostPerMillion: 0.1,
|
|
102
|
+
outputCostPerMillion: 0.5,
|
|
103
|
+
cacheWriteCostPerMillion: 0.125,
|
|
104
|
+
cacheReadCostPerMillion: 0.01,
|
|
105
|
+
},
|
|
106
|
+
'claude-haiku-5.5': {
|
|
107
|
+
inputCostPerMillion: 0.1,
|
|
108
|
+
outputCostPerMillion: 0.5,
|
|
109
|
+
cacheWriteCostPerMillion: 0.125,
|
|
110
|
+
cacheReadCostPerMillion: 0.01,
|
|
111
|
+
},
|
|
112
|
+
'anthropic/claude-haiku-5.5': {
|
|
113
|
+
inputCostPerMillion: 0.1,
|
|
114
|
+
outputCostPerMillion: 0.5,
|
|
115
|
+
cacheWriteCostPerMillion: 0.125,
|
|
116
|
+
cacheReadCostPerMillion: 0.01,
|
|
117
|
+
},
|
|
118
|
+
'gemini-4-argon': {
|
|
119
|
+
inputCostPerMillion: 2,
|
|
120
|
+
outputCostPerMillion: 10,
|
|
121
|
+
cacheWriteCostPerMillion: 0,
|
|
122
|
+
cacheReadCostPerMillion: 0.1,
|
|
123
|
+
},
|
|
124
|
+
'gemini/gemini-4-argon': {
|
|
125
|
+
inputCostPerMillion: 2,
|
|
126
|
+
outputCostPerMillion: 10,
|
|
127
|
+
cacheWriteCostPerMillion: 0,
|
|
128
|
+
cacheReadCostPerMillion: 0.1,
|
|
129
|
+
},
|
|
130
|
+
'gemini-3.8-flash': {
|
|
131
|
+
inputCostPerMillion: 0.75,
|
|
132
|
+
outputCostPerMillion: 3.75,
|
|
133
|
+
cacheWriteCostPerMillion: 0,
|
|
134
|
+
cacheReadCostPerMillion: 0.075,
|
|
135
|
+
},
|
|
136
|
+
'gemini/gemini-3.8-flash': {
|
|
137
|
+
inputCostPerMillion: 0.75,
|
|
138
|
+
outputCostPerMillion: 3.75,
|
|
139
|
+
cacheWriteCostPerMillion: 0,
|
|
140
|
+
cacheReadCostPerMillion: 0.075,
|
|
141
|
+
},
|
|
142
|
+
'deepseek-flash': {
|
|
143
|
+
inputCostPerMillion: 0.3,
|
|
144
|
+
outputCostPerMillion: 1.2,
|
|
145
|
+
cacheWriteCostPerMillion: 0,
|
|
146
|
+
cacheReadCostPerMillion: 0.006,
|
|
147
|
+
},
|
|
148
|
+
'deepseek/deepseek-flash': {
|
|
149
|
+
inputCostPerMillion: 0.3,
|
|
150
|
+
outputCostPerMillion: 1.2,
|
|
151
|
+
cacheWriteCostPerMillion: 0,
|
|
152
|
+
cacheReadCostPerMillion: 0.006,
|
|
153
|
+
},
|
|
154
|
+
'deepseek-v4-flash': {
|
|
155
|
+
inputCostPerMillion: 0.3,
|
|
156
|
+
outputCostPerMillion: 1.2,
|
|
157
|
+
cacheWriteCostPerMillion: 0,
|
|
158
|
+
cacheReadCostPerMillion: 0.006,
|
|
159
|
+
},
|
|
160
|
+
'deepseek/deepseek-v4-flash': {
|
|
161
|
+
inputCostPerMillion: 0.3,
|
|
162
|
+
outputCostPerMillion: 1.2,
|
|
163
|
+
cacheWriteCostPerMillion: 0,
|
|
164
|
+
cacheReadCostPerMillion: 0.006,
|
|
165
|
+
},
|
|
166
|
+
'deepseek-v4-flash-vision-exp': {
|
|
167
|
+
inputCostPerMillion: 0.3,
|
|
168
|
+
outputCostPerMillion: 1.2,
|
|
169
|
+
cacheWriteCostPerMillion: 0,
|
|
170
|
+
cacheReadCostPerMillion: 0.006,
|
|
171
|
+
},
|
|
172
|
+
'deepseek/deepseek-v4-flash-vision-exp': {
|
|
173
|
+
inputCostPerMillion: 0.3,
|
|
174
|
+
outputCostPerMillion: 1.2,
|
|
175
|
+
cacheWriteCostPerMillion: 0,
|
|
176
|
+
cacheReadCostPerMillion: 0.006,
|
|
177
|
+
},
|
|
178
|
+
'deepseek-v4-pro': {
|
|
179
|
+
inputCostPerMillion: 1.32,
|
|
180
|
+
outputCostPerMillion: 3.96,
|
|
181
|
+
cacheWriteCostPerMillion: 0,
|
|
182
|
+
cacheReadCostPerMillion: 0.044,
|
|
183
|
+
},
|
|
184
|
+
'deepseek/deepseek-v4-pro': {
|
|
185
|
+
inputCostPerMillion: 1.32,
|
|
186
|
+
outputCostPerMillion: 3.96,
|
|
187
|
+
cacheWriteCostPerMillion: 0,
|
|
188
|
+
cacheReadCostPerMillion: 0.044,
|
|
189
|
+
},
|
|
190
|
+
'glm-5.3': {
|
|
191
|
+
inputCostPerMillion: 1.4,
|
|
192
|
+
outputCostPerMillion: 4.4,
|
|
193
|
+
cacheWriteCostPerMillion: 0,
|
|
194
|
+
cacheReadCostPerMillion: 0.26,
|
|
195
|
+
},
|
|
196
|
+
'zai/glm-5.3': {
|
|
197
|
+
inputCostPerMillion: 1.4,
|
|
198
|
+
outputCostPerMillion: 4.4,
|
|
199
|
+
cacheWriteCostPerMillion: 0,
|
|
200
|
+
cacheReadCostPerMillion: 0.26,
|
|
201
|
+
},
|
|
202
|
+
'glm-5.3-flash': {
|
|
203
|
+
inputCostPerMillion: 0.15,
|
|
204
|
+
outputCostPerMillion: 0.5,
|
|
205
|
+
cacheWriteCostPerMillion: 0,
|
|
206
|
+
cacheReadCostPerMillion: 0.03,
|
|
207
|
+
},
|
|
208
|
+
'zai/glm-5.3-flash': {
|
|
209
|
+
inputCostPerMillion: 0.15,
|
|
210
|
+
outputCostPerMillion: 0.5,
|
|
211
|
+
cacheWriteCostPerMillion: 0,
|
|
212
|
+
cacheReadCostPerMillion: 0.03,
|
|
213
|
+
},
|
|
214
|
+
'glm-5.3-flashx': {
|
|
215
|
+
inputCostPerMillion: 0.37,
|
|
216
|
+
outputCostPerMillion: 1.25,
|
|
217
|
+
cacheWriteCostPerMillion: 0,
|
|
218
|
+
cacheReadCostPerMillion: 0.075,
|
|
219
|
+
},
|
|
220
|
+
'zai/glm-5.3-flashx': {
|
|
221
|
+
inputCostPerMillion: 0.37,
|
|
222
|
+
outputCostPerMillion: 1.25,
|
|
223
|
+
cacheWriteCostPerMillion: 0,
|
|
224
|
+
cacheReadCostPerMillion: 0.075,
|
|
225
|
+
},
|
|
40
226
|
// ── Anthropic: Claude ──
|
|
41
227
|
// Fable 5.1 cache reads cost 0.025x input; Fable 5 retains its 0.1x rate.
|
|
42
228
|
'claude-fable-5-1': {
|
|
@@ -70,6 +70,7 @@ export function installCredentialGuard(options = {}) {
|
|
|
70
70
|
const realFs = builtin('node:fs');
|
|
71
71
|
const fs = realFs;
|
|
72
72
|
const { syncBuiltinESMExports } = builtin('node:module');
|
|
73
|
+
const { promisify } = builtin('node:util');
|
|
73
74
|
const blockedBinaries = new Set((options.blockedBinaries ?? DEFAULT_BLOCKED_BINARIES).map((name) => name.toLowerCase()));
|
|
74
75
|
// os.userInfo() reads the passwd entry, so it still names the real home
|
|
75
76
|
// after HOME is redirected below.
|
|
@@ -145,13 +146,37 @@ export function installCredentialGuard(options = {}) {
|
|
|
145
146
|
const original = childProcess[name];
|
|
146
147
|
if (typeof original !== 'function')
|
|
147
148
|
continue;
|
|
148
|
-
|
|
149
|
+
const check = (args) => {
|
|
149
150
|
const binary = binaryName(args[0]);
|
|
150
151
|
if (blockedBinaries.has(binary)) {
|
|
151
152
|
record(`child_process.${name}('${binary}') reached the real binary; mock child_process or inject a runner`);
|
|
152
153
|
}
|
|
154
|
+
};
|
|
155
|
+
const guarded = function guarded(...args) {
|
|
156
|
+
check(args);
|
|
153
157
|
return original.apply(this, args);
|
|
154
158
|
};
|
|
159
|
+
// execFile and exec carry Node's promisify.custom, which resolves to
|
|
160
|
+
// { stdout, stderr }; without it promisify() falls back to the first
|
|
161
|
+
// callback value. Guard it too and delegate, so .child, the error's
|
|
162
|
+
// stdout/stderr, encoding, and maxBuffer stay Node's own.
|
|
163
|
+
const custom = original[promisify.custom];
|
|
164
|
+
if (typeof custom === 'function') {
|
|
165
|
+
Object.defineProperty(guarded, promisify.custom, {
|
|
166
|
+
configurable: true,
|
|
167
|
+
writable: true,
|
|
168
|
+
value: function guardedPromisified(...args) {
|
|
169
|
+
try {
|
|
170
|
+
check(args);
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
return Promise.reject(error);
|
|
174
|
+
}
|
|
175
|
+
return custom.apply(this, args);
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
childProcess[name] = guarded;
|
|
155
180
|
}
|
|
156
181
|
for (const name of FS_WRITE_FUNCTIONS) {
|
|
157
182
|
const original = fs[name];
|
package/dist/modelContext.js
CHANGED
|
@@ -44,6 +44,38 @@ exports.getModelContextWindowSize = getModelContextWindowSize;
|
|
|
44
44
|
const modelAliases_1 = require("./modelAliases");
|
|
45
45
|
/** Known model context window sizes (in tokens); current models verified 2026-09-05. */
|
|
46
46
|
const MODEL_CONTEXT_SIZES = {
|
|
47
|
+
// Published API limits verified 2026-10-30; GLM's API documents 1M even
|
|
48
|
+
// though local weights may support more. Catalog/observed overrides win.
|
|
49
|
+
'gpt-6.1-sol': 1_050_000,
|
|
50
|
+
'openai/gpt-6.1-sol': 1_050_000,
|
|
51
|
+
'gpt-6.1-terra': 1_050_000,
|
|
52
|
+
'openai/gpt-6.1-terra': 1_050_000,
|
|
53
|
+
'claude-sonnet-5-5': 1_000_000,
|
|
54
|
+
'anthropic/claude-sonnet-5-5': 1_000_000,
|
|
55
|
+
'claude-sonnet-5.5': 1_000_000,
|
|
56
|
+
'anthropic/claude-sonnet-5.5': 1_000_000,
|
|
57
|
+
'claude-haiku-5-5': 1_000_000,
|
|
58
|
+
'anthropic/claude-haiku-5-5': 1_000_000,
|
|
59
|
+
'claude-haiku-5.5': 1_000_000,
|
|
60
|
+
'anthropic/claude-haiku-5.5': 1_000_000,
|
|
61
|
+
'gemini-4-argon': 1_048_576,
|
|
62
|
+
'gemini/gemini-4-argon': 1_048_576,
|
|
63
|
+
'gemini-3.8-flash': 1_048_576,
|
|
64
|
+
'gemini/gemini-3.8-flash': 1_048_576,
|
|
65
|
+
'deepseek-flash': 1_000_000,
|
|
66
|
+
'deepseek/deepseek-flash': 1_000_000,
|
|
67
|
+
'deepseek-v4-flash': 1_000_000,
|
|
68
|
+
'deepseek/deepseek-v4-flash': 1_000_000,
|
|
69
|
+
'deepseek-v4-flash-vision-exp': 1_000_000,
|
|
70
|
+
'deepseek/deepseek-v4-flash-vision-exp': 1_000_000,
|
|
71
|
+
'deepseek-v4-pro': 1_000_000,
|
|
72
|
+
'deepseek/deepseek-v4-pro': 1_000_000,
|
|
73
|
+
'glm-5.3': 1_000_000,
|
|
74
|
+
'zai/glm-5.3': 1_000_000,
|
|
75
|
+
'glm-5.3-flash': 1_000_000,
|
|
76
|
+
'zai/glm-5.3-flash': 1_000_000,
|
|
77
|
+
'glm-5.3-flashx': 1_000_000,
|
|
78
|
+
'zai/glm-5.3-flashx': 1_000_000,
|
|
47
79
|
// Claude — native 1M context (Fable 5+, Opus 4.6+, Sonnet 4.6+)
|
|
48
80
|
'claude-fable-5-1': 1_000_000,
|
|
49
81
|
'claude-fable-5.1': 1_000_000,
|
package/dist/modelInfo.js
CHANGED
|
@@ -60,6 +60,192 @@ Object.defineProperty(exports, "MODEL_PROVIDER_IDS", { enumerable: true, get: fu
|
|
|
60
60
|
* prefix matching cannot bridge the two, so both are needed.
|
|
61
61
|
*/
|
|
62
62
|
const PRICING_TABLE = {
|
|
63
|
+
// Current coding models verified 2026-10-30. Standard short-context rates;
|
|
64
|
+
// DeepSeek uses peak rates. Gemini promotions end 2026-11-30 (Argon) and
|
|
65
|
+
// 2026-12-31 (Flash). Haiku 5.5 costs more above 100K prompt tokens.
|
|
66
|
+
// Sources and estimation limits: docs/configuration/model-resolution.md.
|
|
67
|
+
// Explicit direct-provider keys support offline OpenCode model IDs without
|
|
68
|
+
// stripping arbitrary deployment prefixes or changing alias resolution.
|
|
69
|
+
'gpt-6.1-sol': {
|
|
70
|
+
inputCostPerMillion: 2,
|
|
71
|
+
outputCostPerMillion: 10,
|
|
72
|
+
cacheWriteCostPerMillion: 2.5,
|
|
73
|
+
cacheReadCostPerMillion: 0.1,
|
|
74
|
+
},
|
|
75
|
+
'openai/gpt-6.1-sol': {
|
|
76
|
+
inputCostPerMillion: 2,
|
|
77
|
+
outputCostPerMillion: 10,
|
|
78
|
+
cacheWriteCostPerMillion: 2.5,
|
|
79
|
+
cacheReadCostPerMillion: 0.1,
|
|
80
|
+
},
|
|
81
|
+
'gpt-6.1-terra': {
|
|
82
|
+
inputCostPerMillion: 1,
|
|
83
|
+
outputCostPerMillion: 5,
|
|
84
|
+
cacheWriteCostPerMillion: 1.25,
|
|
85
|
+
cacheReadCostPerMillion: 0.05,
|
|
86
|
+
},
|
|
87
|
+
'openai/gpt-6.1-terra': {
|
|
88
|
+
inputCostPerMillion: 1,
|
|
89
|
+
outputCostPerMillion: 5,
|
|
90
|
+
cacheWriteCostPerMillion: 1.25,
|
|
91
|
+
cacheReadCostPerMillion: 0.05,
|
|
92
|
+
},
|
|
93
|
+
'claude-sonnet-5-5': {
|
|
94
|
+
inputCostPerMillion: 2,
|
|
95
|
+
outputCostPerMillion: 10,
|
|
96
|
+
cacheWriteCostPerMillion: 2.5,
|
|
97
|
+
cacheReadCostPerMillion: 0.1,
|
|
98
|
+
},
|
|
99
|
+
'anthropic/claude-sonnet-5-5': {
|
|
100
|
+
inputCostPerMillion: 2,
|
|
101
|
+
outputCostPerMillion: 10,
|
|
102
|
+
cacheWriteCostPerMillion: 2.5,
|
|
103
|
+
cacheReadCostPerMillion: 0.1,
|
|
104
|
+
},
|
|
105
|
+
'claude-sonnet-5.5': {
|
|
106
|
+
inputCostPerMillion: 2,
|
|
107
|
+
outputCostPerMillion: 10,
|
|
108
|
+
cacheWriteCostPerMillion: 2.5,
|
|
109
|
+
cacheReadCostPerMillion: 0.1,
|
|
110
|
+
},
|
|
111
|
+
'anthropic/claude-sonnet-5.5': {
|
|
112
|
+
inputCostPerMillion: 2,
|
|
113
|
+
outputCostPerMillion: 10,
|
|
114
|
+
cacheWriteCostPerMillion: 2.5,
|
|
115
|
+
cacheReadCostPerMillion: 0.1,
|
|
116
|
+
},
|
|
117
|
+
'claude-haiku-5-5': {
|
|
118
|
+
inputCostPerMillion: 0.1,
|
|
119
|
+
outputCostPerMillion: 0.5,
|
|
120
|
+
cacheWriteCostPerMillion: 0.125,
|
|
121
|
+
cacheReadCostPerMillion: 0.01,
|
|
122
|
+
},
|
|
123
|
+
'anthropic/claude-haiku-5-5': {
|
|
124
|
+
inputCostPerMillion: 0.1,
|
|
125
|
+
outputCostPerMillion: 0.5,
|
|
126
|
+
cacheWriteCostPerMillion: 0.125,
|
|
127
|
+
cacheReadCostPerMillion: 0.01,
|
|
128
|
+
},
|
|
129
|
+
'claude-haiku-5.5': {
|
|
130
|
+
inputCostPerMillion: 0.1,
|
|
131
|
+
outputCostPerMillion: 0.5,
|
|
132
|
+
cacheWriteCostPerMillion: 0.125,
|
|
133
|
+
cacheReadCostPerMillion: 0.01,
|
|
134
|
+
},
|
|
135
|
+
'anthropic/claude-haiku-5.5': {
|
|
136
|
+
inputCostPerMillion: 0.1,
|
|
137
|
+
outputCostPerMillion: 0.5,
|
|
138
|
+
cacheWriteCostPerMillion: 0.125,
|
|
139
|
+
cacheReadCostPerMillion: 0.01,
|
|
140
|
+
},
|
|
141
|
+
'gemini-4-argon': {
|
|
142
|
+
inputCostPerMillion: 2,
|
|
143
|
+
outputCostPerMillion: 10,
|
|
144
|
+
cacheWriteCostPerMillion: 0,
|
|
145
|
+
cacheReadCostPerMillion: 0.1,
|
|
146
|
+
},
|
|
147
|
+
'gemini/gemini-4-argon': {
|
|
148
|
+
inputCostPerMillion: 2,
|
|
149
|
+
outputCostPerMillion: 10,
|
|
150
|
+
cacheWriteCostPerMillion: 0,
|
|
151
|
+
cacheReadCostPerMillion: 0.1,
|
|
152
|
+
},
|
|
153
|
+
'gemini-3.8-flash': {
|
|
154
|
+
inputCostPerMillion: 0.75,
|
|
155
|
+
outputCostPerMillion: 3.75,
|
|
156
|
+
cacheWriteCostPerMillion: 0,
|
|
157
|
+
cacheReadCostPerMillion: 0.075,
|
|
158
|
+
},
|
|
159
|
+
'gemini/gemini-3.8-flash': {
|
|
160
|
+
inputCostPerMillion: 0.75,
|
|
161
|
+
outputCostPerMillion: 3.75,
|
|
162
|
+
cacheWriteCostPerMillion: 0,
|
|
163
|
+
cacheReadCostPerMillion: 0.075,
|
|
164
|
+
},
|
|
165
|
+
'deepseek-flash': {
|
|
166
|
+
inputCostPerMillion: 0.3,
|
|
167
|
+
outputCostPerMillion: 1.2,
|
|
168
|
+
cacheWriteCostPerMillion: 0,
|
|
169
|
+
cacheReadCostPerMillion: 0.006,
|
|
170
|
+
},
|
|
171
|
+
'deepseek/deepseek-flash': {
|
|
172
|
+
inputCostPerMillion: 0.3,
|
|
173
|
+
outputCostPerMillion: 1.2,
|
|
174
|
+
cacheWriteCostPerMillion: 0,
|
|
175
|
+
cacheReadCostPerMillion: 0.006,
|
|
176
|
+
},
|
|
177
|
+
'deepseek-v4-flash': {
|
|
178
|
+
inputCostPerMillion: 0.3,
|
|
179
|
+
outputCostPerMillion: 1.2,
|
|
180
|
+
cacheWriteCostPerMillion: 0,
|
|
181
|
+
cacheReadCostPerMillion: 0.006,
|
|
182
|
+
},
|
|
183
|
+
'deepseek/deepseek-v4-flash': {
|
|
184
|
+
inputCostPerMillion: 0.3,
|
|
185
|
+
outputCostPerMillion: 1.2,
|
|
186
|
+
cacheWriteCostPerMillion: 0,
|
|
187
|
+
cacheReadCostPerMillion: 0.006,
|
|
188
|
+
},
|
|
189
|
+
'deepseek-v4-flash-vision-exp': {
|
|
190
|
+
inputCostPerMillion: 0.3,
|
|
191
|
+
outputCostPerMillion: 1.2,
|
|
192
|
+
cacheWriteCostPerMillion: 0,
|
|
193
|
+
cacheReadCostPerMillion: 0.006,
|
|
194
|
+
},
|
|
195
|
+
'deepseek/deepseek-v4-flash-vision-exp': {
|
|
196
|
+
inputCostPerMillion: 0.3,
|
|
197
|
+
outputCostPerMillion: 1.2,
|
|
198
|
+
cacheWriteCostPerMillion: 0,
|
|
199
|
+
cacheReadCostPerMillion: 0.006,
|
|
200
|
+
},
|
|
201
|
+
'deepseek-v4-pro': {
|
|
202
|
+
inputCostPerMillion: 1.32,
|
|
203
|
+
outputCostPerMillion: 3.96,
|
|
204
|
+
cacheWriteCostPerMillion: 0,
|
|
205
|
+
cacheReadCostPerMillion: 0.044,
|
|
206
|
+
},
|
|
207
|
+
'deepseek/deepseek-v4-pro': {
|
|
208
|
+
inputCostPerMillion: 1.32,
|
|
209
|
+
outputCostPerMillion: 3.96,
|
|
210
|
+
cacheWriteCostPerMillion: 0,
|
|
211
|
+
cacheReadCostPerMillion: 0.044,
|
|
212
|
+
},
|
|
213
|
+
'glm-5.3': {
|
|
214
|
+
inputCostPerMillion: 1.4,
|
|
215
|
+
outputCostPerMillion: 4.4,
|
|
216
|
+
cacheWriteCostPerMillion: 0,
|
|
217
|
+
cacheReadCostPerMillion: 0.26,
|
|
218
|
+
},
|
|
219
|
+
'zai/glm-5.3': {
|
|
220
|
+
inputCostPerMillion: 1.4,
|
|
221
|
+
outputCostPerMillion: 4.4,
|
|
222
|
+
cacheWriteCostPerMillion: 0,
|
|
223
|
+
cacheReadCostPerMillion: 0.26,
|
|
224
|
+
},
|
|
225
|
+
'glm-5.3-flash': {
|
|
226
|
+
inputCostPerMillion: 0.15,
|
|
227
|
+
outputCostPerMillion: 0.5,
|
|
228
|
+
cacheWriteCostPerMillion: 0,
|
|
229
|
+
cacheReadCostPerMillion: 0.03,
|
|
230
|
+
},
|
|
231
|
+
'zai/glm-5.3-flash': {
|
|
232
|
+
inputCostPerMillion: 0.15,
|
|
233
|
+
outputCostPerMillion: 0.5,
|
|
234
|
+
cacheWriteCostPerMillion: 0,
|
|
235
|
+
cacheReadCostPerMillion: 0.03,
|
|
236
|
+
},
|
|
237
|
+
'glm-5.3-flashx': {
|
|
238
|
+
inputCostPerMillion: 0.37,
|
|
239
|
+
outputCostPerMillion: 1.25,
|
|
240
|
+
cacheWriteCostPerMillion: 0,
|
|
241
|
+
cacheReadCostPerMillion: 0.075,
|
|
242
|
+
},
|
|
243
|
+
'zai/glm-5.3-flashx': {
|
|
244
|
+
inputCostPerMillion: 0.37,
|
|
245
|
+
outputCostPerMillion: 1.25,
|
|
246
|
+
cacheWriteCostPerMillion: 0,
|
|
247
|
+
cacheReadCostPerMillion: 0.075,
|
|
248
|
+
},
|
|
63
249
|
// ── Anthropic: Claude ──
|
|
64
250
|
// Fable 5.1 cache reads cost 0.025x input; Fable 5 retains its 0.1x rate.
|
|
65
251
|
'claude-fable-5-1': {
|
|
@@ -106,6 +106,7 @@ function installCredentialGuard(options = {}) {
|
|
|
106
106
|
const realFs = builtin('node:fs');
|
|
107
107
|
const fs = realFs;
|
|
108
108
|
const { syncBuiltinESMExports } = builtin('node:module');
|
|
109
|
+
const { promisify } = builtin('node:util');
|
|
109
110
|
const blockedBinaries = new Set((options.blockedBinaries ?? DEFAULT_BLOCKED_BINARIES).map((name) => name.toLowerCase()));
|
|
110
111
|
// os.userInfo() reads the passwd entry, so it still names the real home
|
|
111
112
|
// after HOME is redirected below.
|
|
@@ -181,13 +182,37 @@ function installCredentialGuard(options = {}) {
|
|
|
181
182
|
const original = childProcess[name];
|
|
182
183
|
if (typeof original !== 'function')
|
|
183
184
|
continue;
|
|
184
|
-
|
|
185
|
+
const check = (args) => {
|
|
185
186
|
const binary = binaryName(args[0]);
|
|
186
187
|
if (blockedBinaries.has(binary)) {
|
|
187
188
|
record(`child_process.${name}('${binary}') reached the real binary; mock child_process or inject a runner`);
|
|
188
189
|
}
|
|
190
|
+
};
|
|
191
|
+
const guarded = function guarded(...args) {
|
|
192
|
+
check(args);
|
|
189
193
|
return original.apply(this, args);
|
|
190
194
|
};
|
|
195
|
+
// execFile and exec carry Node's promisify.custom, which resolves to
|
|
196
|
+
// { stdout, stderr }; without it promisify() falls back to the first
|
|
197
|
+
// callback value. Guard it too and delegate, so .child, the error's
|
|
198
|
+
// stdout/stderr, encoding, and maxBuffer stay Node's own.
|
|
199
|
+
const custom = original[promisify.custom];
|
|
200
|
+
if (typeof custom === 'function') {
|
|
201
|
+
Object.defineProperty(guarded, promisify.custom, {
|
|
202
|
+
configurable: true,
|
|
203
|
+
writable: true,
|
|
204
|
+
value: function guardedPromisified(...args) {
|
|
205
|
+
try {
|
|
206
|
+
check(args);
|
|
207
|
+
}
|
|
208
|
+
catch (error) {
|
|
209
|
+
return Promise.reject(error);
|
|
210
|
+
}
|
|
211
|
+
return custom.apply(this, args);
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
childProcess[name] = guarded;
|
|
191
216
|
}
|
|
192
217
|
for (const name of FS_WRITE_FUNCTIONS) {
|
|
193
218
|
const original = fs[name];
|