@theokit/sdk 2.11.3 → 2.12.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/cron.d.cts CHANGED
@@ -1,2 +1,2 @@
1
1
  import './run-TMdc7gmo.cjs';
2
- export { K as Cron } from './cron-DOw-Hqol.cjs';
2
+ export { K as Cron } from './cron-Dv94Lgat.cjs';
package/dist/cron.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  import './run-TMdc7gmo.js';
2
- export { K as Cron } from './cron-BRfFPEKY.js';
2
+ export { K as Cron } from './cron-BchPdvs2.js';
package/dist/cron.js CHANGED
@@ -10953,6 +10953,35 @@ function toOllamaTools(tools) {
10953
10953
  }));
10954
10954
  }
10955
10955
 
10956
+ // src/internal/llm/hermes-tool-extract.ts
10957
+ var HERMES_BLOCK = /<function=\s*([^>\s]+)\s*>([\s\S]*?)<\/tool_call>/g;
10958
+ var HERMES_PARAM = /<parameter=\s*([^>\s]+)\s*>([\s\S]*?)<\/parameter>/g;
10959
+ function extractHermesToolCalls(content, makeId) {
10960
+ const toolCalls = [];
10961
+ for (const block of content.matchAll(HERMES_BLOCK)) {
10962
+ const name = (block[1] ?? "").trim();
10963
+ if (name.length === 0) continue;
10964
+ toolCalls.push({
10965
+ type: "tool_use",
10966
+ id: makeId(),
10967
+ name,
10968
+ input: parseHermesParams(block[2] ?? "")
10969
+ });
10970
+ }
10971
+ const residualText = toolCalls.length === 0 ? content : content.replace(HERMES_BLOCK, "").trim();
10972
+ return { toolCalls, residualText };
10973
+ }
10974
+ function parseHermesParams(inner) {
10975
+ const input = {};
10976
+ for (const param of inner.matchAll(HERMES_PARAM)) {
10977
+ const key = param[1];
10978
+ const value = param[2];
10979
+ if (key === void 0 || value === void 0) continue;
10980
+ input[key.trim()] = value;
10981
+ }
10982
+ return input;
10983
+ }
10984
+
10956
10985
  // src/internal/llm/openai.ts
10957
10986
  var OpenAIClient = class {
10958
10987
  constructor(options) {
@@ -11014,7 +11043,10 @@ var OpenAIClient = class {
11014
11043
  endpoint: "/v1/chat/completions"
11015
11044
  });
11016
11045
  }
11017
- const accumulator = new OpenAIStreamAccumulator();
11046
+ const accumulator = new OpenAIStreamAccumulator(
11047
+ this.options.extractToolCallsFromContent ?? false,
11048
+ providerId
11049
+ );
11018
11050
  for await (const record of parseSseStream(response.body, signal)) {
11019
11051
  if (record.data === "[DONE]") break;
11020
11052
  let chunk;
@@ -11040,6 +11072,16 @@ var OpenAIClient = class {
11040
11072
  }
11041
11073
  };
11042
11074
  var OpenAIStreamAccumulator = class {
11075
+ /**
11076
+ * @param extractFromContent opt-in leaked-dialect safe-parse (theokit#58). Default false.
11077
+ * @param providerName provider id, used only to label the recovery log line.
11078
+ */
11079
+ constructor(extractFromContent = false, providerName = "openai") {
11080
+ this.extractFromContent = extractFromContent;
11081
+ this.providerName = providerName;
11082
+ }
11083
+ extractFromContent;
11084
+ providerName;
11043
11085
  text = "";
11044
11086
  stopReason = "end_turn";
11045
11087
  inputTokens;
@@ -11105,9 +11147,26 @@ var OpenAIStreamAccumulator = class {
11105
11147
  const input = parseToolArguments(call.args);
11106
11148
  toolCalls.push({ type: "tool_use", id: call.id, name: call.name, input });
11107
11149
  }
11150
+ let text = this.text;
11151
+ let stopReason = this.stopReason;
11152
+ if (this.extractFromContent && toolCalls.length === 0) {
11153
+ const recovered = extractHermesToolCalls(
11154
+ this.text,
11155
+ () => `hermes-${globalThis.crypto.randomUUID()}`
11156
+ );
11157
+ if (recovered.toolCalls.length > 0) {
11158
+ toolCalls.push(...recovered.toolCalls);
11159
+ text = recovered.residualText;
11160
+ stopReason = "tool_use";
11161
+ process.stderr.write(
11162
+ `[theokit-sdk] recovered ${recovered.toolCalls.length} leaked tool call(s) from assistant content (provider="${this.providerName}", names=${recovered.toolCalls.map((c) => c.name).join(",")})
11163
+ `
11164
+ );
11165
+ }
11166
+ }
11108
11167
  return makeLlmFinish({
11109
- stopReason: this.stopReason,
11110
- text: this.text,
11168
+ stopReason,
11169
+ text,
11111
11170
  toolCalls,
11112
11171
  inputTokens: this.inputTokens,
11113
11172
  outputTokens: this.outputTokens,
@@ -11687,6 +11746,9 @@ function selectTransport(profile, apiKey) {
11687
11746
  const opts = { apiKey };
11688
11747
  opts.baseUrl = profile.baseUrl;
11689
11748
  opts.providerName = profile.name;
11749
+ if (profile.extractToolCallsFromContent === true) {
11750
+ opts.extractToolCallsFromContent = true;
11751
+ }
11690
11752
  if (profile.name === "openai" && process.env.OPENAI_ORGANIZATION !== void 0) {
11691
11753
  opts.organization = process.env.OPENAI_ORGANIZATION;
11692
11754
  }