@ljoukov/llm 4.0.9 → 4.0.10
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.cjs +164 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +168 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -4700,6 +4700,150 @@ function toOpenAiToolOutput(value) {
|
|
|
4700
4700
|
}
|
|
4701
4701
|
return mergeToolOutput(value);
|
|
4702
4702
|
}
|
|
4703
|
+
function toGeminiToolOutputItems(value) {
|
|
4704
|
+
if (isLlmToolOutputContentItem(value)) {
|
|
4705
|
+
return [value];
|
|
4706
|
+
}
|
|
4707
|
+
if (Array.isArray(value) && value.every((item) => isLlmToolOutputContentItem(item))) {
|
|
4708
|
+
return value;
|
|
4709
|
+
}
|
|
4710
|
+
return null;
|
|
4711
|
+
}
|
|
4712
|
+
function inferToolOutputMimeTypeFromFilename(filename) {
|
|
4713
|
+
const normalized = filename?.trim().toLowerCase() ?? "";
|
|
4714
|
+
if (normalized.length === 0) {
|
|
4715
|
+
return void 0;
|
|
4716
|
+
}
|
|
4717
|
+
if (normalized.endsWith(".png")) {
|
|
4718
|
+
return "image/png";
|
|
4719
|
+
}
|
|
4720
|
+
if (normalized.endsWith(".jpg") || normalized.endsWith(".jpeg")) {
|
|
4721
|
+
return "image/jpeg";
|
|
4722
|
+
}
|
|
4723
|
+
if (normalized.endsWith(".webp")) {
|
|
4724
|
+
return "image/webp";
|
|
4725
|
+
}
|
|
4726
|
+
if (normalized.endsWith(".gif")) {
|
|
4727
|
+
return "image/gif";
|
|
4728
|
+
}
|
|
4729
|
+
if (normalized.endsWith(".heic")) {
|
|
4730
|
+
return "image/heic";
|
|
4731
|
+
}
|
|
4732
|
+
if (normalized.endsWith(".heif")) {
|
|
4733
|
+
return "image/heif";
|
|
4734
|
+
}
|
|
4735
|
+
if (normalized.endsWith(".pdf")) {
|
|
4736
|
+
return "application/pdf";
|
|
4737
|
+
}
|
|
4738
|
+
if (normalized.endsWith(".json")) {
|
|
4739
|
+
return "application/json";
|
|
4740
|
+
}
|
|
4741
|
+
if (normalized.endsWith(".md")) {
|
|
4742
|
+
return "text/markdown";
|
|
4743
|
+
}
|
|
4744
|
+
if (normalized.endsWith(".txt")) {
|
|
4745
|
+
return "text/plain";
|
|
4746
|
+
}
|
|
4747
|
+
return void 0;
|
|
4748
|
+
}
|
|
4749
|
+
function buildGeminiToolOutputMediaPart(item) {
|
|
4750
|
+
if (item.type === "input_image") {
|
|
4751
|
+
const parsed = parseDataUrlPayload(item.image_url);
|
|
4752
|
+
if (!parsed) {
|
|
4753
|
+
return null;
|
|
4754
|
+
}
|
|
4755
|
+
return (0, import_genai2.createFunctionResponsePartFromBase64)(parsed.dataBase64, parsed.mimeType);
|
|
4756
|
+
}
|
|
4757
|
+
if (item.type === "input_file") {
|
|
4758
|
+
const dataUrl = typeof item.file_url === "string" ? parseDataUrlPayload(item.file_url) : null;
|
|
4759
|
+
if (dataUrl) {
|
|
4760
|
+
const part = (0, import_genai2.createFunctionResponsePartFromBase64)(dataUrl.dataBase64, dataUrl.mimeType);
|
|
4761
|
+
const displayName = item.filename?.trim();
|
|
4762
|
+
if (displayName && part.inlineData) {
|
|
4763
|
+
part.inlineData.displayName = displayName;
|
|
4764
|
+
}
|
|
4765
|
+
return part;
|
|
4766
|
+
}
|
|
4767
|
+
const inferredMimeType = inferToolOutputMimeTypeFromFilename(item.filename);
|
|
4768
|
+
if (typeof item.file_data === "string" && item.file_data.trim().length > 0 && inferredMimeType) {
|
|
4769
|
+
const part = (0, import_genai2.createFunctionResponsePartFromBase64)(item.file_data, inferredMimeType);
|
|
4770
|
+
const displayName = item.filename?.trim();
|
|
4771
|
+
if (displayName && part.inlineData) {
|
|
4772
|
+
part.inlineData.displayName = displayName;
|
|
4773
|
+
}
|
|
4774
|
+
return part;
|
|
4775
|
+
}
|
|
4776
|
+
if (typeof item.file_url === "string" && item.file_url.trim().length > 0 && inferredMimeType) {
|
|
4777
|
+
const part = (0, import_genai2.createFunctionResponsePartFromUri)(item.file_url, inferredMimeType);
|
|
4778
|
+
const displayName = item.filename?.trim();
|
|
4779
|
+
if (displayName && part.fileData) {
|
|
4780
|
+
part.fileData.displayName = displayName;
|
|
4781
|
+
}
|
|
4782
|
+
return part;
|
|
4783
|
+
}
|
|
4784
|
+
}
|
|
4785
|
+
return null;
|
|
4786
|
+
}
|
|
4787
|
+
function toGeminiToolOutputPlaceholder(item) {
|
|
4788
|
+
if (item.type === "input_text") {
|
|
4789
|
+
return {
|
|
4790
|
+
type: item.type,
|
|
4791
|
+
text: item.text
|
|
4792
|
+
};
|
|
4793
|
+
}
|
|
4794
|
+
if (item.type === "input_image") {
|
|
4795
|
+
const parsed = parseDataUrlPayload(item.image_url);
|
|
4796
|
+
return {
|
|
4797
|
+
type: item.type,
|
|
4798
|
+
mimeType: parsed?.mimeType ?? void 0,
|
|
4799
|
+
media: "attached-inline-data"
|
|
4800
|
+
};
|
|
4801
|
+
}
|
|
4802
|
+
const dataUrl = typeof item.file_url === "string" ? parseDataUrlPayload(item.file_url) : null;
|
|
4803
|
+
return {
|
|
4804
|
+
type: item.type,
|
|
4805
|
+
filename: item.filename ?? void 0,
|
|
4806
|
+
fileId: item.file_id ?? void 0,
|
|
4807
|
+
mimeType: dataUrl?.mimeType ?? inferToolOutputMimeTypeFromFilename(item.filename) ?? void 0,
|
|
4808
|
+
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
|
|
4809
|
+
};
|
|
4810
|
+
}
|
|
4811
|
+
function buildGeminiFunctionResponsePart(options) {
|
|
4812
|
+
const outputItems = toGeminiToolOutputItems(options.outputPayload);
|
|
4813
|
+
if (!outputItems) {
|
|
4814
|
+
const responsePayload2 = isPlainRecord(options.outputPayload) ? sanitiseLogValue(options.outputPayload) : { output: sanitiseLogValue(options.outputPayload) };
|
|
4815
|
+
if (options.callId) {
|
|
4816
|
+
return (0, import_genai2.createPartFromFunctionResponse)(options.callId, options.toolName, responsePayload2);
|
|
4817
|
+
}
|
|
4818
|
+
return {
|
|
4819
|
+
functionResponse: {
|
|
4820
|
+
name: options.toolName,
|
|
4821
|
+
response: responsePayload2
|
|
4822
|
+
}
|
|
4823
|
+
};
|
|
4824
|
+
}
|
|
4825
|
+
const responseOutput = outputItems.map((item) => toGeminiToolOutputPlaceholder(item));
|
|
4826
|
+
const responseMediaParts = outputItems.flatMap((item) => {
|
|
4827
|
+
const mediaPart = buildGeminiToolOutputMediaPart(item);
|
|
4828
|
+
return mediaPart ? [mediaPart] : [];
|
|
4829
|
+
});
|
|
4830
|
+
const responsePayload = { output: responseOutput };
|
|
4831
|
+
if (options.callId) {
|
|
4832
|
+
return (0, import_genai2.createPartFromFunctionResponse)(
|
|
4833
|
+
options.callId,
|
|
4834
|
+
options.toolName,
|
|
4835
|
+
responsePayload,
|
|
4836
|
+
responseMediaParts
|
|
4837
|
+
);
|
|
4838
|
+
}
|
|
4839
|
+
return {
|
|
4840
|
+
functionResponse: {
|
|
4841
|
+
name: options.toolName,
|
|
4842
|
+
response: { output: responseOutput },
|
|
4843
|
+
...responseMediaParts.length > 0 ? { parts: responseMediaParts } : {}
|
|
4844
|
+
}
|
|
4845
|
+
};
|
|
4846
|
+
}
|
|
4703
4847
|
function parseOpenAiToolArguments(raw) {
|
|
4704
4848
|
const trimmed = raw.trim();
|
|
4705
4849
|
if (trimmed.length === 0) {
|
|
@@ -5160,7 +5304,7 @@ function resolveAttachmentExtension(mimeType) {
|
|
|
5160
5304
|
function buildLoggedAttachmentFilename(prefix, index, mimeType) {
|
|
5161
5305
|
return `${prefix}-${index.toString()}.${resolveAttachmentExtension(mimeType)}`;
|
|
5162
5306
|
}
|
|
5163
|
-
function
|
|
5307
|
+
function parseDataUrlPayload(value) {
|
|
5164
5308
|
const trimmed = value.trim();
|
|
5165
5309
|
if (!trimmed.toLowerCase().startsWith("data:")) {
|
|
5166
5310
|
return null;
|
|
@@ -5176,13 +5320,24 @@ function decodeDataUrlAttachment(value, options) {
|
|
|
5176
5320
|
try {
|
|
5177
5321
|
const bytes = isBase64 ? import_node_buffer3.Buffer.from(payload, "base64") : import_node_buffer3.Buffer.from(decodeURIComponent(payload), "utf8");
|
|
5178
5322
|
return {
|
|
5179
|
-
|
|
5323
|
+
mimeType,
|
|
5324
|
+
dataBase64: bytes.toString("base64"),
|
|
5180
5325
|
bytes
|
|
5181
5326
|
};
|
|
5182
5327
|
} catch {
|
|
5183
5328
|
return null;
|
|
5184
5329
|
}
|
|
5185
5330
|
}
|
|
5331
|
+
function decodeDataUrlAttachment(value, options) {
|
|
5332
|
+
const parsed = parseDataUrlPayload(value);
|
|
5333
|
+
if (!parsed) {
|
|
5334
|
+
return null;
|
|
5335
|
+
}
|
|
5336
|
+
return {
|
|
5337
|
+
filename: buildLoggedAttachmentFilename(options.prefix, options.index, parsed.mimeType),
|
|
5338
|
+
bytes: parsed.bytes
|
|
5339
|
+
};
|
|
5340
|
+
}
|
|
5186
5341
|
function collectPayloadAttachments(value, options) {
|
|
5187
5342
|
if (typeof value === "string") {
|
|
5188
5343
|
const attachment = decodeDataUrlAttachment(value, {
|
|
@@ -7514,14 +7669,13 @@ async function runToolLoop(request) {
|
|
|
7514
7669
|
error: result.error,
|
|
7515
7670
|
durationMs: result.durationMs
|
|
7516
7671
|
});
|
|
7517
|
-
|
|
7518
|
-
|
|
7519
|
-
|
|
7520
|
-
|
|
7521
|
-
|
|
7522
|
-
|
|
7523
|
-
|
|
7524
|
-
});
|
|
7672
|
+
responseParts.push(
|
|
7673
|
+
buildGeminiFunctionResponsePart({
|
|
7674
|
+
toolName: entry.toolName,
|
|
7675
|
+
callId: entry.call.id,
|
|
7676
|
+
outputPayload
|
|
7677
|
+
})
|
|
7678
|
+
);
|
|
7525
7679
|
}
|
|
7526
7680
|
const stepCompletedAtMs = Date.now();
|
|
7527
7681
|
const timing = buildStepTiming({
|