llm-exe 3.0.0 → 3.0.2
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.d.mts +77 -27
- package/dist/index.d.ts +77 -27
- package/dist/index.js +283 -24
- package/dist/index.mjs +281 -24
- package/package.json +2 -1
- package/readme.md +1 -1
package/dist/index.mjs
CHANGED
|
@@ -464,6 +464,48 @@ function formatErrorList(values, options) {
|
|
|
464
464
|
}
|
|
465
465
|
return parts.join(", ");
|
|
466
466
|
}
|
|
467
|
+
function formatLlmExeErrorForLog(error) {
|
|
468
|
+
if (!error || typeof error !== "object") {
|
|
469
|
+
return formatErrorValue(error);
|
|
470
|
+
}
|
|
471
|
+
const e = error;
|
|
472
|
+
const name = typeof e.name === "string" && e.name ? e.name : "Error";
|
|
473
|
+
const message = typeof e.message === "string" ? e.message : "";
|
|
474
|
+
const code = typeof e.code === "string" ? e.code : void 0;
|
|
475
|
+
const category = typeof e.category === "string" ? e.category : void 0;
|
|
476
|
+
let header;
|
|
477
|
+
if (code) {
|
|
478
|
+
header = `${name} [${code}]: ${message}`;
|
|
479
|
+
} else if (category) {
|
|
480
|
+
header = `${name} [${category}]: ${message}`;
|
|
481
|
+
} else {
|
|
482
|
+
header = `${name}: ${message}`;
|
|
483
|
+
}
|
|
484
|
+
const chain = [];
|
|
485
|
+
let current = e.cause;
|
|
486
|
+
let depth = 0;
|
|
487
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
488
|
+
while (current && depth < 5) {
|
|
489
|
+
if (typeof current === "object") {
|
|
490
|
+
if (seen.has(current)) {
|
|
491
|
+
chain.push("Caused by: [Circular]");
|
|
492
|
+
break;
|
|
493
|
+
}
|
|
494
|
+
seen.add(current);
|
|
495
|
+
}
|
|
496
|
+
const c = current;
|
|
497
|
+
const cName = typeof c.name === "string" && c.name ? c.name : "Error";
|
|
498
|
+
const cMsg = typeof c.message === "string" ? c.message : String(current);
|
|
499
|
+
const cCode = typeof c.code === "string" ? c.code : void 0;
|
|
500
|
+
chain.push(
|
|
501
|
+
cCode ? `Caused by: ${cName} [${cCode}]: ${cMsg}` : `Caused by: ${cName}: ${cMsg}`
|
|
502
|
+
);
|
|
503
|
+
current = c.cause;
|
|
504
|
+
depth++;
|
|
505
|
+
}
|
|
506
|
+
return chain.length > 0 ? `${header}
|
|
507
|
+
${chain.join("\n")}` : header;
|
|
508
|
+
}
|
|
467
509
|
|
|
468
510
|
// src/errors/createLlmExeError.ts
|
|
469
511
|
var DOCS_BASE_URL = "https://llm-exe.com";
|
|
@@ -985,7 +1027,9 @@ var BaseExecutor = class {
|
|
|
985
1027
|
return this;
|
|
986
1028
|
}
|
|
987
1029
|
on(eventName, fn) {
|
|
988
|
-
return this.setHooks({
|
|
1030
|
+
return this.setHooks({
|
|
1031
|
+
[eventName]: fn
|
|
1032
|
+
});
|
|
989
1033
|
}
|
|
990
1034
|
off(eventName, fn) {
|
|
991
1035
|
return this.removeHook(eventName, fn);
|
|
@@ -1083,8 +1127,8 @@ var CoreExecutor = class extends BaseExecutor {
|
|
|
1083
1127
|
__publicField(this, "_handler");
|
|
1084
1128
|
this._handler = fn.handler.bind(null);
|
|
1085
1129
|
}
|
|
1086
|
-
async handler(_input) {
|
|
1087
|
-
return this._handler.call(null, _input);
|
|
1130
|
+
async handler(_input, _options, _context) {
|
|
1131
|
+
return this._handler.call(null, _input, _context);
|
|
1088
1132
|
}
|
|
1089
1133
|
};
|
|
1090
1134
|
|
|
@@ -3236,6 +3280,7 @@ __export(utils_exports, {
|
|
|
3236
3280
|
assert: () => assert,
|
|
3237
3281
|
asyncCallWithTimeout: () => asyncCallWithTimeout,
|
|
3238
3282
|
defineSchema: () => defineSchema,
|
|
3283
|
+
escapeTemplateString: () => escapeTemplateString,
|
|
3239
3284
|
filterObjectOnSchema: () => filterObjectOnSchema,
|
|
3240
3285
|
guessProviderFromModel: () => guessProviderFromModel,
|
|
3241
3286
|
importHelpers: () => importHelpers,
|
|
@@ -3308,6 +3353,12 @@ function importHelpers(_helpers) {
|
|
|
3308
3353
|
return helpers;
|
|
3309
3354
|
}
|
|
3310
3355
|
|
|
3356
|
+
// src/utils/modules/escapeTemplateString.ts
|
|
3357
|
+
function escapeTemplateString(input) {
|
|
3358
|
+
if (typeof input !== "string") return input;
|
|
3359
|
+
return input.replace(/\{\{/g, "\\{{");
|
|
3360
|
+
}
|
|
3361
|
+
|
|
3311
3362
|
// src/utils/modules/replaceTemplateStringAsync.ts
|
|
3312
3363
|
async function replaceTemplateStringAsync(templateString, substitutions = {}, configuration = {
|
|
3313
3364
|
helpers: [],
|
|
@@ -3973,9 +4024,53 @@ function OutputOpenAIChat(result, _config) {
|
|
|
3973
4024
|
};
|
|
3974
4025
|
}
|
|
3975
4026
|
|
|
4027
|
+
// src/llm/config/_utils/imageContent.ts
|
|
4028
|
+
function isImageUrlContentBlock(block) {
|
|
4029
|
+
if (typeof block !== "object" || block === null) {
|
|
4030
|
+
return false;
|
|
4031
|
+
}
|
|
4032
|
+
const imageUrl = block.image_url;
|
|
4033
|
+
return typeof imageUrl === "object" && imageUrl !== null && typeof imageUrl.url === "string";
|
|
4034
|
+
}
|
|
4035
|
+
var DATA_URI_PATTERN = /^data:([^;,]+);base64,(.+)$/;
|
|
4036
|
+
function parseImageUrl(url, context) {
|
|
4037
|
+
if (typeof url !== "string" || url.trim() === "") {
|
|
4038
|
+
throw new LlmExeError("Image content block has an empty url", {
|
|
4039
|
+
code: "prompt.invalid_messages",
|
|
4040
|
+
context: {
|
|
4041
|
+
...context,
|
|
4042
|
+
received: url,
|
|
4043
|
+
expected: "an https URL or a data: URI",
|
|
4044
|
+
resolution: "Set image_url.url to an https URL or a base64 data: URI (data:image/png;base64,...)."
|
|
4045
|
+
}
|
|
4046
|
+
});
|
|
4047
|
+
}
|
|
4048
|
+
if (url.startsWith("data:")) {
|
|
4049
|
+
const match = url.match(DATA_URI_PATTERN);
|
|
4050
|
+
if (!match) {
|
|
4051
|
+
throw new LlmExeError("Malformed data: URI in image content block", {
|
|
4052
|
+
code: "prompt.invalid_messages",
|
|
4053
|
+
context: {
|
|
4054
|
+
...context,
|
|
4055
|
+
received: `${url.slice(0, 48)}...`,
|
|
4056
|
+
expected: "data:<media-type>;base64,<data>",
|
|
4057
|
+
resolution: "Images must be base64-encoded with an explicit media type, e.g. data:image/png;base64,iVBOR..."
|
|
4058
|
+
}
|
|
4059
|
+
});
|
|
4060
|
+
}
|
|
4061
|
+
return { kind: "base64", mediaType: match[1], data: match[2] };
|
|
4062
|
+
}
|
|
4063
|
+
return { kind: "url", url };
|
|
4064
|
+
}
|
|
4065
|
+
|
|
3976
4066
|
// src/llm/config/openai/promptSanitizeMessageCallback.ts
|
|
3977
4067
|
function openaiPromptMessageCallback(_message) {
|
|
3978
4068
|
let message = { ..._message };
|
|
4069
|
+
if (Array.isArray(message.content)) {
|
|
4070
|
+
message.content = message.content.map(
|
|
4071
|
+
(block) => isImageUrlContentBlock(block) && block.type !== "image_url" ? { ...block, type: "image_url" } : block
|
|
4072
|
+
);
|
|
4073
|
+
}
|
|
3979
4074
|
if (message.role === "function") {
|
|
3980
4075
|
message.role = "tool";
|
|
3981
4076
|
message.tool_call_id = message.id;
|
|
@@ -4181,6 +4276,9 @@ var openai = {
|
|
|
4181
4276
|
"openai.chat.v1": openAiChatV1,
|
|
4182
4277
|
"openai.chat-mock.v1": openAiChatMockV1,
|
|
4183
4278
|
// GPT-5 family
|
|
4279
|
+
"openai.gpt-5.5": withDefaultModel(openAiChatV1, "gpt-5.5"),
|
|
4280
|
+
"openai.gpt-5.4": withDefaultModel(openAiChatV1, "gpt-5.4"),
|
|
4281
|
+
"openai.gpt-5.4-mini": withDefaultModel(openAiChatV1, "gpt-5.4-mini"),
|
|
4184
4282
|
"openai.gpt-5.2": withDefaultModel(openAiChatV1, "gpt-5.2"),
|
|
4185
4283
|
"openai.gpt-5-mini": withDefaultModel(openAiChatV1, "gpt-5-mini"),
|
|
4186
4284
|
"openai.gpt-5-nano": withDefaultModel(openAiChatV1, "gpt-5-nano"),
|
|
@@ -4202,8 +4300,46 @@ var openai = {
|
|
|
4202
4300
|
};
|
|
4203
4301
|
|
|
4204
4302
|
// src/llm/config/anthropic/promptSanitizeMessageCallback.ts
|
|
4205
|
-
function anthropicPromptMessageCallback(_message) {
|
|
4303
|
+
function anthropicPromptMessageCallback(_message, options = {}) {
|
|
4304
|
+
const { provider = "anthropic.chat", allowImageUrlSources = true } = options;
|
|
4206
4305
|
let message = { ..._message };
|
|
4306
|
+
if (Array.isArray(message.content)) {
|
|
4307
|
+
message.content = message.content.map((block) => {
|
|
4308
|
+
if (!isImageUrlContentBlock(block)) {
|
|
4309
|
+
return block;
|
|
4310
|
+
}
|
|
4311
|
+
const parsed = parseImageUrl(block.image_url.url, {
|
|
4312
|
+
operation: "anthropicPromptMessageCallback",
|
|
4313
|
+
provider
|
|
4314
|
+
});
|
|
4315
|
+
if (parsed.kind === "base64") {
|
|
4316
|
+
return {
|
|
4317
|
+
type: "image",
|
|
4318
|
+
source: {
|
|
4319
|
+
type: "base64",
|
|
4320
|
+
media_type: parsed.mediaType,
|
|
4321
|
+
data: parsed.data
|
|
4322
|
+
}
|
|
4323
|
+
};
|
|
4324
|
+
}
|
|
4325
|
+
if (!allowImageUrlSources) {
|
|
4326
|
+
throw new LlmExeError("Image URLs are not supported by this provider", {
|
|
4327
|
+
code: "prompt.invalid_messages",
|
|
4328
|
+
context: {
|
|
4329
|
+
operation: "anthropicPromptMessageCallback",
|
|
4330
|
+
provider,
|
|
4331
|
+
received: parsed.url,
|
|
4332
|
+
expected: "a base64 data: URI",
|
|
4333
|
+
resolution: "Bedrock does not fetch remote images. Base64-encode the image and pass it as a data: URI (data:image/png;base64,...)."
|
|
4334
|
+
}
|
|
4335
|
+
});
|
|
4336
|
+
}
|
|
4337
|
+
return {
|
|
4338
|
+
type: "image",
|
|
4339
|
+
source: { type: "url", url: parsed.url }
|
|
4340
|
+
};
|
|
4341
|
+
});
|
|
4342
|
+
}
|
|
4207
4343
|
if (message.role === "function") {
|
|
4208
4344
|
message.role = "user";
|
|
4209
4345
|
message.content = [
|
|
@@ -4249,10 +4385,11 @@ function mergeConsecutiveSameRole(messages) {
|
|
|
4249
4385
|
}
|
|
4250
4386
|
return merged;
|
|
4251
4387
|
}
|
|
4252
|
-
function anthropicPromptSanitize(_messages, _inputBodyObj, _outputObj) {
|
|
4388
|
+
function anthropicPromptSanitize(_messages, _inputBodyObj, _outputObj, _options = {}) {
|
|
4389
|
+
const toAnthropicMessage = (m) => anthropicPromptMessageCallback(m, _options);
|
|
4253
4390
|
if (typeof _messages === "string") {
|
|
4254
4391
|
return [{ role: "user", content: _messages }].map(
|
|
4255
|
-
|
|
4392
|
+
toAnthropicMessage
|
|
4256
4393
|
);
|
|
4257
4394
|
}
|
|
4258
4395
|
const [first, ...messages] = [
|
|
@@ -4262,7 +4399,7 @@ function anthropicPromptSanitize(_messages, _inputBodyObj, _outputObj) {
|
|
|
4262
4399
|
return [
|
|
4263
4400
|
{ role: "user", content: first.content },
|
|
4264
4401
|
...messages
|
|
4265
|
-
].map(
|
|
4402
|
+
].map(toAnthropicMessage);
|
|
4266
4403
|
}
|
|
4267
4404
|
if (first.role === "system" && messages.length > 0) {
|
|
4268
4405
|
_outputObj.system = first.content;
|
|
@@ -4271,7 +4408,7 @@ function anthropicPromptSanitize(_messages, _inputBodyObj, _outputObj) {
|
|
|
4271
4408
|
return { ...m, role: "user" };
|
|
4272
4409
|
}
|
|
4273
4410
|
return m;
|
|
4274
|
-
}).map(
|
|
4411
|
+
}).map(toAnthropicMessage);
|
|
4275
4412
|
return mergeConsecutiveSameRole(result2);
|
|
4276
4413
|
}
|
|
4277
4414
|
const result = [
|
|
@@ -4282,7 +4419,7 @@ function anthropicPromptSanitize(_messages, _inputBodyObj, _outputObj) {
|
|
|
4282
4419
|
}
|
|
4283
4420
|
return m;
|
|
4284
4421
|
})
|
|
4285
|
-
].map(
|
|
4422
|
+
].map(toAnthropicMessage);
|
|
4286
4423
|
return mergeConsecutiveSameRole(result);
|
|
4287
4424
|
}
|
|
4288
4425
|
|
|
@@ -4395,7 +4532,11 @@ var amazonAnthropicChatV1 = {
|
|
|
4395
4532
|
mapBody: {
|
|
4396
4533
|
prompt: {
|
|
4397
4534
|
key: "messages",
|
|
4398
|
-
transform: anthropicPromptSanitize
|
|
4535
|
+
transform: (v, i, o) => anthropicPromptSanitize(v, i, o, {
|
|
4536
|
+
provider: "amazon:anthropic.chat",
|
|
4537
|
+
// Bedrock's invoke API only accepts base64 image sources
|
|
4538
|
+
allowImageUrlSources: false
|
|
4539
|
+
})
|
|
4399
4540
|
},
|
|
4400
4541
|
topP: {
|
|
4401
4542
|
key: "top_p"
|
|
@@ -4451,6 +4592,21 @@ var amazonMetaChatV1 = {
|
|
|
4451
4592
|
if (typeof messages === "string") {
|
|
4452
4593
|
return messages;
|
|
4453
4594
|
} else {
|
|
4595
|
+
const hasImageContent = messages.some(
|
|
4596
|
+
(message) => Array.isArray(message?.content) && message.content.some(isImageUrlContentBlock)
|
|
4597
|
+
);
|
|
4598
|
+
if (hasImageContent) {
|
|
4599
|
+
throw new LlmExeError("Image content is not supported", {
|
|
4600
|
+
code: "prompt.invalid_messages",
|
|
4601
|
+
context: {
|
|
4602
|
+
operation: "amazonMetaChatV1.prompt.transform",
|
|
4603
|
+
provider: "amazon:meta.chat",
|
|
4604
|
+
received: "a message with image content",
|
|
4605
|
+
expected: "text-only messages",
|
|
4606
|
+
resolution: "This model accepts a flattened text prompt and cannot receive images."
|
|
4607
|
+
}
|
|
4608
|
+
});
|
|
4609
|
+
}
|
|
4454
4610
|
return replaceTemplateString(`{{>DialogueHistory key='messages'}}`, {
|
|
4455
4611
|
messages
|
|
4456
4612
|
});
|
|
@@ -4478,7 +4634,11 @@ var bedrock = {
|
|
|
4478
4634
|
|
|
4479
4635
|
// src/llm/config/anthropic/index.ts
|
|
4480
4636
|
var ANTHROPIC_VERSION = "2023-06-01";
|
|
4481
|
-
var MODELS_REJECTING_SAMPLING_PARAMS = [
|
|
4637
|
+
var MODELS_REJECTING_SAMPLING_PARAMS = [
|
|
4638
|
+
"claude-opus-4-7",
|
|
4639
|
+
"claude-opus-4-8",
|
|
4640
|
+
"claude-fable-5"
|
|
4641
|
+
];
|
|
4482
4642
|
var isClaude4x = (model) => /^claude-(opus|sonnet|haiku)-4-/.test(model);
|
|
4483
4643
|
var dropIfModelRejectsSamplingParams = (v, body) => MODELS_REJECTING_SAMPLING_PARAMS.includes(body.model) ? void 0 : v;
|
|
4484
4644
|
var topPTransform = (v, body) => {
|
|
@@ -4499,6 +4659,15 @@ var anthropicChatV1 = {
|
|
|
4499
4659
|
required: [true, "maxTokens required"],
|
|
4500
4660
|
default: 4096
|
|
4501
4661
|
},
|
|
4662
|
+
// Every key mapped in mapBody must also be declared here:
|
|
4663
|
+
// stateFromOptions picks only declared option keys, so an undeclared
|
|
4664
|
+
// key never reaches mapBody (see issue #661).
|
|
4665
|
+
temperature: {},
|
|
4666
|
+
topP: {},
|
|
4667
|
+
topK: {},
|
|
4668
|
+
stopSequences: {},
|
|
4669
|
+
metadata: {},
|
|
4670
|
+
serviceTier: {},
|
|
4502
4671
|
anthropicApiKey: {
|
|
4503
4672
|
default: getEnvironmentVariable("ANTHROPIC_API_KEY")
|
|
4504
4673
|
}
|
|
@@ -4532,9 +4701,8 @@ var anthropicChatV1 = {
|
|
|
4532
4701
|
stopSequences: {
|
|
4533
4702
|
key: "stop_sequences"
|
|
4534
4703
|
},
|
|
4535
|
-
stream:
|
|
4536
|
-
|
|
4537
|
-
},
|
|
4704
|
+
// No `stream` mapping: the request pipeline has no SSE support, so
|
|
4705
|
+
// forwarding stream=true would return an unparseable response.
|
|
4538
4706
|
metadata: {
|
|
4539
4707
|
key: "metadata"
|
|
4540
4708
|
},
|
|
@@ -4563,6 +4731,11 @@ var anthropicChatV1 = {
|
|
|
4563
4731
|
};
|
|
4564
4732
|
var anthropic = {
|
|
4565
4733
|
"anthropic.chat.v1": anthropicChatV1,
|
|
4734
|
+
// Claude Fable 5 models
|
|
4735
|
+
"anthropic.claude-fable-5": withDefaultModel(
|
|
4736
|
+
anthropicChatV1,
|
|
4737
|
+
"claude-fable-5"
|
|
4738
|
+
),
|
|
4566
4739
|
// Claude 4.8 models
|
|
4567
4740
|
"anthropic.claude-opus-4-8": withDefaultModel(
|
|
4568
4741
|
anthropicChatV1,
|
|
@@ -4596,10 +4769,9 @@ var anthropic = {
|
|
|
4596
4769
|
config: withDefaultModel(anthropicChatV1, "claude-opus-4-6"),
|
|
4597
4770
|
message: 'Shorthand "anthropic.claude-opus-4-6" is deprecated and may be removed in a future release.'
|
|
4598
4771
|
}),
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
}),
|
|
4772
|
+
// NOTE: "anthropic.claude-opus-4-1" (claude-opus-4-1-20250805) was removed —
|
|
4773
|
+
// Anthropic retires that model on Aug 5, 2026. Migrate to
|
|
4774
|
+
// anthropic.claude-opus-4-5/-6/-7/-8.
|
|
4603
4775
|
...deprecateShorthand("anthropic.claude-sonnet-4", {
|
|
4604
4776
|
config: withDefaultModel(anthropicChatV1, "claude-sonnet-4-0"),
|
|
4605
4777
|
message: 'Shorthand "anthropic.claude-sonnet-4" is deprecated and may be removed in a future release.'
|
|
@@ -4745,6 +4917,60 @@ function OutputOllamaChat(result, _config) {
|
|
|
4745
4917
|
};
|
|
4746
4918
|
}
|
|
4747
4919
|
|
|
4920
|
+
// src/llm/config/ollama/promptSanitize.ts
|
|
4921
|
+
function ollamaPromptSanitize(_messages) {
|
|
4922
|
+
if (typeof _messages === "string") {
|
|
4923
|
+
return [{ role: "user", content: _messages }];
|
|
4924
|
+
}
|
|
4925
|
+
return _messages.map((_message) => {
|
|
4926
|
+
if (!Array.isArray(_message.content)) {
|
|
4927
|
+
return _message;
|
|
4928
|
+
}
|
|
4929
|
+
const message = { ..._message };
|
|
4930
|
+
const textParts = [];
|
|
4931
|
+
const images = [];
|
|
4932
|
+
for (const block of message.content) {
|
|
4933
|
+
if (isImageUrlContentBlock(block)) {
|
|
4934
|
+
const parsed = parseImageUrl(block.image_url.url, {
|
|
4935
|
+
operation: "ollamaPromptSanitize",
|
|
4936
|
+
provider: "ollama.chat"
|
|
4937
|
+
});
|
|
4938
|
+
if (parsed.kind === "url") {
|
|
4939
|
+
throw new LlmExeError("Image URLs are not supported by ollama", {
|
|
4940
|
+
code: "prompt.invalid_messages",
|
|
4941
|
+
context: {
|
|
4942
|
+
operation: "ollamaPromptSanitize",
|
|
4943
|
+
provider: "ollama.chat",
|
|
4944
|
+
received: parsed.url,
|
|
4945
|
+
expected: "a base64 data: URI",
|
|
4946
|
+
resolution: "Ollama does not fetch remote images. Base64-encode the image and pass it as a data: URI (data:image/png;base64,...)."
|
|
4947
|
+
}
|
|
4948
|
+
});
|
|
4949
|
+
}
|
|
4950
|
+
images.push(parsed.data);
|
|
4951
|
+
} else if (typeof block?.text === "string") {
|
|
4952
|
+
textParts.push(block.text);
|
|
4953
|
+
} else {
|
|
4954
|
+
throw new LlmExeError("Unsupported content block for ollama", {
|
|
4955
|
+
code: "prompt.invalid_messages",
|
|
4956
|
+
context: {
|
|
4957
|
+
operation: "ollamaPromptSanitize",
|
|
4958
|
+
provider: "ollama.chat",
|
|
4959
|
+
received: block,
|
|
4960
|
+
expected: "text or image_url content blocks",
|
|
4961
|
+
resolution: "Ollama messages only support text and base64 images."
|
|
4962
|
+
}
|
|
4963
|
+
});
|
|
4964
|
+
}
|
|
4965
|
+
}
|
|
4966
|
+
message.content = textParts.join("\n");
|
|
4967
|
+
if (images.length > 0) {
|
|
4968
|
+
message.images = images;
|
|
4969
|
+
}
|
|
4970
|
+
return message;
|
|
4971
|
+
});
|
|
4972
|
+
}
|
|
4973
|
+
|
|
4748
4974
|
// src/llm/config/ollama/index.ts
|
|
4749
4975
|
var ollamaChatV1 = {
|
|
4750
4976
|
key: "ollama.chat.v1",
|
|
@@ -4762,12 +4988,7 @@ var ollamaChatV1 = {
|
|
|
4762
4988
|
mapBody: {
|
|
4763
4989
|
prompt: {
|
|
4764
4990
|
key: "messages",
|
|
4765
|
-
transform: (v) =>
|
|
4766
|
-
if (typeof v === "string") {
|
|
4767
|
-
return [{ role: "user", content: v }];
|
|
4768
|
-
}
|
|
4769
|
-
return v;
|
|
4770
|
-
}
|
|
4991
|
+
transform: (v) => ollamaPromptSanitize(v)
|
|
4771
4992
|
},
|
|
4772
4993
|
model: {
|
|
4773
4994
|
key: "model"
|
|
@@ -4804,6 +5025,37 @@ var ollama = {
|
|
|
4804
5025
|
};
|
|
4805
5026
|
|
|
4806
5027
|
// src/llm/config/google/promptSanitizeMessageCallback.ts
|
|
5028
|
+
var GOOGLE_SUPPORTED_FILE_URI = /^(gs:\/\/|https:\/\/generativelanguage\.googleapis\.com\/)/;
|
|
5029
|
+
function googleGeminiContentBlockToPart(block) {
|
|
5030
|
+
if (isImageUrlContentBlock(block)) {
|
|
5031
|
+
const parsed = parseImageUrl(block.image_url.url, {
|
|
5032
|
+
operation: "googleGeminiPromptMessageCallback",
|
|
5033
|
+
provider: "google.chat"
|
|
5034
|
+
});
|
|
5035
|
+
if (parsed.kind === "base64") {
|
|
5036
|
+
return {
|
|
5037
|
+
inlineData: { mimeType: parsed.mediaType, data: parsed.data }
|
|
5038
|
+
};
|
|
5039
|
+
}
|
|
5040
|
+
if (GOOGLE_SUPPORTED_FILE_URI.test(parsed.url)) {
|
|
5041
|
+
return { fileData: { fileUri: parsed.url } };
|
|
5042
|
+
}
|
|
5043
|
+
throw new LlmExeError("Gemini cannot load images from arbitrary URLs", {
|
|
5044
|
+
code: "prompt.invalid_messages",
|
|
5045
|
+
context: {
|
|
5046
|
+
operation: "googleGeminiPromptMessageCallback",
|
|
5047
|
+
provider: "google.chat",
|
|
5048
|
+
received: parsed.url,
|
|
5049
|
+
expected: "a base64 data: URI, a Files API URI, or a gs:// URI",
|
|
5050
|
+
resolution: "Pass the image as a data: URI (data:image/png;base64,...), or upload it with the Gemini Files API and pass the returned file URI."
|
|
5051
|
+
}
|
|
5052
|
+
});
|
|
5053
|
+
}
|
|
5054
|
+
if (typeof block?.text === "string") {
|
|
5055
|
+
return { text: block.text };
|
|
5056
|
+
}
|
|
5057
|
+
return block;
|
|
5058
|
+
}
|
|
4807
5059
|
function googleGeminiPromptMessageCallback(_message) {
|
|
4808
5060
|
let message = { ..._message };
|
|
4809
5061
|
const parts = [];
|
|
@@ -4817,6 +5069,9 @@ function googleGeminiPromptMessageCallback(_message) {
|
|
|
4817
5069
|
if (typeof payload.content === "string" && message.role !== "function") {
|
|
4818
5070
|
parts.push({ text: message.content });
|
|
4819
5071
|
}
|
|
5072
|
+
if (Array.isArray(payload.content) && message.role !== "function") {
|
|
5073
|
+
parts.push(...payload.content.map(googleGeminiContentBlockToPart));
|
|
5074
|
+
}
|
|
4820
5075
|
if (message.role === "function") {
|
|
4821
5076
|
role = "user";
|
|
4822
5077
|
parts.push({
|
|
@@ -7633,10 +7888,12 @@ export {
|
|
|
7633
7888
|
createState,
|
|
7634
7889
|
createStateItem,
|
|
7635
7890
|
defineSchema,
|
|
7891
|
+
formatLlmExeErrorForLog,
|
|
7636
7892
|
guards_exports as guards,
|
|
7637
7893
|
isLlmExeError,
|
|
7638
7894
|
registerHelpers,
|
|
7639
7895
|
registerPartials,
|
|
7896
|
+
serializeLlmExeError,
|
|
7640
7897
|
useExecutors,
|
|
7641
7898
|
useLlm,
|
|
7642
7899
|
useLlmConfiguration,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "llm-exe",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.2",
|
|
4
4
|
"description": "Simplify building LLM-powered apps with easy-to-use base components, supporting text and chat-based prompts with handlebars template engine, output parsers, and flexible function calling capabilities.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
"predocs:build": "npm run build:docs-examples && bash scripts/generate-llms-txt.sh",
|
|
49
49
|
"docs:dev": "eval $(cat docs/.env) && concurrently \"vitepress dev docs\" \"npm run build:watch:docs-examples\"",
|
|
50
50
|
"docs:build": "eval $(cat docs/.env) && vitepress build docs",
|
|
51
|
+
"postdocs:build": "node docs/.vitepress/scripts/verify-docs-build.mjs",
|
|
51
52
|
"docs:update-providers": "ts-node --transpile-only -r tsconfig-paths/register docs/.vitepress/scripts/updateProviders.ts",
|
|
52
53
|
"lint": "eslint .",
|
|
53
54
|
"format:check": "prettier --check \"src\"",
|
package/readme.md
CHANGED
|
@@ -14,7 +14,7 @@ A package that provides simplified base components to make building and maintain
|
|
|
14
14
|
- Allow LLM's to call functions (or call other LLM executors).
|
|
15
15
|
- Not very opinionated. You have control on how you use it.
|
|
16
16
|
|
|
17
|
-

|
|
17
|
+

|
|
18
18
|
|
|
19
19
|
See full docs here: [https://llm-exe.com](https://llm-exe.com)
|
|
20
20
|
|