Skip to content

Commit 5f13221

Browse files
committed
feat: add context management support and corresponding beta handling
- Updated `computeAnthropicBetas` to include a new `context_management` option, which adds the `context-management-2025-06-27` beta when set. - Enhanced the `buildServerToolResultBlock` documentation to reflect the new context management feature. - Added tests to verify the correct forwarding of `context_management` and the attachment of the required beta in the adapter. - Ensured that the beta is not added when `context_management` is null. Closes issue #1074.
1 parent 79d8812 commit 5f13221

4 files changed

Lines changed: 70 additions & 1 deletion

File tree

.changeset/little-guests-trade.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
"@tanstack/ai-anthropic": patch
3+
---
4+
5+
Fix `modelOptions.context_management` by attaching the required
6+
`context-management-2025-06-27` beta. The option was typed and forwarded on the
7+
request body, but Anthropic rejects context editing without the beta header —
8+
so the feature typechecked and could not work (issue #1074).

packages/ai-anthropic/src/adapters/text.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,8 @@ function buildServerToolResultBlock(
147147
* Computes the `betas` array for a Messages request. Unions:
148148
* - `interleaved-thinking-2025-05-14` when interleaved thinking is enabled,
149149
* - `code-execution-2025-08-25` when a `code_execution` tool is present,
150-
* - `skills-2025-10-02` when that tool carries skills.
150+
* - `skills-2025-10-02` when that tool carries skills,
151+
* - `context-management-2025-06-27` when `context_management` is set.
151152
* Returns `undefined` when none apply (so the call site omits `betas`).
152153
*/
153154
export function computeAnthropicBetas(
@@ -158,6 +159,7 @@ export function computeAnthropicBetas(
158159
type?: 'enabled' | 'disabled' | 'adaptive'
159160
budget_tokens?: number
160161
}
162+
context_management?: unknown | null
161163
}
162164
| undefined,
163165
): Array<AnthropicBeta> | undefined {
@@ -169,6 +171,12 @@ export function computeAnthropicBetas(
169171
modelOptions.thinking.budget_tokens > 0
170172
if (useInterleavedThinking) betas.add('interleaved-thinking-2025-05-14')
171173

174+
// Context editing requires the beta header; the body field alone is not
175+
// enough (issue #1074). `null` is a typed "unset" — do not enable the beta.
176+
if (modelOptions?.context_management != null) {
177+
betas.add('context-management-2025-06-27')
178+
}
179+
172180
// Code-execution beta is version-aware: select from the FIRST code_execution
173181
// tool's config type.
174182
const codeExecTool = tools?.find((t) => t.name === 'code_execution')

packages/ai-anthropic/tests/anthropic-adapter.test.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,29 @@ describe('Anthropic adapter option mapping', () => {
397397
expect(payload.max_tokens).toBe(2048)
398398
})
399399

400+
it('forwards context_management and attaches the required beta (issue #1074)', async () => {
401+
mocks.betaMessagesCreate.mockResolvedValueOnce(createTextStream('ok'))
402+
403+
const adapter = createAdapter('claude-opus-4-1')
404+
const contextManagement = {
405+
edits: [{ type: 'clear_tool_uses_20250919' as const }],
406+
}
407+
408+
for await (const _ of chat({
409+
adapter,
410+
messages: [{ role: 'user', content: 'Hi' }],
411+
modelOptions: {
412+
context_management: contextManagement,
413+
} satisfies AnthropicTextProviderOptions,
414+
})) {
415+
// consume stream
416+
}
417+
418+
const [payload] = mocks.betaMessagesCreate.mock.calls[0]!
419+
expect(payload.context_management).toEqual(contextManagement)
420+
expect(payload.betas).toEqual(['context-management-2025-06-27'])
421+
})
422+
400423
it('forwards top-level cache_control from modelOptions instead of dropping it', async () => {
401424
mocks.betaMessagesCreate.mockResolvedValueOnce(createTextStream('ok'))
402425

packages/ai-anthropic/tests/text.skills.test.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,36 @@ describe('computeAnthropicBetas', () => {
107107
expect(computeAnthropicBetas(undefined, undefined)).toBeUndefined()
108108
})
109109

110+
it('adds context-management beta when context_management is set (issue #1074)', () => {
111+
const betas = computeAnthropicBetas(undefined, {
112+
context_management: {
113+
edits: [{ type: 'clear_tool_uses_20250919' }],
114+
},
115+
})
116+
expect(betas).toEqual(['context-management-2025-06-27'])
117+
})
118+
119+
it('does not add context-management beta when context_management is null', () => {
120+
expect(
121+
computeAnthropicBetas(undefined, { context_management: null }),
122+
).toBeUndefined()
123+
})
124+
125+
it('unions context-management with interleaved-thinking betas', () => {
126+
const betas = computeAnthropicBetas(undefined, {
127+
thinking: { type: 'enabled', budget_tokens: 2048 },
128+
context_management: {
129+
edits: [{ type: 'clear_thinking_20251015', keep: 'all' }],
130+
},
131+
})
132+
expect(betas).toEqual(
133+
expect.arrayContaining([
134+
'interleaved-thinking-2025-05-14',
135+
'context-management-2025-06-27',
136+
]),
137+
)
138+
})
139+
110140
it('uses code-execution-2025-05-22 beta for legacy code_execution_20250522 tool', () => {
111141
const tool = codeExecutionTool({
112142
type: 'code_execution_20250522',

0 commit comments

Comments
 (0)