llm-exe 2.1.2 → 2.1.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.
package/dist/index.d.mts CHANGED
@@ -955,7 +955,10 @@ type AllLlm = {
955
955
  input: AmazonBedrockRequest;
956
956
  };
957
957
  "xai.chat.v1": {
958
- input: OpenAiRequest;
958
+ input: GenericLLm;
959
+ };
960
+ "ollama.chat.v1": {
961
+ input: GenericLLm;
959
962
  };
960
963
  };
961
964
  type AllUseLlmOptions = AllLlm & {
@@ -1000,7 +1003,7 @@ interface BaseRequest<_T extends Record<string, any>> {
1000
1003
  interface BaseLlm<_T extends BaseLlCall = BaseLlCall> extends BaseRequest<_T> {
1001
1004
  }
1002
1005
 
1003
- type LlmProvider = "openai.chat" | "openai.embedding" | "openai.chat-mock" | "anthropic.chat" | "amazon:anthropic.chat" | "amazon:meta.chat" | "amazon:nova.chat" | "amazon.embedding" | "xai.chat";
1006
+ type LlmProvider = "openai.chat" | "openai.embedding" | "openai.chat-mock" | "anthropic.chat" | "amazon:anthropic.chat" | "amazon:meta.chat" | "amazon:nova.chat" | "amazon.embedding" | "xai.chat" | "ollama.chat";
1004
1007
  interface Config<Pk = LlmProviderKey> {
1005
1008
  key: Pk;
1006
1009
  provider: LlmProvider;
@@ -1149,6 +1152,10 @@ declare function filterObjectOnSchema(schema: any, doc: any, detach?: any, prope
1149
1152
 
1150
1153
  declare const asyncCallWithTimeout: <T = any>(asyncPromise: Promise<T>, timeLimit?: number) => Promise<T>;
1151
1154
 
1155
+ declare function guessProviderFromModel(payload: {
1156
+ model: string;
1157
+ }): "openai" | "xai" | "bedrock:anthropic" | "anthropic";
1158
+
1152
1159
  declare const maybeStringifyJSON: (objOrMaybeString: any) => string;
1153
1160
  declare const maybeParseJSON: <Expected = any>(objOrMaybeJSON: any) => Expected;
1154
1161
  declare function isObjectStringified(maybeObject: string): boolean;
@@ -1160,6 +1167,7 @@ declare const index_assert: typeof assert;
1160
1167
  declare const index_asyncCallWithTimeout: typeof asyncCallWithTimeout;
1161
1168
  declare const index_defineSchema: typeof defineSchema;
1162
1169
  declare const index_filterObjectOnSchema: typeof filterObjectOnSchema;
1170
+ declare const index_guessProviderFromModel: typeof guessProviderFromModel;
1163
1171
  declare const index_importHelpers: typeof importHelpers;
1164
1172
  declare const index_importPartials: typeof importPartials;
1165
1173
  declare const index_isObjectStringified: typeof isObjectStringified;
@@ -1170,10 +1178,11 @@ declare const index_registerPartials: typeof registerPartials;
1170
1178
  declare const index_replaceTemplateString: typeof replaceTemplateString;
1171
1179
  declare const index_replaceTemplateStringAsync: typeof replaceTemplateStringAsync;
1172
1180
  declare namespace index {
1173
- export { index_assert as assert, index_asyncCallWithTimeout as asyncCallWithTimeout, index_defineSchema as defineSchema, index_filterObjectOnSchema as filterObjectOnSchema, index_importHelpers as importHelpers, index_importPartials as importPartials, index_isObjectStringified as isObjectStringified, index_maybeParseJSON as maybeParseJSON, index_maybeStringifyJSON as maybeStringifyJSON, index_registerHelpers as registerHelpers, index_registerPartials as registerPartials, index_replaceTemplateString as replaceTemplateString, index_replaceTemplateStringAsync as replaceTemplateStringAsync };
1181
+ export { index_assert as assert, index_asyncCallWithTimeout as asyncCallWithTimeout, index_defineSchema as defineSchema, index_filterObjectOnSchema as filterObjectOnSchema, index_guessProviderFromModel as guessProviderFromModel, index_importHelpers as importHelpers, index_importPartials as importPartials, index_isObjectStringified as isObjectStringified, index_maybeParseJSON as maybeParseJSON, index_maybeStringifyJSON as maybeStringifyJSON, index_registerHelpers as registerHelpers, index_registerPartials as registerPartials, index_replaceTemplateString as replaceTemplateString, index_replaceTemplateStringAsync as replaceTemplateStringAsync };
1174
1182
  }
1175
1183
 
1176
1184
  declare const configs: {
1185
+ "ollama.chat.v1": Config<keyof AllLlm>;
1177
1186
  "xai.chat.v1": Config<keyof AllLlm>;
1178
1187
  "xai.grok-2": Config<keyof AllLlm>;
1179
1188
  "amazon:anthropic.chat.v1": Config<keyof AllLlm>;
package/dist/index.d.ts CHANGED
@@ -955,7 +955,10 @@ type AllLlm = {
955
955
  input: AmazonBedrockRequest;
956
956
  };
957
957
  "xai.chat.v1": {
958
- input: OpenAiRequest;
958
+ input: GenericLLm;
959
+ };
960
+ "ollama.chat.v1": {
961
+ input: GenericLLm;
959
962
  };
960
963
  };
961
964
  type AllUseLlmOptions = AllLlm & {
@@ -1000,7 +1003,7 @@ interface BaseRequest<_T extends Record<string, any>> {
1000
1003
  interface BaseLlm<_T extends BaseLlCall = BaseLlCall> extends BaseRequest<_T> {
1001
1004
  }
1002
1005
 
1003
- type LlmProvider = "openai.chat" | "openai.embedding" | "openai.chat-mock" | "anthropic.chat" | "amazon:anthropic.chat" | "amazon:meta.chat" | "amazon:nova.chat" | "amazon.embedding" | "xai.chat";
1006
+ type LlmProvider = "openai.chat" | "openai.embedding" | "openai.chat-mock" | "anthropic.chat" | "amazon:anthropic.chat" | "amazon:meta.chat" | "amazon:nova.chat" | "amazon.embedding" | "xai.chat" | "ollama.chat";
1004
1007
  interface Config<Pk = LlmProviderKey> {
1005
1008
  key: Pk;
1006
1009
  provider: LlmProvider;
@@ -1149,6 +1152,10 @@ declare function filterObjectOnSchema(schema: any, doc: any, detach?: any, prope
1149
1152
 
1150
1153
  declare const asyncCallWithTimeout: <T = any>(asyncPromise: Promise<T>, timeLimit?: number) => Promise<T>;
1151
1154
 
1155
+ declare function guessProviderFromModel(payload: {
1156
+ model: string;
1157
+ }): "openai" | "xai" | "bedrock:anthropic" | "anthropic";
1158
+
1152
1159
  declare const maybeStringifyJSON: (objOrMaybeString: any) => string;
1153
1160
  declare const maybeParseJSON: <Expected = any>(objOrMaybeJSON: any) => Expected;
1154
1161
  declare function isObjectStringified(maybeObject: string): boolean;
@@ -1160,6 +1167,7 @@ declare const index_assert: typeof assert;
1160
1167
  declare const index_asyncCallWithTimeout: typeof asyncCallWithTimeout;
1161
1168
  declare const index_defineSchema: typeof defineSchema;
1162
1169
  declare const index_filterObjectOnSchema: typeof filterObjectOnSchema;
1170
+ declare const index_guessProviderFromModel: typeof guessProviderFromModel;
1163
1171
  declare const index_importHelpers: typeof importHelpers;
1164
1172
  declare const index_importPartials: typeof importPartials;
1165
1173
  declare const index_isObjectStringified: typeof isObjectStringified;
@@ -1170,10 +1178,11 @@ declare const index_registerPartials: typeof registerPartials;
1170
1178
  declare const index_replaceTemplateString: typeof replaceTemplateString;
1171
1179
  declare const index_replaceTemplateStringAsync: typeof replaceTemplateStringAsync;
1172
1180
  declare namespace index {
1173
- export { index_assert as assert, index_asyncCallWithTimeout as asyncCallWithTimeout, index_defineSchema as defineSchema, index_filterObjectOnSchema as filterObjectOnSchema, index_importHelpers as importHelpers, index_importPartials as importPartials, index_isObjectStringified as isObjectStringified, index_maybeParseJSON as maybeParseJSON, index_maybeStringifyJSON as maybeStringifyJSON, index_registerHelpers as registerHelpers, index_registerPartials as registerPartials, index_replaceTemplateString as replaceTemplateString, index_replaceTemplateStringAsync as replaceTemplateStringAsync };
1181
+ export { index_assert as assert, index_asyncCallWithTimeout as asyncCallWithTimeout, index_defineSchema as defineSchema, index_filterObjectOnSchema as filterObjectOnSchema, index_guessProviderFromModel as guessProviderFromModel, index_importHelpers as importHelpers, index_importPartials as importPartials, index_isObjectStringified as isObjectStringified, index_maybeParseJSON as maybeParseJSON, index_maybeStringifyJSON as maybeStringifyJSON, index_registerHelpers as registerHelpers, index_registerPartials as registerPartials, index_replaceTemplateString as replaceTemplateString, index_replaceTemplateStringAsync as replaceTemplateStringAsync };
1174
1182
  }
1175
1183
 
1176
1184
  declare const configs: {
1185
+ "ollama.chat.v1": Config<keyof AllLlm>;
1177
1186
  "xai.chat.v1": Config<keyof AllLlm>;
1178
1187
  "xai.grok-2": Config<keyof AllLlm>;
1179
1188
  "amazon:anthropic.chat.v1": Config<keyof AllLlm>;
package/dist/index.js CHANGED
@@ -429,6 +429,7 @@ __export(utils_exports, {
429
429
  asyncCallWithTimeout: () => asyncCallWithTimeout,
430
430
  defineSchema: () => defineSchema,
431
431
  filterObjectOnSchema: () => filterObjectOnSchema,
432
+ guessProviderFromModel: () => guessProviderFromModel,
432
433
  importHelpers: () => importHelpers,
433
434
  importPartials: () => importPartials,
434
435
  isObjectStringified: () => isObjectStringified,
@@ -1403,6 +1404,61 @@ var asyncCallWithTimeout = /* @__PURE__ */ __name(async (asyncPromise, timeLimit
1403
1404
  });
1404
1405
  }, "asyncCallWithTimeout");
1405
1406
 
1407
+ // src/utils/modules/guessProviderFromModel.ts
1408
+ function isModelKnownOpenAi(payload) {
1409
+ const model = payload.model.toLowerCase();
1410
+ if (model.startsWith("gpt-") || model.startsWith("chatgpt-")) {
1411
+ return true;
1412
+ }
1413
+ if (model === "o1" || model.startsWith("o1-")) {
1414
+ return true;
1415
+ }
1416
+ if (model === "o3-mini") {
1417
+ return true;
1418
+ }
1419
+ return false;
1420
+ }
1421
+ __name(isModelKnownOpenAi, "isModelKnownOpenAi");
1422
+ function isModelKnownAnthropic(payload) {
1423
+ const model = payload.model.toLowerCase();
1424
+ if (model.startsWith("claude-")) {
1425
+ return true;
1426
+ }
1427
+ return false;
1428
+ }
1429
+ __name(isModelKnownAnthropic, "isModelKnownAnthropic");
1430
+ function isModelKnownXai(payload) {
1431
+ const model = payload.model.toLowerCase();
1432
+ if (model.startsWith("grok-")) {
1433
+ return true;
1434
+ }
1435
+ return false;
1436
+ }
1437
+ __name(isModelKnownXai, "isModelKnownXai");
1438
+ function isModelKnownBedrockAnthropic(payload) {
1439
+ const model = payload.model.toLowerCase();
1440
+ if (model.startsWith("anthropic.claude-")) {
1441
+ return true;
1442
+ }
1443
+ return false;
1444
+ }
1445
+ __name(isModelKnownBedrockAnthropic, "isModelKnownBedrockAnthropic");
1446
+ function guessProviderFromModel(payload) {
1447
+ switch (true) {
1448
+ case isModelKnownOpenAi(payload):
1449
+ return "openai";
1450
+ case isModelKnownXai(payload):
1451
+ return "xai";
1452
+ case isModelKnownBedrockAnthropic(payload):
1453
+ return "bedrock:anthropic";
1454
+ case isModelKnownAnthropic(payload):
1455
+ return "anthropic";
1456
+ default:
1457
+ throw new Error("Unsupported model");
1458
+ }
1459
+ }
1460
+ __name(guessProviderFromModel, "guessProviderFromModel");
1461
+
1406
1462
  // src/utils/modules/index.ts
1407
1463
  function registerHelpers(helpers) {
1408
1464
  hbs.registerHelpers(helpers);
@@ -2342,12 +2398,47 @@ var xai = {
2342
2398
  "xai.grok-2": withDefaultModel(xaiChatV1, "grok-2-latest")
2343
2399
  };
2344
2400
 
2401
+ // src/llm/config/ollama/index.ts
2402
+ var ollamaChatV1 = {
2403
+ key: "ollama.chat.v1",
2404
+ provider: "ollama.chat",
2405
+ endpoint: `${getEnvironmentVariable("OLLAMA_ENDPOINT") || `http://localhost:11434`}/api/chat`,
2406
+ options: {
2407
+ prompt: {}
2408
+ },
2409
+ method: "POST",
2410
+ headers: `{"Content-Type": "application/json" }`,
2411
+ mapBody: {
2412
+ prompt: {
2413
+ key: "messages",
2414
+ sanitize: /* @__PURE__ */ __name((v) => {
2415
+ if (typeof v === "string") {
2416
+ return [
2417
+ {
2418
+ role: "user",
2419
+ content: v
2420
+ }
2421
+ ];
2422
+ }
2423
+ return v;
2424
+ }, "sanitize")
2425
+ },
2426
+ model: {
2427
+ key: "model"
2428
+ }
2429
+ }
2430
+ };
2431
+ var ollama = {
2432
+ "ollama.chat.v1": ollamaChatV1
2433
+ };
2434
+
2345
2435
  // src/llm/config.ts
2346
2436
  var configs = {
2347
2437
  ...openai,
2348
2438
  ...anthropic,
2349
2439
  ...bedrock,
2350
- ...xai
2440
+ ...xai,
2441
+ ...ollama
2351
2442
  };
2352
2443
  function getLlmConfig(provider) {
2353
2444
  const pick2 = configs[provider];
@@ -2626,6 +2717,80 @@ function OutputXAIChat(result, _config) {
2626
2717
  }
2627
2718
  __name(OutputXAIChat, "OutputXAIChat");
2628
2719
 
2720
+ // src/llm/output/_utils/combineJsonl.ts
2721
+ function combineJsonl(jsonl) {
2722
+ const lines = jsonl.trim().split("\n").map((line) => line.trim()).filter((line) => line.length > 0).map((line) => {
2723
+ try {
2724
+ return JSON.parse(line);
2725
+ } catch (e) {
2726
+ throw new Error(`Invalid JSON: ${line}`);
2727
+ }
2728
+ });
2729
+ if (lines.length === 0) {
2730
+ throw new Error("No JSON lines provided.");
2731
+ }
2732
+ lines.sort((a, b) => new Date(a.created_at).getTime() - new Date(b.created_at).getTime());
2733
+ let combinedContent = lines.map((line) => line?.message?.content ?? "").join("");
2734
+ combinedContent = combinedContent.replace(/\\u003c/g, "<").replace(/\\u003e/g, ">");
2735
+ const finalLine = lines.find((line) => line.done === true);
2736
+ if (!finalLine) {
2737
+ throw new Error("No line found where done = true.");
2738
+ }
2739
+ const result = {
2740
+ model: finalLine.model,
2741
+ created_at: finalLine.created_at,
2742
+ message: {
2743
+ role: finalLine?.message?.role || "assistant",
2744
+ content: combinedContent
2745
+ },
2746
+ done_reason: finalLine.done_reason,
2747
+ done: finalLine.done,
2748
+ total_duration: finalLine.total_duration,
2749
+ load_duration: finalLine.load_duration,
2750
+ prompt_eval_count: finalLine.prompt_eval_count,
2751
+ prompt_eval_duration: finalLine.prompt_eval_duration,
2752
+ eval_count: finalLine.eval_count,
2753
+ eval_duration: finalLine.eval_duration
2754
+ };
2755
+ const content = {
2756
+ type: "text",
2757
+ text: combinedContent
2758
+ };
2759
+ return {
2760
+ lines,
2761
+ result,
2762
+ content
2763
+ };
2764
+ }
2765
+ __name(combineJsonl, "combineJsonl");
2766
+
2767
+ // src/llm/output/ollama.ts
2768
+ function OutputOllamaChat(result, _config) {
2769
+ const combined = combineJsonl(result);
2770
+ const id = `${combined.result.model}.${combined.result.created_at}`;
2771
+ const name = combined.result.model || _config?.model || "ollama.unknown";
2772
+ const created = (/* @__PURE__ */ new Date(`${combined.result.created_at}`)).getTime();
2773
+ const stopReason = `${combined?.result?.done_reason || "stop"}`;
2774
+ const content = [
2775
+ combined.content
2776
+ ];
2777
+ const usage = {
2778
+ output_tokens: 0,
2779
+ input_tokens: 0,
2780
+ total_tokens: 0
2781
+ };
2782
+ return BaseLlmOutput2({
2783
+ id,
2784
+ name,
2785
+ created,
2786
+ usage,
2787
+ stopReason,
2788
+ content,
2789
+ options: []
2790
+ });
2791
+ }
2792
+ __name(OutputOllamaChat, "OutputOllamaChat");
2793
+
2629
2794
  // src/llm/output/index.ts
2630
2795
  function getOutputParser(config, response) {
2631
2796
  switch (config?.key) {
@@ -2641,6 +2806,8 @@ function getOutputParser(config, response) {
2641
2806
  // return OutputDefault(response, config);
2642
2807
  case "xai.chat.v1":
2643
2808
  return OutputXAIChat(response, config);
2809
+ case "ollama.chat.v1":
2810
+ return OutputOllamaChat(response, config);
2644
2811
  default: {
2645
2812
  if (config?.key?.startsWith("custom:")) {
2646
2813
  return OutputDefault(response, config);
@@ -2651,12 +2818,26 @@ function getOutputParser(config, response) {
2651
2818
  }
2652
2819
  __name(getOutputParser, "getOutputParser");
2653
2820
 
2821
+ // src/utils/modules/isValidUrl.ts
2822
+ function isValidUrl(input) {
2823
+ try {
2824
+ new URL(input);
2825
+ return true;
2826
+ } catch {
2827
+ return false;
2828
+ }
2829
+ }
2830
+ __name(isValidUrl, "isValidUrl");
2831
+
2654
2832
  // src/utils/modules/request.ts
2655
2833
  async function apiRequest(url, options) {
2656
2834
  const finalOptions = {
2657
2835
  ...options
2658
2836
  };
2659
2837
  try {
2838
+ if (!url || !isValidUrl(url)) {
2839
+ throw new Error("Invalid URL");
2840
+ }
2660
2841
  const response = await fetch(url, finalOptions);
2661
2842
  if (!response.ok) {
2662
2843
  let message = `HTTP error. Status: ${response.status}. Error Message: ${response?.statusText || "Unknown error."}`;
@@ -2669,8 +2850,13 @@ async function apiRequest(url, options) {
2669
2850
  }
2670
2851
  throw new Error(message);
2671
2852
  }
2672
- const responseData = await response.json();
2673
- return responseData;
2853
+ if (response.headers.get("content-type")?.includes("application/json")) {
2854
+ const responseData = await response.json();
2855
+ return responseData;
2856
+ } else {
2857
+ const responseData = await response.text();
2858
+ return responseData;
2859
+ }
2674
2860
  } catch (error) {
2675
2861
  const message = error instanceof Error ? error.message : "Error";
2676
2862
  throw new Error(`Request to ${url} failed: ${message}`);
package/dist/index.mjs CHANGED
@@ -381,6 +381,7 @@ __export(utils_exports, {
381
381
  asyncCallWithTimeout: () => asyncCallWithTimeout,
382
382
  defineSchema: () => defineSchema,
383
383
  filterObjectOnSchema: () => filterObjectOnSchema,
384
+ guessProviderFromModel: () => guessProviderFromModel,
384
385
  importHelpers: () => importHelpers,
385
386
  importPartials: () => importPartials,
386
387
  isObjectStringified: () => isObjectStringified,
@@ -1355,6 +1356,61 @@ var asyncCallWithTimeout = /* @__PURE__ */ __name(async (asyncPromise, timeLimit
1355
1356
  });
1356
1357
  }, "asyncCallWithTimeout");
1357
1358
 
1359
+ // src/utils/modules/guessProviderFromModel.ts
1360
+ function isModelKnownOpenAi(payload) {
1361
+ const model = payload.model.toLowerCase();
1362
+ if (model.startsWith("gpt-") || model.startsWith("chatgpt-")) {
1363
+ return true;
1364
+ }
1365
+ if (model === "o1" || model.startsWith("o1-")) {
1366
+ return true;
1367
+ }
1368
+ if (model === "o3-mini") {
1369
+ return true;
1370
+ }
1371
+ return false;
1372
+ }
1373
+ __name(isModelKnownOpenAi, "isModelKnownOpenAi");
1374
+ function isModelKnownAnthropic(payload) {
1375
+ const model = payload.model.toLowerCase();
1376
+ if (model.startsWith("claude-")) {
1377
+ return true;
1378
+ }
1379
+ return false;
1380
+ }
1381
+ __name(isModelKnownAnthropic, "isModelKnownAnthropic");
1382
+ function isModelKnownXai(payload) {
1383
+ const model = payload.model.toLowerCase();
1384
+ if (model.startsWith("grok-")) {
1385
+ return true;
1386
+ }
1387
+ return false;
1388
+ }
1389
+ __name(isModelKnownXai, "isModelKnownXai");
1390
+ function isModelKnownBedrockAnthropic(payload) {
1391
+ const model = payload.model.toLowerCase();
1392
+ if (model.startsWith("anthropic.claude-")) {
1393
+ return true;
1394
+ }
1395
+ return false;
1396
+ }
1397
+ __name(isModelKnownBedrockAnthropic, "isModelKnownBedrockAnthropic");
1398
+ function guessProviderFromModel(payload) {
1399
+ switch (true) {
1400
+ case isModelKnownOpenAi(payload):
1401
+ return "openai";
1402
+ case isModelKnownXai(payload):
1403
+ return "xai";
1404
+ case isModelKnownBedrockAnthropic(payload):
1405
+ return "bedrock:anthropic";
1406
+ case isModelKnownAnthropic(payload):
1407
+ return "anthropic";
1408
+ default:
1409
+ throw new Error("Unsupported model");
1410
+ }
1411
+ }
1412
+ __name(guessProviderFromModel, "guessProviderFromModel");
1413
+
1358
1414
  // src/utils/modules/index.ts
1359
1415
  function registerHelpers(helpers) {
1360
1416
  hbs.registerHelpers(helpers);
@@ -2294,12 +2350,47 @@ var xai = {
2294
2350
  "xai.grok-2": withDefaultModel(xaiChatV1, "grok-2-latest")
2295
2351
  };
2296
2352
 
2353
+ // src/llm/config/ollama/index.ts
2354
+ var ollamaChatV1 = {
2355
+ key: "ollama.chat.v1",
2356
+ provider: "ollama.chat",
2357
+ endpoint: `${getEnvironmentVariable("OLLAMA_ENDPOINT") || `http://localhost:11434`}/api/chat`,
2358
+ options: {
2359
+ prompt: {}
2360
+ },
2361
+ method: "POST",
2362
+ headers: `{"Content-Type": "application/json" }`,
2363
+ mapBody: {
2364
+ prompt: {
2365
+ key: "messages",
2366
+ sanitize: /* @__PURE__ */ __name((v) => {
2367
+ if (typeof v === "string") {
2368
+ return [
2369
+ {
2370
+ role: "user",
2371
+ content: v
2372
+ }
2373
+ ];
2374
+ }
2375
+ return v;
2376
+ }, "sanitize")
2377
+ },
2378
+ model: {
2379
+ key: "model"
2380
+ }
2381
+ }
2382
+ };
2383
+ var ollama = {
2384
+ "ollama.chat.v1": ollamaChatV1
2385
+ };
2386
+
2297
2387
  // src/llm/config.ts
2298
2388
  var configs = {
2299
2389
  ...openai,
2300
2390
  ...anthropic,
2301
2391
  ...bedrock,
2302
- ...xai
2392
+ ...xai,
2393
+ ...ollama
2303
2394
  };
2304
2395
  function getLlmConfig(provider) {
2305
2396
  const pick2 = configs[provider];
@@ -2578,6 +2669,80 @@ function OutputXAIChat(result, _config) {
2578
2669
  }
2579
2670
  __name(OutputXAIChat, "OutputXAIChat");
2580
2671
 
2672
+ // src/llm/output/_utils/combineJsonl.ts
2673
+ function combineJsonl(jsonl) {
2674
+ const lines = jsonl.trim().split("\n").map((line) => line.trim()).filter((line) => line.length > 0).map((line) => {
2675
+ try {
2676
+ return JSON.parse(line);
2677
+ } catch (e) {
2678
+ throw new Error(`Invalid JSON: ${line}`);
2679
+ }
2680
+ });
2681
+ if (lines.length === 0) {
2682
+ throw new Error("No JSON lines provided.");
2683
+ }
2684
+ lines.sort((a, b) => new Date(a.created_at).getTime() - new Date(b.created_at).getTime());
2685
+ let combinedContent = lines.map((line) => line?.message?.content ?? "").join("");
2686
+ combinedContent = combinedContent.replace(/\\u003c/g, "<").replace(/\\u003e/g, ">");
2687
+ const finalLine = lines.find((line) => line.done === true);
2688
+ if (!finalLine) {
2689
+ throw new Error("No line found where done = true.");
2690
+ }
2691
+ const result = {
2692
+ model: finalLine.model,
2693
+ created_at: finalLine.created_at,
2694
+ message: {
2695
+ role: finalLine?.message?.role || "assistant",
2696
+ content: combinedContent
2697
+ },
2698
+ done_reason: finalLine.done_reason,
2699
+ done: finalLine.done,
2700
+ total_duration: finalLine.total_duration,
2701
+ load_duration: finalLine.load_duration,
2702
+ prompt_eval_count: finalLine.prompt_eval_count,
2703
+ prompt_eval_duration: finalLine.prompt_eval_duration,
2704
+ eval_count: finalLine.eval_count,
2705
+ eval_duration: finalLine.eval_duration
2706
+ };
2707
+ const content = {
2708
+ type: "text",
2709
+ text: combinedContent
2710
+ };
2711
+ return {
2712
+ lines,
2713
+ result,
2714
+ content
2715
+ };
2716
+ }
2717
+ __name(combineJsonl, "combineJsonl");
2718
+
2719
+ // src/llm/output/ollama.ts
2720
+ function OutputOllamaChat(result, _config) {
2721
+ const combined = combineJsonl(result);
2722
+ const id = `${combined.result.model}.${combined.result.created_at}`;
2723
+ const name = combined.result.model || _config?.model || "ollama.unknown";
2724
+ const created = (/* @__PURE__ */ new Date(`${combined.result.created_at}`)).getTime();
2725
+ const stopReason = `${combined?.result?.done_reason || "stop"}`;
2726
+ const content = [
2727
+ combined.content
2728
+ ];
2729
+ const usage = {
2730
+ output_tokens: 0,
2731
+ input_tokens: 0,
2732
+ total_tokens: 0
2733
+ };
2734
+ return BaseLlmOutput2({
2735
+ id,
2736
+ name,
2737
+ created,
2738
+ usage,
2739
+ stopReason,
2740
+ content,
2741
+ options: []
2742
+ });
2743
+ }
2744
+ __name(OutputOllamaChat, "OutputOllamaChat");
2745
+
2581
2746
  // src/llm/output/index.ts
2582
2747
  function getOutputParser(config, response) {
2583
2748
  switch (config?.key) {
@@ -2593,6 +2758,8 @@ function getOutputParser(config, response) {
2593
2758
  // return OutputDefault(response, config);
2594
2759
  case "xai.chat.v1":
2595
2760
  return OutputXAIChat(response, config);
2761
+ case "ollama.chat.v1":
2762
+ return OutputOllamaChat(response, config);
2596
2763
  default: {
2597
2764
  if (config?.key?.startsWith("custom:")) {
2598
2765
  return OutputDefault(response, config);
@@ -2603,12 +2770,26 @@ function getOutputParser(config, response) {
2603
2770
  }
2604
2771
  __name(getOutputParser, "getOutputParser");
2605
2772
 
2773
+ // src/utils/modules/isValidUrl.ts
2774
+ function isValidUrl(input) {
2775
+ try {
2776
+ new URL(input);
2777
+ return true;
2778
+ } catch {
2779
+ return false;
2780
+ }
2781
+ }
2782
+ __name(isValidUrl, "isValidUrl");
2783
+
2606
2784
  // src/utils/modules/request.ts
2607
2785
  async function apiRequest(url, options) {
2608
2786
  const finalOptions = {
2609
2787
  ...options
2610
2788
  };
2611
2789
  try {
2790
+ if (!url || !isValidUrl(url)) {
2791
+ throw new Error("Invalid URL");
2792
+ }
2612
2793
  const response = await fetch(url, finalOptions);
2613
2794
  if (!response.ok) {
2614
2795
  let message = `HTTP error. Status: ${response.status}. Error Message: ${response?.statusText || "Unknown error."}`;
@@ -2621,8 +2802,13 @@ async function apiRequest(url, options) {
2621
2802
  }
2622
2803
  throw new Error(message);
2623
2804
  }
2624
- const responseData = await response.json();
2625
- return responseData;
2805
+ if (response.headers.get("content-type")?.includes("application/json")) {
2806
+ const responseData = await response.json();
2807
+ return responseData;
2808
+ } else {
2809
+ const responseData = await response.text();
2810
+ return responseData;
2811
+ }
2626
2812
  } catch (error) {
2627
2813
  const message = error instanceof Error ? error.message : "Error";
2628
2814
  throw new Error(`Request to ${url} failed: ${message}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "llm-exe",
3
- "version": "2.1.2",
3
+ "version": "2.1.3",
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",
@@ -45,7 +45,9 @@
45
45
  "docs:build": "vitepress build docs",
46
46
  "lint": "eslint",
47
47
  "format:check": "prettier --check \"src\"",
48
- "format:write": "prettier --write \"src\""
48
+ "format:write": "prettier --write \"src\"",
49
+ "publish-main": "npm publish",
50
+ "publish-beta": "npm publish --tag beta"
49
51
  },
50
52
  "author": "Greg Reindel",
51
53
  "license": "MIT",