@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/CHANGELOG.md +6 -0
- package/dist/a2a/index.cjs +30 -7
- package/dist/a2a/index.cjs.map +1 -1
- package/dist/a2a/index.js +30 -7
- package/dist/a2a/index.js.map +1 -1
- package/dist/cron.cjs +30 -7
- package/dist/cron.cjs.map +1 -1
- package/dist/cron.js +30 -7
- package/dist/cron.js.map +1 -1
- package/dist/eval.cjs +30 -7
- package/dist/eval.cjs.map +1 -1
- package/dist/eval.js +30 -7
- package/dist/eval.js.map +1 -1
- package/dist/index.cjs +30 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +30 -7
- package/dist/index.js.map +1 -1
- package/dist/internal/llm/hermes-tool-extract.d.ts +5 -1
- package/dist/internal/llm/openai.d.ts +5 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.15.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- bec2077: Make the leaked-dialect recovery **request-scoped (R5)**. The opt-in `extractToolCallsFromContent` recovery previously promoted ANY `<function=NAME>` block leaked into assistant text on an enabled route, so a code assistant printing a literal `<function=example>` in a fenced code block could be wrongly turned into a tool call. Recovery now gates on an exact, case-sensitive allowlist derived automatically from the current request's declared tools (`request.tools`): the per-route flag stays the coarse enable, and the allowlist is the precise false-positive guard. A request with no tools recovers nothing; a gated-out block keeps its text visible (it is not silently deleted). No public API change — the allowlist is derived from the tools you already pass. Mirrors openclaw's `@openclaw/tool-call-repair` allowlist.
|
|
8
|
+
|
|
3
9
|
## 2.15.0
|
|
4
10
|
|
|
5
11
|
### Minor Changes
|
package/dist/a2a/index.cjs
CHANGED
|
@@ -10332,11 +10332,16 @@ var init_sanitize_tool_input = __esm({
|
|
|
10332
10332
|
});
|
|
10333
10333
|
|
|
10334
10334
|
// src/internal/llm/hermes-tool-extract.ts
|
|
10335
|
-
function extractHermesToolCalls(content, makeId) {
|
|
10335
|
+
function extractHermesToolCalls(content, makeId, allowedToolNames) {
|
|
10336
|
+
const isPromoted = (name) => name.length > 0 && (allowedToolNames === void 0 || allowedToolNames.has(name));
|
|
10336
10337
|
const toolCalls = [];
|
|
10338
|
+
const droppedNames = [];
|
|
10337
10339
|
for (const block of content.matchAll(HERMES_BLOCK)) {
|
|
10338
10340
|
const name = (block[1] ?? "").trim();
|
|
10339
|
-
if (name
|
|
10341
|
+
if (!isPromoted(name)) {
|
|
10342
|
+
if (name.length > 0 && allowedToolNames !== void 0) droppedNames.push(name);
|
|
10343
|
+
continue;
|
|
10344
|
+
}
|
|
10340
10345
|
toolCalls.push({
|
|
10341
10346
|
type: "tool_use",
|
|
10342
10347
|
id: makeId(),
|
|
@@ -10344,8 +10349,11 @@ function extractHermesToolCalls(content, makeId) {
|
|
|
10344
10349
|
input: parseHermesParams(block[2] ?? "")
|
|
10345
10350
|
});
|
|
10346
10351
|
}
|
|
10347
|
-
const residualText = toolCalls.length === 0 ? content : content.replace(
|
|
10348
|
-
|
|
10352
|
+
const residualText = toolCalls.length === 0 ? content : content.replace(
|
|
10353
|
+
HERMES_BLOCK,
|
|
10354
|
+
(full, rawName) => isPromoted((rawName ?? "").trim()) ? "" : full
|
|
10355
|
+
).trim();
|
|
10356
|
+
return { toolCalls, residualText, droppedNames };
|
|
10349
10357
|
}
|
|
10350
10358
|
function parseHermesParams(inner) {
|
|
10351
10359
|
const input = {};
|
|
@@ -10550,7 +10558,10 @@ var init_openai2 = __esm({
|
|
|
10550
10558
|
}
|
|
10551
10559
|
const accumulator = new OpenAIStreamAccumulator(
|
|
10552
10560
|
this.options.extractToolCallsFromContent ?? false,
|
|
10553
|
-
providerId
|
|
10561
|
+
providerId,
|
|
10562
|
+
// R5: request-scoped allowlist — leaked recovery only promotes a block whose name is a tool the
|
|
10563
|
+
// model was actually given. Empty set (no tools) recovers nothing.
|
|
10564
|
+
new Set(request.tools?.map((tool) => tool.name) ?? [])
|
|
10554
10565
|
);
|
|
10555
10566
|
for await (const record of parseSseStream(response.body, signal)) {
|
|
10556
10567
|
if (record.data === "[DONE]") break;
|
|
@@ -10580,13 +10591,18 @@ var init_openai2 = __esm({
|
|
|
10580
10591
|
/**
|
|
10581
10592
|
* @param extractFromContent opt-in leaked-dialect safe-parse (theokit#58). Default false.
|
|
10582
10593
|
* @param providerName provider id, used only to label the recovery log line.
|
|
10594
|
+
* @param allowedToolNames R5 request-scoped allowlist — built from `request.tools` at `stream()`;
|
|
10595
|
+
* leaked recovery in `finish()` only promotes a block whose name is in this set. `undefined`
|
|
10596
|
+
* (direct construction) recovers all (back-compat); an empty set recovers nothing.
|
|
10583
10597
|
*/
|
|
10584
|
-
constructor(extractFromContent = false, providerName = "openai") {
|
|
10598
|
+
constructor(extractFromContent = false, providerName = "openai", allowedToolNames) {
|
|
10585
10599
|
this.extractFromContent = extractFromContent;
|
|
10586
10600
|
this.providerName = providerName;
|
|
10601
|
+
this.allowedToolNames = allowedToolNames;
|
|
10587
10602
|
}
|
|
10588
10603
|
extractFromContent;
|
|
10589
10604
|
providerName;
|
|
10605
|
+
allowedToolNames;
|
|
10590
10606
|
text = "";
|
|
10591
10607
|
stopReason = "end_turn";
|
|
10592
10608
|
inputTokens;
|
|
@@ -10657,7 +10673,8 @@ var init_openai2 = __esm({
|
|
|
10657
10673
|
if (this.extractFromContent && toolCalls.length === 0) {
|
|
10658
10674
|
const recovered = extractHermesToolCalls(
|
|
10659
10675
|
this.text,
|
|
10660
|
-
() => `hermes-${globalThis.crypto.randomUUID()}
|
|
10676
|
+
() => `hermes-${globalThis.crypto.randomUUID()}`,
|
|
10677
|
+
this.allowedToolNames
|
|
10661
10678
|
);
|
|
10662
10679
|
if (recovered.toolCalls.length > 0) {
|
|
10663
10680
|
toolCalls.push(...recovered.toolCalls);
|
|
@@ -10665,6 +10682,12 @@ var init_openai2 = __esm({
|
|
|
10665
10682
|
stopReason = "tool_use";
|
|
10666
10683
|
process.stderr.write(
|
|
10667
10684
|
`[theokit-sdk] recovered ${recovered.toolCalls.length} leaked tool call(s) from assistant content (provider="${this.providerName}", names=${recovered.toolCalls.map((c) => c.name).join(",")})
|
|
10685
|
+
`
|
|
10686
|
+
);
|
|
10687
|
+
}
|
|
10688
|
+
if (recovered.droppedNames.length > 0) {
|
|
10689
|
+
process.stderr.write(
|
|
10690
|
+
`[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(",")})
|
|
10668
10691
|
`
|
|
10669
10692
|
);
|
|
10670
10693
|
}
|