Skip to content

Commit 8d992d8

Browse files
committed
Re-carry the claude-fable-5-1 adaptive thinking patch lost in the vendor sync
The 2026-09-07 re-sync to upstream 0205b07b dropped one divergence that was never ledgered: claude-fable-5-1 in anthropic.ts's ADAPTIVE_THINKING_MODELS, plus the adaptive-thinking request-shape suite in anthropic.test.ts. The pristine sync restored upstream's list, so the shipped model would receive the thinking:{type:enabled,budget_tokens} shape that adaptive-only models reject. Restore both in the patch layer, ledger the divergence as providers-ts-anthropic-adaptive-fable-5-1, and correct the re-sync narrative so it records the drop and recovery.
1 parent b567f65 commit 8d992d8

3 files changed

Lines changed: 66 additions & 1 deletion

File tree

‎vendor/intx-inference/PATCHES.md‎

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,12 @@ the new upstream code, not by assuming).
2323
### 2026-09-07 re-sync (upstream `0205b07b`)
2424

2525
Every entry above was re-carried against the new pin; none was dropped as
26-
upstream-absorbed. Upstream changes in the pinned range touched exactly two
26+
upstream-absorbed. The sync also dropped one divergence that was **not**
27+
ledgered at the time: `claude-fable-5-1` in `providers/anthropic.ts`'s
28+
`ADAPTIVE_THINKING_MODELS` and its "adaptive thinking request shape" suite in
29+
`providers/anthropic.test.ts`. It is recovered post-sync as
30+
`providers-ts-anthropic-adaptive-fable-5-1` below. Upstream changes in the
31+
pinned range touched exactly two
2732
patched files: `reactor.ts` (doom-loop detection: `doomLoopThreshold`
2833
config, `toolBatchSignature`, run-scoped repeat accounting in `executeTools`,
2934
and a fatal break in the action loop) and `assembly.ts` (a
@@ -253,6 +258,23 @@ gap rather than carrying indefinitely.
253258
Corbits adds a local type assertion wrapper and removes the cast from the
254259
vendored patch.
255260

261+
## providers-ts-anthropic-adaptive-fable-5-1
262+
263+
`providers/anthropic.ts` — Adds `claude-fable-5-1` to
264+
`ADAPTIVE_THINKING_MODELS`, so the adapter sends the
265+
`thinking:{type:"adaptive"}` + `output_config.effort` wire shape the model
266+
requires instead of the `thinking:{type:"enabled",budget_tokens}` shape
267+
adaptive-only models reject. Upstream's list lacks the model. Consumed by the
268+
`first-class-providers` registry (`claude-fable-5-1` is a shipped, selectable
269+
anthropic and zen model; CHANGELOG 0.3.17 advertises adaptive thinking for
270+
Fable 5) and guarded by the "adaptive thinking request shape" suite in
271+
`providers/anthropic.test.ts`.
272+
273+
**Disposition:** Re-carryable — a one-line list addition that survives sync
274+
trivially; the guard suite re-applies verbatim. Risk: upstream may grow its
275+
own adaptive-models list; reconcile the two on next sync. **Removal path:**
276+
Upstream adding `claude-fable-5-1` to its own `ADAPTIVE_THINKING_MODELS`.
277+
256278
---
257279

258280
The `void track(p)` → `track(p)` change at three call sites in `reactor.ts`

‎vendor/intx-inference/src/providers/anthropic.test.ts‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,47 @@ describe("Anthropic adapter — responseFormat boundary", () => {
817817
});
818818
});
819819

820+
describe("Anthropic adapter — adaptive thinking request shape", () => {
821+
const ThinkingBody = type({
822+
thinking: {
823+
type: "string",
824+
"budget_tokens?": "number",
825+
},
826+
"output_config?": { effort: "string" },
827+
});
828+
829+
function parseThinkingBody(body: string) {
830+
const parsed = ThinkingBody(JSON.parse(body));
831+
if (parsed instanceof type.errors) {
832+
throw new Error(`unexpected request body shape: ${parsed.summary}`);
833+
}
834+
return parsed;
835+
}
836+
837+
test("claude-fable-5-1 with thinking.enabled uses type adaptive and output_config.effort", () => {
838+
const req = createAnthropicAdapter(TEST_SOURCE).buildRequest(
839+
[],
840+
"claude-fable-5-1",
841+
{ thinking: { enabled: true } },
842+
);
843+
const body = parseThinkingBody(req.body);
844+
expect(body.thinking).toEqual({ type: "adaptive" });
845+
expect(body.output_config?.effort).toBeDefined();
846+
});
847+
848+
test("a non-adaptive model with thinking.enabled uses type enabled and budget_tokens", () => {
849+
const req = createAnthropicAdapter(TEST_SOURCE).buildRequest(
850+
[],
851+
"claude-haiku-4-5",
852+
{ thinking: { enabled: true } },
853+
);
854+
const body = parseThinkingBody(req.body);
855+
expect(body.thinking.type).toBe("enabled");
856+
expect(body.thinking.budget_tokens).toBeDefined();
857+
expect(body.output_config).toBeUndefined();
858+
});
859+
});
860+
820861
describe("Anthropic adapter — tool-name codec round-trip", () => {
821862
const PREFIXED = "@intx/tools-posix/sidecar-bundle:run_shell";
822863
const ToolsBody = type({ tools: type({ name: "string" }).array() });

‎vendor/intx-inference/src/providers/anthropic.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ export const ADAPTIVE_THINKING_MODELS: ReadonlySet<string> = new Set([
3939
"claude-sonnet-5",
4040
"claude-opus-5",
4141
"claude-fable-5",
42+
// Locally patched — see vendor/intx-inference/PATCHES.md#providers-ts-anthropic-adaptive-fable-5-1
43+
"claude-fable-5-1",
4244
"claude-opus-4-8",
4345
"claude-opus-4-6",
4446
"claude-opus-4-7",

0 commit comments

Comments
 (0)