@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.
@@ -1,4 +1,4 @@
1
- import { a as AdapterFactory, d as AuthKind, A as AuthSpec, l as LlmEvent, M as Message, L as LlmAdapter, c as ApiKeyAuth, g as ClientOptions, P as PromptRequest, n as ModelInfo, b as AdapterManifest } from '../types-D8rgMCbi.cjs';
1
+ import { a as AdapterFactory, d as AuthKind, A as AuthSpec, L as LlmAdapter, c as ApiKeyAuth, g as ClientOptions, P as PromptRequest, l as LlmEvent, M as Message, o as ToolCallEvent, n as ModelInfo, b as AdapterManifest } from '../types-bq1XMi_T.cjs';
2
2
 
3
3
  /**
4
4
  * Named scenarios the harness must be able to stage. Each scenario configures
@@ -88,19 +88,6 @@ interface ContractHarness {
88
88
  * (toolCallStart precedes toolCall) runs; if false, that check is skipped.
89
89
  */
90
90
  emitsToolCallStart: boolean;
91
- /**
92
- * Construct an assistant `Message` (with `vendorRaw` populated in the shape
93
- * THIS adapter expects back on re-submission) given a `toolCall` event the
94
- * adapter previously emitted. Used by checks #13 and #20 to round-trip a
95
- * realistic history through a subsequent `stream()` call.
96
- *
97
- * Implementation tip: set `vendorRaw` to the full vendor-native assistant
98
- * message — the same shape your adapter puts in history after emitting a
99
- * tool call during streaming.
100
- */
101
- buildAssistantWithToolCall(tc: Extract<LlmEvent, {
102
- type: 'toolCall';
103
- }>): Message;
104
91
  }
105
92
 
106
93
  /**
@@ -142,6 +129,7 @@ declare class FakeAdapter implements LlmAdapter<ApiKeyAuth> {
142
129
  constructor(state: FakeState);
143
130
  init(auth: ApiKeyAuth, _client?: ClientOptions): void;
144
131
  stream(req: PromptRequest): AsyncIterable<LlmEvent>;
132
+ appendAssistantToolCall(history: Message[], toolCalls: ReadonlyArray<ToolCallEvent>): Message[];
145
133
  appendToolResult(history: Message[], toolCallId: string, result: unknown): Message[];
146
134
  listAvailableModels(): Promise<ModelInfo[]>;
147
135
  private ensureInitialized;
@@ -1,4 +1,4 @@
1
- import { a as AdapterFactory, d as AuthKind, A as AuthSpec, l as LlmEvent, M as Message, L as LlmAdapter, c as ApiKeyAuth, g as ClientOptions, P as PromptRequest, n as ModelInfo, b as AdapterManifest } from '../types-D8rgMCbi.js';
1
+ import { a as AdapterFactory, d as AuthKind, A as AuthSpec, L as LlmAdapter, c as ApiKeyAuth, g as ClientOptions, P as PromptRequest, l as LlmEvent, M as Message, o as ToolCallEvent, n as ModelInfo, b as AdapterManifest } from '../types-bq1XMi_T.js';
2
2
 
3
3
  /**
4
4
  * Named scenarios the harness must be able to stage. Each scenario configures
@@ -88,19 +88,6 @@ interface ContractHarness {
88
88
  * (toolCallStart precedes toolCall) runs; if false, that check is skipped.
89
89
  */
90
90
  emitsToolCallStart: boolean;
91
- /**
92
- * Construct an assistant `Message` (with `vendorRaw` populated in the shape
93
- * THIS adapter expects back on re-submission) given a `toolCall` event the
94
- * adapter previously emitted. Used by checks #13 and #20 to round-trip a
95
- * realistic history through a subsequent `stream()` call.
96
- *
97
- * Implementation tip: set `vendorRaw` to the full vendor-native assistant
98
- * message — the same shape your adapter puts in history after emitting a
99
- * tool call during streaming.
100
- */
101
- buildAssistantWithToolCall(tc: Extract<LlmEvent, {
102
- type: 'toolCall';
103
- }>): Message;
104
91
  }
105
92
 
