@jambonz/llm 0.6.2 → 0.6.4

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.
@@ -271,10 +271,11 @@ async function* streamFromOpenAI(client, req, options) {
271
271
  }
272
272
  yield endEvent;
273
273
  }
274
- function appendOpenAIAssistantToolCall(history, toolCalls) {
274
+ function appendOpenAIAssistantToolCall(history, toolCalls, assistantText) {
275
+ const text = assistantText?.trim() ? assistantText : null;
275
276
  const wireMessage = {
276
277
  role: "assistant",
277
- content: null,
278
+ content: text,
278
279
  tool_calls: toolCalls.map((tc) => ({
279
280
  id: tc.id,
280
281
  type: "function",
@@ -288,7 +289,7 @@ function appendOpenAIAssistantToolCall(history, toolCalls) {
288
289
  ...history,
289
290
  {
290
291
  role: "assistant",
291
- content: "",
292
+ content: text ?? "",
292
293
  vendorRaw: wireMessage
293
294
  }
294
295
  ];
@@ -559,8 +560,8 @@ var OpenAIAdapter = class {
559
560
  includeCacheKey: this.forwardCacheKey()
560
561
  });
561
562
  }
562
- appendAssistantToolCall(history, toolCalls) {
563
- return appendOpenAIAssistantToolCall(history, toolCalls);
563
+ appendAssistantToolCall(history, toolCalls, assistantText) {
564
+ return appendOpenAIAssistantToolCall(history, toolCalls, assistantText);
564
565
  }
565
566
  appendToolResult(history, toolCallId, result) {
566
567
  return appendOpenAIToolResult(history, toolCallId, result);
@@ -1526,21 +1527,25 @@ var AnthropicAdapter = class {
1526
1527
  }
1527
1528
  yield endEvent;
1528
1529
  }
1529
- appendAssistantToolCall(history, toolCalls) {
1530
+ appendAssistantToolCall(history, toolCalls, assistantText) {
1531
+ const text = assistantText?.trim() ? assistantText : null;
1530
1532
  const wireMessage = {
1531
1533
  role: "assistant",
1532
- content: toolCalls.map((tc) => ({
1533
- type: "tool_use",
1534
- id: tc.id,
1535
- name: tc.name,
1536
- input: tc.arguments ?? {}
1537
- }))
1534
+ content: [
1535
+ ...text ? [{ type: "text", text }] : [],
1536
+ ...toolCalls.map((tc) => ({
1537
+ type: "tool_use",
1538
+ id: tc.id,
1539
+ name: tc.name,
1540
+ input: tc.arguments ?? {}
1541
+ }))
1542
+ ]
1538
1543
  };
1539
1544
  return [
1540
1545
  ...history,
1541
1546
  {
1542
1547
  role: "assistant",
1543
- content: "",
1548
+ content: text ?? "",
1544
1549
  vendorRaw: wireMessage
1545
1550
  }
1546
1551
  ];
@@ -1792,21 +1797,25 @@ async function* streamFromGemini(client, req) {
1792
1797
  };
1793
1798
  yield endEvent;
1794
1799
  }
1795
- function appendGeminiAssistantToolCall(history, toolCalls) {
1800
+ function appendGeminiAssistantToolCall(history, toolCalls, assistantText) {
1801
+ const text = assistantText?.trim() ? assistantText : null;
1796
1802
  const wireMessage = {
1797
1803
  role: "model",
1798
- parts: toolCalls.map((tc) => ({
1799
- functionCall: {
1800
- name: parseToolName(tc.id),
1801
- args: tc.arguments ?? {}
1802
- }
1803
- }))
1804
+ parts: [
1805
+ ...text ? [{ text }] : [],
1806
+ ...toolCalls.map((tc) => ({
1807
+ functionCall: {
1808
+ name: parseToolName(tc.id),
1809
+ args: tc.arguments ?? {}
1810
+ }
1811
+ }))
1812
+ ]
1804
1813
  };
1805
1814
  return [
1806
1815
  ...history,
1807
1816
  {
1808
1817
  role: "assistant",
1809
- content: "",
1818
+ content: text ?? "",
1810
1819
  vendorRaw: wireMessage
1811
1820
  }
1812
1821
  ];
@@ -2066,8 +2075,8 @@ var GoogleAdapter = class {
2066
2075
  stream(req) {
2067
2076
  return streamFromGemini(this.ensureClient(), req);
2068
2077
  }
2069
- appendAssistantToolCall(history, toolCalls) {
2070
- return appendGeminiAssistantToolCall(history, toolCalls);
2078
+ appendAssistantToolCall(history, toolCalls, assistantText) {
2079
+ return appendGeminiAssistantToolCall(history, toolCalls, assistantText);
2071
2080
  }
2072
2081
  appendToolResult(history, toolCallId, result) {
2073
2082
  return appendGeminiToolResult(history, toolCallId, result);
@@ -2272,8 +2281,8 @@ var VertexGeminiAdapter = class {
2272
2281
  stream(req) {
2273
2282
  return streamFromGemini(this.ensureClient(), req);
2274
2283
  }
2275
- appendAssistantToolCall(history, toolCalls) {
2276
- return appendGeminiAssistantToolCall(history, toolCalls);
2284
+ appendAssistantToolCall(history, toolCalls, assistantText) {
2285
+ return appendGeminiAssistantToolCall(history, toolCalls, assistantText);
2277
2286
  }
2278
2287
  appendToolResult(history, toolCallId, result) {
2279
2288
  return appendGeminiToolResult(history, toolCallId, result);
@@ -2470,8 +2479,8 @@ var VertexOpenAIAdapter = class {
2470
2479
  vendorMetadataExtractor: VERTEX_OPENAI_METADATA_EXTRACTOR
2471
2480
  });
2472
2481
  }
2473
- appendAssistantToolCall(history, toolCalls) {
2474
- return appendOpenAIAssistantToolCall(history, toolCalls);
2482
+ appendAssistantToolCall(history, toolCalls, assistantText) {
2483
+ return appendOpenAIAssistantToolCall(history, toolCalls, assistantText);
2475
2484
  }
2476
2485
  appendToolResult(history, toolCallId, result) {
2477
2486
  return appendOpenAIToolResult(history, toolCallId, result);
@@ -2816,11 +2825,12 @@ var BedrockAdapter = class {
2816
2825
  if (Object.keys(inferenceConfig).length > 0) {
2817
2826
  commandInput.inferenceConfig = inferenceConfig;
2818
2827
  }
2819
- if (req.cacheKey) {
2828
+ const caching = req.cacheKey ? cachePointSupport(req.model) : void 0;
2829
+ if (caching) {
2820
2830
  if (commandInput.system) {
2821
2831
  commandInput.system.push({ cachePoint: { type: "default" } });
2822
2832
  }
2823
- if (tools) {
2833
+ if (tools && caching.tools) {
2824
2834
  tools.tools.push({ cachePoint: { type: "default" } });
2825
2835
  }
2826
2836
  markLastMessageForCaching2(messages);
@@ -2957,22 +2967,26 @@ var BedrockAdapter = class {
2957
2967
  }
2958
2968
  yield endEvent;
2959
2969
  }
2960
- appendAssistantToolCall(history, toolCalls) {
2970
+ appendAssistantToolCall(history, toolCalls, assistantText) {
2971
+ const text = assistantText?.trim() ? assistantText : null;
2961
2972
  const wireMessage = {
2962
2973
  role: "assistant",
2963
- content: toolCalls.map((tc) => ({
2964
- toolUse: {
2965
- toolUseId: tc.id,
2966
- name: tc.name,
2967
- input: tc.arguments ?? {}
2968
- }
2969
- }))
2974
+ content: [
2975
+ ...text ? [{ text }] : [],
2976
+ ...toolCalls.map((tc) => ({
2977
+ toolUse: {
2978
+ toolUseId: tc.id,
2979
+ name: tc.name,
2980
+ input: tc.arguments ?? {}
2981
+ }
2982
+ }))
2983
+ ]
2970
2984
  };
2971
2985
  return [
2972
2986
  ...history,
2973
2987
  {
2974
2988
  role: "assistant",
2975
- content: "",
2989
+ content: text ?? "",
2976
2990
  vendorRaw: wireMessage
2977
2991
  }
2978
2992
  ];
@@ -3040,6 +3054,11 @@ function buildWireMessages3(req) {
3040
3054
  }
3041
3055
  return out;
3042
3056
  }
3057
+ function cachePointSupport(model) {
3058
+ if (model.includes("anthropic.claude")) return { tools: true };
3059
+ if (model.includes("amazon.nova")) return { tools: false };
3060
+ return void 0;
3061
+ }
3043
3062
  function markLastMessageForCaching2(messages) {
3044
3063
  if (messages.length === 0) return;
3045
3064
  const last = messages[messages.length - 1];
@@ -3262,8 +3281,8 @@ var AzureOpenAIAdapter = class {
3262
3281
  vendorMetadataExtractor: AZURE_OPENAI_METADATA_EXTRACTOR
3263
3282
  });
3264
3283
  }
3265
- appendAssistantToolCall(history, toolCalls) {
3266
- return appendOpenAIAssistantToolCall(history, toolCalls);
3284
+ appendAssistantToolCall(history, toolCalls, assistantText) {
3285
+ return appendOpenAIAssistantToolCall(history, toolCalls, assistantText);
3267
3286
  }
3268
3287
  appendToolResult(history, toolCallId, result) {
3269
3288
  return appendOpenAIToolResult(history, toolCallId, result);
@@ -3918,6 +3937,55 @@ function runContractTests(harness) {
3918
3937
  (0, import_vitest.expect)(appended.role).toBe("assistant");
3919
3938
  (0, import_vitest.expect)(appended.vendorRaw).toBeDefined();
3920
3939
  });
3940
+ (0, import_vitest.it)("[22] appendAssistantToolCall carries pre-tool assistant text onto the wire", async () => {
3941
+ await harness.mockScenario("tool-call");
3942
+ const adapter = await init(harness);
3943
+ const first = await drainStream(adapter, {
3944
+ model: harness.toolCapableModel,
3945
+ messages: [{ role: "user", content: "go" }],
3946
+ tools: [
3947
+ { name: "test_tool", description: "x", parameters: { type: "object" } }
3948
+ ]
3949
+ });
3950
+ const tc = first.find(
3951
+ (e) => e.type === "toolCall"
3952
+ );
3953
+ (0, import_vitest.expect)(tc).toBeDefined();
3954
+ const preToolText = "Checking that now.";
3955
+ const history = adapter.appendAssistantToolCall(
3956
+ [{ role: "user", content: "go" }],
3957
+ [tc],
3958
+ preToolText
3959
+ );
3960
+ const appended = history[history.length - 1];
3961
+ (0, import_vitest.expect)(appended.content).toBe(preToolText);
3962
+ (0, import_vitest.expect)(JSON.stringify(appended.vendorRaw)).toContain(preToolText);
3963
+ });
3964
+ (0, import_vitest.it)("[23] appendAssistantToolCall omits empty pre-tool text from the wire", async () => {
3965
+ await harness.mockScenario("tool-call");
3966
+ const adapter = await init(harness);
3967
+ const first = await drainStream(adapter, {
3968
+ model: harness.toolCapableModel,
3969
+ messages: [{ role: "user", content: "go" }],
3970
+ tools: [
3971
+ { name: "test_tool", description: "x", parameters: { type: "object" } }
3972
+ ]
3973
+ });
3974
+ const tc = first.find(
3975
+ (e) => e.type === "toolCall"
3976
+ );
3977
+ (0, import_vitest.expect)(tc).toBeDefined();
3978
+ for (const blank of [void 0, "", " "]) {
3979
+ const history = adapter.appendAssistantToolCall(
3980
+ [{ role: "user", content: "go" }],
3981
+ [tc],
3982
+ blank
3983
+ );
3984
+ const appended = history[history.length - 1];
3985
+ (0, import_vitest.expect)(appended.content).toBe("");
3986
+ (0, import_vitest.expect)(JSON.stringify(appended.vendorRaw)).not.toContain('"text":""');
3987
+ }
3988
+ });
3921
3989
  });
3922
3990
  }
3923
3991
  async function init(harness) {
@@ -3982,13 +4050,15 @@ var FakeAdapter = class {
3982
4050
  throw new Error(`FakeAdapter: unknown scenario '${scenario}'`);
3983
4051
  }
3984
4052
  }
3985
- appendAssistantToolCall(history, toolCalls) {
4053
+ appendAssistantToolCall(history, toolCalls, assistantText) {
4054
+ const text = assistantText?.trim() ? assistantText : null;
3986
4055
  return [
3987
4056
  ...history,
3988
4057
  {
3989
4058
  role: "assistant",
3990
- content: "",
4059
+ content: text ?? "",
3991
4060
  vendorRaw: {
4061
+ ...text ? { text } : {},
3992
4062
  role: "assistant",
3993
4063
  toolCalls: toolCalls.map((tc) => ({
3994
4064
  id: tc.id,