@jambonz/llm 0.1.0 → 0.2.1

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.
@@ -212,6 +212,28 @@ async function* streamFromOpenAI(client, req, options) {
212
212
  };
213
213
  yield endEvent;
214
214
  }
215
+ function appendOpenAIAssistantToolCall(history, toolCalls) {
216
+ const wireMessage = {
217
+ role: "assistant",
218
+ content: null,
219
+ tool_calls: toolCalls.map((tc) => ({
220
+ id: tc.id,
221
+ type: "function",
222
+ function: {
223
+ name: tc.name,
224
+ arguments: typeof tc.arguments === "string" ? tc.arguments : JSON.stringify(tc.arguments ?? {})
225
+ }
226
+ }))
227
+ };
228
+ return [
229
+ ...history,
230
+ {
231
+ role: "assistant",
232
+ content: "",
233
+ vendorRaw: wireMessage
234
+ }
235
+ ];
236
+ }
215
237
  function appendOpenAIToolResult(history, toolCallId, result) {
216
238
  const content = typeof result === "string" ? result : JSON.stringify(result);
217
239
  const wireMessage = {
@@ -433,6 +455,9 @@ var OpenAIAdapter = class {
433
455
  knownModels: openAIManifest.knownModels
434
456
  });
435
457
  }
458
+ appendAssistantToolCall(history, toolCalls) {
459
+ return appendOpenAIAssistantToolCall(history, toolCalls);
460
+ }
436
461
  appendToolResult(history, toolCallId, result) {
437
462
  return appendOpenAIToolResult(history, toolCallId, result);
438
463
  }
@@ -783,6 +808,25 @@ var AnthropicAdapter = class {
783
808
  };
784
809
  yield endEvent;
785
810
  }
