@theokit/sdk 2.11.2 → 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/CHANGELOG.md +12 -0
- package/dist/a2a/index.cjs +81 -3
- package/dist/a2a/index.cjs.map +1 -1
- package/dist/a2a/index.js +81 -3
- package/dist/a2a/index.js.map +1 -1
- package/dist/{cron-BRfFPEKY.d.ts → cron-BchPdvs2.d.ts} +7 -0
- package/dist/{cron-DOw-Hqol.d.cts → cron-Dv94Lgat.d.cts} +7 -0
- package/dist/cron.cjs +75 -3
- package/dist/cron.cjs.map +1 -1
- package/dist/cron.d.cts +1 -1
- package/dist/cron.d.ts +1 -1
- package/dist/cron.js +75 -3
- package/dist/cron.js.map +1 -1
- package/dist/eval.cjs +75 -3
- package/dist/eval.cjs.map +1 -1
- package/dist/eval.js +75 -3
- package/dist/eval.js.map +1 -1
- package/dist/index.cjs +75 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +75 -3
- package/dist/index.js.map +1 -1
- package/dist/internal/llm/hermes-tool-extract.d.ts +6 -0
- package/dist/internal/llm/openai.d.ts +19 -0
- package/dist/internal/providers/types.d.ts +7 -0
- package/package.json +14 -14
|
@@ -873,6 +873,13 @@ interface ProviderProfile {
|
|
|
873
873
|
fallbackModels: ReadonlyArray<string>;
|
|
874
874
|
extraHeaders?: Record<string, string>;
|
|
875
875
|
bodyOverrides?: Record<string, unknown>;
|
|
876
|
+
/**
|
|
877
|
+
* Opt-in leaked-dialect safe-parse (theokit#58 follow-up). When `true`, a chat_completions finish
|
|
878
|
+
* with ZERO native `tool_calls` has its assistant content scanned for the Hermes
|
|
879
|
+
* `<function=…></tool_call>` dialect and any recovered calls are surfaced as real `tool_calls`.
|
|
880
|
+
* Default off — only enable for routes/models known to leak (e.g. a qwen3-coder profile variant).
|
|
881
|
+
*/
|
|
882
|
+
extractToolCallsFromContent?: boolean;
|
|
876
883
|
}
|
|
877
884
|
|
|
878
885
|
type HookName = "pre_tool_call" | "post_tool_call" | "pre_llm_call" | "post_llm_call" | "on_session_start" | "on_session_end" | "transform_tool_result" | "transform_llm_output" | "pre_user_send" | "post_assistant_reply";
|
|
@@ -873,6 +873,13 @@ interface ProviderProfile {
|
|
|
873
873
|
fallbackModels: ReadonlyArray<string>;
|
|
874
874
|
extraHeaders?: Record<string, string>;
|
|
875
875
|
bodyOverrides?: Record<string, unknown>;
|
|
876
|
+
/**
|
|
877
|
+
* Opt-in leaked-dialect safe-parse (theokit#58 follow-up). When `true`, a chat_completions finish
|
|
878
|
+
* with ZERO native `tool_calls` has its assistant content scanned for the Hermes
|
|
879
|
+
* `<function=…></tool_call>` dialect and any recovered calls are surfaced as real `tool_calls`.
|
|
880
|
+
* Default off — only enable for routes/models known to leak (e.g. a qwen3-coder profile variant).
|
|
881
|
+
*/
|
|
882
|
+
extractToolCallsFromContent?: boolean;
|
|
876
883
|
}
|
|
877
884
|
|
|
878
885
|
type HookName = "pre_tool_call" | "post_tool_call" | "pre_llm_call" | "post_llm_call" | "on_session_start" | "on_session_end" | "transform_tool_result" | "transform_llm_output" | "pre_user_send" | "post_assistant_reply";
|
package/dist/cron.cjs
CHANGED
|
@@ -10956,6 +10956,35 @@ function toOllamaTools(tools) {
|
|
|
10956
10956
|
}));
|
|
10957
10957
|
}
|
|
10958
10958
|
|
|
10959
|
+
// src/internal/llm/hermes-tool-extract.ts
|
|
10960
|
+
var HERMES_BLOCK = /<function=\s*([^>\s]+)\s*>([\s\S]*?)<\/tool_call>/g;
|
|
10961
|
+
var HERMES_PARAM = /<parameter=\s*([^>\s]+)\s*>([\s\S]*?)<\/parameter>/g;
|
|
10962
|
+
function extractHermesToolCalls(content, makeId) {
|
|
10963
|
+
const toolCalls = [];
|
|
10964
|
+
for (const block of content.matchAll(HERMES_BLOCK)) {
|
|
10965
|
+
const name = (block[1] ?? "").trim();
|
|
10966
|
+
if (name.length === 0) continue;
|
|
10967
|
+
toolCalls.push({
|
|
10968
|
+
type: "tool_use",
|
|
10969
|
+
id: makeId(),
|
|
10970
|
+
name,
|
|
10971
|
+
input: parseHermesParams(block[2] ?? "")
|
|
10972
|
+
});
|
|
10973
|
+
}
|
|
10974
|
+
const residualText = toolCalls.length === 0 ? content : content.replace(HERMES_BLOCK, "").trim();
|
|
10975
|
+
return { toolCalls, residualText };
|
|
10976
|
+
}
|
|
10977
|
+
function parseHermesParams(inner) {
|
|
10978
|
+
const input = {};
|
|
10979
|
+
for (const param of inner.matchAll(HERMES_PARAM)) {
|
|
10980
|
+
const key = param[1];
|
|
10981
|
+
const value = param[2];
|
|
10982
|
+
if (key === void 0 || value === void 0) continue;
|
|
10983
|
+
input[key.trim()] = value;
|
|
10984
|
+
}
|
|
10985
|
+
return input;
|
|
10986
|
+
}
|
|
10987
|
+
|
|
10959
10988
|
// src/internal/llm/openai.ts
|
|
10960
10989
|
var OpenAIClient = class {
|
|
10961
10990
|
constructor(options) {
|
|
@@ -11017,7 +11046,10 @@ var OpenAIClient = class {
|
|
|
11017
11046
|
endpoint: "/v1/chat/completions"
|
|
11018
11047
|
});
|
|
11019
11048
|
}
|
|
11020
|
-
const accumulator = new OpenAIStreamAccumulator(
|
|
11049
|
+
const accumulator = new OpenAIStreamAccumulator(
|
|
11050
|
+
this.options.extractToolCallsFromContent ?? false,
|
|
11051
|
+
providerId
|
|
11052
|
+
);
|
|
11021
11053
|
for await (const record of parseSseStream(response.body, signal)) {
|
|
11022
11054
|
if (record.data === "[DONE]") break;
|
|
11023
11055
|
let chunk;
|
|
@@ -11026,6 +11058,16 @@ var OpenAIClient = class {
|
|
|
11026
11058
|
} catch {
|
|
11027
11059
|
continue;
|
|
11028
11060
|
}
|
|
11061
|
+
if (chunk.error !== void 0 && chunk.error !== null) {
|
|
11062
|
+
const status = typeof chunk.error.code === "number" ? chunk.error.code : 502;
|
|
11063
|
+
throw mapOpenAICompatibleError({
|
|
11064
|
+
providerId,
|
|
11065
|
+
status,
|
|
11066
|
+
body: chunk,
|
|
11067
|
+
headers: response.headers,
|
|
11068
|
+
endpoint: "/v1/chat/completions"
|
|
11069
|
+
});
|
|
11070
|
+
}
|
|
11029
11071
|
const events = accumulator.consume(chunk);
|
|
11030
11072
|
for (const event of events) yield event;
|
|
11031
11073
|
}
|
|
@@ -11033,6 +11075,16 @@ var OpenAIClient = class {
|
|
|
11033
11075
|
}
|
|
11034
11076
|
};
|
|
11035
11077
|
var OpenAIStreamAccumulator = class {
|
|
11078
|
+
/**
|
|
11079
|
+
* @param extractFromContent opt-in leaked-dialect safe-parse (theokit#58). Default false.
|
|
11080
|
+
* @param providerName provider id, used only to label the recovery log line.
|
|
11081
|
+
*/
|
|
11082
|
+
constructor(extractFromContent = false, providerName = "openai") {
|
|
11083
|
+
this.extractFromContent = extractFromContent;
|
|
11084
|
+
this.providerName = providerName;
|
|
11085
|
+
}
|
|
11086
|
+
extractFromContent;
|
|
11087
|
+
providerName;
|
|
11036
11088
|
text = "";
|
|
11037
11089
|
stopReason = "end_turn";
|
|
11038
11090
|
inputTokens;
|
|
@@ -11098,9 +11150,26 @@ var OpenAIStreamAccumulator = class {
|
|
|
11098
11150
|
const input = parseToolArguments(call.args);
|
|
11099
11151
|
toolCalls.push({ type: "tool_use", id: call.id, name: call.name, input });
|
|
11100
11152
|
}
|
|
11153
|
+
let text = this.text;
|
|
11154
|
+
let stopReason = this.stopReason;
|
|
11155
|
+
if (this.extractFromContent && toolCalls.length === 0) {
|
|
11156
|
+
const recovered = extractHermesToolCalls(
|
|
11157
|
+
this.text,
|
|
11158
|
+
() => `hermes-${globalThis.crypto.randomUUID()}`
|
|
11159
|
+
);
|
|
11160
|
+
if (recovered.toolCalls.length > 0) {
|
|
11161
|
+
toolCalls.push(...recovered.toolCalls);
|
|
11162
|
+
text = recovered.residualText;
|
|
11163
|
+
stopReason = "tool_use";
|
|
11164
|
+
process.stderr.write(
|
|
11165
|
+
`[theokit-sdk] recovered ${recovered.toolCalls.length} leaked tool call(s) from assistant content (provider="${this.providerName}", names=${recovered.toolCalls.map((c) => c.name).join(",")})
|
|
11166
|
+
`
|
|
11167
|
+
);
|
|
11168
|
+
}
|
|
11169
|
+
}
|
|
11101
11170
|
return makeLlmFinish({
|
|
11102
|
-
stopReason
|
|
11103
|
-
text
|
|
11171
|
+
stopReason,
|
|
11172
|
+
text,
|
|
11104
11173
|
toolCalls,
|
|
11105
11174
|
inputTokens: this.inputTokens,
|
|
11106
11175
|
outputTokens: this.outputTokens,
|
|
@@ -11680,6 +11749,9 @@ function selectTransport(profile, apiKey) {
|
|
|
11680
11749
|
const opts = { apiKey };
|
|
11681
11750
|
opts.baseUrl = profile.baseUrl;
|
|
11682
11751
|
opts.providerName = profile.name;
|
|
11752
|
+
if (profile.extractToolCallsFromContent === true) {
|
|
11753
|
+
opts.extractToolCallsFromContent = true;
|
|
11754
|
+
}
|
|
11683
11755
|
if (profile.name === "openai" && process.env.OPENAI_ORGANIZATION !== void 0) {
|
|
11684
11756
|
opts.organization = process.env.OPENAI_ORGANIZATION;
|
|
11685
11757
|
}
|