@theokit/sdk 2.15.0 → 2.15.1

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/a2a/index.js CHANGED
@@ -10329,11 +10329,16 @@ var init_sanitize_tool_input = __esm({
10329
10329
  });
10330
10330
 
10331
10331
  // src/internal/llm/hermes-tool-extract.ts
10332
- function extractHermesToolCalls(content, makeId) {
10332
+ function extractHermesToolCalls(content, makeId, allowedToolNames) {
10333
+ const isPromoted = (name) => name.length > 0 && (allowedToolNames === void 0 || allowedToolNames.has(name));
10333
10334
  const toolCalls = [];
10335
+ const droppedNames = [];
10334
10336
  for (const block of content.matchAll(HERMES_BLOCK)) {
10335
10337
  const name = (block[1] ?? "").trim();
10336
- if (name.length === 0) continue;
10338
+ if (!isPromoted(name)) {
10339
+ if (name.length > 0 && allowedToolNames !== void 0) droppedNames.push(name);
10340
+ continue;
10341
+ }
10337
10342
  toolCalls.push({
10338
10343
  type: "tool_use",
10339
10344
  id: makeId(),
@@ -10341,8 +10346,11 @@ function extractHermesToolCalls(content, makeId) {
10341
10346
  input: parseHermesParams(block[2] ?? "")
10342
10347
  });
10343
10348
  }
10344
- const residualText = toolCalls.length === 0 ? content : content.replace(HERMES_BLOCK, "").trim();
10345
- return { toolCalls, residualText };
10349
+ const residualText = toolCalls.length === 0 ? content : content.replace(
10350
+ HERMES_BLOCK,
10351
+ (full, rawName) => isPromoted((rawName ?? "").trim()) ? "" : full
10352
+ ).trim();
10353
+ return { toolCalls, residualText, droppedNames };
10346
10354
  }
10347
10355
  function parseHermesParams(inner) {
10348
10356
  const input = {};
@@ -10547,7 +10555,10 @@ var init_openai2 = __esm({
10547
10555
  }
10548
10556
  const accumulator = new OpenAIStreamAccumulator(
10549
10557
  this.options.extractToolCallsFromContent ?? false,
10550
- providerId
10558
+ providerId,
10559
+ // R5: request-scoped allowlist — leaked recovery only promotes a block whose name is a tool the
10560
+ // model was actually given. Empty set (no tools) recovers nothing.
10561
+ new Set(request.tools?.map((tool) => tool.name) ?? [])
10551
10562
  );
10552
10563
  for await (const record of parseSseStream(response.body, signal)) {
10553
10564
  if (record.data === "[DONE]") break;
@@ -10577,13 +10588,18 @@ var init_openai2 = __esm({
10577
10588
  /**
10578
10589
  * @param extractFromContent opt-in leaked-dialect safe-parse (theokit#58). Default false.
10579
10590
  * @param providerName provider id, used only to label the recovery log line.
10591
+ * @param allowedToolNames R5 request-scoped allowlist — built from `request.tools` at `stream()`;
10592
+ * leaked recovery in `finish()` only promotes a block whose name is in this set. `undefined`
10593
+ * (direct construction) recovers all (back-compat); an empty set recovers nothing.
10580
10594
  */
10581
- constructor(extractFromContent = false, providerName = "openai") {
10595
+ constructor(extractFromContent = false, providerName = "openai", allowedToolNames) {
10582
10596
  this.extractFromContent = extractFromContent;
10583
10597
  this.providerName = providerName;
10598
+ this.allowedToolNames = allowedToolNames;
10584
10599
  }
10585
10600
  extractFromContent;
10586
10601
  providerName;
10602
+ allowedToolNames;
10587
10603
  text = "";
10588
10604
  stopReason = "end_turn";
10589
10605
  inputTokens;
@@ -10654,7 +10670,8 @@ var init_openai2 = __esm({
10654
10670
  if (this.extractFromContent && toolCalls.length === 0) {
10655
10671
  const recovered = extractHermesToolCalls(
10656
10672
  this.text,
10657
- () => `hermes-${globalThis.crypto.randomUUID()}`
10673
+ () => `hermes-${globalThis.crypto.randomUUID()}`,
10674
+ this.allowedToolNames
10658
10675
  );
10659
10676
  if (recovered.toolCalls.length > 0) {
10660
10677
  toolCalls.push(...recovered.toolCalls);
@@ -10662,6 +10679,12 @@ var init_openai2 = __esm({
10662
10679
  stopReason = "tool_use";
10663
10680
  process.stderr.write(
10664
10681
  `[theokit-sdk] recovered ${recovered.toolCalls.length} leaked tool call(s) from assistant content (provider="${this.providerName}", names=${recovered.toolCalls.map((c) => c.name).join(",")})
10682
+ `
10683
+ );
10684
+ }
10685
+ if (recovered.droppedNames.length > 0) {
10686
+ process.stderr.write(
10687
+ `[theokit-sdk] dropped ${recovered.droppedNames.length} leaked block(s) whose name is not a tool in the request (provider="${this.providerName}", names=${recovered.droppedNames.join(",")})
10665
10688
  `
10666
10689
  );
10667
10690
  }