811
+ appendAssistantToolCall(history, toolCalls) {
812
+ const wireMessage = {
813
+ role: "assistant",
814
+ content: toolCalls.map((tc) => ({
815
+ type: "tool_use",
816
+ id: tc.id,
817
+ name: tc.name,
818
+ input: tc.arguments ?? {}
819
+ }))
820
+ };
821
+ return [
822
+ ...history,
823
+ {
824
+ role: "assistant",
825
+ content: "",
826
+ vendorRaw: wireMessage
827
+ }
828
+ ];
829
+ }
786
830
  appendToolResult(history, toolCallId, result) {
787
831
  const content = typeof result === "string" ? result : JSON.stringify(result);
788
832
  const wireMessage = {
@@ -998,6 +1042,25 @@ async function* streamFromGemini(client, req) {
998
1042
  };
999
1043
  yield endEvent;
1000
1044
  }
1045
+ function appendGeminiAssistantToolCall(history, toolCalls) {
1046
+ const wireMessage = {
1047
+ role: "model",
1048
+ parts: toolCalls.map((tc) => ({
1049
+ functionCall: {
1050
+ name: parseToolName(tc.id),
1051
+ args: tc.arguments ?? {}
1052
+ }
1053
+ }))
1054
+ };
1055
+ return [
1056
+ ...history,
1057
+ {
1058
+ role: "assistant",
1059
+ content: "",
1060
+ vendorRaw: wireMessage
1061
+ }
1062
+ ];
1063
+ }
1001
1064
  function appendGeminiToolResult(history, toolCallId, result) {
1002
1065
  const name = parseToolName(toolCallId);
1003
1066
  const content = typeof result === "string" ? result : JSON.stringify(result);
@@ -1220,6 +1283,9 @@ var GoogleAdapter = class {
1220
1283
  stream(req) {
1221
1284
  return streamFromGemini(this.ensureClient(), req);
1222
1285
  }
1286
+ appendAssistantToolCall(history, toolCalls) {
1287
+ return appendGeminiAssistantToolCall(history, toolCalls);
1288
+ }
1223
1289
  appendToolResult(history, toolCallId, result) {
1224
1290
  return appendGeminiToolResult(history, toolCallId, result);
1225
1291
  }
@@ -1387,6 +1453,9 @@ var VertexGeminiAdapter = class {
1387
1453
  stream(req) {
1388
1454
  return streamFromGemini(this.ensureClient(), req);
1389
1455
  }
1456
+ appendAssistantToolCall(history, toolCalls) {
1457
+ return appendGeminiAssistantToolCall(history, toolCalls);
1458
+ }
1390
1459
  appendToolResult(history, toolCallId, result) {
1391
1460
  return appendGeminiToolResult(history, toolCallId, result);
1392
1461
  }
@@ -1553,6 +1622,9 @@ var VertexOpenAIAdapter = class {
1553
1622
  knownModels: vertexOpenAIManifest.knownModels
1554
1623
  });
1555
1624
  }
1625
+ appendAssistantToolCall(history, toolCalls) {
1626
+ return appendOpenAIAssistantToolCall(history, toolCalls);
1627
+ }
1556
1628
  appendToolResult(history, toolCallId, result) {
1557
1629
  return appendOpenAIToolResult(history, toolCallId, result);
1558
1630
  }
@@ -1584,30 +1656,30 @@ var import_client_bedrock_runtime = require("@aws-sdk/client-bedrock-runtime");
1584
1656
  // src/adapters/bedrock/manifest.ts
1585
1657
  var BEDROCK_KNOWN_MODELS = [
1586
1658
  {
1587
- id: "anthropic.claude-opus-4-v1:0",
1588
- displayName: "Claude Opus 4 (on Bedrock)",
1659
+ id: "anthropic.claude-3-haiku-20240307-v1:0",
1660
+ displayName: "Claude 3 Haiku (on Bedrock)",
1589
1661
  capabilities: {
1590
1662
  streaming: true,
1591
1663
  tools: true,
1592
- vision: true,
1664
+ vision: false,
1593
1665
  systemPrompt: true,
1594
1666
  maxContextTokens: 2e5
1595
1667
  }
1596
1668
  },
1597
1669
  {
1598
- id: "anthropic.claude-sonnet-4-v1:0",
1599
- displayName: "Claude Sonnet 4 (on Bedrock)",
1670
+ id: "anthropic.claude-3-5-haiku-20241022-v1:0",
1671
+ displayName: "Claude 3.5 Haiku (on Bedrock)",
1600
1672
  capabilities: {
1601
1673
  streaming: true,
1602
1674
  tools: true,
1603
- vision: true,
1675
+ vision: false,
1604
1676
  systemPrompt: true,
1605
1677
  maxContextTokens: 2e5
1606
1678
  }
1607
1679
  },
1608
1680
  {
1609
- id: "anthropic.claude-3-7-sonnet-20250219-v1:0",
1610
- displayName: "Claude 3.7 Sonnet (on Bedrock)",
1681
+ id: "anthropic.claude-3-5-sonnet-20240620-v1:0",
1682
+ displayName: "Claude 3.5 Sonnet (on Bedrock)",
1611
1683
  capabilities: {
1612
1684
  streaming: true,
1613
1685
  tools: true,
@@ -1628,19 +1700,19 @@ var BEDROCK_KNOWN_MODELS = [
1628
1700
  }
1629
1701
  },
1630
1702
  {
1631
- id: "anthropic.claude-3-5-haiku-20241022-v1:0",
1632
- displayName: "Claude 3.5 Haiku (on Bedrock)",
1703
+ id: "anthropic.claude-3-7-sonnet-20250219-v1:0",
1704
+ displayName: "Claude 3.7 Sonnet (on Bedrock)",
1633
1705
  capabilities: {
1634
1706
  streaming: true,
1635
1707
  tools: true,
1636
- vision: false,
1708
+ vision: true,
1637
1709
  systemPrompt: true,
1638
1710
  maxContextTokens: 2e5
1639
1711
  }
1640
1712
  },
1641
1713
  {
1642
- id: "meta.llama3-3-70b-instruct-v1:0",
1643
- displayName: "Llama 3.3 70B Instruct (on Bedrock)",
1714
+ id: "amazon.nova-micro-v1:0",
1715
+ displayName: "Amazon Nova Micro",
1644
1716
  capabilities: {
1645
1717
  streaming: true,
1646
1718
  tools: true,
@@ -1650,14 +1722,14 @@ var BEDROCK_KNOWN_MODELS = [
1650
1722
  }
1651
1723
  },
1652
1724
  {
1653
- id: "mistral.mistral-large-2407-v1:0",
1654
- displayName: "Mistral Large (on Bedrock)",
1725
+ id: "amazon.nova-lite-v1:0",
1726
+ displayName: "Amazon Nova Lite",
1655
1727
  capabilities: {
1656
1728
  streaming: true,
1657
1729
  tools: true,
1658
- vision: false,
1730
+ vision: true,
1659
1731
  systemPrompt: true,
1660
- maxContextTokens: 128e3
1732
+ maxContextTokens: 3e5
1661
1733
  }
1662
1734
  },
1663
1735
  {
@@ -1672,19 +1744,19 @@ var BEDROCK_KNOWN_MODELS = [
1672
1744
  }
1673
1745
  },
1674
1746
  {
1675
- id: "amazon.nova-lite-v1:0",
1676
- displayName: "Amazon Nova Lite",
1747
+ id: "meta.llama3-3-70b-instruct-v1:0",
1748
+ displayName: "Llama 3.3 70B Instruct (on Bedrock)",
1677
1749
  capabilities: {
1678
1750
  streaming: true,
1679
1751
  tools: true,
1680
- vision: true,
1752
+ vision: false,
1681
1753
  systemPrompt: true,
1682
- maxContextTokens: 3e5
1754
+ maxContextTokens: 128e3
1683
1755
  }
1684
1756
  },
1685
1757
  {
1686
- id: "amazon.nova-micro-v1:0",
1687
- displayName: "Amazon Nova Micro",
1758
+ id: "mistral.mistral-large-2407-v1:0",
1759
+ displayName: "Mistral Large (on Bedrock)",
1688
1760
  capabilities: {
1689
1761
  streaming: true,
1690
1762
  tools: true,
@@ -1942,6 +2014,26 @@ var BedrockAdapter = class {
1942
2014
  };
1943
2015
  yield endEvent;
1944
2016
  }
2017
+ appendAssistantToolCall(history, toolCalls) {
2018
+ const wireMessage = {
2019
+ role: "assistant",
2020
+ content: toolCalls.map((tc) => ({
2021
+ toolUse: {
2022
+ toolUseId: tc.id,
2023
+ name: tc.name,
2024
+ input: tc.arguments ?? {}
2025
+ }
2026
+ }))
2027
+ };
2028
+ return [
2029
+ ...history,
2030
+ {
2031
+ role: "assistant",
2032
+ content: "",
2033
+ vendorRaw: wireMessage
2034
+ }
2035
+ ];
2036
+ }
1945
2037
  appendToolResult(history, toolCallId, result) {
1946
2038
  const text = typeof result === "string" ? result : JSON.stringify(result);
1947
2039
  const wireMessage = {
@@ -2269,12 +2361,11 @@ function runContractTests(harness) {
2269
2361
  (e) => e.type === "toolCall"
2270
2362
  );
2271
2363
  (0, import_vitest.expect)(tc).toBeDefined();
2272
- const history = [
2273
- { role: "user", content: "call it" },
2274
- harness.buildAssistantWithToolCall(tc)
2275
- ];
2276
- const withResult = adapter.appendToolResult(history, tc.id, { ok: true });
2277
- (0, import_vitest.expect)(withResult.length).toBe(history.length + 1);
2364
+ const baseHistory = [{ role: "user", content: "call it" }];
2365
+ const afterAssistant = adapter.appendAssistantToolCall(baseHistory, [tc]);
2366
+ (0, import_vitest.expect)(afterAssistant.length).toBe(baseHistory.length + 1);
2367
+ const withResult = adapter.appendToolResult(afterAssistant, tc.id, { ok: true });
2368
+ (0, import_vitest.expect)(withResult.length).toBe(afterAssistant.length + 1);
2278
2369
  await harness.mockScenario("simple-stream");
2279
2370
  await (0, import_vitest.expect)(
2280
2371
  drainStream(adapter, {
@@ -2362,11 +2453,11 @@ function runContractTests(harness) {
2362
2453
  (e) => e.type === "toolCall"
2363
2454
  );
2364
2455
  (0, import_vitest.expect)(tc).toBeDefined();
2365
- const history = [
2366
- { role: "user", content: "go" },
2367
- harness.buildAssistantWithToolCall(tc)
2368
- ];
2369
- const withResult = adapter.appendToolResult(history, tc.id, { ok: true });
2456
+ const afterAssistant = adapter.appendAssistantToolCall(
2457
+ [{ role: "user", content: "go" }],
2458
+ [tc]
2459
+ );
2460
+ const withResult = adapter.appendToolResult(afterAssistant, tc.id, { ok: true });
2370
2461
  await harness.mockScenario("simple-stream");
2371
2462
  await drainStream(adapter, {
2372
2463
  model: harness.toolCapableModel,
@@ -2376,6 +2467,28 @@ function runContractTests(harness) {
2376
2467
  (0, import_vitest.expect)(captured).not.toBeNull();
2377
2468
  (0, import_vitest.expect)(captured.vendorRawHonored).toBe(true);
2378
2469
  });
2470
+ (0, import_vitest.it)("[21] appendAssistantToolCall output + appendToolResult re-stream preserves tool-call id on wire", async () => {
2471
+ await harness.mockScenario("tool-call");
2472
+ const adapter = await init(harness);
2473
+ const first = await drainStream(adapter, {
2474
+ model: harness.toolCapableModel,
2475
+ messages: [{ role: "user", content: "go" }],
2476
+ tools: [
2477
+ { name: "test_tool", description: "x", parameters: { type: "object" } }
2478
+ ]
2479
+ });
2480
+ const tc = first.find(
2481
+ (e) => e.type === "toolCall"
2482
+ );
2483
+ (0, import_vitest.expect)(tc).toBeDefined();
2484
+ const history = adapter.appendAssistantToolCall(
2485
+ [{ role: "user", content: "go" }],
2486
+ [tc]
2487
+ );
2488
+ const appended = history[history.length - 1];
2489
+ (0, import_vitest.expect)(appended.role).toBe("assistant");
2490
+ (0, import_vitest.expect)(appended.vendorRaw).toBeDefined();
2491
+ });
2379
2492
  });
2380
2493
  }
2381
2494
  async function init(harness) {
@@ -2440,6 +2553,23 @@ var FakeAdapter = class {
2440
2553
  throw new Error(`FakeAdapter: unknown scenario '${scenario}'`);
2441
2554
  }
2442
2555
  }
2556
+ appendAssistantToolCall(history, toolCalls) {
2557
+ return [
2558
+ ...history,
2559
+ {
2560
+ role: "assistant",
2561
+ content: "",
2562
+ vendorRaw: {
2563
+ role: "assistant",
2564
+ toolCalls: toolCalls.map((tc) => ({
2565
+ id: tc.id,
2566
+ name: tc.name,
2567
+ arguments: tc.arguments
2568
+ }))
2569
+ }
2570
+ }
2571
+ ];
2572
+ }
2443
2573
  appendToolResult(history, toolCallId, result) {
2444
2574
  const content = typeof result === "string" ? result : JSON.stringify(result);
2445
2575
  return [
@@ -2622,17 +2752,7 @@ function createFakeHarness() {
2622
2752
  },
2623
2753
  toolCapableModel: "fake-tool-model",
2624
2754
  nonToolCapableModel: "fake-plain-model",
2625
- emitsToolCallStart: true,
2626
- buildAssistantWithToolCall(tc) {
2627
- return {
2628
- role: "assistant",
2629
- content: "",
2630
- vendorRaw: {
2631
- role: "assistant",
2632
- toolCall: { id: tc.id, name: tc.name, arguments: tc.arguments }
2633
- }
2634
- };
2635
- }
2755
+ emitsToolCallStart: true
2636
2756
  };
2637
2757
  }
2638
2758
  // Annotate the CommonJS export names for ESM import in node: