chutes-build 1.0.2 → 1.0.4

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.
Files changed (2) hide show
  1. package/CHANGELOG.md +236 -0
  2. package/package.json +7 -7
package/CHANGELOG.md CHANGED
@@ -6,6 +6,242 @@ project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [1.0.4] - 2026-08-12
10
+
11
+ Two threads. The manual port from upstream `b13fa526` begins — one area per
12
+ commit, each landing with its own tests green and measured against a pre-port
13
+ baseline rather than an absolute count. And the verification system itself was
14
+ overhauled, because three of the previous release's problems were failures to
15
+ *notice*, not failures of code: 188 tests were failing where nobody looked, a
16
+ pager suite reported failures that were the terminal rather than the product,
17
+ and a kill switch that documents a privacy guarantee turned out to gate nothing.
18
+
19
+ ### Security
20
+
21
+ - **`webbrowser` updated for RUSTSEC-2026-0257**, argument injection through the
22
+ Unix `BROWSER` template: an attacker-controlled non-HTTP(S) URL retaining
23
+ spaces could become extra browser arguments, reproduced upstream by injecting
24
+ `--remote-debugging-port` and `--proxy-server`. Chutes Build opens a browser on
25
+ the OAuth login path, so this is a path we use. Fixed in 1.2.2; the lock now
26
+ resolves 1.2.4. The advisory was published while this release was being
27
+ prepared and turned a commit red that had passed an hour earlier — which is
28
+ what `cargo deny` reading the live database is for.
29
+ - **The self-update kill switch gated nothing.**
30
+ `product::AUTOMATIC_SELF_UPDATE` documents that a running Chutes Build never
31
+ downloads its own update, and it appeared exactly once in the tree — inside a
32
+ comment. What held the line was narrower and accidental: the `internal`
33
+ installer's base URLs are deadened to `127.0.0.1:9`. But `get_installer()`
34
+ honours `CHUTES_BUILD_INSTALLER=npm` and `[cli] installer` in `config.toml`,
35
+ and neither the npm path (`npm view`) nor gh-release (the GitHub API) is
36
+ deadened, so one line of user configuration turned a release binary into one
37
+ that contacts a registry at startup and can spawn a download child. The gate
38
+ is read now, and a test asserts it is read rather than merely present.
39
+
40
+ ### Added
41
+
42
+ - **A failed `SKILL.md` read now says where that skill is actually registered**,
43
+ instead of a bare "does not exist". Ambiguous names, disabled skills, stale
44
+ registrations and reads that are not `SKILL.md` deliberately suggest nothing,
45
+ so a wrong pointer is never preferred to no pointer.
46
+ - **Every workspace RPC declares whether it reads or writes** (`ACTIVITY`), and
47
+ the proxy client can report the server binary's version.
48
+
49
+ ### Changed
50
+
51
+ - The terminal runtime sizes its worker pool against per-user ceilings
52
+ (`pids.max` / `RLIMIT_NPROC`) using upstream's reworked logic, with 329 lines
53
+ of tests it did not have before — including the EAGAIN path.
54
+ - Sandbox hook write-deny is compiled only where it enforces. Its identity
55
+ capture, symlink and rename-race errors and JSON snapshot check move from
56
+ `#[cfg(unix)]` to `#[cfg(any(target_os = "linux", all(unix, test)))]`: the
57
+ rules are applied through Linux namespaces, so on macOS that code compiled and
58
+ never ran. Linux behaviour is unchanged.
59
+
60
+ ### Fixed
61
+
62
+ - **A busy model is waited for, not replaced.** A capacity 429 used to swap the
63
+ model you chose for `model-router` on the first attempt, instantly, discarding
64
+ the `Retry-After` the server had just sent — the header was parsed and then
65
+ dropped at that layer. A short delay (≤5s) on a 429 or 503 is now honoured on
66
+ the selected model before any switch; a long one still switches, because that
67
+ chute is busy for a while and another candidate can answer now. A server
68
+ sending `x-should-retry: false` is obeyed rather than retried against.
69
+ - **Esc worked only once a stream existed.** Everything before the first chunk
70
+ ignored the cancellation token, so a slow connect left the key dead until the
71
+ request returned on its own. All three backends now race the request against
72
+ cancellation, with the cancel arm biased first — the request goes out on the
73
+ future's first poll, so an already-cancelled turn was previously winning only
74
+ about half the time.
75
+ - **`scripts/rebrand.py` rewrote the sentences that name upstream on purpose.**
76
+ Running `--apply` over the tree changed six files with nothing to do with the
77
+ port in hand, every one of them wrongly: the README attribution became
78
+ "SpaceXAI's Chutes Build", `AGENTS.md` came to say the re-base replaced our own
79
+ wordmark with our own, and the getting-started guide gained a fork link to
80
+ `github.com/xai-org/chutes-build`, which does not exist. `--check` reported the
81
+ correct sentences as violations, so it would have pushed the next person to
82
+ "fix" them. The rules cannot tell "Grok Build, the thing we forked" from "Grok
83
+ Build, a name to replace"; those six are now pinned by exact text, and the
84
+ script fails loudly if one is reworded rather than silently exempting a file.
85
+
86
+ ### Verification
87
+
88
+ - **Those two crates' failing tests are not a fixed set, and that is the
89
+ finding.** CI ran narrow filters over `xai-grok-tools` and
90
+ `xai-grok-workspace`, leaving ~188 tests neither passing nor watched, so a new
91
+ failure among them was indistinguishable from the rest. The intended fix was a
92
+ committed per-test baseline that CI compares against — and it does not work
93
+ here, because the set moves: of 53 `xai-grok-workspace` failures recorded on a
94
+ local Windows machine, 17 pass on the Windows runner and 2 others fail; a
95
+ `daemonize` test failed on Linux in one run and not in the run 90 minutes
96
+ before. Same commit, same platform.
97
+
98
+ So `scripts/known_failures.py` and the two baselines ship as a **local
99
+ diagnostic**, not a CI gate, and the CI steps are removed. A gate is possible
100
+ once these suites are deterministic, and making them so is the actual work
101
+ this uncovered — the baseline is not a substitute for it. Separately, the full
102
+ `xai-grok-tools --lib` suite never completes on the Windows runner at all: 107
103
+ minutes, then 140, then a 40-minute timeout, against six minutes on Linux.
104
+ Both are recorded in `docs/upstream-sync.md` under what is still open.
105
+ - **The pager suite reported seven failures that were the terminal.**
106
+ `default_actions()` reads the process environment, so inside a VS Code terminal
107
+ Quit binds to Ctrl+D, interject moves to Ctrl+L, and a terminal with native
108
+ link hover owns link clicks. Each test asserted one side of a rule that has
109
+ two. They use the pinned registries that already existed, and the link test now
110
+ asserts both sides — covering something nothing covered: with native link
111
+ hover, *not* intercepting is correct. 8275 pass in both configurations.
112
+ - `scripts/port_assist.py` sorts an upstream delta into what needs a judgement
113
+ call and what does not — files absent here, files we never touched, and files
114
+ whose divergence *is* the rebrand, verifiable because
115
+ `rebrand(upstream@base)` reproduces our version character for character. 127 of
116
+ the 208 outstanding files need no human decision. It leaves genuine divergence
117
+ alone, refuses to resurrect files we deleted on purpose, and skips binaries.
118
+ - A notification-hook test waited five seconds for a forked shell and went red on
119
+ a loaded runner. `run_hook` returns its join handle now, so the test waits for
120
+ the fact rather than the clock.
121
+
122
+ ### Documentation
123
+
124
+ - `docs/upstream-sync.md` records what the first areas taught, for the eighty-six
125
+ files still to come: an area is always bigger than the module it started as and
126
+ clippy's `dead_code` is what proves it, since `dead_modules.py` cannot see a
127
+ module that *is* reachable; measure the baseline failure set before attributing
128
+ anything; and upstream's fixtures assume POSIX absolute paths, which on Windows
129
+ are drive-relative, so eleven tests failed here that pass on upstream's CI.
130
+ - `AGENTS.md` gains the three rules the port produced — check `git status` after
131
+ every rebrand run, finish an area on clippy rather than on green tests, and
132
+ measure the baseline failure set before attributing anything — and
133
+ `docs/releasing.md` records that a cancelled job ships nothing even when it
134
+ built everything.
135
+
136
+
137
+
138
+ ## [1.0.3] - 2026-08-11
139
+
140
+ Measured against the live Chutes endpoint with a real key, not reasoned about from
141
+ the source. Two of the findings below contradicted what the code looked like it
142
+ did, and one contradicted an earlier fix in this same release.
143
+
144
+ ### Fixed
145
+
146
+ - **Every model claimed a 256,000-token context.** The catalogue at
147
+ `llm.chutes.ai/v1/models` publishes `context_length` per model;
148
+ `parse_remote_model_value` looked for `contextWindow`, `context_window` and two
149
+ `_meta` spellings, none of which Chutes sends, so all thirteen fell through to
150
+ one default. It was wrong in both directions at once: `Qwen3-32B` holds 40,960,
151
+ so the product promised six times what exists and its requests were refused;
152
+ `DeepSeek-V4-Flash`, `Kimi-K3` and `GLM-5.2` hold 1,048,576, so three quarters
153
+ of the window went unused. Compaction and truncation were sizing themselves
154
+ against a figure no model agreed with. Eleven of thirteen now carry their
155
+ published value; the two that publish nothing keep a default.
156
+ - **Each model now carries its own output limit**, from `max_output_length` —
157
+ but only where that is *smaller* than the window. Several models publish the
158
+ two as the same number, which means "output may use the whole context" rather
159
+ than "always ask for this much": sending it as `max_tokens` leaves no room for
160
+ the prompt, and `Qwen3-32B` answers `400 Requested token count exceeds`. Nine
161
+ models gain a real cap, two are skipped. This was caught by testing the fix
162
+ against the endpoint before shipping it — the first version of the change would
163
+ have broken a model that previously worked.
164
+ - **An endpoint override reached inference but not the catalogue.**
165
+ `docs/configuration.md` documents `CHUTES_ROUTER_BASE_URL` and
166
+ `CHUTES_INFERENCE_BASE_URL` — `CHUTES_MODELS_BASE_URL` was supported and
167
+ undocumented, and is in the table now — and `chutes-build-core` honours them,
168
+ but the re-base left the agent's
169
+ `EndpointsConfig` reading only the `CHUTES_BUILD_*` spellings. The documented
170
+ names come first now, with the others kept as fallbacks.
171
+ - **The system prompt introduced the agent as xAI's.** The re-base overwrote
172
+ `templates/prompt.md` with upstream's, so every model was told at every turn
173
+ that it was "released by xAI" instead of "a privacy-first coding agent
174
+ optimized for the Chutes ecosystem" — the branding fix in 1.0.1 covered what
175
+ the user could see, not what the model was told. The same overwrite deleted
176
+ the `<official_chutes_sources>` block, which is the larger loss: it is what
177
+ directed the model to treat `chutes.ai/docs` and `chutes.ai/news` as the
178
+ primary authority on Chutes products, APIs, models, pricing and quotas, to
179
+ say when a claim is unverified rather than blending fact with inference, and
180
+ — a security instruction, not a stylistic one — never to put API keys,
181
+ credentials, private code or repository contents into a search query or
182
+ outbound request. Both restored from 0.4.3 and the encrypted templates
183
+ regenerated.
184
+ - **Only streaming requests could survive a busy model.** The Chutes fallback
185
+ chain — selected model, then `CHUTES_FALLBACK_MODELS`, then `model-router` —
186
+ was wired into `chat_completion_stream` and never into `chat_completion`. The
187
+ two paths had diverged by omission rather than by any decision, so an
188
+ interactive turn recovered quietly from `429 Infrastructure is at maximum
189
+ capacity` while compaction, title generation and the advisor surfaced it raw.
190
+ Both paths now share one chain and one policy. Nothing on the non-streaming
191
+ path can be mid-stream, so the "never switch models once bytes have shipped"
192
+ rule is satisfied trivially there. The chain's ordering also became testable
193
+ without touching process-wide environment variables, which no test could do
194
+ safely while the rest of the suite runs in parallel — the env reads moved to a
195
+ wrapper around a pure core.
196
+ - **`CHUTES_BUILD_OAUTH2_PRINCIPAL_TYPE=Team` could never complete a flow.**
197
+ `default_team_oauth2_scopes()` was still upstream's — `grok-cli:access`,
198
+ `api:access`, `team:read`, `conversations:*`, `workspaces:*`. The user-facing
199
+ list was corrected during the re-base cleanup and this one was missed.
200
+ `api.chutes.ai` advertises no team principal at all: its `scopes_supported` is
201
+ entirely user-level, so an authorization server was being asked for scopes it
202
+ has never heard of. The default is now the user list; a deployment that really
203
+ does define a team principal says so through `CHUTES_BUILD_OAUTH2_SCOPES`.
204
+ Established by reading the IdP's own discovery document rather than the prose
205
+ documentation, which does not cover team principals either way.
206
+
207
+ ### Release engineering
208
+
209
+ - **The first 1.0.3 built every artifact and shipped none.** `darwin-arm64`
210
+ finished in 118m40s of a 120-minute budget: binary, strip, smoke test,
211
+ package, checksum and upload all succeeded, and the wall then killed the
212
+ cache-save step eighty seconds later. A cancelled job fails the run, so
213
+ `Publish GitHub release` and `Publish npm packages` were skipped. Not a
214
+ regression — the macOS jobs of the previous three releases ran 67, 74, 91, 84,
215
+ 96 and 102 minutes, so the budget had been within ~15% of the slowest observed
216
+ build for several releases. Raised to 180.
217
+ - **`main` had been red since 06:40 and nothing showed it.** A rebranded string
218
+ grew three characters past 100 columns, `Check formatting` is the first step of
219
+ the Linux job, and its failure skipped the six test steps and clippy behind it.
220
+ It stayed invisible because `cancel-in-progress: true` plus a run of quick
221
+ pushes cancelled every CI run in between.
222
+
223
+ ### Documentation
224
+
225
+ - `docs/upstream-sync.md` records the pending port measured rather than
226
+ estimated: 3 commits, 238 files, of which 147 overlap work of ours and 91 do
227
+ not. It also records that `git diff HEAD upstream/main` is the wrong
228
+ instrument — it reports 1424 files, because the fork is not a descendant of
229
+ upstream and the diff is mostly our own re-base read backwards.
230
+ - `AGENTS.md` records that `xai-grok-pager --lib` reports seven failures when
231
+ run from a VS Code terminal, and that they are the terminal rather than the
232
+ code: `default_actions()` reads the process environment, so Quit binds to
233
+ Ctrl+D there and the `ctrl_q` tests fail against a correct app.
234
+
235
+ ### Notes on tool compatibility
236
+
237
+ The catalogue's `supported_features` is accurate: every model advertising `tools`
238
+ emits a real `tool_calls` finish, and the two advertising nothing do not. A first
239
+ probe suggested three Qwen models were broken — they were not. The probe gave them
240
+ 96 output tokens, which a reasoning model spends thinking before it can emit the
241
+ call. That is the finding worth keeping: **a thinking model needs output budget
242
+ before tool use works at all**, and without it the failure is silent and looks like
243
+ missing support.
244
+
9
245
  ## [1.0.2] - 2026-08-11
10
246
 
11
247
  Three faults a user meets in the first minute. All reproduced against the live
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chutes-build",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Privacy-first, open-source coding agent for the Chutes ecosystem",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Michael Gasperini (Mikesoft)",
@@ -37,12 +37,12 @@
37
37
  "check": "npm test && npm run verify:release && npm pack --dry-run"
38
38
  },
39
39
  "optionalDependencies": {
40
- "chutes-build-darwin-arm64": "1.0.2",
41
- "chutes-build-darwin-x64": "1.0.2",
42
- "chutes-build-linux-arm64-gnu": "1.0.2",
43
- "chutes-build-linux-x64-gnu": "1.0.2",
44
- "chutes-build-win32-arm64": "1.0.2",
45
- "chutes-build-win32-x64": "1.0.2"
40
+ "chutes-build-darwin-arm64": "1.0.4",
41
+ "chutes-build-darwin-x64": "1.0.4",
42
+ "chutes-build-linux-arm64-gnu": "1.0.4",
43
+ "chutes-build-linux-x64-gnu": "1.0.4",
44
+ "chutes-build-win32-arm64": "1.0.4",
45
+ "chutes-build-win32-x64": "1.0.4"
46
46
  },
47
47
  "keywords": [
48
48
  "ai",