106
93
  /**
@@ -142,6 +129,7 @@ declare class FakeAdapter implements LlmAdapter<ApiKeyAuth> {
142
129
  constructor(state: FakeState);
143
130
  init(auth: ApiKeyAuth, _client?: ClientOptions): void;
144
131
  stream(req: PromptRequest): AsyncIterable<LlmEvent>;
132
+ appendAssistantToolCall(history: Message[], toolCalls: ReadonlyArray<ToolCallEvent>): Message[];
145
133
  appendToolResult(history: Message[], toolCallId: string, result: unknown): Message[];
146
134
  listAvailableModels(): Promise<ModelInfo[]>;
147
135
  private ensureInitialized;
@@ -173,6 +173,28 @@ async function* streamFromOpenAI(client, req, options) {
173
173
  };
174
174
  yield endEvent;
175
175
  }
176
+ function appendOpenAIAssistantToolCall(history, toolCalls) {
177
+ const wireMessage = {
178
+ role: "assistant",
179
+ content: null,
180
+ tool_calls: toolCalls.map((tc) => ({
181
+ id: tc.id,
182
+ type: "function",
183
+ function: {
184
+ name: tc.name,
185
+ arguments: typeof tc.arguments === "string" ? tc.arguments : JSON.stringify(tc.arguments ?? {})
186
+ }
187
+ }))
188
+ };
189
+ return [
190
+ ...history,
191
+ {
192
+ role: "assistant",
193
+ content: "",
194
+ vendorRaw: wireMessage
195
+ }
196
+ ];
197
+ }
176
198
  function appendOpenAIToolResult(history, toolCallId, result) {
177
199
  const content = typeof result === "string" ? result : JSON.stringify(result);
178
200
  const wireMessage = {
@@ -394,6 +416,9 @@ var OpenAIAdapter = class {
394
416
  knownModels: openAIManifest.knownModels
395
417
  });
396
418
  }
419
+ appendAssistantToolCall(history, toolCalls) {
420
+ return appendOpenAIAssistantToolCall(history, toolCalls);
421
+ }
397
422
  appendToolResult(history, toolCallId, result) {
398
423
  return appendOpenAIToolResult(history, toolCallId, result);
399
424
  }
@@ -744,6 +769,25 @@ var AnthropicAdapter = class {
744
769
  };
745
770
  yield endEvent;
746
771
  }
772
+ appendAssistantToolCall(history, toolCalls) {
773
+ const wireMessage = {
774
+ role: "assistant",
775
+ content: toolCalls.map((tc) => ({
776
+ type: "tool_use",
777
+ id: tc.id,
778
+ name: tc.name,
779
+ input: tc.arguments ?? {}
780
+ }))
781
+ };
782
+ return [
783
+ ...history,
784
+ {
785
+ role: "assistant",
786
+ content: "",
787
+ vendorRaw: wireMessage
788
+ }
789
+ ];
790
+ }
747
791
  appendToolResult(history, toolCallId, result) {
748
792
  const content = typeof result === "string" ? result : JSON.stringify(result);
749
793
  const wireMessage = {
@@ -959,6 +1003,25 @@ async function* streamFromGemini(client, req) {
959
1003
  };
960
1004
  yield endEvent;
961
1005
  }
1006
+ function appendGeminiAssistantToolCall(history, toolCalls) {
1007
+ const wireMessage = {
1008
+ role: "model",
1009
+ parts: toolCalls.map((tc) => ({
1010
+ functionCall: {
1011
+ name: parseToolName(tc.id),
1012
+ args: tc.arguments ?? {}
1013
+ }
1014
+ }))
1015
+ };
1016
+ return [
1017
+ ...history,
1018
+ {
1019
+ role: "assistant",
1020
+ content: "",
1021
+ vendorRaw: wireMessage
1022
+ }
1023
+ ];
1024
+ }
962
1025
  function appendGeminiToolResult(history, toolCallId, result) {
963
1026
  const name = parseToolName(toolCallId);
964
1027
  const content = typeof result === "string" ? result : JSON.stringify(result);
@@ -1181,6 +1244,9 @@ var GoogleAdapter = class {
1181
1244
  stream(req) {
1182
1245
  return streamFromGemini(this.ensureClient(), req);
1183
1246
  }
1247
+ appendAssistantToolCall(history, toolCalls) {
1248
+ return appendGeminiAssistantToolCall(history, toolCalls);
1249
+ }
1184
1250
  appendToolResult(history, toolCallId, result) {
1185
1251
  return appendGeminiToolResult(history, toolCallId, result);
1186
1252
  }
@@ -1348,6 +1414,9 @@ var VertexGeminiAdapter = class {
1348
1414
  stream(req) {
1349
1415
  return streamFromGemini(this.ensureClient(), req);
1350
1416
  }
1417
+ appendAssistantToolCall(history, toolCalls) {
1418
+ return appendGeminiAssistantToolCall(history, toolCalls);
1419
+ }
1351
1420
  appendToolResult(history, toolCallId, result) {
1352
1421
  return appendGeminiToolResult(history, toolCallId, result);
1353
1422
  }
@@ -1514,6 +1583,9 @@ var VertexOpenAIAdapter = class {
1514
1583
  knownModels: vertexOpenAIManifest.knownModels
1515
1584
  });
1516
1585
  }
1586
+ appendAssistantToolCall(history, toolCalls) {
1587
+ return appendOpenAIAssistantToolCall(history, toolCalls);
1588
+ }
1517
1589
  appendToolResult(history, toolCallId, result) {
1518
1590
  return appendOpenAIToolResult(history, toolCallId, result);
1519
1591
  }
@@ -1548,30 +1620,30 @@ import {
1548
1620
  // src/adapters/bedrock/manifest.ts
1549
1621
  var BEDROCK_KNOWN_MODELS = [
1550
1622
  {
1551
- id: "anthropic.claude-opus-4-v1:0",
1552
- displayName: "Claude Opus 4 (on Bedrock)",
1623
+ id: "anthropic.claude-3-haiku-20240307-v1:0",
1624
+ displayName: "Claude 3 Haiku (on Bedrock)",
1553
1625
  capabilities: {
1554
1626
  streaming: true,
1555
1627
  tools: true,
1556
- vision: true,
1628
+ vision: false,
1557
1629
  systemPrompt: true,
1558
1630
  maxContextTokens: 2e5
1559
1631
  }
1560
1632
  },
1561
1633
  {
1562
- id: "anthropic.claude-sonnet-4-v1:0",
1563
- displayName: "Claude Sonnet 4 (on Bedrock)",
1634
+ id: "anthropic.claude-3-5-haiku-20241022-v1:0",
1635
+ displayName: "Claude 3.5 Haiku (on Bedrock)",
1564
1636
  capabilities: {
1565
1637
  streaming: true,
1566
1638
  tools: true,
1567
- vision: true,
1639
+ vision: false,
1568
1640
  systemPrompt: true,
1569
1641
  maxContextTokens: 2e5
1570
1642
  }
1571
1643
  },
1572
1644
  {
1573
- id: "anthropic.claude-3-7-sonnet-20250219-v1:0",
1574
- displayName: "Claude 3.7 Sonnet (on Bedrock)",
1645
+ id: "anthropic.claude-3-5-sonnet-20240620-v1:0",
1646
+ displayName: "Claude 3.5 Sonnet (on Bedrock)",
1575
1647
  capabilities: {
1576
1648
  streaming: true,
1577
1649
  tools: true,
@@ -1592,19 +1664,19 @@ var BEDROCK_KNOWN_MODELS = [
1592
1664
  }
1593
1665
  },
1594
1666
  {
1595
- id: "anthropic.claude-3-5-haiku-20241022-v1:0",
1596
- displayName: "Claude 3.5 Haiku (on Bedrock)",
1667
+ id: "anthropic.claude-3-7-sonnet-20250219-v1:0",
1668
+ displayName: "Claude 3.7 Sonnet (on Bedrock)",
1597
1669
  capabilities: {
1598
1670
  streaming: true,
1599
1671
  tools: true,
1600
- vision: false,
1672
+ vision: true,
1601
1673
  systemPrompt: true,
1602
1674
  maxContextTokens: 2e5
1603
1675
  }
1604
1676
  },
1605
1677
  {
1606
- id: "meta.llama3-3-70b-instruct-v1:0",
1607
- displayName: "Llama 3.3 70B Instruct (on Bedrock)",
1678
+ id: "amazon.nova-micro-v1:0",
1679
+ displayName: "Amazon Nova Micro",
1608
1680
  capabilities: {
1609
1681
  streaming: true,
1610
1682
  tools: true,
@@ -1614,14 +1686,14 @@ var BEDROCK_KNOWN_MODELS = [
1614
1686
  }
1615
1687
  },
1616
1688
  {
1617
- id: "mistral.mistral-large-2407-v1:0",
1618
- displayName: "Mistral Large (on Bedrock)",
1689
+ id: "amazon.nova-lite-v1:0",
1690
+ displayName: "Amazon Nova Lite",
1619
1691
  capabilities: {
1620
1692
  streaming: true,
1621
1693
  tools: true,
1622
- vision: false,
1694
+ vision: true,
1623
1695
  systemPrompt: true,
1624
- maxContextTokens: 128e3
1696
+ maxContextTokens: 3e5
1625
1697
  }
1626
1698
  },
1627
1699
  {
@@ -1636,19 +1708,19 @@ var BEDROCK_KNOWN_MODELS = [
1636
1708
  }
1637
1709
  },
1638
1710
  {
1639
- id: "amazon.nova-lite-v1:0",
1640
- displayName: "Amazon Nova Lite",
1711
+ id: "meta.llama3-3-70b-instruct-v1:0",
1712
+ displayName: "Llama 3.3 70B Instruct (on Bedrock)",
1641
1713
  capabilities: {
1642
1714
  streaming: true,
1643
1715
  tools: true,
1644
- vision: true,
1716
+ vision: false,
1645
1717
  systemPrompt: true,
1646
- maxContextTokens: 3e5
1718
+ maxContextTokens: 128e3
1647
1719
  }
1648
1720
  },
1649
1721
  {
1650
- id: "amazon.nova-micro-v1:0",
1651
- displayName: "Amazon Nova Micro",
1722
+ id: "mistral.mistral-large-2407-v1:0",
1723
+ displayName: "Mistral Large (on Bedrock)",
1652
1724
  capabilities: {
1653
1725
  streaming: true,
1654
1726
  tools: true,
@@ -1906,6 +1978,26 @@ var BedrockAdapter = class {
1906
1978
  };
1907
1979
  yield endEvent;
1908
1980
  }
1981
+ appendAssistantToolCall(history, toolCalls) {
1982
+ const wireMessage = {
1983
+ role: "assistant",
1984
+ content: toolCalls.map((tc) => ({
1985
+ toolUse: {
1986
+ toolUseId: tc.id,
1987
+ name: tc.name,
1988
+ input: tc.arguments ?? {}
1989
+ }
1990
+ }))
1991
+ };
1992
+ return [
1993
+ ...history,
1994
+ {
1995
+ role: "assistant",
1996
+ content: "",
1997
+ vendorRaw: wireMessage
1998
+ }
1999
+ ];
2000
+ }
1909
2001
  appendToolResult(history, toolCallId, result) {
1910
2002
  const text = typeof result === "string" ? result : JSON.stringify(result);
1911
2003
  const wireMessage = {
@@ -2233,12 +2325,11 @@ function runContractTests(harness) {
2233
2325
  (e) => e.type === "toolCall"
2234
2326
  );
2235
2327
  expect(tc).toBeDefined();
2236
- const history = [
2237
- { role: "user", content: "call it" },
2238
- harness.buildAssistantWithToolCall(tc)
2239
- ];
2240
- const withResult = adapter.appendToolResult(history, tc.id, { ok: true });
2241
- expect(withResult.length).toBe(history.length + 1);
2328
+ const baseHistory = [{ role: "user", content: "call it" }];
2329
+ const afterAssistant = adapter.appendAssistantToolCall(baseHistory, [tc]);
2330
+ expect(afterAssistant.length).toBe(baseHistory.length + 1);
2331
+ const withResult = adapter.appendToolResult(afterAssistant, tc.id, { ok: true });
2332
+ expect(withResult.length).toBe(afterAssistant.length + 1);
2242
2333
  await harness.mockScenario("simple-stream");
2243
2334
  await expect(
2244
2335
  drainStream(adapter, {
@@ -2326,11 +2417,11 @@ function runContractTests(harness) {
2326
2417
  (e) => e.type === "toolCall"
2327
2418
  );
2328
2419
  expect(tc).toBeDefined();
2329
- const history = [
2330
- { role: "user", content: "go" },
2331
- harness.buildAssistantWithToolCall(tc)
2332
- ];
2333
- const withResult = adapter.appendToolResult(history, tc.id, { ok: true });
2420
+ const afterAssistant = adapter.appendAssistantToolCall(
2421
+ [{ role: "user", content: "go" }],
2422
+ [tc]
2423
+ );
2424
+ const withResult = adapter.appendToolResult(afterAssistant, tc.id, { ok: true });
2334
2425
  await harness.mockScenario("simple-stream");
2335
2426
  await drainStream(adapter, {
2336
2427
  model: harness.toolCapableModel,
@@ -2340,6 +2431,28 @@ function runContractTests(harness) {
2340
2431
  expect(captured).not.toBeNull();
2341
2432
  expect(captured.vendorRawHonored).toBe(true);
2342
2433
  });
2434
+ it("[21] appendAssistantToolCall output + appendToolResult re-stream preserves tool-call id on wire", async () => {
2435
+ await harness.mockScenario("tool-call");
2436
+ const adapter = await init(harness);
2437
+ const first = await drainStream(adapter, {
2438
+ model: harness.toolCapableModel,
2439
+ messages: [{ role: "user", content: "go" }],
2440
+ tools: [
2441
+ { name: "test_tool", description: "x", parameters: { type: "object" } }
2442
+ ]
2443
+ });
2444
+ const tc = first.find(
2445
+ (e) => e.type === "toolCall"
2446
+ );
2447
+ expect(tc).toBeDefined();
2448
+ const history = adapter.appendAssistantToolCall(
2449
+ [{ role: "user", content: "go" }],
2450
+ [tc]
2451
+ );
2452
+ const appended = history[history.length - 1];
2453
+ expect(appended.role).toBe("assistant");
2454
+ expect(appended.vendorRaw).toBeDefined();
2455
+ });
2343
2456
  });
2344
2457
  }
2345
2458
  async function init(harness) {
@@ -2404,6 +2517,23 @@ var FakeAdapter = class {
2404
2517
  throw new Error(`FakeAdapter: unknown scenario '${scenario}'`);
2405
2518
  }
2406
2519
  }
2520
+ appendAssistantToolCall(history, toolCalls) {
2521
+ return [
2522
+ ...history,
2523
+ {
2524
+ role: "assistant",
2525
+ content: "",
2526
+ vendorRaw: {
2527
+ role: "assistant",
2528
+ toolCalls: toolCalls.map((tc) => ({
2529
+ id: tc.id,
2530
+ name: tc.name,
2531
+ arguments: tc.arguments
2532
+ }))
2533
+ }
2534
+ }
2535
+ ];
2536
+ }
2407
2537
  appendToolResult(history, toolCallId, result) {
2408
2538
  const content = typeof result === "string" ? result : JSON.stringify(result);
2409
2539
  return [
@@ -2586,17 +2716,7 @@ function createFakeHarness() {
2586
2716
  },
2587
2717
  toolCapableModel: "fake-tool-model",
2588
2718
  nonToolCapableModel: "fake-plain-model",
2589
- emitsToolCallStart: true,
2590
- buildAssistantWithToolCall(tc) {
2591
- return {
2592
- role: "assistant",
2593
- content: "",
2594
- vendorRaw: {
2595
- role: "assistant",
2596
- toolCall: { id: tc.id, name: tc.name, arguments: tc.arguments }
2597
- }
2598
- };
2599
- }
2719
+ emitsToolCallStart: true
2600
2720
  };
2601
2721
  }
2602
2722
  export {