blun-king-cli 9.1.614 → 9.1.615
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 +10 -0
- package/LIESMICH.txt +1 -1
- package/README.md +1 -1
- package/blun.mjs +1543 -780
- package/codebase-index/codebase_index.py +25 -17
- package/package.json +1 -1
- package/telegram-plugin/dist/bridge.mjs +1 -200
- package/telegram-plugin/dist/mcp-server.mjs +8 -4
- package/worker-host.mjs +1615 -622
package/blun.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// BLUN_BUILD_INPUT_SHA256:
|
|
2
|
+
// BLUN_BUILD_INPUT_SHA256:57a7160081cd6a2ce9e3535b31b87f9410c0dafd58da9629b68cb0042a8e57e5
|
|
3
3
|
import { fileURLToPath as __cjsShimFileURLToPath } from 'node:url';
|
|
4
4
|
import { dirname as __cjsShimDirname } from 'node:path';
|
|
5
5
|
const __filename = __cjsShimFileURLToPath(import.meta.url);
|
|
@@ -181492,6 +181492,10 @@ var init_goal$1 = __esmMin((() => {
|
|
|
181492
181492
|
restoreUpdate(record) {
|
|
181493
181493
|
const state = this.state;
|
|
181494
181494
|
if (state === void 0) return;
|
|
181495
|
+
if (record.objective !== void 0) {
|
|
181496
|
+
state.objective = record.objective;
|
|
181497
|
+
this.lifecycleRevision += 1;
|
|
181498
|
+
}
|
|
181495
181499
|
const status = record.status;
|
|
181496
181500
|
if (status !== void 0) {
|
|
181497
181501
|
this.lifecycleRevision += 1;
|
|
@@ -181506,7 +181510,17 @@ var init_goal$1 = __esmMin((() => {
|
|
|
181506
181510
|
state.wallClockResumedAt = void 0;
|
|
181507
181511
|
}
|
|
181508
181512
|
if (record.budgetLimits !== void 0) state.budgetLimits = record.budgetLimits;
|
|
181509
|
-
if (status === void 0)
|
|
181513
|
+
if (status === void 0) {
|
|
181514
|
+
if (record.objective !== void 0) this.agent.replayBuilder.push({
|
|
181515
|
+
type: "goal_updated",
|
|
181516
|
+
snapshot: this.toSnapshot(state),
|
|
181517
|
+
change: {
|
|
181518
|
+
kind: "edited",
|
|
181519
|
+
actor: record.actor
|
|
181520
|
+
}
|
|
181521
|
+
});
|
|
181522
|
+
return;
|
|
181523
|
+
}
|
|
181510
181524
|
this.agent.replayBuilder.push({
|
|
181511
181525
|
type: "goal_updated",
|
|
181512
181526
|
snapshot: this.toSnapshot(state),
|
|
@@ -181550,11 +181564,11 @@ var init_goal$1 = __esmMin((() => {
|
|
|
181550
181564
|
if (objective.length === 0) throw new BlunError(ErrorCodes.GOAL_OBJECTIVE_EMPTY, "Goal objective cannot be empty");
|
|
181551
181565
|
if (objective.length > MAX_GOAL_OBJECTIVE_LENGTH$3) throw new BlunError(ErrorCodes.GOAL_OBJECTIVE_TOO_LONG, `Goal objective cannot exceed ${MAX_GOAL_OBJECTIVE_LENGTH$3} characters`);
|
|
181552
181566
|
const verificationScope = normalizeVerificationScope(input.verificationScope);
|
|
181567
|
+
const completionCriterion = normalizeCompletionCriterion(input.completionCriterion);
|
|
181553
181568
|
if (this.state !== void 0) {
|
|
181554
181569
|
if (input.replace !== true) throw new BlunError(ErrorCodes.GOAL_ALREADY_EXISTS, "A goal already exists; use replace to start a new one");
|
|
181555
181570
|
this.clearInternal("system");
|
|
181556
181571
|
}
|
|
181557
|
-
const completionCriterion = normalizeCompletionCriterion(input.completionCriterion);
|
|
181558
181572
|
const state = {
|
|
181559
181573
|
goalId: randomUUID(),
|
|
181560
181574
|
objective,
|
|
@@ -181578,6 +181592,35 @@ var init_goal$1 = __esmMin((() => {
|
|
|
181578
181592
|
this.trackGoalCreated(actor, input.replace === true);
|
|
181579
181593
|
return this.toSnapshot(state);
|
|
181580
181594
|
}
|
|
181595
|
+
async completeGoal() {
|
|
181596
|
+
const state = this.requireState();
|
|
181597
|
+
if (state.status !== "active") throw new BlunError(ErrorCodes.GOAL_STATUS_INVALID, `Cannot complete a goal in status "${state.status}"`);
|
|
181598
|
+
return this.markComplete({}, "user");
|
|
181599
|
+
}
|
|
181600
|
+
async blockGoal(input = {}) {
|
|
181601
|
+
const state = this.requireState();
|
|
181602
|
+
if (state.status === "blocked") return this.toSnapshot(state);
|
|
181603
|
+
if (state.status !== "active") throw new BlunError(ErrorCodes.GOAL_STATUS_INVALID, `Cannot block a goal in status "${state.status}"`);
|
|
181604
|
+
return await this.markBlocked(input, "user");
|
|
181605
|
+
}
|
|
181606
|
+
async editGoal(input, actor = "user") {
|
|
181607
|
+
const state = this.requireState();
|
|
181608
|
+
const objective = input.objective.trim();
|
|
181609
|
+
if (objective.length === 0) throw new BlunError(ErrorCodes.GOAL_OBJECTIVE_EMPTY, "Goal objective cannot be empty");
|
|
181610
|
+
if (objective.length > MAX_GOAL_OBJECTIVE_LENGTH$3) throw new BlunError(ErrorCodes.GOAL_OBJECTIVE_TOO_LONG, `Goal objective cannot exceed ${MAX_GOAL_OBJECTIVE_LENGTH$3} characters`);
|
|
181611
|
+
if (objective === state.objective) return this.toSnapshot(state);
|
|
181612
|
+
state.objective = objective;
|
|
181613
|
+
this.lifecycleRevision += 1;
|
|
181614
|
+
this.appendGoalUpdate({
|
|
181615
|
+
objective,
|
|
181616
|
+
actor
|
|
181617
|
+
});
|
|
181618
|
+
this.persistState(state, { change: {
|
|
181619
|
+
kind: "edited",
|
|
181620
|
+
actor
|
|
181621
|
+
} });
|
|
181622
|
+
return this.toSnapshot(state);
|
|
181623
|
+
}
|
|
181581
181624
|
async pauseGoal(input = {}, actor = "user") {
|
|
181582
181625
|
const state = this.requireState();
|
|
181583
181626
|
if (state.status === "paused") return this.toSnapshot(state);
|
|
@@ -182320,6 +182363,621 @@ var init_provider_retry_wait = __esmMin((() => {
|
|
|
182320
182363
|
};
|
|
182321
182364
|
}));
|
|
182322
182365
|
//#endregion
|
|
182366
|
+
//#region ../../packages/agent-core/src/tools/support/file-type.ts
|
|
182367
|
+
function toBuffer$2(data) {
|
|
182368
|
+
return Buffer.isBuffer(data) ? data : Buffer.from(data.buffer, data.byteOffset, data.byteLength);
|
|
182369
|
+
}
|
|
182370
|
+
function startsWith(buf, prefix) {
|
|
182371
|
+
const needle = Buffer.isBuffer(prefix) ? prefix : Buffer.from(prefix);
|
|
182372
|
+
if (buf.length < needle.length) return false;
|
|
182373
|
+
for (let i = 0; i < needle.length; i += 1) if (buf[i] !== needle[i]) return false;
|
|
182374
|
+
return true;
|
|
182375
|
+
}
|
|
182376
|
+
function sniffFtypBrand(header) {
|
|
182377
|
+
if (header.length < 12) return null;
|
|
182378
|
+
if (header.subarray(4, 8).toString("latin1") !== "ftyp") return null;
|
|
182379
|
+
return header.subarray(8, 12).toString("latin1").toLowerCase().replaceAll(/[\s\u0000]+$/g, "").trim();
|
|
182380
|
+
}
|
|
182381
|
+
function sniffMediaFromMagic(data) {
|
|
182382
|
+
const buf = toBuffer$2(data);
|
|
182383
|
+
const header = buf.length > 512 ? buf.subarray(0, 512) : buf;
|
|
182384
|
+
if (startsWith(header, [
|
|
182385
|
+
137,
|
|
182386
|
+
80,
|
|
182387
|
+
78,
|
|
182388
|
+
71,
|
|
182389
|
+
13,
|
|
182390
|
+
10,
|
|
182391
|
+
26,
|
|
182392
|
+
10
|
|
182393
|
+
])) return {
|
|
182394
|
+
kind: "image",
|
|
182395
|
+
mimeType: "image/png"
|
|
182396
|
+
};
|
|
182397
|
+
if (startsWith(header, [
|
|
182398
|
+
255,
|
|
182399
|
+
216,
|
|
182400
|
+
255
|
|
182401
|
+
])) return {
|
|
182402
|
+
kind: "image",
|
|
182403
|
+
mimeType: "image/jpeg"
|
|
182404
|
+
};
|
|
182405
|
+
if (startsWith(header, Buffer.from("GIF87a")) || startsWith(header, Buffer.from("GIF89a"))) return {
|
|
182406
|
+
kind: "image",
|
|
182407
|
+
mimeType: "image/gif"
|
|
182408
|
+
};
|
|
182409
|
+
if (startsWith(header, Buffer.from("BM"))) return {
|
|
182410
|
+
kind: "image",
|
|
182411
|
+
mimeType: "image/bmp"
|
|
182412
|
+
};
|
|
182413
|
+
if (startsWith(header, [
|
|
182414
|
+
73,
|
|
182415
|
+
73,
|
|
182416
|
+
42,
|
|
182417
|
+
0
|
|
182418
|
+
]) || startsWith(header, [
|
|
182419
|
+
77,
|
|
182420
|
+
77,
|
|
182421
|
+
0,
|
|
182422
|
+
42
|
|
182423
|
+
])) return {
|
|
182424
|
+
kind: "image",
|
|
182425
|
+
mimeType: "image/tiff"
|
|
182426
|
+
};
|
|
182427
|
+
if (startsWith(header, [
|
|
182428
|
+
0,
|
|
182429
|
+
0,
|
|
182430
|
+
1,
|
|
182431
|
+
0
|
|
182432
|
+
])) return {
|
|
182433
|
+
kind: "image",
|
|
182434
|
+
mimeType: "image/x-icon"
|
|
182435
|
+
};
|
|
182436
|
+
if (startsWith(header, Buffer.from("RIFF")) && header.length >= 12) {
|
|
182437
|
+
const chunk = header.subarray(8, 12).toString("latin1");
|
|
182438
|
+
if (chunk === "WEBP") return {
|
|
182439
|
+
kind: "image",
|
|
182440
|
+
mimeType: "image/webp"
|
|
182441
|
+
};
|
|
182442
|
+
if (chunk === "AVI ") return {
|
|
182443
|
+
kind: "video",
|
|
182444
|
+
mimeType: "video/x-msvideo"
|
|
182445
|
+
};
|
|
182446
|
+
}
|
|
182447
|
+
if (startsWith(header, Buffer.from("FLV"))) return {
|
|
182448
|
+
kind: "video",
|
|
182449
|
+
mimeType: "video/x-flv"
|
|
182450
|
+
};
|
|
182451
|
+
if (startsWith(header, ASF_HEADER)) return {
|
|
182452
|
+
kind: "video",
|
|
182453
|
+
mimeType: "video/x-ms-wmv"
|
|
182454
|
+
};
|
|
182455
|
+
if (startsWith(header, [
|
|
182456
|
+
26,
|
|
182457
|
+
69,
|
|
182458
|
+
223,
|
|
182459
|
+
163
|
|
182460
|
+
])) {
|
|
182461
|
+
const lowered = header.toString("latin1").toLowerCase();
|
|
182462
|
+
if (lowered.includes("webm")) return {
|
|
182463
|
+
kind: "video",
|
|
182464
|
+
mimeType: "video/webm"
|
|
182465
|
+
};
|
|
182466
|
+
if (lowered.includes("matroska")) return {
|
|
182467
|
+
kind: "video",
|
|
182468
|
+
mimeType: "video/x-matroska"
|
|
182469
|
+
};
|
|
182470
|
+
}
|
|
182471
|
+
const brand = sniffFtypBrand(header);
|
|
182472
|
+
if (brand !== null && brand !== "") {
|
|
182473
|
+
if (brand in FTYP_IMAGE_BRANDS) return {
|
|
182474
|
+
kind: "image",
|
|
182475
|
+
mimeType: FTYP_IMAGE_BRANDS[brand]
|
|
182476
|
+
};
|
|
182477
|
+
if (brand in FTYP_VIDEO_BRANDS) return {
|
|
182478
|
+
kind: "video",
|
|
182479
|
+
mimeType: FTYP_VIDEO_BRANDS[brand]
|
|
182480
|
+
};
|
|
182481
|
+
}
|
|
182482
|
+
return null;
|
|
182483
|
+
}
|
|
182484
|
+
/**
|
|
182485
|
+
* Best-effort pixel-dimension reader for common raster formats.
|
|
182486
|
+
*
|
|
182487
|
+
* Inspects only the fixed region near the start of the file where each
|
|
182488
|
+
* format records its dimensions (the IHDR/DIB header, the RIFF chunk
|
|
182489
|
+
* after the `WEBP` tag, or the first JPEG SOFn segment). Returns `null`
|
|
182490
|
+
* for formats whose dimensions are not locatable from that region, or
|
|
182491
|
+
* when the supplied buffer is too short to cover it.
|
|
182492
|
+
*/
|
|
182493
|
+
function sniffImageDimensions(data) {
|
|
182494
|
+
const buf = toBuffer$2(data);
|
|
182495
|
+
if (startsWith(buf, [
|
|
182496
|
+
137,
|
|
182497
|
+
80,
|
|
182498
|
+
78,
|
|
182499
|
+
71,
|
|
182500
|
+
13,
|
|
182501
|
+
10,
|
|
182502
|
+
26,
|
|
182503
|
+
10
|
|
182504
|
+
]) && buf.length >= 24) return {
|
|
182505
|
+
width: buf.readUInt32BE(16),
|
|
182506
|
+
height: buf.readUInt32BE(20)
|
|
182507
|
+
};
|
|
182508
|
+
if ((startsWith(buf, Buffer.from("GIF87a")) || startsWith(buf, Buffer.from("GIF89a"))) && buf.length >= 10) return {
|
|
182509
|
+
width: buf.readUInt16LE(6),
|
|
182510
|
+
height: buf.readUInt16LE(8)
|
|
182511
|
+
};
|
|
182512
|
+
if (startsWith(buf, Buffer.from("BM")) && buf.length >= 26) return {
|
|
182513
|
+
width: buf.readInt32LE(18),
|
|
182514
|
+
height: Math.abs(buf.readInt32LE(22))
|
|
182515
|
+
};
|
|
182516
|
+
if (startsWith(buf, Buffer.from("RIFF")) && buf.length >= 30) {
|
|
182517
|
+
const fourCc = buf.subarray(12, 16).toString("latin1");
|
|
182518
|
+
if (fourCc === "VP8 ") return {
|
|
182519
|
+
width: buf.readUInt16LE(26) & 16383,
|
|
182520
|
+
height: buf.readUInt16LE(28) & 16383
|
|
182521
|
+
};
|
|
182522
|
+
if (fourCc === "VP8L" && buf.length >= 25) {
|
|
182523
|
+
const bits = buf.readUInt32LE(21);
|
|
182524
|
+
return {
|
|
182525
|
+
width: (bits & 16383) + 1,
|
|
182526
|
+
height: (bits >> 14 & 16383) + 1
|
|
182527
|
+
};
|
|
182528
|
+
}
|
|
182529
|
+
if (fourCc === "VP8X") return {
|
|
182530
|
+
width: 1 + (buf[24] | buf[25] << 8 | buf[26] << 16),
|
|
182531
|
+
height: 1 + (buf[27] | buf[28] << 8 | buf[29] << 16)
|
|
182532
|
+
};
|
|
182533
|
+
}
|
|
182534
|
+
if (startsWith(buf, [255, 216])) {
|
|
182535
|
+
let offset = 2;
|
|
182536
|
+
while (offset + 9 < buf.length) {
|
|
182537
|
+
if (buf[offset] !== 255) {
|
|
182538
|
+
offset += 1;
|
|
182539
|
+
continue;
|
|
182540
|
+
}
|
|
182541
|
+
const marker = buf[offset + 1];
|
|
182542
|
+
if (marker >= 192 && marker <= 207 && marker !== 196 && marker !== 200 && marker !== 204) return {
|
|
182543
|
+
height: buf.readUInt16BE(offset + 5),
|
|
182544
|
+
width: buf.readUInt16BE(offset + 7)
|
|
182545
|
+
};
|
|
182546
|
+
if (marker === 216 || marker === 217 || marker >= 208 && marker <= 215) {
|
|
182547
|
+
offset += 2;
|
|
182548
|
+
continue;
|
|
182549
|
+
}
|
|
182550
|
+
const segmentLength = buf.readUInt16BE(offset + 2);
|
|
182551
|
+
if (segmentLength < 2) break;
|
|
182552
|
+
offset += 2 + segmentLength;
|
|
182553
|
+
}
|
|
182554
|
+
}
|
|
182555
|
+
return null;
|
|
182556
|
+
}
|
|
182557
|
+
function getSuffix(path) {
|
|
182558
|
+
const idx = path.lastIndexOf(".");
|
|
182559
|
+
if (idx === -1) return "";
|
|
182560
|
+
if (idx <= Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\")) + 1) return "";
|
|
182561
|
+
return path.slice(idx).toLowerCase();
|
|
182562
|
+
}
|
|
182563
|
+
function detectFileType(path, header, type = "text") {
|
|
182564
|
+
const suffix = getSuffix(path);
|
|
182565
|
+
let mediaHint = null;
|
|
182566
|
+
if (suffix in TEXT_MIME_BY_SUFFIX) mediaHint = {
|
|
182567
|
+
kind: "text",
|
|
182568
|
+
mimeType: TEXT_MIME_BY_SUFFIX[suffix]
|
|
182569
|
+
};
|
|
182570
|
+
else if (suffix in IMAGE_MIME_BY_SUFFIX) mediaHint = {
|
|
182571
|
+
kind: "image",
|
|
182572
|
+
mimeType: IMAGE_MIME_BY_SUFFIX[suffix]
|
|
182573
|
+
};
|
|
182574
|
+
else if (suffix in VIDEO_MIME_BY_SUFFIX$1) mediaHint = {
|
|
182575
|
+
kind: "video",
|
|
182576
|
+
mimeType: VIDEO_MIME_BY_SUFFIX$1[suffix]
|
|
182577
|
+
};
|
|
182578
|
+
if (header !== void 0) {
|
|
182579
|
+
const buf = toBuffer$2(header);
|
|
182580
|
+
const sniffed = sniffMediaFromMagic(buf);
|
|
182581
|
+
if (sniffed) {
|
|
182582
|
+
if (type === "media") return sniffed;
|
|
182583
|
+
if (mediaHint) {
|
|
182584
|
+
if (sniffed.kind !== mediaHint.kind) return {
|
|
182585
|
+
kind: "unknown",
|
|
182586
|
+
mimeType: ""
|
|
182587
|
+
};
|
|
182588
|
+
return mediaHint;
|
|
182589
|
+
}
|
|
182590
|
+
return sniffed;
|
|
182591
|
+
}
|
|
182592
|
+
if (mediaHint?.kind === "image") return {
|
|
182593
|
+
kind: "unknown",
|
|
182594
|
+
mimeType: ""
|
|
182595
|
+
};
|
|
182596
|
+
if (type === "media" && mediaHint?.kind === "video") return mediaHint;
|
|
182597
|
+
if (buf.includes(0)) return {
|
|
182598
|
+
kind: "unknown",
|
|
182599
|
+
mimeType: ""
|
|
182600
|
+
};
|
|
182601
|
+
}
|
|
182602
|
+
if (mediaHint) return mediaHint;
|
|
182603
|
+
if (NON_TEXT_SUFFIXES.has(suffix)) return {
|
|
182604
|
+
kind: "unknown",
|
|
182605
|
+
mimeType: ""
|
|
182606
|
+
};
|
|
182607
|
+
return {
|
|
182608
|
+
kind: "text",
|
|
182609
|
+
mimeType: "text/plain"
|
|
182610
|
+
};
|
|
182611
|
+
}
|
|
182612
|
+
var IMAGE_MIME_BY_SUFFIX, VIDEO_MIME_BY_SUFFIX$1, TEXT_MIME_BY_SUFFIX, NON_TEXT_SUFFIXES, ASF_HEADER, FTYP_IMAGE_BRANDS, FTYP_VIDEO_BRANDS;
|
|
182613
|
+
var init_file_type$1 = __esmMin((() => {
|
|
182614
|
+
IMAGE_MIME_BY_SUFFIX = Object.freeze({
|
|
182615
|
+
".png": "image/png",
|
|
182616
|
+
".jpg": "image/jpeg",
|
|
182617
|
+
".jpeg": "image/jpeg",
|
|
182618
|
+
".gif": "image/gif",
|
|
182619
|
+
".bmp": "image/bmp",
|
|
182620
|
+
".tif": "image/tiff",
|
|
182621
|
+
".tiff": "image/tiff",
|
|
182622
|
+
".webp": "image/webp",
|
|
182623
|
+
".ico": "image/x-icon",
|
|
182624
|
+
".heic": "image/heic",
|
|
182625
|
+
".heif": "image/heif",
|
|
182626
|
+
".avif": "image/avif",
|
|
182627
|
+
".svgz": "image/svg+xml"
|
|
182628
|
+
});
|
|
182629
|
+
VIDEO_MIME_BY_SUFFIX$1 = Object.freeze({
|
|
182630
|
+
".mp4": "video/mp4",
|
|
182631
|
+
".mpg": "video/mpeg",
|
|
182632
|
+
".mpeg": "video/mpeg",
|
|
182633
|
+
".mkv": "video/x-matroska",
|
|
182634
|
+
".avi": "video/x-msvideo",
|
|
182635
|
+
".mov": "video/quicktime",
|
|
182636
|
+
".ogv": "video/ogg",
|
|
182637
|
+
".wmv": "video/x-ms-wmv",
|
|
182638
|
+
".webm": "video/webm",
|
|
182639
|
+
".m4v": "video/x-m4v",
|
|
182640
|
+
".flv": "video/x-flv",
|
|
182641
|
+
".3gp": "video/3gpp",
|
|
182642
|
+
".3g2": "video/3gpp2"
|
|
182643
|
+
});
|
|
182644
|
+
TEXT_MIME_BY_SUFFIX = Object.freeze({ ".svg": "image/svg+xml" });
|
|
182645
|
+
NON_TEXT_SUFFIXES = new Set([
|
|
182646
|
+
".icns",
|
|
182647
|
+
".psd",
|
|
182648
|
+
".ai",
|
|
182649
|
+
".eps",
|
|
182650
|
+
".pdf",
|
|
182651
|
+
".doc",
|
|
182652
|
+
".docx",
|
|
182653
|
+
".dot",
|
|
182654
|
+
".dotx",
|
|
182655
|
+
".rtf",
|
|
182656
|
+
".odt",
|
|
182657
|
+
".xls",
|
|
182658
|
+
".xlsx",
|
|
182659
|
+
".xlsm",
|
|
182660
|
+
".xlt",
|
|
182661
|
+
".xltx",
|
|
182662
|
+
".xltm",
|
|
182663
|
+
".ods",
|
|
182664
|
+
".ppt",
|
|
182665
|
+
".pptx",
|
|
182666
|
+
".pptm",
|
|
182667
|
+
".pps",
|
|
182668
|
+
".ppsx",
|
|
182669
|
+
".odp",
|
|
182670
|
+
".pages",
|
|
182671
|
+
".numbers",
|
|
182672
|
+
".key",
|
|
182673
|
+
".zip",
|
|
182674
|
+
".rar",
|
|
182675
|
+
".7z",
|
|
182676
|
+
".tar",
|
|
182677
|
+
".gz",
|
|
182678
|
+
".tgz",
|
|
182679
|
+
".bz2",
|
|
182680
|
+
".xz",
|
|
182681
|
+
".zst",
|
|
182682
|
+
".lz",
|
|
182683
|
+
".lz4",
|
|
182684
|
+
".br",
|
|
182685
|
+
".cab",
|
|
182686
|
+
".ar",
|
|
182687
|
+
".deb",
|
|
182688
|
+
".rpm",
|
|
182689
|
+
".mp3",
|
|
182690
|
+
".wav",
|
|
182691
|
+
".flac",
|
|
182692
|
+
".ogg",
|
|
182693
|
+
".oga",
|
|
182694
|
+
".opus",
|
|
182695
|
+
".aac",
|
|
182696
|
+
".m4a",
|
|
182697
|
+
".wma",
|
|
182698
|
+
".ttf",
|
|
182699
|
+
".otf",
|
|
182700
|
+
".woff",
|
|
182701
|
+
".woff2",
|
|
182702
|
+
".exe",
|
|
182703
|
+
".dll",
|
|
182704
|
+
".so",
|
|
182705
|
+
".dylib",
|
|
182706
|
+
".bin",
|
|
182707
|
+
".apk",
|
|
182708
|
+
".ipa",
|
|
182709
|
+
".jar",
|
|
182710
|
+
".class",
|
|
182711
|
+
".pyc",
|
|
182712
|
+
".pyo",
|
|
182713
|
+
".wasm",
|
|
182714
|
+
".dmg",
|
|
182715
|
+
".iso",
|
|
182716
|
+
".img",
|
|
182717
|
+
".sqlite",
|
|
182718
|
+
".sqlite3",
|
|
182719
|
+
".db",
|
|
182720
|
+
".db3"
|
|
182721
|
+
]);
|
|
182722
|
+
ASF_HEADER = Buffer.from([
|
|
182723
|
+
48,
|
|
182724
|
+
38,
|
|
182725
|
+
178,
|
|
182726
|
+
117,
|
|
182727
|
+
142,
|
|
182728
|
+
102,
|
|
182729
|
+
207,
|
|
182730
|
+
17,
|
|
182731
|
+
166,
|
|
182732
|
+
217,
|
|
182733
|
+
0,
|
|
182734
|
+
170,
|
|
182735
|
+
0,
|
|
182736
|
+
98,
|
|
182737
|
+
206,
|
|
182738
|
+
108
|
|
182739
|
+
]);
|
|
182740
|
+
FTYP_IMAGE_BRANDS = Object.freeze({
|
|
182741
|
+
avif: "image/avif",
|
|
182742
|
+
avis: "image/avif",
|
|
182743
|
+
heic: "image/heic",
|
|
182744
|
+
heif: "image/heif",
|
|
182745
|
+
heix: "image/heif",
|
|
182746
|
+
hevc: "image/heic",
|
|
182747
|
+
mif1: "image/heif",
|
|
182748
|
+
msf1: "image/heif"
|
|
182749
|
+
});
|
|
182750
|
+
FTYP_VIDEO_BRANDS = Object.freeze({
|
|
182751
|
+
isom: "video/mp4",
|
|
182752
|
+
iso2: "video/mp4",
|
|
182753
|
+
iso5: "video/mp4",
|
|
182754
|
+
mp41: "video/mp4",
|
|
182755
|
+
mp42: "video/mp4",
|
|
182756
|
+
avc1: "video/mp4",
|
|
182757
|
+
mp4v: "video/mp4",
|
|
182758
|
+
m4v: "video/x-m4v",
|
|
182759
|
+
qt: "video/quicktime",
|
|
182760
|
+
"3gp4": "video/3gpp",
|
|
182761
|
+
"3gp5": "video/3gpp",
|
|
182762
|
+
"3gp6": "video/3gpp",
|
|
182763
|
+
"3gp7": "video/3gpp",
|
|
182764
|
+
"3g2": "video/3gpp2"
|
|
182765
|
+
});
|
|
182766
|
+
}));
|
|
182767
|
+
//#endregion
|
|
182768
|
+
//#region ../../packages/agent-core/src/utils/tokens.ts
|
|
182769
|
+
/** Open assistant messages grow while streaming; completed history stays cached. */
|
|
182770
|
+
function invalidateMessageTokenEstimate(message) {
|
|
182771
|
+
messageTokenEstimateCache.delete(message);
|
|
182772
|
+
}
|
|
182773
|
+
/**
|
|
182774
|
+
* Estimate token count from text using a character-based heuristic.
|
|
182775
|
+
* - ASCII (~4 chars per token)
|
|
182776
|
+
* - CJK and other non-ASCII (~1 char per token)
|
|
182777
|
+
* The estimate is transient — the next LLM call returns the real count
|
|
182778
|
+
* and supersedes this value. Used to keep `tokenCountWithPending`
|
|
182779
|
+
* monotonic between LLM round-trips without paying for a tokenizer.
|
|
182780
|
+
*/
|
|
182781
|
+
function estimateTokens(text) {
|
|
182782
|
+
let asciiCount = 0;
|
|
182783
|
+
let nonAsciiCount = 0;
|
|
182784
|
+
for (const char of text) if (char.codePointAt(0) <= 127) asciiCount++;
|
|
182785
|
+
else nonAsciiCount++;
|
|
182786
|
+
return Math.ceil(asciiCount / 4) + nonAsciiCount;
|
|
182787
|
+
}
|
|
182788
|
+
function estimateTokensForMessages(messages) {
|
|
182789
|
+
let total = 0;
|
|
182790
|
+
for (const message of messages) total += estimateTokensForMessage(message);
|
|
182791
|
+
return total;
|
|
182792
|
+
}
|
|
182793
|
+
/** With stopAfter, the result is a lower bound once it exceeds that budget. */
|
|
182794
|
+
function estimateTokensForTools(tools, stopAfter = Infinity) {
|
|
182795
|
+
let total = 0;
|
|
182796
|
+
for (const tool of tools) {
|
|
182797
|
+
total += estimateTokens(tool.name);
|
|
182798
|
+
total += estimateTokens(tool.description);
|
|
182799
|
+
total += estimateTokens(JSON.stringify(tool.parameters));
|
|
182800
|
+
if (total > stopAfter) return total;
|
|
182801
|
+
}
|
|
182802
|
+
return total;
|
|
182803
|
+
}
|
|
182804
|
+
function estimateTokensForMessage(message) {
|
|
182805
|
+
const cached = messageTokenEstimateCache.get(message);
|
|
182806
|
+
if (cached !== void 0) return cached;
|
|
182807
|
+
let total = estimateTokens(message.role);
|
|
182808
|
+
total += estimateTokensForContentParts(message.content);
|
|
182809
|
+
if (message.toolCalls !== void 0) for (const call of message.toolCalls) {
|
|
182810
|
+
total += estimateTokens(call.name);
|
|
182811
|
+
total += estimateTokens(JSON.stringify(call.arguments));
|
|
182812
|
+
}
|
|
182813
|
+
messageTokenEstimateCache.set(message, total);
|
|
182814
|
+
return total;
|
|
182815
|
+
}
|
|
182816
|
+
function estimateTokensForContentParts(parts) {
|
|
182817
|
+
let total = 0;
|
|
182818
|
+
for (const part of parts) total += estimateTokensForContentPart(part);
|
|
182819
|
+
return total;
|
|
182820
|
+
}
|
|
182821
|
+
function imageDimensionsFromDataUrl(url) {
|
|
182822
|
+
const commaIndex = url.indexOf(",");
|
|
182823
|
+
if (commaIndex <= 0) return null;
|
|
182824
|
+
const metadata = url.slice(0, commaIndex).toLowerCase();
|
|
182825
|
+
if (!metadata.startsWith("data:image/") || !metadata.split(";").includes("base64")) return null;
|
|
182826
|
+
const maxBase64Chars = Math.ceil(MAX_IMAGE_HEADER_BYTES / 3) * 4;
|
|
182827
|
+
const encodedHeader = url.slice(commaIndex + 1, commaIndex + 1 + maxBase64Chars);
|
|
182828
|
+
if (encodedHeader.length === 0) return null;
|
|
182829
|
+
try {
|
|
182830
|
+
const dimensions = sniffImageDimensions(Buffer.from(encodedHeader, "base64"));
|
|
182831
|
+
if (dimensions === null || !Number.isSafeInteger(dimensions.width) || !Number.isSafeInteger(dimensions.height) || dimensions.width <= 0 || dimensions.height <= 0) return null;
|
|
182832
|
+
return dimensions;
|
|
182833
|
+
} catch {
|
|
182834
|
+
return null;
|
|
182835
|
+
}
|
|
182836
|
+
}
|
|
182837
|
+
function estimateImageTokensFromDimensions(width, height) {
|
|
182838
|
+
if (!Number.isSafeInteger(width) || !Number.isSafeInteger(height) || width <= 0 || height <= 0) return MEDIA_TOKEN_ESTIMATE;
|
|
182839
|
+
const patchSize = BigInt(32);
|
|
182840
|
+
const tokens = (BigInt(width) + patchSize - 1n) / patchSize * ((BigInt(height) + patchSize - 1n) / patchSize);
|
|
182841
|
+
return tokens > BigInt(Number.MAX_SAFE_INTEGER) ? Number.MAX_SAFE_INTEGER : Number(tokens);
|
|
182842
|
+
}
|
|
182843
|
+
function estimateImageTokens(url) {
|
|
182844
|
+
const dimensions = imageDimensionsFromDataUrl(url);
|
|
182845
|
+
return dimensions === null ? MEDIA_TOKEN_ESTIMATE : estimateImageTokensFromDimensions(dimensions.width, dimensions.height);
|
|
182846
|
+
}
|
|
182847
|
+
function estimateTokensForContentPart(part) {
|
|
182848
|
+
switch (part.type) {
|
|
182849
|
+
case "text": return estimateTokens(part.text);
|
|
182850
|
+
case "think": return estimateTokens(part.think);
|
|
182851
|
+
case "image_url": return estimateImageTokens(part.imageUrl.url);
|
|
182852
|
+
case "audio_url":
|
|
182853
|
+
case "video_url": return MEDIA_TOKEN_ESTIMATE;
|
|
182854
|
+
default: return 0;
|
|
182855
|
+
}
|
|
182856
|
+
}
|
|
182857
|
+
var messageTokenEstimateCache, MEDIA_TOKEN_ESTIMATE, MAX_IMAGE_HEADER_BYTES;
|
|
182858
|
+
var init_tokens = __esmMin((() => {
|
|
182859
|
+
init_file_type$1();
|
|
182860
|
+
messageTokenEstimateCache = /* @__PURE__ */ new WeakMap();
|
|
182861
|
+
MEDIA_TOKEN_ESTIMATE = 2e3;
|
|
182862
|
+
MAX_IMAGE_HEADER_BYTES = 1024 * 1024;
|
|
182863
|
+
}));
|
|
182864
|
+
//#endregion
|
|
182865
|
+
//#region ../../packages/agent-core/src/agent/compaction/tool-continuity.ts
|
|
182866
|
+
function saturatingAdd(left, right) {
|
|
182867
|
+
return left + Math.min(right, Number.MAX_SAFE_INTEGER - left);
|
|
182868
|
+
}
|
|
182869
|
+
function renderUnchecked(value) {
|
|
182870
|
+
return [
|
|
182871
|
+
"",
|
|
182872
|
+
"",
|
|
182873
|
+
"<tool-continuity>",
|
|
182874
|
+
"Observed tool-result flags; may be synthetic, not verified job success or permission. omitted counts excluded observations cumulatively, not jobs.",
|
|
182875
|
+
JSON.stringify(value).replaceAll(/[<>&]/g, (character) => {
|
|
182876
|
+
return `\\u${character.codePointAt(0).toString(16).padStart(4, "0")}`;
|
|
182877
|
+
}),
|
|
182878
|
+
"</tool-continuity>"
|
|
182879
|
+
].join("\n");
|
|
182880
|
+
}
|
|
182881
|
+
function hasExactKeys$1(value, expected) {
|
|
182882
|
+
const prototype = Object.getPrototypeOf(value);
|
|
182883
|
+
if (prototype !== Object.prototype && prototype !== null) return false;
|
|
182884
|
+
return Reflect.ownKeys(value).length === expected.length && expected.every((key) => {
|
|
182885
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
182886
|
+
return descriptor !== void 0 && descriptor.enumerable === true && Object.hasOwn(descriptor, "value");
|
|
182887
|
+
});
|
|
182888
|
+
}
|
|
182889
|
+
function isDataArray(value) {
|
|
182890
|
+
if (!Array.isArray(value) || Object.getPrototypeOf(value) !== Array.prototype || value.length > 8 || Reflect.ownKeys(value).length !== value.length + 1) return false;
|
|
182891
|
+
for (let index = 0; index < value.length; index++) {
|
|
182892
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
|
|
182893
|
+
if (descriptor === void 0 || descriptor.enumerable !== true || !Object.hasOwn(descriptor, "value")) return false;
|
|
182894
|
+
}
|
|
182895
|
+
return true;
|
|
182896
|
+
}
|
|
182897
|
+
/** Validate restored metadata without interpreting any summarizer or tool prose. */
|
|
182898
|
+
function isToolContinuity(value) {
|
|
182899
|
+
try {
|
|
182900
|
+
if (value === null || typeof value !== "object" || !hasExactKeys$1(value, ["receipts", "omitted"])) return false;
|
|
182901
|
+
const candidate = value;
|
|
182902
|
+
if (!Number.isSafeInteger(candidate["omitted"]) || candidate["omitted"] < 0 || !isDataArray(candidate["receipts"]) || candidate["receipts"].length > 8) return false;
|
|
182903
|
+
for (const receipt of candidate["receipts"]) if (receipt === null || typeof receipt !== "object" || !hasExactKeys$1(receipt, ["toolCallId", "observedIsError"]) || !("toolCallId" in receipt) || !("observedIsError" in receipt) || typeof receipt.toolCallId !== "string" || receipt.toolCallId.length === 0 || Buffer.byteLength(receipt.toolCallId, "utf8") > 256 || receipt.observedIsError !== null && typeof receipt.observedIsError !== "boolean") return false;
|
|
182904
|
+
return Buffer.byteLength(JSON.stringify(renderUnchecked(value)), "utf8") <= MAX_TOOL_CONTINUITY_SERIALIZED_BYTES;
|
|
182905
|
+
} catch {
|
|
182906
|
+
return false;
|
|
182907
|
+
}
|
|
182908
|
+
}
|
|
182909
|
+
function renderToolContinuity(value) {
|
|
182910
|
+
if (!isToolContinuity(value) || value.receipts.length === 0 && value.omitted === 0) return void 0;
|
|
182911
|
+
return renderUnchecked(value);
|
|
182912
|
+
}
|
|
182913
|
+
/** The caller passes only the compactable prefix, excluding the preserved tool suffix. */
|
|
182914
|
+
function collectToolContinuity(messages) {
|
|
182915
|
+
const observed = /* @__PURE__ */ new Map();
|
|
182916
|
+
let ordinal = 0;
|
|
182917
|
+
let inheritedOmitted = 0;
|
|
182918
|
+
let excluded = 0;
|
|
182919
|
+
const remember = (toolCallId, observedIsError) => {
|
|
182920
|
+
if (toolCallId.length === 0 || Buffer.byteLength(toolCallId, "utf8") > 256) {
|
|
182921
|
+
excluded = saturatingAdd(excluded, 1);
|
|
182922
|
+
return;
|
|
182923
|
+
}
|
|
182924
|
+
const key = JSON.stringify([toolCallId, observedIsError]);
|
|
182925
|
+
observed.set(key, {
|
|
182926
|
+
toolCallId,
|
|
182927
|
+
observedIsError,
|
|
182928
|
+
ordinal: ordinal++
|
|
182929
|
+
});
|
|
182930
|
+
};
|
|
182931
|
+
for (const message of messages) if (message.role === "tool" && typeof message.toolCallId === "string") remember(message.toolCallId, typeof message.isError === "boolean" ? message.isError : null);
|
|
182932
|
+
else if (message.role === "user" && message.origin?.kind === "compaction_summary") {
|
|
182933
|
+
const previous = message.origin.toolContinuity;
|
|
182934
|
+
if (!isToolContinuity(previous)) continue;
|
|
182935
|
+
for (const receipt of previous.receipts.toReversed()) remember(receipt.toolCallId, receipt.observedIsError);
|
|
182936
|
+
inheritedOmitted = Math.max(inheritedOmitted, previous.omitted);
|
|
182937
|
+
}
|
|
182938
|
+
const prioritized = [...observed.values()].toSorted((left, right) => Number(right.observedIsError === true) - Number(left.observedIsError === true) || right.ordinal - left.ordinal);
|
|
182939
|
+
const receipts = prioritized.slice(0, 8).map(({ toolCallId, observedIsError }) => ({
|
|
182940
|
+
toolCallId,
|
|
182941
|
+
observedIsError
|
|
182942
|
+
}));
|
|
182943
|
+
let omitted = saturatingAdd(saturatingAdd(inheritedOmitted, excluded), prioritized.length - receipts.length);
|
|
182944
|
+
while (true) {
|
|
182945
|
+
const result = {
|
|
182946
|
+
receipts: [...receipts],
|
|
182947
|
+
omitted
|
|
182948
|
+
};
|
|
182949
|
+
if (renderToolContinuity(result) !== void 0) return result;
|
|
182950
|
+
if (receipts.length === 0) return void 0;
|
|
182951
|
+
receipts.pop();
|
|
182952
|
+
omitted = saturatingAdd(omitted, 1);
|
|
182953
|
+
}
|
|
182954
|
+
}
|
|
182955
|
+
/** Fit complete tuples and their disclaimer; never start a new failure or retry path. */
|
|
182956
|
+
function fitToolContinuity(value, additionalTokenBudget) {
|
|
182957
|
+
if (value === void 0 || !isToolContinuity(value) || !(additionalTokenBudget > 0)) return void 0;
|
|
182958
|
+
const receipts = [...value.receipts];
|
|
182959
|
+
let omitted = value.omitted;
|
|
182960
|
+
while (true) {
|
|
182961
|
+
const continuity = {
|
|
182962
|
+
receipts: [...receipts],
|
|
182963
|
+
omitted
|
|
182964
|
+
};
|
|
182965
|
+
const text = renderToolContinuity(continuity);
|
|
182966
|
+
if (text !== void 0 && estimateTokens(text) <= additionalTokenBudget) return {
|
|
182967
|
+
continuity,
|
|
182968
|
+
text
|
|
182969
|
+
};
|
|
182970
|
+
if (receipts.length === 0) return void 0;
|
|
182971
|
+
receipts.pop();
|
|
182972
|
+
omitted = saturatingAdd(omitted, 1);
|
|
182973
|
+
}
|
|
182974
|
+
}
|
|
182975
|
+
var MAX_TOOL_CONTINUITY_SERIALIZED_BYTES;
|
|
182976
|
+
var init_tool_continuity = __esmMin((() => {
|
|
182977
|
+
init_tokens();
|
|
182978
|
+
MAX_TOOL_CONTINUITY_SERIALIZED_BYTES = 4096;
|
|
182979
|
+
}));
|
|
182980
|
+
//#endregion
|
|
182323
182981
|
//#region ../../packages/agent-core/src/agent/records/resume-snapshot.ts
|
|
182324
182982
|
function resumeRecordKind(type) {
|
|
182325
182983
|
if ([
|
|
@@ -182408,6 +183066,7 @@ var init_resume_snapshot = __esmMin((() => {
|
|
|
182408
183066
|
init_schema();
|
|
182409
183067
|
init_goal$1();
|
|
182410
183068
|
init_provider_retry_wait();
|
|
183069
|
+
init_tool_continuity();
|
|
182411
183070
|
init_migration();
|
|
182412
183071
|
integer$1 = number$1().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
|
|
182413
183072
|
finite = number$1().finite().nonnegative();
|
|
@@ -182501,6 +183160,7 @@ var init_resume_snapshot = __esmMin((() => {
|
|
|
182501
183160
|
verificationScope: _enum(GOAL_VERIFICATION_SCOPES).optional()
|
|
182502
183161
|
}),
|
|
182503
183162
|
record$1("goal.update", {
|
|
183163
|
+
objective: text.min(1).max(4e3).regex(/\S/).optional(),
|
|
182504
183164
|
status: _enum([
|
|
182505
183165
|
"active",
|
|
182506
183166
|
"paused",
|
|
@@ -182552,7 +183212,7 @@ var init_resume_snapshot = __esmMin((() => {
|
|
|
182552
183212
|
}).passthrough();
|
|
182553
183213
|
origin = union([
|
|
182554
183214
|
originCase("user"),
|
|
182555
|
-
originCase("compaction_summary"),
|
|
183215
|
+
originCase("compaction_summary", { toolContinuity: custom$1(isToolContinuity).optional() }),
|
|
182556
183216
|
originCase("skill_activation", {
|
|
182557
183217
|
activationId: text,
|
|
182558
183218
|
skillName: text,
|
|
@@ -182789,6 +183449,7 @@ async function writeResumeCheckpoint(wirePath, position, snapshot) {
|
|
|
182789
183449
|
if (Buffer.byteLength(bytes) > MAX_CHECKPOINT_BYTES) return false;
|
|
182790
183450
|
const target = resumeCheckpointPath(wirePath);
|
|
182791
183451
|
const temporary = `${target}.tmp-${process.pid}-${randomBytes(8).toString("hex")}`;
|
|
183452
|
+
let renamed = false;
|
|
182792
183453
|
try {
|
|
182793
183454
|
const output = await open(temporary, "wx", 384);
|
|
182794
183455
|
try {
|
|
@@ -182798,10 +183459,11 @@ async function writeResumeCheckpoint(wirePath, position, snapshot) {
|
|
|
182798
183459
|
await output.close();
|
|
182799
183460
|
}
|
|
182800
183461
|
await rename(temporary, target);
|
|
183462
|
+
renamed = true;
|
|
182801
183463
|
await syncDir(dirname$3(target));
|
|
182802
183464
|
return true;
|
|
182803
183465
|
} finally {
|
|
182804
|
-
await rm(temporary, { force: true }).catch(() => {});
|
|
183466
|
+
if (!renamed) await rm(temporary, { force: true }).catch(() => {});
|
|
182805
183467
|
}
|
|
182806
183468
|
}
|
|
182807
183469
|
var MAX_RESUME_SNAPSHOT_BYTES, MAX_CHECKPOINT_BYTES, SAMPLE_BYTES, integer, digest$1, exactInteger, samplesSchema, identitySchema, envelopeSchema$2, resumeCheckpointPath, sha256$6, milliseconds;
|
|
@@ -186215,503 +186877,6 @@ var init_todo_list = __esmMin((() => {
|
|
|
186215
186877
|
};
|
|
186216
186878
|
}));
|
|
186217
186879
|
//#endregion
|
|
186218
|
-
//#region ../../packages/agent-core/src/tools/support/file-type.ts
|
|
186219
|
-
function toBuffer$2(data) {
|
|
186220
|
-
return Buffer.isBuffer(data) ? data : Buffer.from(data.buffer, data.byteOffset, data.byteLength);
|
|
186221
|
-
}
|
|
186222
|
-
function startsWith(buf, prefix) {
|
|
186223
|
-
const needle = Buffer.isBuffer(prefix) ? prefix : Buffer.from(prefix);
|
|
186224
|
-
if (buf.length < needle.length) return false;
|
|
186225
|
-
for (let i = 0; i < needle.length; i += 1) if (buf[i] !== needle[i]) return false;
|
|
186226
|
-
return true;
|
|
186227
|
-
}
|
|
186228
|
-
function sniffFtypBrand(header) {
|
|
186229
|
-
if (header.length < 12) return null;
|
|
186230
|
-
if (header.subarray(4, 8).toString("latin1") !== "ftyp") return null;
|
|
186231
|
-
return header.subarray(8, 12).toString("latin1").toLowerCase().replaceAll(/[\s\u0000]+$/g, "").trim();
|
|
186232
|
-
}
|
|
186233
|
-
function sniffMediaFromMagic(data) {
|
|
186234
|
-
const buf = toBuffer$2(data);
|
|
186235
|
-
const header = buf.length > 512 ? buf.subarray(0, 512) : buf;
|
|
186236
|
-
if (startsWith(header, [
|
|
186237
|
-
137,
|
|
186238
|
-
80,
|
|
186239
|
-
78,
|
|
186240
|
-
71,
|
|
186241
|
-
13,
|
|
186242
|
-
10,
|
|
186243
|
-
26,
|
|
186244
|
-
10
|
|
186245
|
-
])) return {
|
|
186246
|
-
kind: "image",
|
|
186247
|
-
mimeType: "image/png"
|
|
186248
|
-
};
|
|
186249
|
-
if (startsWith(header, [
|
|
186250
|
-
255,
|
|
186251
|
-
216,
|
|
186252
|
-
255
|
|
186253
|
-
])) return {
|
|
186254
|
-
kind: "image",
|
|
186255
|
-
mimeType: "image/jpeg"
|
|
186256
|
-
};
|
|
186257
|
-
if (startsWith(header, Buffer.from("GIF87a")) || startsWith(header, Buffer.from("GIF89a"))) return {
|
|
186258
|
-
kind: "image",
|
|
186259
|
-
mimeType: "image/gif"
|
|
186260
|
-
};
|
|
186261
|
-
if (startsWith(header, Buffer.from("BM"))) return {
|
|
186262
|
-
kind: "image",
|
|
186263
|
-
mimeType: "image/bmp"
|
|
186264
|
-
};
|
|
186265
|
-
if (startsWith(header, [
|
|
186266
|
-
73,
|
|
186267
|
-
73,
|
|
186268
|
-
42,
|
|
186269
|
-
0
|
|
186270
|
-
]) || startsWith(header, [
|
|
186271
|
-
77,
|
|
186272
|
-
77,
|
|
186273
|
-
0,
|
|
186274
|
-
42
|
|
186275
|
-
])) return {
|
|
186276
|
-
kind: "image",
|
|
186277
|
-
mimeType: "image/tiff"
|
|
186278
|
-
};
|
|
186279
|
-
if (startsWith(header, [
|
|
186280
|
-
0,
|
|
186281
|
-
0,
|
|
186282
|
-
1,
|
|
186283
|
-
0
|
|
186284
|
-
])) return {
|
|
186285
|
-
kind: "image",
|
|
186286
|
-
mimeType: "image/x-icon"
|
|
186287
|
-
};
|
|
186288
|
-
if (startsWith(header, Buffer.from("RIFF")) && header.length >= 12) {
|
|
186289
|
-
const chunk = header.subarray(8, 12).toString("latin1");
|
|
186290
|
-
if (chunk === "WEBP") return {
|
|
186291
|
-
kind: "image",
|
|
186292
|
-
mimeType: "image/webp"
|
|
186293
|
-
};
|
|
186294
|
-
if (chunk === "AVI ") return {
|
|
186295
|
-
kind: "video",
|
|
186296
|
-
mimeType: "video/x-msvideo"
|
|
186297
|
-
};
|
|
186298
|
-
}
|
|
186299
|
-
if (startsWith(header, Buffer.from("FLV"))) return {
|
|
186300
|
-
kind: "video",
|
|
186301
|
-
mimeType: "video/x-flv"
|
|
186302
|
-
};
|
|
186303
|
-
if (startsWith(header, ASF_HEADER)) return {
|
|
186304
|
-
kind: "video",
|
|
186305
|
-
mimeType: "video/x-ms-wmv"
|
|
186306
|
-
};
|
|
186307
|
-
if (startsWith(header, [
|
|
186308
|
-
26,
|
|
186309
|
-
69,
|
|
186310
|
-
223,
|
|
186311
|
-
163
|
|
186312
|
-
])) {
|
|
186313
|
-
const lowered = header.toString("latin1").toLowerCase();
|
|
186314
|
-
if (lowered.includes("webm")) return {
|
|
186315
|
-
kind: "video",
|
|
186316
|
-
mimeType: "video/webm"
|
|
186317
|
-
};
|
|
186318
|
-
if (lowered.includes("matroska")) return {
|
|
186319
|
-
kind: "video",
|
|
186320
|
-
mimeType: "video/x-matroska"
|
|
186321
|
-
};
|
|
186322
|
-
}
|
|
186323
|
-
const brand = sniffFtypBrand(header);
|
|
186324
|
-
if (brand !== null && brand !== "") {
|
|
186325
|
-
if (brand in FTYP_IMAGE_BRANDS) return {
|
|
186326
|
-
kind: "image",
|
|
186327
|
-
mimeType: FTYP_IMAGE_BRANDS[brand]
|
|
186328
|
-
};
|
|
186329
|
-
if (brand in FTYP_VIDEO_BRANDS) return {
|
|
186330
|
-
kind: "video",
|
|
186331
|
-
mimeType: FTYP_VIDEO_BRANDS[brand]
|
|
186332
|
-
};
|
|
186333
|
-
}
|
|
186334
|
-
return null;
|
|
186335
|
-
}
|
|
186336
|
-
/**
|
|
186337
|
-
* Best-effort pixel-dimension reader for common raster formats.
|
|
186338
|
-
*
|
|
186339
|
-
* Inspects only the fixed region near the start of the file where each
|
|
186340
|
-
* format records its dimensions (the IHDR/DIB header, the RIFF chunk
|
|
186341
|
-
* after the `WEBP` tag, or the first JPEG SOFn segment). Returns `null`
|
|
186342
|
-
* for formats whose dimensions are not locatable from that region, or
|
|
186343
|
-
* when the supplied buffer is too short to cover it.
|
|
186344
|
-
*/
|
|
186345
|
-
function sniffImageDimensions(data) {
|
|
186346
|
-
const buf = toBuffer$2(data);
|
|
186347
|
-
if (startsWith(buf, [
|
|
186348
|
-
137,
|
|
186349
|
-
80,
|
|
186350
|
-
78,
|
|
186351
|
-
71,
|
|
186352
|
-
13,
|
|
186353
|
-
10,
|
|
186354
|
-
26,
|
|
186355
|
-
10
|
|
186356
|
-
]) && buf.length >= 24) return {
|
|
186357
|
-
width: buf.readUInt32BE(16),
|
|
186358
|
-
height: buf.readUInt32BE(20)
|
|
186359
|
-
};
|
|
186360
|
-
if ((startsWith(buf, Buffer.from("GIF87a")) || startsWith(buf, Buffer.from("GIF89a"))) && buf.length >= 10) return {
|
|
186361
|
-
width: buf.readUInt16LE(6),
|
|
186362
|
-
height: buf.readUInt16LE(8)
|
|
186363
|
-
};
|
|
186364
|
-
if (startsWith(buf, Buffer.from("BM")) && buf.length >= 26) return {
|
|
186365
|
-
width: buf.readInt32LE(18),
|
|
186366
|
-
height: Math.abs(buf.readInt32LE(22))
|
|
186367
|
-
};
|
|
186368
|
-
if (startsWith(buf, Buffer.from("RIFF")) && buf.length >= 30) {
|
|
186369
|
-
const fourCc = buf.subarray(12, 16).toString("latin1");
|
|
186370
|
-
if (fourCc === "VP8 ") return {
|
|
186371
|
-
width: buf.readUInt16LE(26) & 16383,
|
|
186372
|
-
height: buf.readUInt16LE(28) & 16383
|
|
186373
|
-
};
|
|
186374
|
-
if (fourCc === "VP8L" && buf.length >= 25) {
|
|
186375
|
-
const bits = buf.readUInt32LE(21);
|
|
186376
|
-
return {
|
|
186377
|
-
width: (bits & 16383) + 1,
|
|
186378
|
-
height: (bits >> 14 & 16383) + 1
|
|
186379
|
-
};
|
|
186380
|
-
}
|
|
186381
|
-
if (fourCc === "VP8X") return {
|
|
186382
|
-
width: 1 + (buf[24] | buf[25] << 8 | buf[26] << 16),
|
|
186383
|
-
height: 1 + (buf[27] | buf[28] << 8 | buf[29] << 16)
|
|
186384
|
-
};
|
|
186385
|
-
}
|
|
186386
|
-
if (startsWith(buf, [255, 216])) {
|
|
186387
|
-
let offset = 2;
|
|
186388
|
-
while (offset + 9 < buf.length) {
|
|
186389
|
-
if (buf[offset] !== 255) {
|
|
186390
|
-
offset += 1;
|
|
186391
|
-
continue;
|
|
186392
|
-
}
|
|
186393
|
-
const marker = buf[offset + 1];
|
|
186394
|
-
if (marker >= 192 && marker <= 207 && marker !== 196 && marker !== 200 && marker !== 204) return {
|
|
186395
|
-
height: buf.readUInt16BE(offset + 5),
|
|
186396
|
-
width: buf.readUInt16BE(offset + 7)
|
|
186397
|
-
};
|
|
186398
|
-
if (marker === 216 || marker === 217 || marker >= 208 && marker <= 215) {
|
|
186399
|
-
offset += 2;
|
|
186400
|
-
continue;
|
|
186401
|
-
}
|
|
186402
|
-
const segmentLength = buf.readUInt16BE(offset + 2);
|
|
186403
|
-
if (segmentLength < 2) break;
|
|
186404
|
-
offset += 2 + segmentLength;
|
|
186405
|
-
}
|
|
186406
|
-
}
|
|
186407
|
-
return null;
|
|
186408
|
-
}
|
|
186409
|
-
function getSuffix(path) {
|
|
186410
|
-
const idx = path.lastIndexOf(".");
|
|
186411
|
-
if (idx === -1) return "";
|
|
186412
|
-
if (idx <= Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\")) + 1) return "";
|
|
186413
|
-
return path.slice(idx).toLowerCase();
|
|
186414
|
-
}
|
|
186415
|
-
function detectFileType(path, header, type = "text") {
|
|
186416
|
-
const suffix = getSuffix(path);
|
|
186417
|
-
let mediaHint = null;
|
|
186418
|
-
if (suffix in TEXT_MIME_BY_SUFFIX) mediaHint = {
|
|
186419
|
-
kind: "text",
|
|
186420
|
-
mimeType: TEXT_MIME_BY_SUFFIX[suffix]
|
|
186421
|
-
};
|
|
186422
|
-
else if (suffix in IMAGE_MIME_BY_SUFFIX) mediaHint = {
|
|
186423
|
-
kind: "image",
|
|
186424
|
-
mimeType: IMAGE_MIME_BY_SUFFIX[suffix]
|
|
186425
|
-
};
|
|
186426
|
-
else if (suffix in VIDEO_MIME_BY_SUFFIX$1) mediaHint = {
|
|
186427
|
-
kind: "video",
|
|
186428
|
-
mimeType: VIDEO_MIME_BY_SUFFIX$1[suffix]
|
|
186429
|
-
};
|
|
186430
|
-
if (header !== void 0) {
|
|
186431
|
-
const buf = toBuffer$2(header);
|
|
186432
|
-
const sniffed = sniffMediaFromMagic(buf);
|
|
186433
|
-
if (sniffed) {
|
|
186434
|
-
if (type === "media") return sniffed;
|
|
186435
|
-
if (mediaHint) {
|
|
186436
|
-
if (sniffed.kind !== mediaHint.kind) return {
|
|
186437
|
-
kind: "unknown",
|
|
186438
|
-
mimeType: ""
|
|
186439
|
-
};
|
|
186440
|
-
return mediaHint;
|
|
186441
|
-
}
|
|
186442
|
-
return sniffed;
|
|
186443
|
-
}
|
|
186444
|
-
if (mediaHint?.kind === "image") return {
|
|
186445
|
-
kind: "unknown",
|
|
186446
|
-
mimeType: ""
|
|
186447
|
-
};
|
|
186448
|
-
if (type === "media" && mediaHint?.kind === "video") return mediaHint;
|
|
186449
|
-
if (buf.includes(0)) return {
|
|
186450
|
-
kind: "unknown",
|
|
186451
|
-
mimeType: ""
|
|
186452
|
-
};
|
|
186453
|
-
}
|
|
186454
|
-
if (mediaHint) return mediaHint;
|
|
186455
|
-
if (NON_TEXT_SUFFIXES.has(suffix)) return {
|
|
186456
|
-
kind: "unknown",
|
|
186457
|
-
mimeType: ""
|
|
186458
|
-
};
|
|
186459
|
-
return {
|
|
186460
|
-
kind: "text",
|
|
186461
|
-
mimeType: "text/plain"
|
|
186462
|
-
};
|
|
186463
|
-
}
|
|
186464
|
-
var IMAGE_MIME_BY_SUFFIX, VIDEO_MIME_BY_SUFFIX$1, TEXT_MIME_BY_SUFFIX, NON_TEXT_SUFFIXES, ASF_HEADER, FTYP_IMAGE_BRANDS, FTYP_VIDEO_BRANDS;
|
|
186465
|
-
var init_file_type$1 = __esmMin((() => {
|
|
186466
|
-
IMAGE_MIME_BY_SUFFIX = Object.freeze({
|
|
186467
|
-
".png": "image/png",
|
|
186468
|
-
".jpg": "image/jpeg",
|
|
186469
|
-
".jpeg": "image/jpeg",
|
|
186470
|
-
".gif": "image/gif",
|
|
186471
|
-
".bmp": "image/bmp",
|
|
186472
|
-
".tif": "image/tiff",
|
|
186473
|
-
".tiff": "image/tiff",
|
|
186474
|
-
".webp": "image/webp",
|
|
186475
|
-
".ico": "image/x-icon",
|
|
186476
|
-
".heic": "image/heic",
|
|
186477
|
-
".heif": "image/heif",
|
|
186478
|
-
".avif": "image/avif",
|
|
186479
|
-
".svgz": "image/svg+xml"
|
|
186480
|
-
});
|
|
186481
|
-
VIDEO_MIME_BY_SUFFIX$1 = Object.freeze({
|
|
186482
|
-
".mp4": "video/mp4",
|
|
186483
|
-
".mpg": "video/mpeg",
|
|
186484
|
-
".mpeg": "video/mpeg",
|
|
186485
|
-
".mkv": "video/x-matroska",
|
|
186486
|
-
".avi": "video/x-msvideo",
|
|
186487
|
-
".mov": "video/quicktime",
|
|
186488
|
-
".ogv": "video/ogg",
|
|
186489
|
-
".wmv": "video/x-ms-wmv",
|
|
186490
|
-
".webm": "video/webm",
|
|
186491
|
-
".m4v": "video/x-m4v",
|
|
186492
|
-
".flv": "video/x-flv",
|
|
186493
|
-
".3gp": "video/3gpp",
|
|
186494
|
-
".3g2": "video/3gpp2"
|
|
186495
|
-
});
|
|
186496
|
-
TEXT_MIME_BY_SUFFIX = Object.freeze({ ".svg": "image/svg+xml" });
|
|
186497
|
-
NON_TEXT_SUFFIXES = new Set([
|
|
186498
|
-
".icns",
|
|
186499
|
-
".psd",
|
|
186500
|
-
".ai",
|
|
186501
|
-
".eps",
|
|
186502
|
-
".pdf",
|
|
186503
|
-
".doc",
|
|
186504
|
-
".docx",
|
|
186505
|
-
".dot",
|
|
186506
|
-
".dotx",
|
|
186507
|
-
".rtf",
|
|
186508
|
-
".odt",
|
|
186509
|
-
".xls",
|
|
186510
|
-
".xlsx",
|
|
186511
|
-
".xlsm",
|
|
186512
|
-
".xlt",
|
|
186513
|
-
".xltx",
|
|
186514
|
-
".xltm",
|
|
186515
|
-
".ods",
|
|
186516
|
-
".ppt",
|
|
186517
|
-
".pptx",
|
|
186518
|
-
".pptm",
|
|
186519
|
-
".pps",
|
|
186520
|
-
".ppsx",
|
|
186521
|
-
".odp",
|
|
186522
|
-
".pages",
|
|
186523
|
-
".numbers",
|
|
186524
|
-
".key",
|
|
186525
|
-
".zip",
|
|
186526
|
-
".rar",
|
|
186527
|
-
".7z",
|
|
186528
|
-
".tar",
|
|
186529
|
-
".gz",
|
|
186530
|
-
".tgz",
|
|
186531
|
-
".bz2",
|
|
186532
|
-
".xz",
|
|
186533
|
-
".zst",
|
|
186534
|
-
".lz",
|
|
186535
|
-
".lz4",
|
|
186536
|
-
".br",
|
|
186537
|
-
".cab",
|
|
186538
|
-
".ar",
|
|
186539
|
-
".deb",
|
|
186540
|
-
".rpm",
|
|
186541
|
-
".mp3",
|
|
186542
|
-
".wav",
|
|
186543
|
-
".flac",
|
|
186544
|
-
".ogg",
|
|
186545
|
-
".oga",
|
|
186546
|
-
".opus",
|
|
186547
|
-
".aac",
|
|
186548
|
-
".m4a",
|
|
186549
|
-
".wma",
|
|
186550
|
-
".ttf",
|
|
186551
|
-
".otf",
|
|
186552
|
-
".woff",
|
|
186553
|
-
".woff2",
|
|
186554
|
-
".exe",
|
|
186555
|
-
".dll",
|
|
186556
|
-
".so",
|
|
186557
|
-
".dylib",
|
|
186558
|
-
".bin",
|
|
186559
|
-
".apk",
|
|
186560
|
-
".ipa",
|
|
186561
|
-
".jar",
|
|
186562
|
-
".class",
|
|
186563
|
-
".pyc",
|
|
186564
|
-
".pyo",
|
|
186565
|
-
".wasm",
|
|
186566
|
-
".dmg",
|
|
186567
|
-
".iso",
|
|
186568
|
-
".img",
|
|
186569
|
-
".sqlite",
|
|
186570
|
-
".sqlite3",
|
|
186571
|
-
".db",
|
|
186572
|
-
".db3"
|
|
186573
|
-
]);
|
|
186574
|
-
ASF_HEADER = Buffer.from([
|
|
186575
|
-
48,
|
|
186576
|
-
38,
|
|
186577
|
-
178,
|
|
186578
|
-
117,
|
|
186579
|
-
142,
|
|
186580
|
-
102,
|
|
186581
|
-
207,
|
|
186582
|
-
17,
|
|
186583
|
-
166,
|
|
186584
|
-
217,
|
|
186585
|
-
0,
|
|
186586
|
-
170,
|
|
186587
|
-
0,
|
|
186588
|
-
98,
|
|
186589
|
-
206,
|
|
186590
|
-
108
|
|
186591
|
-
]);
|
|
186592
|
-
FTYP_IMAGE_BRANDS = Object.freeze({
|
|
186593
|
-
avif: "image/avif",
|
|
186594
|
-
avis: "image/avif",
|
|
186595
|
-
heic: "image/heic",
|
|
186596
|
-
heif: "image/heif",
|
|
186597
|
-
heix: "image/heif",
|
|
186598
|
-
hevc: "image/heic",
|
|
186599
|
-
mif1: "image/heif",
|
|
186600
|
-
msf1: "image/heif"
|
|
186601
|
-
});
|
|
186602
|
-
FTYP_VIDEO_BRANDS = Object.freeze({
|
|
186603
|
-
isom: "video/mp4",
|
|
186604
|
-
iso2: "video/mp4",
|
|
186605
|
-
iso5: "video/mp4",
|
|
186606
|
-
mp41: "video/mp4",
|
|
186607
|
-
mp42: "video/mp4",
|
|
186608
|
-
avc1: "video/mp4",
|
|
186609
|
-
mp4v: "video/mp4",
|
|
186610
|
-
m4v: "video/x-m4v",
|
|
186611
|
-
qt: "video/quicktime",
|
|
186612
|
-
"3gp4": "video/3gpp",
|
|
186613
|
-
"3gp5": "video/3gpp",
|
|
186614
|
-
"3gp6": "video/3gpp",
|
|
186615
|
-
"3gp7": "video/3gpp",
|
|
186616
|
-
"3g2": "video/3gpp2"
|
|
186617
|
-
});
|
|
186618
|
-
}));
|
|
186619
|
-
//#endregion
|
|
186620
|
-
//#region ../../packages/agent-core/src/utils/tokens.ts
|
|
186621
|
-
/** Open assistant messages grow while streaming; completed history stays cached. */
|
|
186622
|
-
function invalidateMessageTokenEstimate(message) {
|
|
186623
|
-
messageTokenEstimateCache.delete(message);
|
|
186624
|
-
}
|
|
186625
|
-
/**
|
|
186626
|
-
* Estimate token count from text using a character-based heuristic.
|
|
186627
|
-
* - ASCII (~4 chars per token)
|
|
186628
|
-
* - CJK and other non-ASCII (~1 char per token)
|
|
186629
|
-
* The estimate is transient — the next LLM call returns the real count
|
|
186630
|
-
* and supersedes this value. Used to keep `tokenCountWithPending`
|
|
186631
|
-
* monotonic between LLM round-trips without paying for a tokenizer.
|
|
186632
|
-
*/
|
|
186633
|
-
function estimateTokens(text) {
|
|
186634
|
-
let asciiCount = 0;
|
|
186635
|
-
let nonAsciiCount = 0;
|
|
186636
|
-
for (const char of text) if (char.codePointAt(0) <= 127) asciiCount++;
|
|
186637
|
-
else nonAsciiCount++;
|
|
186638
|
-
return Math.ceil(asciiCount / 4) + nonAsciiCount;
|
|
186639
|
-
}
|
|
186640
|
-
function estimateTokensForMessages(messages) {
|
|
186641
|
-
let total = 0;
|
|
186642
|
-
for (const message of messages) total += estimateTokensForMessage(message);
|
|
186643
|
-
return total;
|
|
186644
|
-
}
|
|
186645
|
-
function estimateTokensForTools(tools) {
|
|
186646
|
-
let total = 0;
|
|
186647
|
-
for (const tool of tools) {
|
|
186648
|
-
total += estimateTokens(tool.name);
|
|
186649
|
-
total += estimateTokens(tool.description);
|
|
186650
|
-
total += estimateTokens(JSON.stringify(tool.parameters));
|
|
186651
|
-
}
|
|
186652
|
-
return total;
|
|
186653
|
-
}
|
|
186654
|
-
function estimateTokensForMessage(message) {
|
|
186655
|
-
const cached = messageTokenEstimateCache.get(message);
|
|
186656
|
-
if (cached !== void 0) return cached;
|
|
186657
|
-
let total = estimateTokens(message.role);
|
|
186658
|
-
total += estimateTokensForContentParts(message.content);
|
|
186659
|
-
if (message.toolCalls !== void 0) for (const call of message.toolCalls) {
|
|
186660
|
-
total += estimateTokens(call.name);
|
|
186661
|
-
total += estimateTokens(JSON.stringify(call.arguments));
|
|
186662
|
-
}
|
|
186663
|
-
messageTokenEstimateCache.set(message, total);
|
|
186664
|
-
return total;
|
|
186665
|
-
}
|
|
186666
|
-
function estimateTokensForContentParts(parts) {
|
|
186667
|
-
let total = 0;
|
|
186668
|
-
for (const part of parts) total += estimateTokensForContentPart(part);
|
|
186669
|
-
return total;
|
|
186670
|
-
}
|
|
186671
|
-
function imageDimensionsFromDataUrl(url) {
|
|
186672
|
-
const commaIndex = url.indexOf(",");
|
|
186673
|
-
if (commaIndex <= 0) return null;
|
|
186674
|
-
const metadata = url.slice(0, commaIndex).toLowerCase();
|
|
186675
|
-
if (!metadata.startsWith("data:image/") || !metadata.split(";").includes("base64")) return null;
|
|
186676
|
-
const maxBase64Chars = Math.ceil(MAX_IMAGE_HEADER_BYTES / 3) * 4;
|
|
186677
|
-
const encodedHeader = url.slice(commaIndex + 1, commaIndex + 1 + maxBase64Chars);
|
|
186678
|
-
if (encodedHeader.length === 0) return null;
|
|
186679
|
-
try {
|
|
186680
|
-
const dimensions = sniffImageDimensions(Buffer.from(encodedHeader, "base64"));
|
|
186681
|
-
if (dimensions === null || !Number.isSafeInteger(dimensions.width) || !Number.isSafeInteger(dimensions.height) || dimensions.width <= 0 || dimensions.height <= 0) return null;
|
|
186682
|
-
return dimensions;
|
|
186683
|
-
} catch {
|
|
186684
|
-
return null;
|
|
186685
|
-
}
|
|
186686
|
-
}
|
|
186687
|
-
function estimateImageTokensFromDimensions(width, height) {
|
|
186688
|
-
if (!Number.isSafeInteger(width) || !Number.isSafeInteger(height) || width <= 0 || height <= 0) return MEDIA_TOKEN_ESTIMATE;
|
|
186689
|
-
const patchSize = BigInt(32);
|
|
186690
|
-
const tokens = (BigInt(width) + patchSize - 1n) / patchSize * ((BigInt(height) + patchSize - 1n) / patchSize);
|
|
186691
|
-
return tokens > BigInt(Number.MAX_SAFE_INTEGER) ? Number.MAX_SAFE_INTEGER : Number(tokens);
|
|
186692
|
-
}
|
|
186693
|
-
function estimateImageTokens(url) {
|
|
186694
|
-
const dimensions = imageDimensionsFromDataUrl(url);
|
|
186695
|
-
return dimensions === null ? MEDIA_TOKEN_ESTIMATE : estimateImageTokensFromDimensions(dimensions.width, dimensions.height);
|
|
186696
|
-
}
|
|
186697
|
-
function estimateTokensForContentPart(part) {
|
|
186698
|
-
switch (part.type) {
|
|
186699
|
-
case "text": return estimateTokens(part.text);
|
|
186700
|
-
case "think": return estimateTokens(part.think);
|
|
186701
|
-
case "image_url": return estimateImageTokens(part.imageUrl.url);
|
|
186702
|
-
case "audio_url":
|
|
186703
|
-
case "video_url": return MEDIA_TOKEN_ESTIMATE;
|
|
186704
|
-
default: return 0;
|
|
186705
|
-
}
|
|
186706
|
-
}
|
|
186707
|
-
var messageTokenEstimateCache, MEDIA_TOKEN_ESTIMATE, MAX_IMAGE_HEADER_BYTES;
|
|
186708
|
-
var init_tokens = __esmMin((() => {
|
|
186709
|
-
init_file_type$1();
|
|
186710
|
-
messageTokenEstimateCache = /* @__PURE__ */ new WeakMap();
|
|
186711
|
-
MEDIA_TOKEN_ESTIMATE = 2e3;
|
|
186712
|
-
MAX_IMAGE_HEADER_BYTES = 1024 * 1024;
|
|
186713
|
-
}));
|
|
186714
|
-
//#endregion
|
|
186715
186880
|
//#region ../../node_modules/.pnpm/bmp-ts@1.0.9/node_modules/bmp-ts/dist/esm/header-types.js
|
|
186716
186881
|
var HeaderTypes, header_types_default;
|
|
186717
186882
|
var init_header_types = __esmMin((() => {
|
|
@@ -235103,8 +235268,9 @@ function makeSyntheticToolResult(toolCallId) {
|
|
|
235103
235268
|
}
|
|
235104
235269
|
function mergeAdjacentUserMessages(history, onAnomaly) {
|
|
235105
235270
|
const out = [];
|
|
235106
|
-
|
|
235107
|
-
|
|
235271
|
+
const latestUserIndex = history.findLastIndex((message) => message.role === "user" && message.partial !== true && (message.origin === void 0 || message.origin.kind === "user"));
|
|
235272
|
+
for (const [index, source] of history.entries()) {
|
|
235273
|
+
const message = prepareMessageForProjection(source, onAnomaly, index < latestUserIndex);
|
|
235108
235274
|
if (message === null) continue;
|
|
235109
235275
|
const previous = out.at(-1);
|
|
235110
235276
|
if (canMergeUserMessage(message) && previous !== void 0 && canMergeUserMessage(previous)) {
|
|
@@ -235115,7 +235281,7 @@ function mergeAdjacentUserMessages(history, onAnomaly) {
|
|
|
235115
235281
|
}
|
|
235116
235282
|
return out.map(stripContextMetadata);
|
|
235117
235283
|
}
|
|
235118
|
-
function prepareMessageForProjection(message, onAnomaly) {
|
|
235284
|
+
function prepareMessageForProjection(message, onAnomaly, historical = false) {
|
|
235119
235285
|
if (message.partial === true) return null;
|
|
235120
235286
|
let content;
|
|
235121
235287
|
for (const [index, part] of message.content.entries()) {
|
|
@@ -235127,6 +235293,19 @@ function prepareMessageForProjection(message, onAnomaly) {
|
|
|
235127
235293
|
});
|
|
235128
235294
|
continue;
|
|
235129
235295
|
}
|
|
235296
|
+
if (historical && message.role === "user" && part.type === "text") {
|
|
235297
|
+
const text = withoutHistoricalTelegramGroupReminder(part.text);
|
|
235298
|
+
if (text !== part.text) {
|
|
235299
|
+
content ??= message.content.slice(0, index);
|
|
235300
|
+
const shortened = {
|
|
235301
|
+
...part,
|
|
235302
|
+
text
|
|
235303
|
+
};
|
|
235304
|
+
copyRequestTextOrigin(part, shortened, message.origin);
|
|
235305
|
+
content.push(shortened);
|
|
235306
|
+
continue;
|
|
235307
|
+
}
|
|
235308
|
+
}
|
|
235130
235309
|
content?.push(part);
|
|
235131
235310
|
}
|
|
235132
235311
|
const next = content === void 0 ? message : {
|
|
@@ -235136,6 +235315,14 @@ function prepareMessageForProjection(message, onAnomaly) {
|
|
|
235136
235315
|
if (next.role === "tool" && next.content.length === 0) throw new BlunError(ErrorCodes.REQUEST_INVALID, "Tool result message content cannot be empty after removing empty text blocks.", { details: { toolCallId: next.toolCallId } });
|
|
235137
235316
|
return next.content.length === 0 && next.toolCalls.length === 0 ? null : next;
|
|
235138
235317
|
}
|
|
235318
|
+
function withoutHistoricalTelegramGroupReminder(text) {
|
|
235319
|
+
if (!text.startsWith("<channel source=\"telegram\"") && !text.startsWith("You are connected to a Telegram channel.")) return text;
|
|
235320
|
+
const start = text.lastIndexOf(`</channel>\n[GRUPPENANTWORT:`);
|
|
235321
|
+
if (start < 0) return text;
|
|
235322
|
+
const reminder = text.slice(start + 10 + 1);
|
|
235323
|
+
if (!/^\[GRUPPENANTWORT:[^\r\n]*\]$/.test(reminder)) return text;
|
|
235324
|
+
return text.slice(0, start + 10);
|
|
235325
|
+
}
|
|
235139
235326
|
function canMergeUserMessage(message) {
|
|
235140
235327
|
return message.role === "user" && message.origin?.kind === "user";
|
|
235141
235328
|
}
|
|
@@ -235267,6 +235454,7 @@ var init_context$2 = __esmMin((() => {
|
|
|
235267
235454
|
init_tokens();
|
|
235268
235455
|
init_xml_escape();
|
|
235269
235456
|
init_compaction();
|
|
235457
|
+
init_tool_continuity();
|
|
235270
235458
|
init_projector();
|
|
235271
235459
|
init_types$6();
|
|
235272
235460
|
init_types$6();
|
|
@@ -235277,6 +235465,8 @@ var init_context$2 = __esmMin((() => {
|
|
|
235277
235465
|
TOOL_INTERRUPTED_ON_RESUME_OUTPUT$2 = "Tool execution was interrupted before its result was recorded. Do not assume the tool completed successfully.";
|
|
235278
235466
|
ContextMemory = class {
|
|
235279
235467
|
agent;
|
|
235468
|
+
mutationGeneration = randomUUID();
|
|
235469
|
+
mutationRevision = 0;
|
|
235280
235470
|
_history = [];
|
|
235281
235471
|
_tokenCount = 0;
|
|
235282
235472
|
tokenCountCoveredMessageCount = 0;
|
|
@@ -235288,6 +235478,15 @@ var init_context$2 = __esmMin((() => {
|
|
|
235288
235478
|
constructor(agent) {
|
|
235289
235479
|
this.agent = agent;
|
|
235290
235480
|
}
|
|
235481
|
+
publishMutation(reason) {
|
|
235482
|
+
if (this.agent.records.restoring) return;
|
|
235483
|
+
this.agent.emitEvent({
|
|
235484
|
+
type: "context.changed",
|
|
235485
|
+
generation: this.mutationGeneration,
|
|
235486
|
+
revision: ++this.mutationRevision,
|
|
235487
|
+
reason
|
|
235488
|
+
});
|
|
235489
|
+
}
|
|
235291
235490
|
get lastAssistantAt() {
|
|
235292
235491
|
return this._lastAssistantAt;
|
|
235293
235492
|
}
|
|
@@ -235441,6 +235640,7 @@ var init_context$2 = __esmMin((() => {
|
|
|
235441
235640
|
return removedMessages.size;
|
|
235442
235641
|
}
|
|
235443
235642
|
clear() {
|
|
235643
|
+
const changed = this._history.length > 0;
|
|
235444
235644
|
this.agent.records.logRecord({ type: "context.clear" });
|
|
235445
235645
|
this._history = [];
|
|
235446
235646
|
this._tokenCount = 0;
|
|
@@ -235452,6 +235652,7 @@ var init_context$2 = __esmMin((() => {
|
|
|
235452
235652
|
this.agent.microCompaction.reset();
|
|
235453
235653
|
this.agent.injection.onContextClear();
|
|
235454
235654
|
this.agent.emitStatusUpdated();
|
|
235655
|
+
if (changed) this.publishMutation("clear");
|
|
235455
235656
|
}
|
|
235456
235657
|
undo(count) {
|
|
235457
235658
|
if (count <= 0) return;
|
|
@@ -235489,6 +235690,7 @@ var init_context$2 = __esmMin((() => {
|
|
|
235489
235690
|
this.deferredMessages = [];
|
|
235490
235691
|
this.agent.microCompaction.reset(this._history.length);
|
|
235491
235692
|
this.agent.emitStatusUpdated();
|
|
235693
|
+
if (removedMessages.size > 0) this.publishMutation("undo");
|
|
235492
235694
|
if (!this.agent.records.restoring && (stoppedAtBoundary || removedUserCount < count)) throw new BlunError(ErrorCodes.REQUEST_INVALID, formatUndoUnavailableMessage(count, removedUserCount, stoppedAtBoundary), { details: {
|
|
235493
235695
|
reason: "undo_limit",
|
|
235494
235696
|
requestedCount: count,
|
|
@@ -235497,6 +235699,7 @@ var init_context$2 = __esmMin((() => {
|
|
|
235497
235699
|
} });
|
|
235498
235700
|
}
|
|
235499
235701
|
applyCompaction(input, options = {}) {
|
|
235702
|
+
if (this.agent.records.restoring !== null && input.toolContinuity !== void 0 && !isToolContinuity(input.toolContinuity)) throw new Error("Invalid compaction tool continuity");
|
|
235500
235703
|
let preservedToolTailCount = input.preservedToolTailCount;
|
|
235501
235704
|
if (this.agent.records.restoring === null && this.hasOpenToolExchange()) {
|
|
235502
235705
|
const start = this._history.findIndex((message) => message.role === "assistant" && message.toolCalls.some((call) => this.pendingToolResultIds.has(call.id)));
|
|
@@ -235533,25 +235736,75 @@ var init_context$2 = __esmMin((() => {
|
|
|
235533
235736
|
elisionMessage,
|
|
235534
235737
|
...selection.tail
|
|
235535
235738
|
];
|
|
235536
|
-
|
|
235537
|
-
|
|
235739
|
+
let contextSummary = input.contextSummary ?? input.summary;
|
|
235740
|
+
let toolContinuity = this.agent.records.restoring === null ? void 0 : input.toolContinuity;
|
|
235741
|
+
let summaryMessage = {
|
|
235538
235742
|
role: "user",
|
|
235539
235743
|
content: [{
|
|
235540
235744
|
type: "text",
|
|
235541
235745
|
text: contextSummary
|
|
235542
235746
|
}],
|
|
235543
235747
|
toolCalls: [],
|
|
235544
|
-
origin: {
|
|
235748
|
+
origin: {
|
|
235749
|
+
kind: "compaction_summary",
|
|
235750
|
+
...toolContinuity === void 0 ? {} : { toolContinuity }
|
|
235751
|
+
}
|
|
235545
235752
|
};
|
|
235546
|
-
|
|
235753
|
+
let replacement = [
|
|
235547
235754
|
...keptMessages,
|
|
235548
235755
|
summaryMessage,
|
|
235549
235756
|
...preservedToolTail
|
|
235550
235757
|
];
|
|
235758
|
+
const previousHistoryTokens = options.requireReduction && this.agent.records.restoring === null ? estimateTokensForMessages(project(this.agent.microCompaction.compact(this._history), { dropOrphanResults: true })) : void 0;
|
|
235759
|
+
if (this.agent.records.restoring === null) {
|
|
235760
|
+
toolContinuity = void 0;
|
|
235761
|
+
const observations = collectToolContinuity(this._history.slice(0, tailStart));
|
|
235762
|
+
if (observations !== void 0) {
|
|
235763
|
+
const baseProjected = project(replacement, { dropOrphanResults: true });
|
|
235764
|
+
const baseTokens = estimateTokensForMessages(baseProjected);
|
|
235765
|
+
let extraTokens = previousHistoryTokens === void 0 ? Number.POSITIVE_INFINITY : Math.max(0, previousHistoryTokens - baseTokens - 1);
|
|
235766
|
+
if (this.agent.config.hasProvider) {
|
|
235767
|
+
const window = this.agent.fullCompaction.getEffectiveMaxContextTokens();
|
|
235768
|
+
const budget = this.agent.fullCompaction.getCompactionBudgetTokens();
|
|
235769
|
+
const requestLimit = Math.min(window > 0 ? window - 1 : Number.POSITIVE_INFINITY, budget ?? Number.POSITIVE_INFINITY);
|
|
235770
|
+
extraTokens = Math.min(extraTokens, Math.max(0, requestLimit - this.agent.fullCompaction.estimateProjectedRequestTokens({ messages: baseProjected }) - 1));
|
|
235771
|
+
}
|
|
235772
|
+
let fitted = fitToolContinuity(observations, extraTokens);
|
|
235773
|
+
while (fitted !== void 0) {
|
|
235774
|
+
const candidateSummary = {
|
|
235775
|
+
...summaryMessage,
|
|
235776
|
+
content: [{
|
|
235777
|
+
type: "text",
|
|
235778
|
+
text: contextSummary + fitted.text
|
|
235779
|
+
}],
|
|
235780
|
+
origin: {
|
|
235781
|
+
kind: "compaction_summary",
|
|
235782
|
+
toolContinuity: fitted.continuity
|
|
235783
|
+
}
|
|
235784
|
+
};
|
|
235785
|
+
const candidate = [
|
|
235786
|
+
...keptMessages,
|
|
235787
|
+
candidateSummary,
|
|
235788
|
+
...preservedToolTail
|
|
235789
|
+
];
|
|
235790
|
+
const projected = project(candidate, { dropOrphanResults: true });
|
|
235791
|
+
const status = this.agent.fullCompaction.proactiveCompactionStatus({ messages: projected });
|
|
235792
|
+
const reducing = previousHistoryTokens === void 0 || estimateTokensForMessages(projected) < previousHistoryTokens;
|
|
235793
|
+
const bytesFit = (status.usedHistoryBytes === void 0 || status.thresholdHistoryBytes === void 0 || status.usedHistoryBytes < status.thresholdHistoryBytes) && (status.usedRequestBytesEstimate === void 0 || status.thresholdRequestBytes === void 0 || status.usedRequestBytesEstimate < status.thresholdRequestBytes);
|
|
235794
|
+
if (reducing && bytesFit) {
|
|
235795
|
+
toolContinuity = fitted.continuity;
|
|
235796
|
+
contextSummary += fitted.text;
|
|
235797
|
+
summaryMessage = candidateSummary;
|
|
235798
|
+
replacement = candidate;
|
|
235799
|
+
break;
|
|
235800
|
+
}
|
|
235801
|
+
fitted = fitToolContinuity(observations, estimateTokens(fitted.text) - 1);
|
|
235802
|
+
}
|
|
235803
|
+
}
|
|
235804
|
+
}
|
|
235551
235805
|
if (options.requireReduction && this.agent.records.restoring === null) {
|
|
235552
|
-
const previousHistoryTokens = estimateTokensForMessages(project(this.agent.microCompaction.compact(this._history), { dropOrphanResults: true }));
|
|
235553
235806
|
const nextHistoryTokens = estimateTokensForMessages(project(replacement, { dropOrphanResults: true }));
|
|
235554
|
-
if (nextHistoryTokens >= previousHistoryTokens) throw new BlunError(ErrorCodes.COMPACTION_FAILED, "Automatic compaction did not reduce the history. The conversation history was not changed.", { details: {
|
|
235807
|
+
if (previousHistoryTokens !== void 0 && nextHistoryTokens >= previousHistoryTokens) throw new BlunError(ErrorCodes.COMPACTION_FAILED, "Automatic compaction did not reduce the history. The conversation history was not changed.", { details: {
|
|
235555
235808
|
reason: "non_reducing_summary",
|
|
235556
235809
|
contextUnchanged: true,
|
|
235557
235810
|
previousHistoryTokens,
|
|
@@ -235564,6 +235817,7 @@ var init_context$2 = __esmMin((() => {
|
|
|
235564
235817
|
const result = {
|
|
235565
235818
|
summary: input.summary,
|
|
235566
235819
|
contextSummary,
|
|
235820
|
+
...toolContinuity === void 0 ? {} : { toolContinuity },
|
|
235567
235821
|
compactedCount: input.compactedCount,
|
|
235568
235822
|
tokensBefore: input.tokensBefore,
|
|
235569
235823
|
tokensAfter,
|
|
@@ -235580,6 +235834,7 @@ var init_context$2 = __esmMin((() => {
|
|
|
235580
235834
|
this.agent.replayBuilder.patchLast("compaction", { result: {
|
|
235581
235835
|
summary: result.summary,
|
|
235582
235836
|
contextSummary: result.contextSummary,
|
|
235837
|
+
...result.toolContinuity === void 0 ? {} : { toolContinuity: result.toolContinuity },
|
|
235583
235838
|
compactedCount: result.compactedCount,
|
|
235584
235839
|
tokensBefore: result.tokensBefore,
|
|
235585
235840
|
tokensAfter: result.tokensAfter,
|
|
@@ -237134,20 +237389,75 @@ function fingerprintTitle(title) {
|
|
|
237134
237389
|
return createHash("sha256").update(title.trim().toLowerCase()).digest("hex");
|
|
237135
237390
|
}
|
|
237136
237391
|
async function loadRegister(mistakeDir = defaultMistakeDir()) {
|
|
237392
|
+
const target = join(mistakeDir, REGISTER_FILENAME);
|
|
237137
237393
|
try {
|
|
237138
237394
|
await mkdir(mistakeDir, { recursive: true });
|
|
237139
|
-
const
|
|
237140
|
-
|
|
237141
|
-
|
|
237142
|
-
|
|
237395
|
+
const before = await lstat(target).catch((error) => {
|
|
237396
|
+
if (error.code === "ENOENT") return void 0;
|
|
237397
|
+
throw error;
|
|
237398
|
+
});
|
|
237399
|
+
if (before === void 0) return {
|
|
237143
237400
|
version: 1,
|
|
237144
237401
|
entries: []
|
|
237145
237402
|
};
|
|
237403
|
+
if (!before.isFile() || before.isSymbolicLink()) throw new Error("Mistake register must be a regular file.");
|
|
237404
|
+
const handle = await open(target, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
|
|
237405
|
+
let content;
|
|
237406
|
+
try {
|
|
237407
|
+
const opened = await handle.stat();
|
|
237408
|
+
if (!opened.isFile() || opened.dev !== before.dev || opened.ino !== before.ino) throw new Error("Mistake register changed while opening.");
|
|
237409
|
+
content = await handle.readFile("utf8");
|
|
237410
|
+
} finally {
|
|
237411
|
+
await handle.close();
|
|
237412
|
+
}
|
|
237413
|
+
let parsed;
|
|
237414
|
+
try {
|
|
237415
|
+
parsed = JSON.parse(content);
|
|
237416
|
+
} catch {
|
|
237417
|
+
throw new Error("Mistake register has invalid JSON.");
|
|
237418
|
+
}
|
|
237419
|
+
assertRegister(parsed);
|
|
237420
|
+
return parsed;
|
|
237421
|
+
} catch (error) {
|
|
237422
|
+
throw registerError(error, "read");
|
|
237146
237423
|
}
|
|
237147
237424
|
}
|
|
237148
237425
|
async function saveRegister(register, mistakeDir = defaultMistakeDir()) {
|
|
237149
|
-
|
|
237150
|
-
|
|
237426
|
+
assertRegister(register);
|
|
237427
|
+
const target = join(mistakeDir, REGISTER_FILENAME);
|
|
237428
|
+
const temporary = `${target}.tmp.${process.pid}.${randomUUID()}`;
|
|
237429
|
+
let created = false;
|
|
237430
|
+
try {
|
|
237431
|
+
await loadRegister(mistakeDir);
|
|
237432
|
+
const handle = await open(temporary, "wx", 384);
|
|
237433
|
+
created = true;
|
|
237434
|
+
try {
|
|
237435
|
+
await handle.writeFile(JSON.stringify(register, null, 2), "utf8");
|
|
237436
|
+
await handle.sync();
|
|
237437
|
+
} finally {
|
|
237438
|
+
await handle.close();
|
|
237439
|
+
}
|
|
237440
|
+
await rename(temporary, target);
|
|
237441
|
+
} catch (error) {
|
|
237442
|
+
throw registerError(error, "write");
|
|
237443
|
+
} finally {
|
|
237444
|
+
if (created) await unlink(temporary).catch(() => {});
|
|
237445
|
+
}
|
|
237446
|
+
}
|
|
237447
|
+
function assertRegister(value) {
|
|
237448
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error("Mistake register has an invalid v1 schema.");
|
|
237449
|
+
const register = value;
|
|
237450
|
+
if (register["version"] !== 1 || !Array.isArray(register["entries"]) || !register["entries"].every((entry) => {
|
|
237451
|
+
if (typeof entry !== "object" || entry === null || Array.isArray(entry)) return false;
|
|
237452
|
+
const fields = entry;
|
|
237453
|
+
return typeof fields["entryIndex"] === "number" && Number.isSafeInteger(fields["entryIndex"]) && fields["entryIndex"] >= 0 && typeof fields["titleFingerprint"] === "string" && fields["titleFingerprint"].trim().length > 0 && typeof fields["title"] === "string" && fields["title"].trim().length > 0 && typeof fields["count"] === "number" && Number.isSafeInteger(fields["count"]) && fields["count"] >= 0 && typeof fields["lastHitAt"] === "string" && fields["lastHitAt"].trim().length > 0 && (fields["origin"] === "program" || fields["origin"] === "hand");
|
|
237454
|
+
})) throw new Error("Mistake register has an invalid v1 schema.");
|
|
237455
|
+
}
|
|
237456
|
+
function registerError(error, operation) {
|
|
237457
|
+
if (error instanceof Error && error.message.startsWith("Mistake register ")) return error;
|
|
237458
|
+
const code = typeof error === "object" && error !== null ? error.code : void 0;
|
|
237459
|
+
const suffix = typeof code === "string" && /^[A-Z0-9_]+$/u.test(code) ? ` (${code})` : "";
|
|
237460
|
+
return /* @__PURE__ */ new Error(`Mistake register ${operation} failed${suffix}.`);
|
|
237151
237461
|
}
|
|
237152
237462
|
/**
|
|
237153
237463
|
* Findet einen Register-Eintrag anhand des Titels (Fingerabdruck).
|
|
@@ -239937,6 +240247,7 @@ var require_turn_tool_performance_policy = /* @__PURE__ */ __commonJSMin(((expor
|
|
|
239937
240247
|
const DEFERRED_TOOL_LOADER_NAME = "ToolSearch";
|
|
239938
240248
|
const MAX_PERSISTENT_DEFERRED_TOOLS = 12;
|
|
239939
240249
|
const MAX_TOOL_SEARCH_QUERY_CHARS = 1e3;
|
|
240250
|
+
const MAX_TOOL_CATALOG_RESULT_BYTES = 4096;
|
|
239940
240251
|
const MAX_AUTO_RANKED_TOOLS = 6;
|
|
239941
240252
|
const deferredToolLoaders = /* @__PURE__ */ new WeakSet();
|
|
239942
240253
|
const TOOL_RANK_EMBEDDED_CONTENT_RE = /<(attached_documents?|attachment_content|document_content|file_content)\b[^>]*>[\s\S]*?<\/\1>/giu;
|
|
@@ -240181,6 +240492,27 @@ var require_turn_tool_performance_policy = /* @__PURE__ */ __commonJSMin(((expor
|
|
|
240181
240492
|
for (const leaf of leaves) leafCounts.set(leaf, (leafCounts.get(leaf) || 0) + 1);
|
|
240182
240493
|
return names.map((name, index) => leafCounts.get(leaves[index]) === 1 ? leaves[index] : name).sort((left, right) => left.localeCompare(right));
|
|
240183
240494
|
}
|
|
240495
|
+
function boundedDeferredToolCatalog(tools, filter) {
|
|
240496
|
+
const needle = filter.toLowerCase();
|
|
240497
|
+
const matched = deferredToolCatalog(tools).filter((name) => name.toLowerCase().includes(needle));
|
|
240498
|
+
const names = [];
|
|
240499
|
+
let bytes = Buffer.byteLength(JSON.stringify({
|
|
240500
|
+
names,
|
|
240501
|
+
total: matched.length,
|
|
240502
|
+
truncated: false
|
|
240503
|
+
}));
|
|
240504
|
+
for (const name of matched) {
|
|
240505
|
+
const nextBytes = Buffer.byteLength(JSON.stringify(name)) + (names.length > 0 ? 1 : 0);
|
|
240506
|
+
if (bytes + nextBytes > MAX_TOOL_CATALOG_RESULT_BYTES) break;
|
|
240507
|
+
names.push(name);
|
|
240508
|
+
bytes += nextBytes;
|
|
240509
|
+
}
|
|
240510
|
+
return JSON.stringify({
|
|
240511
|
+
names,
|
|
240512
|
+
total: matched.length,
|
|
240513
|
+
truncated: names.length < matched.length
|
|
240514
|
+
});
|
|
240515
|
+
}
|
|
240184
240516
|
function normalizeDeferredToolQuery(value) {
|
|
240185
240517
|
const query = String(value ?? "").trim();
|
|
240186
240518
|
if (query.length <= MAX_TOOL_SEARCH_QUERY_CHARS) return query;
|
|
@@ -240255,14 +240587,14 @@ var require_turn_tool_performance_policy = /* @__PURE__ */ __commonJSMin(((expor
|
|
|
240255
240587
|
function rankingTokens(value) {
|
|
240256
240588
|
return [...new Set(String(value || "").normalize("NFKC").toLowerCase().match(/[\p{L}\p{N}]{3,}/gu) || [])].filter((token) => !TOOL_RANK_STOP_WORDS.has(token));
|
|
240257
240589
|
}
|
|
240258
|
-
function toolRankingDocument(tool) {
|
|
240590
|
+
function toolRankingDocument(tool, trustedToolNames) {
|
|
240259
240591
|
const name = String(tool?.name || "");
|
|
240260
240592
|
const leaf = name.split(/__|:/).at(-1) || name;
|
|
240261
240593
|
const splitToolName = (value) => String(value || "").replace(/([a-z0-9])([A-Z])/g, "$1 $2").replaceAll("_", " ");
|
|
240262
240594
|
const nameTokens = rankingTokens(`${splitToolName(name)} ${splitToolName(leaf)}`);
|
|
240263
240595
|
const descriptionTokens = rankingTokens(tool?.description);
|
|
240264
240596
|
const parameterText = [];
|
|
240265
|
-
const properties = tool?.parameters?.properties;
|
|
240597
|
+
const properties = /^mcp__/iu.test(name) && !trustedToolNames?.has(name) ? void 0 : tool?.parameters?.properties;
|
|
240266
240598
|
if (properties && typeof properties === "object") for (const [parameterName, definition] of Object.entries(properties)) parameterText.push(parameterName, definition?.description || "");
|
|
240267
240599
|
const exampleText = Array.isArray(tool?.examples) ? tool.examples.map((example) => example?.prompt || "").join(" ") : "";
|
|
240268
240600
|
return {
|
|
@@ -240294,7 +240626,7 @@ var require_turn_tool_performance_policy = /* @__PURE__ */ __commonJSMin(((expor
|
|
|
240294
240626
|
const queryTokens = [...new Set(rankingIntentTexts(value).flatMap(rankingTokens))];
|
|
240295
240627
|
if (queryTokens.length === 0) return /* @__PURE__ */ new Set();
|
|
240296
240628
|
const ranked = (Array.isArray(tools) ? tools : []).map((tool) => {
|
|
240297
|
-
const document = toolRankingDocument(tool);
|
|
240629
|
+
const document = toolRankingDocument(tool, options.trustedToolNames);
|
|
240298
240630
|
if (!document.name) return null;
|
|
240299
240631
|
let score = 0;
|
|
240300
240632
|
let matchedTokens = 0;
|
|
@@ -240402,8 +240734,8 @@ var require_turn_tool_performance_policy = /* @__PURE__ */ __commonJSMin(((expor
|
|
|
240402
240734
|
name: loaderName,
|
|
240403
240735
|
description: [
|
|
240404
240736
|
`Search ${deferredCount} deferred ${deferredCount === 1 ? "tool schema" : "tool schemas"} without loading all definitions.`,
|
|
240405
|
-
"Use select:leaf_name for one known tool, plain keywords to search,
|
|
240406
|
-
`Loaded tools are available in the next step;
|
|
240737
|
+
"Use select:leaf_name for one known tool, plain keywords to search, +word to require a name word, or catalog:fragment to list matching names.",
|
|
240738
|
+
`Loaded tools are available in the next step; up to ${MAX_PERSISTENT_DEFERRED_TOOLS} recently selected schemas remain loaded when the context budget allows.`
|
|
240407
240739
|
].join("\n"),
|
|
240408
240740
|
parameters: {
|
|
240409
240741
|
type: "object",
|
|
@@ -240420,7 +240752,12 @@ var require_turn_tool_performance_policy = /* @__PURE__ */ __commonJSMin(((expor
|
|
|
240420
240752
|
return {
|
|
240421
240753
|
description: query ? `Searching tool schemas for ${query}` : "Searching tool schemas",
|
|
240422
240754
|
approvalRule: loaderName,
|
|
240423
|
-
execute: async () => {
|
|
240755
|
+
execute: async (context) => {
|
|
240756
|
+
context?.signal?.throwIfAborted();
|
|
240757
|
+
if (query.toLowerCase().startsWith("catalog:")) return {
|
|
240758
|
+
isError: false,
|
|
240759
|
+
output: boundedDeferredToolCatalog([...available.values()], query.slice(8).trim())
|
|
240760
|
+
};
|
|
240424
240761
|
let matches = searchDeferredTools([...available.values()], query);
|
|
240425
240762
|
let relatedFallback = false;
|
|
240426
240763
|
if (matches.length === 0) {
|
|
@@ -252407,7 +252744,7 @@ var init_modelCatalog$2 = __esmMin((() => {
|
|
|
252407
252744
|
function isVolatileEventType(type) {
|
|
252408
252745
|
return volatileEventTypeSet.has(type);
|
|
252409
252746
|
}
|
|
252410
|
-
var MCP_OAUTH_AUTHORIZATION_URL_TOOL_UPDATE, tokenUsageSchema, finishReasonSchema, usageStatusSchema, permissionModeSchema, skillSourceSchema, userPromptOriginSchema, skillActivationOriginSchema, pluginCommandOriginSchema, injectionOriginSchema, shellCommandOriginSchema, compactionSummaryOriginSchema, systemTriggerOriginSchema, agentCoreBackgroundTaskStatusSchema, backgroundTaskOriginSchema, cronJobOriginSchema, cronMissedOriginSchema, hookResultOriginSchema, retryOriginSchema, promptOriginSchema, goalStatusSchema, goalActorSchema, goalBudgetReportSchema, goalSnapshotSchema, goalChangeStatsSchema, goalChangeKindSchema, goalChangeSchema, blunErrorCodeSchema, blunErrorPayloadSchema, backgroundTaskInfoBaseSchema, processBackgroundTaskInfoSchema, agentBackgroundTaskInfoSchema, questionBackgroundTaskInfoSchema, backgroundTaskInfoSchema, compactionResultSchema, toolUpdateSchema, turnEndReasonSchema, agentStatusUpdatedEventSchema, sessionMetaUpdatedEventSchema, sessionCreatedEventSchema, workspaceCreatedEventSchema, workspaceUpdatedEventSchema, workspaceDeletedEventSchema, sessionStatusChangedEventSchema, modelCatalogChangedEventSchema, goalUpdatedEventSchema, skillActivatedEventSchema, pluginCommandActivatedEventSchema, errorEventSchema, warningEventSchema, turnStartedEventSchema, turnEndedEventSchema, turnStepStartedEventSchema, turnStepCompletedEventSchema, turnStepRetryingEventSchema, turnStepInterruptedEventSchema, assistantDeltaEventSchema, hookResultEventSchema, thinkingDeltaEventSchema, toolCallDeltaEventSchema, toolCallStartedEventSchema, toolProgressEventSchema, shellOutputEventSchema, shellStartedEventSchema, toolResultEventSchema, subagentSpawnedEventSchema, subagentStartedEventSchema, subagentSuspendedEventSchema, subagentCompletedEventSchema, subagentFailedEventSchema, compactionStartedEventSchema, compactionBlockedEventSchema, compactionCancelledEventSchema, compactionProgressEventSchema, compactionCompletedEventSchema, backgroundTaskStartedEventSchema, backgroundTaskTerminatedEventSchema, cronFiredEventSchema, cronRunUpdatedEventSchema, promptSubmittedEventSchema, toolListUpdatedReasonSchema, toolListUpdatedEventSchema, mcpServerStatusPayloadSchema, mcpServerStatusEventSchema, mediaDroppedEventSchema, agentEventSchema, eventSchema, VOLATILE_EVENT_TYPES, volatileEventTypeSet;
|
|
252747
|
+
var MCP_OAUTH_AUTHORIZATION_URL_TOOL_UPDATE, tokenUsageSchema, finishReasonSchema, usageStatusSchema, permissionModeSchema, skillSourceSchema, userPromptOriginSchema, skillActivationOriginSchema, pluginCommandOriginSchema, injectionOriginSchema, shellCommandOriginSchema, compactionSummaryOriginSchema, systemTriggerOriginSchema, agentCoreBackgroundTaskStatusSchema, backgroundTaskOriginSchema, cronJobOriginSchema, cronMissedOriginSchema, hookResultOriginSchema, retryOriginSchema, promptOriginSchema, goalStatusSchema, goalActorSchema, goalBudgetReportSchema, goalSnapshotSchema, goalChangeStatsSchema, goalChangeKindSchema, goalChangeSchema, blunErrorCodeSchema, blunErrorPayloadSchema, backgroundTaskInfoBaseSchema, processBackgroundTaskInfoSchema, agentBackgroundTaskInfoSchema, questionBackgroundTaskInfoSchema, backgroundTaskInfoSchema, compactionResultSchema, toolUpdateSchema, turnEndReasonSchema, contextChangedEventSchema, agentStatusUpdatedEventSchema, sessionMetaUpdatedEventSchema, sessionCreatedEventSchema, workspaceCreatedEventSchema, workspaceUpdatedEventSchema, workspaceDeletedEventSchema, sessionStatusChangedEventSchema, modelCatalogChangedEventSchema, goalUpdatedEventSchema, skillActivatedEventSchema, pluginCommandActivatedEventSchema, errorEventSchema, warningEventSchema, turnStartedEventSchema, turnEndedEventSchema, turnStepStartedEventSchema, turnStepCompletedEventSchema, turnStepRetryingEventSchema, turnStepInterruptedEventSchema, assistantDeltaEventSchema, hookResultEventSchema, thinkingDeltaEventSchema, toolCallDeltaEventSchema, toolCallStartedEventSchema, toolProgressEventSchema, shellOutputEventSchema, shellStartedEventSchema, toolResultEventSchema, subagentSpawnedEventSchema, subagentStartedEventSchema, subagentSuspendedEventSchema, subagentCompletedEventSchema, subagentFailedEventSchema, compactionStartedEventSchema, compactionBlockedEventSchema, compactionCancelledEventSchema, compactionProgressEventSchema, compactionCompletedEventSchema, backgroundTaskStartedEventSchema, backgroundTaskTerminatedEventSchema, cronFiredEventSchema, cronRunUpdatedEventSchema, promptSubmittedEventSchema, toolListUpdatedReasonSchema, toolListUpdatedEventSchema, mcpServerStatusPayloadSchema, mcpServerStatusEventSchema, mediaDroppedEventSchema, agentEventSchema, eventSchema, VOLATILE_EVENT_TYPES, volatileEventTypeSet;
|
|
252411
252748
|
var init_events$1 = __esmMin((() => {
|
|
252412
252749
|
init_zod$1();
|
|
252413
252750
|
init_display();
|
|
@@ -252583,7 +252920,11 @@ var init_events$1 = __esmMin((() => {
|
|
|
252583
252920
|
tokensUsed: number$1(),
|
|
252584
252921
|
wallClockMs: number$1()
|
|
252585
252922
|
});
|
|
252586
|
-
goalChangeKindSchema = _enum([
|
|
252923
|
+
goalChangeKindSchema = _enum([
|
|
252924
|
+
"lifecycle",
|
|
252925
|
+
"completion",
|
|
252926
|
+
"edited"
|
|
252927
|
+
]);
|
|
252587
252928
|
goalChangeSchema = object$1({
|
|
252588
252929
|
kind: goalChangeKindSchema,
|
|
252589
252930
|
status: goalStatusSchema.optional(),
|
|
@@ -252740,6 +253081,12 @@ var init_events$1 = __esmMin((() => {
|
|
|
252740
253081
|
"failed",
|
|
252741
253082
|
"filtered"
|
|
252742
253083
|
]);
|
|
253084
|
+
contextChangedEventSchema = object$1({
|
|
253085
|
+
type: literal("context.changed"),
|
|
253086
|
+
generation: string().uuid(),
|
|
253087
|
+
revision: number$1().int().positive().max(Number.MAX_SAFE_INTEGER),
|
|
253088
|
+
reason: _enum(["clear", "undo"])
|
|
253089
|
+
});
|
|
252743
253090
|
agentStatusUpdatedEventSchema = object$1({
|
|
252744
253091
|
type: literal("agent.status.updated"),
|
|
252745
253092
|
model: string().optional(),
|
|
@@ -253076,6 +253423,7 @@ var init_events$1 = __esmMin((() => {
|
|
|
253076
253423
|
errorEventSchema,
|
|
253077
253424
|
warningEventSchema,
|
|
253078
253425
|
agentStatusUpdatedEventSchema,
|
|
253426
|
+
contextChangedEventSchema,
|
|
253079
253427
|
sessionMetaUpdatedEventSchema,
|
|
253080
253428
|
sessionCreatedEventSchema,
|
|
253081
253429
|
workspaceCreatedEventSchema,
|
|
@@ -266315,9 +266663,16 @@ var init_tool_dedup = __esmMin((() => {
|
|
|
266315
266663
|
}));
|
|
266316
266664
|
//#endregion
|
|
266317
266665
|
//#region ../../packages/agent-core/src/agent/turn/tool-result-budget.ts
|
|
266666
|
+
function toolResultMaxChars(maxContextTokens) {
|
|
266667
|
+
if (maxContextTokens === void 0 || !Number.isFinite(maxContextTokens) || maxContextTokens <= 0) return TOOL_RESULT_MAX_CHARS;
|
|
266668
|
+
if (maxContextTokens < 1e5) return 16e3;
|
|
266669
|
+
if (maxContextTokens < 2e5) return 32e3;
|
|
266670
|
+
return TOOL_RESULT_MAX_CHARS;
|
|
266671
|
+
}
|
|
266318
266672
|
async function budgetToolResultForModel(options) {
|
|
266319
266673
|
const text = persistableToolResultText(options.result.output);
|
|
266320
|
-
|
|
266674
|
+
const maxChars = toolResultMaxChars(options.maxContextTokens);
|
|
266675
|
+
if (text === void 0 || text.length <= maxChars) return options.result;
|
|
266321
266676
|
if (options.result.truncated === true) return options.result;
|
|
266322
266677
|
if (options.homedir === void 0) return options.result;
|
|
266323
266678
|
if (text.includes("\0") || Buffer.from(text, "utf8").toString("utf8") !== text || text.split("\n").some((line) => line.length > 2e3)) return options.result;
|
|
@@ -266328,7 +266683,7 @@ async function budgetToolResultForModel(options) {
|
|
|
266328
266683
|
toolCallId: options.toolCallId
|
|
266329
266684
|
}, text);
|
|
266330
266685
|
if (outputPath === void 0) return options.result;
|
|
266331
|
-
const output = renderPersistedToolResult(options.toolName, options.toolCallId, text, outputPath);
|
|
266686
|
+
const output = renderPersistedToolResult(options.toolName, options.toolCallId, text, outputPath, maxChars);
|
|
266332
266687
|
return options.result.isError === true ? {
|
|
266333
266688
|
...options.result,
|
|
266334
266689
|
output,
|
|
@@ -266360,9 +266715,9 @@ async function saveToolResult(options, text) {
|
|
|
266360
266715
|
return;
|
|
266361
266716
|
}
|
|
266362
266717
|
}
|
|
266363
|
-
function renderPersistedToolResult(toolName, toolCallId, text, outputPath) {
|
|
266718
|
+
function renderPersistedToolResult(toolName, toolCallId, text, outputPath, maxChars) {
|
|
266364
266719
|
const lines = [
|
|
266365
|
-
`Tool output exceeded ${String(
|
|
266720
|
+
`Tool output exceeded ${String(maxChars)} characters; showing a preview only.`,
|
|
266366
266721
|
`tool_name: ${toolName}`,
|
|
266367
266722
|
`tool_call_id: ${toolCallId}`,
|
|
266368
266723
|
`output_size_chars: ${String(text.length)}`,
|
|
@@ -268320,14 +268675,27 @@ function blunToolsForOrigin(tools, origin) {
|
|
|
268320
268675
|
* the ordinary permission pipeline.
|
|
268321
268676
|
*/
|
|
268322
268677
|
function blunSelectTurnTools(tools, maxContextTokens, loadedToolNames = /* @__PURE__ */ new Set(), requiredToolNames = /* @__PURE__ */ new Set(), selected = []) {
|
|
268323
|
-
|
|
268678
|
+
const schemaBudget = (0, import_turn_tool_performance_policy.toolSchemaBudgetTokens)(maxContextTokens);
|
|
268679
|
+
if (estimateTokensForTools(tools, schemaBudget) <= schemaBudget || tools.some(import_turn_tool_performance_policy.isDeferredToolLoader)) {
|
|
268324
268680
|
selected.splice(0, selected.length, ...tools);
|
|
268325
268681
|
return selected;
|
|
268326
268682
|
}
|
|
268327
|
-
|
|
268328
|
-
const
|
|
268329
|
-
const
|
|
268330
|
-
|
|
268683
|
+
const priorLoaderIndex = selected.findIndex(import_turn_tool_performance_policy.isDeferredToolLoader);
|
|
268684
|
+
const justLoaded = new Set(priorLoaderIndex < 0 ? [] : selected.slice(priorLoaderIndex + 1).filter((tool) => loadedToolNames.has(tool.name)).map((tool) => tool.name));
|
|
268685
|
+
const remembered = new Set(loadedToolNames);
|
|
268686
|
+
const choose = () => {
|
|
268687
|
+
selected.splice(0, selected.length, ...tools.filter((tool) => BLUN_LEAN_TOOL_NAMES.has(tool.name) || BLUN_LEAN_KEEP_RE.test(tool.name) || BLUN_LANGUAGE_REVIEW_TOOL_NAMES.has(tool.name) || remembered.has(tool.name) || requiredToolNames.has(tool.name)));
|
|
268688
|
+
const names = new Set(selected.map((tool) => tool.name));
|
|
268689
|
+
const deferred = tools.filter((tool) => !names.has(tool.name));
|
|
268690
|
+
if (deferred.length > 0) selected.push((0, import_turn_tool_performance_policy.createDeferredToolLoader)(selected, deferred, loadedToolNames));
|
|
268691
|
+
};
|
|
268692
|
+
choose();
|
|
268693
|
+
for (const name of loadedToolNames) {
|
|
268694
|
+
if (estimateTokensForTools(selected, schemaBudget) <= schemaBudget) break;
|
|
268695
|
+
if (justLoaded.has(name)) continue;
|
|
268696
|
+
if (!remembered.delete(name)) continue;
|
|
268697
|
+
choose();
|
|
268698
|
+
}
|
|
268331
268699
|
return selected;
|
|
268332
268700
|
}
|
|
268333
268701
|
function goalContinuationOrigin(origin) {
|
|
@@ -269356,10 +269724,12 @@ var init_turn = __esmMin((() => {
|
|
|
269356
269724
|
taskToolsNeeded ||= blunTurnNeedsTools(intent, origin) || blunTurnHasAttachment(toolInput);
|
|
269357
269725
|
const required = (0, import_turn_tool_performance_policy.mediaToolNamesForTurnText)(blunExtractText(toolInput));
|
|
269358
269726
|
if (taskToolsNeeded) {
|
|
269359
|
-
|
|
269360
|
-
|
|
269727
|
+
const maxContextTokens = this.agent.fullCompaction.getEffectiveMaxContextTokens();
|
|
269728
|
+
blunSelectTurnTools(eligibleTools, maxContextTokens, this.loadedToolNames, required, selectedTools);
|
|
269729
|
+
const trustedToolNames = new Set(eligibleTools.filter((tool) => this.agent.tools.isUserTool(tool)).map((tool) => tool.name));
|
|
269730
|
+
for (const name of (0, import_turn_tool_performance_policy.rankedToolNamesForTurnText)(eligibleTools, blunExtractText(intent), { trustedToolNames })) {
|
|
269361
269731
|
const tool = eligibleTools.find((candidate) => candidate.name === name);
|
|
269362
|
-
if (tool !== void 0 && !selectedTools.some((candidate) => candidate.name === name) && estimateTokensForTools([...selectedTools, tool]) <= (0, import_turn_tool_performance_policy.toolSchemaBudgetTokens)(
|
|
269732
|
+
if (tool !== void 0 && !selectedTools.some((candidate) => candidate.name === name) && estimateTokensForTools([...selectedTools, tool]) <= (0, import_turn_tool_performance_policy.toolSchemaBudgetTokens)(maxContextTokens)) selectedTools.push(tool);
|
|
269363
269733
|
}
|
|
269364
269734
|
} else selectedTools.splice(0, selectedTools.length, ...eligibleTools.filter((tool) => BLUN_LANGUAGE_REVIEW_TOOL_NAMES.has(tool.name) || BLUN_TELEGRAM_OUTBOUND_TOOL_RE.test(tool.name)));
|
|
269365
269735
|
recordPreRequestPhase("tool-selection", selectionStartedAt);
|
|
@@ -269500,6 +269870,7 @@ var init_turn = __esmMin((() => {
|
|
|
269500
269870
|
});
|
|
269501
269871
|
return budgetToolResultForModel({
|
|
269502
269872
|
homedir: this.agent.homedir,
|
|
269873
|
+
maxContextTokens: this.agent.fullCompaction.getEffectiveMaxContextTokens(),
|
|
269503
269874
|
toolName: ctx.toolCall.name,
|
|
269504
269875
|
toolCallId: ctx.toolCall.id,
|
|
269505
269876
|
result: finalResult
|
|
@@ -270210,10 +270581,10 @@ var init_bash = __esmMin((() => {
|
|
|
270210
270581
|
},
|
|
270211
270582
|
approvalRule: literalRulePattern(this.name, args.command),
|
|
270212
270583
|
matchesRule: (ruleArgs) => matchesGlobRuleSubject(ruleArgs, args.command),
|
|
270213
|
-
execute: ({ signal, onUpdate, onForegroundTaskStart }) => this.execution(args, signal, onUpdate, onForegroundTaskStart)
|
|
270584
|
+
execute: ({ signal, onUpdate, onForegroundTaskStart, executionOrigin }) => this.execution(args, signal, onUpdate, onForegroundTaskStart, executionOrigin)
|
|
270214
270585
|
};
|
|
270215
270586
|
}
|
|
270216
|
-
spawn(effectiveCwd, command) {
|
|
270587
|
+
spawn(effectiveCwd, command, executionOrigin) {
|
|
270217
270588
|
const shellCwd = this.isWindowsBash ? windowsPathToPosixPath(effectiveCwd) : effectiveCwd;
|
|
270218
270589
|
const shellArgs = [
|
|
270219
270590
|
this.kaos.osEnv.shellPath,
|
|
@@ -270230,9 +270601,11 @@ var init_bash = __esmMin((() => {
|
|
|
270230
270601
|
...process.env,
|
|
270231
270602
|
...noninteractiveEnv
|
|
270232
270603
|
};
|
|
270604
|
+
delete mergedEnv["BLUN_SHELL"];
|
|
270605
|
+
if (executionOrigin === "operator_shell") mergedEnv["BLUN_SHELL"] = "operator-local";
|
|
270233
270606
|
return this.kaos.execWithEnv(shellArgs, mergedEnv);
|
|
270234
270607
|
}
|
|
270235
|
-
async execution(args, signal, onUpdate, onForegroundTaskStart) {
|
|
270608
|
+
async execution(args, signal, onUpdate, onForegroundTaskStart, executionOrigin) {
|
|
270236
270609
|
const validationError = this.validateRunRequest(args, signal);
|
|
270237
270610
|
if (validationError !== void 0) return validationError;
|
|
270238
270611
|
const startsInBackground = args.run_in_background === true;
|
|
@@ -270244,7 +270617,7 @@ var init_bash = __esmMin((() => {
|
|
|
270244
270617
|
const builder = new ToolResultBuilder();
|
|
270245
270618
|
let proc;
|
|
270246
270619
|
try {
|
|
270247
|
-
proc = await this.spawn(effectiveCwd, command);
|
|
270620
|
+
proc = await this.spawn(effectiveCwd, command, executionOrigin);
|
|
270248
270621
|
} catch (error) {
|
|
270249
270622
|
return {
|
|
270250
270623
|
isError: true,
|
|
@@ -270579,7 +270952,7 @@ var init_web_search = __esmMin((() => {
|
|
|
270579
270952
|
//#region ../../packages/agent-core/src/tools/builtin/search/codebase-search.md?raw
|
|
270580
270953
|
var codebase_search_default;
|
|
270581
270954
|
var init_codebase_search$1 = __esmMin((() => {
|
|
270582
|
-
codebase_search_default = "Find code by **meaning**, not by keywords.\n\nThis tool runs a semantic search over the codebase index. It understands what a file or function *does*, not just what words appear in it. Use it when you are looking for *where* something is handled, *which file* implements a concept, or *how* a particular concern is addressed — even when the exact term never appears in the source.\n\n**When to use this tool:**\n- \"Where is keyboard input handled?\" — finds the handler even if the word \"keyboard\" never appears.\n- \"Which file manages the retry logic for API calls?\"\n- \"How does the app decide which model to route a message to?\"\n- \"Find the code that handles user authentication flow.\"\n- Any question where you want to locate code by its *purpose* or *behavior*.\n\n**When NOT to use this tool — use a different one instead:**\n- Exact string matches, regex patterns, or specific identifiers → `Grep`\n- Finding files by name, extension, or path glob → `Glob`\n- Reading a known file path → `Read`\n\n**Parameters:**\n- `query` (required): A natural-language question, concept, or phrase describing what the code does. Examples: `\"keyboard event handling\"`, `\"retry with exponential backoff\"`, `\"where chat messages are routed to the model\"`.\n- `top` (optional, default 5): Maximum number of results to return.\n\n**Output:**\nEach result includes a file path and a relevance
|
|
270955
|
+
codebase_search_default = "Find code by **meaning**, not by keywords.\n\nThis tool runs a semantic search over the codebase index. It understands what a file or function *does*, not just what words appear in it. Use it when you are looking for *where* something is handled, *which file* implements a concept, or *how* a particular concern is addressed — even when the exact term never appears in the source.\n\n**When to use this tool:**\n- \"Where is keyboard input handled?\" — finds the handler even if the word \"keyboard\" never appears.\n- \"Which file manages the retry logic for API calls?\"\n- \"How does the app decide which model to route a message to?\"\n- \"Find the code that handles user authentication flow.\"\n- Any question where you want to locate code by its *purpose* or *behavior*.\n\n**When NOT to use this tool — use a different one instead:**\n- Exact string matches, regex patterns, or specific identifiers → `Grep`\n- Finding files by name, extension, or path glob → `Glob`\n- Reading a known file path → `Read`\n\n**Parameters:**\n- `query` (required): A natural-language question, concept, or phrase describing what the code does. Examples: `\"keyboard event handling\"`, `\"retry with exponential backoff\"`, `\"where chat messages are routed to the model\"`.\n- `top` (optional, default 5, maximum 100): Maximum number of results to return.\n\n**Output:**\nEach result includes a file path and a relevance score, plus the index model and revision. The index is rebuilt incrementally; if a file was recently added it may not appear until the next index update. Always verify the finding by reading the file before relying on it.\n";
|
|
270583
270956
|
}));
|
|
270584
270957
|
//#endregion
|
|
270585
270958
|
//#region ../../packages/agent-core/src/tools/builtin/search/codebase-search.ts
|
|
@@ -270587,7 +270960,7 @@ var init_codebase_search$1 = __esmMin((() => {
|
|
|
270587
270960
|
* CodebaseSearchTool — semantic code search via the codebase-index.
|
|
270588
270961
|
*
|
|
270589
270962
|
* Shells out to `python codebase_index.py query <repo> "<frage>" --top N`
|
|
270590
|
-
* through
|
|
270963
|
+
* through asynchronous execFile. The script lives at
|
|
270591
270964
|
* `packages/codebase-index/codebase_index.py` relative to the workspace root.
|
|
270592
270965
|
*
|
|
270593
270966
|
* Unlike Grep (keyword/regex) or Glob (file-name patterns), this tool finds
|
|
@@ -270611,18 +270984,20 @@ function resolveScriptPath() {
|
|
|
270611
270984
|
}
|
|
270612
270985
|
return "";
|
|
270613
270986
|
}
|
|
270614
|
-
var CodebaseSearchInputSchema, SCRIPT_TIMEOUT_MS, CodebaseSearchTool;
|
|
270987
|
+
var MAX_SEARCH_RESULTS, CodebaseSearchInputSchema, SCRIPT_TIMEOUT_MS, SCRIPT_MAX_BUFFER, CodebaseSearchTool;
|
|
270615
270988
|
var init_codebase_search = __esmMin((() => {
|
|
270616
270989
|
init_zod$1();
|
|
270617
270990
|
init_rule_match();
|
|
270618
270991
|
init_input_schema();
|
|
270619
270992
|
init_result_builder();
|
|
270620
270993
|
init_codebase_search$1();
|
|
270994
|
+
MAX_SEARCH_RESULTS = 100;
|
|
270621
270995
|
CodebaseSearchInputSchema = object$1({
|
|
270622
270996
|
query: string().min(1, "Query cannot be empty.").describe("A natural-language question or concept describing what the code does. Examples: \"keyboard event handling\", \"retry with exponential backoff\", \"where chat messages are routed to the model\"."),
|
|
270623
|
-
top: number$1().int().positive().default(5).describe(
|
|
270997
|
+
top: number$1().int().positive().max(MAX_SEARCH_RESULTS).default(5).describe(`Maximum number of results to return (1-${String(MAX_SEARCH_RESULTS)}). Defaults to 5.`)
|
|
270624
270998
|
});
|
|
270625
270999
|
SCRIPT_TIMEOUT_MS = 6e4;
|
|
271000
|
+
SCRIPT_MAX_BUFFER = 1024 * 1024;
|
|
270626
271001
|
CodebaseSearchTool = class {
|
|
270627
271002
|
cwd;
|
|
270628
271003
|
name = "CodebaseSearch";
|
|
@@ -270645,45 +271020,72 @@ var init_codebase_search = __esmMin((() => {
|
|
|
270645
271020
|
},
|
|
270646
271021
|
approvalRule: literalRulePattern(this.name, args.query),
|
|
270647
271022
|
matchesRule: (ruleArgs) => matchesGlobRuleSubject(ruleArgs, args.query),
|
|
270648
|
-
execute: () =>
|
|
271023
|
+
execute: async (context) => {
|
|
271024
|
+
context.signal.throwIfAborted();
|
|
271025
|
+
return this.execution(args, context.signal);
|
|
271026
|
+
}
|
|
270649
271027
|
};
|
|
270650
271028
|
}
|
|
270651
|
-
execution(args) {
|
|
271029
|
+
async execution(args, signal) {
|
|
270652
271030
|
const builder = new ToolResultBuilder();
|
|
270653
|
-
if (
|
|
271031
|
+
if (!Number.isSafeInteger(args.top) || args.top < 1 || args.top > MAX_SEARCH_RESULTS) return builder.error(`Codebase search top must be between 1 and ${String(MAX_SEARCH_RESULTS)}.`);
|
|
271032
|
+
if (this.scriptPath.length === 0) return builder.error("Could not locate codebase_index.py. Set CODEBASE_INDEX_SCRIPT to its absolute path.");
|
|
270654
271033
|
try {
|
|
270655
|
-
const result =
|
|
270656
|
-
|
|
270657
|
-
|
|
270658
|
-
|
|
270659
|
-
|
|
270660
|
-
|
|
270661
|
-
|
|
270662
|
-
|
|
270663
|
-
|
|
270664
|
-
|
|
270665
|
-
|
|
270666
|
-
|
|
270667
|
-
|
|
270668
|
-
|
|
271034
|
+
const result = await new Promise((resolve) => {
|
|
271035
|
+
let closed = false;
|
|
271036
|
+
let output;
|
|
271037
|
+
const finish = () => {
|
|
271038
|
+
if (closed && output !== void 0) resolve(output);
|
|
271039
|
+
};
|
|
271040
|
+
execFile("python", [
|
|
271041
|
+
this.scriptPath,
|
|
271042
|
+
"query",
|
|
271043
|
+
this.cwd,
|
|
271044
|
+
args.query,
|
|
271045
|
+
"--top",
|
|
271046
|
+
String(args.top),
|
|
271047
|
+
"--model",
|
|
271048
|
+
"auto"
|
|
271049
|
+
], {
|
|
271050
|
+
cwd: this.cwd,
|
|
271051
|
+
timeout: SCRIPT_TIMEOUT_MS,
|
|
271052
|
+
encoding: "utf-8",
|
|
271053
|
+
windowsHide: true,
|
|
271054
|
+
shell: false,
|
|
271055
|
+
maxBuffer: SCRIPT_MAX_BUFFER,
|
|
271056
|
+
signal
|
|
271057
|
+
}, (error, stdout, stderr) => {
|
|
271058
|
+
output = {
|
|
271059
|
+
error,
|
|
271060
|
+
stdout,
|
|
271061
|
+
stderr
|
|
271062
|
+
};
|
|
271063
|
+
finish();
|
|
271064
|
+
}).once("close", () => {
|
|
271065
|
+
closed = true;
|
|
271066
|
+
finish();
|
|
271067
|
+
});
|
|
270669
271068
|
});
|
|
270670
|
-
|
|
271069
|
+
signal.throwIfAborted();
|
|
271070
|
+
if (result.error !== null && typeof result.error.code !== "number") {
|
|
270671
271071
|
const msg = result.error instanceof Error ? result.error.message : String(result.error);
|
|
270672
|
-
|
|
271072
|
+
builder.write(result.stdout + result.stderr);
|
|
271073
|
+
return builder.error(`Failed to run codebase_index.py: ${msg}`);
|
|
270673
271074
|
}
|
|
270674
271075
|
const stdout = result.stdout ?? "";
|
|
270675
271076
|
const stderr = result.stderr ?? "";
|
|
270676
|
-
const exitCode = result.
|
|
271077
|
+
const exitCode = result.error?.code ?? 0;
|
|
270677
271078
|
if (exitCode !== 0) {
|
|
270678
271079
|
const combined = stderr.trim().length > 0 ? `${stdout}${stdout.length > 0 ? "\n" : ""}Error: ${stderr.trim()}` : stdout;
|
|
270679
271080
|
builder.write(combined.length > 0 ? combined : `codebase_index.py exited with code ${String(exitCode)}`);
|
|
270680
|
-
return
|
|
271081
|
+
return builder.error(`Codebase search failed with exit code ${String(exitCode)}.`);
|
|
270681
271082
|
}
|
|
270682
271083
|
builder.write(stdout.length > 0 ? stdout : "No results found.");
|
|
270683
|
-
return
|
|
271084
|
+
return builder.ok();
|
|
270684
271085
|
} catch (error) {
|
|
271086
|
+
signal.throwIfAborted();
|
|
270685
271087
|
const msg = error instanceof Error ? error.message : String(error);
|
|
270686
|
-
return
|
|
271088
|
+
return builder.error(`Codebase search error: ${msg}`);
|
|
270687
271089
|
}
|
|
270688
271090
|
}
|
|
270689
271091
|
};
|
|
@@ -272017,6 +272419,7 @@ var init_tool$1 = __esmMin((() => {
|
|
|
272017
272419
|
const result = await execution.execute({
|
|
272018
272420
|
turnId: "",
|
|
272019
272421
|
toolCallId: "shell-command",
|
|
272422
|
+
executionOrigin: "operator_shell",
|
|
272020
272423
|
signal: controller.signal,
|
|
272021
272424
|
onUpdate: (update) => {
|
|
272022
272425
|
if (update.kind === "stdout") stdout += update.text ?? "";
|
|
@@ -272105,6 +272508,9 @@ var init_tool$1 = __esmMin((() => {
|
|
|
272105
272508
|
hasUserTool(name) {
|
|
272106
272509
|
return this.userTools.has(name);
|
|
272107
272510
|
}
|
|
272511
|
+
isUserTool(tool) {
|
|
272512
|
+
return this.userTools.get(tool.name) === tool;
|
|
272513
|
+
}
|
|
272108
272514
|
inheritUserTools(parent) {
|
|
272109
272515
|
for (const tool of parent.userTools.values()) {
|
|
272110
272516
|
if (!parent.enabledTools.has(tool.name)) continue;
|
|
@@ -273718,7 +274124,7 @@ var init_agent = __esmMin((() => {
|
|
|
273718
274124
|
fitProfileInstructions(profile, context, tools = this.tools.loopTools, notify = false) {
|
|
273719
274125
|
if (context?.agentsMdText === void 0 || this.config.modelAlias === void 0) return context;
|
|
273720
274126
|
if (this.config.runtimeModel(this.config.modelAlias).provider.name !== "blun") return context;
|
|
273721
|
-
const
|
|
274127
|
+
const renderFixedPrompt = (candidate) => {
|
|
273722
274128
|
const rendered = profile.systemPrompt({
|
|
273723
274129
|
osEnv: this.kaos.osEnv,
|
|
273724
274130
|
now: this.systemPromptStartedAt,
|
|
@@ -273729,13 +274135,35 @@ var init_agent = __esmMin((() => {
|
|
|
273729
274135
|
additionalDirsInfo: candidate.additionalDirsInfo
|
|
273730
274136
|
});
|
|
273731
274137
|
const compact = this.skills?.registry === void 0 ? rendered : compactLegacyModelSkillListing(rendered, this.skills.registry);
|
|
273732
|
-
return
|
|
274138
|
+
return this.runtimeSystemPromptAppend.length === 0 ? compact : compact.length === 0 ? this.runtimeSystemPromptAppend : `${compact}\n\n${this.runtimeSystemPromptAppend}`;
|
|
274139
|
+
};
|
|
274140
|
+
const fitted = fitAgentsMdContext(context, 4e5, (candidate) => {
|
|
274141
|
+
return estimateBlunSerializedBodyBytes(renderFixedPrompt(candidate), tools, []) + 4096;
|
|
274142
|
+
});
|
|
274143
|
+
const describeFixedEstimate = () => {
|
|
274144
|
+
const systemPrompt = renderFixedPrompt(fitted.context);
|
|
274145
|
+
const envelopeBytes = estimateBlunSerializedBodyBytes("", [], []);
|
|
274146
|
+
const withoutToolsBytes = estimateBlunSerializedBodyBytes(systemPrompt, [], []);
|
|
274147
|
+
return {
|
|
274148
|
+
estimationStage: notify ? "request" : "profile",
|
|
274149
|
+
toolCount: tools.length,
|
|
274150
|
+
serializedPromptBytes: withoutToolsBytes - envelopeBytes,
|
|
274151
|
+
serializedToolsBytes: fitted.fixedRequestBytes - 4096 - withoutToolsBytes,
|
|
274152
|
+
envelopeBytes,
|
|
274153
|
+
reserveBytes: 4096,
|
|
274154
|
+
instructionBytes: fitted.context.agentsMdSources?.totalBytes ?? 0,
|
|
274155
|
+
runtimeAppendBytes: Buffer.byteLength(this.runtimeSystemPromptAppend, "utf8")
|
|
274156
|
+
};
|
|
274157
|
+
};
|
|
274158
|
+
if (!fitted.fits) this.log.warn("fixed BLUN request exceeds 400000 bytes without AGENTS.md", {
|
|
274159
|
+
fixedRequestBytes: fitted.fixedRequestBytes,
|
|
274160
|
+
...describeFixedEstimate()
|
|
273733
274161
|
});
|
|
273734
|
-
if (!fitted.fits) this.log.warn("fixed BLUN request exceeds 400000 bytes without AGENTS.md", { fixedRequestBytes: fitted.fixedRequestBytes });
|
|
273735
274162
|
else if (fitted.omittedBytes > 0) {
|
|
273736
274163
|
this.log.warn("AGENTS.md content shortened for BLUN request budget", {
|
|
273737
274164
|
omittedBytes: fitted.omittedBytes,
|
|
273738
|
-
fixedRequestBytes: fitted.fixedRequestBytes
|
|
274165
|
+
fixedRequestBytes: fitted.fixedRequestBytes,
|
|
274166
|
+
...describeFixedEstimate()
|
|
273739
274167
|
});
|
|
273740
274168
|
if (notify && !this.agentsMdRequestWarningShown) {
|
|
273741
274169
|
this.agentsMdRequestWarningShown = true;
|
|
@@ -273949,6 +274377,9 @@ var init_agent = __esmMin((() => {
|
|
|
273949
274377
|
},
|
|
273950
274378
|
startBtw: () => this.subagentHost.startBtw(),
|
|
273951
274379
|
createGoal: (payload) => this.goal.createGoal(payload),
|
|
274380
|
+
editGoal: (payload) => this.goal.editGoal(payload),
|
|
274381
|
+
blockGoal: (payload) => this.goal.blockGoal(payload),
|
|
274382
|
+
completeGoal: () => this.goal.completeGoal(),
|
|
273952
274383
|
getGoal: () => this.goal.getGoal(),
|
|
273953
274384
|
pauseGoal: () => this.goal.pauseGoal(),
|
|
273954
274385
|
resumeGoal: () => this.goal.resumeGoal(),
|
|
@@ -339272,6 +339703,15 @@ var init_rpc$1 = __esmMin((() => {
|
|
|
339272
339703
|
async createGoal({ agentId, ...payload }) {
|
|
339273
339704
|
return (await this.getAgent(agentId)).createGoal(payload);
|
|
339274
339705
|
}
|
|
339706
|
+
async editGoal({ agentId, ...payload }) {
|
|
339707
|
+
return (await this.getAgent(agentId)).editGoal(payload);
|
|
339708
|
+
}
|
|
339709
|
+
async blockGoal({ agentId, ...payload }) {
|
|
339710
|
+
return (await this.getAgent(agentId)).blockGoal(payload);
|
|
339711
|
+
}
|
|
339712
|
+
async completeGoal({ agentId }) {
|
|
339713
|
+
return (await this.getAgent(agentId)).completeGoal({});
|
|
339714
|
+
}
|
|
339275
339715
|
async getGoal({ agentId, ...payload }) {
|
|
339276
339716
|
return (await this.getAgent(agentId, true)).getGoal(payload);
|
|
339277
339717
|
}
|
|
@@ -340706,6 +341146,15 @@ var init_core_impl = __esmMin((() => {
|
|
|
340706
341146
|
getGoal({ sessionId, ...payload }) {
|
|
340707
341147
|
return Promise.resolve(this.sessionApi(sessionId).getGoal(payload));
|
|
340708
341148
|
}
|
|
341149
|
+
editGoal({ sessionId, ...payload }) {
|
|
341150
|
+
return Promise.resolve(this.sessionApi(sessionId).editGoal(payload));
|
|
341151
|
+
}
|
|
341152
|
+
blockGoal({ sessionId, ...payload }) {
|
|
341153
|
+
return Promise.resolve(this.sessionApi(sessionId).blockGoal(payload));
|
|
341154
|
+
}
|
|
341155
|
+
completeGoal({ sessionId, ...payload }) {
|
|
341156
|
+
return Promise.resolve(this.sessionApi(sessionId).completeGoal(payload));
|
|
341157
|
+
}
|
|
340709
341158
|
pauseGoal({ sessionId, ...payload }) {
|
|
340710
341159
|
return Promise.resolve(this.sessionApi(sessionId).pauseGoal(payload));
|
|
340711
341160
|
}
|
|
@@ -348319,7 +348768,10 @@ function reduceWireRecords(records) {
|
|
|
348319
348768
|
text: record.summary
|
|
348320
348769
|
}],
|
|
348321
348770
|
toolCalls: [],
|
|
348322
|
-
origin: {
|
|
348771
|
+
origin: {
|
|
348772
|
+
kind: "compaction_summary",
|
|
348773
|
+
...record.toolContinuity === void 0 ? {} : { toolContinuity: record.toolContinuity }
|
|
348774
|
+
}
|
|
348323
348775
|
},
|
|
348324
348776
|
time: record.time
|
|
348325
348777
|
};
|
|
@@ -350593,6 +351045,24 @@ var Session = class {
|
|
|
350593
351045
|
this.ensureOpen();
|
|
350594
351046
|
return this.rpc.getGoal({ sessionId: this.id });
|
|
350595
351047
|
}
|
|
351048
|
+
async editGoal(input) {
|
|
351049
|
+
this.ensureOpen();
|
|
351050
|
+
return this.rpc.editGoal({
|
|
351051
|
+
sessionId: this.id,
|
|
351052
|
+
objective: input.objective
|
|
351053
|
+
});
|
|
351054
|
+
}
|
|
351055
|
+
async blockGoal(input = {}) {
|
|
351056
|
+
this.ensureOpen();
|
|
351057
|
+
return this.rpc.blockGoal({
|
|
351058
|
+
sessionId: this.id,
|
|
351059
|
+
reason: input.reason
|
|
351060
|
+
});
|
|
351061
|
+
}
|
|
351062
|
+
async completeGoal() {
|
|
351063
|
+
this.ensureOpen();
|
|
351064
|
+
return this.rpc.completeGoal({ sessionId: this.id });
|
|
351065
|
+
}
|
|
350596
351066
|
async pauseGoal() {
|
|
350597
351067
|
this.ensureOpen();
|
|
350598
351068
|
return this.rpc.pauseGoal({ sessionId: this.id });
|
|
@@ -351982,6 +352452,26 @@ var SDKRpcClientBase = class {
|
|
|
351982
352452
|
replace: input.replace
|
|
351983
352453
|
});
|
|
351984
352454
|
}
|
|
352455
|
+
async editGoal(input) {
|
|
352456
|
+
return (await this.getRpc()).editGoal({
|
|
352457
|
+
sessionId: input.sessionId,
|
|
352458
|
+
agentId: this.interactiveAgentId,
|
|
352459
|
+
objective: input.objective
|
|
352460
|
+
});
|
|
352461
|
+
}
|
|
352462
|
+
async blockGoal(input) {
|
|
352463
|
+
return (await this.getRpc()).blockGoal({
|
|
352464
|
+
sessionId: input.sessionId,
|
|
352465
|
+
agentId: this.interactiveAgentId,
|
|
352466
|
+
reason: input.reason
|
|
352467
|
+
});
|
|
352468
|
+
}
|
|
352469
|
+
async completeGoal(input) {
|
|
352470
|
+
return (await this.getRpc()).completeGoal({
|
|
352471
|
+
sessionId: input.sessionId,
|
|
352472
|
+
agentId: this.interactiveAgentId
|
|
352473
|
+
});
|
|
352474
|
+
}
|
|
351985
352475
|
async getGoal(input) {
|
|
351986
352476
|
return (await this.getRpc()).getGoal({
|
|
351987
352477
|
sessionId: input.sessionId,
|
|
@@ -426659,7 +427149,7 @@ async function searchLocalToolEvents(homeDir, sessions, query, limit = 8) {
|
|
|
426659
427149
|
skippedRecords++;
|
|
426660
427150
|
continue;
|
|
426661
427151
|
}
|
|
426662
|
-
const searchable = `${event.tool} ${event.filePath ?? ""}`.normalize("NFKC").toLocaleLowerCase();
|
|
427152
|
+
const searchable = `${event.tool} ${event.status} ${event.filePath ?? ""}`.normalize("NFKC").toLocaleLowerCase();
|
|
426663
427153
|
if (terms.every((term) => searchable.includes(term))) {
|
|
426664
427154
|
hits.push(event);
|
|
426665
427155
|
hits.sort((a, b) => b.at - a.at || a.sessionId.localeCompare(b.sessionId));
|
|
@@ -439574,7 +440064,7 @@ function buildUsageReportLines(options) {
|
|
|
439574
440064
|
const errorStyle = (text) => currentTheme.fg("error", text);
|
|
439575
440065
|
const severityColor = (sev) => sev === "danger" ? "error" : sev === "warn" ? "warning" : "success";
|
|
439576
440066
|
const lines = [accent(uiText("usage.session.title")), ...buildSessionUsageSection(options.sessionUsage, options.sessionUsageError, value, muted, errorStyle)];
|
|
439577
|
-
if (options.maxContextTokens > 0) {
|
|
440067
|
+
if (Number.isFinite(options.maxContextTokens) && options.maxContextTokens > 0) {
|
|
439578
440068
|
const ratio = safeUsageRatio(options.contextTokens / options.maxContextTokens);
|
|
439579
440069
|
const bar = renderProgressBar(ratio, 20);
|
|
439580
440070
|
const pct = `${(ratio * 100).toFixed(1)}%`;
|
|
@@ -439825,7 +440315,7 @@ function buildStatusReportLines(options) {
|
|
|
439825
440315
|
const { ratio, tokens, maxTokens } = contextValues(options);
|
|
439826
440316
|
lines.push("");
|
|
439827
440317
|
lines.push(accent(uiText("usage.context.title")));
|
|
439828
|
-
if (maxTokens > 0) {
|
|
440318
|
+
if (Number.isFinite(maxTokens) && maxTokens > 0) {
|
|
439829
440319
|
const safeRatio = safeUsageRatio(ratio);
|
|
439830
440320
|
const bar = renderProgressBar(safeRatio, 20);
|
|
439831
440321
|
const barColoured = currentTheme.fg(severityToken(ratioSeverity(safeRatio)), bar);
|
|
@@ -440776,11 +441266,18 @@ registerUiCatalogFragment({
|
|
|
440776
441266
|
//#endregion
|
|
440777
441267
|
//#region src/tui/utils/event-payload.ts
|
|
440778
441268
|
function appendStreamingArgsPreview(current, next) {
|
|
440779
|
-
|
|
441269
|
+
let existing = (current ?? "").slice(0, STREAMING_ARGS_PREVIEW_MAX_CHARS);
|
|
441270
|
+
const boundary = existing.charCodeAt(existing.length - 1);
|
|
441271
|
+
if (existing.length === 65536 && boundary >= 55296 && boundary <= 56319) existing = existing.slice(0, -1);
|
|
440780
441272
|
if (next === null || next === void 0 || next.length === 0) return existing;
|
|
440781
441273
|
const remaining = STREAMING_ARGS_PREVIEW_MAX_CHARS - existing.length;
|
|
440782
441274
|
if (remaining <= 0) return existing;
|
|
440783
|
-
|
|
441275
|
+
const first = next.charCodeAt(0);
|
|
441276
|
+
const previous = existing.charCodeAt(existing.length - 1);
|
|
441277
|
+
const continuation = first >= 56320 && first <= 57343 && !(previous >= 55296 && previous <= 56319) ? next.slice(1) : next;
|
|
441278
|
+
const preview = `${existing}${continuation.slice(0, remaining)}`;
|
|
441279
|
+
const last = preview.charCodeAt(preview.length - 1);
|
|
441280
|
+
return preview.length === 65536 && last >= 55296 && last <= 56319 ? preview.slice(0, -1) : preview;
|
|
440784
441281
|
}
|
|
440785
441282
|
function unescapeJsonString$1(s) {
|
|
440786
441283
|
return s.replaceAll(/\\(["\\/bfnrt])/g, (_, ch) => {
|
|
@@ -502691,6 +503188,7 @@ const BUILTIN_SLASH_COMMAND_DEFINITIONS = [
|
|
|
502691
503188
|
const tokens = trimmed.split(/\s+/);
|
|
502692
503189
|
const action = tokens[0]?.toLowerCase();
|
|
502693
503190
|
if (action === "next") return "always";
|
|
503191
|
+
if (action === "edit" || action === "block") return "always";
|
|
502694
503192
|
if (tokens.length === 1 && (action === "status" || action === "pause" || action === "paused" || action === "cancel" || action === "clear" || action === "stop")) return "always";
|
|
502695
503193
|
return "idle-only";
|
|
502696
503194
|
}
|
|
@@ -509515,7 +510013,9 @@ registerUiCatalogFragment({
|
|
|
509515
510013
|
//#region src/tui/commands/goal.ts
|
|
509516
510014
|
const MAX_GOAL_OBJECTIVE_LENGTH = 4e3;
|
|
509517
510015
|
const RESUME_GOAL_INPUT = "Resume the active goal.";
|
|
510016
|
+
const pendingGoalEdits = /* @__PURE__ */ new WeakMap();
|
|
509518
510017
|
const CONTROL_SUBCOMMANDS = new Map([
|
|
510018
|
+
["complete", "complete"],
|
|
509519
510019
|
["pause", "pause"],
|
|
509520
510020
|
["paused", "pause"],
|
|
509521
510021
|
["resume", "resume"],
|
|
@@ -509537,6 +510037,26 @@ function parseGoalCommand(rawArgs) {
|
|
|
509537
510037
|
if (args.length === 0 || args.toLowerCase() === "status") return { kind: "status" };
|
|
509538
510038
|
const tokens = args.split(/\s+/);
|
|
509539
510039
|
const first = tokens[0]?.toLowerCase();
|
|
510040
|
+
if (first === "block") return {
|
|
510041
|
+
kind: "block",
|
|
510042
|
+
reason: tokens.slice(1).join(" ").trim() || void 0
|
|
510043
|
+
};
|
|
510044
|
+
if (first === "edit") {
|
|
510045
|
+
const objective = tokens.slice(1).join(" ").trim();
|
|
510046
|
+
if (objective.length === 0) return {
|
|
510047
|
+
kind: "error",
|
|
510048
|
+
severity: "hint",
|
|
510049
|
+
message: uiText("goal.error.objectiveRequired")
|
|
510050
|
+
};
|
|
510051
|
+
if (objective.length > MAX_GOAL_OBJECTIVE_LENGTH) return {
|
|
510052
|
+
kind: "error",
|
|
510053
|
+
message: uiText("goal.error.objectiveTooLong", { max: MAX_GOAL_OBJECTIVE_LENGTH })
|
|
510054
|
+
};
|
|
510055
|
+
return {
|
|
510056
|
+
kind: "edit",
|
|
510057
|
+
objective
|
|
510058
|
+
};
|
|
510059
|
+
}
|
|
509540
510060
|
if (first === "next") return parseNextGoalCommand(tokens);
|
|
509541
510061
|
const control = first === void 0 ? void 0 : CONTROL_SUBCOMMANDS.get(first);
|
|
509542
510062
|
if (control !== void 0 && tokens.length === 1) return { kind: control };
|
|
@@ -509574,6 +510094,15 @@ async function handleGoalCommand(host, args) {
|
|
|
509574
510094
|
case "status":
|
|
509575
510095
|
await showGoalStatus(host);
|
|
509576
510096
|
return;
|
|
510097
|
+
case "edit":
|
|
510098
|
+
await editGoal(host, parsed.objective);
|
|
510099
|
+
return;
|
|
510100
|
+
case "block":
|
|
510101
|
+
await blockGoal(host, parsed.reason);
|
|
510102
|
+
return;
|
|
510103
|
+
case "complete":
|
|
510104
|
+
await completeGoal(host);
|
|
510105
|
+
return;
|
|
509577
510106
|
case "pause":
|
|
509578
510107
|
await pauseGoal(host);
|
|
509579
510108
|
return;
|
|
@@ -509819,12 +510348,78 @@ async function startGoal(host, parsed, options) {
|
|
|
509819
510348
|
else host.sendNormalUserInput(parsed.objective);
|
|
509820
510349
|
return true;
|
|
509821
510350
|
}
|
|
510351
|
+
async function completeGoal(host) {
|
|
510352
|
+
if (isBusy(host)) {
|
|
510353
|
+
host.showStatus(slashBusyMessage("goal", host.state.appState.isCompacting ? "compacting" : "streaming"));
|
|
510354
|
+
return;
|
|
510355
|
+
}
|
|
510356
|
+
const session = host.requireSession();
|
|
510357
|
+
pendingGoalEdits.delete(host);
|
|
510358
|
+
try {
|
|
510359
|
+
const result = await session.completeGoal();
|
|
510360
|
+
if (host.session !== session || result !== null) return;
|
|
510361
|
+
const { goal } = await session.getGoal();
|
|
510362
|
+
if (host.session !== session) return;
|
|
510363
|
+
host.setAppState({ goal });
|
|
510364
|
+
if (goal === null) host.showStatus(uiText("goal.status.noneSet"));
|
|
510365
|
+
else renderGoalStatus(host, goal);
|
|
510366
|
+
} catch (error) {
|
|
510367
|
+
if (host.session !== session) return;
|
|
510368
|
+
if (isBlunError(error) && error.code === ErrorCodes.GOAL_NOT_FOUND) {
|
|
510369
|
+
host.showStatus(uiText("goal.status.noneSet"));
|
|
510370
|
+
return;
|
|
510371
|
+
}
|
|
510372
|
+
host.showError(formatErrorMessage$2(error));
|
|
510373
|
+
}
|
|
510374
|
+
}
|
|
510375
|
+
async function blockGoal(host, reason) {
|
|
510376
|
+
const session = host.requireSession();
|
|
510377
|
+
pendingGoalEdits.delete(host);
|
|
510378
|
+
try {
|
|
510379
|
+
const goal = await session.blockGoal({ reason });
|
|
510380
|
+
if (host.session !== session) return;
|
|
510381
|
+
if (isStreaming$1(host)) await session.cancel();
|
|
510382
|
+
if (host.session !== session) return;
|
|
510383
|
+
host.setAppState({ goal });
|
|
510384
|
+
renderGoalStatus(host, goal);
|
|
510385
|
+
} catch (error) {
|
|
510386
|
+
if (host.session !== session) return;
|
|
510387
|
+
if (isBlunError(error) && error.code === ErrorCodes.GOAL_NOT_FOUND) {
|
|
510388
|
+
host.showStatus(uiText("goal.status.noneSet"));
|
|
510389
|
+
return;
|
|
510390
|
+
}
|
|
510391
|
+
host.showError(formatErrorMessage$2(error));
|
|
510392
|
+
}
|
|
510393
|
+
}
|
|
510394
|
+
async function editGoal(host, objective) {
|
|
510395
|
+
const session = host.requireSession();
|
|
510396
|
+
const request = Symbol("goal-edit");
|
|
510397
|
+
pendingGoalEdits.set(host, request);
|
|
510398
|
+
try {
|
|
510399
|
+
const goal = await session.editGoal({ objective });
|
|
510400
|
+
if (host.session !== session || pendingGoalEdits.get(host) !== request) return;
|
|
510401
|
+
host.setAppState({ goal });
|
|
510402
|
+
renderGoalStatus(host, goal);
|
|
510403
|
+
} catch (error) {
|
|
510404
|
+
if (host.session !== session || pendingGoalEdits.get(host) !== request) return;
|
|
510405
|
+
if (isBlunError(error) && error.code === ErrorCodes.GOAL_NOT_FOUND) {
|
|
510406
|
+
host.showStatus(uiText("goal.status.noneSet"));
|
|
510407
|
+
return;
|
|
510408
|
+
}
|
|
510409
|
+
host.showError(formatErrorMessage$2(error));
|
|
510410
|
+
} finally {
|
|
510411
|
+
if (pendingGoalEdits.get(host) === request) pendingGoalEdits.delete(host);
|
|
510412
|
+
}
|
|
510413
|
+
}
|
|
509822
510414
|
async function pauseGoal(host) {
|
|
509823
510415
|
const session = host.requireSession();
|
|
510416
|
+
pendingGoalEdits.delete(host);
|
|
509824
510417
|
try {
|
|
509825
510418
|
await session.pauseGoal();
|
|
510419
|
+
if (host.session !== session) return;
|
|
509826
510420
|
if (isStreaming$1(host)) await session.cancel();
|
|
509827
510421
|
} catch (error) {
|
|
510422
|
+
if (host.session !== session) return;
|
|
509828
510423
|
if (isBlunError(error) && error.code === ErrorCodes.GOAL_NOT_FOUND) {
|
|
509829
510424
|
host.showStatus(uiText("goal.status.noneToPause"));
|
|
509830
510425
|
return;
|
|
@@ -509832,6 +510427,7 @@ async function pauseGoal(host) {
|
|
|
509832
510427
|
host.showError(formatErrorMessage$2(error));
|
|
509833
510428
|
return;
|
|
509834
510429
|
}
|
|
510430
|
+
if (host.session !== session) return;
|
|
509835
510431
|
host.track("goal_pause");
|
|
509836
510432
|
host.showStatus(uiText("goal.status.paused"));
|
|
509837
510433
|
}
|
|
@@ -509840,9 +510436,12 @@ async function resumeGoal(host) {
|
|
|
509840
510436
|
host.showError(uiText("goal.error.modelNotSet"));
|
|
509841
510437
|
return;
|
|
509842
510438
|
}
|
|
510439
|
+
const session = host.requireSession();
|
|
510440
|
+
pendingGoalEdits.delete(host);
|
|
509843
510441
|
try {
|
|
509844
|
-
await
|
|
510442
|
+
await session.resumeGoal();
|
|
509845
510443
|
} catch (error) {
|
|
510444
|
+
if (host.session !== session) return;
|
|
509846
510445
|
if (isBlunError(error) && error.code === ErrorCodes.GOAL_NOT_FOUND) {
|
|
509847
510446
|
host.showStatus(uiText("goal.status.noneToResume"));
|
|
509848
510447
|
return;
|
|
@@ -509850,15 +510449,19 @@ async function resumeGoal(host) {
|
|
|
509850
510449
|
host.showError(formatErrorMessage$2(error));
|
|
509851
510450
|
return;
|
|
509852
510451
|
}
|
|
510452
|
+
if (host.session !== session) return;
|
|
509853
510453
|
host.track("goal_resume");
|
|
509854
510454
|
host.sendNormalUserInput(RESUME_GOAL_INPUT);
|
|
509855
510455
|
}
|
|
509856
510456
|
async function cancelGoal(host) {
|
|
509857
510457
|
const session = host.requireSession();
|
|
510458
|
+
pendingGoalEdits.delete(host);
|
|
509858
510459
|
try {
|
|
509859
510460
|
await session.cancelGoal();
|
|
510461
|
+
if (host.session !== session) return;
|
|
509860
510462
|
if (isStreaming$1(host)) await session.cancel();
|
|
509861
510463
|
} catch (error) {
|
|
510464
|
+
if (host.session !== session) return;
|
|
509862
510465
|
if (isBlunError(error) && error.code === ErrorCodes.GOAL_NOT_FOUND) {
|
|
509863
510466
|
host.showStatus(uiText("goal.status.noneToCancel"));
|
|
509864
510467
|
return;
|
|
@@ -509866,6 +510469,7 @@ async function cancelGoal(host) {
|
|
|
509866
510469
|
host.showError(formatErrorMessage$2(error));
|
|
509867
510470
|
return;
|
|
509868
510471
|
}
|
|
510472
|
+
if (host.session !== session) return;
|
|
509869
510473
|
host.track("goal_cancel");
|
|
509870
510474
|
host.showNotice(uiText("goal.status.cancelled"));
|
|
509871
510475
|
}
|
|
@@ -509876,6 +510480,9 @@ async function showGoalStatus(host) {
|
|
|
509876
510480
|
host.showStatus(uiText("goal.status.noneSet"));
|
|
509877
510481
|
return;
|
|
509878
510482
|
}
|
|
510483
|
+
renderGoalStatus(host, goal);
|
|
510484
|
+
}
|
|
510485
|
+
function renderGoalStatus(host, goal) {
|
|
509879
510486
|
if (host.getChannelCommandContext?.() !== void 0) {
|
|
509880
510487
|
host.showStatus(`${goalPanelTitle(goal).trim()}\n${goal.objective}`);
|
|
509881
510488
|
return;
|
|
@@ -521188,6 +521795,196 @@ function numberField(record, key) {
|
|
|
521188
521795
|
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
521189
521796
|
}
|
|
521190
521797
|
//#endregion
|
|
521798
|
+
//#region src/tui/components/media/image-thumbnail.ts
|
|
521799
|
+
/**
|
|
521800
|
+
* Transcript-side rendering of a pasted image.
|
|
521801
|
+
*
|
|
521802
|
+
* On terminals that speak the Kitty graphics protocol or iTerm2 inline
|
|
521803
|
+
* image protocol (detected by pi-tui's `getCapabilities()`), we show
|
|
521804
|
+
* the actual image. Everywhere else we fall back to a one-line text
|
|
521805
|
+
* marker matching the placeholder the user sees in the input box —
|
|
521806
|
+
* this keeps the transcript readable on Terminal.app / Linux default
|
|
521807
|
+
* terminals / `script` recordings without extra chrome.
|
|
521808
|
+
*
|
|
521809
|
+
* Height is capped at ~12 rows so a single screenshot can't monopolize
|
|
521810
|
+
* the viewport; pi-tui handles proportional scaling internally.
|
|
521811
|
+
*/
|
|
521812
|
+
const MAX_IMAGE_ROWS = 12;
|
|
521813
|
+
const MAX_IMAGE_WIDTH = 40;
|
|
521814
|
+
var ImageThumbnail = class extends Container {
|
|
521815
|
+
attachment;
|
|
521816
|
+
image;
|
|
521817
|
+
lastBuiltProtocol;
|
|
521818
|
+
constructor(attachment) {
|
|
521819
|
+
super();
|
|
521820
|
+
this.attachment = attachment;
|
|
521821
|
+
this.buildChildren();
|
|
521822
|
+
}
|
|
521823
|
+
buildChildren() {
|
|
521824
|
+
this.clear();
|
|
521825
|
+
const caps = getCapabilities();
|
|
521826
|
+
const supportsInline = caps.images === "kitty" || caps.images === "iterm2";
|
|
521827
|
+
this.lastBuiltProtocol = caps.images;
|
|
521828
|
+
if (!supportsInline) {
|
|
521829
|
+
this.addChild(new Text(currentTheme.fg("accent", this.attachment.placeholder), 0, 0));
|
|
521830
|
+
return;
|
|
521831
|
+
}
|
|
521832
|
+
const theme = { fallbackColor: (s) => currentTheme.fg("textDim", s) };
|
|
521833
|
+
this.image ??= new Image(Buffer.from(this.attachment.bytes).toString("base64"), this.attachment.mime, theme, {
|
|
521834
|
+
maxHeightCells: MAX_IMAGE_ROWS,
|
|
521835
|
+
maxWidthCells: MAX_IMAGE_WIDTH,
|
|
521836
|
+
filename: this.attachment.placeholder
|
|
521837
|
+
}, {
|
|
521838
|
+
widthPx: this.attachment.width,
|
|
521839
|
+
heightPx: this.attachment.height
|
|
521840
|
+
});
|
|
521841
|
+
this.image.invalidate();
|
|
521842
|
+
this.addChild(this.image);
|
|
521843
|
+
}
|
|
521844
|
+
render(width) {
|
|
521845
|
+
const safeWidth = Math.max(0, width);
|
|
521846
|
+
if (safeWidth === 0) return [""];
|
|
521847
|
+
if (safeWidth < MAX_IMAGE_WIDTH + 2) return new Text(currentTheme.fg("accent", this.attachment.placeholder), 0, 0).render(safeWidth);
|
|
521848
|
+
const caps = getCapabilities();
|
|
521849
|
+
if (this.lastBuiltProtocol !== caps.images) this.buildChildren();
|
|
521850
|
+
return super.render(safeWidth);
|
|
521851
|
+
}
|
|
521852
|
+
invalidate() {
|
|
521853
|
+
this.buildChildren();
|
|
521854
|
+
super.invalidate();
|
|
521855
|
+
}
|
|
521856
|
+
};
|
|
521857
|
+
//#endregion
|
|
521858
|
+
//#region src/utils/image/image-mime.ts
|
|
521859
|
+
function parseImageMeta(bytes) {
|
|
521860
|
+
if (isPng(bytes)) return parsePng(bytes);
|
|
521861
|
+
if (isJpeg(bytes)) return parseJpeg(bytes);
|
|
521862
|
+
if (isGif(bytes)) return parseGif(bytes);
|
|
521863
|
+
if (isWebp(bytes)) return parseWebp(bytes);
|
|
521864
|
+
return null;
|
|
521865
|
+
}
|
|
521866
|
+
function isPng(b) {
|
|
521867
|
+
return b.length >= 8 && b[0] === 137 && b[1] === 80 && b[2] === 78 && b[3] === 71 && b[4] === 13 && b[5] === 10 && b[6] === 26 && b[7] === 10;
|
|
521868
|
+
}
|
|
521869
|
+
function parsePng(b) {
|
|
521870
|
+
if (b.length < 24) return null;
|
|
521871
|
+
const width = readUInt32BE(b, 16);
|
|
521872
|
+
const height = readUInt32BE(b, 20);
|
|
521873
|
+
if (width <= 0 || height <= 0) return null;
|
|
521874
|
+
return {
|
|
521875
|
+
mime: "image/png",
|
|
521876
|
+
width,
|
|
521877
|
+
height
|
|
521878
|
+
};
|
|
521879
|
+
}
|
|
521880
|
+
function isJpeg(b) {
|
|
521881
|
+
return b.length >= 3 && b[0] === 255 && b[1] === 216 && b[2] === 255;
|
|
521882
|
+
}
|
|
521883
|
+
function parseJpeg(b) {
|
|
521884
|
+
let i = 2;
|
|
521885
|
+
while (i < b.length) {
|
|
521886
|
+
if (b[i] !== 255) {
|
|
521887
|
+
i += 1;
|
|
521888
|
+
continue;
|
|
521889
|
+
}
|
|
521890
|
+
while (i < b.length && b[i] === 255) i += 1;
|
|
521891
|
+
if (i >= b.length) return null;
|
|
521892
|
+
const marker = b[i];
|
|
521893
|
+
i += 1;
|
|
521894
|
+
if (marker === 216 || marker === 217) continue;
|
|
521895
|
+
if (i + 1 >= b.length) return null;
|
|
521896
|
+
const segLen = readUInt16BE(b, i);
|
|
521897
|
+
if (isSofMarker(marker)) {
|
|
521898
|
+
if (i + 7 >= b.length) return null;
|
|
521899
|
+
const height = readUInt16BE(b, i + 3);
|
|
521900
|
+
const width = readUInt16BE(b, i + 5);
|
|
521901
|
+
if (width <= 0 || height <= 0) return null;
|
|
521902
|
+
return {
|
|
521903
|
+
mime: "image/jpeg",
|
|
521904
|
+
width,
|
|
521905
|
+
height
|
|
521906
|
+
};
|
|
521907
|
+
}
|
|
521908
|
+
i += segLen;
|
|
521909
|
+
}
|
|
521910
|
+
return null;
|
|
521911
|
+
}
|
|
521912
|
+
function isSofMarker(marker) {
|
|
521913
|
+
if (marker < 192 || marker > 207) return false;
|
|
521914
|
+
return marker !== 196 && marker !== 200 && marker !== 204;
|
|
521915
|
+
}
|
|
521916
|
+
function isGif(b) {
|
|
521917
|
+
return b.length >= 6 && b[0] === 71 && b[1] === 73 && b[2] === 70 && b[3] === 56 && (b[4] === 55 || b[4] === 57) && b[5] === 97;
|
|
521918
|
+
}
|
|
521919
|
+
function parseGif(b) {
|
|
521920
|
+
if (b.length < 10) return null;
|
|
521921
|
+
const width = readUInt16LE(b, 6);
|
|
521922
|
+
const height = readUInt16LE(b, 8);
|
|
521923
|
+
if (width <= 0 || height <= 0) return null;
|
|
521924
|
+
return {
|
|
521925
|
+
mime: "image/gif",
|
|
521926
|
+
width,
|
|
521927
|
+
height
|
|
521928
|
+
};
|
|
521929
|
+
}
|
|
521930
|
+
function isWebp(b) {
|
|
521931
|
+
return b.length >= 12 && b[0] === 82 && b[1] === 73 && b[2] === 70 && b[3] === 70 && b[8] === 87 && b[9] === 69 && b[10] === 66 && b[11] === 80;
|
|
521932
|
+
}
|
|
521933
|
+
function parseWebp(b) {
|
|
521934
|
+
if (b.length < 30) return null;
|
|
521935
|
+
const chunk = String.fromCodePoint(b[12], b[13], b[14], b[15]);
|
|
521936
|
+
if (chunk === "VP8 ") {
|
|
521937
|
+
const widthRaw = readUInt16LE(b, 26);
|
|
521938
|
+
const heightRaw = readUInt16LE(b, 28);
|
|
521939
|
+
const width = widthRaw & 16383;
|
|
521940
|
+
const height = heightRaw & 16383;
|
|
521941
|
+
if (width <= 0 || height <= 0) return null;
|
|
521942
|
+
return {
|
|
521943
|
+
mime: "image/webp",
|
|
521944
|
+
width,
|
|
521945
|
+
height
|
|
521946
|
+
};
|
|
521947
|
+
}
|
|
521948
|
+
if (chunk === "VP8L") {
|
|
521949
|
+
if (b[20] !== 47) return null;
|
|
521950
|
+
const b1 = b[21];
|
|
521951
|
+
const b2 = b[22];
|
|
521952
|
+
const b3 = b[23];
|
|
521953
|
+
const b4 = b[24];
|
|
521954
|
+
const width = 1 + ((b2 & 63) << 8 | b1);
|
|
521955
|
+
const height = 1 + ((b4 & 15) << 10 | b3 << 2 | (b2 & 192) >> 6);
|
|
521956
|
+
if (width <= 0 || height <= 0) return null;
|
|
521957
|
+
return {
|
|
521958
|
+
mime: "image/webp",
|
|
521959
|
+
width,
|
|
521960
|
+
height
|
|
521961
|
+
};
|
|
521962
|
+
}
|
|
521963
|
+
if (chunk === "VP8X") {
|
|
521964
|
+
const width = 1 + readUInt24LE(b, 24);
|
|
521965
|
+
const height = 1 + readUInt24LE(b, 27);
|
|
521966
|
+
if (width <= 0 || height <= 0) return null;
|
|
521967
|
+
return {
|
|
521968
|
+
mime: "image/webp",
|
|
521969
|
+
width,
|
|
521970
|
+
height
|
|
521971
|
+
};
|
|
521972
|
+
}
|
|
521973
|
+
return null;
|
|
521974
|
+
}
|
|
521975
|
+
function readUInt16BE(b, off) {
|
|
521976
|
+
return b[off] << 8 | b[off + 1];
|
|
521977
|
+
}
|
|
521978
|
+
function readUInt16LE(b, off) {
|
|
521979
|
+
return b[off] | b[off + 1] << 8;
|
|
521980
|
+
}
|
|
521981
|
+
function readUInt24LE(b, off) {
|
|
521982
|
+
return b[off] | b[off + 1] << 8 | b[off + 2] << 16;
|
|
521983
|
+
}
|
|
521984
|
+
function readUInt32BE(b, off) {
|
|
521985
|
+
return Math.trunc(b[off] * 16777216 + (b[off + 1] << 16) + (b[off + 2] << 8) + b[off + 3]);
|
|
521986
|
+
}
|
|
521987
|
+
//#endregion
|
|
521191
521988
|
//#region src/tui/components/messages/tool-renderers/media.copy.ts
|
|
521192
521989
|
registerUiCatalogFragment({
|
|
521193
521990
|
en: { "mediaChip.uploaded": "uploaded" },
|
|
@@ -521202,6 +521999,51 @@ registerUiCatalogFragment({
|
|
|
521202
521999
|
const PATH_TAG_RE = /^<(image|video)\s+path="([^"]+)">$/;
|
|
521203
522000
|
const ORIGINAL_SIZE_RE = /original size\s+(\d+x\d+px)/;
|
|
521204
522001
|
const DATA_URL_RE = /^data:([^;]+);base64,(.*)$/s;
|
|
522002
|
+
const MAX_PREVIEW_BYTES = 8 * 1024 * 1024;
|
|
522003
|
+
const MAX_PREVIEW_IMAGES = 4;
|
|
522004
|
+
function imagePreviews(output) {
|
|
522005
|
+
const protocol = getCapabilities().images;
|
|
522006
|
+
if (protocol !== "kitty" && protocol !== "iterm2") return [];
|
|
522007
|
+
let parts;
|
|
522008
|
+
try {
|
|
522009
|
+
parts = JSON.parse(output);
|
|
522010
|
+
} catch {
|
|
522011
|
+
return [];
|
|
522012
|
+
}
|
|
522013
|
+
if (!Array.isArray(parts)) return [];
|
|
522014
|
+
const previews = [];
|
|
522015
|
+
let remainingBytes = MAX_PREVIEW_BYTES;
|
|
522016
|
+
for (const raw of parts) {
|
|
522017
|
+
if (previews.length >= MAX_PREVIEW_IMAGES || remainingBytes <= 0) break;
|
|
522018
|
+
if (typeof raw !== "object" || raw === null) continue;
|
|
522019
|
+
const part = raw;
|
|
522020
|
+
if (part["type"] !== "image_url") continue;
|
|
522021
|
+
const holder = part["imageUrl"];
|
|
522022
|
+
if (typeof holder !== "object" || holder === null) continue;
|
|
522023
|
+
const url = holder["url"];
|
|
522024
|
+
if (typeof url !== "string") continue;
|
|
522025
|
+
const data = DATA_URL_RE.exec(url);
|
|
522026
|
+
if (data === null || data[2] === void 0) continue;
|
|
522027
|
+
const encoded = data[2];
|
|
522028
|
+
if (bytesFromBase64(encoded) > remainingBytes || !/^[A-Za-z0-9+/]*={0,2}$/.test(encoded)) continue;
|
|
522029
|
+
const bytes = Buffer.from(encoded, "base64");
|
|
522030
|
+
if (bytes.length > remainingBytes) continue;
|
|
522031
|
+
const meta = parseImageMeta(bytes);
|
|
522032
|
+
if (meta === null || meta.mime !== data[1]) continue;
|
|
522033
|
+
const attachment = {
|
|
522034
|
+
id: 0,
|
|
522035
|
+
kind: "image",
|
|
522036
|
+
bytes,
|
|
522037
|
+
mime: meta.mime,
|
|
522038
|
+
width: meta.width,
|
|
522039
|
+
height: meta.height,
|
|
522040
|
+
placeholder: `${meta.mime} (${meta.width}x${meta.height})`
|
|
522041
|
+
};
|
|
522042
|
+
previews.push(new ImageThumbnail(attachment));
|
|
522043
|
+
remainingBytes -= bytes.length;
|
|
522044
|
+
}
|
|
522045
|
+
return previews;
|
|
522046
|
+
}
|
|
521205
522047
|
function bytesFromBase64(b64) {
|
|
521206
522048
|
const len = b64.length;
|
|
521207
522049
|
if (len === 0) return 0;
|
|
@@ -521285,7 +522127,6 @@ const readMediaChip = (_toolCall, result) => {
|
|
|
521285
522127
|
return `${summary.kind} (${meta.join(", ")})`;
|
|
521286
522128
|
};
|
|
521287
522129
|
const readMediaSummary = (toolCall, result, ctx) => {
|
|
521288
|
-
if (result.is_error) return renderTruncated(toolCall, result, ctx);
|
|
521289
522130
|
const summary = parseReadMediaOutput(result.output);
|
|
521290
522131
|
if (summary === null) return renderTruncated(toolCall, result, ctx);
|
|
521291
522132
|
if (!ctx.expanded) return [];
|
|
@@ -521297,6 +522138,22 @@ const readMediaSummary = (toolCall, result, ctx) => {
|
|
|
521297
522138
|
if (meta.length > 0) tail.push(meta.join(", "));
|
|
521298
522139
|
if (summary.url !== void 0) tail.push(summary.url);
|
|
521299
522140
|
out.push(new Text(` ${dim(tail.join(" · "))}`, 0, 0));
|
|
522141
|
+
if (!result.is_error && summary.kind === "image") out.push(...imagePreviews(result.output));
|
|
522142
|
+
return out;
|
|
522143
|
+
};
|
|
522144
|
+
const genericMediaResult = (toolCall, result, ctx) => {
|
|
522145
|
+
if (!result.output.includes("\"image_url\"") && !result.output.includes("\"video_url\"")) return renderTruncated(toolCall, result, ctx);
|
|
522146
|
+
const summary = parseReadMediaOutput(result.output);
|
|
522147
|
+
if (summary === null) return renderTruncated(toolCall, result, ctx);
|
|
522148
|
+
const textParts = JSON.parse(result.output).filter((part) => typeof part === "object" && part !== null && part["type"] === "text" && typeof part["text"] === "string").map((part) => part.text);
|
|
522149
|
+
const meta = metaSegments(summary);
|
|
522150
|
+
const label = [summary.kind, ...meta].join(" · ");
|
|
522151
|
+
const out = [new Text(` ${chalk.dim(label)}`, 0, 0)];
|
|
522152
|
+
if (textParts.length > 0) out.push(...renderTruncated(toolCall, {
|
|
522153
|
+
...result,
|
|
522154
|
+
output: textParts.join("\n")
|
|
522155
|
+
}, ctx));
|
|
522156
|
+
if (ctx.expanded && !result.is_error) out.push(...imagePreviews(result.output));
|
|
521300
522157
|
return out;
|
|
521301
522158
|
};
|
|
521302
522159
|
//#endregion
|
|
@@ -521463,8 +522320,8 @@ const globSummary = withGlance(globGlance);
|
|
|
521463
522320
|
*
|
|
521464
522321
|
* Each tool name maps to a `ResultRenderer` that turns the tool's
|
|
521465
522322
|
* `ToolResultBlockData` into renderable Components. Tools without an
|
|
521466
|
-
* explicit entry fall through to
|
|
521467
|
-
* 3-line + ctrl+o behavior
|
|
522323
|
+
* explicit entry fall through to the generic renderer, which keeps the
|
|
522324
|
+
* original 3-line + ctrl+o behavior for text results.
|
|
521468
522325
|
*
|
|
521469
522326
|
* Keep this dispatch flat — tool names live next to the renderer they
|
|
521470
522327
|
* choose, so adding a new tool means appending one case.
|
|
@@ -521476,7 +522333,7 @@ const globSummary = withGlance(globGlance);
|
|
|
521476
522333
|
* the main agent previews it.
|
|
521477
522334
|
*/
|
|
521478
522335
|
function isGenericToolResult(toolName) {
|
|
521479
|
-
return pickResultRenderer(toolName) ===
|
|
522336
|
+
return pickResultRenderer(toolName) === genericMediaResult;
|
|
521480
522337
|
}
|
|
521481
522338
|
function pickResultRenderer(toolName) {
|
|
521482
522339
|
switch (toolName) {
|
|
@@ -521494,7 +522351,7 @@ function pickResultRenderer(toolName) {
|
|
|
521494
522351
|
case "GetGoal":
|
|
521495
522352
|
case "SetGoalBudget":
|
|
521496
522353
|
case "UpdateGoal": return goalSummary;
|
|
521497
|
-
default: return
|
|
522354
|
+
default: return genericMediaResult;
|
|
521498
522355
|
}
|
|
521499
522356
|
}
|
|
521500
522357
|
//#endregion
|
|
@@ -523449,66 +524306,6 @@ function formatActivityLine(phase, toolName, args, workspaceDir) {
|
|
|
523449
524306
|
return keyArg ? `${verb} ${toolName} (${keyArg})` : `${verb} ${toolName}`;
|
|
523450
524307
|
}
|
|
523451
524308
|
//#endregion
|
|
523452
|
-
//#region src/tui/components/media/image-thumbnail.ts
|
|
523453
|
-
/**
|
|
523454
|
-
* Transcript-side rendering of a pasted image.
|
|
523455
|
-
*
|
|
523456
|
-
* On terminals that speak the Kitty graphics protocol or iTerm2 inline
|
|
523457
|
-
* image protocol (detected by pi-tui's `getCapabilities()`), we show
|
|
523458
|
-
* the actual image. Everywhere else we fall back to a one-line text
|
|
523459
|
-
* marker matching the placeholder the user sees in the input box —
|
|
523460
|
-
* this keeps the transcript readable on Terminal.app / Linux default
|
|
523461
|
-
* terminals / `script` recordings without extra chrome.
|
|
523462
|
-
*
|
|
523463
|
-
* Height is capped at ~12 rows so a single screenshot can't monopolize
|
|
523464
|
-
* the viewport; pi-tui handles proportional scaling internally.
|
|
523465
|
-
*/
|
|
523466
|
-
const MAX_IMAGE_ROWS = 12;
|
|
523467
|
-
const MAX_IMAGE_WIDTH = 40;
|
|
523468
|
-
var ImageThumbnail = class extends Container {
|
|
523469
|
-
attachment;
|
|
523470
|
-
image;
|
|
523471
|
-
lastBuiltProtocol;
|
|
523472
|
-
constructor(attachment) {
|
|
523473
|
-
super();
|
|
523474
|
-
this.attachment = attachment;
|
|
523475
|
-
this.buildChildren();
|
|
523476
|
-
}
|
|
523477
|
-
buildChildren() {
|
|
523478
|
-
this.clear();
|
|
523479
|
-
const caps = getCapabilities();
|
|
523480
|
-
const supportsInline = caps.images === "kitty" || caps.images === "iterm2";
|
|
523481
|
-
this.lastBuiltProtocol = caps.images;
|
|
523482
|
-
if (!supportsInline) {
|
|
523483
|
-
this.addChild(new Text(currentTheme.fg("accent", this.attachment.placeholder), 0, 0));
|
|
523484
|
-
return;
|
|
523485
|
-
}
|
|
523486
|
-
const theme = { fallbackColor: (s) => currentTheme.fg("textDim", s) };
|
|
523487
|
-
this.image ??= new Image(Buffer.from(this.attachment.bytes).toString("base64"), this.attachment.mime, theme, {
|
|
523488
|
-
maxHeightCells: MAX_IMAGE_ROWS,
|
|
523489
|
-
maxWidthCells: MAX_IMAGE_WIDTH,
|
|
523490
|
-
filename: this.attachment.placeholder
|
|
523491
|
-
}, {
|
|
523492
|
-
widthPx: this.attachment.width,
|
|
523493
|
-
heightPx: this.attachment.height
|
|
523494
|
-
});
|
|
523495
|
-
this.image.invalidate();
|
|
523496
|
-
this.addChild(this.image);
|
|
523497
|
-
}
|
|
523498
|
-
render(width) {
|
|
523499
|
-
const safeWidth = Math.max(0, width);
|
|
523500
|
-
if (safeWidth === 0) return [""];
|
|
523501
|
-
if (safeWidth < MAX_IMAGE_WIDTH + 2) return new Text(currentTheme.fg("accent", this.attachment.placeholder), 0, 0).render(safeWidth);
|
|
523502
|
-
const caps = getCapabilities();
|
|
523503
|
-
if (this.lastBuiltProtocol !== caps.images) this.buildChildren();
|
|
523504
|
-
return super.render(safeWidth);
|
|
523505
|
-
}
|
|
523506
|
-
invalidate() {
|
|
523507
|
-
this.buildChildren();
|
|
523508
|
-
super.invalidate();
|
|
523509
|
-
}
|
|
523510
|
-
};
|
|
523511
|
-
//#endregion
|
|
523512
524309
|
//#region src/tui/components/messages/user-message.ts
|
|
523513
524310
|
/**
|
|
523514
524311
|
* Renders a user message in the transcript.
|
|
@@ -523613,6 +524410,14 @@ async function handleUndoCommand(host, args = "") {
|
|
|
523613
524410
|
await undoByCount(host, count);
|
|
523614
524411
|
}
|
|
523615
524412
|
async function undoByCount(host, count) {
|
|
524413
|
+
const finish = host.beginLocalContextMutation?.();
|
|
524414
|
+
try {
|
|
524415
|
+
return await undoByCountOwned(host, count);
|
|
524416
|
+
} finally {
|
|
524417
|
+
finish?.();
|
|
524418
|
+
}
|
|
524419
|
+
}
|
|
524420
|
+
async function undoByCountOwned(host, count) {
|
|
523616
524421
|
const session = host.session;
|
|
523617
524422
|
if (session === void 0) {
|
|
523618
524423
|
host.showError(uiText("undo.error.noActiveSession"));
|
|
@@ -532588,136 +533393,6 @@ var ClipboardImageHintController = class {
|
|
|
532588
533393
|
}
|
|
532589
533394
|
};
|
|
532590
533395
|
//#endregion
|
|
532591
|
-
//#region src/utils/image/image-mime.ts
|
|
532592
|
-
function parseImageMeta(bytes) {
|
|
532593
|
-
if (isPng(bytes)) return parsePng(bytes);
|
|
532594
|
-
if (isJpeg(bytes)) return parseJpeg(bytes);
|
|
532595
|
-
if (isGif(bytes)) return parseGif(bytes);
|
|
532596
|
-
if (isWebp(bytes)) return parseWebp(bytes);
|
|
532597
|
-
return null;
|
|
532598
|
-
}
|
|
532599
|
-
function isPng(b) {
|
|
532600
|
-
return b.length >= 8 && b[0] === 137 && b[1] === 80 && b[2] === 78 && b[3] === 71 && b[4] === 13 && b[5] === 10 && b[6] === 26 && b[7] === 10;
|
|
532601
|
-
}
|
|
532602
|
-
function parsePng(b) {
|
|
532603
|
-
if (b.length < 24) return null;
|
|
532604
|
-
const width = readUInt32BE(b, 16);
|
|
532605
|
-
const height = readUInt32BE(b, 20);
|
|
532606
|
-
if (width <= 0 || height <= 0) return null;
|
|
532607
|
-
return {
|
|
532608
|
-
mime: "image/png",
|
|
532609
|
-
width,
|
|
532610
|
-
height
|
|
532611
|
-
};
|
|
532612
|
-
}
|
|
532613
|
-
function isJpeg(b) {
|
|
532614
|
-
return b.length >= 3 && b[0] === 255 && b[1] === 216 && b[2] === 255;
|
|
532615
|
-
}
|
|
532616
|
-
function parseJpeg(b) {
|
|
532617
|
-
let i = 2;
|
|
532618
|
-
while (i < b.length) {
|
|
532619
|
-
if (b[i] !== 255) {
|
|
532620
|
-
i += 1;
|
|
532621
|
-
continue;
|
|
532622
|
-
}
|
|
532623
|
-
while (i < b.length && b[i] === 255) i += 1;
|
|
532624
|
-
if (i >= b.length) return null;
|
|
532625
|
-
const marker = b[i];
|
|
532626
|
-
i += 1;
|
|
532627
|
-
if (marker === 216 || marker === 217) continue;
|
|
532628
|
-
if (i + 1 >= b.length) return null;
|
|
532629
|
-
const segLen = readUInt16BE(b, i);
|
|
532630
|
-
if (isSofMarker(marker)) {
|
|
532631
|
-
if (i + 7 >= b.length) return null;
|
|
532632
|
-
const height = readUInt16BE(b, i + 3);
|
|
532633
|
-
const width = readUInt16BE(b, i + 5);
|
|
532634
|
-
if (width <= 0 || height <= 0) return null;
|
|
532635
|
-
return {
|
|
532636
|
-
mime: "image/jpeg",
|
|
532637
|
-
width,
|
|
532638
|
-
height
|
|
532639
|
-
};
|
|
532640
|
-
}
|
|
532641
|
-
i += segLen;
|
|
532642
|
-
}
|
|
532643
|
-
return null;
|
|
532644
|
-
}
|
|
532645
|
-
function isSofMarker(marker) {
|
|
532646
|
-
if (marker < 192 || marker > 207) return false;
|
|
532647
|
-
return marker !== 196 && marker !== 200 && marker !== 204;
|
|
532648
|
-
}
|
|
532649
|
-
function isGif(b) {
|
|
532650
|
-
return b.length >= 6 && b[0] === 71 && b[1] === 73 && b[2] === 70 && b[3] === 56 && (b[4] === 55 || b[4] === 57) && b[5] === 97;
|
|
532651
|
-
}
|
|
532652
|
-
function parseGif(b) {
|
|
532653
|
-
if (b.length < 10) return null;
|
|
532654
|
-
const width = readUInt16LE(b, 6);
|
|
532655
|
-
const height = readUInt16LE(b, 8);
|
|
532656
|
-
if (width <= 0 || height <= 0) return null;
|
|
532657
|
-
return {
|
|
532658
|
-
mime: "image/gif",
|
|
532659
|
-
width,
|
|
532660
|
-
height
|
|
532661
|
-
};
|
|
532662
|
-
}
|
|
532663
|
-
function isWebp(b) {
|
|
532664
|
-
return b.length >= 12 && b[0] === 82 && b[1] === 73 && b[2] === 70 && b[3] === 70 && b[8] === 87 && b[9] === 69 && b[10] === 66 && b[11] === 80;
|
|
532665
|
-
}
|
|
532666
|
-
function parseWebp(b) {
|
|
532667
|
-
if (b.length < 30) return null;
|
|
532668
|
-
const chunk = String.fromCodePoint(b[12], b[13], b[14], b[15]);
|
|
532669
|
-
if (chunk === "VP8 ") {
|
|
532670
|
-
const widthRaw = readUInt16LE(b, 26);
|
|
532671
|
-
const heightRaw = readUInt16LE(b, 28);
|
|
532672
|
-
const width = widthRaw & 16383;
|
|
532673
|
-
const height = heightRaw & 16383;
|
|
532674
|
-
if (width <= 0 || height <= 0) return null;
|
|
532675
|
-
return {
|
|
532676
|
-
mime: "image/webp",
|
|
532677
|
-
width,
|
|
532678
|
-
height
|
|
532679
|
-
};
|
|
532680
|
-
}
|
|
532681
|
-
if (chunk === "VP8L") {
|
|
532682
|
-
if (b[20] !== 47) return null;
|
|
532683
|
-
const b1 = b[21];
|
|
532684
|
-
const b2 = b[22];
|
|
532685
|
-
const b3 = b[23];
|
|
532686
|
-
const b4 = b[24];
|
|
532687
|
-
const width = 1 + ((b2 & 63) << 8 | b1);
|
|
532688
|
-
const height = 1 + ((b4 & 15) << 10 | b3 << 2 | (b2 & 192) >> 6);
|
|
532689
|
-
if (width <= 0 || height <= 0) return null;
|
|
532690
|
-
return {
|
|
532691
|
-
mime: "image/webp",
|
|
532692
|
-
width,
|
|
532693
|
-
height
|
|
532694
|
-
};
|
|
532695
|
-
}
|
|
532696
|
-
if (chunk === "VP8X") {
|
|
532697
|
-
const width = 1 + readUInt24LE(b, 24);
|
|
532698
|
-
const height = 1 + readUInt24LE(b, 27);
|
|
532699
|
-
if (width <= 0 || height <= 0) return null;
|
|
532700
|
-
return {
|
|
532701
|
-
mime: "image/webp",
|
|
532702
|
-
width,
|
|
532703
|
-
height
|
|
532704
|
-
};
|
|
532705
|
-
}
|
|
532706
|
-
return null;
|
|
532707
|
-
}
|
|
532708
|
-
function readUInt16BE(b, off) {
|
|
532709
|
-
return b[off] << 8 | b[off + 1];
|
|
532710
|
-
}
|
|
532711
|
-
function readUInt16LE(b, off) {
|
|
532712
|
-
return b[off] | b[off + 1] << 8;
|
|
532713
|
-
}
|
|
532714
|
-
function readUInt24LE(b, off) {
|
|
532715
|
-
return b[off] | b[off + 1] << 8 | b[off + 2] << 16;
|
|
532716
|
-
}
|
|
532717
|
-
function readUInt32BE(b, off) {
|
|
532718
|
-
return Math.trunc(b[off] * 16777216 + (b[off + 1] << 16) + (b[off + 2] << 8) + b[off + 3]);
|
|
532719
|
-
}
|
|
532720
|
-
//#endregion
|
|
532721
533396
|
//#region src/utils/clipboard/clipboard-image.ts
|
|
532722
533397
|
/**
|
|
532723
533398
|
* Read media from the system clipboard with graceful platform fallbacks.
|
|
@@ -535643,7 +536318,7 @@ function isTelegramBridgeFraming(value) {
|
|
|
535643
536318
|
let remaining = value.trim();
|
|
535644
536319
|
let foundFrame = false;
|
|
535645
536320
|
while (remaining.length > 0) {
|
|
535646
|
-
const frame = /^(?:\[(?:REPLY-PFLICHT|SEMANTISCHE ADRESSIERUNG|NUR MITLESEN|SPRACH-GATE)\b[\s\S]*?\]|<vision-observation\s+source="telegram"\b[^>]*>[\s\S]*?<\/vision-observation>)/i.exec(remaining);
|
|
536321
|
+
const frame = /^(?:\[GRUPPENANTWORT:[^[\]\r\n]*(?:\[\[BLUN_TELEGRAM_SILENT\]\][^[\]\r\n]*)*\]|\[(?:REPLY-PFLICHT|SEMANTISCHE ADRESSIERUNG|NUR MITLESEN|SPRACH-GATE)\b[\s\S]*?\]|<vision-observation\s+source="telegram"\b[^>]*>[\s\S]*?<\/vision-observation>)/i.exec(remaining);
|
|
535647
536322
|
if (frame === null) return false;
|
|
535648
536323
|
foundFrame = true;
|
|
535649
536324
|
remaining = remaining.slice(frame[0].length).trim();
|
|
@@ -536854,10 +537529,71 @@ var SessionEventHandler = class {
|
|
|
536854
537529
|
pendingCompactionRetry;
|
|
536855
537530
|
compactionRetryPanel;
|
|
536856
537531
|
localToolEvents;
|
|
537532
|
+
contextRefreshEpoch = 0;
|
|
537533
|
+
contextRefreshPending = false;
|
|
537534
|
+
contextRefreshRunning = false;
|
|
537535
|
+
contextRefreshTurnActive = false;
|
|
537536
|
+
contextRefreshFailed = false;
|
|
537537
|
+
localContextMutations = 0;
|
|
537538
|
+
contextRevisions = /* @__PURE__ */ new Map();
|
|
537539
|
+
beginLocalContextMutation() {
|
|
537540
|
+
const epoch = this.contextRefreshEpoch;
|
|
537541
|
+
this.localContextMutations++;
|
|
537542
|
+
let finished = false;
|
|
537543
|
+
return () => {
|
|
537544
|
+
if (finished) return;
|
|
537545
|
+
finished = true;
|
|
537546
|
+
if (epoch !== this.contextRefreshEpoch) return;
|
|
537547
|
+
this.localContextMutations--;
|
|
537548
|
+
this.drainContextRefresh();
|
|
537549
|
+
};
|
|
537550
|
+
}
|
|
537551
|
+
handleContextChanged(event) {
|
|
537552
|
+
if (event.agentId !== "main") return;
|
|
537553
|
+
const previous = this.contextRevisions.get(event.generation) ?? 0;
|
|
537554
|
+
if (event.revision < previous || event.revision === previous && !this.contextRefreshFailed) return;
|
|
537555
|
+
this.contextRevisions.delete(event.generation);
|
|
537556
|
+
this.contextRevisions.set(event.generation, event.revision);
|
|
537557
|
+
if (this.contextRevisions.size > 64) {
|
|
537558
|
+
const oldest = this.contextRevisions.keys().next().value;
|
|
537559
|
+
if (oldest !== void 0) this.contextRevisions.delete(oldest);
|
|
537560
|
+
}
|
|
537561
|
+
this.contextRefreshPending = true;
|
|
537562
|
+
this.drainContextRefresh();
|
|
537563
|
+
}
|
|
537564
|
+
drainContextRefresh() {
|
|
537565
|
+
const session = this.host.session;
|
|
537566
|
+
const refresh = this.host.refreshContextFromReplay;
|
|
537567
|
+
if (!this.contextRefreshPending || this.contextRefreshRunning || this.contextRefreshTurnActive || this.localContextMutations > 0 || session === void 0 || refresh === void 0) return;
|
|
537568
|
+
const epoch = this.contextRefreshEpoch;
|
|
537569
|
+
const isCurrent = () => epoch === this.contextRefreshEpoch && !this.host.aborted && this.host.session === session && this.host.state.appState.sessionId === session.id && this.localContextMutations === 0 && !this.contextRefreshPending && !this.contextRefreshTurnActive;
|
|
537570
|
+
this.contextRefreshPending = false;
|
|
537571
|
+
this.contextRefreshRunning = true;
|
|
537572
|
+
this.contextRefreshFailed = false;
|
|
537573
|
+
refresh.call(this.host, session, isCurrent).then((result) => {
|
|
537574
|
+
if (result === false && isCurrent()) this.contextRefreshFailed = true;
|
|
537575
|
+
}).catch((error) => {
|
|
537576
|
+
if (isCurrent()) {
|
|
537577
|
+
this.contextRefreshFailed = true;
|
|
537578
|
+
this.host.showError(formatErrorMessage$2(error));
|
|
537579
|
+
}
|
|
537580
|
+
}).finally(() => {
|
|
537581
|
+
if (epoch !== this.contextRefreshEpoch) return;
|
|
537582
|
+
this.contextRefreshRunning = false;
|
|
537583
|
+
this.drainContextRefresh();
|
|
537584
|
+
});
|
|
537585
|
+
}
|
|
536857
537586
|
setLocalToolEventRecordingEnabled(enabled) {
|
|
536858
537587
|
this.localToolEvents?.setEnabled(enabled);
|
|
536859
537588
|
}
|
|
536860
537589
|
resetRuntimeState() {
|
|
537590
|
+
this.contextRefreshEpoch++;
|
|
537591
|
+
this.contextRefreshPending = false;
|
|
537592
|
+
this.contextRefreshRunning = false;
|
|
537593
|
+
this.contextRefreshTurnActive = false;
|
|
537594
|
+
this.contextRefreshFailed = false;
|
|
537595
|
+
this.localContextMutations = 0;
|
|
537596
|
+
this.contextRevisions.clear();
|
|
536861
537597
|
this.backgroundTasks.clear();
|
|
536862
537598
|
this.backgroundTaskTranscriptedTerminal.clear();
|
|
536863
537599
|
this.subAgentEventHandler.resetRuntimeState();
|
|
@@ -536979,10 +537715,14 @@ var SessionEventHandler = class {
|
|
|
536979
537715
|
if ("turnId" in event && event.turnId !== void 0) this.host.streamingUI.setTurnId(String(event.turnId));
|
|
536980
537716
|
switch (event.type) {
|
|
536981
537717
|
case "turn.started":
|
|
537718
|
+
this.contextRefreshTurnActive = true;
|
|
537719
|
+
if (this.contextRefreshRunning) this.contextRefreshPending = true;
|
|
536982
537720
|
this.handleTurnBegin(event);
|
|
536983
537721
|
break;
|
|
536984
537722
|
case "turn.ended":
|
|
537723
|
+
this.contextRefreshTurnActive = false;
|
|
536985
537724
|
this.handleTurnEnd(event, sendQueued);
|
|
537725
|
+
this.drainContextRefresh();
|
|
536986
537726
|
break;
|
|
536987
537727
|
case "turn.step.started":
|
|
536988
537728
|
this.handleStepBegin(event);
|
|
@@ -537028,6 +537768,9 @@ var SessionEventHandler = class {
|
|
|
537028
537768
|
case "agent.status.updated":
|
|
537029
537769
|
this.handleStatusUpdate(event);
|
|
537030
537770
|
break;
|
|
537771
|
+
case "context.changed":
|
|
537772
|
+
this.handleContextChanged(event);
|
|
537773
|
+
break;
|
|
537031
537774
|
case "session.meta.updated":
|
|
537032
537775
|
this.handleSessionMetaChanged(event);
|
|
537033
537776
|
break;
|
|
@@ -537423,7 +538166,7 @@ var SessionEventHandler = class {
|
|
|
537423
538166
|
if (change.kind === "completion" && event.snapshot !== null) {
|
|
537424
538167
|
this.pendingModelBlockedFallback = void 0;
|
|
537425
538168
|
this.goalCompletionAwaitingClear = true;
|
|
537426
|
-
this.goalCompletionTurnEnded =
|
|
538169
|
+
this.goalCompletionTurnEnded = change.actor === "user" && state.appState.streamingPhase === "idle";
|
|
537427
538170
|
this.host.appendTranscriptEntry({
|
|
537428
538171
|
id: nextTranscriptId(),
|
|
537429
538172
|
kind: "assistant",
|
|
@@ -537495,7 +538238,7 @@ var SessionEventHandler = class {
|
|
|
537495
538238
|
this.scheduleQueuedGoalPromotion();
|
|
537496
538239
|
}
|
|
537497
538240
|
isReadyForQueuedGoalPromotion(session) {
|
|
537498
|
-
return (session === void 0 || this.host.session === session) && !this.host.aborted && this.host.state.appState.streamingPhase === "idle" && this.host.state.queuedMessages.length === 0;
|
|
538241
|
+
return (session === void 0 || this.host.session === session) && !this.host.aborted && this.host.state.appState.streamingPhase === "idle" && !this.host.state.appState.isCompacting && this.host.state.queuedMessages.length === 0;
|
|
537499
538242
|
}
|
|
537500
538243
|
async promoteNextQueuedGoal() {
|
|
537501
538244
|
const { host } = this;
|
|
@@ -538100,6 +538843,14 @@ var SessionReplayRenderer = class {
|
|
|
538100
538843
|
constructor(host) {
|
|
538101
538844
|
this.host = host;
|
|
538102
538845
|
}
|
|
538846
|
+
async refreshFromReplay(session, isCurrent, clearTranscript, historyLimit = 200) {
|
|
538847
|
+
if (!isCurrent()) return false;
|
|
538848
|
+
await session.refreshResumeState({ historyLimit });
|
|
538849
|
+
if (!isCurrent()) return false;
|
|
538850
|
+
if (session.getResumeState()?.agents["main"] === void 0) return this.hydrateFromReplay(session);
|
|
538851
|
+
clearTranscript();
|
|
538852
|
+
return this.hydrateFromReplay(session);
|
|
538853
|
+
}
|
|
538103
538854
|
/** Records-only projection for a detached page; never hydrates the live snapshot. */
|
|
538104
538855
|
renderHistoricalPage(agent) {
|
|
538105
538856
|
this.renderRecords(agent);
|
|
@@ -539408,7 +540159,8 @@ function contextMetrics(state) {
|
|
|
539408
540159
|
const responder = state.availableModels[responderAlias];
|
|
539409
540160
|
const responderMax = responder === void 0 ? void 0 : effectiveModelAlias(responder).maxContextSize;
|
|
539410
540161
|
const runtimeMax = Number.isFinite(state.maxContextTokens) ? Math.max(0, state.maxContextTokens) : 0;
|
|
539411
|
-
const
|
|
540162
|
+
const hardMaxTokens = runtimeMax > 0 ? runtimeMax : responderMax ?? 0;
|
|
540163
|
+
const maxTokens = Number.isFinite(hardMaxTokens) && hardMaxTokens > 0 ? hardMaxTokens : 0;
|
|
539412
540164
|
return {
|
|
539413
540165
|
tokens,
|
|
539414
540166
|
maxTokens,
|
|
@@ -543080,9 +543832,12 @@ function isGroupNoiseReply(text) {
|
|
|
543080
543832
|
function isGroupSuppressed(text, _contextOnly) {
|
|
543081
543833
|
return isGroupNoiseReply(text);
|
|
543082
543834
|
}
|
|
543835
|
+
function isSilentTurnMarker(text) {
|
|
543836
|
+
return text.trim() === "[[BLUN_TELEGRAM_SILENT]]";
|
|
543837
|
+
}
|
|
543083
543838
|
async function sendReplyFallback(chatId, text, contextOnly = false, requireDelivery = false, progress, threadId) {
|
|
543084
543839
|
if (threadId !== void 0 && !validChannelThreadId(threadId)) return false;
|
|
543085
|
-
if (text
|
|
543840
|
+
if (isSilentTurnMarker(text)) return !requireDelivery;
|
|
543086
543841
|
const topic = threadId === void 0 ? {} : { message_thread_id: Number(threadId) };
|
|
543087
543842
|
if (isGroupChat(chatId) && isGroupSuppressed(text, contextOnly)) {
|
|
543088
543843
|
try {
|
|
@@ -545770,7 +546525,7 @@ var BlunTUI = class {
|
|
|
545770
546525
|
})) return;
|
|
545771
546526
|
if (outboxGrewForChat(guard.outboxMarker, guard.chatId, guard.threadId)) return;
|
|
545772
546527
|
const finalText = this.state.transcriptEntries.slice(guard.transcriptStart).filter((entry) => entry.kind === "assistant" && entry.content.trim().length > 0).map((entry) => entry.content.trim()).at(-1) ?? "";
|
|
545773
|
-
if (finalText.length === 0) return;
|
|
546528
|
+
if (finalText.length === 0 || isSilentTurnMarker(finalText)) return;
|
|
545774
546529
|
(guard.threadId === void 0 ? sendReplyFallback(guard.chatId, finalText, guard.contextOnly) : sendReplyFallback(guard.chatId, finalText, guard.contextOnly, false, void 0, guard.threadId)).then((sent) => {
|
|
545775
546530
|
if (sent) this.showStatus(uiText("blunTui.telegram.fallbackDelivered"));
|
|
545776
546531
|
});
|
|
@@ -546719,6 +547474,14 @@ var BlunTUI = class {
|
|
|
546719
547474
|
mergeSteps: (state) => this.mergeAllTurnSteps(state)
|
|
546720
547475
|
});
|
|
546721
547476
|
}
|
|
547477
|
+
beginLocalContextMutation() {
|
|
547478
|
+
return this.sessionEventHandler.beginLocalContextMutation();
|
|
547479
|
+
}
|
|
547480
|
+
async refreshContextFromReplay(session, isCurrent) {
|
|
547481
|
+
return this.sessionReplay.refreshFromReplay(session, isCurrent, () => {
|
|
547482
|
+
this.clearTranscriptAndRedraw();
|
|
547483
|
+
}, this.historyLimit);
|
|
547484
|
+
}
|
|
546722
547485
|
createTranscriptComponent(entry, state = this.state) {
|
|
546723
547486
|
if (entry.compactionData !== void 0) {
|
|
546724
547487
|
const data = entry.compactionData;
|