blun-king-cli 9.1.613 → 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 +14 -0
- package/LIESMICH.txt +1 -1
- package/README.md +1 -1
- package/agent-spine-plugin/src/lib/documents.js +1 -1
- package/agent-spine-plugin/src/lib/hook-context.js +1 -0
- package/agent-spine-plugin/src/lib/host-instruction-budget.js +1 -2
- package/agent-spine-plugin/src/lib/preflight.js +16 -5
- package/agent-spine-plugin/src/lib/source-roots.js +1 -1
- package/blun.mjs +1927 -1011
- package/bundled-agent-sources.json +5 -5
- 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 +1215 -600
package/worker-host.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);
|
|
@@ -14,13 +14,14 @@ import { Blob as Blob$1, File as File$1 } from "node:buffer";
|
|
|
14
14
|
import fs, { access, appendFile, chmod, copyFile, cp, link, lstat, mkdir, mkdtemp, open, readFile, readdir, readlink, realpath, rename, rm, rmdir, stat, unlink, writeFile } from "node:fs/promises";
|
|
15
15
|
import * as nodeOs from "node:os";
|
|
16
16
|
import os, { arch, homedir, hostname, release, tmpdir, type, userInfo } from "node:os";
|
|
17
|
-
import { execFile, execFileSync, spawn
|
|
17
|
+
import { execFile, execFileSync, spawn } from "node:child_process";
|
|
18
18
|
import { Worker } from "node:worker_threads";
|
|
19
19
|
import * as sysPath from "path";
|
|
20
20
|
import path$1, { dirname as dirname$1, parse as parse$1 } from "path";
|
|
21
21
|
import I, { existsSync as existsSync$1, promises as promises$1, stat as stat$1, unwatchFile, watch, watchFile } from "fs";
|
|
22
22
|
import zi from "assert";
|
|
23
23
|
import Qr, { EventEmitter } from "events";
|
|
24
|
+
import { StringDecoder } from "node:string_decoder";
|
|
24
25
|
import { lstat as lstat$1, open as open$1, readdir as readdir$1, realpath as realpath$1, stat as stat$2 } from "fs/promises";
|
|
25
26
|
import Cs, { PassThrough, Readable, pipeline } from "node:stream";
|
|
26
27
|
import { type as type$1 } from "os";
|
|
@@ -35,7 +36,6 @@ import * as win32Path from "node:path/win32";
|
|
|
35
36
|
import { createServer } from "node:http";
|
|
36
37
|
import { pipeline as pipeline$1 } from "node:stream/promises";
|
|
37
38
|
import { EventEmitter as EventEmitter$1 } from "node:events";
|
|
38
|
-
import { StringDecoder } from "node:string_decoder";
|
|
39
39
|
import co from "node:assert";
|
|
40
40
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
41
41
|
import { QuickJSAsyncWASMModule, RELEASE_ASYNC, newQuickJSAsyncWASMModule, shouldInterruptAfterDeadline } from "quickjs-emscripten";
|
|
@@ -2687,12 +2687,22 @@ function collectBlunVisionAttachments(messages) {
|
|
|
2687
2687
|
}
|
|
2688
2688
|
return attachments;
|
|
2689
2689
|
}
|
|
2690
|
-
function
|
|
2691
|
-
const
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
};
|
|
2690
|
+
function estimateBlunSerializedBodyBytes(systemPrompt, tools, history) {
|
|
2691
|
+
const normalizedHistory = normalizeToolCallIdsForProvider([...history], BLUN_TOOL_CALL_ID_POLICY);
|
|
2692
|
+
const messages = systemPrompt ? [{
|
|
2693
|
+
role: "system",
|
|
2694
|
+
content: systemPrompt
|
|
2695
|
+
}] : [];
|
|
2696
|
+
for (const message of normalizedHistory) if (!isEmptyAssistantHistoryMessage(message)) messages.push(convertMessage(message));
|
|
2697
|
+
const attachments = collectBlunVisionAttachments(normalizedHistory);
|
|
2698
|
+
return Buffer.byteLength(JSON.stringify({
|
|
2699
|
+
model: "king",
|
|
2700
|
+
messages,
|
|
2701
|
+
stream: true,
|
|
2702
|
+
...tools.length > 0 ? { tools: tools.map(convertTool) } : {},
|
|
2703
|
+
...attachments.length > 0 ? { visionAttachments: attachments } : {},
|
|
2704
|
+
stream_options: { include_usage: true }
|
|
2705
|
+
}), "utf8");
|
|
2696
2706
|
}
|
|
2697
2707
|
function convertMessage(message) {
|
|
2698
2708
|
let reasoningContent = "";
|
|
@@ -21766,6 +21776,31 @@ var InstructionText = class InstructionText {
|
|
|
21766
21776
|
get content() {
|
|
21767
21777
|
return this.pieces.map((piece) => piece.text).join("");
|
|
21768
21778
|
}
|
|
21779
|
+
prefixUtf8(maxBytes) {
|
|
21780
|
+
if (!Number.isSafeInteger(maxBytes) || maxBytes < 0) throw new RangeError("Invalid instruction byte budget");
|
|
21781
|
+
const kept = [];
|
|
21782
|
+
let remaining = maxBytes;
|
|
21783
|
+
let totalBytes = 0;
|
|
21784
|
+
let readBytes = 0;
|
|
21785
|
+
for (const piece of this.pieces) {
|
|
21786
|
+
const encoded = Buffer.from(piece.text, "utf8");
|
|
21787
|
+
totalBytes += encoded.length;
|
|
21788
|
+
if (remaining <= 0) continue;
|
|
21789
|
+
const content = encoded.length <= remaining ? piece.text : new StringDecoder("utf8").write(encoded.subarray(0, remaining));
|
|
21790
|
+
const bytes = Buffer.byteLength(content, "utf8");
|
|
21791
|
+
if (content.length > 0) kept.push({
|
|
21792
|
+
...piece,
|
|
21793
|
+
text: content
|
|
21794
|
+
});
|
|
21795
|
+
readBytes += bytes;
|
|
21796
|
+
remaining -= bytes;
|
|
21797
|
+
if (bytes < encoded.length) remaining = 0;
|
|
21798
|
+
}
|
|
21799
|
+
return {
|
|
21800
|
+
text: new InstructionText(kept, new Map(this.sources)),
|
|
21801
|
+
omittedBytes: totalBytes - readBytes
|
|
21802
|
+
};
|
|
21803
|
+
}
|
|
21769
21804
|
replaceFirst(needle, replacement) {
|
|
21770
21805
|
const start = this.content.indexOf(needle);
|
|
21771
21806
|
if (start >= 0) this.replaceRange(start, start + needle.length, replacement);
|
|
@@ -21823,6 +21858,64 @@ const IMPORT_MAX_DEPTH = 4;
|
|
|
21823
21858
|
const IMPORT_LINE_RE = /^@import\s+(.+)$/gm;
|
|
21824
21859
|
const S_IFMT$4 = 61440;
|
|
21825
21860
|
const S_IFREG$2 = 32768;
|
|
21861
|
+
function fitAgentsMdContext(context, maxFixedRequestBytes, measureFixedRequestBytes) {
|
|
21862
|
+
if (!Number.isSafeInteger(maxFixedRequestBytes) || maxFixedRequestBytes <= 0) throw new RangeError("Invalid fixed request byte budget");
|
|
21863
|
+
const originalBytes = measureFixedRequestBytes(context);
|
|
21864
|
+
if (originalBytes <= maxFixedRequestBytes) return {
|
|
21865
|
+
context,
|
|
21866
|
+
fixedRequestBytes: originalBytes,
|
|
21867
|
+
omittedBytes: 0,
|
|
21868
|
+
fits: true
|
|
21869
|
+
};
|
|
21870
|
+
const source = context.agentsMdText;
|
|
21871
|
+
if (source === void 0) return {
|
|
21872
|
+
context,
|
|
21873
|
+
fixedRequestBytes: originalBytes,
|
|
21874
|
+
omittedBytes: 0,
|
|
21875
|
+
fits: false
|
|
21876
|
+
};
|
|
21877
|
+
const totalBytes = source.measure().totalBytes;
|
|
21878
|
+
const candidateAt = (maxBytes) => {
|
|
21879
|
+
const { text } = source.prefixUtf8(maxBytes);
|
|
21880
|
+
return {
|
|
21881
|
+
...context,
|
|
21882
|
+
agentsMd: text.content,
|
|
21883
|
+
agentsMdSources: text.measure(),
|
|
21884
|
+
agentsMdText: text
|
|
21885
|
+
};
|
|
21886
|
+
};
|
|
21887
|
+
let low = 0;
|
|
21888
|
+
let high = totalBytes;
|
|
21889
|
+
let fitted = candidateAt(0);
|
|
21890
|
+
let fittedBytes = measureFixedRequestBytes(fitted);
|
|
21891
|
+
if (fittedBytes > maxFixedRequestBytes) {
|
|
21892
|
+
const omittedBytes = context.agentsMdSources?.files.reduce((sum, file) => sum + file.bytes, 0) ?? totalBytes;
|
|
21893
|
+
return {
|
|
21894
|
+
context: fitted,
|
|
21895
|
+
fixedRequestBytes: fittedBytes,
|
|
21896
|
+
omittedBytes,
|
|
21897
|
+
fits: false
|
|
21898
|
+
};
|
|
21899
|
+
}
|
|
21900
|
+
while (low < high) {
|
|
21901
|
+
const middle = Math.ceil((low + high) / 2);
|
|
21902
|
+
const candidate = candidateAt(middle);
|
|
21903
|
+
const bytes = measureFixedRequestBytes(candidate);
|
|
21904
|
+
if (bytes <= maxFixedRequestBytes) {
|
|
21905
|
+
low = middle;
|
|
21906
|
+
fitted = candidate;
|
|
21907
|
+
fittedBytes = bytes;
|
|
21908
|
+
} else high = middle - 1;
|
|
21909
|
+
}
|
|
21910
|
+
const omittedBytes = context.agentsMdSources?.files.reduce((sum, file) => sum + file.bytes, 0) ?? totalBytes;
|
|
21911
|
+
const retainedBytes = fitted.agentsMdSources?.files.reduce((sum, file) => sum + file.bytes, 0) ?? 0;
|
|
21912
|
+
return {
|
|
21913
|
+
context: fitted,
|
|
21914
|
+
fixedRequestBytes: fittedBytes,
|
|
21915
|
+
omittedBytes: omittedBytes - retainedBytes,
|
|
21916
|
+
fits: true
|
|
21917
|
+
};
|
|
21918
|
+
}
|
|
21826
21919
|
async function prepareSystemPromptContext(kaos, brandHome, options) {
|
|
21827
21920
|
const additionalDirs = normalizeAdditionalDirs(options?.additionalDirs ?? []);
|
|
21828
21921
|
const [cwdListing, agentsMdResult, additionalDirsInfo] = await Promise.all([
|
|
@@ -21835,7 +21928,8 @@ async function prepareSystemPromptContext(kaos, brandHome, options) {
|
|
|
21835
21928
|
agentsMd: agentsMdResult.content,
|
|
21836
21929
|
additionalDirsInfo,
|
|
21837
21930
|
agentsMdWarning: agentsMdResult.warning,
|
|
21838
|
-
agentsMdSources: agentsMdResult.sources
|
|
21931
|
+
agentsMdSources: agentsMdResult.sources,
|
|
21932
|
+
agentsMdText: agentsMdResult.text
|
|
21839
21933
|
};
|
|
21840
21934
|
}
|
|
21841
21935
|
async function loadAgentsMd(kaos, brandHome) {
|
|
@@ -21889,6 +21983,7 @@ async function loadAgentsMdForRoots(kaos, brandHome, workDirs) {
|
|
|
21889
21983
|
return {
|
|
21890
21984
|
content,
|
|
21891
21985
|
warning: totalBytes > AGENTS_MD_RECOMMENDED_MAX_BYTES ? `AGENTS.md total ${formatKB(totalBytes)} KB exceeds the recommended ${formatKB(AGENTS_MD_RECOMMENDED_MAX_BYTES)} KB. Large instruction files increase cost and may impact performance; consider trimming.` : void 0,
|
|
21986
|
+
text: rendered,
|
|
21892
21987
|
sources: {
|
|
21893
21988
|
...rendered.measure(),
|
|
21894
21989
|
...notLoadedCandidates.size === 0 ? {} : { notLoadedCandidates: [...notLoadedCandidates] }
|
|
@@ -180764,6 +180859,10 @@ var GoalMode = class {
|
|
|
180764
180859
|
restoreUpdate(record) {
|
|
180765
180860
|
const state = this.state;
|
|
180766
180861
|
if (state === void 0) return;
|
|
180862
|
+
if (record.objective !== void 0) {
|
|
180863
|
+
state.objective = record.objective;
|
|
180864
|
+
this.lifecycleRevision += 1;
|
|
180865
|
+
}
|
|
180767
180866
|
const status = record.status;
|
|
180768
180867
|
if (status !== void 0) {
|
|
180769
180868
|
this.lifecycleRevision += 1;
|
|
@@ -180778,7 +180877,17 @@ var GoalMode = class {
|
|
|
180778
180877
|
state.wallClockResumedAt = void 0;
|
|
180779
180878
|
}
|
|
180780
180879
|
if (record.budgetLimits !== void 0) state.budgetLimits = record.budgetLimits;
|
|
180781
|
-
if (status === void 0)
|
|
180880
|
+
if (status === void 0) {
|
|
180881
|
+
if (record.objective !== void 0) this.agent.replayBuilder.push({
|
|
180882
|
+
type: "goal_updated",
|
|
180883
|
+
snapshot: this.toSnapshot(state),
|
|
180884
|
+
change: {
|
|
180885
|
+
kind: "edited",
|
|
180886
|
+
actor: record.actor
|
|
180887
|
+
}
|
|
180888
|
+
});
|
|
180889
|
+
return;
|
|
180890
|
+
}
|
|
180782
180891
|
this.agent.replayBuilder.push({
|
|
180783
180892
|
type: "goal_updated",
|
|
180784
180893
|
snapshot: this.toSnapshot(state),
|
|
@@ -180822,11 +180931,11 @@ var GoalMode = class {
|
|
|
180822
180931
|
if (objective.length === 0) throw new BlunError(ErrorCodes.GOAL_OBJECTIVE_EMPTY, "Goal objective cannot be empty");
|
|
180823
180932
|
if (objective.length > MAX_GOAL_OBJECTIVE_LENGTH) throw new BlunError(ErrorCodes.GOAL_OBJECTIVE_TOO_LONG, `Goal objective cannot exceed ${MAX_GOAL_OBJECTIVE_LENGTH} characters`);
|
|
180824
180933
|
const verificationScope = normalizeVerificationScope(input.verificationScope);
|
|
180934
|
+
const completionCriterion = normalizeCompletionCriterion(input.completionCriterion);
|
|
180825
180935
|
if (this.state !== void 0) {
|
|
180826
180936
|
if (input.replace !== true) throw new BlunError(ErrorCodes.GOAL_ALREADY_EXISTS, "A goal already exists; use replace to start a new one");
|
|
180827
180937
|
this.clearInternal("system");
|
|
180828
180938
|
}
|
|
180829
|
-
const completionCriterion = normalizeCompletionCriterion(input.completionCriterion);
|
|
180830
180939
|
const state = {
|
|
180831
180940
|
goalId: randomUUID(),
|
|
180832
180941
|
objective,
|
|
@@ -180850,6 +180959,35 @@ var GoalMode = class {
|
|
|
180850
180959
|
this.trackGoalCreated(actor, input.replace === true);
|
|
180851
180960
|
return this.toSnapshot(state);
|
|
180852
180961
|
}
|
|
180962
|
+
async completeGoal() {
|
|
180963
|
+
const state = this.requireState();
|
|
180964
|
+
if (state.status !== "active") throw new BlunError(ErrorCodes.GOAL_STATUS_INVALID, `Cannot complete a goal in status "${state.status}"`);
|
|
180965
|
+
return this.markComplete({}, "user");
|
|
180966
|
+
}
|
|
180967
|
+
async blockGoal(input = {}) {
|
|
180968
|
+
const state = this.requireState();
|
|
180969
|
+
if (state.status === "blocked") return this.toSnapshot(state);
|
|
180970
|
+
if (state.status !== "active") throw new BlunError(ErrorCodes.GOAL_STATUS_INVALID, `Cannot block a goal in status "${state.status}"`);
|
|
180971
|
+
return await this.markBlocked(input, "user");
|
|
180972
|
+
}
|
|
180973
|
+
async editGoal(input, actor = "user") {
|
|
180974
|
+
const state = this.requireState();
|
|
180975
|
+
const objective = input.objective.trim();
|
|
180976
|
+
if (objective.length === 0) throw new BlunError(ErrorCodes.GOAL_OBJECTIVE_EMPTY, "Goal objective cannot be empty");
|
|
180977
|
+
if (objective.length > MAX_GOAL_OBJECTIVE_LENGTH) throw new BlunError(ErrorCodes.GOAL_OBJECTIVE_TOO_LONG, `Goal objective cannot exceed ${MAX_GOAL_OBJECTIVE_LENGTH} characters`);
|
|
180978
|
+
if (objective === state.objective) return this.toSnapshot(state);
|
|
180979
|
+
state.objective = objective;
|
|
180980
|
+
this.lifecycleRevision += 1;
|
|
180981
|
+
this.appendGoalUpdate({
|
|
180982
|
+
objective,
|
|
180983
|
+
actor
|
|
180984
|
+
});
|
|
180985
|
+
this.persistState(state, { change: {
|
|
180986
|
+
kind: "edited",
|
|
180987
|
+
actor
|
|
180988
|
+
} });
|
|
180989
|
+
return this.toSnapshot(state);
|
|
180990
|
+
}
|
|
180853
180991
|
async pauseGoal(input = {}, actor = "user") {
|
|
180854
180992
|
const state = this.requireState();
|
|
180855
180993
|
if (state.status === "paused") return this.toSnapshot(state);
|
|
@@ -181619,6 +181757,613 @@ var ProviderRetryWait = class {
|
|
|
181619
181757
|
}
|
|
181620
181758
|
}
|
|
181621
181759
|
};
|
|
181760
|
+
const IMAGE_MIME_BY_SUFFIX = Object.freeze({
|
|
181761
|
+
".png": "image/png",
|
|
181762
|
+
".jpg": "image/jpeg",
|
|
181763
|
+
".jpeg": "image/jpeg",
|
|
181764
|
+
".gif": "image/gif",
|
|
181765
|
+
".bmp": "image/bmp",
|
|
181766
|
+
".tif": "image/tiff",
|
|
181767
|
+
".tiff": "image/tiff",
|
|
181768
|
+
".webp": "image/webp",
|
|
181769
|
+
".ico": "image/x-icon",
|
|
181770
|
+
".heic": "image/heic",
|
|
181771
|
+
".heif": "image/heif",
|
|
181772
|
+
".avif": "image/avif",
|
|
181773
|
+
".svgz": "image/svg+xml"
|
|
181774
|
+
});
|
|
181775
|
+
const VIDEO_MIME_BY_SUFFIX = Object.freeze({
|
|
181776
|
+
".mp4": "video/mp4",
|
|
181777
|
+
".mpg": "video/mpeg",
|
|
181778
|
+
".mpeg": "video/mpeg",
|
|
181779
|
+
".mkv": "video/x-matroska",
|
|
181780
|
+
".avi": "video/x-msvideo",
|
|
181781
|
+
".mov": "video/quicktime",
|
|
181782
|
+
".ogv": "video/ogg",
|
|
181783
|
+
".wmv": "video/x-ms-wmv",
|
|
181784
|
+
".webm": "video/webm",
|
|
181785
|
+
".m4v": "video/x-m4v",
|
|
181786
|
+
".flv": "video/x-flv",
|
|
181787
|
+
".3gp": "video/3gpp",
|
|
181788
|
+
".3g2": "video/3gpp2"
|
|
181789
|
+
});
|
|
181790
|
+
const TEXT_MIME_BY_SUFFIX = Object.freeze({ ".svg": "image/svg+xml" });
|
|
181791
|
+
const NON_TEXT_SUFFIXES = new Set([
|
|
181792
|
+
".icns",
|
|
181793
|
+
".psd",
|
|
181794
|
+
".ai",
|
|
181795
|
+
".eps",
|
|
181796
|
+
".pdf",
|
|
181797
|
+
".doc",
|
|
181798
|
+
".docx",
|
|
181799
|
+
".dot",
|
|
181800
|
+
".dotx",
|
|
181801
|
+
".rtf",
|
|
181802
|
+
".odt",
|
|
181803
|
+
".xls",
|
|
181804
|
+
".xlsx",
|
|
181805
|
+
".xlsm",
|
|
181806
|
+
".xlt",
|
|
181807
|
+
".xltx",
|
|
181808
|
+
".xltm",
|
|
181809
|
+
".ods",
|
|
181810
|
+
".ppt",
|
|
181811
|
+
".pptx",
|
|
181812
|
+
".pptm",
|
|
181813
|
+
".pps",
|
|
181814
|
+
".ppsx",
|
|
181815
|
+
".odp",
|
|
181816
|
+
".pages",
|
|
181817
|
+
".numbers",
|
|
181818
|
+
".key",
|
|
181819
|
+
".zip",
|
|
181820
|
+
".rar",
|
|
181821
|
+
".7z",
|
|
181822
|
+
".tar",
|
|
181823
|
+
".gz",
|
|
181824
|
+
".tgz",
|
|
181825
|
+
".bz2",
|
|
181826
|
+
".xz",
|
|
181827
|
+
".zst",
|
|
181828
|
+
".lz",
|
|
181829
|
+
".lz4",
|
|
181830
|
+
".br",
|
|
181831
|
+
".cab",
|
|
181832
|
+
".ar",
|
|
181833
|
+
".deb",
|
|
181834
|
+
".rpm",
|
|
181835
|
+
".mp3",
|
|
181836
|
+
".wav",
|
|
181837
|
+
".flac",
|
|
181838
|
+
".ogg",
|
|
181839
|
+
".oga",
|
|
181840
|
+
".opus",
|
|
181841
|
+
".aac",
|
|
181842
|
+
".m4a",
|
|
181843
|
+
".wma",
|
|
181844
|
+
".ttf",
|
|
181845
|
+
".otf",
|
|
181846
|
+
".woff",
|
|
181847
|
+
".woff2",
|
|
181848
|
+
".exe",
|
|
181849
|
+
".dll",
|
|
181850
|
+
".so",
|
|
181851
|
+
".dylib",
|
|
181852
|
+
".bin",
|
|
181853
|
+
".apk",
|
|
181854
|
+
".ipa",
|
|
181855
|
+
".jar",
|
|
181856
|
+
".class",
|
|
181857
|
+
".pyc",
|
|
181858
|
+
".pyo",
|
|
181859
|
+
".wasm",
|
|
181860
|
+
".dmg",
|
|
181861
|
+
".iso",
|
|
181862
|
+
".img",
|
|
181863
|
+
".sqlite",
|
|
181864
|
+
".sqlite3",
|
|
181865
|
+
".db",
|
|
181866
|
+
".db3"
|
|
181867
|
+
]);
|
|
181868
|
+
const ASF_HEADER = Buffer.from([
|
|
181869
|
+
48,
|
|
181870
|
+
38,
|
|
181871
|
+
178,
|
|
181872
|
+
117,
|
|
181873
|
+
142,
|
|
181874
|
+
102,
|
|
181875
|
+
207,
|
|
181876
|
+
17,
|
|
181877
|
+
166,
|
|
181878
|
+
217,
|
|
181879
|
+
0,
|
|
181880
|
+
170,
|
|
181881
|
+
0,
|
|
181882
|
+
98,
|
|
181883
|
+
206,
|
|
181884
|
+
108
|
|
181885
|
+
]);
|
|
181886
|
+
const FTYP_IMAGE_BRANDS = Object.freeze({
|
|
181887
|
+
avif: "image/avif",
|
|
181888
|
+
avis: "image/avif",
|
|
181889
|
+
heic: "image/heic",
|
|
181890
|
+
heif: "image/heif",
|
|
181891
|
+
heix: "image/heif",
|
|
181892
|
+
hevc: "image/heic",
|
|
181893
|
+
mif1: "image/heif",
|
|
181894
|
+
msf1: "image/heif"
|
|
181895
|
+
});
|
|
181896
|
+
const FTYP_VIDEO_BRANDS = Object.freeze({
|
|
181897
|
+
isom: "video/mp4",
|
|
181898
|
+
iso2: "video/mp4",
|
|
181899
|
+
iso5: "video/mp4",
|
|
181900
|
+
mp41: "video/mp4",
|
|
181901
|
+
mp42: "video/mp4",
|
|
181902
|
+
avc1: "video/mp4",
|
|
181903
|
+
mp4v: "video/mp4",
|
|
181904
|
+
m4v: "video/x-m4v",
|
|
181905
|
+
qt: "video/quicktime",
|
|
181906
|
+
"3gp4": "video/3gpp",
|
|
181907
|
+
"3gp5": "video/3gpp",
|
|
181908
|
+
"3gp6": "video/3gpp",
|
|
181909
|
+
"3gp7": "video/3gpp",
|
|
181910
|
+
"3g2": "video/3gpp2"
|
|
181911
|
+
});
|
|
181912
|
+
function toBuffer(data) {
|
|
181913
|
+
return Buffer.isBuffer(data) ? data : Buffer.from(data.buffer, data.byteOffset, data.byteLength);
|
|
181914
|
+
}
|
|
181915
|
+
function startsWith(buf, prefix) {
|
|
181916
|
+
const needle = Buffer.isBuffer(prefix) ? prefix : Buffer.from(prefix);
|
|
181917
|
+
if (buf.length < needle.length) return false;
|
|
181918
|
+
for (let i = 0; i < needle.length; i += 1) if (buf[i] !== needle[i]) return false;
|
|
181919
|
+
return true;
|
|
181920
|
+
}
|
|
181921
|
+
function sniffFtypBrand(header) {
|
|
181922
|
+
if (header.length < 12) return null;
|
|
181923
|
+
if (header.subarray(4, 8).toString("latin1") !== "ftyp") return null;
|
|
181924
|
+
return header.subarray(8, 12).toString("latin1").toLowerCase().replaceAll(/[\s\u0000]+$/g, "").trim();
|
|
181925
|
+
}
|
|
181926
|
+
function sniffMediaFromMagic(data) {
|
|
181927
|
+
const buf = toBuffer(data);
|
|
181928
|
+
const header = buf.length > 512 ? buf.subarray(0, 512) : buf;
|
|
181929
|
+
if (startsWith(header, [
|
|
181930
|
+
137,
|
|
181931
|
+
80,
|
|
181932
|
+
78,
|
|
181933
|
+
71,
|
|
181934
|
+
13,
|
|
181935
|
+
10,
|
|
181936
|
+
26,
|
|
181937
|
+
10
|
|
181938
|
+
])) return {
|
|
181939
|
+
kind: "image",
|
|
181940
|
+
mimeType: "image/png"
|
|
181941
|
+
};
|
|
181942
|
+
if (startsWith(header, [
|
|
181943
|
+
255,
|
|
181944
|
+
216,
|
|
181945
|
+
255
|
|
181946
|
+
])) return {
|
|
181947
|
+
kind: "image",
|
|
181948
|
+
mimeType: "image/jpeg"
|
|
181949
|
+
};
|
|
181950
|
+
if (startsWith(header, Buffer.from("GIF87a")) || startsWith(header, Buffer.from("GIF89a"))) return {
|
|
181951
|
+
kind: "image",
|
|
181952
|
+
mimeType: "image/gif"
|
|
181953
|
+
};
|
|
181954
|
+
if (startsWith(header, Buffer.from("BM"))) return {
|
|
181955
|
+
kind: "image",
|
|
181956
|
+
mimeType: "image/bmp"
|
|
181957
|
+
};
|
|
181958
|
+
if (startsWith(header, [
|
|
181959
|
+
73,
|
|
181960
|
+
73,
|
|
181961
|
+
42,
|
|
181962
|
+
0
|
|
181963
|
+
]) || startsWith(header, [
|
|
181964
|
+
77,
|
|
181965
|
+
77,
|
|
181966
|
+
0,
|
|
181967
|
+
42
|
|
181968
|
+
])) return {
|
|
181969
|
+
kind: "image",
|
|
181970
|
+
mimeType: "image/tiff"
|
|
181971
|
+
};
|
|
181972
|
+
if (startsWith(header, [
|
|
181973
|
+
0,
|
|
181974
|
+
0,
|
|
181975
|
+
1,
|
|
181976
|
+
0
|
|
181977
|
+
])) return {
|
|
181978
|
+
kind: "image",
|
|
181979
|
+
mimeType: "image/x-icon"
|
|
181980
|
+
};
|
|
181981
|
+
if (startsWith(header, Buffer.from("RIFF")) && header.length >= 12) {
|
|
181982
|
+
const chunk = header.subarray(8, 12).toString("latin1");
|
|
181983
|
+
if (chunk === "WEBP") return {
|
|
181984
|
+
kind: "image",
|
|
181985
|
+
mimeType: "image/webp"
|
|
181986
|
+
};
|
|
181987
|
+
if (chunk === "AVI ") return {
|
|
181988
|
+
kind: "video",
|
|
181989
|
+
mimeType: "video/x-msvideo"
|
|
181990
|
+
};
|
|
181991
|
+
}
|
|
181992
|
+
if (startsWith(header, Buffer.from("FLV"))) return {
|
|
181993
|
+
kind: "video",
|
|
181994
|
+
mimeType: "video/x-flv"
|
|
181995
|
+
};
|
|
181996
|
+
if (startsWith(header, ASF_HEADER)) return {
|
|
181997
|
+
kind: "video",
|
|
181998
|
+
mimeType: "video/x-ms-wmv"
|
|
181999
|
+
};
|
|
182000
|
+
if (startsWith(header, [
|
|
182001
|
+
26,
|
|
182002
|
+
69,
|
|
182003
|
+
223,
|
|
182004
|
+
163
|
|
182005
|
+
])) {
|
|
182006
|
+
const lowered = header.toString("latin1").toLowerCase();
|
|
182007
|
+
if (lowered.includes("webm")) return {
|
|
182008
|
+
kind: "video",
|
|
182009
|
+
mimeType: "video/webm"
|
|
182010
|
+
};
|
|
182011
|
+
if (lowered.includes("matroska")) return {
|
|
182012
|
+
kind: "video",
|
|
182013
|
+
mimeType: "video/x-matroska"
|
|
182014
|
+
};
|
|
182015
|
+
}
|
|
182016
|
+
const brand = sniffFtypBrand(header);
|
|
182017
|
+
if (brand !== null && brand !== "") {
|
|
182018
|
+
if (brand in FTYP_IMAGE_BRANDS) return {
|
|
182019
|
+
kind: "image",
|
|
182020
|
+
mimeType: FTYP_IMAGE_BRANDS[brand]
|
|
182021
|
+
};
|
|
182022
|
+
if (brand in FTYP_VIDEO_BRANDS) return {
|
|
182023
|
+
kind: "video",
|
|
182024
|
+
mimeType: FTYP_VIDEO_BRANDS[brand]
|
|
182025
|
+
};
|
|
182026
|
+
}
|
|
182027
|
+
return null;
|
|
182028
|
+
}
|
|
182029
|
+
/**
|
|
182030
|
+
* Best-effort pixel-dimension reader for common raster formats.
|
|
182031
|
+
*
|
|
182032
|
+
* Inspects only the fixed region near the start of the file where each
|
|
182033
|
+
* format records its dimensions (the IHDR/DIB header, the RIFF chunk
|
|
182034
|
+
* after the `WEBP` tag, or the first JPEG SOFn segment). Returns `null`
|
|
182035
|
+
* for formats whose dimensions are not locatable from that region, or
|
|
182036
|
+
* when the supplied buffer is too short to cover it.
|
|
182037
|
+
*/
|
|
182038
|
+
function sniffImageDimensions(data) {
|
|
182039
|
+
const buf = toBuffer(data);
|
|
182040
|
+
if (startsWith(buf, [
|
|
182041
|
+
137,
|
|
182042
|
+
80,
|
|
182043
|
+
78,
|
|
182044
|
+
71,
|
|
182045
|
+
13,
|
|
182046
|
+
10,
|
|
182047
|
+
26,
|
|
182048
|
+
10
|
|
182049
|
+
]) && buf.length >= 24) return {
|
|
182050
|
+
width: buf.readUInt32BE(16),
|
|
182051
|
+
height: buf.readUInt32BE(20)
|
|
182052
|
+
};
|
|
182053
|
+
if ((startsWith(buf, Buffer.from("GIF87a")) || startsWith(buf, Buffer.from("GIF89a"))) && buf.length >= 10) return {
|
|
182054
|
+
width: buf.readUInt16LE(6),
|
|
182055
|
+
height: buf.readUInt16LE(8)
|
|
182056
|
+
};
|
|
182057
|
+
if (startsWith(buf, Buffer.from("BM")) && buf.length >= 26) return {
|
|
182058
|
+
width: buf.readInt32LE(18),
|
|
182059
|
+
height: Math.abs(buf.readInt32LE(22))
|
|
182060
|
+
};
|
|
182061
|
+
if (startsWith(buf, Buffer.from("RIFF")) && buf.length >= 30) {
|
|
182062
|
+
const fourCc = buf.subarray(12, 16).toString("latin1");
|
|
182063
|
+
if (fourCc === "VP8 ") return {
|
|
182064
|
+
width: buf.readUInt16LE(26) & 16383,
|
|
182065
|
+
height: buf.readUInt16LE(28) & 16383
|
|
182066
|
+
};
|
|
182067
|
+
if (fourCc === "VP8L" && buf.length >= 25) {
|
|
182068
|
+
const bits = buf.readUInt32LE(21);
|
|
182069
|
+
return {
|
|
182070
|
+
width: (bits & 16383) + 1,
|
|
182071
|
+
height: (bits >> 14 & 16383) + 1
|
|
182072
|
+
};
|
|
182073
|
+
}
|
|
182074
|
+
if (fourCc === "VP8X") return {
|
|
182075
|
+
width: 1 + (buf[24] | buf[25] << 8 | buf[26] << 16),
|
|
182076
|
+
height: 1 + (buf[27] | buf[28] << 8 | buf[29] << 16)
|
|
182077
|
+
};
|
|
182078
|
+
}
|
|
182079
|
+
if (startsWith(buf, [255, 216])) {
|
|
182080
|
+
let offset = 2;
|
|
182081
|
+
while (offset + 9 < buf.length) {
|
|
182082
|
+
if (buf[offset] !== 255) {
|
|
182083
|
+
offset += 1;
|
|
182084
|
+
continue;
|
|
182085
|
+
}
|
|
182086
|
+
const marker = buf[offset + 1];
|
|
182087
|
+
if (marker >= 192 && marker <= 207 && marker !== 196 && marker !== 200 && marker !== 204) return {
|
|
182088
|
+
height: buf.readUInt16BE(offset + 5),
|
|
182089
|
+
width: buf.readUInt16BE(offset + 7)
|
|
182090
|
+
};
|
|
182091
|
+
if (marker === 216 || marker === 217 || marker >= 208 && marker <= 215) {
|
|
182092
|
+
offset += 2;
|
|
182093
|
+
continue;
|
|
182094
|
+
}
|
|
182095
|
+
const segmentLength = buf.readUInt16BE(offset + 2);
|
|
182096
|
+
if (segmentLength < 2) break;
|
|
182097
|
+
offset += 2 + segmentLength;
|
|
182098
|
+
}
|
|
182099
|
+
}
|
|
182100
|
+
return null;
|
|
182101
|
+
}
|
|
182102
|
+
function getSuffix(path) {
|
|
182103
|
+
const idx = path.lastIndexOf(".");
|
|
182104
|
+
if (idx === -1) return "";
|
|
182105
|
+
if (idx <= Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\")) + 1) return "";
|
|
182106
|
+
return path.slice(idx).toLowerCase();
|
|
182107
|
+
}
|
|
182108
|
+
function detectFileType(path, header, type = "text") {
|
|
182109
|
+
const suffix = getSuffix(path);
|
|
182110
|
+
let mediaHint = null;
|
|
182111
|
+
if (suffix in TEXT_MIME_BY_SUFFIX) mediaHint = {
|
|
182112
|
+
kind: "text",
|
|
182113
|
+
mimeType: TEXT_MIME_BY_SUFFIX[suffix]
|
|
182114
|
+
};
|
|
182115
|
+
else if (suffix in IMAGE_MIME_BY_SUFFIX) mediaHint = {
|
|
182116
|
+
kind: "image",
|
|
182117
|
+
mimeType: IMAGE_MIME_BY_SUFFIX[suffix]
|
|
182118
|
+
};
|
|
182119
|
+
else if (suffix in VIDEO_MIME_BY_SUFFIX) mediaHint = {
|
|
182120
|
+
kind: "video",
|
|
182121
|
+
mimeType: VIDEO_MIME_BY_SUFFIX[suffix]
|
|
182122
|
+
};
|
|
182123
|
+
if (header !== void 0) {
|
|
182124
|
+
const buf = toBuffer(header);
|
|
182125
|
+
const sniffed = sniffMediaFromMagic(buf);
|
|
182126
|
+
if (sniffed) {
|
|
182127
|
+
if (type === "media") return sniffed;
|
|
182128
|
+
if (mediaHint) {
|
|
182129
|
+
if (sniffed.kind !== mediaHint.kind) return {
|
|
182130
|
+
kind: "unknown",
|
|
182131
|
+
mimeType: ""
|
|
182132
|
+
};
|
|
182133
|
+
return mediaHint;
|
|
182134
|
+
}
|
|
182135
|
+
return sniffed;
|
|
182136
|
+
}
|
|
182137
|
+
if (mediaHint?.kind === "image") return {
|
|
182138
|
+
kind: "unknown",
|
|
182139
|
+
mimeType: ""
|
|
182140
|
+
};
|
|
182141
|
+
if (type === "media" && mediaHint?.kind === "video") return mediaHint;
|
|
182142
|
+
if (buf.includes(0)) return {
|
|
182143
|
+
kind: "unknown",
|
|
182144
|
+
mimeType: ""
|
|
182145
|
+
};
|
|
182146
|
+
}
|
|
182147
|
+
if (mediaHint) return mediaHint;
|
|
182148
|
+
if (NON_TEXT_SUFFIXES.has(suffix)) return {
|
|
182149
|
+
kind: "unknown",
|
|
182150
|
+
mimeType: ""
|
|
182151
|
+
};
|
|
182152
|
+
return {
|
|
182153
|
+
kind: "text",
|
|
182154
|
+
mimeType: "text/plain"
|
|
182155
|
+
};
|
|
182156
|
+
}
|
|
182157
|
+
//#endregion
|
|
182158
|
+
//#region ../../packages/agent-core/src/utils/tokens.ts
|
|
182159
|
+
const messageTokenEstimateCache = /* @__PURE__ */ new WeakMap();
|
|
182160
|
+
/** Open assistant messages grow while streaming; completed history stays cached. */
|
|
182161
|
+
function invalidateMessageTokenEstimate(message) {
|
|
182162
|
+
messageTokenEstimateCache.delete(message);
|
|
182163
|
+
}
|
|
182164
|
+
/**
|
|
182165
|
+
* Estimate token count from text using a character-based heuristic.
|
|
182166
|
+
* - ASCII (~4 chars per token)
|
|
182167
|
+
* - CJK and other non-ASCII (~1 char per token)
|
|
182168
|
+
* The estimate is transient — the next LLM call returns the real count
|
|
182169
|
+
* and supersedes this value. Used to keep `tokenCountWithPending`
|
|
182170
|
+
* monotonic between LLM round-trips without paying for a tokenizer.
|
|
182171
|
+
*/
|
|
182172
|
+
function estimateTokens(text) {
|
|
182173
|
+
let asciiCount = 0;
|
|
182174
|
+
let nonAsciiCount = 0;
|
|
182175
|
+
for (const char of text) if (char.codePointAt(0) <= 127) asciiCount++;
|
|
182176
|
+
else nonAsciiCount++;
|
|
182177
|
+
return Math.ceil(asciiCount / 4) + nonAsciiCount;
|
|
182178
|
+
}
|
|
182179
|
+
function estimateTokensForMessages(messages) {
|
|
182180
|
+
let total = 0;
|
|
182181
|
+
for (const message of messages) total += estimateTokensForMessage(message);
|
|
182182
|
+
return total;
|
|
182183
|
+
}
|
|
182184
|
+
/** With stopAfter, the result is a lower bound once it exceeds that budget. */
|
|
182185
|
+
function estimateTokensForTools(tools, stopAfter = Infinity) {
|
|
182186
|
+
let total = 0;
|
|
182187
|
+
for (const tool of tools) {
|
|
182188
|
+
total += estimateTokens(tool.name);
|
|
182189
|
+
total += estimateTokens(tool.description);
|
|
182190
|
+
total += estimateTokens(JSON.stringify(tool.parameters));
|
|
182191
|
+
if (total > stopAfter) return total;
|
|
182192
|
+
}
|
|
182193
|
+
return total;
|
|
182194
|
+
}
|
|
182195
|
+
function estimateTokensForMessage(message) {
|
|
182196
|
+
const cached = messageTokenEstimateCache.get(message);
|
|
182197
|
+
if (cached !== void 0) return cached;
|
|
182198
|
+
let total = estimateTokens(message.role);
|
|
182199
|
+
total += estimateTokensForContentParts(message.content);
|
|
182200
|
+
if (message.toolCalls !== void 0) for (const call of message.toolCalls) {
|
|
182201
|
+
total += estimateTokens(call.name);
|
|
182202
|
+
total += estimateTokens(JSON.stringify(call.arguments));
|
|
182203
|
+
}
|
|
182204
|
+
messageTokenEstimateCache.set(message, total);
|
|
182205
|
+
return total;
|
|
182206
|
+
}
|
|
182207
|
+
function estimateTokensForContentParts(parts) {
|
|
182208
|
+
let total = 0;
|
|
182209
|
+
for (const part of parts) total += estimateTokensForContentPart(part);
|
|
182210
|
+
return total;
|
|
182211
|
+
}
|
|
182212
|
+
/**
|
|
182213
|
+
* Conservative transient fallback for media whose pixel dimensions or duration
|
|
182214
|
+
* are unavailable. Inline raster images use their transmitted dimensions below;
|
|
182215
|
+
* audio, video, remote images, and malformed image data keep this safe floor.
|
|
182216
|
+
* The next successful LLM round-trip replaces the estimate with reported usage.
|
|
182217
|
+
*/
|
|
182218
|
+
const MEDIA_TOKEN_ESTIMATE = 2e3;
|
|
182219
|
+
/** Enough header data for common JPEG metadata followed by the first SOF marker. */
|
|
182220
|
+
const MAX_IMAGE_HEADER_BYTES = 1024 * 1024;
|
|
182221
|
+
function imageDimensionsFromDataUrl(url) {
|
|
182222
|
+
const commaIndex = url.indexOf(",");
|
|
182223
|
+
if (commaIndex <= 0) return null;
|
|
182224
|
+
const metadata = url.slice(0, commaIndex).toLowerCase();
|
|
182225
|
+
if (!metadata.startsWith("data:image/") || !metadata.split(";").includes("base64")) return null;
|
|
182226
|
+
const maxBase64Chars = Math.ceil(MAX_IMAGE_HEADER_BYTES / 3) * 4;
|
|
182227
|
+
const encodedHeader = url.slice(commaIndex + 1, commaIndex + 1 + maxBase64Chars);
|
|
182228
|
+
if (encodedHeader.length === 0) return null;
|
|
182229
|
+
try {
|
|
182230
|
+
const dimensions = sniffImageDimensions(Buffer.from(encodedHeader, "base64"));
|
|
182231
|
+
if (dimensions === null || !Number.isSafeInteger(dimensions.width) || !Number.isSafeInteger(dimensions.height) || dimensions.width <= 0 || dimensions.height <= 0) return null;
|
|
182232
|
+
return dimensions;
|
|
182233
|
+
} catch {
|
|
182234
|
+
return null;
|
|
182235
|
+
}
|
|
182236
|
+
}
|
|
182237
|
+
function estimateImageTokensFromDimensions(width, height) {
|
|
182238
|
+
if (!Number.isSafeInteger(width) || !Number.isSafeInteger(height) || width <= 0 || height <= 0) return MEDIA_TOKEN_ESTIMATE;
|
|
182239
|
+
const patchSize = BigInt(32);
|
|
182240
|
+
const tokens = (BigInt(width) + patchSize - 1n) / patchSize * ((BigInt(height) + patchSize - 1n) / patchSize);
|
|
182241
|
+
return tokens > BigInt(Number.MAX_SAFE_INTEGER) ? Number.MAX_SAFE_INTEGER : Number(tokens);
|
|
182242
|
+
}
|
|
182243
|
+
function estimateImageTokens(url) {
|
|
182244
|
+
const dimensions = imageDimensionsFromDataUrl(url);
|
|
182245
|
+
return dimensions === null ? MEDIA_TOKEN_ESTIMATE : estimateImageTokensFromDimensions(dimensions.width, dimensions.height);
|
|
182246
|
+
}
|
|
182247
|
+
function estimateTokensForContentPart(part) {
|
|
182248
|
+
switch (part.type) {
|
|
182249
|
+
case "text": return estimateTokens(part.text);
|
|
182250
|
+
case "think": return estimateTokens(part.think);
|
|
182251
|
+
case "image_url": return estimateImageTokens(part.imageUrl.url);
|
|
182252
|
+
case "audio_url":
|
|
182253
|
+
case "video_url": return MEDIA_TOKEN_ESTIMATE;
|
|
182254
|
+
default: return 0;
|
|
182255
|
+
}
|
|
182256
|
+
}
|
|
182257
|
+
const MAX_TOOL_CONTINUITY_SERIALIZED_BYTES = 4096;
|
|
182258
|
+
function saturatingAdd(left, right) {
|
|
182259
|
+
return left + Math.min(right, Number.MAX_SAFE_INTEGER - left);
|
|
182260
|
+
}
|
|
182261
|
+
function renderUnchecked(value) {
|
|
182262
|
+
return [
|
|
182263
|
+
"",
|
|
182264
|
+
"",
|
|
182265
|
+
"<tool-continuity>",
|
|
182266
|
+
"Observed tool-result flags; may be synthetic, not verified job success or permission. omitted counts excluded observations cumulatively, not jobs.",
|
|
182267
|
+
JSON.stringify(value).replaceAll(/[<>&]/g, (character) => {
|
|
182268
|
+
return `\\u${character.codePointAt(0).toString(16).padStart(4, "0")}`;
|
|
182269
|
+
}),
|
|
182270
|
+
"</tool-continuity>"
|
|
182271
|
+
].join("\n");
|
|
182272
|
+
}
|
|
182273
|
+
function hasExactKeys(value, expected) {
|
|
182274
|
+
const prototype = Object.getPrototypeOf(value);
|
|
182275
|
+
if (prototype !== Object.prototype && prototype !== null) return false;
|
|
182276
|
+
return Reflect.ownKeys(value).length === expected.length && expected.every((key) => {
|
|
182277
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
182278
|
+
return descriptor !== void 0 && descriptor.enumerable === true && Object.hasOwn(descriptor, "value");
|
|
182279
|
+
});
|
|
182280
|
+
}
|
|
182281
|
+
function isDataArray(value) {
|
|
182282
|
+
if (!Array.isArray(value) || Object.getPrototypeOf(value) !== Array.prototype || value.length > 8 || Reflect.ownKeys(value).length !== value.length + 1) return false;
|
|
182283
|
+
for (let index = 0; index < value.length; index++) {
|
|
182284
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
|
|
182285
|
+
if (descriptor === void 0 || descriptor.enumerable !== true || !Object.hasOwn(descriptor, "value")) return false;
|
|
182286
|
+
}
|
|
182287
|
+
return true;
|
|
182288
|
+
}
|
|
182289
|
+
/** Validate restored metadata without interpreting any summarizer or tool prose. */
|
|
182290
|
+
function isToolContinuity(value) {
|
|
182291
|
+
try {
|
|
182292
|
+
if (value === null || typeof value !== "object" || !hasExactKeys(value, ["receipts", "omitted"])) return false;
|
|
182293
|
+
const candidate = value;
|
|
182294
|
+
if (!Number.isSafeInteger(candidate["omitted"]) || candidate["omitted"] < 0 || !isDataArray(candidate["receipts"]) || candidate["receipts"].length > 8) return false;
|
|
182295
|
+
for (const receipt of candidate["receipts"]) if (receipt === null || typeof receipt !== "object" || !hasExactKeys(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;
|
|
182296
|
+
return Buffer.byteLength(JSON.stringify(renderUnchecked(value)), "utf8") <= MAX_TOOL_CONTINUITY_SERIALIZED_BYTES;
|
|
182297
|
+
} catch {
|
|
182298
|
+
return false;
|
|
182299
|
+
}
|
|
182300
|
+
}
|
|
182301
|
+
function renderToolContinuity(value) {
|
|
182302
|
+
if (!isToolContinuity(value) || value.receipts.length === 0 && value.omitted === 0) return void 0;
|
|
182303
|
+
return renderUnchecked(value);
|
|
182304
|
+
}
|
|
182305
|
+
/** The caller passes only the compactable prefix, excluding the preserved tool suffix. */
|
|
182306
|
+
function collectToolContinuity(messages) {
|
|
182307
|
+
const observed = /* @__PURE__ */ new Map();
|
|
182308
|
+
let ordinal = 0;
|
|
182309
|
+
let inheritedOmitted = 0;
|
|
182310
|
+
let excluded = 0;
|
|
182311
|
+
const remember = (toolCallId, observedIsError) => {
|
|
182312
|
+
if (toolCallId.length === 0 || Buffer.byteLength(toolCallId, "utf8") > 256) {
|
|
182313
|
+
excluded = saturatingAdd(excluded, 1);
|
|
182314
|
+
return;
|
|
182315
|
+
}
|
|
182316
|
+
const key = JSON.stringify([toolCallId, observedIsError]);
|
|
182317
|
+
observed.set(key, {
|
|
182318
|
+
toolCallId,
|
|
182319
|
+
observedIsError,
|
|
182320
|
+
ordinal: ordinal++
|
|
182321
|
+
});
|
|
182322
|
+
};
|
|
182323
|
+
for (const message of messages) if (message.role === "tool" && typeof message.toolCallId === "string") remember(message.toolCallId, typeof message.isError === "boolean" ? message.isError : null);
|
|
182324
|
+
else if (message.role === "user" && message.origin?.kind === "compaction_summary") {
|
|
182325
|
+
const previous = message.origin.toolContinuity;
|
|
182326
|
+
if (!isToolContinuity(previous)) continue;
|
|
182327
|
+
for (const receipt of previous.receipts.toReversed()) remember(receipt.toolCallId, receipt.observedIsError);
|
|
182328
|
+
inheritedOmitted = Math.max(inheritedOmitted, previous.omitted);
|
|
182329
|
+
}
|
|
182330
|
+
const prioritized = [...observed.values()].toSorted((left, right) => Number(right.observedIsError === true) - Number(left.observedIsError === true) || right.ordinal - left.ordinal);
|
|
182331
|
+
const receipts = prioritized.slice(0, 8).map(({ toolCallId, observedIsError }) => ({
|
|
182332
|
+
toolCallId,
|
|
182333
|
+
observedIsError
|
|
182334
|
+
}));
|
|
182335
|
+
let omitted = saturatingAdd(saturatingAdd(inheritedOmitted, excluded), prioritized.length - receipts.length);
|
|
182336
|
+
while (true) {
|
|
182337
|
+
const result = {
|
|
182338
|
+
receipts: [...receipts],
|
|
182339
|
+
omitted
|
|
182340
|
+
};
|
|
182341
|
+
if (renderToolContinuity(result) !== void 0) return result;
|
|
182342
|
+
if (receipts.length === 0) return void 0;
|
|
182343
|
+
receipts.pop();
|
|
182344
|
+
omitted = saturatingAdd(omitted, 1);
|
|
182345
|
+
}
|
|
182346
|
+
}
|
|
182347
|
+
/** Fit complete tuples and their disclaimer; never start a new failure or retry path. */
|
|
182348
|
+
function fitToolContinuity(value, additionalTokenBudget) {
|
|
182349
|
+
if (value === void 0 || !isToolContinuity(value) || !(additionalTokenBudget > 0)) return void 0;
|
|
182350
|
+
const receipts = [...value.receipts];
|
|
182351
|
+
let omitted = value.omitted;
|
|
182352
|
+
while (true) {
|
|
182353
|
+
const continuity = {
|
|
182354
|
+
receipts: [...receipts],
|
|
182355
|
+
omitted
|
|
182356
|
+
};
|
|
182357
|
+
const text = renderToolContinuity(continuity);
|
|
182358
|
+
if (text !== void 0 && estimateTokens(text) <= additionalTokenBudget) return {
|
|
182359
|
+
continuity,
|
|
182360
|
+
text
|
|
182361
|
+
};
|
|
182362
|
+
if (receipts.length === 0) return void 0;
|
|
182363
|
+
receipts.pop();
|
|
182364
|
+
omitted = saturatingAdd(omitted, 1);
|
|
182365
|
+
}
|
|
182366
|
+
}
|
|
181622
182367
|
//#endregion
|
|
181623
182368
|
//#region ../../packages/agent-core/src/agent/records/resume-snapshot.ts
|
|
181624
182369
|
const integer$1 = number$1().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
|
|
@@ -181713,6 +182458,7 @@ const stateRecordSchema = union([
|
|
|
181713
182458
|
verificationScope: _enum(GOAL_VERIFICATION_SCOPES).optional()
|
|
181714
182459
|
}),
|
|
181715
182460
|
record$1("goal.update", {
|
|
182461
|
+
objective: text.min(1).max(4e3).regex(/\S/).optional(),
|
|
181716
182462
|
status: _enum([
|
|
181717
182463
|
"active",
|
|
181718
182464
|
"paused",
|
|
@@ -181764,7 +182510,7 @@ const originCase = (kind, shape = {}) => object({
|
|
|
181764
182510
|
}).passthrough();
|
|
181765
182511
|
const origin = union([
|
|
181766
182512
|
originCase("user"),
|
|
181767
|
-
originCase("compaction_summary"),
|
|
182513
|
+
originCase("compaction_summary", { toolContinuity: custom$1(isToolContinuity).optional() }),
|
|
181768
182514
|
originCase("skill_activation", {
|
|
181769
182515
|
activationId: text,
|
|
181770
182516
|
skillName: text,
|
|
@@ -182115,6 +182861,7 @@ async function writeResumeCheckpoint(wirePath, position, snapshot) {
|
|
|
182115
182861
|
if (Buffer.byteLength(bytes) > MAX_CHECKPOINT_BYTES) return false;
|
|
182116
182862
|
const target = resumeCheckpointPath(wirePath);
|
|
182117
182863
|
const temporary = `${target}.tmp-${process.pid}-${randomBytes(8).toString("hex")}`;
|
|
182864
|
+
let renamed = false;
|
|
182118
182865
|
try {
|
|
182119
182866
|
const output = await open(temporary, "wx", 384);
|
|
182120
182867
|
try {
|
|
@@ -182124,10 +182871,11 @@ async function writeResumeCheckpoint(wirePath, position, snapshot) {
|
|
|
182124
182871
|
await output.close();
|
|
182125
182872
|
}
|
|
182126
182873
|
await rename(temporary, target);
|
|
182874
|
+
renamed = true;
|
|
182127
182875
|
await syncDir(dirname$3(target));
|
|
182128
182876
|
return true;
|
|
182129
182877
|
} finally {
|
|
182130
|
-
await rm(temporary, { force: true }).catch(() => {});
|
|
182878
|
+
if (!renamed) await rm(temporary, { force: true }).catch(() => {});
|
|
182131
182879
|
}
|
|
182132
182880
|
}
|
|
182133
182881
|
//#endregion
|
|
@@ -185464,501 +186212,6 @@ var TodoListTool = class {
|
|
|
185464
186212
|
})));
|
|
185465
186213
|
}
|
|
185466
186214
|
};
|
|
185467
|
-
const IMAGE_MIME_BY_SUFFIX = Object.freeze({
|
|
185468
|
-
".png": "image/png",
|
|
185469
|
-
".jpg": "image/jpeg",
|
|
185470
|
-
".jpeg": "image/jpeg",
|
|
185471
|
-
".gif": "image/gif",
|
|
185472
|
-
".bmp": "image/bmp",
|
|
185473
|
-
".tif": "image/tiff",
|
|
185474
|
-
".tiff": "image/tiff",
|
|
185475
|
-
".webp": "image/webp",
|
|
185476
|
-
".ico": "image/x-icon",
|
|
185477
|
-
".heic": "image/heic",
|
|
185478
|
-
".heif": "image/heif",
|
|
185479
|
-
".avif": "image/avif",
|
|
185480
|
-
".svgz": "image/svg+xml"
|
|
185481
|
-
});
|
|
185482
|
-
const VIDEO_MIME_BY_SUFFIX = Object.freeze({
|
|
185483
|
-
".mp4": "video/mp4",
|
|
185484
|
-
".mpg": "video/mpeg",
|
|
185485
|
-
".mpeg": "video/mpeg",
|
|
185486
|
-
".mkv": "video/x-matroska",
|
|
185487
|
-
".avi": "video/x-msvideo",
|
|
185488
|
-
".mov": "video/quicktime",
|
|
185489
|
-
".ogv": "video/ogg",
|
|
185490
|
-
".wmv": "video/x-ms-wmv",
|
|
185491
|
-
".webm": "video/webm",
|
|
185492
|
-
".m4v": "video/x-m4v",
|
|
185493
|
-
".flv": "video/x-flv",
|
|
185494
|
-
".3gp": "video/3gpp",
|
|
185495
|
-
".3g2": "video/3gpp2"
|
|
185496
|
-
});
|
|
185497
|
-
const TEXT_MIME_BY_SUFFIX = Object.freeze({ ".svg": "image/svg+xml" });
|
|
185498
|
-
const NON_TEXT_SUFFIXES = new Set([
|
|
185499
|
-
".icns",
|
|
185500
|
-
".psd",
|
|
185501
|
-
".ai",
|
|
185502
|
-
".eps",
|
|
185503
|
-
".pdf",
|
|
185504
|
-
".doc",
|
|
185505
|
-
".docx",
|
|
185506
|
-
".dot",
|
|
185507
|
-
".dotx",
|
|
185508
|
-
".rtf",
|
|
185509
|
-
".odt",
|
|
185510
|
-
".xls",
|
|
185511
|
-
".xlsx",
|
|
185512
|
-
".xlsm",
|
|
185513
|
-
".xlt",
|
|
185514
|
-
".xltx",
|
|
185515
|
-
".xltm",
|
|
185516
|
-
".ods",
|
|
185517
|
-
".ppt",
|
|
185518
|
-
".pptx",
|
|
185519
|
-
".pptm",
|
|
185520
|
-
".pps",
|
|
185521
|
-
".ppsx",
|
|
185522
|
-
".odp",
|
|
185523
|
-
".pages",
|
|
185524
|
-
".numbers",
|
|
185525
|
-
".key",
|
|
185526
|
-
".zip",
|
|
185527
|
-
".rar",
|
|
185528
|
-
".7z",
|
|
185529
|
-
".tar",
|
|
185530
|
-
".gz",
|
|
185531
|
-
".tgz",
|
|
185532
|
-
".bz2",
|
|
185533
|
-
".xz",
|
|
185534
|
-
".zst",
|
|
185535
|
-
".lz",
|
|
185536
|
-
".lz4",
|
|
185537
|
-
".br",
|
|
185538
|
-
".cab",
|
|
185539
|
-
".ar",
|
|
185540
|
-
".deb",
|
|
185541
|
-
".rpm",
|
|
185542
|
-
".mp3",
|
|
185543
|
-
".wav",
|
|
185544
|
-
".flac",
|
|
185545
|
-
".ogg",
|
|
185546
|
-
".oga",
|
|
185547
|
-
".opus",
|
|
185548
|
-
".aac",
|
|
185549
|
-
".m4a",
|
|
185550
|
-
".wma",
|
|
185551
|
-
".ttf",
|
|
185552
|
-
".otf",
|
|
185553
|
-
".woff",
|
|
185554
|
-
".woff2",
|
|
185555
|
-
".exe",
|
|
185556
|
-
".dll",
|
|
185557
|
-
".so",
|
|
185558
|
-
".dylib",
|
|
185559
|
-
".bin",
|
|
185560
|
-
".apk",
|
|
185561
|
-
".ipa",
|
|
185562
|
-
".jar",
|
|
185563
|
-
".class",
|
|
185564
|
-
".pyc",
|
|
185565
|
-
".pyo",
|
|
185566
|
-
".wasm",
|
|
185567
|
-
".dmg",
|
|
185568
|
-
".iso",
|
|
185569
|
-
".img",
|
|
185570
|
-
".sqlite",
|
|
185571
|
-
".sqlite3",
|
|
185572
|
-
".db",
|
|
185573
|
-
".db3"
|
|
185574
|
-
]);
|
|
185575
|
-
const ASF_HEADER = Buffer.from([
|
|
185576
|
-
48,
|
|
185577
|
-
38,
|
|
185578
|
-
178,
|
|
185579
|
-
117,
|
|
185580
|
-
142,
|
|
185581
|
-
102,
|
|
185582
|
-
207,
|
|
185583
|
-
17,
|
|
185584
|
-
166,
|
|
185585
|
-
217,
|
|
185586
|
-
0,
|
|
185587
|
-
170,
|
|
185588
|
-
0,
|
|
185589
|
-
98,
|
|
185590
|
-
206,
|
|
185591
|
-
108
|
|
185592
|
-
]);
|
|
185593
|
-
const FTYP_IMAGE_BRANDS = Object.freeze({
|
|
185594
|
-
avif: "image/avif",
|
|
185595
|
-
avis: "image/avif",
|
|
185596
|
-
heic: "image/heic",
|
|
185597
|
-
heif: "image/heif",
|
|
185598
|
-
heix: "image/heif",
|
|
185599
|
-
hevc: "image/heic",
|
|
185600
|
-
mif1: "image/heif",
|
|
185601
|
-
msf1: "image/heif"
|
|
185602
|
-
});
|
|
185603
|
-
const FTYP_VIDEO_BRANDS = Object.freeze({
|
|
185604
|
-
isom: "video/mp4",
|
|
185605
|
-
iso2: "video/mp4",
|
|
185606
|
-
iso5: "video/mp4",
|
|
185607
|
-
mp41: "video/mp4",
|
|
185608
|
-
mp42: "video/mp4",
|
|
185609
|
-
avc1: "video/mp4",
|
|
185610
|
-
mp4v: "video/mp4",
|
|
185611
|
-
m4v: "video/x-m4v",
|
|
185612
|
-
qt: "video/quicktime",
|
|
185613
|
-
"3gp4": "video/3gpp",
|
|
185614
|
-
"3gp5": "video/3gpp",
|
|
185615
|
-
"3gp6": "video/3gpp",
|
|
185616
|
-
"3gp7": "video/3gpp",
|
|
185617
|
-
"3g2": "video/3gpp2"
|
|
185618
|
-
});
|
|
185619
|
-
function toBuffer(data) {
|
|
185620
|
-
return Buffer.isBuffer(data) ? data : Buffer.from(data.buffer, data.byteOffset, data.byteLength);
|
|
185621
|
-
}
|
|
185622
|
-
function startsWith(buf, prefix) {
|
|
185623
|
-
const needle = Buffer.isBuffer(prefix) ? prefix : Buffer.from(prefix);
|
|
185624
|
-
if (buf.length < needle.length) return false;
|
|
185625
|
-
for (let i = 0; i < needle.length; i += 1) if (buf[i] !== needle[i]) return false;
|
|
185626
|
-
return true;
|
|
185627
|
-
}
|
|
185628
|
-
function sniffFtypBrand(header) {
|
|
185629
|
-
if (header.length < 12) return null;
|
|
185630
|
-
if (header.subarray(4, 8).toString("latin1") !== "ftyp") return null;
|
|
185631
|
-
return header.subarray(8, 12).toString("latin1").toLowerCase().replaceAll(/[\s\u0000]+$/g, "").trim();
|
|
185632
|
-
}
|
|
185633
|
-
function sniffMediaFromMagic(data) {
|
|
185634
|
-
const buf = toBuffer(data);
|
|
185635
|
-
const header = buf.length > 512 ? buf.subarray(0, 512) : buf;
|
|
185636
|
-
if (startsWith(header, [
|
|
185637
|
-
137,
|
|
185638
|
-
80,
|
|
185639
|
-
78,
|
|
185640
|
-
71,
|
|
185641
|
-
13,
|
|
185642
|
-
10,
|
|
185643
|
-
26,
|
|
185644
|
-
10
|
|
185645
|
-
])) return {
|
|
185646
|
-
kind: "image",
|
|
185647
|
-
mimeType: "image/png"
|
|
185648
|
-
};
|
|
185649
|
-
if (startsWith(header, [
|
|
185650
|
-
255,
|
|
185651
|
-
216,
|
|
185652
|
-
255
|
|
185653
|
-
])) return {
|
|
185654
|
-
kind: "image",
|
|
185655
|
-
mimeType: "image/jpeg"
|
|
185656
|
-
};
|
|
185657
|
-
if (startsWith(header, Buffer.from("GIF87a")) || startsWith(header, Buffer.from("GIF89a"))) return {
|
|
185658
|
-
kind: "image",
|
|
185659
|
-
mimeType: "image/gif"
|
|
185660
|
-
};
|
|
185661
|
-
if (startsWith(header, Buffer.from("BM"))) return {
|
|
185662
|
-
kind: "image",
|
|
185663
|
-
mimeType: "image/bmp"
|
|
185664
|
-
};
|
|
185665
|
-
if (startsWith(header, [
|
|
185666
|
-
73,
|
|
185667
|
-
73,
|
|
185668
|
-
42,
|
|
185669
|
-
0
|
|
185670
|
-
]) || startsWith(header, [
|
|
185671
|
-
77,
|
|
185672
|
-
77,
|
|
185673
|
-
0,
|
|
185674
|
-
42
|
|
185675
|
-
])) return {
|
|
185676
|
-
kind: "image",
|
|
185677
|
-
mimeType: "image/tiff"
|
|
185678
|
-
};
|
|
185679
|
-
if (startsWith(header, [
|
|
185680
|
-
0,
|
|
185681
|
-
0,
|
|
185682
|
-
1,
|
|
185683
|
-
0
|
|
185684
|
-
])) return {
|
|
185685
|
-
kind: "image",
|
|
185686
|
-
mimeType: "image/x-icon"
|
|
185687
|
-
};
|
|
185688
|
-
if (startsWith(header, Buffer.from("RIFF")) && header.length >= 12) {
|
|
185689
|
-
const chunk = header.subarray(8, 12).toString("latin1");
|
|
185690
|
-
if (chunk === "WEBP") return {
|
|
185691
|
-
kind: "image",
|
|
185692
|
-
mimeType: "image/webp"
|
|
185693
|
-
};
|
|
185694
|
-
if (chunk === "AVI ") return {
|
|
185695
|
-
kind: "video",
|
|
185696
|
-
mimeType: "video/x-msvideo"
|
|
185697
|
-
};
|
|
185698
|
-
}
|
|
185699
|
-
if (startsWith(header, Buffer.from("FLV"))) return {
|
|
185700
|
-
kind: "video",
|
|
185701
|
-
mimeType: "video/x-flv"
|
|
185702
|
-
};
|
|
185703
|
-
if (startsWith(header, ASF_HEADER)) return {
|
|
185704
|
-
kind: "video",
|
|
185705
|
-
mimeType: "video/x-ms-wmv"
|
|
185706
|
-
};
|
|
185707
|
-
if (startsWith(header, [
|
|
185708
|
-
26,
|
|
185709
|
-
69,
|
|
185710
|
-
223,
|
|
185711
|
-
163
|
|
185712
|
-
])) {
|
|
185713
|
-
const lowered = header.toString("latin1").toLowerCase();
|
|
185714
|
-
if (lowered.includes("webm")) return {
|
|
185715
|
-
kind: "video",
|
|
185716
|
-
mimeType: "video/webm"
|
|
185717
|
-
};
|
|
185718
|
-
if (lowered.includes("matroska")) return {
|
|
185719
|
-
kind: "video",
|
|
185720
|
-
mimeType: "video/x-matroska"
|
|
185721
|
-
};
|
|
185722
|
-
}
|
|
185723
|
-
const brand = sniffFtypBrand(header);
|
|
185724
|
-
if (brand !== null && brand !== "") {
|
|
185725
|
-
if (brand in FTYP_IMAGE_BRANDS) return {
|
|
185726
|
-
kind: "image",
|
|
185727
|
-
mimeType: FTYP_IMAGE_BRANDS[brand]
|
|
185728
|
-
};
|
|
185729
|
-
if (brand in FTYP_VIDEO_BRANDS) return {
|
|
185730
|
-
kind: "video",
|
|
185731
|
-
mimeType: FTYP_VIDEO_BRANDS[brand]
|
|
185732
|
-
};
|
|
185733
|
-
}
|
|
185734
|
-
return null;
|
|
185735
|
-
}
|
|
185736
|
-
/**
|
|
185737
|
-
* Best-effort pixel-dimension reader for common raster formats.
|
|
185738
|
-
*
|
|
185739
|
-
* Inspects only the fixed region near the start of the file where each
|
|
185740
|
-
* format records its dimensions (the IHDR/DIB header, the RIFF chunk
|
|
185741
|
-
* after the `WEBP` tag, or the first JPEG SOFn segment). Returns `null`
|
|
185742
|
-
* for formats whose dimensions are not locatable from that region, or
|
|
185743
|
-
* when the supplied buffer is too short to cover it.
|
|
185744
|
-
*/
|
|
185745
|
-
function sniffImageDimensions(data) {
|
|
185746
|
-
const buf = toBuffer(data);
|
|
185747
|
-
if (startsWith(buf, [
|
|
185748
|
-
137,
|
|
185749
|
-
80,
|
|
185750
|
-
78,
|
|
185751
|
-
71,
|
|
185752
|
-
13,
|
|
185753
|
-
10,
|
|
185754
|
-
26,
|
|
185755
|
-
10
|
|
185756
|
-
]) && buf.length >= 24) return {
|
|
185757
|
-
width: buf.readUInt32BE(16),
|
|
185758
|
-
height: buf.readUInt32BE(20)
|
|
185759
|
-
};
|
|
185760
|
-
if ((startsWith(buf, Buffer.from("GIF87a")) || startsWith(buf, Buffer.from("GIF89a"))) && buf.length >= 10) return {
|
|
185761
|
-
width: buf.readUInt16LE(6),
|
|
185762
|
-
height: buf.readUInt16LE(8)
|
|
185763
|
-
};
|
|
185764
|
-
if (startsWith(buf, Buffer.from("BM")) && buf.length >= 26) return {
|
|
185765
|
-
width: buf.readInt32LE(18),
|
|
185766
|
-
height: Math.abs(buf.readInt32LE(22))
|
|
185767
|
-
};
|
|
185768
|
-
if (startsWith(buf, Buffer.from("RIFF")) && buf.length >= 30) {
|
|
185769
|
-
const fourCc = buf.subarray(12, 16).toString("latin1");
|
|
185770
|
-
if (fourCc === "VP8 ") return {
|
|
185771
|
-
width: buf.readUInt16LE(26) & 16383,
|
|
185772
|
-
height: buf.readUInt16LE(28) & 16383
|
|
185773
|
-
};
|
|
185774
|
-
if (fourCc === "VP8L" && buf.length >= 25) {
|
|
185775
|
-
const bits = buf.readUInt32LE(21);
|
|
185776
|
-
return {
|
|
185777
|
-
width: (bits & 16383) + 1,
|
|
185778
|
-
height: (bits >> 14 & 16383) + 1
|
|
185779
|
-
};
|
|
185780
|
-
}
|
|
185781
|
-
if (fourCc === "VP8X") return {
|
|
185782
|
-
width: 1 + (buf[24] | buf[25] << 8 | buf[26] << 16),
|
|
185783
|
-
height: 1 + (buf[27] | buf[28] << 8 | buf[29] << 16)
|
|
185784
|
-
};
|
|
185785
|
-
}
|
|
185786
|
-
if (startsWith(buf, [255, 216])) {
|
|
185787
|
-
let offset = 2;
|
|
185788
|
-
while (offset + 9 < buf.length) {
|
|
185789
|
-
if (buf[offset] !== 255) {
|
|
185790
|
-
offset += 1;
|
|
185791
|
-
continue;
|
|
185792
|
-
}
|
|
185793
|
-
const marker = buf[offset + 1];
|
|
185794
|
-
if (marker >= 192 && marker <= 207 && marker !== 196 && marker !== 200 && marker !== 204) return {
|
|
185795
|
-
height: buf.readUInt16BE(offset + 5),
|
|
185796
|
-
width: buf.readUInt16BE(offset + 7)
|
|
185797
|
-
};
|
|
185798
|
-
if (marker === 216 || marker === 217 || marker >= 208 && marker <= 215) {
|
|
185799
|
-
offset += 2;
|
|
185800
|
-
continue;
|
|
185801
|
-
}
|
|
185802
|
-
const segmentLength = buf.readUInt16BE(offset + 2);
|
|
185803
|
-
if (segmentLength < 2) break;
|
|
185804
|
-
offset += 2 + segmentLength;
|
|
185805
|
-
}
|
|
185806
|
-
}
|
|
185807
|
-
return null;
|
|
185808
|
-
}
|
|
185809
|
-
function getSuffix(path) {
|
|
185810
|
-
const idx = path.lastIndexOf(".");
|
|
185811
|
-
if (idx === -1) return "";
|
|
185812
|
-
if (idx <= Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\")) + 1) return "";
|
|
185813
|
-
return path.slice(idx).toLowerCase();
|
|
185814
|
-
}
|
|
185815
|
-
function detectFileType(path, header, type = "text") {
|
|
185816
|
-
const suffix = getSuffix(path);
|
|
185817
|
-
let mediaHint = null;
|
|
185818
|
-
if (suffix in TEXT_MIME_BY_SUFFIX) mediaHint = {
|
|
185819
|
-
kind: "text",
|
|
185820
|
-
mimeType: TEXT_MIME_BY_SUFFIX[suffix]
|
|
185821
|
-
};
|
|
185822
|
-
else if (suffix in IMAGE_MIME_BY_SUFFIX) mediaHint = {
|
|
185823
|
-
kind: "image",
|
|
185824
|
-
mimeType: IMAGE_MIME_BY_SUFFIX[suffix]
|
|
185825
|
-
};
|
|
185826
|
-
else if (suffix in VIDEO_MIME_BY_SUFFIX) mediaHint = {
|
|
185827
|
-
kind: "video",
|
|
185828
|
-
mimeType: VIDEO_MIME_BY_SUFFIX[suffix]
|
|
185829
|
-
};
|
|
185830
|
-
if (header !== void 0) {
|
|
185831
|
-
const buf = toBuffer(header);
|
|
185832
|
-
const sniffed = sniffMediaFromMagic(buf);
|
|
185833
|
-
if (sniffed) {
|
|
185834
|
-
if (type === "media") return sniffed;
|
|
185835
|
-
if (mediaHint) {
|
|
185836
|
-
if (sniffed.kind !== mediaHint.kind) return {
|
|
185837
|
-
kind: "unknown",
|
|
185838
|
-
mimeType: ""
|
|
185839
|
-
};
|
|
185840
|
-
return mediaHint;
|
|
185841
|
-
}
|
|
185842
|
-
return sniffed;
|
|
185843
|
-
}
|
|
185844
|
-
if (mediaHint?.kind === "image") return {
|
|
185845
|
-
kind: "unknown",
|
|
185846
|
-
mimeType: ""
|
|
185847
|
-
};
|
|
185848
|
-
if (type === "media" && mediaHint?.kind === "video") return mediaHint;
|
|
185849
|
-
if (buf.includes(0)) return {
|
|
185850
|
-
kind: "unknown",
|
|
185851
|
-
mimeType: ""
|
|
185852
|
-
};
|
|
185853
|
-
}
|
|
185854
|
-
if (mediaHint) return mediaHint;
|
|
185855
|
-
if (NON_TEXT_SUFFIXES.has(suffix)) return {
|
|
185856
|
-
kind: "unknown",
|
|
185857
|
-
mimeType: ""
|
|
185858
|
-
};
|
|
185859
|
-
return {
|
|
185860
|
-
kind: "text",
|
|
185861
|
-
mimeType: "text/plain"
|
|
185862
|
-
};
|
|
185863
|
-
}
|
|
185864
|
-
//#endregion
|
|
185865
|
-
//#region ../../packages/agent-core/src/utils/tokens.ts
|
|
185866
|
-
const messageTokenEstimateCache = /* @__PURE__ */ new WeakMap();
|
|
185867
|
-
/** Open assistant messages grow while streaming; completed history stays cached. */
|
|
185868
|
-
function invalidateMessageTokenEstimate(message) {
|
|
185869
|
-
messageTokenEstimateCache.delete(message);
|
|
185870
|
-
}
|
|
185871
|
-
/**
|
|
185872
|
-
* Estimate token count from text using a character-based heuristic.
|
|
185873
|
-
* - ASCII (~4 chars per token)
|
|
185874
|
-
* - CJK and other non-ASCII (~1 char per token)
|
|
185875
|
-
* The estimate is transient — the next LLM call returns the real count
|
|
185876
|
-
* and supersedes this value. Used to keep `tokenCountWithPending`
|
|
185877
|
-
* monotonic between LLM round-trips without paying for a tokenizer.
|
|
185878
|
-
*/
|
|
185879
|
-
function estimateTokens(text) {
|
|
185880
|
-
let asciiCount = 0;
|
|
185881
|
-
let nonAsciiCount = 0;
|
|
185882
|
-
for (const char of text) if (char.codePointAt(0) <= 127) asciiCount++;
|
|
185883
|
-
else nonAsciiCount++;
|
|
185884
|
-
return Math.ceil(asciiCount / 4) + nonAsciiCount;
|
|
185885
|
-
}
|
|
185886
|
-
function estimateTokensForMessages(messages) {
|
|
185887
|
-
let total = 0;
|
|
185888
|
-
for (const message of messages) total += estimateTokensForMessage(message);
|
|
185889
|
-
return total;
|
|
185890
|
-
}
|
|
185891
|
-
function estimateTokensForTools(tools) {
|
|
185892
|
-
let total = 0;
|
|
185893
|
-
for (const tool of tools) {
|
|
185894
|
-
total += estimateTokens(tool.name);
|
|
185895
|
-
total += estimateTokens(tool.description);
|
|
185896
|
-
total += estimateTokens(JSON.stringify(tool.parameters));
|
|
185897
|
-
}
|
|
185898
|
-
return total;
|
|
185899
|
-
}
|
|
185900
|
-
function estimateTokensForMessage(message) {
|
|
185901
|
-
const cached = messageTokenEstimateCache.get(message);
|
|
185902
|
-
if (cached !== void 0) return cached;
|
|
185903
|
-
let total = estimateTokens(message.role);
|
|
185904
|
-
total += estimateTokensForContentParts(message.content);
|
|
185905
|
-
if (message.toolCalls !== void 0) for (const call of message.toolCalls) {
|
|
185906
|
-
total += estimateTokens(call.name);
|
|
185907
|
-
total += estimateTokens(JSON.stringify(call.arguments));
|
|
185908
|
-
}
|
|
185909
|
-
messageTokenEstimateCache.set(message, total);
|
|
185910
|
-
return total;
|
|
185911
|
-
}
|
|
185912
|
-
function estimateTokensForContentParts(parts) {
|
|
185913
|
-
let total = 0;
|
|
185914
|
-
for (const part of parts) total += estimateTokensForContentPart(part);
|
|
185915
|
-
return total;
|
|
185916
|
-
}
|
|
185917
|
-
/**
|
|
185918
|
-
* Conservative transient fallback for media whose pixel dimensions or duration
|
|
185919
|
-
* are unavailable. Inline raster images use their transmitted dimensions below;
|
|
185920
|
-
* audio, video, remote images, and malformed image data keep this safe floor.
|
|
185921
|
-
* The next successful LLM round-trip replaces the estimate with reported usage.
|
|
185922
|
-
*/
|
|
185923
|
-
const MEDIA_TOKEN_ESTIMATE = 2e3;
|
|
185924
|
-
/** Enough header data for common JPEG metadata followed by the first SOF marker. */
|
|
185925
|
-
const MAX_IMAGE_HEADER_BYTES = 1024 * 1024;
|
|
185926
|
-
function imageDimensionsFromDataUrl(url) {
|
|
185927
|
-
const commaIndex = url.indexOf(",");
|
|
185928
|
-
if (commaIndex <= 0) return null;
|
|
185929
|
-
const metadata = url.slice(0, commaIndex).toLowerCase();
|
|
185930
|
-
if (!metadata.startsWith("data:image/") || !metadata.split(";").includes("base64")) return null;
|
|
185931
|
-
const maxBase64Chars = Math.ceil(MAX_IMAGE_HEADER_BYTES / 3) * 4;
|
|
185932
|
-
const encodedHeader = url.slice(commaIndex + 1, commaIndex + 1 + maxBase64Chars);
|
|
185933
|
-
if (encodedHeader.length === 0) return null;
|
|
185934
|
-
try {
|
|
185935
|
-
const dimensions = sniffImageDimensions(Buffer.from(encodedHeader, "base64"));
|
|
185936
|
-
if (dimensions === null || !Number.isSafeInteger(dimensions.width) || !Number.isSafeInteger(dimensions.height) || dimensions.width <= 0 || dimensions.height <= 0) return null;
|
|
185937
|
-
return dimensions;
|
|
185938
|
-
} catch {
|
|
185939
|
-
return null;
|
|
185940
|
-
}
|
|
185941
|
-
}
|
|
185942
|
-
function estimateImageTokensFromDimensions(width, height) {
|
|
185943
|
-
if (!Number.isSafeInteger(width) || !Number.isSafeInteger(height) || width <= 0 || height <= 0) return MEDIA_TOKEN_ESTIMATE;
|
|
185944
|
-
const patchSize = BigInt(32);
|
|
185945
|
-
const tokens = (BigInt(width) + patchSize - 1n) / patchSize * ((BigInt(height) + patchSize - 1n) / patchSize);
|
|
185946
|
-
return tokens > BigInt(Number.MAX_SAFE_INTEGER) ? Number.MAX_SAFE_INTEGER : Number(tokens);
|
|
185947
|
-
}
|
|
185948
|
-
function estimateImageTokens(url) {
|
|
185949
|
-
const dimensions = imageDimensionsFromDataUrl(url);
|
|
185950
|
-
return dimensions === null ? MEDIA_TOKEN_ESTIMATE : estimateImageTokensFromDimensions(dimensions.width, dimensions.height);
|
|
185951
|
-
}
|
|
185952
|
-
function estimateTokensForContentPart(part) {
|
|
185953
|
-
switch (part.type) {
|
|
185954
|
-
case "text": return estimateTokens(part.text);
|
|
185955
|
-
case "think": return estimateTokens(part.think);
|
|
185956
|
-
case "image_url": return estimateImageTokens(part.imageUrl.url);
|
|
185957
|
-
case "audio_url":
|
|
185958
|
-
case "video_url": return MEDIA_TOKEN_ESTIMATE;
|
|
185959
|
-
default: return 0;
|
|
185960
|
-
}
|
|
185961
|
-
}
|
|
185962
186215
|
//#endregion
|
|
185963
186216
|
//#region ../../node_modules/.pnpm/bmp-ts@1.0.9/node_modules/bmp-ts/dist/esm/header-types.js
|
|
185964
186217
|
var HeaderTypes, header_types_default;
|
|
@@ -230214,7 +230467,7 @@ function buildCompactionSummaryText(summary) {
|
|
|
230214
230467
|
const MAX_SESSION_COMPACTION_FAILURES = 2;
|
|
230215
230468
|
const DEFAULT_COMPACTION_MAX_COMPLETION_TOKENS = 128 * 1024;
|
|
230216
230469
|
const COMPACTION_SUMMARY_RESERVE_RATIO = .1;
|
|
230217
|
-
const BLUN_COMPACTION_REQUEST_BUDGET_BYTES =
|
|
230470
|
+
const BLUN_COMPACTION_REQUEST_BUDGET_BYTES = 48e4;
|
|
230218
230471
|
const MAX_HIERARCHICAL_COMPACTION_PASSES = 64;
|
|
230219
230472
|
const HIERARCHICAL_COMPACTION_PREFIX = "This is a complete summary of an earlier chronological segment. Preserve it as source material when merging it with the following conversation:";
|
|
230220
230473
|
var CompactionTruncatedError = class extends Error {
|
|
@@ -230374,26 +230627,10 @@ var FullCompaction = class {
|
|
|
230374
230627
|
const model = this.agent.activeResponderModel ?? this.agent.config.modelAlias;
|
|
230375
230628
|
if (model === void 0 || this.agent.config.runtimeModel(model).provider.name !== "blun") return void 0;
|
|
230376
230629
|
const systemPrompt = context.systemPrompt ?? this.agent.effectiveSystemPrompt;
|
|
230377
|
-
const tools =
|
|
230378
|
-
|
|
230379
|
-
description: tool.description,
|
|
230380
|
-
parameters: tool.parameters
|
|
230381
|
-
}));
|
|
230382
|
-
let extraBytes;
|
|
230383
|
-
try {
|
|
230384
|
-
extraBytes = estimateBlunRequestExtraBytes(tools, messages);
|
|
230385
|
-
} catch {
|
|
230386
|
-
return;
|
|
230387
|
-
}
|
|
230388
|
-
if (Buffer.byteLength(JSON.stringify({
|
|
230389
|
-
systemPrompt,
|
|
230390
|
-
messages: []
|
|
230391
|
-
}), "utf8") >= BLUN_COMPACTION_REQUEST_BUDGET_BYTES) return void 0;
|
|
230630
|
+
const tools = context.tools ?? this.agent.tools.loopTools;
|
|
230631
|
+
if (estimateBlunSerializedBodyBytes(systemPrompt, [], []) + 4096 >= BLUN_COMPACTION_REQUEST_BUDGET_BYTES) return void 0;
|
|
230392
230632
|
return {
|
|
230393
|
-
usedRequestBytesEstimate:
|
|
230394
|
-
systemPrompt,
|
|
230395
|
-
messages
|
|
230396
|
-
}), "utf8") + extraBytes.toolsBytes + extraBytes.visionBytes,
|
|
230633
|
+
usedRequestBytesEstimate: estimateBlunSerializedBodyBytes(systemPrompt, tools, messages) + 4096,
|
|
230397
230634
|
thresholdRequestBytes: BLUN_COMPACTION_REQUEST_BUDGET_BYTES
|
|
230398
230635
|
};
|
|
230399
230636
|
}
|
|
@@ -230748,10 +230985,7 @@ var FullCompaction = class {
|
|
|
230748
230985
|
dropOrphanResults: true
|
|
230749
230986
|
}), createUserMessage(requestInstruction)], capability));
|
|
230750
230987
|
};
|
|
230751
|
-
const estimateRequestBytes = (messages) =>
|
|
230752
|
-
systemPrompt: this.agent.effectiveSystemPrompt,
|
|
230753
|
-
messages
|
|
230754
|
-
}), "utf8");
|
|
230988
|
+
const estimateRequestBytes = (messages) => estimateBlunSerializedBodyBytes(this.agent.effectiveSystemPrompt, compactionTools, messages) + 4096;
|
|
230755
230989
|
while (true) {
|
|
230756
230990
|
signal.throwIfAborted();
|
|
230757
230991
|
if (hierarchicalPassCount >= MAX_HIERARCHICAL_COMPACTION_PASSES) throw new BlunError(ErrorCodes.COMPACTION_FAILED, `Compaction stopped after ${String(MAX_HIERARCHICAL_COMPACTION_PASSES)} staged requests without reaching a final summary. The conversation history was not changed.`, { details: {
|
|
@@ -234331,8 +234565,9 @@ function makeSyntheticToolResult(toolCallId) {
|
|
|
234331
234565
|
}
|
|
234332
234566
|
function mergeAdjacentUserMessages(history, onAnomaly) {
|
|
234333
234567
|
const out = [];
|
|
234334
|
-
|
|
234335
|
-
|
|
234568
|
+
const latestUserIndex = history.findLastIndex((message) => message.role === "user" && message.partial !== true && (message.origin === void 0 || message.origin.kind === "user"));
|
|
234569
|
+
for (const [index, source] of history.entries()) {
|
|
234570
|
+
const message = prepareMessageForProjection(source, onAnomaly, index < latestUserIndex);
|
|
234336
234571
|
if (message === null) continue;
|
|
234337
234572
|
const previous = out.at(-1);
|
|
234338
234573
|
if (canMergeUserMessage(message) && previous !== void 0 && canMergeUserMessage(previous)) {
|
|
@@ -234343,7 +234578,7 @@ function mergeAdjacentUserMessages(history, onAnomaly) {
|
|
|
234343
234578
|
}
|
|
234344
234579
|
return out.map(stripContextMetadata);
|
|
234345
234580
|
}
|
|
234346
|
-
function prepareMessageForProjection(message, onAnomaly) {
|
|
234581
|
+
function prepareMessageForProjection(message, onAnomaly, historical = false) {
|
|
234347
234582
|
if (message.partial === true) return null;
|
|
234348
234583
|
let content;
|
|
234349
234584
|
for (const [index, part] of message.content.entries()) {
|
|
@@ -234355,6 +234590,19 @@ function prepareMessageForProjection(message, onAnomaly) {
|
|
|
234355
234590
|
});
|
|
234356
234591
|
continue;
|
|
234357
234592
|
}
|
|
234593
|
+
if (historical && message.role === "user" && part.type === "text") {
|
|
234594
|
+
const text = withoutHistoricalTelegramGroupReminder(part.text);
|
|
234595
|
+
if (text !== part.text) {
|
|
234596
|
+
content ??= message.content.slice(0, index);
|
|
234597
|
+
const shortened = {
|
|
234598
|
+
...part,
|
|
234599
|
+
text
|
|
234600
|
+
};
|
|
234601
|
+
copyRequestTextOrigin(part, shortened, message.origin);
|
|
234602
|
+
content.push(shortened);
|
|
234603
|
+
continue;
|
|
234604
|
+
}
|
|
234605
|
+
}
|
|
234358
234606
|
content?.push(part);
|
|
234359
234607
|
}
|
|
234360
234608
|
const next = content === void 0 ? message : {
|
|
@@ -234364,6 +234612,14 @@ function prepareMessageForProjection(message, onAnomaly) {
|
|
|
234364
234612
|
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 } });
|
|
234365
234613
|
return next.content.length === 0 && next.toolCalls.length === 0 ? null : next;
|
|
234366
234614
|
}
|
|
234615
|
+
function withoutHistoricalTelegramGroupReminder(text) {
|
|
234616
|
+
if (!text.startsWith("<channel source=\"telegram\"") && !text.startsWith("You are connected to a Telegram channel.")) return text;
|
|
234617
|
+
const start = text.lastIndexOf(`</channel>\n[GRUPPENANTWORT:`);
|
|
234618
|
+
if (start < 0) return text;
|
|
234619
|
+
const reminder = text.slice(start + 10 + 1);
|
|
234620
|
+
if (!/^\[GRUPPENANTWORT:[^\r\n]*\]$/.test(reminder)) return text;
|
|
234621
|
+
return text.slice(0, start + 10);
|
|
234622
|
+
}
|
|
234367
234623
|
function canMergeUserMessage(message) {
|
|
234368
234624
|
return message.role === "user" && message.origin?.kind === "user";
|
|
234369
234625
|
}
|
|
@@ -234428,6 +234684,8 @@ function checkedRemovalIndexes(indexes, length) {
|
|
|
234428
234684
|
}
|
|
234429
234685
|
var ContextMemory = class {
|
|
234430
234686
|
agent;
|
|
234687
|
+
mutationGeneration = randomUUID();
|
|
234688
|
+
mutationRevision = 0;
|
|
234431
234689
|
_history = [];
|
|
234432
234690
|
_tokenCount = 0;
|
|
234433
234691
|
tokenCountCoveredMessageCount = 0;
|
|
@@ -234439,6 +234697,15 @@ var ContextMemory = class {
|
|
|
234439
234697
|
constructor(agent) {
|
|
234440
234698
|
this.agent = agent;
|
|
234441
234699
|
}
|
|
234700
|
+
publishMutation(reason) {
|
|
234701
|
+
if (this.agent.records.restoring) return;
|
|
234702
|
+
this.agent.emitEvent({
|
|
234703
|
+
type: "context.changed",
|
|
234704
|
+
generation: this.mutationGeneration,
|
|
234705
|
+
revision: ++this.mutationRevision,
|
|
234706
|
+
reason
|
|
234707
|
+
});
|
|
234708
|
+
}
|
|
234442
234709
|
get lastAssistantAt() {
|
|
234443
234710
|
return this._lastAssistantAt;
|
|
234444
234711
|
}
|
|
@@ -234592,6 +234859,7 @@ var ContextMemory = class {
|
|
|
234592
234859
|
return removedMessages.size;
|
|
234593
234860
|
}
|
|
234594
234861
|
clear() {
|
|
234862
|
+
const changed = this._history.length > 0;
|
|
234595
234863
|
this.agent.records.logRecord({ type: "context.clear" });
|
|
234596
234864
|
this._history = [];
|
|
234597
234865
|
this._tokenCount = 0;
|
|
@@ -234603,6 +234871,7 @@ var ContextMemory = class {
|
|
|
234603
234871
|
this.agent.microCompaction.reset();
|
|
234604
234872
|
this.agent.injection.onContextClear();
|
|
234605
234873
|
this.agent.emitStatusUpdated();
|
|
234874
|
+
if (changed) this.publishMutation("clear");
|
|
234606
234875
|
}
|
|
234607
234876
|
undo(count) {
|
|
234608
234877
|
if (count <= 0) return;
|
|
@@ -234640,6 +234909,7 @@ var ContextMemory = class {
|
|
|
234640
234909
|
this.deferredMessages = [];
|
|
234641
234910
|
this.agent.microCompaction.reset(this._history.length);
|
|
234642
234911
|
this.agent.emitStatusUpdated();
|
|
234912
|
+
if (removedMessages.size > 0) this.publishMutation("undo");
|
|
234643
234913
|
if (!this.agent.records.restoring && (stoppedAtBoundary || removedUserCount < count)) throw new BlunError(ErrorCodes.REQUEST_INVALID, formatUndoUnavailableMessage(count, removedUserCount, stoppedAtBoundary), { details: {
|
|
234644
234914
|
reason: "undo_limit",
|
|
234645
234915
|
requestedCount: count,
|
|
@@ -234648,6 +234918,7 @@ var ContextMemory = class {
|
|
|
234648
234918
|
} });
|
|
234649
234919
|
}
|
|
234650
234920
|
applyCompaction(input, options = {}) {
|
|
234921
|
+
if (this.agent.records.restoring !== null && input.toolContinuity !== void 0 && !isToolContinuity(input.toolContinuity)) throw new Error("Invalid compaction tool continuity");
|
|
234651
234922
|
let preservedToolTailCount = input.preservedToolTailCount;
|
|
234652
234923
|
if (this.agent.records.restoring === null && this.hasOpenToolExchange()) {
|
|
234653
234924
|
const start = this._history.findIndex((message) => message.role === "assistant" && message.toolCalls.some((call) => this.pendingToolResultIds.has(call.id)));
|
|
@@ -234684,25 +234955,75 @@ var ContextMemory = class {
|
|
|
234684
234955
|
elisionMessage,
|
|
234685
234956
|
...selection.tail
|
|
234686
234957
|
];
|
|
234687
|
-
|
|
234688
|
-
|
|
234958
|
+
let contextSummary = input.contextSummary ?? input.summary;
|
|
234959
|
+
let toolContinuity = this.agent.records.restoring === null ? void 0 : input.toolContinuity;
|
|
234960
|
+
let summaryMessage = {
|
|
234689
234961
|
role: "user",
|
|
234690
234962
|
content: [{
|
|
234691
234963
|
type: "text",
|
|
234692
234964
|
text: contextSummary
|
|
234693
234965
|
}],
|
|
234694
234966
|
toolCalls: [],
|
|
234695
|
-
origin: {
|
|
234967
|
+
origin: {
|
|
234968
|
+
kind: "compaction_summary",
|
|
234969
|
+
...toolContinuity === void 0 ? {} : { toolContinuity }
|
|
234970
|
+
}
|
|
234696
234971
|
};
|
|
234697
|
-
|
|
234972
|
+
let replacement = [
|
|
234698
234973
|
...keptMessages,
|
|
234699
234974
|
summaryMessage,
|
|
234700
234975
|
...preservedToolTail
|
|
234701
234976
|
];
|
|
234977
|
+
const previousHistoryTokens = options.requireReduction && this.agent.records.restoring === null ? estimateTokensForMessages(project(this.agent.microCompaction.compact(this._history), { dropOrphanResults: true })) : void 0;
|
|
234978
|
+
if (this.agent.records.restoring === null) {
|
|
234979
|
+
toolContinuity = void 0;
|
|
234980
|
+
const observations = collectToolContinuity(this._history.slice(0, tailStart));
|
|
234981
|
+
if (observations !== void 0) {
|
|
234982
|
+
const baseProjected = project(replacement, { dropOrphanResults: true });
|
|
234983
|
+
const baseTokens = estimateTokensForMessages(baseProjected);
|
|
234984
|
+
let extraTokens = previousHistoryTokens === void 0 ? Number.POSITIVE_INFINITY : Math.max(0, previousHistoryTokens - baseTokens - 1);
|
|
234985
|
+
if (this.agent.config.hasProvider) {
|
|
234986
|
+
const window = this.agent.fullCompaction.getEffectiveMaxContextTokens();
|
|
234987
|
+
const budget = this.agent.fullCompaction.getCompactionBudgetTokens();
|
|
234988
|
+
const requestLimit = Math.min(window > 0 ? window - 1 : Number.POSITIVE_INFINITY, budget ?? Number.POSITIVE_INFINITY);
|
|
234989
|
+
extraTokens = Math.min(extraTokens, Math.max(0, requestLimit - this.agent.fullCompaction.estimateProjectedRequestTokens({ messages: baseProjected }) - 1));
|
|
234990
|
+
}
|
|
234991
|
+
let fitted = fitToolContinuity(observations, extraTokens);
|
|
234992
|
+
while (fitted !== void 0) {
|
|
234993
|
+
const candidateSummary = {
|
|
234994
|
+
...summaryMessage,
|
|
234995
|
+
content: [{
|
|
234996
|
+
type: "text",
|
|
234997
|
+
text: contextSummary + fitted.text
|
|
234998
|
+
}],
|
|
234999
|
+
origin: {
|
|
235000
|
+
kind: "compaction_summary",
|
|
235001
|
+
toolContinuity: fitted.continuity
|
|
235002
|
+
}
|
|
235003
|
+
};
|
|
235004
|
+
const candidate = [
|
|
235005
|
+
...keptMessages,
|
|
235006
|
+
candidateSummary,
|
|
235007
|
+
...preservedToolTail
|
|
235008
|
+
];
|
|
235009
|
+
const projected = project(candidate, { dropOrphanResults: true });
|
|
235010
|
+
const status = this.agent.fullCompaction.proactiveCompactionStatus({ messages: projected });
|
|
235011
|
+
const reducing = previousHistoryTokens === void 0 || estimateTokensForMessages(projected) < previousHistoryTokens;
|
|
235012
|
+
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);
|
|
235013
|
+
if (reducing && bytesFit) {
|
|
235014
|
+
toolContinuity = fitted.continuity;
|
|
235015
|
+
contextSummary += fitted.text;
|
|
235016
|
+
summaryMessage = candidateSummary;
|
|
235017
|
+
replacement = candidate;
|
|
235018
|
+
break;
|
|
235019
|
+
}
|
|
235020
|
+
fitted = fitToolContinuity(observations, estimateTokens(fitted.text) - 1);
|
|
235021
|
+
}
|
|
235022
|
+
}
|
|
235023
|
+
}
|
|
234702
235024
|
if (options.requireReduction && this.agent.records.restoring === null) {
|
|
234703
|
-
const previousHistoryTokens = estimateTokensForMessages(project(this.agent.microCompaction.compact(this._history), { dropOrphanResults: true }));
|
|
234704
235025
|
const nextHistoryTokens = estimateTokensForMessages(project(replacement, { dropOrphanResults: true }));
|
|
234705
|
-
if (nextHistoryTokens >= previousHistoryTokens) throw new BlunError(ErrorCodes.COMPACTION_FAILED, "Automatic compaction did not reduce the history. The conversation history was not changed.", { details: {
|
|
235026
|
+
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: {
|
|
234706
235027
|
reason: "non_reducing_summary",
|
|
234707
235028
|
contextUnchanged: true,
|
|
234708
235029
|
previousHistoryTokens,
|
|
@@ -234715,6 +235036,7 @@ var ContextMemory = class {
|
|
|
234715
235036
|
const result = {
|
|
234716
235037
|
summary: input.summary,
|
|
234717
235038
|
contextSummary,
|
|
235039
|
+
...toolContinuity === void 0 ? {} : { toolContinuity },
|
|
234718
235040
|
compactedCount: input.compactedCount,
|
|
234719
235041
|
tokensBefore: input.tokensBefore,
|
|
234720
235042
|
tokensAfter,
|
|
@@ -234731,6 +235053,7 @@ var ContextMemory = class {
|
|
|
234731
235053
|
this.agent.replayBuilder.patchLast("compaction", { result: {
|
|
234732
235054
|
summary: result.summary,
|
|
234733
235055
|
contextSummary: result.contextSummary,
|
|
235056
|
+
...result.toolContinuity === void 0 ? {} : { toolContinuity: result.toolContinuity },
|
|
234734
235057
|
compactedCount: result.compactedCount,
|
|
234735
235058
|
tokensBefore: result.tokensBefore,
|
|
234736
235059
|
tokensAfter: result.tokensAfter,
|
|
@@ -236338,20 +236661,75 @@ function fingerprintTitle(title) {
|
|
|
236338
236661
|
return createHash("sha256").update(title.trim().toLowerCase()).digest("hex");
|
|
236339
236662
|
}
|
|
236340
236663
|
async function loadRegister(mistakeDir = defaultMistakeDir()) {
|
|
236664
|
+
const target = join(mistakeDir, REGISTER_FILENAME);
|
|
236341
236665
|
try {
|
|
236342
236666
|
await mkdir(mistakeDir, { recursive: true });
|
|
236343
|
-
const
|
|
236344
|
-
|
|
236345
|
-
|
|
236346
|
-
|
|
236667
|
+
const before = await lstat(target).catch((error) => {
|
|
236668
|
+
if (error.code === "ENOENT") return void 0;
|
|
236669
|
+
throw error;
|
|
236670
|
+
});
|
|
236671
|
+
if (before === void 0) return {
|
|
236347
236672
|
version: 1,
|
|
236348
236673
|
entries: []
|
|
236349
236674
|
};
|
|
236675
|
+
if (!before.isFile() || before.isSymbolicLink()) throw new Error("Mistake register must be a regular file.");
|
|
236676
|
+
const handle = await open(target, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
|
|
236677
|
+
let content;
|
|
236678
|
+
try {
|
|
236679
|
+
const opened = await handle.stat();
|
|
236680
|
+
if (!opened.isFile() || opened.dev !== before.dev || opened.ino !== before.ino) throw new Error("Mistake register changed while opening.");
|
|
236681
|
+
content = await handle.readFile("utf8");
|
|
236682
|
+
} finally {
|
|
236683
|
+
await handle.close();
|
|
236684
|
+
}
|
|
236685
|
+
let parsed;
|
|
236686
|
+
try {
|
|
236687
|
+
parsed = JSON.parse(content);
|
|
236688
|
+
} catch {
|
|
236689
|
+
throw new Error("Mistake register has invalid JSON.");
|
|
236690
|
+
}
|
|
236691
|
+
assertRegister(parsed);
|
|
236692
|
+
return parsed;
|
|
236693
|
+
} catch (error) {
|
|
236694
|
+
throw registerError(error, "read");
|
|
236350
236695
|
}
|
|
236351
236696
|
}
|
|
236352
236697
|
async function saveRegister(register, mistakeDir = defaultMistakeDir()) {
|
|
236353
|
-
|
|
236354
|
-
|
|
236698
|
+
assertRegister(register);
|
|
236699
|
+
const target = join(mistakeDir, REGISTER_FILENAME);
|
|
236700
|
+
const temporary = `${target}.tmp.${process.pid}.${randomUUID()}`;
|
|
236701
|
+
let created = false;
|
|
236702
|
+
try {
|
|
236703
|
+
await loadRegister(mistakeDir);
|
|
236704
|
+
const handle = await open(temporary, "wx", 384);
|
|
236705
|
+
created = true;
|
|
236706
|
+
try {
|
|
236707
|
+
await handle.writeFile(JSON.stringify(register, null, 2), "utf8");
|
|
236708
|
+
await handle.sync();
|
|
236709
|
+
} finally {
|
|
236710
|
+
await handle.close();
|
|
236711
|
+
}
|
|
236712
|
+
await rename(temporary, target);
|
|
236713
|
+
} catch (error) {
|
|
236714
|
+
throw registerError(error, "write");
|
|
236715
|
+
} finally {
|
|
236716
|
+
if (created) await unlink(temporary).catch(() => {});
|
|
236717
|
+
}
|
|
236718
|
+
}
|
|
236719
|
+
function assertRegister(value) {
|
|
236720
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error("Mistake register has an invalid v1 schema.");
|
|
236721
|
+
const register = value;
|
|
236722
|
+
if (register["version"] !== 1 || !Array.isArray(register["entries"]) || !register["entries"].every((entry) => {
|
|
236723
|
+
if (typeof entry !== "object" || entry === null || Array.isArray(entry)) return false;
|
|
236724
|
+
const fields = entry;
|
|
236725
|
+
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");
|
|
236726
|
+
})) throw new Error("Mistake register has an invalid v1 schema.");
|
|
236727
|
+
}
|
|
236728
|
+
function registerError(error, operation) {
|
|
236729
|
+
if (error instanceof Error && error.message.startsWith("Mistake register ")) return error;
|
|
236730
|
+
const code = typeof error === "object" && error !== null ? error.code : void 0;
|
|
236731
|
+
const suffix = typeof code === "string" && /^[A-Z0-9_]+$/u.test(code) ? ` (${code})` : "";
|
|
236732
|
+
return /* @__PURE__ */ new Error(`Mistake register ${operation} failed${suffix}.`);
|
|
236355
236733
|
}
|
|
236356
236734
|
/**
|
|
236357
236735
|
* Findet einen Register-Eintrag anhand des Titels (Fingerabdruck).
|
|
@@ -239044,6 +239422,7 @@ var import_turn_tool_performance_policy = (/* @__PURE__ */ __commonJSMin(((expor
|
|
|
239044
239422
|
const DEFERRED_TOOL_LOADER_NAME = "ToolSearch";
|
|
239045
239423
|
const MAX_PERSISTENT_DEFERRED_TOOLS = 12;
|
|
239046
239424
|
const MAX_TOOL_SEARCH_QUERY_CHARS = 1e3;
|
|
239425
|
+
const MAX_TOOL_CATALOG_RESULT_BYTES = 4096;
|
|
239047
239426
|
const MAX_AUTO_RANKED_TOOLS = 6;
|
|
239048
239427
|
const deferredToolLoaders = /* @__PURE__ */ new WeakSet();
|
|
239049
239428
|
const TOOL_RANK_EMBEDDED_CONTENT_RE = /<(attached_documents?|attachment_content|document_content|file_content)\b[^>]*>[\s\S]*?<\/\1>/giu;
|
|
@@ -239288,6 +239667,27 @@ var import_turn_tool_performance_policy = (/* @__PURE__ */ __commonJSMin(((expor
|
|
|
239288
239667
|
for (const leaf of leaves) leafCounts.set(leaf, (leafCounts.get(leaf) || 0) + 1);
|
|
239289
239668
|
return names.map((name, index) => leafCounts.get(leaves[index]) === 1 ? leaves[index] : name).sort((left, right) => left.localeCompare(right));
|
|
239290
239669
|
}
|
|
239670
|
+
function boundedDeferredToolCatalog(tools, filter) {
|
|
239671
|
+
const needle = filter.toLowerCase();
|
|
239672
|
+
const matched = deferredToolCatalog(tools).filter((name) => name.toLowerCase().includes(needle));
|
|
239673
|
+
const names = [];
|
|
239674
|
+
let bytes = Buffer.byteLength(JSON.stringify({
|
|
239675
|
+
names,
|
|
239676
|
+
total: matched.length,
|
|
239677
|
+
truncated: false
|
|
239678
|
+
}));
|
|
239679
|
+
for (const name of matched) {
|
|
239680
|
+
const nextBytes = Buffer.byteLength(JSON.stringify(name)) + (names.length > 0 ? 1 : 0);
|
|
239681
|
+
if (bytes + nextBytes > MAX_TOOL_CATALOG_RESULT_BYTES) break;
|
|
239682
|
+
names.push(name);
|
|
239683
|
+
bytes += nextBytes;
|
|
239684
|
+
}
|
|
239685
|
+
return JSON.stringify({
|
|
239686
|
+
names,
|
|
239687
|
+
total: matched.length,
|
|
239688
|
+
truncated: names.length < matched.length
|
|
239689
|
+
});
|
|
239690
|
+
}
|
|
239291
239691
|
function normalizeDeferredToolQuery(value) {
|
|
239292
239692
|
const query = String(value ?? "").trim();
|
|
239293
239693
|
if (query.length <= MAX_TOOL_SEARCH_QUERY_CHARS) return query;
|
|
@@ -239362,14 +239762,14 @@ var import_turn_tool_performance_policy = (/* @__PURE__ */ __commonJSMin(((expor
|
|
|
239362
239762
|
function rankingTokens(value) {
|
|
239363
239763
|
return [...new Set(String(value || "").normalize("NFKC").toLowerCase().match(/[\p{L}\p{N}]{3,}/gu) || [])].filter((token) => !TOOL_RANK_STOP_WORDS.has(token));
|
|
239364
239764
|
}
|
|
239365
|
-
function toolRankingDocument(tool) {
|
|
239765
|
+
function toolRankingDocument(tool, trustedToolNames) {
|
|
239366
239766
|
const name = String(tool?.name || "");
|
|
239367
239767
|
const leaf = name.split(/__|:/).at(-1) || name;
|
|
239368
239768
|
const splitToolName = (value) => String(value || "").replace(/([a-z0-9])([A-Z])/g, "$1 $2").replaceAll("_", " ");
|
|
239369
239769
|
const nameTokens = rankingTokens(`${splitToolName(name)} ${splitToolName(leaf)}`);
|
|
239370
239770
|
const descriptionTokens = rankingTokens(tool?.description);
|
|
239371
239771
|
const parameterText = [];
|
|
239372
|
-
const properties = tool?.parameters?.properties;
|
|
239772
|
+
const properties = /^mcp__/iu.test(name) && !trustedToolNames?.has(name) ? void 0 : tool?.parameters?.properties;
|
|
239373
239773
|
if (properties && typeof properties === "object") for (const [parameterName, definition] of Object.entries(properties)) parameterText.push(parameterName, definition?.description || "");
|
|
239374
239774
|
const exampleText = Array.isArray(tool?.examples) ? tool.examples.map((example) => example?.prompt || "").join(" ") : "";
|
|
239375
239775
|
return {
|
|
@@ -239401,7 +239801,7 @@ var import_turn_tool_performance_policy = (/* @__PURE__ */ __commonJSMin(((expor
|
|
|
239401
239801
|
const queryTokens = [...new Set(rankingIntentTexts(value).flatMap(rankingTokens))];
|
|
239402
239802
|
if (queryTokens.length === 0) return /* @__PURE__ */ new Set();
|
|
239403
239803
|
const ranked = (Array.isArray(tools) ? tools : []).map((tool) => {
|
|
239404
|
-
const document = toolRankingDocument(tool);
|
|
239804
|
+
const document = toolRankingDocument(tool, options.trustedToolNames);
|
|
239405
239805
|
if (!document.name) return null;
|
|
239406
239806
|
let score = 0;
|
|
239407
239807
|
let matchedTokens = 0;
|
|
@@ -239509,8 +239909,8 @@ var import_turn_tool_performance_policy = (/* @__PURE__ */ __commonJSMin(((expor
|
|
|
239509
239909
|
name: loaderName,
|
|
239510
239910
|
description: [
|
|
239511
239911
|
`Search ${deferredCount} deferred ${deferredCount === 1 ? "tool schema" : "tool schemas"} without loading all definitions.`,
|
|
239512
|
-
"Use select:leaf_name for one known tool, plain keywords to search,
|
|
239513
|
-
`Loaded tools are available in the next step;
|
|
239912
|
+
"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.",
|
|
239913
|
+
`Loaded tools are available in the next step; up to ${MAX_PERSISTENT_DEFERRED_TOOLS} recently selected schemas remain loaded when the context budget allows.`
|
|
239514
239914
|
].join("\n"),
|
|
239515
239915
|
parameters: {
|
|
239516
239916
|
type: "object",
|
|
@@ -239527,7 +239927,12 @@ var import_turn_tool_performance_policy = (/* @__PURE__ */ __commonJSMin(((expor
|
|
|
239527
239927
|
return {
|
|
239528
239928
|
description: query ? `Searching tool schemas for ${query}` : "Searching tool schemas",
|
|
239529
239929
|
approvalRule: loaderName,
|
|
239530
|
-
execute: async () => {
|
|
239930
|
+
execute: async (context) => {
|
|
239931
|
+
context?.signal?.throwIfAborted();
|
|
239932
|
+
if (query.toLowerCase().startsWith("catalog:")) return {
|
|
239933
|
+
isError: false,
|
|
239934
|
+
output: boundedDeferredToolCatalog([...available.values()], query.slice(8).trim())
|
|
239935
|
+
};
|
|
239531
239936
|
let matches = searchDeferredTools([...available.values()], query);
|
|
239532
239937
|
let relatedFallback = false;
|
|
239533
239938
|
if (matches.length === 0) {
|
|
@@ -251393,7 +251798,11 @@ const goalChangeStatsSchema = object({
|
|
|
251393
251798
|
wallClockMs: number$1()
|
|
251394
251799
|
});
|
|
251395
251800
|
const goalChangeSchema = object({
|
|
251396
|
-
kind: _enum([
|
|
251801
|
+
kind: _enum([
|
|
251802
|
+
"lifecycle",
|
|
251803
|
+
"completion",
|
|
251804
|
+
"edited"
|
|
251805
|
+
]),
|
|
251397
251806
|
status: goalStatusSchema.optional(),
|
|
251398
251807
|
reason: string().optional(),
|
|
251399
251808
|
stats: goalChangeStatsSchema.optional(),
|
|
@@ -251544,6 +251953,12 @@ const turnEndReasonSchema = _enum([
|
|
|
251544
251953
|
"failed",
|
|
251545
251954
|
"filtered"
|
|
251546
251955
|
]);
|
|
251956
|
+
const contextChangedEventSchema = object({
|
|
251957
|
+
type: literal("context.changed"),
|
|
251958
|
+
generation: string().uuid(),
|
|
251959
|
+
revision: number$1().int().positive().max(Number.MAX_SAFE_INTEGER),
|
|
251960
|
+
reason: _enum(["clear", "undo"])
|
|
251961
|
+
});
|
|
251547
251962
|
const agentStatusUpdatedEventSchema = object({
|
|
251548
251963
|
type: literal("agent.status.updated"),
|
|
251549
251964
|
model: string().optional(),
|
|
@@ -251863,6 +252278,7 @@ const eventSchema = discriminatedUnion("type", [
|
|
|
251863
252278
|
errorEventSchema,
|
|
251864
252279
|
warningEventSchema,
|
|
251865
252280
|
agentStatusUpdatedEventSchema,
|
|
252281
|
+
contextChangedEventSchema,
|
|
251866
252282
|
sessionMetaUpdatedEventSchema,
|
|
251867
252283
|
sessionCreatedEventSchema,
|
|
251868
252284
|
workspaceCreatedEventSchema,
|
|
@@ -265263,9 +265679,16 @@ var ToolCallDeduplicator = class {
|
|
|
265263
265679
|
//#region ../../packages/agent-core/src/agent/turn/tool-result-budget.ts
|
|
265264
265680
|
const TOOL_RESULT_MAX_CHARS = 5e4;
|
|
265265
265681
|
const TOOL_RESULT_PREVIEW_CHARS = 2e3;
|
|
265682
|
+
function toolResultMaxChars(maxContextTokens) {
|
|
265683
|
+
if (maxContextTokens === void 0 || !Number.isFinite(maxContextTokens) || maxContextTokens <= 0) return TOOL_RESULT_MAX_CHARS;
|
|
265684
|
+
if (maxContextTokens < 1e5) return 16e3;
|
|
265685
|
+
if (maxContextTokens < 2e5) return 32e3;
|
|
265686
|
+
return TOOL_RESULT_MAX_CHARS;
|
|
265687
|
+
}
|
|
265266
265688
|
async function budgetToolResultForModel(options) {
|
|
265267
265689
|
const text = persistableToolResultText(options.result.output);
|
|
265268
|
-
|
|
265690
|
+
const maxChars = toolResultMaxChars(options.maxContextTokens);
|
|
265691
|
+
if (text === void 0 || text.length <= maxChars) return options.result;
|
|
265269
265692
|
if (options.result.truncated === true) return options.result;
|
|
265270
265693
|
if (options.homedir === void 0) return options.result;
|
|
265271
265694
|
if (text.includes("\0") || Buffer.from(text, "utf8").toString("utf8") !== text || text.split("\n").some((line) => line.length > 2e3)) return options.result;
|
|
@@ -265276,7 +265699,7 @@ async function budgetToolResultForModel(options) {
|
|
|
265276
265699
|
toolCallId: options.toolCallId
|
|
265277
265700
|
}, text);
|
|
265278
265701
|
if (outputPath === void 0) return options.result;
|
|
265279
|
-
const output = renderPersistedToolResult(options.toolName, options.toolCallId, text, outputPath);
|
|
265702
|
+
const output = renderPersistedToolResult(options.toolName, options.toolCallId, text, outputPath, maxChars);
|
|
265280
265703
|
return options.result.isError === true ? {
|
|
265281
265704
|
...options.result,
|
|
265282
265705
|
output,
|
|
@@ -265308,9 +265731,9 @@ async function saveToolResult(options, text) {
|
|
|
265308
265731
|
return;
|
|
265309
265732
|
}
|
|
265310
265733
|
}
|
|
265311
|
-
function renderPersistedToolResult(toolName, toolCallId, text, outputPath) {
|
|
265734
|
+
function renderPersistedToolResult(toolName, toolCallId, text, outputPath, maxChars) {
|
|
265312
265735
|
const lines = [
|
|
265313
|
-
`Tool output exceeded ${String(
|
|
265736
|
+
`Tool output exceeded ${String(maxChars)} characters; showing a preview only.`,
|
|
265314
265737
|
`tool_name: ${toolName}`,
|
|
265315
265738
|
`tool_call_id: ${toolCallId}`,
|
|
265316
265739
|
`output_size_chars: ${String(text.length)}`,
|
|
@@ -267276,14 +267699,27 @@ function blunToolsForOrigin(tools, origin) {
|
|
|
267276
267699
|
* the ordinary permission pipeline.
|
|
267277
267700
|
*/
|
|
267278
267701
|
function blunSelectTurnTools(tools, maxContextTokens, loadedToolNames = /* @__PURE__ */ new Set(), requiredToolNames = /* @__PURE__ */ new Set(), selected = []) {
|
|
267279
|
-
|
|
267702
|
+
const schemaBudget = (0, import_turn_tool_performance_policy.toolSchemaBudgetTokens)(maxContextTokens);
|
|
267703
|
+
if (estimateTokensForTools(tools, schemaBudget) <= schemaBudget || tools.some(import_turn_tool_performance_policy.isDeferredToolLoader)) {
|
|
267280
267704
|
selected.splice(0, selected.length, ...tools);
|
|
267281
267705
|
return selected;
|
|
267282
267706
|
}
|
|
267283
|
-
|
|
267284
|
-
const
|
|
267285
|
-
const
|
|
267286
|
-
|
|
267707
|
+
const priorLoaderIndex = selected.findIndex(import_turn_tool_performance_policy.isDeferredToolLoader);
|
|
267708
|
+
const justLoaded = new Set(priorLoaderIndex < 0 ? [] : selected.slice(priorLoaderIndex + 1).filter((tool) => loadedToolNames.has(tool.name)).map((tool) => tool.name));
|
|
267709
|
+
const remembered = new Set(loadedToolNames);
|
|
267710
|
+
const choose = () => {
|
|
267711
|
+
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)));
|
|
267712
|
+
const names = new Set(selected.map((tool) => tool.name));
|
|
267713
|
+
const deferred = tools.filter((tool) => !names.has(tool.name));
|
|
267714
|
+
if (deferred.length > 0) selected.push((0, import_turn_tool_performance_policy.createDeferredToolLoader)(selected, deferred, loadedToolNames));
|
|
267715
|
+
};
|
|
267716
|
+
choose();
|
|
267717
|
+
for (const name of loadedToolNames) {
|
|
267718
|
+
if (estimateTokensForTools(selected, schemaBudget) <= schemaBudget) break;
|
|
267719
|
+
if (justLoaded.has(name)) continue;
|
|
267720
|
+
if (!remembered.delete(name)) continue;
|
|
267721
|
+
choose();
|
|
267722
|
+
}
|
|
267287
267723
|
return selected;
|
|
267288
267724
|
}
|
|
267289
267725
|
const LLM_NOT_SET_MESSAGE = "LLM not set, send \"/login\" to login";
|
|
@@ -268044,10 +268480,12 @@ var TurnFlow = class {
|
|
|
268044
268480
|
taskToolsNeeded ||= blunTurnNeedsTools(intent, origin) || blunTurnHasAttachment(toolInput);
|
|
268045
268481
|
const required = (0, import_turn_tool_performance_policy.mediaToolNamesForTurnText)(blunExtractText(toolInput));
|
|
268046
268482
|
if (taskToolsNeeded) {
|
|
268047
|
-
|
|
268048
|
-
|
|
268483
|
+
const maxContextTokens = this.agent.fullCompaction.getEffectiveMaxContextTokens();
|
|
268484
|
+
blunSelectTurnTools(eligibleTools, maxContextTokens, this.loadedToolNames, required, selectedTools);
|
|
268485
|
+
const trustedToolNames = new Set(eligibleTools.filter((tool) => this.agent.tools.isUserTool(tool)).map((tool) => tool.name));
|
|
268486
|
+
for (const name of (0, import_turn_tool_performance_policy.rankedToolNamesForTurnText)(eligibleTools, blunExtractText(intent), { trustedToolNames })) {
|
|
268049
268487
|
const tool = eligibleTools.find((candidate) => candidate.name === name);
|
|
268050
|
-
if (tool !== void 0 && !selectedTools.some((candidate) => candidate.name === name) && estimateTokensForTools([...selectedTools, tool]) <= (0, import_turn_tool_performance_policy.toolSchemaBudgetTokens)(
|
|
268488
|
+
if (tool !== void 0 && !selectedTools.some((candidate) => candidate.name === name) && estimateTokensForTools([...selectedTools, tool]) <= (0, import_turn_tool_performance_policy.toolSchemaBudgetTokens)(maxContextTokens)) selectedTools.push(tool);
|
|
268051
268489
|
}
|
|
268052
268490
|
} 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)));
|
|
268053
268491
|
recordPreRequestPhase("tool-selection", selectionStartedAt);
|
|
@@ -268188,6 +268626,7 @@ var TurnFlow = class {
|
|
|
268188
268626
|
});
|
|
268189
268627
|
return budgetToolResultForModel({
|
|
268190
268628
|
homedir: this.agent.homedir,
|
|
268629
|
+
maxContextTokens: this.agent.fullCompaction.getEffectiveMaxContextTokens(),
|
|
268191
268630
|
toolName: ctx.toolCall.name,
|
|
268192
268631
|
toolCallId: ctx.toolCall.id,
|
|
268193
268632
|
result: finalResult
|
|
@@ -269045,10 +269484,10 @@ var BashTool = class {
|
|
|
269045
269484
|
},
|
|
269046
269485
|
approvalRule: literalRulePattern(this.name, args.command),
|
|
269047
269486
|
matchesRule: (ruleArgs) => matchesGlobRuleSubject(ruleArgs, args.command),
|
|
269048
|
-
execute: ({ signal, onUpdate, onForegroundTaskStart }) => this.execution(args, signal, onUpdate, onForegroundTaskStart)
|
|
269487
|
+
execute: ({ signal, onUpdate, onForegroundTaskStart, executionOrigin }) => this.execution(args, signal, onUpdate, onForegroundTaskStart, executionOrigin)
|
|
269049
269488
|
};
|
|
269050
269489
|
}
|
|
269051
|
-
spawn(effectiveCwd, command) {
|
|
269490
|
+
spawn(effectiveCwd, command, executionOrigin) {
|
|
269052
269491
|
const shellCwd = this.isWindowsBash ? windowsPathToPosixPath(effectiveCwd) : effectiveCwd;
|
|
269053
269492
|
const shellArgs = [
|
|
269054
269493
|
this.kaos.osEnv.shellPath,
|
|
@@ -269065,9 +269504,11 @@ var BashTool = class {
|
|
|
269065
269504
|
...process.env,
|
|
269066
269505
|
...noninteractiveEnv
|
|
269067
269506
|
};
|
|
269507
|
+
delete mergedEnv["BLUN_SHELL"];
|
|
269508
|
+
if (executionOrigin === "operator_shell") mergedEnv["BLUN_SHELL"] = "operator-local";
|
|
269068
269509
|
return this.kaos.execWithEnv(shellArgs, mergedEnv);
|
|
269069
269510
|
}
|
|
269070
|
-
async execution(args, signal, onUpdate, onForegroundTaskStart) {
|
|
269511
|
+
async execution(args, signal, onUpdate, onForegroundTaskStart, executionOrigin) {
|
|
269071
269512
|
const validationError = this.validateRunRequest(args, signal);
|
|
269072
269513
|
if (validationError !== void 0) return validationError;
|
|
269073
269514
|
const startsInBackground = args.run_in_background === true;
|
|
@@ -269079,7 +269520,7 @@ var BashTool = class {
|
|
|
269079
269520
|
const builder = new ToolResultBuilder();
|
|
269080
269521
|
let proc;
|
|
269081
269522
|
try {
|
|
269082
|
-
proc = await this.spawn(effectiveCwd, command);
|
|
269523
|
+
proc = await this.spawn(effectiveCwd, command, executionOrigin);
|
|
269083
269524
|
} catch (error) {
|
|
269084
269525
|
return {
|
|
269085
269526
|
isError: true,
|
|
@@ -269443,14 +269884,14 @@ function classifySearchError(error) {
|
|
|
269443
269884
|
}
|
|
269444
269885
|
//#endregion
|
|
269445
269886
|
//#region ../../packages/agent-core/src/tools/builtin/search/codebase-search.md?raw
|
|
269446
|
-
var 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
|
|
269887
|
+
var 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";
|
|
269447
269888
|
//#endregion
|
|
269448
269889
|
//#region ../../packages/agent-core/src/tools/builtin/search/codebase-search.ts
|
|
269449
269890
|
/**
|
|
269450
269891
|
* CodebaseSearchTool — semantic code search via the codebase-index.
|
|
269451
269892
|
*
|
|
269452
269893
|
* Shells out to `python codebase_index.py query <repo> "<frage>" --top N`
|
|
269453
|
-
* through
|
|
269894
|
+
* through asynchronous execFile. The script lives at
|
|
269454
269895
|
* `packages/codebase-index/codebase_index.py` relative to the workspace root.
|
|
269455
269896
|
*
|
|
269456
269897
|
* Unlike Grep (keyword/regex) or Glob (file-name patterns), this tool finds
|
|
@@ -269458,11 +269899,13 @@ var codebase_search_default = "Find code by **meaning**, not by keywords.\n\nThi
|
|
|
269458
269899
|
* to the query, so it can locate a keyboard handler even when the word
|
|
269459
269900
|
* "keyboard" never appears in the source.
|
|
269460
269901
|
*/
|
|
269902
|
+
const MAX_SEARCH_RESULTS = 100;
|
|
269461
269903
|
const CodebaseSearchInputSchema = object({
|
|
269462
269904
|
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\"."),
|
|
269463
|
-
top: number$1().int().positive().default(5).describe(
|
|
269905
|
+
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.`)
|
|
269464
269906
|
});
|
|
269465
269907
|
const SCRIPT_TIMEOUT_MS = 6e4;
|
|
269908
|
+
const SCRIPT_MAX_BUFFER = 1024 * 1024;
|
|
269466
269909
|
function isScriptFile(path) {
|
|
269467
269910
|
try {
|
|
269468
269911
|
return statSync(path).isFile();
|
|
@@ -269501,45 +269944,72 @@ var CodebaseSearchTool = class {
|
|
|
269501
269944
|
},
|
|
269502
269945
|
approvalRule: literalRulePattern(this.name, args.query),
|
|
269503
269946
|
matchesRule: (ruleArgs) => matchesGlobRuleSubject(ruleArgs, args.query),
|
|
269504
|
-
execute: () =>
|
|
269947
|
+
execute: async (context) => {
|
|
269948
|
+
context.signal.throwIfAborted();
|
|
269949
|
+
return this.execution(args, context.signal);
|
|
269950
|
+
}
|
|
269505
269951
|
};
|
|
269506
269952
|
}
|
|
269507
|
-
execution(args) {
|
|
269953
|
+
async execution(args, signal) {
|
|
269508
269954
|
const builder = new ToolResultBuilder();
|
|
269509
|
-
if (
|
|
269955
|
+
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)}.`);
|
|
269956
|
+
if (this.scriptPath.length === 0) return builder.error("Could not locate codebase_index.py. Set CODEBASE_INDEX_SCRIPT to its absolute path.");
|
|
269510
269957
|
try {
|
|
269511
|
-
const result =
|
|
269512
|
-
|
|
269513
|
-
|
|
269514
|
-
|
|
269515
|
-
|
|
269516
|
-
|
|
269517
|
-
|
|
269518
|
-
|
|
269519
|
-
|
|
269520
|
-
|
|
269521
|
-
|
|
269522
|
-
|
|
269523
|
-
|
|
269524
|
-
|
|
269958
|
+
const result = await new Promise((resolve) => {
|
|
269959
|
+
let closed = false;
|
|
269960
|
+
let output;
|
|
269961
|
+
const finish = () => {
|
|
269962
|
+
if (closed && output !== void 0) resolve(output);
|
|
269963
|
+
};
|
|
269964
|
+
execFile("python", [
|
|
269965
|
+
this.scriptPath,
|
|
269966
|
+
"query",
|
|
269967
|
+
this.cwd,
|
|
269968
|
+
args.query,
|
|
269969
|
+
"--top",
|
|
269970
|
+
String(args.top),
|
|
269971
|
+
"--model",
|
|
269972
|
+
"auto"
|
|
269973
|
+
], {
|
|
269974
|
+
cwd: this.cwd,
|
|
269975
|
+
timeout: SCRIPT_TIMEOUT_MS,
|
|
269976
|
+
encoding: "utf-8",
|
|
269977
|
+
windowsHide: true,
|
|
269978
|
+
shell: false,
|
|
269979
|
+
maxBuffer: SCRIPT_MAX_BUFFER,
|
|
269980
|
+
signal
|
|
269981
|
+
}, (error, stdout, stderr) => {
|
|
269982
|
+
output = {
|
|
269983
|
+
error,
|
|
269984
|
+
stdout,
|
|
269985
|
+
stderr
|
|
269986
|
+
};
|
|
269987
|
+
finish();
|
|
269988
|
+
}).once("close", () => {
|
|
269989
|
+
closed = true;
|
|
269990
|
+
finish();
|
|
269991
|
+
});
|
|
269525
269992
|
});
|
|
269526
|
-
|
|
269993
|
+
signal.throwIfAborted();
|
|
269994
|
+
if (result.error !== null && typeof result.error.code !== "number") {
|
|
269527
269995
|
const msg = result.error instanceof Error ? result.error.message : String(result.error);
|
|
269528
|
-
|
|
269996
|
+
builder.write(result.stdout + result.stderr);
|
|
269997
|
+
return builder.error(`Failed to run codebase_index.py: ${msg}`);
|
|
269529
269998
|
}
|
|
269530
269999
|
const stdout = result.stdout ?? "";
|
|
269531
270000
|
const stderr = result.stderr ?? "";
|
|
269532
|
-
const exitCode = result.
|
|
270001
|
+
const exitCode = result.error?.code ?? 0;
|
|
269533
270002
|
if (exitCode !== 0) {
|
|
269534
270003
|
const combined = stderr.trim().length > 0 ? `${stdout}${stdout.length > 0 ? "\n" : ""}Error: ${stderr.trim()}` : stdout;
|
|
269535
270004
|
builder.write(combined.length > 0 ? combined : `codebase_index.py exited with code ${String(exitCode)}`);
|
|
269536
|
-
return
|
|
270005
|
+
return builder.error(`Codebase search failed with exit code ${String(exitCode)}.`);
|
|
269537
270006
|
}
|
|
269538
270007
|
builder.write(stdout.length > 0 ? stdout : "No results found.");
|
|
269539
|
-
return
|
|
270008
|
+
return builder.ok();
|
|
269540
270009
|
} catch (error) {
|
|
270010
|
+
signal.throwIfAborted();
|
|
269541
270011
|
const msg = error instanceof Error ? error.message : String(error);
|
|
269542
|
-
return
|
|
270012
|
+
return builder.error(`Codebase search error: ${msg}`);
|
|
269543
270013
|
}
|
|
269544
270014
|
}
|
|
269545
270015
|
};
|
|
@@ -270779,6 +271249,7 @@ var ToolManager = class {
|
|
|
270779
271249
|
const result = await execution.execute({
|
|
270780
271250
|
turnId: "",
|
|
270781
271251
|
toolCallId: "shell-command",
|
|
271252
|
+
executionOrigin: "operator_shell",
|
|
270782
271253
|
signal: controller.signal,
|
|
270783
271254
|
onUpdate: (update) => {
|
|
270784
271255
|
if (update.kind === "stdout") stdout += update.text ?? "";
|
|
@@ -270867,6 +271338,9 @@ var ToolManager = class {
|
|
|
270867
271338
|
hasUserTool(name) {
|
|
270868
271339
|
return this.userTools.has(name);
|
|
270869
271340
|
}
|
|
271341
|
+
isUserTool(tool) {
|
|
271342
|
+
return this.userTools.get(tool.name) === tool;
|
|
271343
|
+
}
|
|
270870
271344
|
inheritUserTools(parent) {
|
|
270871
271345
|
for (const tool of parent.userTools.values()) {
|
|
270872
271346
|
if (!parent.enabledTools.has(tool.name)) continue;
|
|
@@ -272112,6 +272586,9 @@ var Agent$1 = class {
|
|
|
272112
272586
|
additionalDirs;
|
|
272113
272587
|
systemPromptStartedAt = /* @__PURE__ */ new Date();
|
|
272114
272588
|
activeProfile;
|
|
272589
|
+
rawSystemPromptContext;
|
|
272590
|
+
profileSystemPromptText;
|
|
272591
|
+
agentsMdRequestWarningShown = false;
|
|
272115
272592
|
brandHome;
|
|
272116
272593
|
_activeResponderModel;
|
|
272117
272594
|
allowModelFallback = true;
|
|
@@ -272266,6 +272743,7 @@ var Agent$1 = class {
|
|
|
272266
272743
|
tools: requestTools,
|
|
272267
272744
|
messages: await rebuildMessages()
|
|
272268
272745
|
};
|
|
272746
|
+
if (this.activeProfile !== void 0 && this.rawSystemPromptContext !== void 0 && this.config.systemPrompt === this.profileSystemPromptText) this.updateSystemPromptFromProfile(this.activeProfile, this.fitProfileInstructions(this.activeProfile, this.rawSystemPromptContext, requestTools, true));
|
|
272269
272747
|
let systemPrompt = this.effectiveSystemPrompt;
|
|
272270
272748
|
const preflightStartedAt = performance.now();
|
|
272271
272749
|
const compacted = await this.fullCompaction.beforeStep(params.signal, {
|
|
@@ -272294,6 +272772,13 @@ var Agent$1 = class {
|
|
|
272294
272772
|
...params,
|
|
272295
272773
|
messages: await rebuildMessages()
|
|
272296
272774
|
};
|
|
272775
|
+
if (this.config.runtimeModel(_candidate.alias).provider.name === "blun") {
|
|
272776
|
+
const requestBytes = estimateBlunSerializedBodyBytes(systemPrompt, tools, params.messages) + 4096;
|
|
272777
|
+
if (requestBytes >= 5e5) throw new BlunError(ErrorCodes.CONTEXT_OVERFLOW, "The BLUN request is too large after compaction. Shorten fixed instructions or tools.", { details: {
|
|
272778
|
+
estimatedRequestBytes: requestBytes,
|
|
272779
|
+
requestBudgetBytes: 5e5
|
|
272780
|
+
} });
|
|
272781
|
+
}
|
|
272297
272782
|
return {
|
|
272298
272783
|
params: {
|
|
272299
272784
|
...params,
|
|
@@ -272372,8 +272857,14 @@ var Agent$1 = class {
|
|
|
272372
272857
|
}
|
|
272373
272858
|
useProfile(profile, context, brandHome) {
|
|
272374
272859
|
this.setActiveProfile(profile, brandHome);
|
|
272375
|
-
this.
|
|
272860
|
+
this.rawSystemPromptContext = context;
|
|
272861
|
+
if (context?.agentsMdText === void 0) {
|
|
272862
|
+
this.updateSystemPromptFromProfile(profile, context);
|
|
272863
|
+
this.tools.setActiveTools(profile.tools);
|
|
272864
|
+
return;
|
|
272865
|
+
}
|
|
272376
272866
|
this.tools.setActiveTools(profile.tools);
|
|
272867
|
+
this.updateSystemPromptFromProfile(profile, this.fitProfileInstructions(profile, context));
|
|
272377
272868
|
}
|
|
272378
272869
|
setActiveProfile(profile, brandHome) {
|
|
272379
272870
|
this.activeProfile = profile;
|
|
@@ -272388,7 +272879,68 @@ var Agent$1 = class {
|
|
|
272388
272879
|
async refreshSystemPrompt() {
|
|
272389
272880
|
if (this.activeProfile === void 0) return;
|
|
272390
272881
|
const context = this.systemPromptContextProvider === void 0 ? await prepareSystemPromptContext(this.kaos, this.brandHome, { additionalDirs: this.additionalDirs }) : await this.systemPromptContextProvider();
|
|
272391
|
-
this.
|
|
272882
|
+
this.rawSystemPromptContext = context;
|
|
272883
|
+
this.updateSystemPromptFromProfile(this.activeProfile, this.fitProfileInstructions(this.activeProfile, context));
|
|
272884
|
+
}
|
|
272885
|
+
fitProfileInstructions(profile, context, tools = this.tools.loopTools, notify = false) {
|
|
272886
|
+
if (context?.agentsMdText === void 0 || this.config.modelAlias === void 0) return context;
|
|
272887
|
+
if (this.config.runtimeModel(this.config.modelAlias).provider.name !== "blun") return context;
|
|
272888
|
+
const renderFixedPrompt = (candidate) => {
|
|
272889
|
+
const rendered = profile.systemPrompt({
|
|
272890
|
+
osEnv: this.kaos.osEnv,
|
|
272891
|
+
now: this.systemPromptStartedAt,
|
|
272892
|
+
cwd: this.config.cwd,
|
|
272893
|
+
skills: this.skills?.registry,
|
|
272894
|
+
cwdListing: candidate.cwdListing,
|
|
272895
|
+
agentsMd: candidate.agentsMd,
|
|
272896
|
+
additionalDirsInfo: candidate.additionalDirsInfo
|
|
272897
|
+
});
|
|
272898
|
+
const compact = this.skills?.registry === void 0 ? rendered : compactLegacyModelSkillListing(rendered, this.skills.registry);
|
|
272899
|
+
return this.runtimeSystemPromptAppend.length === 0 ? compact : compact.length === 0 ? this.runtimeSystemPromptAppend : `${compact}\n\n${this.runtimeSystemPromptAppend}`;
|
|
272900
|
+
};
|
|
272901
|
+
const fitted = fitAgentsMdContext(context, 4e5, (candidate) => {
|
|
272902
|
+
return estimateBlunSerializedBodyBytes(renderFixedPrompt(candidate), tools, []) + 4096;
|
|
272903
|
+
});
|
|
272904
|
+
const describeFixedEstimate = () => {
|
|
272905
|
+
const systemPrompt = renderFixedPrompt(fitted.context);
|
|
272906
|
+
const envelopeBytes = estimateBlunSerializedBodyBytes("", [], []);
|
|
272907
|
+
const withoutToolsBytes = estimateBlunSerializedBodyBytes(systemPrompt, [], []);
|
|
272908
|
+
return {
|
|
272909
|
+
estimationStage: notify ? "request" : "profile",
|
|
272910
|
+
toolCount: tools.length,
|
|
272911
|
+
serializedPromptBytes: withoutToolsBytes - envelopeBytes,
|
|
272912
|
+
serializedToolsBytes: fitted.fixedRequestBytes - 4096 - withoutToolsBytes,
|
|
272913
|
+
envelopeBytes,
|
|
272914
|
+
reserveBytes: 4096,
|
|
272915
|
+
instructionBytes: fitted.context.agentsMdSources?.totalBytes ?? 0,
|
|
272916
|
+
runtimeAppendBytes: Buffer.byteLength(this.runtimeSystemPromptAppend, "utf8")
|
|
272917
|
+
};
|
|
272918
|
+
};
|
|
272919
|
+
if (!fitted.fits) this.log.warn("fixed BLUN request exceeds 400000 bytes without AGENTS.md", {
|
|
272920
|
+
fixedRequestBytes: fitted.fixedRequestBytes,
|
|
272921
|
+
...describeFixedEstimate()
|
|
272922
|
+
});
|
|
272923
|
+
else if (fitted.omittedBytes > 0) {
|
|
272924
|
+
this.log.warn("AGENTS.md content shortened for BLUN request budget", {
|
|
272925
|
+
omittedBytes: fitted.omittedBytes,
|
|
272926
|
+
fixedRequestBytes: fitted.fixedRequestBytes,
|
|
272927
|
+
...describeFixedEstimate()
|
|
272928
|
+
});
|
|
272929
|
+
if (notify && !this.agentsMdRequestWarningShown) {
|
|
272930
|
+
this.agentsMdRequestWarningShown = true;
|
|
272931
|
+
const retained = new Map(fitted.context.agentsMdSources?.files.map((file) => [file.path, file.bytes]));
|
|
272932
|
+
const files = context.agentsMdSources?.files.flatMap((file) => {
|
|
272933
|
+
const read = retained.get(file.path) ?? 0;
|
|
272934
|
+
return read < file.bytes ? [`${file.path}: ${file.bytes} bytes, ${read} read, ${file.bytes - read} omitted`] : [];
|
|
272935
|
+
}) ?? [];
|
|
272936
|
+
this.emitEvent({
|
|
272937
|
+
type: "warning",
|
|
272938
|
+
code: "agents-md-request-truncated",
|
|
272939
|
+
message: `Instructions shortened for the request size limit: ${files.join("; ")}.`
|
|
272940
|
+
});
|
|
272941
|
+
}
|
|
272942
|
+
}
|
|
272943
|
+
return fitted.context;
|
|
272392
272944
|
}
|
|
272393
272945
|
updateSystemPromptFromProfile(profile, context) {
|
|
272394
272946
|
let contributions;
|
|
@@ -272409,6 +272961,7 @@ var Agent$1 = class {
|
|
|
272409
272961
|
profileName: profile.name,
|
|
272410
272962
|
systemPrompt
|
|
272411
272963
|
});
|
|
272964
|
+
this.profileSystemPromptText = systemPrompt;
|
|
272412
272965
|
this.renderedPromptContributions = contributions === void 0 ? void 0 : {
|
|
272413
272966
|
text: systemPrompt,
|
|
272414
272967
|
value: structuredClone(contributions)
|
|
@@ -272585,6 +273138,9 @@ var Agent$1 = class {
|
|
|
272585
273138
|
},
|
|
272586
273139
|
startBtw: () => this.subagentHost.startBtw(),
|
|
272587
273140
|
createGoal: (payload) => this.goal.createGoal(payload),
|
|
273141
|
+
editGoal: (payload) => this.goal.editGoal(payload),
|
|
273142
|
+
blockGoal: (payload) => this.goal.blockGoal(payload),
|
|
273143
|
+
completeGoal: () => this.goal.completeGoal(),
|
|
272588
273144
|
getGoal: () => this.goal.getGoal(),
|
|
272589
273145
|
pauseGoal: () => this.goal.pauseGoal(),
|
|
272590
273146
|
resumeGoal: () => this.goal.resumeGoal(),
|
|
@@ -336839,6 +337395,15 @@ var SessionAPIImpl = class {
|
|
|
336839
337395
|
async createGoal({ agentId, ...payload }) {
|
|
336840
337396
|
return (await this.getAgent(agentId)).createGoal(payload);
|
|
336841
337397
|
}
|
|
337398
|
+
async editGoal({ agentId, ...payload }) {
|
|
337399
|
+
return (await this.getAgent(agentId)).editGoal(payload);
|
|
337400
|
+
}
|
|
337401
|
+
async blockGoal({ agentId, ...payload }) {
|
|
337402
|
+
return (await this.getAgent(agentId)).blockGoal(payload);
|
|
337403
|
+
}
|
|
337404
|
+
async completeGoal({ agentId }) {
|
|
337405
|
+
return (await this.getAgent(agentId)).completeGoal({});
|
|
337406
|
+
}
|
|
336842
337407
|
async getGoal({ agentId, ...payload }) {
|
|
336843
337408
|
return (await this.getAgent(agentId, true)).getGoal(payload);
|
|
336844
337409
|
}
|
|
@@ -338083,6 +338648,15 @@ var BlunCore = class {
|
|
|
338083
338648
|
getGoal({ sessionId, ...payload }) {
|
|
338084
338649
|
return Promise.resolve(this.sessionApi(sessionId).getGoal(payload));
|
|
338085
338650
|
}
|
|
338651
|
+
editGoal({ sessionId, ...payload }) {
|
|
338652
|
+
return Promise.resolve(this.sessionApi(sessionId).editGoal(payload));
|
|
338653
|
+
}
|
|
338654
|
+
blockGoal({ sessionId, ...payload }) {
|
|
338655
|
+
return Promise.resolve(this.sessionApi(sessionId).blockGoal(payload));
|
|
338656
|
+
}
|
|
338657
|
+
completeGoal({ sessionId, ...payload }) {
|
|
338658
|
+
return Promise.resolve(this.sessionApi(sessionId).completeGoal(payload));
|
|
338659
|
+
}
|
|
338086
338660
|
pauseGoal({ sessionId, ...payload }) {
|
|
338087
338661
|
return Promise.resolve(this.sessionApi(sessionId).pauseGoal(payload));
|
|
338088
338662
|
}
|
|
@@ -345284,7 +345858,10 @@ function reduceWireRecords(records) {
|
|
|
345284
345858
|
text: record.summary
|
|
345285
345859
|
}],
|
|
345286
345860
|
toolCalls: [],
|
|
345287
|
-
origin: {
|
|
345861
|
+
origin: {
|
|
345862
|
+
kind: "compaction_summary",
|
|
345863
|
+
...record.toolContinuity === void 0 ? {} : { toolContinuity: record.toolContinuity }
|
|
345864
|
+
}
|
|
345288
345865
|
},
|
|
345289
345866
|
time: record.time
|
|
345290
345867
|
};
|
|
@@ -347535,6 +348112,24 @@ var Session = class {
|
|
|
347535
348112
|
this.ensureOpen();
|
|
347536
348113
|
return this.rpc.getGoal({ sessionId: this.id });
|
|
347537
348114
|
}
|
|
348115
|
+
async editGoal(input) {
|
|
348116
|
+
this.ensureOpen();
|
|
348117
|
+
return this.rpc.editGoal({
|
|
348118
|
+
sessionId: this.id,
|
|
348119
|
+
objective: input.objective
|
|
348120
|
+
});
|
|
348121
|
+
}
|
|
348122
|
+
async blockGoal(input = {}) {
|
|
348123
|
+
this.ensureOpen();
|
|
348124
|
+
return this.rpc.blockGoal({
|
|
348125
|
+
sessionId: this.id,
|
|
348126
|
+
reason: input.reason
|
|
348127
|
+
});
|
|
348128
|
+
}
|
|
348129
|
+
async completeGoal() {
|
|
348130
|
+
this.ensureOpen();
|
|
348131
|
+
return this.rpc.completeGoal({ sessionId: this.id });
|
|
348132
|
+
}
|
|
347538
348133
|
async pauseGoal() {
|
|
347539
348134
|
this.ensureOpen();
|
|
347540
348135
|
return this.rpc.pauseGoal({ sessionId: this.id });
|
|
@@ -348915,6 +349510,26 @@ var SDKRpcClientBase = class {
|
|
|
348915
349510
|
replace: input.replace
|
|
348916
349511
|
});
|
|
348917
349512
|
}
|
|
349513
|
+
async editGoal(input) {
|
|
349514
|
+
return (await this.getRpc()).editGoal({
|
|
349515
|
+
sessionId: input.sessionId,
|
|
349516
|
+
agentId: this.interactiveAgentId,
|
|
349517
|
+
objective: input.objective
|
|
349518
|
+
});
|
|
349519
|
+
}
|
|
349520
|
+
async blockGoal(input) {
|
|
349521
|
+
return (await this.getRpc()).blockGoal({
|
|
349522
|
+
sessionId: input.sessionId,
|
|
349523
|
+
agentId: this.interactiveAgentId,
|
|
349524
|
+
reason: input.reason
|
|
349525
|
+
});
|
|
349526
|
+
}
|
|
349527
|
+
async completeGoal(input) {
|
|
349528
|
+
return (await this.getRpc()).completeGoal({
|
|
349529
|
+
sessionId: input.sessionId,
|
|
349530
|
+
agentId: this.interactiveAgentId
|
|
349531
|
+
});
|
|
349532
|
+
}
|
|
348918
349533
|
async getGoal(input) {
|
|
348919
349534
|
return (await this.getRpc()).getGoal({
|
|
348920
349535
|
sessionId: input.sessionId,
|