llm-exe 3.0.0-beta.1 → 3.0.0-beta.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.js CHANGED
@@ -1266,9 +1266,12 @@ var BOOLEAN_VALUES = ["true", "false", "yes", "no", "y", "n", "1", "0"];
1266
1266
  var TRUTHY_VALUES = /* @__PURE__ */ new Set(["true", "yes", "y", "1"]);
1267
1267
  var FALSY_VALUES = /* @__PURE__ */ new Set(["false", "no", "n", "0"]);
1268
1268
  var MAX_ERROR_INPUT_EXCERPT_LENGTH = 500;
1269
+ var BOOLEAN_TOKEN_PATTERN = /(?<![\p{L}\p{N}])(?:true|false|yes|no|y|n|1|0)(?![\p{L}\p{N}])/giu;
1269
1270
  var BooleanParser = class extends BaseParser {
1270
- constructor() {
1271
+ constructor(options) {
1271
1272
  super("boolean");
1273
+ __publicField(this, "match");
1274
+ this.match = options?.match ?? "exact";
1272
1275
  }
1273
1276
  getInputErrorContext(text) {
1274
1277
  const context = {
@@ -1316,6 +1319,36 @@ var BooleanParser = class extends BaseParser {
1316
1319
  if (FALSY_VALUES.has(clean)) {
1317
1320
  return false;
1318
1321
  }
1322
+ if (this.match === "extract") {
1323
+ const matches = Array.from(
1324
+ text.toLowerCase().matchAll(BOOLEAN_TOKEN_PATTERN)
1325
+ ).map((match) => match[0]);
1326
+ const values = Array.from(
1327
+ new Set(
1328
+ matches.map((match) => {
1329
+ if (TRUTHY_VALUES.has(match)) return true;
1330
+ return false;
1331
+ })
1332
+ )
1333
+ );
1334
+ if (values.length === 1) {
1335
+ return values[0];
1336
+ }
1337
+ if (values.length > 1) {
1338
+ throw new LlmExeError(`Multiple boolean values found in input.`, {
1339
+ code: "parser.parse_failed",
1340
+ context: {
1341
+ operation: "BooleanParser.parse",
1342
+ parser: "boolean",
1343
+ reason: "ambiguous_boolean",
1344
+ expected: "one boolean value",
1345
+ match: this.match,
1346
+ matchCount: values.length,
1347
+ ...this.getInputErrorContext(text)
1348
+ }
1349
+ });
1350
+ }
1351
+ }
1319
1352
  throw new LlmExeError(`No boolean value found in input.`, {
1320
1353
  code: "parser.parse_failed",
1321
1354
  context: {
@@ -1323,6 +1356,7 @@ var BooleanParser = class extends BaseParser {
1323
1356
  parser: "boolean",
1324
1357
  reason: "unrecognized_boolean",
1325
1358
  expected: BOOLEAN_VALUES,
1359
+ match: this.match,
1326
1360
  ...this.getInputErrorContext(text)
1327
1361
  }
1328
1362
  });
@@ -1347,7 +1381,7 @@ function toNumber(value) {
1347
1381
 
1348
1382
  // src/parser/parsers/NumberParser.ts
1349
1383
  var NUMERIC_TOKEN_PATTERN = /(^|[^\w.,])([+-]?(?:(?:\d{1,3}(?:,\d{3})+|\d+)(?:\.\d+)?|\.\d+)(?:[eE][+-]?\d+)?)(?![\w,])/g;
1350
- var WHOLE_NUMERIC_PATTERN = /^[+-]?(?:(?:\d{1,3}(?:,\d{3})+|\d+)(?:\.\d+)?|\.\d+)(?:[eE][+-]?\d+)?$/;
1384
+ var EXACT_NUMERIC_PATTERN = /^[+-]?(?:(?:\d{1,3}(?:,\d{3})+|\d+)(?:\.\d+)?|\.\d+)(?:[eE][+-]?\d+)?$/;
1351
1385
  var NumberParser = class extends BaseParser {
1352
1386
  constructor(options) {
1353
1387
  super("number");
@@ -1382,16 +1416,16 @@ var NumberParser = class extends BaseParser {
1382
1416
  }
1383
1417
  });
1384
1418
  }
1385
- if (this.match === "whole") {
1419
+ if (this.match === "exact") {
1386
1420
  const trimmed = text.trim();
1387
- if (!WHOLE_NUMERIC_PATTERN.test(trimmed)) {
1388
- throw new LlmExeError(`Input is not a whole numeric value.`, {
1421
+ if (!EXACT_NUMERIC_PATTERN.test(trimmed)) {
1422
+ throw new LlmExeError(`Input is not an exact numeric value.`, {
1389
1423
  code: "parser.parse_failed",
1390
1424
  context: {
1391
1425
  operation: "NumberParser.parse",
1392
1426
  parser: "number",
1393
1427
  reason: "no_numeric_value",
1394
- expected: "whole number",
1428
+ expected: "exact number",
1395
1429
  match: this.match,
1396
1430
  inputLength: text.length
1397
1431
  }
@@ -1658,9 +1692,11 @@ function isPlainObject2(value) {
1658
1692
  const proto = Object.getPrototypeOf(value);
1659
1693
  return proto === Object.prototype || proto === null;
1660
1694
  }
1661
- function normalizeWholeResponseJsonText(input) {
1695
+ function normalizeExactResponseJsonText(input) {
1662
1696
  const trimmed = input.trim();
1663
- const fenceMatch = trimmed.match(/^```([a-zA-Z]*)[^\S\r\n]*\r?\n([\s\S]*)```$/);
1697
+ const fenceMatch = trimmed.match(
1698
+ /^```([a-zA-Z]*)[^\S\r\n]*\r?\n([\s\S]*)```$/
1699
+ );
1664
1700
  if (!fenceMatch) {
1665
1701
  return trimmed;
1666
1702
  }
@@ -1670,19 +1706,82 @@ function normalizeWholeResponseJsonText(input) {
1670
1706
  }
1671
1707
  return body.trim();
1672
1708
  }
1709
+ function findBalancedJsonEnd(input, start) {
1710
+ const first = input[start];
1711
+ const stack = first === "{" ? ["}"] : first === "[" ? ["]"] : [];
1712
+ let inString = false;
1713
+ let escaping = false;
1714
+ for (let index = start + 1; index < input.length; index += 1) {
1715
+ const char = input[index];
1716
+ if (inString) {
1717
+ if (escaping) {
1718
+ escaping = false;
1719
+ } else if (char === "\\") {
1720
+ escaping = true;
1721
+ } else if (char === '"') {
1722
+ inString = false;
1723
+ }
1724
+ continue;
1725
+ }
1726
+ if (char === '"') {
1727
+ inString = true;
1728
+ continue;
1729
+ }
1730
+ if (char === "{" || char === "[") {
1731
+ stack.push(char === "{" ? "}" : "]");
1732
+ continue;
1733
+ }
1734
+ if (char !== "}" && char !== "]") {
1735
+ continue;
1736
+ }
1737
+ if (stack[stack.length - 1] !== char) {
1738
+ return void 0;
1739
+ }
1740
+ stack.pop();
1741
+ if (stack.length === 0) {
1742
+ return index;
1743
+ }
1744
+ }
1745
+ return void 0;
1746
+ }
1747
+ function extractJsonCandidates(input) {
1748
+ const candidates = [];
1749
+ for (let index = 0; index < input.length; index += 1) {
1750
+ const char = input[index];
1751
+ if (char !== "{" && char !== "[") {
1752
+ continue;
1753
+ }
1754
+ const end = findBalancedJsonEnd(input, index);
1755
+ if (end === void 0) {
1756
+ continue;
1757
+ }
1758
+ const candidate = input.slice(index, end + 1);
1759
+ try {
1760
+ candidates.push({
1761
+ parsed: JSON.parse(candidate)
1762
+ });
1763
+ index = end;
1764
+ } catch {
1765
+ }
1766
+ }
1767
+ return candidates;
1768
+ }
1673
1769
  var JsonParser = class extends BaseParserWithJson {
1674
1770
  constructor(options = {}) {
1675
1771
  super("json", options);
1676
1772
  __publicField(this, "shouldValidateSchema");
1773
+ __publicField(this, "match");
1774
+ this.match = options.match ?? "exact";
1677
1775
  this.shouldValidateSchema = !!options.schema && options.validateSchema !== false;
1678
1776
  }
1679
1777
  /**
1680
1778
  * v3 parser contract:
1681
1779
  * Category: strict
1682
- * Mode: whole-output
1780
+ * Mode: exact
1683
1781
  *
1684
- * Parses strict JSON object/array output only. Invalid JSON, empty input,
1685
- * JSON primitives, and non-plain runtime objects throw typed parser errors.
1782
+ * Parses strict JSON object/array output by default. Pass match: "extract"
1783
+ * to extract one JSON object or array from surrounding text. Invalid JSON,
1784
+ * empty input, JSON primitives, and non-plain runtime objects throw typed parser errors.
1686
1785
  * Schema validation is on by default when a schema is provided unless
1687
1786
  * validateSchema: false is explicitly set.
1688
1787
  *
@@ -1705,19 +1804,52 @@ var JsonParser = class extends BaseParserWithJson {
1705
1804
  });
1706
1805
  }
1707
1806
  try {
1708
- parsed = JSON.parse(normalizeWholeResponseJsonText(text));
1807
+ parsed = JSON.parse(normalizeExactResponseJsonText(text));
1709
1808
  } catch (cause) {
1710
- throw new LlmExeError(`Invalid JSON input.`, {
1711
- code: "parser.parse_failed",
1712
- context: {
1713
- operation: "JsonParser.parse",
1714
- parser: "json",
1715
- reason: "invalid_json",
1716
- expected: "JSON object or array",
1717
- inputLength
1718
- },
1719
- cause
1720
- });
1809
+ if (this.match === "extract") {
1810
+ const candidates = extractJsonCandidates(text);
1811
+ if (candidates.length === 1) {
1812
+ parsed = candidates[0].parsed;
1813
+ } else if (candidates.length > 1) {
1814
+ throw new LlmExeError(`Multiple JSON values found in input.`, {
1815
+ code: "parser.parse_failed",
1816
+ context: {
1817
+ operation: "JsonParser.parse",
1818
+ parser: "json",
1819
+ reason: "ambiguous_json_match",
1820
+ expected: "one JSON object or array",
1821
+ match: this.match,
1822
+ inputLength,
1823
+ matchCount: candidates.length
1824
+ }
1825
+ });
1826
+ } else {
1827
+ throw new LlmExeError(`No JSON value found in input.`, {
1828
+ code: "parser.parse_failed",
1829
+ context: {
1830
+ operation: "JsonParser.parse",
1831
+ parser: "json",
1832
+ reason: "no_json_value",
1833
+ expected: "JSON object or array",
1834
+ match: this.match,
1835
+ inputLength
1836
+ },
1837
+ cause
1838
+ });
1839
+ }
1840
+ } else {
1841
+ throw new LlmExeError(`Invalid JSON input.`, {
1842
+ code: "parser.parse_failed",
1843
+ context: {
1844
+ operation: "JsonParser.parse",
1845
+ parser: "json",
1846
+ reason: "invalid_json",
1847
+ expected: "JSON object or array",
1848
+ inputLength
1849
+ },
1850
+ cause
1851
+ });
1852
+ }
1721
1853
  }
1722
1854
  } else if (Array.isArray(text) || isPlainObject2(text)) {
1723
1855
  parsed = text;
@@ -2988,7 +3120,7 @@ var StringExtractParser = class extends BaseParser {
2988
3120
  * Mode: configured value extraction
2989
3121
  *
2990
3122
  * Returns the single configured enum value found in input. Matching is
2991
- * word-bounded by default; pass match: "whole" to require exact input or
3123
+ * word-bounded by default; pass match: "exact" to require exact input or
2992
3124
  * match: "substring" for legacy contains() behavior. Case-insensitive by
2993
3125
  * default.
2994
3126
  *
@@ -3070,8 +3202,8 @@ var StringExtractParser = class extends BaseParser {
3070
3202
  }
3071
3203
  findMatches(text) {
3072
3204
  switch (this.match) {
3073
- case "whole":
3074
- return this.matchWhole(text);
3205
+ case "exact":
3206
+ return this.matchExact(text);
3075
3207
  case "substring":
3076
3208
  return this.matchSubstring(text);
3077
3209
  case "word":
@@ -3079,7 +3211,7 @@ var StringExtractParser = class extends BaseParser {
3079
3211
  return this.matchWord(text);
3080
3212
  }
3081
3213
  }
3082
- matchWhole(text) {
3214
+ matchExact(text) {
3083
3215
  const candidate = this.ignoreCase ? text.trim().toLowerCase() : text.trim();
3084
3216
  return this.enum.filter((option) => {
3085
3217
  if (option === "") return false;
@@ -3129,36 +3261,33 @@ function createParser(...args) {
3129
3261
  case "replaceStringTemplate":
3130
3262
  return new ReplaceStringTemplateParser();
3131
3263
  case "boolean":
3132
- return new BooleanParser();
3264
+ return new BooleanParser(options);
3133
3265
  case "number":
3134
3266
  return new NumberParser(options);
3135
3267
  case "string":
3136
3268
  return new StringParser();
3137
3269
  default:
3138
- throw new LlmExeError(
3139
- `Invalid parser type: "${type}"`,
3140
- {
3141
- code: "parser.invalid_type",
3142
- context: {
3143
- operation: "createParser",
3144
- parser: type,
3145
- availableParsers: [
3146
- "json",
3147
- "string",
3148
- "boolean",
3149
- "number",
3150
- "stringExtract",
3151
- "listToArray",
3152
- "listToJson",
3153
- "listToKeyValue",
3154
- "replaceStringTemplate",
3155
- "markdownCodeBlock",
3156
- "markdownCodeBlocks"
3157
- ],
3158
- resolution: "Use a registered parser type, or define a custom parser."
3159
- }
3270
+ throw new LlmExeError(`Invalid parser type: "${type}"`, {
3271
+ code: "parser.invalid_type",
3272
+ context: {
3273
+ operation: "createParser",
3274
+ parser: type,
3275
+ availableParsers: [
3276
+ "json",
3277
+ "string",
3278
+ "boolean",
3279
+ "number",
3280
+ "stringExtract",
3281
+ "listToArray",
3282
+ "listToJson",
3283
+ "listToKeyValue",
3284
+ "replaceStringTemplate",
3285
+ "markdownCodeBlock",
3286
+ "markdownCodeBlocks"
3287
+ ],
3288
+ resolution: "Use a registered parser type, or define a custom parser."
3160
3289
  }
3161
- );
3290
+ });
3162
3291
  }
3163
3292
  }
3164
3293
  function createCustomParser(name, parserFn) {
@@ -4223,6 +4352,20 @@ function anthropicPromptSanitize(_messages, _inputBodyObj, _outputObj) {
4223
4352
  return mergeConsecutiveSameRole(result);
4224
4353
  }
4225
4354
 
4355
+ // src/llm/output/_utils/getBedrockTokenCounts.ts
4356
+ function getBedrockTokenCounts(headers) {
4357
+ if (!headers) return void 0;
4358
+ const input = parseInt(headers["x-amzn-bedrock-input-token-count"], 10);
4359
+ const output = parseInt(headers["x-amzn-bedrock-output-token-count"], 10);
4360
+ if (!Number.isFinite(input) && !Number.isFinite(output)) {
4361
+ return void 0;
4362
+ }
4363
+ return {
4364
+ input_tokens: Number.isFinite(input) ? input : 0,
4365
+ output_tokens: Number.isFinite(output) ? output : 0
4366
+ };
4367
+ }
4368
+
4226
4369
  // src/llm/output/claude.ts
4227
4370
  function formatResult2(response) {
4228
4371
  const content = response?.content || [];
@@ -4245,15 +4388,18 @@ function formatResult2(response) {
4245
4388
  }
4246
4389
  return out;
4247
4390
  }
4248
- function OutputAnthropicClaude3Chat(result, _config) {
4391
+ function OutputAnthropicClaude3Chat(result, _config, headers) {
4249
4392
  const id = result.id;
4250
4393
  const name = result.model || _config?.options.model?.default || "anthropic.unknown";
4251
4394
  const stopReason = result.stop_reason;
4252
4395
  const content = formatResult2(result);
4396
+ const headerUsage = getBedrockTokenCounts(headers);
4397
+ const input_tokens = result?.usage?.input_tokens ?? headerUsage?.input_tokens ?? 0;
4398
+ const output_tokens = result?.usage?.output_tokens ?? headerUsage?.output_tokens ?? 0;
4253
4399
  const usage = {
4254
- input_tokens: result?.usage?.input_tokens,
4255
- output_tokens: result?.usage?.output_tokens,
4256
- total_tokens: result?.usage?.input_tokens + result?.usage?.output_tokens
4400
+ input_tokens,
4401
+ output_tokens,
4402
+ total_tokens: input_tokens + output_tokens
4257
4403
  };
4258
4404
  return {
4259
4405
  id,
@@ -4266,7 +4412,7 @@ function OutputAnthropicClaude3Chat(result, _config) {
4266
4412
  }
4267
4413
 
4268
4414
  // src/llm/output/llama.ts
4269
- function OutputMetaLlama3Chat(result, _config) {
4415
+ function OutputMetaLlama3Chat(result, _config, headers) {
4270
4416
  const id = (0, import_uuid.v4)();
4271
4417
  const name = _config?.options?.model?.default || "meta";
4272
4418
  const created = (/* @__PURE__ */ new Date()).getTime();
@@ -4274,10 +4420,13 @@ function OutputMetaLlama3Chat(result, _config) {
4274
4420
  const content = [
4275
4421
  { type: "text", text: result.generation }
4276
4422
  ];
4423
+ const headerUsage = getBedrockTokenCounts(headers);
4424
+ const output_tokens = result?.generation_token_count ?? headerUsage?.output_tokens ?? 0;
4425
+ const input_tokens = result?.prompt_token_count ?? headerUsage?.input_tokens ?? 0;
4277
4426
  const usage = {
4278
- output_tokens: result?.generation_token_count,
4279
- input_tokens: result?.prompt_token_count,
4280
- total_tokens: result?.generation_token_count + result?.prompt_token_count
4427
+ output_tokens,
4428
+ input_tokens,
4429
+ total_tokens: output_tokens + input_tokens
4281
4430
  };
4282
4431
  return {
4283
4432
  id,
@@ -4395,7 +4544,7 @@ var bedrock = {
4395
4544
 
4396
4545
  // src/llm/config/anthropic/index.ts
4397
4546
  var ANTHROPIC_VERSION = "2023-06-01";
4398
- var MODELS_REJECTING_SAMPLING_PARAMS = ["claude-opus-4-7"];
4547
+ var MODELS_REJECTING_SAMPLING_PARAMS = ["claude-opus-4-7", "claude-opus-4-8"];
4399
4548
  var isClaude4x = (model) => /^claude-(opus|sonnet|haiku)-4-/.test(model);
4400
4549
  var dropIfModelRejectsSamplingParams = (v, body) => MODELS_REJECTING_SAMPLING_PARAMS.includes(body.model) ? void 0 : v;
4401
4550
  var topPTransform = (v, body) => {
@@ -4480,6 +4629,11 @@ var anthropicChatV1 = {
4480
4629
  };
4481
4630
  var anthropic = {
4482
4631
  "anthropic.chat.v1": anthropicChatV1,
4632
+ // Claude 4.8 models
4633
+ "anthropic.claude-opus-4-8": withDefaultModel(
4634
+ anthropicChatV1,
4635
+ "claude-opus-4-8"
4636
+ ),
4483
4637
  // Claude 4.7 models
4484
4638
  "anthropic.claude-opus-4-7": withDefaultModel(
4485
4639
  anthropicChatV1,
@@ -4663,7 +4817,11 @@ var ollamaChatV1 = {
4663
4817
  provider: "ollama.chat",
4664
4818
  endpoint: `${getEnvironmentVariable("OLLAMA_ENDPOINT") || `http://localhost:11434`}/api/chat`,
4665
4819
  options: {
4666
- prompt: {}
4820
+ prompt: {},
4821
+ temperature: {},
4822
+ topP: {},
4823
+ maxTokens: {},
4824
+ stopSequences: {}
4667
4825
  },
4668
4826
  method: "POST",
4669
4827
  headers: `{"Content-Type": "application/json" }`,
@@ -4679,6 +4837,18 @@ var ollamaChatV1 = {
4679
4837
  },
4680
4838
  model: {
4681
4839
  key: "model"
4840
+ },
4841
+ temperature: {
4842
+ key: "options.temperature"
4843
+ },
4844
+ topP: {
4845
+ key: "options.top_p"
4846
+ },
4847
+ maxTokens: {
4848
+ key: "options.num_predict"
4849
+ },
4850
+ stopSequences: {
4851
+ key: "options.stop"
4682
4852
  }
4683
4853
  },
4684
4854
  transformResponse: OutputOllamaChat
@@ -4874,7 +5044,10 @@ var googleGeminiChatV1 = {
4874
5044
  options: {
4875
5045
  effort: {},
4876
5046
  prompt: {},
4877
- // topP: {},
5047
+ temperature: {},
5048
+ topP: {},
5049
+ maxTokens: {},
5050
+ stopSequences: {},
4878
5051
  geminiApiKey: {
4879
5052
  default: getEnvironmentVariable("GEMINI_API_KEY")
4880
5053
  }
@@ -4886,6 +5059,18 @@ var googleGeminiChatV1 = {
4886
5059
  key: "contents",
4887
5060
  transform: googleGeminiPromptSanitize
4888
5061
  },
5062
+ temperature: {
5063
+ key: "generationConfig.temperature"
5064
+ },
5065
+ topP: {
5066
+ key: "generationConfig.topP"
5067
+ },
5068
+ maxTokens: {
5069
+ key: "generationConfig.maxOutputTokens"
5070
+ },
5071
+ stopSequences: {
5072
+ key: "generationConfig.stopSequences"
5073
+ },
4889
5074
  effort: {
4890
5075
  key: "config.thinkingConfig.thinkingBudget",
4891
5076
  transform: (v, _s) => {
@@ -5027,6 +5212,13 @@ function isValidUrl(input) {
5027
5212
  }
5028
5213
 
5029
5214
  // src/utils/modules/request.ts
5215
+ function headersToRecord(headers) {
5216
+ const record = {};
5217
+ headers.forEach((value, key) => {
5218
+ record[key.toLowerCase()] = value;
5219
+ });
5220
+ return record;
5221
+ }
5030
5222
  async function apiRequest(url, options) {
5031
5223
  const finalOptions = {
5032
5224
  ...options
@@ -5112,13 +5304,16 @@ async function apiRequest(url, options) {
5112
5304
  });
5113
5305
  }
5114
5306
  const contentType = response.headers.get("content-type");
5307
+ const headers = headersToRecord(response.headers);
5115
5308
  if (contentType?.includes("application/json")) {
5116
- const responseData = await response.json();
5117
- return responseData;
5118
- } else {
5119
- const responseData = await response.text();
5120
- return responseData;
5309
+ const responseData2 = await response.json();
5310
+ return { data: responseData2, headers };
5121
5311
  }
5312
+ const responseData = await response.text();
5313
+ return {
5314
+ data: responseData,
5315
+ headers
5316
+ };
5122
5317
  }
5123
5318
 
5124
5319
  // src/utils/modules/convertDotNotation.ts
@@ -5490,7 +5685,7 @@ async function useLlm_call(state, messages, _options) {
5490
5685
  }
5491
5686
  ]
5492
5687
  };
5493
- return BaseLlmOutput(transformResponse(mockResponse, config));
5688
+ return BaseLlmOutput(transformResponse(mockResponse, config, {}));
5494
5689
  }
5495
5690
  try {
5496
5691
  const response = await apiRequest(url, {
@@ -5498,7 +5693,9 @@ async function useLlm_call(state, messages, _options) {
5498
5693
  body,
5499
5694
  headers
5500
5695
  });
5501
- return BaseLlmOutput(transformResponse(response, config));
5696
+ return BaseLlmOutput(
5697
+ transformResponse(response.data, config, response.headers)
5698
+ );
5502
5699
  } catch (e) {
5503
5700
  if (!isLlmExeError(e, "request.http_error")) throw e;
5504
5701
  const ctx = e.context ?? {};
@@ -5679,7 +5876,9 @@ var embeddingConfigs = {
5679
5876
  "openai.embedding.v1": {
5680
5877
  key: "openai.embedding.v1",
5681
5878
  provider: "openai.embedding",
5682
- endpoint: `https://api.openai.com/v1/embeddings`,
5879
+ // Templated host: `baseUrl` defaults to OpenAI. Override to point at any
5880
+ // OpenAI-compatible embeddings server (Baseten, vLLM, TEI, Together, etc.).
5881
+ endpoint: `{{baseUrl}}/embeddings`,
5683
5882
  method: "POST",
5684
5883
  headers: `{"Authorization":"Bearer {{openAiApiKey}}", "Content-Type": "application/json" }`,
5685
5884
  options: {
@@ -5690,6 +5889,9 @@ var embeddingConfigs = {
5690
5889
  encodingFormat: {},
5691
5890
  openAiApiKey: {
5692
5891
  default: getEnvironmentVariable("OPENAI_API_KEY")
5892
+ },
5893
+ baseUrl: {
5894
+ default: "https://api.openai.com/v1"
5693
5895
  }
5694
5896
  },
5695
5897
  mapBody: {
@@ -5876,15 +6078,34 @@ function AmazonTitanEmbedding(result, config) {
5876
6078
  }
5877
6079
 
5878
6080
  // src/embedding/output/CohereBedrockEmbedding.ts
5879
- function CohereBedrockEmbedding(result, config) {
6081
+ function resolveEmbeddings(embeddings, model) {
6082
+ if (Array.isArray(embeddings)) {
6083
+ return embeddings;
6084
+ }
6085
+ if (embeddings && typeof embeddings === "object") {
6086
+ if (Array.isArray(embeddings.float)) {
6087
+ return embeddings.float;
6088
+ }
6089
+ throw new Error(
6090
+ `Unexpected embeddings in Cohere Bedrock response (model: "${model}"). Expected float embeddings, received object with keys: [${Object.keys(embeddings).join(", ")}]`
6091
+ );
6092
+ }
6093
+ throw new Error(
6094
+ `Unexpected embeddings shape in Cohere Bedrock response (model: "${model}"). Expected an array (Embed v3) or an object with float embeddings (Embed v4), received: ${embeddings === null ? "null" : typeof embeddings}`
6095
+ );
6096
+ }
6097
+ function CohereBedrockEmbedding(result, config, headers) {
6098
+ const headerUsage = getBedrockTokenCounts(headers);
5880
6099
  const __result = deepClone(result);
5881
6100
  const model = config.model || "cohere.unknown";
5882
6101
  const created = (/* @__PURE__ */ new Date()).getTime();
5883
- const embedding = Array.isArray(__result.embeddings) ? __result.embeddings : [];
6102
+ const embedding = resolveEmbeddings(__result.embeddings, model);
6103
+ const input_tokens = headerUsage?.input_tokens ?? 0;
6104
+ const output_tokens = headerUsage?.output_tokens ?? 0;
5884
6105
  const usage = {
5885
- output_tokens: 0,
5886
- input_tokens: 0,
5887
- total_tokens: 0
6106
+ output_tokens,
6107
+ input_tokens,
6108
+ total_tokens: input_tokens + output_tokens
5888
6109
  };
5889
6110
  return BaseEmbeddingOutput({
5890
6111
  id: __result.id,
@@ -5916,14 +6137,14 @@ function OpenAiEmbedding(result, config) {
5916
6137
  }
5917
6138
 
5918
6139
  // src/embedding/output/getEmbeddingOutputParser.ts
5919
- function getEmbeddingOutputParser(config, response) {
6140
+ function getEmbeddingOutputParser(config, response, headers) {
5920
6141
  switch (config.key) {
5921
6142
  case "openai.embedding.v1":
5922
6143
  return OpenAiEmbedding(response, config);
5923
6144
  case "amazon.embedding.v1":
5924
6145
  return AmazonTitanEmbedding(response, config);
5925
6146
  case "amazon:cohere.embedding.v1":
5926
- return CohereBedrockEmbedding(response, config);
6147
+ return CohereBedrockEmbedding(response, config, headers);
5927
6148
  default:
5928
6149
  throw new LlmExeError("Unsupported provider", {
5929
6150
  code: "embedding.invalid_response_shape",
@@ -5960,7 +6181,7 @@ async function createEmbedding_call(state, _input, _options) {
5960
6181
  body,
5961
6182
  headers
5962
6183
  });
5963
- return getEmbeddingOutputParser(state, request);
6184
+ return getEmbeddingOutputParser(state, request.data, request.headers);
5964
6185
  } catch (e) {
5965
6186
  if (!isLlmExeError(e, "request.http_error")) throw e;
5966
6187
  const ctx = e.context ?? {};