llm-exe 2.2.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -47,6 +47,8 @@ __export(index_exports, {
47
47
  DefaultState: () => DefaultState,
48
48
  DefaultStateItem: () => DefaultStateItem,
49
49
  LlmExecutorOpenAiFunctions: () => LlmExecutorOpenAiFunctions,
50
+ LlmExecutorWithFunctions: () => LlmExecutorWithFunctions,
51
+ LlmNativeFunctionParser: () => LlmNativeFunctionParser,
50
52
  OpenAiFunctionParser: () => OpenAiFunctionParser,
51
53
  TextPrompt: () => TextPrompt,
52
54
  createCallableExecutor: () => createCallableExecutor,
@@ -56,11 +58,13 @@ __export(index_exports, {
56
58
  createDialogue: () => createDialogue,
57
59
  createEmbedding: () => createEmbedding,
58
60
  createLlmExecutor: () => createLlmExecutor,
61
+ createLlmFunctionExecutor: () => createLlmFunctionExecutor,
59
62
  createParser: () => createParser,
60
63
  createPrompt: () => createPrompt,
61
64
  createState: () => createState,
62
65
  createStateItem: () => createStateItem,
63
66
  defineSchema: () => defineSchema,
67
+ guards: () => guards_exports,
64
68
  registerHelpers: () => registerHelpers,
65
69
  registerPartials: () => registerPartials,
66
70
  useExecutors: () => useExecutors,
@@ -390,6 +394,123 @@ var BaseParserWithJson = class extends BaseParser {
390
394
  }
391
395
  };
392
396
 
397
+ // src/utils/modules/assert.ts
398
+ function assert(condition, message) {
399
+ if (condition === void 0 || condition === null || condition === false) {
400
+ if (typeof message === "string") {
401
+ throw new Error(message);
402
+ } else if (message instanceof Error) {
403
+ throw message;
404
+ } else {
405
+ throw new Error(`Assertion error`);
406
+ }
407
+ }
408
+ }
409
+
410
+ // src/utils/guards.ts
411
+ var guards_exports = {};
412
+ __export(guards_exports, {
413
+ hasFunctionCall: () => hasFunctionCall,
414
+ hasToolCall: () => hasToolCall,
415
+ isAssistantMessage: () => isAssistantMessage,
416
+ isFunctionCall: () => isFunctionCall,
417
+ isOutputResult: () => isOutputResult,
418
+ isOutputResultContentText: () => isOutputResultContentText,
419
+ isSystemMessage: () => isSystemMessage,
420
+ isToolCall: () => isToolCall,
421
+ isUserMessage: () => isUserMessage
422
+ });
423
+ function isOutputResult(obj) {
424
+ return !!(obj && typeof obj === "object" && "id" in obj && "stopReason" in obj && "content" in obj && Array.isArray(obj.content));
425
+ }
426
+ function isOutputResultContentText(obj) {
427
+ return !!(obj && typeof obj === "object" && "text" in obj && "type" in obj && obj.type === "text" && typeof obj.text === "string");
428
+ }
429
+ function isFunctionCall(result) {
430
+ return !!(result && typeof result === "object" && "functionId" in result && "type" in result && result.type === "function_use");
431
+ }
432
+ function isToolCall(result) {
433
+ return isFunctionCall(result);
434
+ }
435
+ function hasFunctionCall(results) {
436
+ return !!(results && Array.isArray(results) && results.some(isToolCall));
437
+ }
438
+ function hasToolCall(results) {
439
+ return hasFunctionCall(results);
440
+ }
441
+ function isUserMessage(message) {
442
+ return message.role === "user";
443
+ }
444
+ function isAssistantMessage(message) {
445
+ return message.role === "assistant" || message.role === "model";
446
+ }
447
+ function isSystemMessage(message) {
448
+ return message.role === "system";
449
+ }
450
+
451
+ // src/parser/parsers/StringParser.ts
452
+ var StringParser = class extends BaseParser {
453
+ constructor(options) {
454
+ super("string", options);
455
+ }
456
+ parse(text, _options) {
457
+ if (isOutputResult(text)) {
458
+ return text.content?.[0]?.text ?? "";
459
+ }
460
+ assert(
461
+ typeof text === "string",
462
+ `Invalid input. Expected string. Received ${typeof text}.`
463
+ );
464
+ const parsed = text.toString();
465
+ return parsed;
466
+ }
467
+ };
468
+
469
+ // src/parser/parsers/BooleanParser.ts
470
+ var BooleanParser = class extends BaseParser {
471
+ constructor(options) {
472
+ super("boolean", options);
473
+ }
474
+ parse(text) {
475
+ assert(
476
+ typeof text === "string",
477
+ `Invalid input. Expected string. Received ${typeof text}.`
478
+ );
479
+ const clean = text.toLowerCase().trim();
480
+ if (clean === "true") {
481
+ return true;
482
+ }
483
+ return false;
484
+ }
485
+ };
486
+
487
+ // src/utils/modules/isFinite.ts
488
+ function isFinite(value) {
489
+ return typeof value === "number" && Number.isFinite(value);
490
+ }
491
+
492
+ // src/utils/modules/toNumber.ts
493
+ function toNumber(value) {
494
+ if (typeof value === "number") {
495
+ return value;
496
+ }
497
+ if (typeof value === "string" && value.trim() !== "") {
498
+ return Number(value);
499
+ }
500
+ return NaN;
501
+ }
502
+
503
+ // src/parser/parsers/NumberParser.ts
504
+ var NumberParser = class extends BaseParser {
505
+ constructor(options) {
506
+ super("number", options);
507
+ }
508
+ parse(text) {
509
+ const match = text.match(/\d/g);
510
+ return match && isFinite(toNumber(match[0])) ? toNumber(match[0]) : -1;
511
+ }
512
+ };
513
+
393
514
  // src/utils/index.ts
394
515
  var utils_exports = {};
395
516
  __export(utils_exports, {
@@ -409,19 +530,6 @@ __export(utils_exports, {
409
530
  replaceTemplateStringAsync: () => replaceTemplateStringAsync
410
531
  });
411
532
 
412
- // src/utils/modules/assert.ts
413
- function assert(condition, message) {
414
- if (condition === void 0 || condition === null || condition === false) {
415
- if (typeof message === "string") {
416
- throw new Error(message);
417
- } else if (message instanceof Error) {
418
- throw message;
419
- } else {
420
- throw new Error(`Assertion error`);
421
- }
422
- }
423
- }
424
-
425
533
  // src/utils/modules/defineSchema.ts
426
534
  var import_json_schema_to_ts = require("json-schema-to-ts");
427
535
  function defineSchema(obj) {
@@ -467,17 +575,6 @@ function importHelpers(_helpers) {
467
575
  return helpers;
468
576
  }
469
577
 
470
- // src/utils/modules/toNumber.ts
471
- function toNumber(value) {
472
- if (typeof value === "number") {
473
- return value;
474
- }
475
- if (typeof value === "string" && value.trim() !== "") {
476
- return Number(value);
477
- }
478
- return NaN;
479
- }
480
-
481
578
  // src/utils/modules/get.ts
482
579
  function get(obj, path, defaultValue) {
483
580
  if (obj == null || path === "" || Array.isArray(path) && path.length === 0) {
@@ -1377,82 +1474,6 @@ function registerPartials(partials2) {
1377
1474
  hbsAsync.registerPartials(partials2);
1378
1475
  }
1379
1476
 
1380
- // src/llm/output/_utils/getResultText.ts
1381
- function getResultText(content) {
1382
- if (content.length === 1 && content.every((a) => a.type === "text")) {
1383
- return content[0]?.text || "";
1384
- }
1385
- return "";
1386
- }
1387
-
1388
- // src/parser/parsers/OpenAiFunctionParser.ts
1389
- var OpenAiFunctionParser = class extends BaseParser {
1390
- constructor(options) {
1391
- super("openAiFunction", options, "function_call");
1392
- __publicField(this, "parser");
1393
- this.parser = options.parser;
1394
- }
1395
- parse(text, _options) {
1396
- const functionUse = text?.find((a) => a.type === "function_use");
1397
- if (functionUse && "name" in functionUse && "input" in functionUse) {
1398
- return {
1399
- name: functionUse.name,
1400
- arguments: maybeParseJSON(functionUse.input)
1401
- };
1402
- }
1403
- return this.parser.parse(getResultText(text));
1404
- }
1405
- };
1406
-
1407
- // src/parser/parsers/StringParser.ts
1408
- var StringParser = class extends BaseParser {
1409
- constructor(options) {
1410
- super("string", options);
1411
- }
1412
- parse(text, _options) {
1413
- assert(
1414
- typeof text === "string",
1415
- `Invalid input. Expected string. Received ${typeof text}.`
1416
- );
1417
- const parsed = text.toString();
1418
- return parsed;
1419
- }
1420
- };
1421
-
1422
- // src/parser/parsers/BooleanParser.ts
1423
- var BooleanParser = class extends BaseParser {
1424
- constructor(options) {
1425
- super("boolean", options);
1426
- }
1427
- parse(text) {
1428
- assert(
1429
- typeof text === "string",
1430
- `Invalid input. Expected string. Received ${typeof text}.`
1431
- );
1432
- const clean = text.toLowerCase().trim();
1433
- if (clean === "true") {
1434
- return true;
1435
- }
1436
- return false;
1437
- }
1438
- };
1439
-
1440
- // src/utils/modules/isFinite.ts
1441
- function isFinite(value) {
1442
- return typeof value === "number" && Number.isFinite(value);
1443
- }
1444
-
1445
- // src/parser/parsers/NumberParser.ts
1446
- var NumberParser = class extends BaseParser {
1447
- constructor(options) {
1448
- super("number", options);
1449
- }
1450
- parse(text) {
1451
- const match = text.match(/\d/g);
1452
- return match && isFinite(toNumber(match[0])) ? toNumber(match[0]) : -1;
1453
- }
1454
- };
1455
-
1456
1477
  // src/parser/_utils.ts
1457
1478
  var import_jsonschema = require("jsonschema");
1458
1479
  function enforceParserSchema(schema, parsed) {
@@ -1745,6 +1766,46 @@ function createCustomParser(name, parserFn) {
1745
1766
  return new CustomParser(name, parserFn);
1746
1767
  }
1747
1768
 
1769
+ // src/parser/parsers/LlmNativeFunctionParser.ts
1770
+ var LlmFunctionParser = class extends BaseParser {
1771
+ constructor(options) {
1772
+ super("functionCall", options, "function_call");
1773
+ __publicField(this, "parser");
1774
+ this.parser = options.parser;
1775
+ }
1776
+ parse(text, _options) {
1777
+ if (typeof text === "string") {
1778
+ return this.parser.parse(text);
1779
+ }
1780
+ const { content } = text;
1781
+ const functionUses = content?.filter((a) => a.type === "function_use") || [];
1782
+ if (functionUses.length === 0) {
1783
+ const [item] = content;
1784
+ return this.parser.parse(item.text);
1785
+ }
1786
+ return content;
1787
+ }
1788
+ };
1789
+ var LlmNativeFunctionParser = class extends BaseParser {
1790
+ constructor(options) {
1791
+ super("openAiFunction", options, "function_call");
1792
+ __publicField(this, "parser");
1793
+ this.parser = options.parser;
1794
+ }
1795
+ parse(text, _options) {
1796
+ const { content } = text;
1797
+ const functionUse = content?.find((a) => a.type === "function_use");
1798
+ if (functionUse && "name" in functionUse && "input" in functionUse) {
1799
+ return {
1800
+ name: functionUse.name,
1801
+ arguments: maybeParseJSON(functionUse.input)
1802
+ };
1803
+ }
1804
+ return this.parser.parse(text?.text ?? text);
1805
+ }
1806
+ };
1807
+ var OpenAiFunctionParser = LlmNativeFunctionParser;
1808
+
1748
1809
  // src/executor/llm.ts
1749
1810
  var LlmExecutor = class extends BaseExecutor {
1750
1811
  constructor(llmConfiguration, options) {
@@ -1800,7 +1861,7 @@ var LlmExecutor = class extends BaseExecutor {
1800
1861
  }
1801
1862
  getHandlerOutput(out, _metadata) {
1802
1863
  if (this.parser.target === "function_call") {
1803
- const outToStr = out.getResultContent();
1864
+ const outToStr = out.getResult();
1804
1865
  return this.parser.parse(outToStr, _metadata);
1805
1866
  } else {
1806
1867
  const outToStr = out.getResultText();
@@ -1820,31 +1881,55 @@ var LlmExecutor = class extends BaseExecutor {
1820
1881
  }
1821
1882
  };
1822
1883
 
1823
- // src/executor/_functions.ts
1824
- function createCoreExecutor(handler, options) {
1825
- return new CoreExecutor({ handler }, options);
1826
- }
1827
- function createLlmExecutor(llmConfiguration, options) {
1828
- return new LlmExecutor(llmConfiguration, options);
1829
- }
1830
-
1831
1884
  // src/executor/llm-openai-function.ts
1885
+ var LlmExecutorWithFunctions = class extends LlmExecutor {
1886
+ constructor(llmConfiguration, options) {
1887
+ super(
1888
+ Object.assign({}, llmConfiguration, {
1889
+ parser: new LlmFunctionParser({
1890
+ parser: llmConfiguration.parser || new StringParser()
1891
+ })
1892
+ }),
1893
+ options
1894
+ );
1895
+ }
1896
+ async execute(_input, _options) {
1897
+ return super.execute(_input, _options);
1898
+ }
1899
+ };
1832
1900
  var LlmExecutorOpenAiFunctions = class extends LlmExecutor {
1833
1901
  constructor(llmConfiguration, options) {
1834
1902
  super(
1835
1903
  Object.assign({}, llmConfiguration, {
1836
- parser: new OpenAiFunctionParser({
1904
+ parser: new LlmNativeFunctionParser({
1837
1905
  parser: llmConfiguration.parser || new StringParser()
1838
1906
  })
1839
1907
  }),
1840
1908
  options
1841
1909
  );
1910
+ console.warn(
1911
+ `LlmExecutorOpenAiFunctions is deprecated. Please migrate to LlmExecutorWithFunctions`
1912
+ );
1842
1913
  }
1843
1914
  async execute(_input, _options) {
1844
1915
  return super.execute(_input, _options);
1845
1916
  }
1846
1917
  };
1847
1918
 
1919
+ // src/executor/_functions.ts
1920
+ function createCoreExecutor(handler, options) {
1921
+ return new CoreExecutor({ handler }, options);
1922
+ }
1923
+ function createLlmExecutor(llmConfiguration, options) {
1924
+ return new LlmExecutor(llmConfiguration, options);
1925
+ }
1926
+ function createLlmFunctionExecutor(llmConfiguration, options) {
1927
+ return new LlmExecutorWithFunctions(
1928
+ llmConfiguration,
1929
+ options
1930
+ );
1931
+ }
1932
+
1848
1933
  // src/utils/modules/enforceResultAttributes.ts
1849
1934
  function enforceResultAttributes(input) {
1850
1935
  if (!input) {
@@ -2033,6 +2118,39 @@ function getEnvironmentVariable(name) {
2033
2118
  }
2034
2119
  }
2035
2120
 
2121
+ // src/llm/config/openai/promptSanitizeMessageCallback.ts
2122
+ function openaiPromptMessageCallback(_message) {
2123
+ let message = { ..._message };
2124
+ if (message.role === "function") {
2125
+ message.role = "tool";
2126
+ message.tool_call_id = message.id;
2127
+ delete message.id;
2128
+ }
2129
+ if (message?.function_call) {
2130
+ const { function_call } = message;
2131
+ const toolsArr = Array.isArray(function_call) ? function_call : [function_call];
2132
+ message.role = "assistant";
2133
+ message.tool_calls = toolsArr.map((call) => {
2134
+ const { id, ...functionCall } = call;
2135
+ return {
2136
+ id,
2137
+ type: "function",
2138
+ function: functionCall
2139
+ };
2140
+ });
2141
+ delete message.function_call;
2142
+ }
2143
+ return message;
2144
+ }
2145
+
2146
+ // src/llm/config/openai/promptSanitize.ts
2147
+ function openaiPromptSanitize(_messages, _inputBodyObj, _outputObj) {
2148
+ if (typeof _messages === "string") {
2149
+ return [{ role: "user", content: _messages }];
2150
+ }
2151
+ return _messages.map(openaiPromptMessageCallback);
2152
+ }
2153
+
2036
2154
  // src/llm/config/openai/index.ts
2037
2155
  var openAiChatV1 = {
2038
2156
  key: "openai.chat.v1",
@@ -2051,12 +2169,7 @@ var openAiChatV1 = {
2051
2169
  mapBody: {
2052
2170
  prompt: {
2053
2171
  key: "messages",
2054
- sanitize: (v) => {
2055
- if (typeof v === "string") {
2056
- return [{ role: "user", content: v }];
2057
- }
2058
- return v;
2059
- }
2172
+ sanitize: openaiPromptSanitize
2060
2173
  },
2061
2174
  model: {
2062
2175
  key: "model"
@@ -2107,14 +2220,54 @@ var openai = {
2107
2220
  "openai.gpt-4o-mini": withDefaultModel(openAiChatV1, "gpt-4o-mini")
2108
2221
  };
2109
2222
 
2223
+ // src/llm/config/anthropic/promptSanitizeMessageCallback.ts
2224
+ function anthropicPromptMessageCallback(_message) {
2225
+ let message = { ..._message };
2226
+ if (message.role === "function") {
2227
+ message.role = "user";
2228
+ message.content = [
2229
+ {
2230
+ type: "tool_result",
2231
+ tool_use_id: message.id,
2232
+ content: maybeStringifyJSON(message.content)
2233
+ }
2234
+ ];
2235
+ delete message.name;
2236
+ delete message.id;
2237
+ }
2238
+ if (message?.function_call) {
2239
+ const { function_call } = message;
2240
+ const toolsArr = Array.isArray(function_call) ? function_call : [function_call];
2241
+ message.role = "assistant";
2242
+ message.content = toolsArr.map((call) => {
2243
+ const { id, name, arguments: input } = call;
2244
+ return {
2245
+ type: "tool_use",
2246
+ id,
2247
+ name,
2248
+ input: maybeParseJSON(input)
2249
+ };
2250
+ });
2251
+ delete message.function_call;
2252
+ }
2253
+ return message;
2254
+ }
2255
+
2110
2256
  // src/llm/config/anthropic/promptSanitize.ts
2111
2257
  function anthropicPromptSanitize(_messages, _inputBodyObj, _outputObj) {
2112
2258
  if (typeof _messages === "string") {
2113
- return [{ role: "user", content: _messages }];
2259
+ return [{ role: "user", content: _messages }].map(
2260
+ anthropicPromptMessageCallback
2261
+ );
2114
2262
  }
2115
- const [first, ...messages] = [..._messages.map((a) => ({ ...a }))];
2263
+ const [first, ...messages] = [
2264
+ ..._messages.map((a) => ({ ...a }))
2265
+ ];
2116
2266
  if (first.role === "system" && messages.length === 0) {
2117
- return [{ role: "user", content: first.content }, ...messages];
2267
+ return [
2268
+ { role: "user", content: first.content },
2269
+ ...messages
2270
+ ].map(anthropicPromptMessageCallback);
2118
2271
  }
2119
2272
  if (first.role === "system" && messages.length > 0) {
2120
2273
  _outputObj.system = first.content;
@@ -2123,7 +2276,7 @@ function anthropicPromptSanitize(_messages, _inputBodyObj, _outputObj) {
2123
2276
  return { ...m, role: "user" };
2124
2277
  }
2125
2278
  return m;
2126
- });
2279
+ }).map(anthropicPromptMessageCallback);
2127
2280
  }
2128
2281
  return [
2129
2282
  first,
@@ -2133,7 +2286,7 @@ function anthropicPromptSanitize(_messages, _inputBodyObj, _outputObj) {
2133
2286
  }
2134
2287
  return m;
2135
2288
  })
2136
- ];
2289
+ ].map(anthropicPromptMessageCallback);
2137
2290
  }
2138
2291
 
2139
2292
  // src/llm/config/bedrock/index.ts
@@ -2352,30 +2505,49 @@ var ollama = {
2352
2505
  "ollama.qwq": withDefaultModel(ollamaChatV1, "qwq")
2353
2506
  };
2354
2507
 
2355
- // src/utils/modules/modifyPromptRoleChange.ts
2356
- function modifyPromptRoleChange(messages, roleChanges) {
2357
- const roleChangeMap = new Map(roleChanges.map(({ from, to }) => [from, to]));
2358
- if (Array.isArray(messages)) {
2359
- return messages.map((message) => {
2360
- const newRole2 = roleChangeMap.get(message.role);
2361
- return newRole2 ? { ...message, role: newRole2 } : message;
2362
- });
2363
- }
2364
- const newRole = roleChangeMap.get(messages.role);
2365
- return newRole ? { ...messages, role: newRole } : messages;
2366
- }
2367
-
2368
2508
  // src/llm/config/google/promptSanitizeMessageCallback.ts
2369
2509
  function googleGeminiPromptMessageCallback(_message) {
2370
2510
  let message = { ..._message };
2371
- message = modifyPromptRoleChange(_message, [
2372
- { from: "assistant", to: "model" }
2373
- ]);
2374
- const { role, ...payload } = message;
2375
2511
  const parts = [];
2512
+ if (message.role === "assistant") {
2513
+ message.role = "model";
2514
+ }
2515
+ if (message.role === "system") {
2516
+ message.role = "model";
2517
+ }
2518
+ let { role, ...payload } = message;
2376
2519
  if (typeof payload.content === "string") {
2377
2520
  parts.push({ text: message.content });
2378
2521
  }
2522
+ if (message.role === "function") {
2523
+ role = "user";
2524
+ parts.push({
2525
+ functionResponse: {
2526
+ name: message.name,
2527
+ response: {
2528
+ result: message.content
2529
+ }
2530
+ }
2531
+ });
2532
+ delete message.id;
2533
+ }
2534
+ if (message?.function_call) {
2535
+ const { function_call } = message;
2536
+ const toolsArr = Array.isArray(function_call) ? function_call : [function_call];
2537
+ role = "model";
2538
+ parts.push(
2539
+ ...toolsArr.map((call) => {
2540
+ const { name, arguments: input } = call;
2541
+ return {
2542
+ functionCall: {
2543
+ name,
2544
+ args: maybeParseJSON(input)
2545
+ }
2546
+ };
2547
+ })
2548
+ );
2549
+ delete message.function_call;
2550
+ }
2379
2551
  return {
2380
2552
  role,
2381
2553
  parts
@@ -2405,7 +2577,9 @@ function googleGeminiPromptSanitize(_messages, _inputBodyObj, _outputObj) {
2405
2577
  (message) => message.role !== "system"
2406
2578
  );
2407
2579
  _outputObj.system_instruction = {
2408
- parts: theSystemInstructions.map((message) => ({ text: message.content }))
2580
+ parts: theSystemInstructions.map((message) => ({
2581
+ text: message.content
2582
+ }))
2409
2583
  };
2410
2584
  return withoutSystemInstructions.map(googleGeminiPromptMessageCallback);
2411
2585
  }
@@ -2526,7 +2700,7 @@ function getLlmConfig(provider) {
2526
2700
 
2527
2701
  // src/llm/output/_utils/getResultContent.ts
2528
2702
  function getResultContent(result, index) {
2529
- if (index && index > 0) {
2703
+ if (typeof index === "number" && index > 0) {
2530
2704
  const arr = result?.options || [];
2531
2705
  const val = arr[index];
2532
2706
  return val ? val : [];
@@ -2534,6 +2708,16 @@ function getResultContent(result, index) {
2534
2708
  return [...result.content];
2535
2709
  }
2536
2710
 
2711
+ // src/llm/output/_utils/getResultText.ts
2712
+ function getResultText(result, index) {
2713
+ if (typeof index === "number" && index > 0) {
2714
+ const arr = result?.options || [];
2715
+ const val = arr[index];
2716
+ return isOutputResultContentText(val?.[0]) ? val[0]?.text : "";
2717
+ }
2718
+ return isOutputResultContentText(result?.content?.[0]) ? result.content[0]?.text : "";
2719
+ }
2720
+
2537
2721
  // src/llm/output/base.ts
2538
2722
  function BaseLlmOutput2(result) {
2539
2723
  const __result = Object.freeze({
@@ -2558,7 +2742,7 @@ function BaseLlmOutput2(result) {
2558
2742
  }
2559
2743
  return {
2560
2744
  getResultContent: (index) => getResultContent(__result, index),
2561
- getResultText: () => getResultText(__result.content),
2745
+ getResultText: (index) => getResultText(__result, index),
2562
2746
  getResult
2563
2747
  };
2564
2748
  }
@@ -2593,25 +2777,24 @@ function formatContent(response, handler) {
2593
2777
 
2594
2778
  // src/llm/output/openai.ts
2595
2779
  function formatResult(result) {
2780
+ const out = [];
2596
2781
  if (typeof result?.message?.content === "string") {
2597
- return {
2782
+ out.push({
2598
2783
  type: "text",
2599
2784
  text: result.message.content
2600
- };
2601
- } else if (result?.message && "tool_calls" in result.message) {
2602
- const tool_calls = result.message.tool_calls;
2603
- for (const call of tool_calls) {
2604
- return {
2785
+ });
2786
+ }
2787
+ if (result?.message?.tool_calls) {
2788
+ for (const call of result.message.tool_calls) {
2789
+ out.push({
2790
+ functionId: call.id,
2605
2791
  type: "function_use",
2606
2792
  name: call.function.name,
2607
- input: JSON.parse(call.function.arguments)
2608
- };
2793
+ input: maybeParseJSON(call.function.arguments)
2794
+ });
2609
2795
  }
2610
2796
  }
2611
- return {
2612
- type: "text",
2613
- text: ""
2614
- };
2797
+ return out;
2615
2798
  }
2616
2799
  function OutputOpenAIChat(result, _config) {
2617
2800
  const id = result.id;
@@ -2619,7 +2802,7 @@ function OutputOpenAIChat(result, _config) {
2619
2802
  const created = result.created;
2620
2803
  const [_content, ..._options] = result?.choices || [];
2621
2804
  const stopReason = _content?.finish_reason;
2622
- const content = formatContent(_content, formatResult);
2805
+ const content = formatResult(_content);
2623
2806
  const options = formatOptions(_options, formatResult);
2624
2807
  const usage = {
2625
2808
  output_tokens: result?.usage?.completion_tokens,
@@ -2650,6 +2833,7 @@ function formatResult2(response) {
2650
2833
  });
2651
2834
  } else if (result.type === "tool_use") {
2652
2835
  out.push({
2836
+ functionId: result.id,
2653
2837
  type: "function_use",
2654
2838
  name: result.name,
2655
2839
  input: result.input
@@ -2727,12 +2911,15 @@ function formatResult3(result) {
2727
2911
  };
2728
2912
  } else if (result?.message && "tool_calls" in result.message) {
2729
2913
  const tool_calls = result.message.tool_calls;
2730
- for (const call of tool_calls) {
2731
- return {
2732
- type: "function_use",
2733
- name: call.function.name,
2734
- input: JSON.parse(call.function.arguments)
2735
- };
2914
+ if (tool_calls) {
2915
+ for (const call of tool_calls) {
2916
+ return {
2917
+ functionId: call.id,
2918
+ type: "function_use",
2919
+ name: call.function.name,
2920
+ input: JSON.parse(call.function.arguments)
2921
+ };
2922
+ }
2736
2923
  }
2737
2924
  }
2738
2925
  return {
@@ -2837,37 +3024,36 @@ function OutputOllamaChat(result, _config) {
2837
3024
  }
2838
3025
 
2839
3026
  // src/llm/output/google.gemini/formatResult.ts
2840
- function formatResult4(result) {
3027
+ function formatResult4(result, id) {
2841
3028
  const { parts = [] } = result?.content || {};
2842
- if (parts.length === 1) {
2843
- const answer = parts[0];
2844
- if (!!answer?.functionCall && typeof answer?.functionCall === "object") {
2845
- return {
2846
- type: "function_use",
2847
- name: answer.functionCall.name,
2848
- input: JSON.parse(answer.functionCall.args)
2849
- };
2850
- } else {
2851
- return {
3029
+ const out = [];
3030
+ for (let i = 0; i < parts.length; i++) {
3031
+ const part = parts[i];
3032
+ if (typeof part.text === "string") {
3033
+ out.push({
2852
3034
  type: "text",
2853
- text: answer.text || ""
2854
- };
3035
+ text: part.text
3036
+ });
3037
+ } else if (part?.functionCall) {
3038
+ out.push({
3039
+ functionId: `${id || (0, import_uuid.v4)()}-${i}`,
3040
+ type: "function_use",
3041
+ name: part.functionCall.name,
3042
+ input: maybeParseJSON(part.functionCall.args)
3043
+ });
2855
3044
  }
2856
3045
  }
2857
- return {
2858
- type: "text",
2859
- text: ""
2860
- };
3046
+ return out;
2861
3047
  }
2862
3048
 
2863
3049
  // src/llm/output/google.gemini/index.ts
2864
3050
  function OutputGoogleGeminiChat(result, _config) {
2865
- const id = "result.id";
2866
- const name = result.modelVersion;
3051
+ const id = result.responseId;
3052
+ const name = result.modelVersion || _config?.model || "gemini";
2867
3053
  const created = (/* @__PURE__ */ new Date()).getTime();
2868
3054
  const [_content, ..._options] = result?.candidates || [];
2869
3055
  const stopReason = _content?.finishReason?.toLowerCase();
2870
- const content = formatContent(_content, formatResult4);
3056
+ const content = formatResult4(_content, id);
2871
3057
  const options = formatOptions(_options, formatResult4);
2872
3058
  const usage = {
2873
3059
  output_tokens: result?.usageMetadata?.candidatesTokenCount,
@@ -2886,7 +3072,7 @@ function OutputGoogleGeminiChat(result, _config) {
2886
3072
  }
2887
3073
 
2888
3074
  // src/llm/output/index.ts
2889
- function getOutputParser(config, response) {
3075
+ function normalizeLlmOutputToInternalFormat(config, response) {
2890
3076
  switch (config?.key) {
2891
3077
  case "openai.chat.v1":
2892
3078
  case "openai.chat-mock.v1":
@@ -3134,11 +3320,20 @@ async function parseHeaders(config, replacements, payload) {
3134
3320
 
3135
3321
  // src/llm/output/_utils/cleanJsonSchemaFor.ts
3136
3322
  var providerFieldExclusions = {
3137
- "openai.chat": ["default"]
3323
+ "openai.chat": ["default"],
3324
+ // fields to exclude for openai.chat
3325
+ "anthropic.chat": []
3138
3326
  // fields to exclude for openai.chat
3139
3327
  };
3140
3328
  function cleanJsonSchemaFor(schema = {}, provider) {
3141
3329
  const clone = deepClone(schema);
3330
+ if (Object.keys(clone).length === 0) {
3331
+ return {
3332
+ type: "object",
3333
+ properties: {},
3334
+ required: []
3335
+ };
3336
+ }
3142
3337
  const exclusions = providerFieldExclusions[provider] || [];
3143
3338
  function removeDisallowedFields(obj) {
3144
3339
  if (Array.isArray(obj)) {
@@ -3167,7 +3362,7 @@ async function useLlm_call(state, messages, _options) {
3167
3362
  })
3168
3363
  );
3169
3364
  if (_options && _options?.jsonSchema) {
3170
- if (state.provider === "openai.chat") {
3365
+ if (state.provider.startsWith("openai")) {
3171
3366
  const curr = input["response_format"] || {};
3172
3367
  input["response_format"] = Object.assign(curr, {
3173
3368
  type: "json_schema",
@@ -3180,7 +3375,7 @@ async function useLlm_call(state, messages, _options) {
3180
3375
  }
3181
3376
  }
3182
3377
  if (_options && _options?.functionCall) {
3183
- if (state.provider === "anthropic.chat") {
3378
+ if (state.provider.startsWith("anthropic")) {
3184
3379
  if (_options?.functionCall === "none") {
3185
3380
  _options.functions = [];
3186
3381
  } else if (_options?.functionCall === "auto" || _options?.functionCall === "any") {
@@ -3188,21 +3383,27 @@ async function useLlm_call(state, messages, _options) {
3188
3383
  } else {
3189
3384
  input["tool_choice"] = _options?.functionCall;
3190
3385
  }
3191
- } else if (state.provider === "openai.chat") {
3386
+ } else if (state.provider.startsWith("openai")) {
3192
3387
  input["tool_choice"] = normalizeFunctionCall(
3193
3388
  _options?.functionCall,
3194
3389
  "openai"
3195
3390
  );
3391
+ } else if (state.provider.startsWith("google")) {
3392
+ input["toolConfig"] = {
3393
+ functionCallingConfig: {
3394
+ mode: normalizeFunctionCall(_options?.functionCall, "google")
3395
+ }
3396
+ };
3196
3397
  }
3197
3398
  }
3198
3399
  if (_options && _options?.functions?.length) {
3199
- if (state.provider === "anthropic.chat") {
3400
+ if (state.provider.startsWith("anthropic")) {
3200
3401
  input["tools"] = _options.functions.map((f) => ({
3201
3402
  name: f.name,
3202
3403
  description: f.description,
3203
- input_schema: f.parameters
3404
+ input_schema: cleanJsonSchemaFor(f.parameters, "anthropic.chat")
3204
3405
  }));
3205
- } else if (state.provider === "openai.chat") {
3406
+ } else if (state.provider.startsWith("openai")) {
3206
3407
  input["tools"] = _options.functions.map((f) => {
3207
3408
  const props = {
3208
3409
  name: f?.name,
@@ -3220,6 +3421,16 @@ async function useLlm_call(state, messages, _options) {
3220
3421
  )
3221
3422
  };
3222
3423
  });
3424
+ } else if (state.provider.startsWith("google")) {
3425
+ input["tools"] = [
3426
+ {
3427
+ functionDeclarations: _options.functions.map((f) => ({
3428
+ name: f.name,
3429
+ description: f.description,
3430
+ parameters: cleanJsonSchemaFor(f.parameters, "google.chat")
3431
+ }))
3432
+ }
3433
+ ];
3223
3434
  }
3224
3435
  }
3225
3436
  const body = JSON.stringify(input);
@@ -3249,7 +3460,7 @@ async function useLlm_call(state, messages, _options) {
3249
3460
  body,
3250
3461
  headers
3251
3462
  });
3252
- return getOutputParser(state, response);
3463
+ return normalizeLlmOutputToInternalFormat(state, response);
3253
3464
  }
3254
3465
 
3255
3466
  // src/llm/_utils.stateFromOptions.ts
@@ -3821,7 +4032,7 @@ var ChatPrompt = class extends BasePrompt {
3821
4032
  this.parseUserTemplates = options?.allowUnsafeUserTemplate;
3822
4033
  }
3823
4034
  }
3824
- addToPrompt(content, role, name) {
4035
+ addToPrompt(content, role, name, id) {
3825
4036
  if (content) {
3826
4037
  switch (role) {
3827
4038
  case "system":
@@ -3835,11 +4046,11 @@ var ChatPrompt = class extends BasePrompt {
3835
4046
  break;
3836
4047
  case "function":
3837
4048
  assert(name, "Function message requires name");
3838
- this.addFunctionMessage(content, name);
4049
+ this.addFunctionMessage(content, name, id);
3839
4050
  break;
3840
4051
  case "function_call":
3841
4052
  assert(name, "Function message requires name");
3842
- this.addFunctionCallMessage({ name, arguments: content });
4053
+ this.addFunctionCallMessage({ name, arguments: content, id });
3843
4054
  break;
3844
4055
  }
3845
4056
  }
@@ -3879,11 +4090,12 @@ var ChatPrompt = class extends BasePrompt {
3879
4090
  * @param content The message content.
3880
4091
  * @return ChatPrompt so it can be chained.
3881
4092
  */
3882
- addFunctionMessage(content, name) {
4093
+ addFunctionMessage(content, name, id) {
3883
4094
  this.messages.push({
3884
4095
  role: "function",
3885
4096
  name,
3886
- content
4097
+ content,
4098
+ id
3887
4099
  });
3888
4100
  return this;
3889
4101
  }
@@ -3895,8 +4107,9 @@ var ChatPrompt = class extends BasePrompt {
3895
4107
  addFunctionCallMessage(function_call) {
3896
4108
  if (function_call) {
3897
4109
  this.messages.push({
3898
- role: "assistant",
4110
+ role: "function_call",
3899
4111
  function_call: {
4112
+ id: function_call.id,
3900
4113
  name: function_call.name,
3901
4114
  arguments: maybeStringifyJSON(function_call.arguments)
3902
4115
  },
@@ -3918,17 +4131,16 @@ var ChatPrompt = class extends BasePrompt {
3918
4131
  this.addUserMessage(message.content, message?.name);
3919
4132
  break;
3920
4133
  case "assistant":
3921
- if (message.function_call) {
3922
- this.addFunctionCallMessage(message.function_call);
3923
- } else if (message?.content) {
3924
- this.addAssistantMessage(message?.content);
3925
- }
4134
+ this.addAssistantMessage(message?.content);
3926
4135
  break;
3927
4136
  case "system":
3928
4137
  this.addSystemMessage(message.content);
3929
4138
  break;
4139
+ case "function_call":
4140
+ this.addFunctionCallMessage(message.function_call);
4141
+ break;
3930
4142
  case "function":
3931
- this.addFunctionMessage(message.content, message.name);
4143
+ this.addFunctionMessage(message.content, message.name, message.id);
3932
4144
  break;
3933
4145
  }
3934
4146
  }
@@ -3992,20 +4204,19 @@ var ChatPrompt = class extends BasePrompt {
3992
4204
  break;
3993
4205
  }
3994
4206
  case "assistant": {
3995
- if (message.function_call) {
3996
- messagesOut.push({
3997
- role: "assistant",
3998
- content: null,
3999
- function_call: message.function_call
4000
- });
4001
- } else if (message?.content) {
4002
- messagesOut.push({
4003
- role: "assistant",
4004
- content: message.content
4005
- });
4006
- }
4207
+ messagesOut.push({
4208
+ role: "assistant",
4209
+ content: message.content
4210
+ });
4007
4211
  break;
4008
4212
  }
4213
+ case "function_call":
4214
+ messagesOut.push({
4215
+ role: "function_call",
4216
+ content: null,
4217
+ function_call: message.function_call
4218
+ });
4219
+ break;
4009
4220
  case "function":
4010
4221
  messagesOut.push({
4011
4222
  role: "function",
@@ -4184,20 +4395,19 @@ var ChatPrompt = class extends BasePrompt {
4184
4395
  break;
4185
4396
  }
4186
4397
  case "assistant": {
4187
- if (message2.function_call) {
4188
- messagesOut.push({
4189
- role: "assistant",
4190
- content: null,
4191
- function_call: message2.function_call
4192
- });
4193
- } else if (message2?.content) {
4194
- messagesOut.push({
4195
- role: "assistant",
4196
- content: message2.content
4197
- });
4198
- }
4398
+ messagesOut.push({
4399
+ role: "assistant",
4400
+ content: message2.content
4401
+ });
4199
4402
  break;
4200
4403
  }
4404
+ case "function_call":
4405
+ messagesOut.push({
4406
+ role: "function_call",
4407
+ content: null,
4408
+ function_call: message2.function_call
4409
+ });
4410
+ break;
4201
4411
  case "function":
4202
4412
  messagesOut.push({
4203
4413
  role: "function",
@@ -4421,10 +4631,17 @@ var Dialogue = class extends BaseStateItem {
4421
4631
  }
4422
4632
  setAssistantMessage(content) {
4423
4633
  if (content) {
4424
- this.value.push({
4425
- role: "assistant",
4426
- content
4427
- });
4634
+ if (isOutputResultContentText(content)) {
4635
+ this.value.push({
4636
+ role: "assistant",
4637
+ content: content.text
4638
+ });
4639
+ } else {
4640
+ this.value.push({
4641
+ role: "assistant",
4642
+ content
4643
+ });
4644
+ }
4428
4645
  }
4429
4646
  return this;
4430
4647
  }
@@ -4437,22 +4654,57 @@ var Dialogue = class extends BaseStateItem {
4437
4654
  }
4438
4655
  return this;
4439
4656
  }
4440
- setFunctionMessage(content, name) {
4657
+ setToolMessage(content, name, id) {
4658
+ this.setFunctionMessage(content, name, id);
4659
+ }
4660
+ setFunctionMessage(content, name, id) {
4441
4661
  if (content) {
4442
4662
  this.value.push({
4443
4663
  role: "function",
4664
+ id,
4444
4665
  name,
4445
4666
  content
4446
4667
  });
4447
4668
  }
4448
4669
  return this;
4449
4670
  }
4671
+ /**
4672
+ * Set
4673
+ */
4674
+ setToolCallMessage(input) {
4675
+ this.setFunctionCallMessage(input);
4676
+ }
4450
4677
  setFunctionCallMessage(input) {
4678
+ if (!input || typeof input !== "object") {
4679
+ throw new LlmExeError(`Invalid arguments`, "state", {
4680
+ error: `Invalid arguments: input must be an object`,
4681
+ module: "dialogue"
4682
+ });
4683
+ }
4684
+ if ("function_call" in input) {
4685
+ if (!input.function_call || typeof input.function_call !== "object") {
4686
+ throw new LlmExeError(`Invalid arguments`, "state", {
4687
+ error: `Invalid arguments: input must be an object`,
4688
+ module: "dialogue"
4689
+ });
4690
+ }
4691
+ this.value.push({
4692
+ role: "function_call",
4693
+ function_call: {
4694
+ id: input?.function_call.id,
4695
+ name: input?.function_call.name,
4696
+ arguments: maybeStringifyJSON(input?.function_call.arguments)
4697
+ },
4698
+ content: null
4699
+ });
4700
+ return this;
4701
+ }
4451
4702
  this.value.push({
4452
- role: "assistant",
4703
+ role: "function_call",
4453
4704
  function_call: {
4454
- name: input?.function_call.name,
4455
- arguments: maybeStringifyJSON(input?.function_call.arguments)
4705
+ id: input?.id,
4706
+ name: input?.name,
4707
+ arguments: maybeStringifyJSON(input?.arguments)
4456
4708
  },
4457
4709
  content: null
4458
4710
  });
@@ -4470,21 +4722,26 @@ var Dialogue = class extends BaseStateItem {
4470
4722
  case "user":
4471
4723
  this.setUserMessage(message?.content, message?.name);
4472
4724
  break;
4725
+ case "model":
4473
4726
  case "assistant":
4474
- if (message.function_call) {
4475
- this.setFunctionCallMessage({
4476
- function_call: message.function_call
4477
- });
4478
- } else if (message?.content) {
4479
- this.setAssistantMessage(message?.content);
4480
- }
4727
+ this.setAssistantMessage(message?.content);
4481
4728
  break;
4482
4729
  case "system":
4483
4730
  this.setSystemMessage(message?.content);
4484
4731
  break;
4732
+ case "function_call":
4733
+ this.setFunctionCallMessage({
4734
+ function_call: message.function_call
4735
+ });
4736
+ break;
4485
4737
  case "function":
4486
4738
  this.setFunctionMessage(message?.content, message.name);
4487
4739
  break;
4740
+ default:
4741
+ this.value.push({
4742
+ role: message.role,
4743
+ content: message.content || ""
4744
+ });
4488
4745
  }
4489
4746
  }
4490
4747
  return this;
@@ -4500,6 +4757,30 @@ var Dialogue = class extends BaseStateItem {
4500
4757
  };
4501
4758
  }
4502
4759
  // deserialize() {}
4760
+ /**
4761
+ * Add LLM output to dialogue history in the order it was returned
4762
+ *
4763
+ * @param output - The LLM output result from llm.call()
4764
+ * @returns this for chaining
4765
+ */
4766
+ addFromOutput(output) {
4767
+ const result = "getResult" in output ? output.getResult() : output;
4768
+ if (!result || typeof result !== "object") {
4769
+ return this;
4770
+ }
4771
+ for (const item of result.content) {
4772
+ if (item.type === "text") {
4773
+ this.setAssistantMessage(item.text);
4774
+ } else if (item.type === "function_use") {
4775
+ this.setToolCallMessage({
4776
+ name: item.name,
4777
+ arguments: maybeStringifyJSON(item.input),
4778
+ id: item.functionId
4779
+ });
4780
+ }
4781
+ }
4782
+ return this;
4783
+ }
4503
4784
  };
4504
4785
 
4505
4786
  // src/state/_base.ts
@@ -4607,6 +4888,8 @@ function createStateItem(name, defaultValue) {
4607
4888
  DefaultState,
4608
4889
  DefaultStateItem,
4609
4890
  LlmExecutorOpenAiFunctions,
4891
+ LlmExecutorWithFunctions,
4892
+ LlmNativeFunctionParser,
4610
4893
  OpenAiFunctionParser,
4611
4894
  TextPrompt,
4612
4895
  createCallableExecutor,
@@ -4616,11 +4899,13 @@ function createStateItem(name, defaultValue) {
4616
4899
  createDialogue,
4617
4900
  createEmbedding,
4618
4901
  createLlmExecutor,
4902
+ createLlmFunctionExecutor,
4619
4903
  createParser,
4620
4904
  createPrompt,
4621
4905
  createState,
4622
4906
  createStateItem,
4623
4907
  defineSchema,
4908
+ guards,
4624
4909
  registerHelpers,
4625
4910
  registerPartials,
4626
4911
  useExecutors,