@jambonz/llm 0.6.8 → 0.6.10

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.
@@ -1291,6 +1291,21 @@ var ANTHROPIC_KNOWN_MODELS = [
1291
1291
  maxContextTokens: 2e5
1292
1292
  }
1293
1293
  },
1294
+ {
1295
+ // Thinks by default (effort `medium`), and the thinking counts toward
1296
+ // max_tokens. For voice, send `providerParams: {output_config: {effort:
1297
+ // 'low'}}`. Rejects non-default sampling parameters, so the adapter
1298
+ // leaves `temperature` out of its requests.
1299
+ id: "claude-haiku-5-5",
1300
+ displayName: "Claude Haiku 5.5",
1301
+ capabilities: {
1302
+ streaming: true,
1303
+ tools: true,
1304
+ vision: true,
1305
+ systemPrompt: true,
1306
+ maxContextTokens: 1e6
1307
+ }
1308
+ },
1294
1309
  {
1295
1310
  id: "claude-haiku-4-5-20251001",
1296
1311
  displayName: "Claude Haiku 4.5",
@@ -1374,6 +1389,7 @@ var ANTHROPIC_METADATA_EXTRACTOR = makeMetadataExtractor([
1374
1389
  { header: "anthropic-ratelimit-input-tokens-remaining", key: "input_tokens_remaining", numeric: true },
1375
1390
  { header: "anthropic-ratelimit-output-tokens-remaining", key: "output_tokens_remaining", numeric: true }
1376
1391
  ]);
1392
+ var REJECTS_SAMPLING_PARAMS = /^claude-(opus-4-[7-9]|opus-5|sonnet-5|haiku-5|fable|mythos)/;
1377
1393
  var AnthropicAdapter = class {
1378
1394
  vendor = anthropicManifest.vendor;
1379
1395
  acceptedAuth = ["apiKey"];
@@ -1406,7 +1422,14 @@ var AnthropicAdapter = class {
1406
1422
  };
1407
1423
  if (req.system) body.system = req.system;
1408
1424
  if (tools) body.tools = tools;
1409
- if (req.temperature !== void 0) body.temperature = req.temperature;
1425
+ if (req.temperature !== void 0 && !REJECTS_SAMPLING_PARAMS.test(req.model)) {
1426
+ body.temperature = req.temperature;
1427
+ }
1428
+ if (req.providerParams) {
1429
+ for (const [key, value] of Object.entries(req.providerParams)) {
1430
+ if (!(key in body)) body[key] = value;
1431
+ }
1432
+ }
1410
1433
  if (req.cacheKey) {
1411
1434
  if (req.system) {
1412
1435
  body.system = [{ type: "text", text: req.system, cache_control: { type: "ephemeral" } }];
@@ -1417,21 +1440,31 @@ var AnthropicAdapter = class {
1417
1440
  }
1418
1441
  markLastMessageForCaching(messages);
1419
1442
  }
1420
- let stream;
1421
- let responseHeaders;
1422
- try {
1443
+ const open = async (b) => {
1423
1444
  const apiPromise = client.messages.create(
1424
- body,
1445
+ b,
1425
1446
  { signal: req.signal }
1426
1447
  );
1427
1448
  const maybeWithResponse = apiPromise.withResponse;
1428
1449
  if (typeof maybeWithResponse === "function") {
1429
1450
  const result = await maybeWithResponse.call(apiPromise);
1430
- stream = result.data;
1431
- responseHeaders = result.response?.headers;
1432
- } else {
1433
- stream = await apiPromise;
1451
+ return { stream: result.data, headers: result.response?.headers };
1434
1452
  }
1453
+ return { stream: await apiPromise, headers: void 0 };
1454
+ };
1455
+ let stream;
1456
+ let responseHeaders;
1457
+ try {
1458
+ let opened;
1459
+ try {
1460
+ opened = await open(body);
1461
+ } catch (err) {
1462
+ const stripped = isThinkingBlockRejection(err) ? withoutThinking(messages) : void 0;
1463
+ if (!stripped) throw err;
1464
+ opened = await open({ ...body, messages: stripped });
1465
+ }
1466
+ stream = opened.stream;
1467
+ responseHeaders = opened.headers;
1435
1468
  } catch (err) {
1436
1469
  if (isAbortError2(err)) {
1437
1470
  yield { type: "end", finishReason: "aborted" };
@@ -1440,7 +1473,10 @@ var AnthropicAdapter = class {
1440
1473
  throw err;
1441
1474
  }
1442
1475
  let currentToolUse = null;
1476
+ let currentThinking = null;
1477
+ let currentText = null;
1443
1478
  const completedToolCalls = [];
1479
+ const turnContent = [];
1444
1480
  let stopReason;
1445
1481
  let inputTokens;
1446
1482
  let outputTokens;
@@ -1473,19 +1509,42 @@ var AnthropicAdapter = class {
1473
1509
  name: currentToolUse.name
1474
1510
  };
1475
1511
  }
1512
+ } else if (block?.type === "text") {
1513
+ currentText = block.text ?? "";
1514
+ } else if (block?.type === "thinking") {
1515
+ currentThinking = {
1516
+ type: "thinking",
1517
+ thinking: block.thinking ?? "",
1518
+ signature: block.signature ?? ""
1519
+ };
1520
+ } else if (block?.type === "redacted_thinking" && block.data) {
1521
+ turnContent.push({ type: "redacted_thinking", data: block.data });
1476
1522
  }
1477
1523
  break;
1478
1524
  }
1479
1525
  case "content_block_delta": {
1480
1526
  const delta = event.delta;
1481
1527
  if (delta?.type === "text_delta" && delta.text) {
1528
+ if (currentText !== null) currentText += delta.text;
1482
1529
  yield { type: "token", text: delta.text };
1483
1530
  } else if (delta?.type === "input_json_delta" && currentToolUse && delta.partial_json) {
1484
1531
  currentToolUse.argumentsText += delta.partial_json;
1532
+ } else if (delta?.type === "thinking_delta" && currentThinking && delta.thinking) {
1533
+ currentThinking.thinking += delta.thinking;
1534
+ } else if (delta?.type === "signature_delta" && currentThinking && delta.signature) {
1535
+ currentThinking.signature += delta.signature;
1485
1536
  }
1486
1537
  break;
1487
1538
  }
1488
1539
  case "content_block_stop":
1540
+ if (currentThinking) {
1541
+ if (currentThinking.signature) turnContent.push(currentThinking);
1542
+ currentThinking = null;
1543
+ }
1544
+ if (currentText !== null) {
1545
+ if (currentText) turnContent.push({ type: "text", text: currentText });
1546
+ currentText = null;
1547
+ }
1489
1548
  if (currentToolUse && currentToolUse.id && currentToolUse.name) {
1490
1549
  let parsed = {};
1491
1550
  try {
@@ -1498,6 +1557,12 @@ var AnthropicAdapter = class {
1498
1557
  name: currentToolUse.name,
1499
1558
  arguments: parsed
1500
1559
  });
1560
+ turnContent.push({
1561
+ type: "tool_use",
1562
+ id: currentToolUse.id,
1563
+ name: currentToolUse.name,
1564
+ input: parsed
1565
+ });
1501
1566
  }
1502
1567
  currentToolUse = null;
1503
1568
  break;
@@ -1526,12 +1591,14 @@ var AnthropicAdapter = class {
1526
1591
  yield { type: "end", finishReason: "aborted" };
1527
1592
  return;
1528
1593
  }
1594
+ const toolCallRaw = { content: turnContent };
1529
1595
  for (const tc of completedToolCalls) {
1530
1596
  yield {
1531
1597
  type: "toolCall",
1532
1598
  id: tc.id,
1533
1599
  name: tc.name,
1534
- arguments: tc.arguments
1600
+ arguments: tc.arguments,
1601
+ vendorRaw: toolCallRaw
1535
1602
  };
1536
1603
  }
1537
1604
  const finishReason = mapStopReason(stopReason, completedToolCalls.length > 0);
@@ -1562,15 +1629,7 @@ var AnthropicAdapter = class {
1562
1629
  const text = assistantText?.trim() ? assistantText : null;
1563
1630
  const wireMessage = {
1564
1631
  role: "assistant",
1565
- content: [
1566
- ...text ? [{ type: "text", text }] : [],
1567
- ...toolCalls.map((tc) => ({
1568
- type: "tool_use",
1569
- id: tc.id,
1570
- name: tc.name,
1571
- input: tc.arguments ?? {}
1572
- }))
1573
- ]
1632
+ content: assistantTurnContent(toolCalls, text)
1574
1633
  };
1575
1634
  return [
1576
1635
  ...history,
@@ -1662,6 +1721,62 @@ function markLastMessageForCaching(messages) {
1662
1721
  };
1663
1722
  }
1664
1723
  }
1724
+ function isThinkingBlockRejection(err) {
1725
+ const e = err;
1726
+ return e?.status === 400 && /`thinking` block/.test(String(e.message ?? ""));
1727
+ }
1728
+ function withoutThinking(messages) {
1729
+ let removed = false;
1730
+ const out = messages.map((m) => {
1731
+ const content = m.content;
1732
+ if (!Array.isArray(content)) return m;
1733
+ const kept = content.filter((b) => {
1734
+ const thinking = b?.type === "thinking" || b?.type === "redacted_thinking";
1735
+ if (thinking) removed = true;
1736
+ return !thinking;
1737
+ });
1738
+ return kept.length === content.length ? m : { ...m, content: kept };
1739
+ });
1740
+ return removed ? out : void 0;
1741
+ }
1742
+ function assistantTurnContent(toolCalls, text) {
1743
+ const recorded = recordedTurnOf(toolCalls);
1744
+ if (!recorded) {
1745
+ return [
1746
+ ...text ? [{ type: "text", text }] : [],
1747
+ ...toolCalls.map((tc) => ({
1748
+ type: "tool_use",
1749
+ id: tc.id,
1750
+ name: tc.name,
1751
+ input: tc.arguments ?? {}
1752
+ }))
1753
+ ];
1754
+ }
1755
+ const ids = new Set(toolCalls.map((tc) => tc.id));
1756
+ const content = recorded.filter(
1757
+ (b) => b.type !== "tool_use" || ids.has(b.id)
1758
+ );
1759
+ if (text && !content.some((b) => b.type === "text")) {
1760
+ const at = content.findIndex((b) => b.type === "tool_use");
1761
+ content.splice(at === -1 ? content.length : at, 0, { type: "text", text });
1762
+ }
1763
+ const known = new Set(
1764
+ content.flatMap((b) => b.type === "tool_use" ? [b.id] : [])
1765
+ );
1766
+ for (const tc of toolCalls) {
1767
+ if (!known.has(tc.id)) {
1768
+ content.push({ type: "tool_use", id: tc.id, name: tc.name, input: tc.arguments ?? {} });
1769
+ }
1770
+ }
1771
+ return content;
1772
+ }
1773
+ function recordedTurnOf(toolCalls) {
1774
+ for (const tc of toolCalls) {
1775
+ const raw = tc.vendorRaw;
1776
+ if (raw && Array.isArray(raw.content)) return raw.content;
1777
+ }
1778
+ return void 0;
1779
+ }
1665
1780
  function formatTools2(tools) {
1666
1781
  return tools.map((t) => ({
1667
1782
  name: t.name,
@@ -1679,6 +1794,8 @@ function mapStopReason(r, hadToolCalls) {
1679
1794
  return "tool";
1680
1795
  case "max_tokens":
1681
1796
  return "length";
1797
+ case "refusal":
1798
+ return "filtered";
1682
1799
  default:
1683
1800
  return "stop";
1684
1801
  }
@@ -3797,7 +3914,60 @@ var harnessManifest = {
3797
3914
  ],
3798
3915
  knownModels: [],
3799
3916
  supportsModelListing: false,
3800
- credentialOnly: true
3917
+ credentialOnly: true,
3918
+ category: "llm"
3919
+ };
3920
+
3921
+ // src/vendors/dialogflow-ces.ts
3922
+ var dialogflowCesManifest = {
3923
+ vendor: "dialogflow_ces",
3924
+ displayName: "Dialogflow CES",
3925
+ authKinds: [
3926
+ {
3927
+ kind: "googleServiceAccount",
3928
+ displayName: "Service Account JSON",
3929
+ fields: [
3930
+ {
3931
+ name: "credentials",
3932
+ label: "Service Account Key (JSON)",
3933
+ type: "json-file",
3934
+ required: true,
3935
+ help: "The key of a service account allowed to run your CES agents (Customer Engagement Suite)."
3936
+ }
3937
+ ]
3938
+ }
3939
+ ],
3940
+ knownModels: [],
3941
+ supportsModelListing: false,
3942
+ docsUrl: "https://cloud.google.com/customer-engagement-ai/conversational-agents/ps",
3943
+ credentialOnly: true,
3944
+ category: "hosted"
3945
+ };
3946
+
3947
+ // src/vendors/openai-s2s.ts
3948
+ var openaiS2sManifest = {
3949
+ vendor: "openai_s2s",
3950
+ displayName: "OpenAI Realtime",
3951
+ authKinds: [
3952
+ {
3953
+ kind: "apiKey",
3954
+ displayName: "API Key",
3955
+ fields: [
3956
+ {
3957
+ name: "apiKey",
3958
+ label: "API Key",
3959
+ type: "password",
3960
+ required: true,
3961
+ help: "An OpenAI API key with access to the Realtime API."
3962
+ }
3963
+ ]
3964
+ }
3965
+ ],
3966
+ knownModels: [],
3967
+ supportsModelListing: false,
3968
+ docsUrl: "https://platform.openai.com/docs/guides/realtime",
3969
+ credentialOnly: true,
3970
+ category: "s2s"
3801
3971
  };
3802
3972
 
3803
3973
  // src/adapters/index.ts
@@ -3818,6 +3988,8 @@ registerAdapter(groqFactory);
3818
3988
  registerAdapter(huggingfaceFactory);
3819
3989
  registerAdapter(openRouterFactory);
3820
3990
  registerCredentialVendor(harnessManifest);
3991
+ registerCredentialVendor(openaiS2sManifest);
3992
+ registerCredentialVendor(dialogflowCesManifest);
3821
3993
 
3822
3994
  // src/index.ts
3823
3995
  async function createLlm(args) {