@jambonz/llm 0.6.2 → 0.6.3

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);
@@ -2957,22 +2966,26 @@ var BedrockAdapter = class {
2957
2966
  }
2958
2967
  yield endEvent;
2959
2968
  }
2960
- appendAssistantToolCall(history, toolCalls) {
2969
+ appendAssistantToolCall(history, toolCalls, assistantText) {
2970
+ const text = assistantText?.trim() ? assistantText : null;
2961
2971
  const wireMessage = {
2962
2972
  role: "assistant",
2963
- content: toolCalls.map((tc) => ({
2964
- toolUse: {
2965
- toolUseId: tc.id,
2966
- name: tc.name,
2967
- input: tc.arguments ?? {}
2968
- }
2969
- }))
2973
+ content: [
2974
+ ...text ? [{ text }] : [],
2975
+ ...toolCalls.map((tc) => ({
2976
+ toolUse: {
2977
+ toolUseId: tc.id,
2978
+ name: tc.name,
2979
+ input: tc.arguments ?? {}
2980
+ }
2981
+ }))
2982
+ ]
2970
2983
  };
2971
2984
  return [
2972
2985
  ...history,
2973
2986
  {
2974
2987
  role: "assistant",
2975
- content: "",
2988
+ content: text ?? "",
2976
2989
  vendorRaw: wireMessage
2977
2990
  }
2978
2991
  ];
@@ -3262,8 +3275,8 @@ var AzureOpenAIAdapter = class {
3262
3275
  vendorMetadataExtractor: AZURE_OPENAI_METADATA_EXTRACTOR
3263
3276
  });
3264
3277
  }
3265
- appendAssistantToolCall(history, toolCalls) {
3266
- return appendOpenAIAssistantToolCall(history, toolCalls);
3278
+ appendAssistantToolCall(history, toolCalls, assistantText) {
3279
+ return appendOpenAIAssistantToolCall(history, toolCalls, assistantText);
3267
3280
  }
3268
3281
  appendToolResult(history, toolCallId, result) {
3269
3282
  return appendOpenAIToolResult(history, toolCallId, result);
@@ -3918,6 +3931,55 @@ function runContractTests(harness) {
3918
3931
  (0, import_vitest.expect)(appended.role).toBe("assistant");
3919
3932
  (0, import_vitest.expect)(appended.vendorRaw).toBeDefined();
3920
3933
  });
3934
+ (0, import_vitest.it)("[22] appendAssistantToolCall carries pre-tool assistant text onto the wire", async () => {
3935
+ await harness.mockScenario("tool-call");
3936
+ const adapter = await init(harness);
3937
+ const first = await drainStream(adapter, {
3938
+ model: harness.toolCapableModel,
3939
+ messages: [{ role: "user", content: "go" }],
3940
+ tools: [
3941
+ { name: "test_tool", description: "x", parameters: { type: "object" } }
3942
+ ]
3943
+ });
3944
+ const tc = first.find(
3945
+ (e) => e.type === "toolCall"
3946
+ );
3947
+ (0, import_vitest.expect)(tc).toBeDefined();
3948
+ const preToolText = "Checking that now.";
3949
+ const history = adapter.appendAssistantToolCall(
3950
+ [{ role: "user", content: "go" }],
3951
+ [tc],
3952
+ preToolText
3953
+ );
3954
+ const appended = history[history.length - 1];
3955
+ (0, import_vitest.expect)(appended.content).toBe(preToolText);
3956
+ (0, import_vitest.expect)(JSON.stringify(appended.vendorRaw)).toContain(preToolText);
3957
+ });
3958
+ (0, import_vitest.it)("[23] appendAssistantToolCall omits empty pre-tool text from the wire", async () => {
3959
+ await harness.mockScenario("tool-call");
3960
+ const adapter = await init(harness);
3961
+ const first = await drainStream(adapter, {
3962
+ model: harness.toolCapableModel,
3963
+ messages: [{ role: "user", content: "go" }],
3964
+ tools: [
3965
+ { name: "test_tool", description: "x", parameters: { type: "object" } }
3966
+ ]
3967
+ });
3968
+ const tc = first.find(
3969
+ (e) => e.type === "toolCall"
3970
+ );
3971
+ (0, import_vitest.expect)(tc).toBeDefined();
3972
+ for (const blank of [void 0, "", " "]) {
3973
+ const history = adapter.appendAssistantToolCall(
3974
+ [{ role: "user", content: "go" }],
3975
+ [tc],
3976
+ blank
3977
+ );
3978
+ const appended = history[history.length - 1];
3979
+ (0, import_vitest.expect)(appended.content).toBe("");
3980
+ (0, import_vitest.expect)(JSON.stringify(appended.vendorRaw)).not.toContain('"text":""');
3981
+ }
3982
+ });
3921
3983
  });
3922
3984
  }
3923
3985
  async function init(harness) {
@@ -3982,13 +4044,15 @@ var FakeAdapter = class {
3982
4044
  throw new Error(`FakeAdapter: unknown scenario '${scenario}'`);
3983
4045
  }
3984
4046
  }
3985
- appendAssistantToolCall(history, toolCalls) {
4047
+ appendAssistantToolCall(history, toolCalls, assistantText) {
4048
+ const text = assistantText?.trim() ? assistantText : null;
3986
4049
  return [
3987
4050
  ...history,
3988
4051
  {
3989
4052
  role: "assistant",
3990
- content: "",
4053
+ content: text ?? "",
3991
4054
  vendorRaw: {
4055
+ ...text ? { text } : {},
3992
4056
  role: "assistant",
3993
4057
  toolCalls: toolCalls.map((tc) => ({
3994
4058
  id: tc.id,