@ykurilov/agent-chat-core 0.65.1 → 0.67.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 +15 -0
- package/dist/{chunk-4NQEQWGW.js → chunk-WMP5AKDU.js} +347 -225
- package/dist/chunk-WMP5AKDU.js.map +1 -0
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/storage-contract.js +1 -1
- package/dist/types/agent-run/premature-closer.d.ts +11 -0
- package/dist/types/agent-run/repair-tool-call.d.ts +21 -5
- package/dist/types/agent-run/run-agent-turn.d.ts +3 -0
- package/dist/types/agent-run/tool-arguments-repair.d.ts +21 -0
- package/dist/types/agent-run/unreadable-tool-input.d.ts +6 -0
- package/dist/types/chat-service.d.ts +8 -0
- package/dist/types/helpers/run-helper.d.ts +2 -0
- package/dist/types/index.d.ts +2 -0
- package/package.json +1 -1
- package/dist/chunk-4NQEQWGW.js.map +0 -1
|
@@ -2215,8 +2215,8 @@ function cutForgedBlocks(text, formats, options2 = {}) {
|
|
|
2215
2215
|
const scanner = createForgedBlockScanner(formats, options2);
|
|
2216
2216
|
const pieces = [...scanner.push(text), ...scanner.end()];
|
|
2217
2217
|
return {
|
|
2218
|
-
text: pieces.map((
|
|
2219
|
-
blocks: pieces.flatMap((
|
|
2218
|
+
text: pieces.map((piece2) => piece2.kind === "text" ? piece2.text : "").join(""),
|
|
2219
|
+
blocks: pieces.flatMap((piece2) => piece2.kind === "block" ? [piece2.name] : [])
|
|
2220
2220
|
};
|
|
2221
2221
|
}
|
|
2222
2222
|
var hasWords = (text) => /[\p{L}\p{N}]/u.test(text);
|
|
@@ -2286,16 +2286,16 @@ function createForgedBlockGuard(formats) {
|
|
|
2286
2286
|
};
|
|
2287
2287
|
const deltaOf = (id, pieces, controller) => {
|
|
2288
2288
|
let delta = "";
|
|
2289
|
-
for (const
|
|
2290
|
-
if (
|
|
2289
|
+
for (const piece2 of pieces) {
|
|
2290
|
+
if (piece2.kind === "text" && hasWords(piece2.text)) {
|
|
2291
2291
|
worded = true;
|
|
2292
2292
|
if (held) settle(false, controller);
|
|
2293
2293
|
}
|
|
2294
|
-
if (
|
|
2294
|
+
if (piece2.kind === "text" && !held) delta += piece2.text;
|
|
2295
2295
|
else if (worded) {
|
|
2296
|
-
if (
|
|
2296
|
+
if (piece2.kind === "block") cut.push(piece2.name);
|
|
2297
2297
|
} else {
|
|
2298
|
-
(held ??= []).push({ id, name:
|
|
2298
|
+
(held ??= []).push({ id, name: piece2.kind === "block" ? piece2.name : "", text: piece2.text });
|
|
2299
2299
|
}
|
|
2300
2300
|
}
|
|
2301
2301
|
return delta;
|
|
@@ -2512,6 +2512,230 @@ function contentFor(value, images) {
|
|
|
2512
2512
|
return value.some(isImage) ? [...kept, { type: "text", text: NO_IMAGE_NOTE }] : kept;
|
|
2513
2513
|
}
|
|
2514
2514
|
|
|
2515
|
+
// src/agent-run/json-repair.ts
|
|
2516
|
+
var VALID_JSON_ESCAPES = /* @__PURE__ */ new Set(['"', "\\", "/", "b", "f", "n", "r", "t"]);
|
|
2517
|
+
function isControlCharacter(char) {
|
|
2518
|
+
const codePoint = char.codePointAt(0);
|
|
2519
|
+
return codePoint !== void 0 && codePoint >= 0 && codePoint <= 31;
|
|
2520
|
+
}
|
|
2521
|
+
function escapeControlCharacter(char) {
|
|
2522
|
+
switch (char) {
|
|
2523
|
+
case "\b":
|
|
2524
|
+
return "\\b";
|
|
2525
|
+
case "\f":
|
|
2526
|
+
return "\\f";
|
|
2527
|
+
case "\n":
|
|
2528
|
+
return "\\n";
|
|
2529
|
+
case "\r":
|
|
2530
|
+
return "\\r";
|
|
2531
|
+
case " ":
|
|
2532
|
+
return "\\t";
|
|
2533
|
+
default:
|
|
2534
|
+
return `\\u${char.codePointAt(0)?.toString(16).padStart(4, "0") ?? "0000"}`;
|
|
2535
|
+
}
|
|
2536
|
+
}
|
|
2537
|
+
function repairJson(json) {
|
|
2538
|
+
let repaired = "";
|
|
2539
|
+
let inString = false;
|
|
2540
|
+
for (let index = 0; index < json.length; index++) {
|
|
2541
|
+
const char = json[index];
|
|
2542
|
+
if (!inString) {
|
|
2543
|
+
repaired += char;
|
|
2544
|
+
if (char === '"') inString = true;
|
|
2545
|
+
continue;
|
|
2546
|
+
}
|
|
2547
|
+
if (char === '"') {
|
|
2548
|
+
repaired += char;
|
|
2549
|
+
inString = false;
|
|
2550
|
+
continue;
|
|
2551
|
+
}
|
|
2552
|
+
if (char === "\\") {
|
|
2553
|
+
const nextChar = json[index + 1];
|
|
2554
|
+
if (nextChar === void 0) {
|
|
2555
|
+
repaired += "\\\\";
|
|
2556
|
+
continue;
|
|
2557
|
+
}
|
|
2558
|
+
if (nextChar === "u") {
|
|
2559
|
+
const unicodeDigits = json.slice(index + 2, index + 6);
|
|
2560
|
+
if (/^[0-9a-fA-F]{4}$/.test(unicodeDigits)) {
|
|
2561
|
+
repaired += `\\u${unicodeDigits}`;
|
|
2562
|
+
index += 5;
|
|
2563
|
+
continue;
|
|
2564
|
+
}
|
|
2565
|
+
}
|
|
2566
|
+
if (VALID_JSON_ESCAPES.has(nextChar)) {
|
|
2567
|
+
repaired += `\\${nextChar}`;
|
|
2568
|
+
index += 1;
|
|
2569
|
+
continue;
|
|
2570
|
+
}
|
|
2571
|
+
repaired += "\\\\";
|
|
2572
|
+
continue;
|
|
2573
|
+
}
|
|
2574
|
+
repaired += isControlCharacter(char) ? escapeControlCharacter(char) : char;
|
|
2575
|
+
}
|
|
2576
|
+
return repaired;
|
|
2577
|
+
}
|
|
2578
|
+
|
|
2579
|
+
// src/agent-run/missing-closers.ts
|
|
2580
|
+
var MAX_MISSING_CLOSERS = 3;
|
|
2581
|
+
var CLOSER = { "{": "}", "[": "]" };
|
|
2582
|
+
function addMissingClosers(json) {
|
|
2583
|
+
const open = [];
|
|
2584
|
+
let text = "";
|
|
2585
|
+
let added = 0;
|
|
2586
|
+
let last = "none";
|
|
2587
|
+
let inString = false;
|
|
2588
|
+
let stringIsKey = false;
|
|
2589
|
+
for (let index = 0; index < json.length; index++) {
|
|
2590
|
+
const char = json[index];
|
|
2591
|
+
if (inString) {
|
|
2592
|
+
text += char;
|
|
2593
|
+
if (char === "\\") {
|
|
2594
|
+
if (index + 1 >= json.length) return void 0;
|
|
2595
|
+
text += json[index + 1];
|
|
2596
|
+
index += 1;
|
|
2597
|
+
} else if (char === '"') {
|
|
2598
|
+
inString = false;
|
|
2599
|
+
last = stringIsKey ? "key" : "string";
|
|
2600
|
+
}
|
|
2601
|
+
continue;
|
|
2602
|
+
}
|
|
2603
|
+
if (/\s/.test(char)) {
|
|
2604
|
+
text += char;
|
|
2605
|
+
continue;
|
|
2606
|
+
}
|
|
2607
|
+
if (char === "}" || char === "]") {
|
|
2608
|
+
const depth = open.lastIndexOf(char === "}" ? "{" : "[");
|
|
2609
|
+
if (depth === -1) return void 0;
|
|
2610
|
+
const missing = open.length - 1 - depth;
|
|
2611
|
+
if (missing > 0) {
|
|
2612
|
+
if (last !== "string" && last !== "bare" && last !== "close") return void 0;
|
|
2613
|
+
for (let skipped = 0; skipped < missing; skipped++) text += CLOSER[open.pop()];
|
|
2614
|
+
added += missing;
|
|
2615
|
+
}
|
|
2616
|
+
open.pop();
|
|
2617
|
+
last = "close";
|
|
2618
|
+
} else if (char === "{" || char === "[") {
|
|
2619
|
+
open.push(char);
|
|
2620
|
+
last = "open";
|
|
2621
|
+
} else if (char === '"') {
|
|
2622
|
+
inString = true;
|
|
2623
|
+
stringIsKey = open.at(-1) === "{" && (last === "open" || last === "comma");
|
|
2624
|
+
} else if (char === ",") {
|
|
2625
|
+
last = "comma";
|
|
2626
|
+
} else if (char === ":") {
|
|
2627
|
+
last = "colon";
|
|
2628
|
+
} else {
|
|
2629
|
+
last = "bare";
|
|
2630
|
+
}
|
|
2631
|
+
text += char;
|
|
2632
|
+
}
|
|
2633
|
+
if (inString || last !== "string" && last !== "close") return void 0;
|
|
2634
|
+
added += open.length;
|
|
2635
|
+
while (open.length > 0) text += CLOSER[open.pop()];
|
|
2636
|
+
return added > 0 && added <= MAX_MISSING_CLOSERS ? { text, added } : void 0;
|
|
2637
|
+
}
|
|
2638
|
+
|
|
2639
|
+
// src/agent-run/premature-closer.ts
|
|
2640
|
+
function dropPrematureCloser(json) {
|
|
2641
|
+
const open = [];
|
|
2642
|
+
let inString = false;
|
|
2643
|
+
for (let index = 0; index < json.length; index++) {
|
|
2644
|
+
const char = json[index];
|
|
2645
|
+
if (inString) {
|
|
2646
|
+
if (char === "\\") index += 1;
|
|
2647
|
+
else if (char === '"') inString = false;
|
|
2648
|
+
continue;
|
|
2649
|
+
}
|
|
2650
|
+
if (char === '"') inString = true;
|
|
2651
|
+
else if (char === "{" || char === "[") open.push(char);
|
|
2652
|
+
else if (char === "}" || char === "]") {
|
|
2653
|
+
if (open.at(-1) !== (char === "}" ? "{" : "[")) return void 0;
|
|
2654
|
+
open.pop();
|
|
2655
|
+
if (open.length === 0) {
|
|
2656
|
+
const rest = json.slice(index + 1);
|
|
2657
|
+
if (!/^\s*,/.test(rest) || index === 0) return void 0;
|
|
2658
|
+
return { text: json.slice(0, index) + rest };
|
|
2659
|
+
}
|
|
2660
|
+
}
|
|
2661
|
+
}
|
|
2662
|
+
return void 0;
|
|
2663
|
+
}
|
|
2664
|
+
|
|
2665
|
+
// src/agent-run/stray-closers.ts
|
|
2666
|
+
var MAX_STRAY_CLOSERS = 2;
|
|
2667
|
+
function dropStrayClosers(json) {
|
|
2668
|
+
const open = [];
|
|
2669
|
+
let text = "";
|
|
2670
|
+
let inside = 0;
|
|
2671
|
+
let end = 0;
|
|
2672
|
+
let inString = false;
|
|
2673
|
+
let started = false;
|
|
2674
|
+
for (let index = 0; index < json.length; index++) {
|
|
2675
|
+
const char = json[index];
|
|
2676
|
+
if (inString) {
|
|
2677
|
+
text += char;
|
|
2678
|
+
if (char === "\\") {
|
|
2679
|
+
text += json[index + 1] ?? "";
|
|
2680
|
+
index += 1;
|
|
2681
|
+
} else if (char === '"') {
|
|
2682
|
+
inString = false;
|
|
2683
|
+
}
|
|
2684
|
+
continue;
|
|
2685
|
+
}
|
|
2686
|
+
const finished = started && open.length === 0;
|
|
2687
|
+
if (char === "}" || char === "]") {
|
|
2688
|
+
if (open.at(-1) === (char === "}" ? "{" : "[")) {
|
|
2689
|
+
open.pop();
|
|
2690
|
+
text += char;
|
|
2691
|
+
} else if (finished) {
|
|
2692
|
+
end += 1;
|
|
2693
|
+
} else if (open.length > 0) {
|
|
2694
|
+
inside += 1;
|
|
2695
|
+
} else {
|
|
2696
|
+
return void 0;
|
|
2697
|
+
}
|
|
2698
|
+
continue;
|
|
2699
|
+
}
|
|
2700
|
+
if (finished && !/\s/.test(char)) return void 0;
|
|
2701
|
+
if (char === "{" || char === "[") {
|
|
2702
|
+
open.push(char);
|
|
2703
|
+
started = true;
|
|
2704
|
+
} else if (char === '"') {
|
|
2705
|
+
inString = true;
|
|
2706
|
+
}
|
|
2707
|
+
text += char;
|
|
2708
|
+
}
|
|
2709
|
+
const dropped = inside + end;
|
|
2710
|
+
if (dropped === 0 || dropped > MAX_STRAY_CLOSERS || inString || open.length > 0) return void 0;
|
|
2711
|
+
return { text, inside, end };
|
|
2712
|
+
}
|
|
2713
|
+
|
|
2714
|
+
// src/agent-run/tool-arguments-repair.ts
|
|
2715
|
+
function parseArgumentsLoosely(json) {
|
|
2716
|
+
const none = { inside: 0, end: 0 };
|
|
2717
|
+
const attempts = [
|
|
2718
|
+
{ text: json, strayClosers: none, missingClosers: 0 },
|
|
2719
|
+
...optional(dropStrayClosers(json), (fix) => ({ text: fix.text, strayClosers: { inside: fix.inside, end: fix.end }, missingClosers: 0 })),
|
|
2720
|
+
...optional(addMissingClosers(json), (fix) => ({ text: fix.text, strayClosers: none, missingClosers: fix.added })),
|
|
2721
|
+
...optional(dropPrematureCloser(json), (fix) => ({ text: fix.text, strayClosers: { inside: 1, end: 0 }, missingClosers: 0 }))
|
|
2722
|
+
];
|
|
2723
|
+
for (const { text, ...rest } of attempts) {
|
|
2724
|
+
try {
|
|
2725
|
+
return { value: JSON.parse(text), ...rest };
|
|
2726
|
+
} catch {
|
|
2727
|
+
}
|
|
2728
|
+
}
|
|
2729
|
+
return void 0;
|
|
2730
|
+
}
|
|
2731
|
+
function repairToolArguments(text) {
|
|
2732
|
+
const parsed = parseArgumentsLoosely(repairJson(text));
|
|
2733
|
+
return parsed === void 0 ? void 0 : JSON.stringify(parsed.value);
|
|
2734
|
+
}
|
|
2735
|
+
function optional(fix, toAttempt) {
|
|
2736
|
+
return fix === void 0 ? [] : [toAttempt(fix)];
|
|
2737
|
+
}
|
|
2738
|
+
|
|
2515
2739
|
// src/storage/chat-storage.ts
|
|
2516
2740
|
var RELEASED_ANSWER_ALIVE_AT = (/* @__PURE__ */ new Date(0)).toISOString();
|
|
2517
2741
|
function aliveAtByLocalClock(mark) {
|
|
@@ -4169,9 +4393,9 @@ function createStepCacheMarks(mark) {
|
|
|
4169
4393
|
const carried = previous;
|
|
4170
4394
|
const unmarked = carried ? messages.map((message) => message === carried.marked ? carried.original : message) : messages;
|
|
4171
4395
|
const original = unmarked[unmarked.length - 1];
|
|
4172
|
-
const
|
|
4173
|
-
previous = { marked, original };
|
|
4174
|
-
return [...unmarked.slice(0, -1),
|
|
4396
|
+
const marked2 = withCacheMark(original, mark);
|
|
4397
|
+
previous = { marked: marked2, original };
|
|
4398
|
+
return [...unmarked.slice(0, -1), marked2];
|
|
4175
4399
|
}
|
|
4176
4400
|
};
|
|
4177
4401
|
}
|
|
@@ -4327,7 +4551,7 @@ function undeliveredIdsOf(messages) {
|
|
|
4327
4551
|
for (const [path, value] of Object.entries(set)) {
|
|
4328
4552
|
if (path.startsWith(prefix) && value === true) ids.add(path.slice(prefix.length));
|
|
4329
4553
|
else if (path === UNDELIVERED_STATE_KEY && typeof value === "object" && value !== null) {
|
|
4330
|
-
for (const [id,
|
|
4554
|
+
for (const [id, marked2] of Object.entries(value)) if (marked2 === true) ids.add(id);
|
|
4331
4555
|
}
|
|
4332
4556
|
}
|
|
4333
4557
|
}
|
|
@@ -5061,252 +5285,127 @@ function checkProviderFallback(setting, catalog) {
|
|
|
5061
5285
|
// src/agent-run/repair-tool-call.ts
|
|
5062
5286
|
import { InvalidToolInputError, asSchema as asSchema2 } from "ai";
|
|
5063
5287
|
|
|
5064
|
-
// src/agent-run/
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
function
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
|
|
5078
|
-
|
|
5079
|
-
|
|
5080
|
-
|
|
5081
|
-
|
|
5082
|
-
|
|
5083
|
-
|
|
5084
|
-
}
|
|
5085
|
-
}
|
|
5086
|
-
|
|
5087
|
-
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
}
|
|
5096
|
-
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
continue;
|
|
5106
|
-
}
|
|
5107
|
-
if (nextChar === "u") {
|
|
5108
|
-
const unicodeDigits = json.slice(index + 2, index + 6);
|
|
5109
|
-
if (/^[0-9a-fA-F]{4}$/.test(unicodeDigits)) {
|
|
5110
|
-
repaired += `\\u${unicodeDigits}`;
|
|
5111
|
-
index += 5;
|
|
5112
|
-
continue;
|
|
5113
|
-
}
|
|
5114
|
-
}
|
|
5115
|
-
if (VALID_JSON_ESCAPES.has(nextChar)) {
|
|
5116
|
-
repaired += `\\${nextChar}`;
|
|
5117
|
-
index += 1;
|
|
5118
|
-
continue;
|
|
5119
|
-
}
|
|
5120
|
-
repaired += "\\\\";
|
|
5121
|
-
continue;
|
|
5122
|
-
}
|
|
5123
|
-
repaired += isControlCharacter(char) ? escapeControlCharacter(char) : char;
|
|
5124
|
-
}
|
|
5125
|
-
return repaired;
|
|
5126
|
-
}
|
|
5127
|
-
|
|
5128
|
-
// src/agent-run/missing-closers.ts
|
|
5129
|
-
var MAX_MISSING_CLOSERS = 3;
|
|
5130
|
-
var CLOSER = { "{": "}", "[": "]" };
|
|
5131
|
-
function addMissingClosers(json) {
|
|
5132
|
-
const open = [];
|
|
5133
|
-
let text = "";
|
|
5134
|
-
let added = 0;
|
|
5135
|
-
let last = "none";
|
|
5136
|
-
let inString = false;
|
|
5137
|
-
let stringIsKey = false;
|
|
5138
|
-
for (let index = 0; index < json.length; index++) {
|
|
5139
|
-
const char = json[index];
|
|
5140
|
-
if (inString) {
|
|
5141
|
-
text += char;
|
|
5142
|
-
if (char === "\\") {
|
|
5143
|
-
if (index + 1 >= json.length) return void 0;
|
|
5144
|
-
text += json[index + 1];
|
|
5145
|
-
index += 1;
|
|
5146
|
-
} else if (char === '"') {
|
|
5147
|
-
inString = false;
|
|
5148
|
-
last = stringIsKey ? "key" : "string";
|
|
5149
|
-
}
|
|
5150
|
-
continue;
|
|
5151
|
-
}
|
|
5152
|
-
if (/\s/.test(char)) {
|
|
5153
|
-
text += char;
|
|
5154
|
-
continue;
|
|
5155
|
-
}
|
|
5156
|
-
if (char === "}" || char === "]") {
|
|
5157
|
-
const depth = open.lastIndexOf(char === "}" ? "{" : "[");
|
|
5158
|
-
if (depth === -1) return void 0;
|
|
5159
|
-
const missing = open.length - 1 - depth;
|
|
5160
|
-
if (missing > 0) {
|
|
5161
|
-
if (last !== "string" && last !== "bare" && last !== "close") return void 0;
|
|
5162
|
-
for (let skipped = 0; skipped < missing; skipped++) text += CLOSER[open.pop()];
|
|
5163
|
-
added += missing;
|
|
5164
|
-
}
|
|
5165
|
-
open.pop();
|
|
5166
|
-
last = "close";
|
|
5167
|
-
} else if (char === "{" || char === "[") {
|
|
5168
|
-
open.push(char);
|
|
5169
|
-
last = "open";
|
|
5170
|
-
} else if (char === '"') {
|
|
5171
|
-
inString = true;
|
|
5172
|
-
stringIsKey = open.at(-1) === "{" && (last === "open" || last === "comma");
|
|
5173
|
-
} else if (char === ",") {
|
|
5174
|
-
last = "comma";
|
|
5175
|
-
} else if (char === ":") {
|
|
5176
|
-
last = "colon";
|
|
5177
|
-
} else {
|
|
5178
|
-
last = "bare";
|
|
5179
|
-
}
|
|
5180
|
-
text += char;
|
|
5181
|
-
}
|
|
5182
|
-
if (inString || last !== "string" && last !== "close") return void 0;
|
|
5183
|
-
added += open.length;
|
|
5184
|
-
while (open.length > 0) text += CLOSER[open.pop()];
|
|
5185
|
-
return added > 0 && added <= MAX_MISSING_CLOSERS ? { text, added } : void 0;
|
|
5186
|
-
}
|
|
5187
|
-
|
|
5188
|
-
// src/agent-run/stray-closers.ts
|
|
5189
|
-
var MAX_STRAY_CLOSERS = 2;
|
|
5190
|
-
function dropStrayClosers(json) {
|
|
5191
|
-
const open = [];
|
|
5192
|
-
let text = "";
|
|
5193
|
-
let inside = 0;
|
|
5194
|
-
let end = 0;
|
|
5195
|
-
let inString = false;
|
|
5196
|
-
let started = false;
|
|
5197
|
-
for (let index = 0; index < json.length; index++) {
|
|
5198
|
-
const char = json[index];
|
|
5199
|
-
if (inString) {
|
|
5200
|
-
text += char;
|
|
5201
|
-
if (char === "\\") {
|
|
5202
|
-
text += json[index + 1] ?? "";
|
|
5203
|
-
index += 1;
|
|
5204
|
-
} else if (char === '"') {
|
|
5205
|
-
inString = false;
|
|
5206
|
-
}
|
|
5207
|
-
continue;
|
|
5208
|
-
}
|
|
5209
|
-
const finished = started && open.length === 0;
|
|
5210
|
-
if (char === "}" || char === "]") {
|
|
5211
|
-
if (open.at(-1) === (char === "}" ? "{" : "[")) {
|
|
5212
|
-
open.pop();
|
|
5213
|
-
text += char;
|
|
5214
|
-
} else if (finished) {
|
|
5215
|
-
end += 1;
|
|
5216
|
-
} else if (open.length > 0) {
|
|
5217
|
-
inside += 1;
|
|
5218
|
-
} else {
|
|
5219
|
-
return void 0;
|
|
5220
|
-
}
|
|
5221
|
-
continue;
|
|
5222
|
-
}
|
|
5223
|
-
if (finished && !/\s/.test(char)) return void 0;
|
|
5224
|
-
if (char === "{" || char === "[") {
|
|
5225
|
-
open.push(char);
|
|
5226
|
-
started = true;
|
|
5227
|
-
} else if (char === '"') {
|
|
5228
|
-
inString = true;
|
|
5229
|
-
}
|
|
5230
|
-
text += char;
|
|
5231
|
-
}
|
|
5232
|
-
const dropped = inside + end;
|
|
5233
|
-
if (dropped === 0 || dropped > MAX_STRAY_CLOSERS || inString || open.length > 0) return void 0;
|
|
5234
|
-
return { text, inside, end };
|
|
5288
|
+
// src/agent-run/unreadable-tool-input.ts
|
|
5289
|
+
import { JSONParseError, TypeValidationError } from "ai";
|
|
5290
|
+
var MAX_PIECE = 30;
|
|
5291
|
+
var MAX_ISSUES = 3;
|
|
5292
|
+
var MAX_ISSUE_LENGTH = 120;
|
|
5293
|
+
var RETRY_NOTE = "\u043F\u0440\u0438\u0448\u043B\u0438 \u0432\u044B\u0437\u043E\u0432 \u0437\u0430\u043D\u043E\u0432\u043E";
|
|
5294
|
+
function describeUnreadableToolInput(error, input) {
|
|
5295
|
+
const cause = error instanceof Error ? error.cause : void 0;
|
|
5296
|
+
if (JSONParseError.isInstance(cause)) return describeBrokenJson(cause, input);
|
|
5297
|
+
if (TypeValidationError.isInstance(cause)) return describeSchemaMismatch(cause);
|
|
5298
|
+
return `\u0430\u0440\u0433\u0443\u043C\u0435\u043D\u0442\u044B \u043D\u0435 \u043F\u043E\u0434\u0445\u043E\u0434\u044F\u0442 \u0438\u043D\u0441\u0442\u0440\u0443\u043C\u0435\u043D\u0442\u0443; ${RETRY_NOTE}`;
|
|
5299
|
+
}
|
|
5300
|
+
function describeBrokenJson(error, input) {
|
|
5301
|
+
const reason = error.cause instanceof Error ? error.cause.message : "";
|
|
5302
|
+
const position = /position (\d+)/.exec(reason)?.[1];
|
|
5303
|
+
if (position === void 0) {
|
|
5304
|
+
return `\u0430\u0440\u0433\u0443\u043C\u0435\u043D\u0442\u044B \u043D\u0435 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u044E\u0442\u0441\u044F \u043A\u0430\u043A JSON: \u0442\u0435\u043A\u0441\u0442 \u043E\u0431\u043E\u0440\u0432\u0430\u043D \u043D\u0430 \u043F\u043E\u0437\u0438\u0446\u0438\u0438 ${input.length} (\u2026${piece(input, input.length)}); ${RETRY_NOTE}`;
|
|
5305
|
+
}
|
|
5306
|
+
const at = Number(position);
|
|
5307
|
+
const char = input[at];
|
|
5308
|
+
const what = char === "}" || char === "]" ? `\u043B\u0438\u0448\u043D\u044F\u044F \`${char}\`` : "\u043E\u0448\u0438\u0431\u043A\u0430";
|
|
5309
|
+
return `\u0430\u0440\u0433\u0443\u043C\u0435\u043D\u0442\u044B \u043D\u0435 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u044E\u0442\u0441\u044F \u043A\u0430\u043A JSON: ${what} \u043E\u043A\u043E\u043B\u043E \u043F\u043E\u0437\u0438\u0446\u0438\u0438 ${at} (\u2026${piece(input, at)}\u2026); ${RETRY_NOTE}`;
|
|
5310
|
+
}
|
|
5311
|
+
function piece(input, at) {
|
|
5312
|
+
const start = Math.max(0, at - MAX_PIECE / 2);
|
|
5313
|
+
return JSON.stringify(input.slice(start, start + MAX_PIECE)).slice(1, -1);
|
|
5314
|
+
}
|
|
5315
|
+
function describeSchemaMismatch(error) {
|
|
5316
|
+
const issues = error.cause?.issues;
|
|
5317
|
+
if (!Array.isArray(issues) || issues.length === 0) {
|
|
5318
|
+
const text = error.cause instanceof Error ? error.cause.message : "\u043D\u0435 \u043F\u043E\u0434\u0445\u043E\u0434\u044F\u0442 \u043F\u043E \u0441\u0445\u0435\u043C\u0435";
|
|
5319
|
+
return `\u0430\u0440\u0433\u0443\u043C\u0435\u043D\u0442\u044B \u043D\u0435 \u043F\u043E\u0434\u0445\u043E\u0434\u044F\u0442 \u043F\u043E \u0441\u0445\u0435\u043C\u0435: ${text.slice(0, MAX_ISSUE_LENGTH)}; ${RETRY_NOTE}`;
|
|
5320
|
+
}
|
|
5321
|
+
const listed = issues.slice(0, MAX_ISSUES).map(describeIssue).join("; ");
|
|
5322
|
+
const rest = issues.length > MAX_ISSUES ? ` (\u0438 \u0435\u0449\u0451 ${issues.length - MAX_ISSUES})` : "";
|
|
5323
|
+
return `\u0430\u0440\u0433\u0443\u043C\u0435\u043D\u0442\u044B \u043D\u0435 \u043F\u043E\u0434\u0445\u043E\u0434\u044F\u0442 \u043F\u043E \u0441\u0445\u0435\u043C\u0435 \u2014 ${listed}${rest}; ${RETRY_NOTE}, \u043F\u043E\u043F\u0440\u0430\u0432\u0438\u0432 \u044D\u0442\u0438 \u043F\u043E\u043B\u044F`;
|
|
5324
|
+
}
|
|
5325
|
+
function describeIssue(issue) {
|
|
5326
|
+
const { path, message } = issue;
|
|
5327
|
+
const where = Array.isArray(path) && path.length > 0 ? path.join(".") : "\u0430\u0440\u0433\u0443\u043C\u0435\u043D\u0442\u044B";
|
|
5328
|
+
return `${where}: ${String(message ?? "\u043D\u0435\u0432\u0435\u0440\u043D\u043E\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435").slice(0, MAX_ISSUE_LENGTH)}`;
|
|
5235
5329
|
}
|
|
5236
5330
|
|
|
5237
5331
|
// src/agent-run/repair-tool-call.ts
|
|
5238
5332
|
function createRepairToolCall(options2 = {}) {
|
|
5239
5333
|
return async ({ toolCall, tools, error, inputSchema }) => {
|
|
5240
5334
|
if (!InvalidToolInputError.isInstance(error)) return null;
|
|
5241
|
-
const escaped = repairJson(toolCall.input);
|
|
5242
|
-
const parsed = parseWithClosers(escaped);
|
|
5243
|
-
if (!parsed) return null;
|
|
5244
5335
|
const schema = await inputSchema({ toolName: toolCall.toolName });
|
|
5245
|
-
const
|
|
5246
|
-
const
|
|
5247
|
-
|
|
5248
|
-
|
|
5336
|
+
const toolSchema = tools[toolCall.toolName]?.inputSchema;
|
|
5337
|
+
const attempt = async (text, byApp) => {
|
|
5338
|
+
const escaped = repairJson(text);
|
|
5339
|
+
const parsed = parseArgumentsLoosely(escaped);
|
|
5340
|
+
if (!parsed) return void 0;
|
|
5341
|
+
const tally = { inside: parsed.strayClosers.inside, end: parsed.strayClosers.end, missing: parsed.missingClosers, nested: false, types: false };
|
|
5342
|
+
const coerced = coerceBySchema(parsed.value, schema, tally);
|
|
5343
|
+
if (!await passesSchema(toolSchema, coerced)) return void 0;
|
|
5344
|
+
options2.onRepaired?.({
|
|
5249
5345
|
toolName: toolCall.toolName,
|
|
5250
5346
|
inputLength: toolCall.input.length,
|
|
5251
|
-
strayClosers:
|
|
5252
|
-
missingClosers:
|
|
5253
|
-
|
|
5254
|
-
|
|
5347
|
+
strayClosers: { inside: tally.inside, end: tally.end },
|
|
5348
|
+
missingClosers: tally.missing,
|
|
5349
|
+
nestedJson: tally.nested,
|
|
5350
|
+
byApp,
|
|
5351
|
+
strings: escaped !== text,
|
|
5352
|
+
types: tally.types
|
|
5255
5353
|
});
|
|
5256
|
-
|
|
5257
|
-
|
|
5354
|
+
return JSON.stringify(coerced);
|
|
5355
|
+
};
|
|
5356
|
+
const builtIn = await attempt(toolCall.input, false);
|
|
5357
|
+
if (builtIn !== void 0) return { ...toolCall, input: builtIn };
|
|
5358
|
+
const fromApp = await askApp(options2.repairToolInput, { toolName: toolCall.toolName, text: toolCall.input, error });
|
|
5359
|
+
const repaired = fromApp === void 0 ? void 0 : await attempt(fromApp, true);
|
|
5360
|
+
if (repaired !== void 0) return { ...toolCall, input: repaired };
|
|
5361
|
+
error.message = `Invalid input for tool ${toolCall.toolName}: ${describeUnreadableToolInput(error, toolCall.input)}`;
|
|
5362
|
+
return null;
|
|
5258
5363
|
};
|
|
5259
5364
|
}
|
|
5365
|
+
async function askApp(repair, call) {
|
|
5366
|
+
if (!repair) return void 0;
|
|
5367
|
+
try {
|
|
5368
|
+
const text = await repair(call);
|
|
5369
|
+
return typeof text === "string" ? text : void 0;
|
|
5370
|
+
} catch {
|
|
5371
|
+
return void 0;
|
|
5372
|
+
}
|
|
5373
|
+
}
|
|
5260
5374
|
function describeToolInputRepair(repair, where) {
|
|
5261
5375
|
const fixes = [
|
|
5262
5376
|
...repair.strayClosers.inside > 0 ? [`\u043B\u0438\u0448\u043D\u0438\u0435 \u0441\u043A\u043E\u0431\u043A\u0438 \u0432\u043D\u0443\u0442\u0440\u0438 \xD7${repair.strayClosers.inside}`] : [],
|
|
5263
5377
|
...repair.strayClosers.end > 0 ? [`\u043B\u0438\u0448\u043D\u0438\u0435 \u0441\u043A\u043E\u0431\u043A\u0438 \u0432 \u043A\u043E\u043D\u0446\u0435 \xD7${repair.strayClosers.end}`] : [],
|
|
5264
5378
|
...repair.missingClosers > 0 ? [`\u0434\u043E\u043F\u0438\u0441\u0430\u043D\u044B \u0441\u043A\u043E\u0431\u043A\u0438 \xD7${repair.missingClosers}`] : [],
|
|
5379
|
+
...repair.nestedJson ? ["JSON \u0438\u0437 \u0441\u0442\u0440\u043E\u043A\u0438"] : [],
|
|
5265
5380
|
...repair.strings ? ["\u0437\u0430\u043F\u0438\u0441\u0438 \u0432 \u0441\u0442\u0440\u043E\u043A\u0430\u0445"] : [],
|
|
5266
|
-
...repair.types ? ["\u0442\u0438\u043F\u044B \u043F\u043E \u0441\u0445\u0435\u043C\u0435"] : []
|
|
5381
|
+
...repair.types ? ["\u0442\u0438\u043F\u044B \u043F\u043E \u0441\u0445\u0435\u043C\u0435"] : [],
|
|
5382
|
+
...repair.byApp ? ["\u043F\u0440\u0430\u0432\u043A\u0430 \u043F\u0440\u0438\u043B\u043E\u0436\u0435\u043D\u0438\u044F"] : []
|
|
5267
5383
|
];
|
|
5268
5384
|
return `[\u0430\u0440\u0433\u0443\u043C\u0435\u043D\u0442\u044B \u043F\u043E\u0447\u0438\u043D\u0435\u043D\u044B] \u0447\u0430\u0442=${where.chatId} \u0438\u043D\u0441\u0442\u0440\u0443\u043C\u0435\u043D\u0442=${repair.toolName} \u043C\u043E\u0434\u0435\u043B\u044C=${where.modelId} \u043F\u0440\u043E\u0432\u0430\u0439\u0434\u0435\u0440=${where.providerId} \u043F\u0440\u0430\u0432\u043A\u0430=${fixes.join(", ")} \u0434\u043B\u0438\u043D\u0430=${repair.inputLength}`;
|
|
5269
5385
|
}
|
|
5270
|
-
function parseWithClosers(json) {
|
|
5271
|
-
const none = { inside: 0, end: 0 };
|
|
5272
|
-
const attempts = [
|
|
5273
|
-
{ text: json, strayClosers: none, missingClosers: 0 },
|
|
5274
|
-
...optional(dropStrayClosers(json), (fix) => ({ text: fix.text, strayClosers: { inside: fix.inside, end: fix.end }, missingClosers: 0 })),
|
|
5275
|
-
...optional(addMissingClosers(json), (fix) => ({ text: fix.text, strayClosers: none, missingClosers: fix.added }))
|
|
5276
|
-
];
|
|
5277
|
-
for (const { text, ...rest } of attempts) {
|
|
5278
|
-
try {
|
|
5279
|
-
return { value: JSON.parse(text), ...rest };
|
|
5280
|
-
} catch {
|
|
5281
|
-
}
|
|
5282
|
-
}
|
|
5283
|
-
return void 0;
|
|
5284
|
-
}
|
|
5285
|
-
function optional(fix, toAttempt) {
|
|
5286
|
-
return fix === void 0 ? [] : [toAttempt(fix)];
|
|
5287
|
-
}
|
|
5288
5386
|
async function passesSchema(schema, value) {
|
|
5289
5387
|
if (schema === void 0) return false;
|
|
5290
5388
|
const validate = asSchema2(schema).validate;
|
|
5291
5389
|
return validate ? (await validate(value)).success : true;
|
|
5292
5390
|
}
|
|
5293
|
-
function coerceBySchema(value, schema) {
|
|
5391
|
+
function coerceBySchema(value, schema, tally) {
|
|
5294
5392
|
if (typeof schema !== "object") return value;
|
|
5295
5393
|
const types = Array.isArray(schema.type) ? schema.type : schema.type ? [schema.type] : [];
|
|
5296
5394
|
if (typeof value === "string") {
|
|
5297
5395
|
if (types.includes("string")) return value;
|
|
5298
|
-
if (types.includes("integer") || types.includes("number")) return numberFrom(value, types.includes("number"))
|
|
5299
|
-
if (types.includes("boolean")) return value === "true" ? true : value === "false" ? false : value;
|
|
5396
|
+
if (types.includes("integer") || types.includes("number")) return marked(numberFrom(value, types.includes("number")), value, tally);
|
|
5397
|
+
if (types.includes("boolean")) return marked(value === "true" ? true : value === "false" ? false : void 0, value, tally);
|
|
5398
|
+
if (types.includes("array") || types.includes("object")) return parseNestedJson(value, schema, tally);
|
|
5300
5399
|
return value;
|
|
5301
5400
|
}
|
|
5302
5401
|
if (Array.isArray(value)) {
|
|
5303
5402
|
const items = Array.isArray(schema.items) ? void 0 : schema.items;
|
|
5304
|
-
return value.map((item) => coerceBySchema(item, items));
|
|
5403
|
+
return value.map((item) => coerceBySchema(item, items, tally));
|
|
5305
5404
|
}
|
|
5306
5405
|
if (typeof value === "object" && value !== null) {
|
|
5307
5406
|
const properties = schema.properties ?? {};
|
|
5308
5407
|
return Object.fromEntries(
|
|
5309
|
-
Object.entries(value).map(([key, property]) => [key, coerceBySchema(property, properties[key])])
|
|
5408
|
+
Object.entries(value).map(([key, property]) => [key, coerceBySchema(property, properties[key], tally)])
|
|
5310
5409
|
);
|
|
5311
5410
|
}
|
|
5312
5411
|
return value;
|
|
@@ -5317,6 +5416,21 @@ function numberFrom(text, allowFraction) {
|
|
|
5317
5416
|
if (!Number.isFinite(number)) return void 0;
|
|
5318
5417
|
return allowFraction || Number.isInteger(number) ? number : void 0;
|
|
5319
5418
|
}
|
|
5419
|
+
function marked(coerced, original, tally) {
|
|
5420
|
+
if (coerced === void 0) return original;
|
|
5421
|
+
tally.types = true;
|
|
5422
|
+
return coerced;
|
|
5423
|
+
}
|
|
5424
|
+
function parseNestedJson(text, schema, tally) {
|
|
5425
|
+
if (!/^\s*[[{]/.test(text)) return text;
|
|
5426
|
+
const parsed = parseArgumentsLoosely(repairJson(text));
|
|
5427
|
+
if (!parsed) return text;
|
|
5428
|
+
tally.nested = true;
|
|
5429
|
+
tally.inside += parsed.strayClosers.inside;
|
|
5430
|
+
tally.end += parsed.strayClosers.end;
|
|
5431
|
+
tally.missing += parsed.missingClosers;
|
|
5432
|
+
return coerceBySchema(parsed.value, schema, tally);
|
|
5433
|
+
}
|
|
5320
5434
|
|
|
5321
5435
|
// src/agent-run/run-agent-turn.ts
|
|
5322
5436
|
import { stepCountIs, streamText } from "ai";
|
|
@@ -6227,9 +6341,9 @@ function trackToolErrors(tools, options2 = {}) {
|
|
|
6227
6341
|
const thrownByTools = /* @__PURE__ */ new WeakSet();
|
|
6228
6342
|
const scrub = (text) => scrubSecrets(text, secrets);
|
|
6229
6343
|
function remember(error) {
|
|
6230
|
-
const
|
|
6231
|
-
thrownByTools.add(
|
|
6232
|
-
throw
|
|
6344
|
+
const marked2 = withoutSecrets(typeof error === "object" && error !== null ? error : new Error(String(error)), scrub);
|
|
6345
|
+
thrownByTools.add(marked2);
|
|
6346
|
+
throw marked2;
|
|
6233
6347
|
}
|
|
6234
6348
|
const tracked = {};
|
|
6235
6349
|
for (const [name, original] of Object.entries(tools ?? {})) {
|
|
@@ -7355,6 +7469,7 @@ async function openAttempt(input, attempt, attemptSignal) {
|
|
|
7355
7469
|
memory: _memory,
|
|
7356
7470
|
resume: _resume,
|
|
7357
7471
|
toolTimeout: _toolTimeout,
|
|
7472
|
+
repairToolInput: _repairToolInput,
|
|
7358
7473
|
sequentialTools: _sequentialTools,
|
|
7359
7474
|
now: _now,
|
|
7360
7475
|
usageSource: _usageSource,
|
|
@@ -7482,6 +7597,7 @@ async function openAttempt(input, attempt, attemptSignal) {
|
|
|
7482
7597
|
abortSignal: attemptSignal,
|
|
7483
7598
|
// Кривые аргументы чинятся по схеме без обращения к модели; каждая починка — строкой в журнал.
|
|
7484
7599
|
repairToolCall: createRepairToolCall({
|
|
7600
|
+
...input.repairToolInput && { repairToolInput: input.repairToolInput },
|
|
7485
7601
|
onRepaired: (repair) => logError(describeToolInputRepair(repair, { chatId: input.chatId, modelId: found.profile.id, providerId }))
|
|
7486
7602
|
}),
|
|
7487
7603
|
// Размер контекста после ответа — по последнему шагу: у прежних шагов тот же префикс, сумма считала бы его много раз.
|
|
@@ -7637,6 +7753,7 @@ function helperRunContext(input, toolQueue, logError) {
|
|
|
7637
7753
|
logError,
|
|
7638
7754
|
...input.toolResultLimit && { toolResultLimit: input.toolResultLimit },
|
|
7639
7755
|
...input.toolTimeout && { toolTimeout: input.toolTimeout },
|
|
7756
|
+
...input.repairToolInput && { repairToolInput: input.repairToolInput },
|
|
7640
7757
|
...input.sequentialTools && { sequentialTools: input.sequentialTools },
|
|
7641
7758
|
...input.providerFallback !== void 0 && { providerFallback: input.providerFallback },
|
|
7642
7759
|
...input.providerOutages && { providerOutages: input.providerOutages },
|
|
@@ -8002,6 +8119,7 @@ async function helperStep(input) {
|
|
|
8002
8119
|
maxRetries: 0,
|
|
8003
8120
|
abortSignal: input.abortSignal,
|
|
8004
8121
|
repairToolCall: createRepairToolCall({
|
|
8122
|
+
...context.repairToolInput && { repairToolInput: context.repairToolInput },
|
|
8005
8123
|
onRepaired: (repair) => context.logError(describeToolInputRepair(repair, { chatId: context.chatId, modelId: helper.model.modelId, providerId }))
|
|
8006
8124
|
})
|
|
8007
8125
|
});
|
|
@@ -12136,6 +12254,7 @@ function createChatService(input) {
|
|
|
12136
12254
|
providerFallback,
|
|
12137
12255
|
cacheMissLog,
|
|
12138
12256
|
toolTimeoutMs: toolTimeoutSetting,
|
|
12257
|
+
repairToolInput,
|
|
12139
12258
|
sequentialTools: sequentialToolsSetting,
|
|
12140
12259
|
timeZone: timeZoneSetting,
|
|
12141
12260
|
modelSilenceTimeout,
|
|
@@ -12523,8 +12642,8 @@ function createChatService(input) {
|
|
|
12523
12642
|
const ids = pendingUndelivered.get(chatId);
|
|
12524
12643
|
pendingUndelivered.delete(chatId);
|
|
12525
12644
|
if (!ids || !await storage.getChat(chatId)) return;
|
|
12526
|
-
const
|
|
12527
|
-
const fresh = [...ids].filter((id) => !
|
|
12645
|
+
const marked2 = undeliveredIdsOf(await currentBranch(chatId));
|
|
12646
|
+
const fresh = [...ids].filter((id) => !marked2.has(id));
|
|
12528
12647
|
if (fresh.length === 0) return;
|
|
12529
12648
|
const state = await readBranchState(storage, chatId);
|
|
12530
12649
|
await storage.insertMessage(stateMessage({ chatId, parentId: state.atMessageId, record: undeliveredRecord(...fresh) }));
|
|
@@ -12850,6 +12969,7 @@ function createChatService(input) {
|
|
|
12850
12969
|
...staff && { staff },
|
|
12851
12970
|
toolResultLimit,
|
|
12852
12971
|
toolTimeout,
|
|
12972
|
+
...repairToolInput && { repairToolInput },
|
|
12853
12973
|
sequentialTools,
|
|
12854
12974
|
toolQueue,
|
|
12855
12975
|
stepContextTimeoutMs,
|
|
@@ -14181,6 +14301,7 @@ function createChatService(input) {
|
|
|
14181
14301
|
usageSource: "background",
|
|
14182
14302
|
toolResultLimit,
|
|
14183
14303
|
toolTimeout,
|
|
14304
|
+
...repairToolInput && { repairToolInput },
|
|
14184
14305
|
sequentialTools,
|
|
14185
14306
|
modelSilence,
|
|
14186
14307
|
logError,
|
|
@@ -14364,6 +14485,7 @@ export {
|
|
|
14364
14485
|
cutForgedBlocks,
|
|
14365
14486
|
toolImageFallbackText,
|
|
14366
14487
|
modelMaySeeToolResultImages,
|
|
14488
|
+
repairToolArguments,
|
|
14367
14489
|
RELEASED_ANSWER_ALIVE_AT,
|
|
14368
14490
|
aliveAtByLocalClock,
|
|
14369
14491
|
silenceBoundaryByLocalClock,
|
|
@@ -14463,4 +14585,4 @@ export {
|
|
|
14463
14585
|
InvalidWidgetAnswerError,
|
|
14464
14586
|
createChatService
|
|
14465
14587
|
};
|
|
14466
|
-
//# sourceMappingURL=chunk-
|
|
14588
|
+
//# sourceMappingURL=chunk-WMP5AKDU.js.map
|