@vellumai/assistant 0.12.5-dev.202609282216.bb92e6d → 0.12.5-dev.202609290048.637f7a7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vellumai/assistant",
3
- "version": "0.12.5-dev.202609282216.bb92e6d",
3
+ "version": "0.12.5-dev.202609290048.637f7a7",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "exports": {
@@ -3653,6 +3653,8 @@ describe("AnthropicProvider — deprecated sampling params (temperature / top_p
3653
3653
  "claude-opus-4-7",
3654
3654
  "claude-sonnet-5",
3655
3655
  "anthropic/claude-sonnet-5",
3656
+ "claude-sonnet-5-5",
3657
+ "anthropic/claude-sonnet-5.5",
3656
3658
  "claude-fable-5",
3657
3659
  "claude-fable-5-1",
3658
3660
  "anthropic/claude-fable-5.1",
@@ -144,6 +144,53 @@ describe("retry normalization: thinking + forced tool_choice", () => {
144
144
  expect(lastConfig()?.thinking).toEqual({ type: "adaptive" });
145
145
  });
146
146
 
147
+ for (const [providerName, model] of [
148
+ ["anthropic", "claude-sonnet-5-5"],
149
+ ["anthropic", "claude-opus-5-5"],
150
+ ["openrouter", "anthropic/claude-sonnet-5.5"],
151
+ ["vercel-ai-gateway", "anthropic/claude-sonnet-5.5"],
152
+ ] as const) {
153
+ test(`downgrades forced tool_choice to auto for ${providerName} ${model}`, async () => {
154
+ // These models always reason and reject forced tool use, so stripping
155
+ // `thinking` is not enough: the forced choice itself has to go.
156
+ setLlmConfig({
157
+ callSites: {
158
+ memoryExtraction: { provider: providerName, model },
159
+ },
160
+ });
161
+ const { provider, lastConfig } = makePipeline(providerName);
162
+ await provider.sendMessage([userMessage], {
163
+ config: {
164
+ callSite: "memoryExtraction",
165
+ tool_choice: { type: "tool", name: "extract_graph_diff" },
166
+ },
167
+ });
168
+ expect(lastConfig()?.tool_choice).toEqual({ type: "auto" });
169
+ });
170
+ }
171
+
172
+ test("keeps forced tool_choice for an adaptive-only model off the Anthropic wire", async () => {
173
+ setLlmConfig({
174
+ callSites: {
175
+ memoryExtraction: {
176
+ provider: "fireworks",
177
+ model: "accounts/fireworks/models/glm-5p3",
178
+ },
179
+ },
180
+ });
181
+ const { provider, lastConfig } = makePipeline("fireworks");
182
+ await provider.sendMessage([userMessage], {
183
+ config: {
184
+ callSite: "memoryExtraction",
185
+ tool_choice: { type: "tool", name: "extract_graph_diff" },
186
+ },
187
+ });
188
+ expect(lastConfig()?.tool_choice).toEqual({
189
+ type: "tool",
190
+ name: "extract_graph_diff",
191
+ });
192
+ });
193
+
147
194
  test("preserves explicit thinking: disabled with forced tool_choice", async () => {
148
195
  // Callers like the retriever explicitly set thinking: { type: "disabled" }
149
196
  // alongside forced tool_choice. This should pass through unchanged since
@@ -1008,7 +1008,7 @@ export class AnthropicProvider implements Provider {
1008
1008
  const isHaiku = effectiveModel.includes("haiku");
1009
1009
  // Effort support is per-model: Haiku and Sonnet 4.5 reject the param (see isEffortSupported).
1010
1010
  const supportsEffort = isEffortSupported(effectiveModel);
1011
- // opus-4-7 / opus-4-8 / opus-5 / opus-5-5 and sonnet-5 reject `temperature`,
1011
+ // opus-4-7 / opus-4-8 / opus-5 / opus-5-5 and sonnet-5 / sonnet-5-5 reject `temperature`,
1012
1012
  // `top_p`, and `top_k` with a 400 "`temperature`/`top_p` is deprecated
1013
1013
  // for this model" — model-wide, not effort-conditional (verified
1014
1014
  // 2026-06-23). opus-4-6 / sonnet-4-6 / haiku-4-5 still accept them.
@@ -331,6 +331,24 @@ const RAW_PROVIDER_CATALOG: ProviderCatalogEntry[] = [
331
331
  cacheReadPer1mTokens: 0.5,
332
332
  },
333
333
  },
334
+ {
335
+ id: "claude-sonnet-5-5",
336
+ displayName: "Claude Sonnet 5.5",
337
+ contextWindowTokens: 1000000,
338
+ maxOutputTokens: 128000,
339
+ longContextPricingThresholdTokens: 200000,
340
+ supportsThinking: true,
341
+ adaptiveThinkingOnly: true,
342
+ supportsCaching: true,
343
+ supportsVision: true,
344
+ supportsToolUse: true,
345
+ pricing: {
346
+ inputPer1mTokens: 2,
347
+ outputPer1mTokens: 10,
348
+ cacheWritePer1mTokens: 2.5,
349
+ cacheReadPer1mTokens: 0.2,
350
+ },
351
+ },
334
352
  {
335
353
  id: "claude-sonnet-5",
336
354
  displayName: "Claude Sonnet 5",
@@ -1336,6 +1354,24 @@ const RAW_PROVIDER_CATALOG: ProviderCatalogEntry[] = [
1336
1354
  cacheReadPer1mTokens: 0.5,
1337
1355
  },
1338
1356
  },
1357
+ {
1358
+ id: "anthropic/claude-sonnet-5.5",
1359
+ displayName: "Claude Sonnet 5.5",
1360
+ contextWindowTokens: 1000000,
1361
+ maxOutputTokens: 128000,
1362
+ longContextPricingThresholdTokens: 200000,
1363
+ supportsThinking: true,
1364
+ adaptiveThinkingOnly: true,
1365
+ supportsCaching: true,
1366
+ supportsVision: true,
1367
+ supportsToolUse: true,
1368
+ pricing: {
1369
+ inputPer1mTokens: 2,
1370
+ outputPer1mTokens: 10,
1371
+ cacheWritePer1mTokens: 2.5,
1372
+ cacheReadPer1mTokens: 0.2,
1373
+ },
1374
+ },
1339
1375
  {
1340
1376
  id: "anthropic/claude-sonnet-5",
1341
1377
  displayName: "Claude Sonnet 5",
@@ -2390,6 +2426,24 @@ const RAW_PROVIDER_CATALOG: ProviderCatalogEntry[] = [
2390
2426
  cacheReadPer1mTokens: 0.5,
2391
2427
  },
2392
2428
  },
2429
+ {
2430
+ id: "anthropic/claude-sonnet-5.5",
2431
+ displayName: "Claude Sonnet 5.5",
2432
+ contextWindowTokens: 1000000,
2433
+ maxOutputTokens: 128000,
2434
+ longContextPricingThresholdTokens: 200000,
2435
+ supportsThinking: true,
2436
+ adaptiveThinkingOnly: true,
2437
+ supportsCaching: true,
2438
+ supportsVision: true,
2439
+ supportsToolUse: true,
2440
+ pricing: {
2441
+ inputPer1mTokens: 2,
2442
+ outputPer1mTokens: 10,
2443
+ cacheWritePer1mTokens: 2.5,
2444
+ cacheReadPer1mTokens: 0.2,
2445
+ },
2446
+ },
2393
2447
  {
2394
2448
  id: "anthropic/claude-sonnet-5",
2395
2449
  displayName: "Claude Sonnet 5",
@@ -928,6 +928,36 @@ function normalizeSendMessageOptions(
928
928
  }
929
929
  }
930
930
 
931
+ // Adaptive-thinking-only Claude models (Fable, Opus 5.5, Sonnet 5.5) cannot
932
+ // turn reasoning off, so stripping `thinking` below does not clear the
933
+ // forced-tool conflict and Anthropic 400s the request. Downgrade the forced
934
+ // choice to `auto` so the call goes out. The tool is no longer guaranteed:
935
+ // forced-tool call sites already treat a missing tool call as a failed
936
+ // result, which is what the 400 gave them on every request.
937
+ const forcedToolModel =
938
+ typeof nextConfig.model === "string" ? nextConfig.model : "";
939
+ const forcedToolChoice = nextConfig.tool_choice as
940
+ | Record<string, unknown>
941
+ | undefined;
942
+ if (
943
+ forcedToolChoice != null &&
944
+ (forcedToolChoice.type === "tool" || forcedToolChoice.type === "any") &&
945
+ isAdaptiveThinkingOnlyModel(forcedToolModel) &&
946
+ targetsAnthropicWire(providerName, forcedToolModel)
947
+ ) {
948
+ log.warn(
949
+ {
950
+ providerName,
951
+ callSite: config.callSite,
952
+ model: forcedToolModel,
953
+ droppedToolChoice: forcedToolChoice,
954
+ },
955
+ "Downgrading forced `tool_choice` to `auto` because this model always " +
956
+ "reasons and rejects forced tool use.",
957
+ );
958
+ nextConfig.tool_choice = { type: "auto" };
959
+ }
960
+
931
961
  // Anthropic (and the gateways fronting Anthropic) rejects requests that
932
962
  // combine extended thinking with forced tool use (`tool_choice.type` of
933
963
  // `"tool"` or `"any"`). Strip thinking when both are present so the