llm-exe 2.1.1 → 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
@@ -954,6 +954,12 @@ type AllLlm = {
954
954
  "amazon:meta.chat.v1": {
955
955
  input: AmazonBedrockRequest;
956
956
  };
957
+ "xai.chat.v1": {
958
+ input: GenericLLm;
959
+ };
960
+ "ollama.chat.v1": {
961
+ input: GenericLLm;
962
+ };
957
963
  };
958
964
  type AllUseLlmOptions = AllLlm & {
959
965
  "openai.gpt-4": {
@@ -977,6 +983,9 @@ type AllUseLlmOptions = AllLlm & {
977
983
  "anthropic.claude-3-haiku": {
978
984
  input: Omit<AnthropicRequest, "model">;
979
985
  };
986
+ "xai.grok-2": {
987
+ input: OpenAiRequest;
988
+ };
980
989
  };
981
990
  type LlmProviderKey = keyof AllLlm;
982
991
  type EmbeddingProviderKey = keyof AllEmbedding;
@@ -994,7 +1003,7 @@ interface BaseRequest<_T extends Record<string, any>> {
994
1003
  interface BaseLlm<_T extends BaseLlCall = BaseLlCall> extends BaseRequest<_T> {
995
1004
  }
996
1005
 
997
- type LlmProvider = "openai.chat" | "openai.embedding" | "openai.chat-mock" | "anthropic.chat" | "amazon:anthropic.chat" | "amazon:meta.chat" | "amazon:nova.chat" | "amazon.embedding";
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";
998
1007
  interface Config<Pk = LlmProviderKey> {
999
1008
  key: Pk;
1000
1009
  provider: LlmProvider;
@@ -1143,6 +1152,10 @@ declare function filterObjectOnSchema(schema: any, doc: any, detach?: any, prope
1143
1152
 
1144
1153
  declare const asyncCallWithTimeout: <T = any>(asyncPromise: Promise<T>, timeLimit?: number) => Promise<T>;
1145
1154
 
1155
+ declare function guessProviderFromModel(payload: {
1156
+ model: string;
1157
+ }): "openai" | "xai" | "bedrock:anthropic" | "anthropic";
1158
+
1146
1159
  declare const maybeStringifyJSON: (objOrMaybeString: any) => string;
1147
1160
  declare const maybeParseJSON: <Expected = any>(objOrMaybeJSON: any) => Expected;
1148
1161
  declare function isObjectStringified(maybeObject: string): boolean;
@@ -1154,6 +1167,7 @@ declare const index_assert: typeof assert;
1154
1167
  declare const index_asyncCallWithTimeout: typeof asyncCallWithTimeout;
1155
1168
  declare const index_defineSchema: typeof defineSchema;
1156
1169
  declare const index_filterObjectOnSchema: typeof filterObjectOnSchema;
1170
+ declare const index_guessProviderFromModel: typeof guessProviderFromModel;
1157
1171
  declare const index_importHelpers: typeof importHelpers;
1158
1172
  declare const index_importPartials: typeof importPartials;
1159
1173
  declare const index_isObjectStringified: typeof isObjectStringified;
@@ -1164,10 +1178,13 @@ declare const index_registerPartials: typeof registerPartials;
1164
1178
  declare const index_replaceTemplateString: typeof replaceTemplateString;
1165
1179
  declare const index_replaceTemplateStringAsync: typeof replaceTemplateStringAsync;
1166
1180
  declare namespace index {
1167
- 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 };
1168
1182
  }
1169
1183
 
1170
1184
  declare const configs: {
1185
+ "ollama.chat.v1": Config<keyof AllLlm>;
1186
+ "xai.chat.v1": Config<keyof AllLlm>;
1187
+ "xai.grok-2": Config<keyof AllLlm>;
1171
1188
  "amazon:anthropic.chat.v1": Config<keyof AllLlm>;
1172
1189
  "amazon:meta.chat.v1": Config<keyof AllLlm>;
1173
1190
  "anthropic.chat.v1": Config<keyof AllLlm>;
package/dist/index.d.ts CHANGED
@@ -954,6 +954,12 @@ type AllLlm = {
954
954
  "amazon:meta.chat.v1": {
955
955
  input: AmazonBedrockRequest;
956
956
  };
957
+ "xai.chat.v1": {
958
+ input: GenericLLm;
959
+ };
960
+ "ollama.chat.v1": {
961
+ input: GenericLLm;
962
+ };
957
963
  };
958
964
  type AllUseLlmOptions = AllLlm & {
959
965
  "openai.gpt-4": {
@@ -977,6 +983,9 @@ type AllUseLlmOptions = AllLlm & {
977
983
  "anthropic.claude-3-haiku": {
978
984
  input: Omit<AnthropicRequest, "model">;
979
985
  };
986
+ "xai.grok-2": {
987
+ input: OpenAiRequest;
988
+ };
980
989
  };
981
990
  type LlmProviderKey = keyof AllLlm;
982
991
  type EmbeddingProviderKey = keyof AllEmbedding;
@@ -994,7 +1003,7 @@ interface BaseRequest<_T extends Record<string, any>> {
994
1003
  interface BaseLlm<_T extends BaseLlCall = BaseLlCall> extends BaseRequest<_T> {
995
1004
  }
996
1005
 
997
- type LlmProvider = "openai.chat" | "openai.embedding" | "openai.chat-mock" | "anthropic.chat" | "amazon:anthropic.chat" | "amazon:meta.chat" | "amazon:nova.chat" | "amazon.embedding";
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";
998
1007
  interface Config<Pk = LlmProviderKey> {
999
1008
  key: Pk;
1000
1009
  provider: LlmProvider;
@@ -1143,6 +1152,10 @@ declare function filterObjectOnSchema(schema: any, doc: any, detach?: any, prope
1143
1152
 
1144
1153
  declare const asyncCallWithTimeout: <T = any>(asyncPromise: Promise<T>, timeLimit?: number) => Promise<T>;
1145
1154
 
1155
+ declare function guessProviderFromModel(payload: {
1156
+ model: string;
1157
+ }): "openai" | "xai" | "bedrock:anthropic" | "anthropic";
1158
+
1146
1159
  declare const maybeStringifyJSON: (objOrMaybeString: any) => string;
1147
1160
  declare const maybeParseJSON: <Expected = any>(objOrMaybeJSON: any) => Expected;
1148
1161
  declare function isObjectStringified(maybeObject: string): boolean;
@@ -1154,6 +1167,7 @@ declare const index_assert: typeof assert;
1154
1167
  declare const index_asyncCallWithTimeout: typeof asyncCallWithTimeout;
1155
1168
  declare const index_defineSchema: typeof defineSchema;
1156
1169
  declare const index_filterObjectOnSchema: typeof filterObjectOnSchema;
1170
+ declare const index_guessProviderFromModel: typeof guessProviderFromModel;
1157
1171
  declare const index_importHelpers: typeof importHelpers;
1158
1172
  declare const index_importPartials: typeof importPartials;
1159
1173
  declare const index_isObjectStringified: typeof isObjectStringified;
@@ -1164,10 +1178,13 @@ declare const index_registerPartials: typeof registerPartials;
1164
1178
  declare const index_replaceTemplateString: typeof replaceTemplateString;
1165
1179
  declare const index_replaceTemplateStringAsync: typeof replaceTemplateStringAsync;
1166
1180
  declare namespace index {
1167
- 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 };
1168
1182
  }
1169
1183
 
1170
1184
  declare const configs: {
1185
+ "ollama.chat.v1": Config<keyof AllLlm>;
1186
+ "xai.chat.v1": Config<keyof AllLlm>;
1187
+ "xai.grok-2": Config<keyof AllLlm>;
1171
1188
  "amazon:anthropic.chat.v1": Config<keyof AllLlm>;
1172
1189
  "amazon:meta.chat.v1": Config<keyof AllLlm>;
1173
1190
  "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);
@@ -2295,11 +2351,94 @@ var bedrock = {
2295
2351
  "amazon:meta.chat.v1": amazonMetaChatV1
2296
2352
  };
2297
2353
 
2354
+ // src/llm/config/x/index.ts
2355
+ var xaiChatV1 = {
2356
+ key: "xai.chat.v1",
2357
+ provider: "xai.chat",
2358
+ endpoint: `https://api.x.ai/v1/chat/completions`,
2359
+ options: {
2360
+ prompt: {},
2361
+ topP: {},
2362
+ useJson: {},
2363
+ xAiApiKey: {
2364
+ default: getEnvironmentVariable("XAI_API_KEY")
2365
+ }
2366
+ },
2367
+ method: "POST",
2368
+ headers: `{"Authorization":"Bearer {{xAiApiKey}}", "Content-Type": "application/json" }`,
2369
+ mapBody: {
2370
+ prompt: {
2371
+ key: "messages",
2372
+ sanitize: /* @__PURE__ */ __name((v) => {
2373
+ if (typeof v === "string") {
2374
+ return [
2375
+ {
2376
+ role: "user",
2377
+ content: v
2378
+ }
2379
+ ];
2380
+ }
2381
+ return v;
2382
+ }, "sanitize")
2383
+ },
2384
+ model: {
2385
+ key: "model"
2386
+ },
2387
+ topP: {
2388
+ key: "top_p"
2389
+ },
2390
+ useJson: {
2391
+ key: "response_format.type",
2392
+ sanitize: /* @__PURE__ */ __name((v) => v ? "json_object" : "text", "sanitize")
2393
+ }
2394
+ }
2395
+ };
2396
+ var xai = {
2397
+ "xai.chat.v1": xaiChatV1,
2398
+ "xai.grok-2": withDefaultModel(xaiChatV1, "grok-2-latest")
2399
+ };
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
+
2298
2435
  // src/llm/config.ts
2299
2436
  var configs = {
2300
2437
  ...openai,
2301
2438
  ...anthropic,
2302
- ...bedrock
2439
+ ...bedrock,
2440
+ ...xai,
2441
+ ...ollama
2303
2442
  };
2304
2443
  function getLlmConfig(provider) {
2305
2444
  const pick2 = configs[provider];
@@ -2530,6 +2669,128 @@ function OutputDefault(result, _config) {
2530
2669
  }
2531
2670
  __name(OutputDefault, "OutputDefault");
2532
2671
 
2672
+ // src/llm/output/xai.ts
2673
+ function formatResult3(result) {
2674
+ if (typeof result?.message?.content === "string") {
2675
+ return {
2676
+ type: "text",
2677
+ text: result.message.content
2678
+ };
2679
+ } else if (result?.message && "tool_calls" in result.message) {
2680
+ const tool_calls = result.message.tool_calls;
2681
+ for (const call of tool_calls) {
2682
+ return {
2683
+ type: "function_use",
2684
+ name: call.function.name,
2685
+ input: JSON.parse(call.function.arguments)
2686
+ };
2687
+ }
2688
+ }
2689
+ return {
2690
+ type: "text",
2691
+ text: ""
2692
+ };
2693
+ }
2694
+ __name(formatResult3, "formatResult");
2695
+ function OutputXAIChat(result, _config) {
2696
+ const id = result.id;
2697
+ const name = result?.model;
2698
+ const created = result.created;
2699
+ const [_content, ..._options] = result?.choices || [];
2700
+ const stopReason = _content?.finish_reason;
2701
+ const content = formatContent(_content, formatResult3);
2702
+ const options = formatOptions(_options, formatResult3);
2703
+ const usage = {
2704
+ output_tokens: result?.usage?.completion_tokens,
2705
+ input_tokens: result?.usage?.prompt_tokens,
2706
+ total_tokens: result?.usage?.total_tokens
2707
+ };
2708
+ return BaseLlmOutput2({
2709
+ id,
2710
+ name,
2711
+ created,
2712
+ usage,
2713
+ stopReason,
2714
+ content,
2715
+ options
2716
+ });
2717
+ }
2718
+ __name(OutputXAIChat, "OutputXAIChat");
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
+
2533
2794
  // src/llm/output/index.ts
2534
2795
  function getOutputParser(config, response) {
2535
2796
  switch (config?.key) {
@@ -2543,6 +2804,10 @@ function getOutputParser(config, response) {
2543
2804
  return OutputMetaLlama3Chat(response, config);
2544
2805
  // case "amazon:nova.chat.v1":
2545
2806
  // return OutputDefault(response, config);
2807
+ case "xai.chat.v1":
2808
+ return OutputXAIChat(response, config);
2809
+ case "ollama.chat.v1":
2810
+ return OutputOllamaChat(response, config);
2546
2811
  default: {
2547
2812
  if (config?.key?.startsWith("custom:")) {
2548
2813
  return OutputDefault(response, config);
@@ -2553,12 +2818,26 @@ function getOutputParser(config, response) {
2553
2818
  }
2554
2819
  __name(getOutputParser, "getOutputParser");
2555
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
+
2556
2832
  // src/utils/modules/request.ts
2557
2833
  async function apiRequest(url, options) {
2558
2834
  const finalOptions = {
2559
2835
  ...options
2560
2836
  };
2561
2837
  try {
2838
+ if (!url || !isValidUrl(url)) {
2839
+ throw new Error("Invalid URL");
2840
+ }
2562
2841
  const response = await fetch(url, finalOptions);
2563
2842
  if (!response.ok) {
2564
2843
  let message = `HTTP error. Status: ${response.status}. Error Message: ${response?.statusText || "Unknown error."}`;
@@ -2571,8 +2850,13 @@ async function apiRequest(url, options) {
2571
2850
  }
2572
2851
  throw new Error(message);
2573
2852
  }
2574
- const responseData = await response.json();
2575
- 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
+ }
2576
2860
  } catch (error) {
2577
2861
  const message = error instanceof Error ? error.message : "Error";
2578
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);
@@ -2247,11 +2303,94 @@ var bedrock = {
2247
2303
  "amazon:meta.chat.v1": amazonMetaChatV1
2248
2304
  };
2249
2305
 
2306
+ // src/llm/config/x/index.ts
2307
+ var xaiChatV1 = {
2308
+ key: "xai.chat.v1",
2309
+ provider: "xai.chat",
2310
+ endpoint: `https://api.x.ai/v1/chat/completions`,
2311
+ options: {
2312
+ prompt: {},
2313
+ topP: {},
2314
+ useJson: {},
2315
+ xAiApiKey: {
2316
+ default: getEnvironmentVariable("XAI_API_KEY")
2317
+ }
2318
+ },
2319
+ method: "POST",
2320
+ headers: `{"Authorization":"Bearer {{xAiApiKey}}", "Content-Type": "application/json" }`,
2321
+ mapBody: {
2322
+ prompt: {
2323
+ key: "messages",
2324
+ sanitize: /* @__PURE__ */ __name((v) => {
2325
+ if (typeof v === "string") {
2326
+ return [
2327
+ {
2328
+ role: "user",
2329
+ content: v
2330
+ }
2331
+ ];
2332
+ }
2333
+ return v;
2334
+ }, "sanitize")
2335
+ },
2336
+ model: {
2337
+ key: "model"
2338
+ },
2339
+ topP: {
2340
+ key: "top_p"
2341
+ },
2342
+ useJson: {
2343
+ key: "response_format.type",
2344
+ sanitize: /* @__PURE__ */ __name((v) => v ? "json_object" : "text", "sanitize")
2345
+ }
2346
+ }
2347
+ };
2348
+ var xai = {
2349
+ "xai.chat.v1": xaiChatV1,
2350
+ "xai.grok-2": withDefaultModel(xaiChatV1, "grok-2-latest")
2351
+ };
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
+
2250
2387
  // src/llm/config.ts
2251
2388
  var configs = {
2252
2389
  ...openai,
2253
2390
  ...anthropic,
2254
- ...bedrock
2391
+ ...bedrock,
2392
+ ...xai,
2393
+ ...ollama
2255
2394
  };
2256
2395
  function getLlmConfig(provider) {
2257
2396
  const pick2 = configs[provider];
@@ -2482,6 +2621,128 @@ function OutputDefault(result, _config) {
2482
2621
  }
2483
2622
  __name(OutputDefault, "OutputDefault");
2484
2623
 
2624
+ // src/llm/output/xai.ts
2625
+ function formatResult3(result) {
2626
+ if (typeof result?.message?.content === "string") {
2627
+ return {
2628
+ type: "text",
2629
+ text: result.message.content
2630
+ };
2631
+ } else if (result?.message && "tool_calls" in result.message) {
2632
+ const tool_calls = result.message.tool_calls;
2633
+ for (const call of tool_calls) {
2634
+ return {
2635
+ type: "function_use",
2636
+ name: call.function.name,
2637
+ input: JSON.parse(call.function.arguments)
2638
+ };
2639
+ }
2640
+ }
2641
+ return {
2642
+ type: "text",
2643
+ text: ""
2644
+ };
2645
+ }
2646
+ __name(formatResult3, "formatResult");
2647
+ function OutputXAIChat(result, _config) {
2648
+ const id = result.id;
2649
+ const name = result?.model;
2650
+ const created = result.created;
2651
+ const [_content, ..._options] = result?.choices || [];
2652
+ const stopReason = _content?.finish_reason;
2653
+ const content = formatContent(_content, formatResult3);
2654
+ const options = formatOptions(_options, formatResult3);
2655
+ const usage = {
2656
+ output_tokens: result?.usage?.completion_tokens,
2657
+ input_tokens: result?.usage?.prompt_tokens,
2658
+ total_tokens: result?.usage?.total_tokens
2659
+ };
2660
+ return BaseLlmOutput2({
2661
+ id,
2662
+ name,
2663
+ created,
2664
+ usage,
2665
+ stopReason,
2666
+ content,
2667
+ options
2668
+ });
2669
+ }
2670
+ __name(OutputXAIChat, "OutputXAIChat");
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
+
2485
2746
  // src/llm/output/index.ts
2486
2747
  function getOutputParser(config, response) {
2487
2748
  switch (config?.key) {
@@ -2495,6 +2756,10 @@ function getOutputParser(config, response) {
2495
2756
  return OutputMetaLlama3Chat(response, config);
2496
2757
  // case "amazon:nova.chat.v1":
2497
2758
  // return OutputDefault(response, config);
2759
+ case "xai.chat.v1":
2760
+ return OutputXAIChat(response, config);
2761
+ case "ollama.chat.v1":
2762
+ return OutputOllamaChat(response, config);
2498
2763
  default: {
2499
2764
  if (config?.key?.startsWith("custom:")) {
2500
2765
  return OutputDefault(response, config);
@@ -2505,12 +2770,26 @@ function getOutputParser(config, response) {
2505
2770
  }
2506
2771
  __name(getOutputParser, "getOutputParser");
2507
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
+
2508
2784
  // src/utils/modules/request.ts
2509
2785
  async function apiRequest(url, options) {
2510
2786
  const finalOptions = {
2511
2787
  ...options
2512
2788
  };
2513
2789
  try {
2790
+ if (!url || !isValidUrl(url)) {
2791
+ throw new Error("Invalid URL");
2792
+ }
2514
2793
  const response = await fetch(url, finalOptions);
2515
2794
  if (!response.ok) {
2516
2795
  let message = `HTTP error. Status: ${response.status}. Error Message: ${response?.statusText || "Unknown error."}`;
@@ -2523,8 +2802,13 @@ async function apiRequest(url, options) {
2523
2802
  }
2524
2803
  throw new Error(message);
2525
2804
  }
2526
- const responseData = await response.json();
2527
- 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
+ }
2528
2812
  } catch (error) {
2529
2813
  const message = error instanceof Error ? error.message : "Error";
2530
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.1",
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",
@@ -12,6 +12,7 @@
12
12
  "gpt-3.5-turbo",
13
13
  "gpt-4",
14
14
  "claude",
15
+ "grok",
15
16
  "chain",
16
17
  "prompt",
17
18
  "agent"
@@ -23,8 +24,7 @@
23
24
  "exports": {
24
25
  ".": {
25
26
  "require": "./dist/index.js",
26
- "import": "./dist/index.mjs",
27
- "types": "./dist/index.d.ts"
27
+ "import": "./dist/index.mjs"
28
28
  }
29
29
  },
30
30
  "files": [
@@ -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",
package/readme.md CHANGED
@@ -6,7 +6,8 @@ A package that provides simplified base components to make building and maintain
6
6
 
7
7
  - Write functions powered by LLM's with easy to use building blocks.
8
8
  - Pure Javascript and Typescript. Allows you to pass and infer types.
9
- - Support for text-based (llama-3) and chat-based prompts (gpt-4o, claude-3.5).
9
+ - Support for text-based (llama-3) and chat-based prompts (gpt-4o, claude-3.5, grok-3).
10
+ - Call LLM's from different providers without changing your code. (OpenAi/Anthropic/xAI/AWS Bedrock)
10
11
  - Supercharge your prompts by using handlebars within prompt template.
11
12
  - Allow LLM's to call functions (or call other LLM executors).
12
13
  - Not very opinionated. You have control on how you use it.
@@ -14,7 +15,7 @@ A package that provides simplified base components to make building and maintain
14
15
  ![llm-exe](https://assets.llm-exe.com/llm-exe-featured.jpg)
15
16
 
16
17
 
17
- See full docs [here](https://llm-exe.com)
18
+ See full docs here: [https://llm-exe.com](https://llm-exe.com)
18
19
 
19
20
 
20
21
  ---