@ai-sdk/anthropic 3.0.0-beta.68 → 3.0.0-beta.70

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.
@@ -1,13 +1,13 @@
1
1
  // src/anthropic-messages-language-model.ts
2
2
  import {
3
- UnsupportedFunctionalityError as UnsupportedFunctionalityError3,
4
- APICallError
3
+ APICallError,
4
+ UnsupportedFunctionalityError as UnsupportedFunctionalityError3
5
5
  } from "@ai-sdk/provider";
6
6
  import {
7
7
  combineHeaders,
8
8
  createEventSourceResponseHandler,
9
9
  createJsonResponseHandler,
10
- DelayedPromise,
10
+ createToolNameMapping,
11
11
  generateId,
12
12
  parseProviderOptions as parseProviderOptions2,
13
13
  postJsonToApi,
@@ -1243,7 +1243,8 @@ async function convertToAnthropicMessagesPrompt({
1243
1243
  prompt,
1244
1244
  sendReasoning,
1245
1245
  warnings,
1246
- cacheControlValidator
1246
+ cacheControlValidator,
1247
+ toolNameMapping
1247
1248
  }) {
1248
1249
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
1249
1250
  const betas = /* @__PURE__ */ new Set();
@@ -1581,6 +1582,9 @@ async function convertToAnthropicMessagesPrompt({
1581
1582
  }
1582
1583
  case "tool-call": {
1583
1584
  if (part.providerExecuted) {
1585
+ const providerToolName = toolNameMapping.toProviderToolName(
1586
+ part.toolName
1587
+ );
1584
1588
  const isMcpToolUse = ((_h = (_g = part.providerOptions) == null ? void 0 : _g.anthropic) == null ? void 0 : _h.type) === "mcp-tool-use";
1585
1589
  if (isMcpToolUse) {
1586
1590
  mcpToolUseIds.add(part.toolCallId);
@@ -1602,7 +1606,7 @@ async function convertToAnthropicMessagesPrompt({
1602
1606
  });
1603
1607
  } else if (
1604
1608
  // code execution 20250825:
1605
- part.toolName === "code_execution" && part.input != null && typeof part.input === "object" && "type" in part.input && typeof part.input.type === "string" && (part.input.type === "bash_code_execution" || part.input.type === "text_editor_code_execution")
1609
+ providerToolName === "code_execution" && part.input != null && typeof part.input === "object" && "type" in part.input && typeof part.input.type === "string" && (part.input.type === "bash_code_execution" || part.input.type === "text_editor_code_execution")
1606
1610
  ) {
1607
1611
  anthropicContent.push({
1608
1612
  type: "server_tool_use",
@@ -1612,20 +1616,22 @@ async function convertToAnthropicMessagesPrompt({
1612
1616
  input: part.input,
1613
1617
  cache_control: cacheControl
1614
1618
  });
1615
- } else if (part.toolName === "code_execution" || // code execution 20250522
1616
- part.toolName === "web_fetch" || part.toolName === "web_search") {
1617
- anthropicContent.push({
1618
- type: "server_tool_use",
1619
- id: part.toolCallId,
1620
- name: part.toolName,
1621
- input: part.input,
1622
- cache_control: cacheControl
1623
- });
1624
1619
  } else {
1625
- warnings.push({
1626
- type: "other",
1627
- message: `provider executed tool call for tool ${part.toolName} is not supported`
1628
- });
1620
+ if (providerToolName === "code_execution" || // code execution 20250522
1621
+ providerToolName === "web_fetch" || providerToolName === "web_search") {
1622
+ anthropicContent.push({
1623
+ type: "server_tool_use",
1624
+ id: part.toolCallId,
1625
+ name: providerToolName,
1626
+ input: part.input,
1627
+ cache_control: cacheControl
1628
+ });
1629
+ } else {
1630
+ warnings.push({
1631
+ type: "other",
1632
+ message: `provider executed tool call for tool ${part.toolName} is not supported`
1633
+ });
1634
+ }
1629
1635
  }
1630
1636
  break;
1631
1637
  }
@@ -1639,6 +1645,9 @@ async function convertToAnthropicMessagesPrompt({
1639
1645
  break;
1640
1646
  }
1641
1647
  case "tool-result": {
1648
+ const providerToolName = toolNameMapping.toProviderToolName(
1649
+ part.toolName
1650
+ );
1642
1651
  if (mcpToolUseIds.has(part.toolCallId)) {
1643
1652
  const output = part.output;
1644
1653
  if (output.type !== "json" && output.type !== "error-json") {
@@ -1655,7 +1664,7 @@ async function convertToAnthropicMessagesPrompt({
1655
1664
  content: output.value,
1656
1665
  cache_control: cacheControl
1657
1666
  });
1658
- } else if (part.toolName === "code_execution") {
1667
+ } else if (providerToolName === "code_execution") {
1659
1668
  const output = part.output;
1660
1669
  if (output.type !== "json") {
1661
1670
  warnings.push({
@@ -1708,7 +1717,7 @@ async function convertToAnthropicMessagesPrompt({
1708
1717
  }
1709
1718
  break;
1710
1719
  }
1711
- if (part.toolName === "web_fetch") {
1720
+ if (providerToolName === "web_fetch") {
1712
1721
  const output = part.output;
1713
1722
  if (output.type !== "json") {
1714
1723
  warnings.push({
@@ -1743,7 +1752,7 @@ async function convertToAnthropicMessagesPrompt({
1743
1752
  });
1744
1753
  break;
1745
1754
  }
1746
- if (part.toolName === "web_search") {
1755
+ if (providerToolName === "web_search") {
1747
1756
  const output = part.output;
1748
1757
  if (output.type !== "json") {
1749
1758
  warnings.push({
@@ -1980,11 +1989,30 @@ var AnthropicMessagesLanguageModel = class {
1980
1989
  inputSchema: responseFormat.schema
1981
1990
  } : void 0;
1982
1991
  const cacheControlValidator = new CacheControlValidator();
1992
+ const toolNameMapping = createToolNameMapping({
1993
+ tools,
1994
+ providerToolNames: {
1995
+ "anthropic.code_execution_20250522": "code_execution",
1996
+ "anthropic.code_execution_20250825": "code_execution",
1997
+ "anthropic.computer_20241022": "computer",
1998
+ "anthropic.computer_20250124": "computer",
1999
+ "anthropic.text_editor_20241022": "str_replace_editor",
2000
+ "anthropic.text_editor_20250124": "str_replace_editor",
2001
+ "anthropic.text_editor_20250429": "str_replace_based_edit_tool",
2002
+ "anthropic.text_editor_20250728": "str_replace_based_edit_tool",
2003
+ "anthropic.bash_20241022": "bash",
2004
+ "anthropic.bash_20250124": "bash",
2005
+ "anthropic.memory_20250818": "memory",
2006
+ "anthropic.web_search_20250305": "web_search",
2007
+ "anthropic.web_fetch_20250910": "web_fetch"
2008
+ }
2009
+ });
1983
2010
  const { prompt: messagesPrompt, betas } = await convertToAnthropicMessagesPrompt({
1984
2011
  prompt,
1985
2012
  sendReasoning: (_b = anthropicOptions == null ? void 0 : anthropicOptions.sendReasoning) != null ? _b : true,
1986
2013
  warnings,
1987
- cacheControlValidator
2014
+ cacheControlValidator,
2015
+ toolNameMapping
1988
2016
  });
1989
2017
  const isThinking = ((_c = anthropicOptions == null ? void 0 : anthropicOptions.thinking) == null ? void 0 : _c.type) === "enabled";
1990
2018
  const thinkingBudget = (_d = anthropicOptions == null ? void 0 : anthropicOptions.thinking) == null ? void 0 : _d.budgetTokens;
@@ -2136,7 +2164,8 @@ var AnthropicMessagesLanguageModel = class {
2136
2164
  },
2137
2165
  warnings: [...warnings, ...toolWarnings, ...cacheWarnings],
2138
2166
  betas: /* @__PURE__ */ new Set([...betas, ...toolsBetas, ...userSuppliedBetas]),
2139
- usesJsonResponseTool: jsonResponseTool != null
2167
+ usesJsonResponseTool: jsonResponseTool != null,
2168
+ toolNameMapping
2140
2169
  };
2141
2170
  }
2142
2171
  async getHeaders({
@@ -2194,7 +2223,7 @@ var AnthropicMessagesLanguageModel = class {
2194
2223
  }
2195
2224
  async doGenerate(options) {
2196
2225
  var _a, _b, _c, _d, _e, _f, _g, _h;
2197
- const { args, warnings, betas, usesJsonResponseTool } = await this.getArgs({
2226
+ const { args, warnings, betas, usesJsonResponseTool, toolNameMapping } = await this.getArgs({
2198
2227
  ...options,
2199
2228
  stream: false,
2200
2229
  userSuppliedBetas: await this.getBetasFromHeaders(options.headers)
@@ -2285,7 +2314,7 @@ var AnthropicMessagesLanguageModel = class {
2285
2314
  content.push({
2286
2315
  type: "tool-call",
2287
2316
  toolCallId: part.id,
2288
- toolName: "code_execution",
2317
+ toolName: toolNameMapping.toCustomToolName("code_execution"),
2289
2318
  input: JSON.stringify({ type: part.name, ...part.input }),
2290
2319
  providerExecuted: true
2291
2320
  });
@@ -2293,7 +2322,7 @@ var AnthropicMessagesLanguageModel = class {
2293
2322
  content.push({
2294
2323
  type: "tool-call",
2295
2324
  toolCallId: part.id,
2296
- toolName: part.name,
2325
+ toolName: toolNameMapping.toCustomToolName(part.name),
2297
2326
  input: JSON.stringify(part.input),
2298
2327
  providerExecuted: true
2299
2328
  });
@@ -2335,7 +2364,7 @@ var AnthropicMessagesLanguageModel = class {
2335
2364
  content.push({
2336
2365
  type: "tool-result",
2337
2366
  toolCallId: part.tool_use_id,
2338
- toolName: "web_fetch",
2367
+ toolName: toolNameMapping.toCustomToolName("web_fetch"),
2339
2368
  result: {
2340
2369
  type: "web_fetch_result",
2341
2370
  url: part.content.url,
@@ -2356,7 +2385,7 @@ var AnthropicMessagesLanguageModel = class {
2356
2385
  content.push({
2357
2386
  type: "tool-result",
2358
2387
  toolCallId: part.tool_use_id,
2359
- toolName: "web_fetch",
2388
+ toolName: toolNameMapping.toCustomToolName("web_fetch"),
2360
2389
  isError: true,
2361
2390
  result: {
2362
2391
  type: "web_fetch_tool_result_error",
@@ -2371,7 +2400,7 @@ var AnthropicMessagesLanguageModel = class {
2371
2400
  content.push({
2372
2401
  type: "tool-result",
2373
2402
  toolCallId: part.tool_use_id,
2374
- toolName: "web_search",
2403
+ toolName: toolNameMapping.toCustomToolName("web_search"),
2375
2404
  result: part.content.map((result) => {
2376
2405
  var _a2;
2377
2406
  return {
@@ -2401,7 +2430,7 @@ var AnthropicMessagesLanguageModel = class {
2401
2430
  content.push({
2402
2431
  type: "tool-result",
2403
2432
  toolCallId: part.tool_use_id,
2404
- toolName: "web_search",
2433
+ toolName: toolNameMapping.toCustomToolName("web_search"),
2405
2434
  isError: true,
2406
2435
  result: {
2407
2436
  type: "web_search_tool_result_error",
@@ -2417,7 +2446,7 @@ var AnthropicMessagesLanguageModel = class {
2417
2446
  content.push({
2418
2447
  type: "tool-result",
2419
2448
  toolCallId: part.tool_use_id,
2420
- toolName: "code_execution",
2449
+ toolName: toolNameMapping.toCustomToolName("code_execution"),
2421
2450
  result: {
2422
2451
  type: part.content.type,
2423
2452
  stdout: part.content.stdout,
@@ -2429,7 +2458,7 @@ var AnthropicMessagesLanguageModel = class {
2429
2458
  content.push({
2430
2459
  type: "tool-result",
2431
2460
  toolCallId: part.tool_use_id,
2432
- toolName: "code_execution",
2461
+ toolName: toolNameMapping.toCustomToolName("code_execution"),
2433
2462
  isError: true,
2434
2463
  result: {
2435
2464
  type: "code_execution_tool_result_error",
@@ -2445,7 +2474,7 @@ var AnthropicMessagesLanguageModel = class {
2445
2474
  content.push({
2446
2475
  type: "tool-result",
2447
2476
  toolCallId: part.tool_use_id,
2448
- toolName: "code_execution",
2477
+ toolName: toolNameMapping.toCustomToolName("code_execution"),
2449
2478
  result: part.content
2450
2479
  });
2451
2480
  break;
@@ -2491,11 +2520,13 @@ var AnthropicMessagesLanguageModel = class {
2491
2520
  };
2492
2521
  }
2493
2522
  async doStream(options) {
2523
+ var _a, _b;
2494
2524
  const {
2495
2525
  args: body,
2496
2526
  warnings,
2497
2527
  betas,
2498
- usesJsonResponseTool
2528
+ usesJsonResponseTool,
2529
+ toolNameMapping
2499
2530
  } = await this.getArgs({
2500
2531
  ...options,
2501
2532
  stream: true,
@@ -2529,25 +2560,13 @@ var AnthropicMessagesLanguageModel = class {
2529
2560
  let isJsonResponseFromTool = false;
2530
2561
  let blockType = void 0;
2531
2562
  const generateId2 = this.generateId;
2532
- let isFirstChunk = true;
2533
- let stream = void 0;
2534
- const returnPromise = new DelayedPromise();
2535
2563
  const transformedStream = response.pipeThrough(
2536
2564
  new TransformStream({
2537
2565
  start(controller) {
2538
2566
  controller.enqueue({ type: "stream-start", warnings });
2539
2567
  },
2540
- async flush() {
2541
- if (returnPromise.isPending()) {
2542
- returnPromise.resolve({
2543
- stream,
2544
- request: { body },
2545
- response: { headers: responseHeaders }
2546
- });
2547
- }
2548
- },
2549
2568
  transform(chunk, controller) {
2550
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
2569
+ var _a2, _b2, _c, _d, _e, _f, _g, _h, _i, _j;
2551
2570
  if (options.includeRawChunks) {
2552
2571
  controller.enqueue({ type: "raw", rawValue: chunk.rawValue });
2553
2572
  }
@@ -2555,29 +2574,6 @@ var AnthropicMessagesLanguageModel = class {
2555
2574
  controller.enqueue({ type: "error", error: chunk.error });
2556
2575
  return;
2557
2576
  }
2558
- if (isFirstChunk) {
2559
- if (chunk.value.type === "error") {
2560
- returnPromise.reject(
2561
- new APICallError({
2562
- message: chunk.value.error.message,
2563
- url,
2564
- requestBodyValues: body,
2565
- statusCode: chunk.value.error.type === "overloaded_error" ? 529 : 500,
2566
- responseHeaders,
2567
- responseBody: JSON.stringify(chunk.value.error),
2568
- isRetryable: chunk.value.error.type === "overloaded_error"
2569
- })
2570
- );
2571
- controller.terminate();
2572
- return;
2573
- }
2574
- isFirstChunk = false;
2575
- returnPromise.resolve({
2576
- stream,
2577
- request: { body },
2578
- response: { headers: responseHeaders }
2579
- });
2580
- }
2581
2577
  const value = chunk.value;
2582
2578
  switch (value.type) {
2583
2579
  case "ping": {
@@ -2656,19 +2652,21 @@ var AnthropicMessagesLanguageModel = class {
2656
2652
  // code execution 20250825 bash:
2657
2653
  "bash_code_execution"
2658
2654
  ].includes(part.name)) {
2655
+ const providerToolName = part.name === "text_editor_code_execution" || part.name === "bash_code_execution" ? "code_execution" : part.name;
2656
+ const customToolName = toolNameMapping.toCustomToolName(providerToolName);
2659
2657
  contentBlocks[value.index] = {
2660
2658
  type: "tool-call",
2661
2659
  toolCallId: part.id,
2662
- toolName: part.name,
2660
+ toolName: customToolName,
2663
2661
  input: "",
2664
2662
  providerExecuted: true,
2665
- firstDelta: true
2663
+ firstDelta: true,
2664
+ providerToolName: part.name
2666
2665
  };
2667
- const mappedToolName = part.name === "text_editor_code_execution" || part.name === "bash_code_execution" ? "code_execution" : part.name;
2668
2666
  controller.enqueue({
2669
2667
  type: "tool-input-start",
2670
2668
  id: part.id,
2671
- toolName: mappedToolName,
2669
+ toolName: customToolName,
2672
2670
  providerExecuted: true
2673
2671
  });
2674
2672
  }
@@ -2679,7 +2677,7 @@ var AnthropicMessagesLanguageModel = class {
2679
2677
  controller.enqueue({
2680
2678
  type: "tool-result",
2681
2679
  toolCallId: part.tool_use_id,
2682
- toolName: "web_fetch",
2680
+ toolName: toolNameMapping.toCustomToolName("web_fetch"),
2683
2681
  result: {
2684
2682
  type: "web_fetch_result",
2685
2683
  url: part.content.url,
@@ -2700,7 +2698,7 @@ var AnthropicMessagesLanguageModel = class {
2700
2698
  controller.enqueue({
2701
2699
  type: "tool-result",
2702
2700
  toolCallId: part.tool_use_id,
2703
- toolName: "web_fetch",
2701
+ toolName: toolNameMapping.toCustomToolName("web_fetch"),
2704
2702
  isError: true,
2705
2703
  result: {
2706
2704
  type: "web_fetch_tool_result_error",
@@ -2715,13 +2713,13 @@ var AnthropicMessagesLanguageModel = class {
2715
2713
  controller.enqueue({
2716
2714
  type: "tool-result",
2717
2715
  toolCallId: part.tool_use_id,
2718
- toolName: "web_search",
2716
+ toolName: toolNameMapping.toCustomToolName("web_search"),
2719
2717
  result: part.content.map((result) => {
2720
- var _a2;
2718
+ var _a3;
2721
2719
  return {
2722
2720
  url: result.url,
2723
2721
  title: result.title,
2724
- pageAge: (_a2 = result.page_age) != null ? _a2 : null,
2722
+ pageAge: (_a3 = result.page_age) != null ? _a3 : null,
2725
2723
  encryptedContent: result.encrypted_content,
2726
2724
  type: result.type
2727
2725
  };
@@ -2736,7 +2734,7 @@ var AnthropicMessagesLanguageModel = class {
2736
2734
  title: result.title,
2737
2735
  providerMetadata: {
2738
2736
  anthropic: {
2739
- pageAge: (_a = result.page_age) != null ? _a : null
2737
+ pageAge: (_a2 = result.page_age) != null ? _a2 : null
2740
2738
  }
2741
2739
  }
2742
2740
  });
@@ -2745,7 +2743,7 @@ var AnthropicMessagesLanguageModel = class {
2745
2743
  controller.enqueue({
2746
2744
  type: "tool-result",
2747
2745
  toolCallId: part.tool_use_id,
2748
- toolName: "web_search",
2746
+ toolName: toolNameMapping.toCustomToolName("web_search"),
2749
2747
  isError: true,
2750
2748
  result: {
2751
2749
  type: "web_search_tool_result_error",
@@ -2761,7 +2759,7 @@ var AnthropicMessagesLanguageModel = class {
2761
2759
  controller.enqueue({
2762
2760
  type: "tool-result",
2763
2761
  toolCallId: part.tool_use_id,
2764
- toolName: "code_execution",
2762
+ toolName: toolNameMapping.toCustomToolName("code_execution"),
2765
2763
  result: {
2766
2764
  type: part.content.type,
2767
2765
  stdout: part.content.stdout,
@@ -2773,7 +2771,7 @@ var AnthropicMessagesLanguageModel = class {
2773
2771
  controller.enqueue({
2774
2772
  type: "tool-result",
2775
2773
  toolCallId: part.tool_use_id,
2776
- toolName: "code_execution",
2774
+ toolName: toolNameMapping.toCustomToolName("code_execution"),
2777
2775
  isError: true,
2778
2776
  result: {
2779
2777
  type: "code_execution_tool_result_error",
@@ -2789,7 +2787,7 @@ var AnthropicMessagesLanguageModel = class {
2789
2787
  controller.enqueue({
2790
2788
  type: "tool-result",
2791
2789
  toolCallId: part.tool_use_id,
2792
- toolName: "code_execution",
2790
+ toolName: toolNameMapping.toCustomToolName("code_execution"),
2793
2791
  result: part.content
2794
2792
  });
2795
2793
  return;
@@ -2857,11 +2855,10 @@ var AnthropicMessagesLanguageModel = class {
2857
2855
  type: "tool-input-end",
2858
2856
  id: contentBlock.toolCallId
2859
2857
  });
2860
- const toolName = contentBlock.toolName === "text_editor_code_execution" || contentBlock.toolName === "bash_code_execution" ? "code_execution" : contentBlock.toolName;
2861
2858
  controller.enqueue({
2862
2859
  type: "tool-call",
2863
2860
  toolCallId: contentBlock.toolCallId,
2864
- toolName,
2861
+ toolName: contentBlock.toolName,
2865
2862
  input: contentBlock.input === "" ? "{}" : contentBlock.input,
2866
2863
  providerExecuted: contentBlock.providerExecuted
2867
2864
  });
@@ -2929,8 +2926,8 @@ var AnthropicMessagesLanguageModel = class {
2929
2926
  if ((contentBlock == null ? void 0 : contentBlock.type) !== "tool-call") {
2930
2927
  return;
2931
2928
  }
2932
- if (contentBlock.firstDelta && (contentBlock.toolName === "bash_code_execution" || contentBlock.toolName === "text_editor_code_execution")) {
2933
- delta = `{"type": "${contentBlock.toolName}",${delta.substring(1)}`;
2929
+ if (contentBlock.firstDelta && (contentBlock.providerToolName === "bash_code_execution" || contentBlock.providerToolName === "text_editor_code_execution")) {
2930
+ delta = `{"type": "${contentBlock.providerToolName}",${delta.substring(1)}`;
2934
2931
  }
2935
2932
  controller.enqueue({
2936
2933
  type: "tool-input-delta",
@@ -2964,7 +2961,7 @@ var AnthropicMessagesLanguageModel = class {
2964
2961
  }
2965
2962
  case "message_start": {
2966
2963
  usage.inputTokens = value.message.usage.input_tokens;
2967
- usage.cachedInputTokens = (_b = value.message.usage.cache_read_input_tokens) != null ? _b : void 0;
2964
+ usage.cachedInputTokens = (_b2 = value.message.usage.cache_read_input_tokens) != null ? _b2 : void 0;
2968
2965
  rawUsage = {
2969
2966
  ...value.message.usage
2970
2967
  };
@@ -3028,22 +3025,35 @@ var AnthropicMessagesLanguageModel = class {
3028
3025
  })
3029
3026
  );
3030
3027
  const [streamForFirstChunk, streamForConsumer] = transformedStream.tee();
3031
- stream = streamForConsumer;
3032
3028
  const firstChunkReader = streamForFirstChunk.getReader();
3033
3029
  try {
3034
- const { done } = await firstChunkReader.read();
3035
- if (!done) {
3036
- firstChunkReader.cancel();
3030
+ await firstChunkReader.read();
3031
+ let result = await firstChunkReader.read();
3032
+ if (((_a = result.value) == null ? void 0 : _a.type) === "raw") {
3033
+ result = await firstChunkReader.read();
3037
3034
  }
3038
- } catch (error) {
3039
- try {
3040
- firstChunkReader.cancel();
3041
- } catch (e) {
3035
+ if (((_b = result.value) == null ? void 0 : _b.type) === "error") {
3036
+ const error = result.value.error;
3037
+ throw new APICallError({
3038
+ message: error.message,
3039
+ url,
3040
+ requestBodyValues: body,
3041
+ statusCode: error.type === "overloaded_error" ? 529 : 500,
3042
+ responseHeaders,
3043
+ responseBody: JSON.stringify(error),
3044
+ isRetryable: error.type === "overloaded_error"
3045
+ });
3042
3046
  }
3043
3047
  } finally {
3048
+ firstChunkReader.cancel().catch(() => {
3049
+ });
3044
3050
  firstChunkReader.releaseLock();
3045
3051
  }
3046
- return returnPromise.promise;
3052
+ return {
3053
+ stream: streamForConsumer,
3054
+ request: { body },
3055
+ response: { headers: responseHeaders }
3056
+ };
3047
3057
  }
3048
3058
  };
3049
3059
  function getModelCapabilities(modelId) {