@ljoukov/llm 4.0.10 → 4.0.12

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.
package/dist/index.js CHANGED
@@ -6,9 +6,9 @@ import {
6
6
  FinishReason,
7
7
  FunctionCallingConfigMode,
8
8
  ThinkingLevel,
9
- createFunctionResponsePartFromBase64,
10
- createFunctionResponsePartFromUri,
11
- createPartFromFunctionResponse
9
+ createPartFromBase64,
10
+ createPartFromFunctionResponse,
11
+ createPartFromUri
12
12
  } from "@google/genai";
13
13
  import { zodToJsonSchema } from "@alcyone-labs/zod-to-json-schema";
14
14
  import { z as z3 } from "zod";
@@ -4643,12 +4643,12 @@ function buildGeminiToolOutputMediaPart(item) {
4643
4643
  if (!parsed) {
4644
4644
  return null;
4645
4645
  }
4646
- return createFunctionResponsePartFromBase64(parsed.dataBase64, parsed.mimeType);
4646
+ return createPartFromBase64(parsed.dataBase64, parsed.mimeType);
4647
4647
  }
4648
4648
  if (item.type === "input_file") {
4649
4649
  const dataUrl = typeof item.file_url === "string" ? parseDataUrlPayload(item.file_url) : null;
4650
4650
  if (dataUrl) {
4651
- const part = createFunctionResponsePartFromBase64(dataUrl.dataBase64, dataUrl.mimeType);
4651
+ const part = createPartFromBase64(dataUrl.dataBase64, dataUrl.mimeType);
4652
4652
  const displayName = item.filename?.trim();
4653
4653
  if (displayName && part.inlineData) {
4654
4654
  part.inlineData.displayName = displayName;
@@ -4657,7 +4657,7 @@ function buildGeminiToolOutputMediaPart(item) {
4657
4657
  }
4658
4658
  const inferredMimeType = inferToolOutputMimeTypeFromFilename(item.filename);
4659
4659
  if (typeof item.file_data === "string" && item.file_data.trim().length > 0 && inferredMimeType) {
4660
- const part = createFunctionResponsePartFromBase64(item.file_data, inferredMimeType);
4660
+ const part = createPartFromBase64(item.file_data, inferredMimeType);
4661
4661
  const displayName = item.filename?.trim();
4662
4662
  if (displayName && part.inlineData) {
4663
4663
  part.inlineData.displayName = displayName;
@@ -4665,7 +4665,7 @@ function buildGeminiToolOutputMediaPart(item) {
4665
4665
  return part;
4666
4666
  }
4667
4667
  if (typeof item.file_url === "string" && item.file_url.trim().length > 0 && inferredMimeType) {
4668
- const part = createFunctionResponsePartFromUri(item.file_url, inferredMimeType);
4668
+ const part = createPartFromUri(item.file_url, inferredMimeType);
4669
4669
  const displayName = item.filename?.trim();
4670
4670
  if (displayName && part.fileData) {
4671
4671
  part.fileData.displayName = displayName;
@@ -4699,41 +4699,35 @@ function toGeminiToolOutputPlaceholder(item) {
4699
4699
  media: dataUrl || typeof item.file_data === "string" && item.file_data.trim().length > 0 ? "attached-inline-data" : typeof item.file_url === "string" && item.file_url.trim().length > 0 ? "attached-file-data" : void 0
4700
4700
  };
4701
4701
  }
4702
- function buildGeminiFunctionResponsePart(options) {
4702
+ function buildGeminiFunctionResponseParts(options) {
4703
4703
  const outputItems = toGeminiToolOutputItems(options.outputPayload);
4704
4704
  if (!outputItems) {
4705
4705
  const responsePayload2 = isPlainRecord(options.outputPayload) ? sanitiseLogValue(options.outputPayload) : { output: sanitiseLogValue(options.outputPayload) };
4706
4706
  if (options.callId) {
4707
- return createPartFromFunctionResponse(options.callId, options.toolName, responsePayload2);
4707
+ return [createPartFromFunctionResponse(options.callId, options.toolName, responsePayload2)];
4708
4708
  }
4709
- return {
4710
- functionResponse: {
4711
- name: options.toolName,
4712
- response: responsePayload2
4709
+ return [
4710
+ {
4711
+ functionResponse: {
4712
+ name: options.toolName,
4713
+ response: responsePayload2
4714
+ }
4713
4715
  }
4714
- };
4716
+ ];
4715
4717
  }
4716
4718
  const responseOutput = outputItems.map((item) => toGeminiToolOutputPlaceholder(item));
4717
- const responseMediaParts = outputItems.flatMap((item) => {
4719
+ const responseParts = outputItems.flatMap((item) => {
4718
4720
  const mediaPart = buildGeminiToolOutputMediaPart(item);
4719
4721
  return mediaPart ? [mediaPart] : [];
4720
4722
  });
4721
4723
  const responsePayload = { output: responseOutput };
4722
- if (options.callId) {
4723
- return createPartFromFunctionResponse(
4724
- options.callId,
4725
- options.toolName,
4726
- responsePayload,
4727
- responseMediaParts
4728
- );
4729
- }
4730
- return {
4724
+ const functionResponsePart = options.callId ? createPartFromFunctionResponse(options.callId, options.toolName, responsePayload) : {
4731
4725
  functionResponse: {
4732
4726
  name: options.toolName,
4733
- response: { output: responseOutput },
4734
- ...responseMediaParts.length > 0 ? { parts: responseMediaParts } : {}
4727
+ response: responsePayload
4735
4728
  }
4736
4729
  };
4730
+ return [functionResponsePart, ...responseParts];
4737
4731
  }
4738
4732
  function parseOpenAiToolArguments(raw) {
4739
4733
  const trimmed = raw.trim();
@@ -7333,8 +7327,6 @@ async function runToolLoop(request) {
7333
7327
  let thoughtsText2 = "";
7334
7328
  const modelParts = [];
7335
7329
  const functionCalls = [];
7336
- const seenFunctionCallIds = /* @__PURE__ */ new Set();
7337
- const seenFunctionCallKeys = /* @__PURE__ */ new Set();
7338
7330
  let latestUsageMetadata;
7339
7331
  let resolvedModelVersion;
7340
7332
  for await (const chunk of stream) {
@@ -7351,34 +7343,13 @@ async function runToolLoop(request) {
7351
7343
  continue;
7352
7344
  }
7353
7345
  const primary = candidates[0];
7354
- const parts = primary?.content?.parts;
7355
- if (!parts || parts.length === 0) {
7346
+ const parts = primary?.content?.parts ?? [];
7347
+ const chunkFunctionCalls = chunk.functionCalls ?? [];
7348
+ if (parts.length === 0 && chunkFunctionCalls.length === 0) {
7356
7349
  continue;
7357
7350
  }
7358
7351
  for (const part of parts) {
7359
7352
  modelParts.push(part);
7360
- const call = part.functionCall;
7361
- if (call) {
7362
- const id = typeof call.id === "string" ? call.id : "";
7363
- const shouldAdd = (() => {
7364
- if (id.length > 0) {
7365
- if (seenFunctionCallIds.has(id)) {
7366
- return false;
7367
- }
7368
- seenFunctionCallIds.add(id);
7369
- return true;
7370
- }
7371
- const key = JSON.stringify({ name: call.name ?? "", args: call.args ?? null });
7372
- if (seenFunctionCallKeys.has(key)) {
7373
- return false;
7374
- }
7375
- seenFunctionCallKeys.add(key);
7376
- return true;
7377
- })();
7378
- if (shouldAdd) {
7379
- functionCalls.push(call);
7380
- }
7381
- }
7382
7353
  if (typeof part.text === "string" && part.text.length > 0) {
7383
7354
  if (part.thought) {
7384
7355
  thoughtsText2 += part.text;
@@ -7391,6 +7362,15 @@ async function runToolLoop(request) {
7391
7362
  }
7392
7363
  }
7393
7364
  }
7365
+ if (chunkFunctionCalls.length > 0) {
7366
+ functionCalls.push(...chunkFunctionCalls);
7367
+ continue;
7368
+ }
7369
+ for (const part of parts) {
7370
+ if (part.functionCall) {
7371
+ functionCalls.push(part.functionCall);
7372
+ }
7373
+ }
7394
7374
  }
7395
7375
  return {
7396
7376
  responseText: responseText2,
@@ -7561,7 +7541,7 @@ async function runToolLoop(request) {
7561
7541
  durationMs: result.durationMs
7562
7542
  });
7563
7543
  responseParts.push(
7564
- buildGeminiFunctionResponsePart({
7544
+ ...buildGeminiFunctionResponseParts({
7565
7545
  toolName: entry.toolName,
7566
7546
  callId: entry.call.id,
7567
7547
  outputPayload