@theokit/sdk 2.12.0 → 2.13.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.
@@ -760,6 +760,17 @@ interface ProviderRoute {
760
760
  capability: ProviderCapability;
761
761
  provider: string;
762
762
  model?: string;
763
+ /**
764
+ * Opt-in leaked-dialect safe-parse for this route's provider (theokit#58
765
+ * follow-up). When `true`, a `chat_completions` finish that carries ZERO
766
+ * native `tool_calls` has its assistant text scanned for the Hermes
767
+ * `<function=…></tool_call>` dialect, and any recovered calls are surfaced as
768
+ * real `tool_calls` so the loop executes them — for models (qwen3-coder via
769
+ * OpenRouter) that intermittently leak tool calls as text. Default `false`;
770
+ * fail-open (a partial/unclosed block never fabricates a call). Scoped to the
771
+ * resolved chat chain, so a non-leaking route is unaffected.
772
+ */
773
+ extractToolCallsFromContent?: boolean;
763
774
  }
764
775
  /**
765
776
  * Provider routing configuration accepted by `Agent.create()` via
@@ -760,6 +760,17 @@ interface ProviderRoute {
760
760
  capability: ProviderCapability;
761
761
  provider: string;
762
762
  model?: string;
763
+ /**
764
+ * Opt-in leaked-dialect safe-parse for this route's provider (theokit#58
765
+ * follow-up). When `true`, a `chat_completions` finish that carries ZERO
766
+ * native `tool_calls` has its assistant text scanned for the Hermes
767
+ * `<function=…></tool_call>` dialect, and any recovered calls are surfaced as
768
+ * real `tool_calls` so the loop executes them — for models (qwen3-coder via
769
+ * OpenRouter) that intermittently leak tool calls as text. Default `false`;
770
+ * fail-open (a partial/unclosed block never fabricates a call). Scoped to the
771
+ * resolved chat chain, so a non-leaking route is unaffected.
772
+ */
773
+ extractToolCallsFromContent?: boolean;
763
774
  }
764
775
  /**
765
776
  * Provider routing configuration accepted by `Agent.create()` via
package/dist/cron.cjs CHANGED
@@ -10980,7 +10980,7 @@ function parseHermesParams(inner) {
10980
10980
  const key = param[1];
10981
10981
  const value = param[2];
10982
10982
  if (key === void 0 || value === void 0) continue;
10983
- input[key.trim()] = value;
10983
+ input[key.trim()] = value.trim();
10984
10984
  }
10985
10985
  return input;
10986
10986
  }
@@ -10996,6 +10996,14 @@ var OpenAIClient = class {
10996
10996
  name = "openai";
10997
10997
  baseUrl;
10998
10998
  fetchImpl;
10999
+ /**
11000
+ * Whether this client recovers leaked Hermes tool-call dialect from assistant
11001
+ * text (theokit#58 follow-up). Observability for the route→client wiring of
11002
+ * `extractToolCallsFromContent`. @internal
11003
+ */
11004
+ get recoversLeakedToolCalls() {
11005
+ return this.options.extractToolCallsFromContent ?? false;
11006
+ }
10999
11007
  // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: HTTP+SSE handshake + accumulator is intentionally one block
11000
11008
  async *stream(request, signal) {
11001
11009
  const headers = {
@@ -11646,8 +11654,9 @@ function buildChain(options) {
11646
11654
  return clients;
11647
11655
  }
11648
11656
  function buildClient(name, routerOptions) {
11649
- const profile = getProviderProfile(name);
11650
- if (profile === void 0) return void 0;
11657
+ const baseProfile = getProviderProfile(name);
11658
+ if (baseProfile === void 0) return void 0;
11659
+ const profile = routerOptions.extractToolCallsFromContent === true && baseProfile.extractToolCallsFromContent !== true ? { ...baseProfile, extractToolCallsFromContent: true } : baseProfile;
11651
11660
  const ambient = currentCredentialPool(name);
11652
11661
  if (ambient !== void 0) {
11653
11662
  return new PoolAwareLlmClient(ambient, (apiKey) => selectTransport(profile, apiKey));
@@ -12048,11 +12057,13 @@ function buildLoopInputs(options, runId, userText) {
12048
12057
  const fallback = options.agentOptions.providers?.fallback;
12049
12058
  const apiKeys = options.agentOptions.providers?.apiKeys;
12050
12059
  const credentialPoolStrategy = options.agentOptions.providers?.credentialPoolStrategy;
12060
+ const extractToolCallsFromContent = options.agentOptions.providers?.routes?.[0]?.extractToolCallsFromContent;
12051
12061
  const chain = resolveProviderChain({
12052
12062
  primary,
12053
12063
  ...fallback !== void 0 ? { fallback } : {},
12054
12064
  ...apiKeys !== void 0 ? { apiKeys } : {},
12055
- ...credentialPoolStrategy !== void 0 ? { credentialPoolStrategy } : {}
12065
+ ...credentialPoolStrategy !== void 0 ? { credentialPoolStrategy } : {},
12066
+ ...extractToolCallsFromContent === true ? { extractToolCallsFromContent: true } : {}
12056
12067
  });
12057
12068
  const llm = chain.length === 1 ? chain[0] : new FallbackLlmClient(chain);
12058
12069
  return {