blun-king-cli 9.1.614 → 9.1.615
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/LIESMICH.txt +1 -1
- package/README.md +1 -1
- package/blun.mjs +1543 -780
- package/codebase-index/codebase_index.py +25 -17
- package/package.json +1 -1
- package/telegram-plugin/dist/bridge.mjs +1 -200
- package/telegram-plugin/dist/mcp-server.mjs +8 -4
- package/worker-host.mjs +1615 -622
package/worker-host.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
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);
|
|
6
6
|
const __dirname = __cjsShimDirname(__filename);
|
|
7
7
|
import { createRequire } from "node:module";
|
|
8
|
-
import crypto$1, { createHash, randomBytes, randomInt, randomUUID } from "node:crypto";
|
|
8
|
+
import crypto$1, { createHash, createHmac, randomBytes, randomInt, randomUUID } from "node:crypto";
|
|
9
9
|
import * as fs$12 from "node:fs";
|
|
10
10
|
import Kt, { appendFileSync, chmodSync, closeSync, constants, createReadStream, createWriteStream, existsSync, fstatSync, fsyncSync, linkSync, lstatSync, mkdirSync, openSync, opendirSync, promises, readFileSync, readSync, readdirSync, realpathSync, renameSync, statSync, unlinkSync, writeFileSync, writeSync } from "node:fs";
|
|
11
11
|
import * as path$11 from "node:path";
|
|
@@ -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";
|
|
@@ -1888,6 +1888,9 @@ var FetchTransport = class {
|
|
|
1888
1888
|
const maxRetries = normalizeMaxRetries(requestOptions?.maxRetries);
|
|
1889
1889
|
const requestBytes = exactBodyBytes(init.body);
|
|
1890
1890
|
const requestBreakdown = pathname === "/chat/completions" && requestOptions?.onTransportAttempt !== void 0 && typeof init.body === "string" && requestBytes !== void 0 ? measureSerializedRequest(init.body, requestBytes) : void 0;
|
|
1891
|
+
if (pathname === "/chat/completions" && typeof init.body === "string") try {
|
|
1892
|
+
requestOptions?.onSerializedRequest?.(init.body);
|
|
1893
|
+
} catch {}
|
|
1891
1894
|
let attempt = 0;
|
|
1892
1895
|
while (true) {
|
|
1893
1896
|
const headers = new Headers(init.headers);
|
|
@@ -1896,6 +1899,9 @@ var FetchTransport = class {
|
|
|
1896
1899
|
const startedAt = performance.now();
|
|
1897
1900
|
const startedAtMs = Date.now();
|
|
1898
1901
|
try {
|
|
1902
|
+
try {
|
|
1903
|
+
requestOptions?.onRequestSent?.();
|
|
1904
|
+
} catch {}
|
|
1899
1905
|
const response = await this.fetch(`${this.baseUrl}${pathname}`, {
|
|
1900
1906
|
...init,
|
|
1901
1907
|
headers
|
|
@@ -1953,16 +1959,6 @@ function measureSerializedRequest(body, requestBytes) {
|
|
|
1953
1959
|
const payload = parsed;
|
|
1954
1960
|
const messages = Array.isArray(payload["messages"]) ? payload["messages"] : [];
|
|
1955
1961
|
const tools = Array.isArray(payload["tools"]) ? payload["tools"] : void 0;
|
|
1956
|
-
let systemMessageBytes = 0;
|
|
1957
|
-
let conversationMessageBytes = 0;
|
|
1958
|
-
let toolResultMessageBytes = 0;
|
|
1959
|
-
for (const message of messages) {
|
|
1960
|
-
const size = Buffer.byteLength(JSON.stringify(message), "utf8");
|
|
1961
|
-
const role = message !== null && typeof message === "object" ? message["role"] : void 0;
|
|
1962
|
-
if (role === "system" || role === "developer") systemMessageBytes += size;
|
|
1963
|
-
else if (role === "tool") toolResultMessageBytes += size;
|
|
1964
|
-
else conversationMessageBytes += size;
|
|
1965
|
-
}
|
|
1966
1962
|
const toolDefinitions = Object.freeze((tools ?? []).map((tool, index) => {
|
|
1967
1963
|
const entry = tool !== null && typeof tool === "object" ? tool : void 0;
|
|
1968
1964
|
const fn = entry?.["function"];
|
|
@@ -1973,6 +1969,44 @@ function measureSerializedRequest(body, requestBytes) {
|
|
|
1973
1969
|
...typeof name === "string" && name.length > 0 && name.length <= 128 ? { name } : {}
|
|
1974
1970
|
});
|
|
1975
1971
|
}));
|
|
1972
|
+
const declaredNames = new Set(toolDefinitions.flatMap((tool) => tool.name === void 0 ? [] : [tool.name]));
|
|
1973
|
+
const callNames = /* @__PURE__ */ new Map();
|
|
1974
|
+
for (const message of messages) {
|
|
1975
|
+
if (message === null || typeof message !== "object" || message["role"] !== "assistant") continue;
|
|
1976
|
+
const calls = message["tool_calls"];
|
|
1977
|
+
if (!Array.isArray(calls)) continue;
|
|
1978
|
+
for (const call of calls) {
|
|
1979
|
+
if (call === null || typeof call !== "object") continue;
|
|
1980
|
+
const entry = call;
|
|
1981
|
+
const fn = entry["function"];
|
|
1982
|
+
const name = fn !== null && typeof fn === "object" ? fn["name"] : void 0;
|
|
1983
|
+
const id = entry["id"];
|
|
1984
|
+
if (typeof id !== "string" || id.length === 0) continue;
|
|
1985
|
+
callNames.set(id, callNames.has(id) ? void 0 : typeof name === "string" && declaredNames.has(name) ? name : void 0);
|
|
1986
|
+
}
|
|
1987
|
+
}
|
|
1988
|
+
let systemMessageBytes = 0;
|
|
1989
|
+
let conversationMessageBytes = 0;
|
|
1990
|
+
let toolResultMessageBytes = 0;
|
|
1991
|
+
const results = /* @__PURE__ */ new Map();
|
|
1992
|
+
for (const message of messages) {
|
|
1993
|
+
const size = Buffer.byteLength(JSON.stringify(message), "utf8");
|
|
1994
|
+
const role = message !== null && typeof message === "object" ? message["role"] : void 0;
|
|
1995
|
+
if (role === "system" || role === "developer") systemMessageBytes += size;
|
|
1996
|
+
else if (role === "tool") {
|
|
1997
|
+
toolResultMessageBytes += size;
|
|
1998
|
+
const id = message["tool_call_id"];
|
|
1999
|
+
const name = typeof id === "string" ? callNames.get(id) : void 0;
|
|
2000
|
+
const key = name ?? "";
|
|
2001
|
+
const previous = results.get(key);
|
|
2002
|
+
results.set(key, {
|
|
2003
|
+
...name === void 0 ? {} : { name },
|
|
2004
|
+
count: (previous?.count ?? 0) + 1,
|
|
2005
|
+
bytes: (previous?.bytes ?? 0) + size
|
|
2006
|
+
});
|
|
2007
|
+
} else conversationMessageBytes += size;
|
|
2008
|
+
}
|
|
2009
|
+
const toolResultByTool = Object.freeze(Array.from(results.values(), (entry) => Object.freeze(entry)));
|
|
1976
2010
|
const toolArrayOverheadBytes = tools === void 0 ? 0 : 2 + Math.max(0, tools.length - 1);
|
|
1977
2011
|
const toolSchemaBytes = toolDefinitions.reduce((sum, tool) => sum + tool.bytes, toolArrayOverheadBytes);
|
|
1978
2012
|
return Object.freeze({
|
|
@@ -1982,6 +2016,7 @@ function measureSerializedRequest(body, requestBytes) {
|
|
|
1982
2016
|
systemMessageBytes,
|
|
1983
2017
|
conversationMessageBytes,
|
|
1984
2018
|
toolResultMessageBytes,
|
|
2019
|
+
...toolResultByTool.length === 0 ? {} : { toolResultByTool },
|
|
1985
2020
|
toolSchemaBytes,
|
|
1986
2021
|
toolDefinitions,
|
|
1987
2022
|
toolArrayOverheadBytes,
|
|
@@ -2366,6 +2401,9 @@ function extractChatCompletionUsage(usage) {
|
|
|
2366
2401
|
const value = usage;
|
|
2367
2402
|
const promptTokens = typeof value["prompt_tokens"] === "number" ? value["prompt_tokens"] : 0;
|
|
2368
2403
|
const completionTokens = typeof value["completion_tokens"] === "number" ? value["completion_tokens"] : 0;
|
|
2404
|
+
const completionDetails = value["completion_tokens_details"];
|
|
2405
|
+
const reportedReasoning = completionDetails !== null && typeof completionDetails === "object" ? completionDetails["reasoning_tokens"] : void 0;
|
|
2406
|
+
const outputReasoning = typeof reportedReasoning === "number" && Number.isSafeInteger(reportedReasoning) && reportedReasoning >= 0 && reportedReasoning <= completionTokens ? reportedReasoning : void 0;
|
|
2369
2407
|
let cachedTokens = 0;
|
|
2370
2408
|
if (typeof value["cached_tokens"] === "number") cachedTokens = value["cached_tokens"];
|
|
2371
2409
|
else if (value["prompt_tokens_details"] !== null && typeof value["prompt_tokens_details"] === "object") {
|
|
@@ -2375,6 +2413,7 @@ function extractChatCompletionUsage(usage) {
|
|
|
2375
2413
|
return {
|
|
2376
2414
|
inputOther: promptTokens - cachedTokens,
|
|
2377
2415
|
output: completionTokens,
|
|
2416
|
+
...outputReasoning === void 0 ? {} : { outputReasoning },
|
|
2378
2417
|
inputCacheRead: cachedTokens,
|
|
2379
2418
|
inputCacheCreation: 0
|
|
2380
2419
|
};
|
|
@@ -2648,6 +2687,23 @@ function collectBlunVisionAttachments(messages) {
|
|
|
2648
2687
|
}
|
|
2649
2688
|
return attachments;
|
|
2650
2689
|
}
|
|
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");
|
|
2706
|
+
}
|
|
2651
2707
|
function convertMessage(message) {
|
|
2652
2708
|
let reasoningContent = "";
|
|
2653
2709
|
const nonThinkParts = [];
|
|
@@ -2957,12 +3013,13 @@ var BlunChatProvider = class {
|
|
|
2957
3013
|
if (this._stream) createParams["stream_options"] = { include_usage: true };
|
|
2958
3014
|
try {
|
|
2959
3015
|
const client = this._createClient(options?.auth);
|
|
2960
|
-
const requestOptions = options?.signal !== void 0 || options?.transportMaxRetries !== void 0 || options?.onTransportAttempt !== void 0 ? {
|
|
3016
|
+
const requestOptions = options?.signal !== void 0 || options?.transportMaxRetries !== void 0 || options?.onRequestSent !== void 0 || options?.onSerializedRequest !== void 0 || options?.onTransportAttempt !== void 0 ? {
|
|
2961
3017
|
...options.signal !== void 0 ? { signal: options.signal } : {},
|
|
2962
3018
|
...options.transportMaxRetries !== void 0 ? { maxRetries: options.transportMaxRetries } : {},
|
|
3019
|
+
...options.onRequestSent !== void 0 ? { onRequestSent: options.onRequestSent } : {},
|
|
3020
|
+
...options.onSerializedRequest !== void 0 ? { onSerializedRequest: options.onSerializedRequest } : {},
|
|
2963
3021
|
...options.onTransportAttempt !== void 0 ? { onTransportAttempt: options.onTransportAttempt } : {}
|
|
2964
3022
|
} : void 0;
|
|
2965
|
-
options?.onRequestSent?.();
|
|
2966
3023
|
let response;
|
|
2967
3024
|
try {
|
|
2968
3025
|
response = await client.chat.completions.create(createParams, requestOptions);
|
|
@@ -2971,7 +3028,6 @@ var BlunChatProvider = class {
|
|
|
2971
3028
|
const cap = rejection instanceof APIContextOverflowError ? contextOverflowOutputCap(rejection, createParams["max_completion_tokens"]) : void 0;
|
|
2972
3029
|
if (cap === void 0) throw rejection;
|
|
2973
3030
|
options?.signal?.throwIfAborted();
|
|
2974
|
-
options?.onRequestSent?.();
|
|
2975
3031
|
response = await client.chat.completions.create({
|
|
2976
3032
|
...createParams,
|
|
2977
3033
|
max_completion_tokens: cap
|
|
@@ -3358,9 +3414,11 @@ function emptyUsage() {
|
|
|
3358
3414
|
* Sum two TokenUsage values.
|
|
3359
3415
|
*/
|
|
3360
3416
|
function addUsage(a, b) {
|
|
3417
|
+
const outputReasoning = a.outputReasoning !== void 0 && b.outputReasoning !== void 0 ? a.outputReasoning + b.outputReasoning : a.output === 0 ? b.outputReasoning : b.output === 0 ? a.outputReasoning : void 0;
|
|
3361
3418
|
return {
|
|
3362
3419
|
inputOther: a.inputOther + b.inputOther,
|
|
3363
3420
|
output: a.output + b.output,
|
|
3421
|
+
...outputReasoning === void 0 ? {} : { outputReasoning },
|
|
3364
3422
|
inputCacheRead: a.inputCacheRead + b.inputCacheRead,
|
|
3365
3423
|
inputCacheCreation: a.inputCacheCreation + b.inputCacheCreation
|
|
3366
3424
|
};
|
|
@@ -9770,6 +9828,8 @@ const StringRecordSchema = record$2(string(), string());
|
|
|
9770
9828
|
const ProviderConfigSchema = object({
|
|
9771
9829
|
type: ProviderTypeSchema,
|
|
9772
9830
|
apiKey: string().optional(),
|
|
9831
|
+
memoryWorkspaceId: string().regex(/^blun-[0-9a-f]{64}$/u).optional(),
|
|
9832
|
+
memoryApiKeyHash: string().regex(/^[0-9a-f]{64}$/u).optional(),
|
|
9773
9833
|
baseUrl: string().optional(),
|
|
9774
9834
|
defaultModel: string().optional(),
|
|
9775
9835
|
oauth: OAuthRefSchema.optional(),
|
|
@@ -10318,7 +10378,8 @@ function tokenToWire(token) {
|
|
|
10318
10378
|
expires_at: token.expiresAt,
|
|
10319
10379
|
scope: token.scope,
|
|
10320
10380
|
token_type: token.tokenType,
|
|
10321
|
-
expires_in: token.expiresIn
|
|
10381
|
+
expires_in: token.expiresIn,
|
|
10382
|
+
...token.memoryWorkspaceId === void 0 ? {} : { memory_workspace_id: token.memoryWorkspaceId }
|
|
10322
10383
|
};
|
|
10323
10384
|
}
|
|
10324
10385
|
function tokenFromWire(wire) {
|
|
@@ -10328,7 +10389,8 @@ function tokenFromWire(wire) {
|
|
|
10328
10389
|
expiresAt: typeof wire.expires_at === "number" ? wire.expires_at : 0,
|
|
10329
10390
|
scope: wire.scope ?? "",
|
|
10330
10391
|
tokenType: wire.token_type ?? "",
|
|
10331
|
-
expiresIn: typeof wire.expires_in === "number" ? wire.expires_in : 0
|
|
10392
|
+
expiresIn: typeof wire.expires_in === "number" ? wire.expires_in : 0,
|
|
10393
|
+
...typeof wire.memory_workspace_id === "string" && wire.memory_workspace_id.length > 0 ? { memoryWorkspaceId: wire.memory_workspace_id } : {}
|
|
10332
10394
|
};
|
|
10333
10395
|
}
|
|
10334
10396
|
//#endregion
|
|
@@ -12719,6 +12781,27 @@ var OAuthManager = class {
|
|
|
12719
12781
|
const state = await this.loadState();
|
|
12720
12782
|
return state.kind === "valid" ? state.token.accessToken : void 0;
|
|
12721
12783
|
}
|
|
12784
|
+
async getCachedMemoryWorkspaceId() {
|
|
12785
|
+
const state = await this.loadState();
|
|
12786
|
+
return state.kind === "valid" && state.token.expiresAt > this.now() ? state.token.memoryWorkspaceId : void 0;
|
|
12787
|
+
}
|
|
12788
|
+
async cacheMemoryWorkspaceId(workspaceId) {
|
|
12789
|
+
if (workspaceId.length === 0) return false;
|
|
12790
|
+
const release = await this.acquireRefreshLock();
|
|
12791
|
+
try {
|
|
12792
|
+
const state = await this.loadState();
|
|
12793
|
+
if (state.kind !== "valid" || state.token.expiresAt <= this.now()) return false;
|
|
12794
|
+
if (state.token.memoryWorkspaceId === workspaceId) return true;
|
|
12795
|
+
if (state.token.memoryWorkspaceId !== void 0) return false;
|
|
12796
|
+
await this.storage.save(this.config.name, {
|
|
12797
|
+
...state.token,
|
|
12798
|
+
memoryWorkspaceId: workspaceId
|
|
12799
|
+
});
|
|
12800
|
+
return true;
|
|
12801
|
+
} finally {
|
|
12802
|
+
await release();
|
|
12803
|
+
}
|
|
12804
|
+
}
|
|
12722
12805
|
async logout() {
|
|
12723
12806
|
await this.inFlightRefresh?.promise.catch(() => void 0);
|
|
12724
12807
|
const release = await this.acquireRefreshLock();
|
|
@@ -12786,7 +12869,10 @@ var OAuthManager = class {
|
|
|
12786
12869
|
if (activeToken.refreshToken.length === 0) throw new OAuthUnauthorizedError(`Token for "${this.config.name}" has no refresh_token; re-login required.`);
|
|
12787
12870
|
try {
|
|
12788
12871
|
const refreshed = await this.refreshImpl(this.config, activeToken.refreshToken);
|
|
12789
|
-
await this.storage.save(this.config.name,
|
|
12872
|
+
await this.storage.save(this.config.name, {
|
|
12873
|
+
...refreshed,
|
|
12874
|
+
memoryWorkspaceId: activeToken.memoryWorkspaceId
|
|
12875
|
+
});
|
|
12790
12876
|
this.notifyRefresh({ success: true });
|
|
12791
12877
|
return refreshed.accessToken;
|
|
12792
12878
|
} catch (error) {
|
|
@@ -14163,6 +14249,16 @@ var BlunOAuthToolkit = class {
|
|
|
14163
14249
|
hasToken: await this.managerFor(name, oauthKey, oauthHost).hasToken()
|
|
14164
14250
|
}] };
|
|
14165
14251
|
}
|
|
14252
|
+
async getCachedMemoryWorkspaceId(oauthRef) {
|
|
14253
|
+
const oauthHost = this.oauthHostFor(oauthRef);
|
|
14254
|
+
const oauthKey = oauthRef?.key ?? this.defaultOAuthKey(void 0, oauthHost);
|
|
14255
|
+
return this.managerFor(BLUN_PROVIDER_NAME$1, oauthKey, oauthHost).getCachedMemoryWorkspaceId();
|
|
14256
|
+
}
|
|
14257
|
+
async cacheMemoryWorkspaceId(workspaceId, oauthRef) {
|
|
14258
|
+
const oauthHost = this.oauthHostFor(oauthRef);
|
|
14259
|
+
const oauthKey = oauthRef?.key ?? this.defaultOAuthKey(void 0, oauthHost);
|
|
14260
|
+
return this.managerFor(BLUN_PROVIDER_NAME$1, oauthKey, oauthHost).cacheMemoryWorkspaceId(workspaceId);
|
|
14261
|
+
}
|
|
14166
14262
|
async login(providerName, options = {}) {
|
|
14167
14263
|
const name = providerName ?? "managed:blun";
|
|
14168
14264
|
const oauthHost = this.oauthHostFor(options.oauthRef, options.oauthHost);
|
|
@@ -16230,6 +16326,8 @@ function providerToToml(provider, rawProvider) {
|
|
|
16230
16326
|
for (const key of [
|
|
16231
16327
|
"type",
|
|
16232
16328
|
"apiKey",
|
|
16329
|
+
"memoryWorkspaceId",
|
|
16330
|
+
"memoryApiKeyHash",
|
|
16233
16331
|
"baseUrl",
|
|
16234
16332
|
"defaultModel",
|
|
16235
16333
|
"oauth",
|
|
@@ -21678,6 +21776,31 @@ var InstructionText = class InstructionText {
|
|
|
21678
21776
|
get content() {
|
|
21679
21777
|
return this.pieces.map((piece) => piece.text).join("");
|
|
21680
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
|
+
}
|
|
21681
21804
|
replaceFirst(needle, replacement) {
|
|
21682
21805
|
const start = this.content.indexOf(needle);
|
|
21683
21806
|
if (start >= 0) this.replaceRange(start, start + needle.length, replacement);
|
|
@@ -21735,6 +21858,64 @@ const IMPORT_MAX_DEPTH = 4;
|
|
|
21735
21858
|
const IMPORT_LINE_RE = /^@import\s+(.+)$/gm;
|
|
21736
21859
|
const S_IFMT$4 = 61440;
|
|
21737
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
|
+
}
|
|
21738
21919
|
async function prepareSystemPromptContext(kaos, brandHome, options) {
|
|
21739
21920
|
const additionalDirs = normalizeAdditionalDirs(options?.additionalDirs ?? []);
|
|
21740
21921
|
const [cwdListing, agentsMdResult, additionalDirsInfo] = await Promise.all([
|
|
@@ -21747,7 +21928,8 @@ async function prepareSystemPromptContext(kaos, brandHome, options) {
|
|
|
21747
21928
|
agentsMd: agentsMdResult.content,
|
|
21748
21929
|
additionalDirsInfo,
|
|
21749
21930
|
agentsMdWarning: agentsMdResult.warning,
|
|
21750
|
-
agentsMdSources: agentsMdResult.sources
|
|
21931
|
+
agentsMdSources: agentsMdResult.sources,
|
|
21932
|
+
agentsMdText: agentsMdResult.text
|
|
21751
21933
|
};
|
|
21752
21934
|
}
|
|
21753
21935
|
async function loadAgentsMd(kaos, brandHome) {
|
|
@@ -21757,10 +21939,15 @@ async function loadAgentsMdForRoots(kaos, brandHome, workDirs) {
|
|
|
21757
21939
|
const discovered = [];
|
|
21758
21940
|
const emptySources = /* @__PURE__ */ new Map();
|
|
21759
21941
|
const seen = /* @__PURE__ */ new Set();
|
|
21942
|
+
const notLoadedCandidates = /* @__PURE__ */ new Set();
|
|
21760
21943
|
const collect = async (path) => {
|
|
21761
21944
|
const file = await readAgentFile(kaos, path);
|
|
21762
|
-
if (file === void 0)
|
|
21945
|
+
if (file === void 0) {
|
|
21946
|
+
notLoadedCandidates.add(kaos.normpath(path));
|
|
21947
|
+
return false;
|
|
21948
|
+
}
|
|
21763
21949
|
const key = kaos.normpath(file.path);
|
|
21950
|
+
notLoadedCandidates.delete(key);
|
|
21764
21951
|
if (file.content.length === 0) {
|
|
21765
21952
|
emptySources.set(key, InstructionText.file(file.path, "", file.sourceTextBytes));
|
|
21766
21953
|
return false;
|
|
@@ -21796,7 +21983,11 @@ async function loadAgentsMdForRoots(kaos, brandHome, workDirs) {
|
|
|
21796
21983
|
return {
|
|
21797
21984
|
content,
|
|
21798
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,
|
|
21799
|
-
|
|
21986
|
+
text: rendered,
|
|
21987
|
+
sources: {
|
|
21988
|
+
...rendered.measure(),
|
|
21989
|
+
...notLoadedCandidates.size === 0 ? {} : { notLoadedCandidates: [...notLoadedCandidates] }
|
|
21990
|
+
}
|
|
21800
21991
|
};
|
|
21801
21992
|
}
|
|
21802
21993
|
async function loadAdditionalDirsInfo(kaos, additionalDirs) {
|
|
@@ -28778,17 +28969,20 @@ function createSystemPromptRenderer(merged) {
|
|
|
28778
28969
|
const counts = renderPromptContributions(merged.systemPromptTemplate, vars, rendered, true) ?? renderPromptContributions(merged.systemPromptTemplate, vars, rendered);
|
|
28779
28970
|
const sources = context.agentsMdSources;
|
|
28780
28971
|
const copies = counts?.instructionCopies ?? 0;
|
|
28781
|
-
const sourceMatches = sources !== void 0 && sources.version === 1 && Number.isSafeInteger(sources.generatedBytes) && sources.generatedBytes >= 0 && sources.files.every((file) => typeof file.path === "string" && Number.isSafeInteger(file.bytes) && file.bytes >= 0) && sources.totalBytes === Buffer.byteLength(vars["BLUN_AGENTS_MD"] ?? "", "utf8") && sources.generatedBytes + sources.files.reduce((sum, file) => sum + file.bytes, 0) === sources.totalBytes;
|
|
28972
|
+
const sourceMatches = sources !== void 0 && sources.version === 1 && Number.isSafeInteger(sources.generatedBytes) && sources.generatedBytes >= 0 && sources.files.every((file) => typeof file.path === "string" && Number.isSafeInteger(file.bytes) && file.bytes >= 0) && (sources.notLoadedCandidates?.every((path) => typeof path === "string") ?? true) && sources.totalBytes === Buffer.byteLength(vars["BLUN_AGENTS_MD"] ?? "", "utf8") && sources.generatedBytes + sources.files.reduce((sum, file) => sum + file.bytes, 0) === sources.totalBytes;
|
|
28973
|
+
const notLoadedCandidates = sourceMatches && sources.notLoadedCandidates !== void 0 ? { notLoadedCandidates: [...sources.notLoadedCandidates] } : {};
|
|
28782
28974
|
const instructionSources = copies === 0 ? {
|
|
28783
28975
|
version: 1,
|
|
28784
28976
|
totalBytes: 0,
|
|
28785
28977
|
generatedBytes: 0,
|
|
28786
|
-
files: sourceMatches ? sources.files.map((file) => copyInstructionFileBytes(file, 0)) : []
|
|
28978
|
+
files: sourceMatches ? sources.files.map((file) => copyInstructionFileBytes(file, 0)) : [],
|
|
28979
|
+
...notLoadedCandidates
|
|
28787
28980
|
} : !sourceMatches ? void 0 : {
|
|
28788
28981
|
version: 1,
|
|
28789
28982
|
totalBytes: sources.totalBytes * copies,
|
|
28790
28983
|
generatedBytes: sources.generatedBytes * copies,
|
|
28791
|
-
files: sources.files.map((file) => copyInstructionFileBytes(file, copies))
|
|
28984
|
+
files: sources.files.map((file) => copyInstructionFileBytes(file, copies)),
|
|
28985
|
+
...notLoadedCandidates
|
|
28792
28986
|
};
|
|
28793
28987
|
const skillListingSources = counts === void 0 ? void 0 : scaleSkillListingSources(skillSources, vars["BLUN_SKILLS"] ?? "", counts.skillListingBytes);
|
|
28794
28988
|
context.onContributions(counts === void 0 ? void 0 : {
|
|
@@ -180665,6 +180859,10 @@ var GoalMode = class {
|
|
|
180665
180859
|
restoreUpdate(record) {
|
|
180666
180860
|
const state = this.state;
|
|
180667
180861
|
if (state === void 0) return;
|
|
180862
|
+
if (record.objective !== void 0) {
|
|
180863
|
+
state.objective = record.objective;
|
|
180864
|
+
this.lifecycleRevision += 1;
|
|
180865
|
+
}
|
|
180668
180866
|
const status = record.status;
|
|
180669
180867
|
if (status !== void 0) {
|
|
180670
180868
|
this.lifecycleRevision += 1;
|
|
@@ -180679,7 +180877,17 @@ var GoalMode = class {
|
|
|
180679
180877
|
state.wallClockResumedAt = void 0;
|
|
180680
180878
|
}
|
|
180681
180879
|
if (record.budgetLimits !== void 0) state.budgetLimits = record.budgetLimits;
|
|
180682
|
-
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
|
+
}
|
|
180683
180891
|
this.agent.replayBuilder.push({
|
|
180684
180892
|
type: "goal_updated",
|
|
180685
180893
|
snapshot: this.toSnapshot(state),
|
|
@@ -180723,11 +180931,11 @@ var GoalMode = class {
|
|
|
180723
180931
|
if (objective.length === 0) throw new BlunError(ErrorCodes.GOAL_OBJECTIVE_EMPTY, "Goal objective cannot be empty");
|
|
180724
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`);
|
|
180725
180933
|
const verificationScope = normalizeVerificationScope(input.verificationScope);
|
|
180934
|
+
const completionCriterion = normalizeCompletionCriterion(input.completionCriterion);
|
|
180726
180935
|
if (this.state !== void 0) {
|
|
180727
180936
|
if (input.replace !== true) throw new BlunError(ErrorCodes.GOAL_ALREADY_EXISTS, "A goal already exists; use replace to start a new one");
|
|
180728
180937
|
this.clearInternal("system");
|
|
180729
180938
|
}
|
|
180730
|
-
const completionCriterion = normalizeCompletionCriterion(input.completionCriterion);
|
|
180731
180939
|
const state = {
|
|
180732
180940
|
goalId: randomUUID(),
|
|
180733
180941
|
objective,
|
|
@@ -180751,6 +180959,35 @@ var GoalMode = class {
|
|
|
180751
180959
|
this.trackGoalCreated(actor, input.replace === true);
|
|
180752
180960
|
return this.toSnapshot(state);
|
|
180753
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
|
+
}
|
|
180754
180991
|
async pauseGoal(input = {}, actor = "user") {
|
|
180755
180992
|
const state = this.requireState();
|
|
180756
180993
|
if (state.status === "paused") return this.toSnapshot(state);
|
|
@@ -181520,6 +181757,613 @@ var ProviderRetryWait = class {
|
|
|
181520
181757
|
}
|
|
181521
181758
|
}
|
|
181522
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
|
+
}
|
|
181523
182367
|
//#endregion
|
|
181524
182368
|
//#region ../../packages/agent-core/src/agent/records/resume-snapshot.ts
|
|
181525
182369
|
const integer$1 = number$1().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
|
|
@@ -181614,6 +182458,7 @@ const stateRecordSchema = union([
|
|
|
181614
182458
|
verificationScope: _enum(GOAL_VERIFICATION_SCOPES).optional()
|
|
181615
182459
|
}),
|
|
181616
182460
|
record$1("goal.update", {
|
|
182461
|
+
objective: text.min(1).max(4e3).regex(/\S/).optional(),
|
|
181617
182462
|
status: _enum([
|
|
181618
182463
|
"active",
|
|
181619
182464
|
"paused",
|
|
@@ -181665,7 +182510,7 @@ const originCase = (kind, shape = {}) => object({
|
|
|
181665
182510
|
}).passthrough();
|
|
181666
182511
|
const origin = union([
|
|
181667
182512
|
originCase("user"),
|
|
181668
|
-
originCase("compaction_summary"),
|
|
182513
|
+
originCase("compaction_summary", { toolContinuity: custom$1(isToolContinuity).optional() }),
|
|
181669
182514
|
originCase("skill_activation", {
|
|
181670
182515
|
activationId: text,
|
|
181671
182516
|
skillName: text,
|
|
@@ -182016,6 +182861,7 @@ async function writeResumeCheckpoint(wirePath, position, snapshot) {
|
|
|
182016
182861
|
if (Buffer.byteLength(bytes) > MAX_CHECKPOINT_BYTES) return false;
|
|
182017
182862
|
const target = resumeCheckpointPath(wirePath);
|
|
182018
182863
|
const temporary = `${target}.tmp-${process.pid}-${randomBytes(8).toString("hex")}`;
|
|
182864
|
+
let renamed = false;
|
|
182019
182865
|
try {
|
|
182020
182866
|
const output = await open(temporary, "wx", 384);
|
|
182021
182867
|
try {
|
|
@@ -182025,10 +182871,11 @@ async function writeResumeCheckpoint(wirePath, position, snapshot) {
|
|
|
182025
182871
|
await output.close();
|
|
182026
182872
|
}
|
|
182027
182873
|
await rename(temporary, target);
|
|
182874
|
+
renamed = true;
|
|
182028
182875
|
await syncDir(dirname$3(target));
|
|
182029
182876
|
return true;
|
|
182030
182877
|
} finally {
|
|
182031
|
-
await rm(temporary, { force: true }).catch(() => {});
|
|
182878
|
+
if (!renamed) await rm(temporary, { force: true }).catch(() => {});
|
|
182032
182879
|
}
|
|
182033
182880
|
}
|
|
182034
182881
|
//#endregion
|
|
@@ -185365,501 +186212,6 @@ var TodoListTool = class {
|
|
|
185365
186212
|
})));
|
|
185366
186213
|
}
|
|
185367
186214
|
};
|
|
185368
|
-
const IMAGE_MIME_BY_SUFFIX = Object.freeze({
|
|
185369
|
-
".png": "image/png",
|
|
185370
|
-
".jpg": "image/jpeg",
|
|
185371
|
-
".jpeg": "image/jpeg",
|
|
185372
|
-
".gif": "image/gif",
|
|
185373
|
-
".bmp": "image/bmp",
|
|
185374
|
-
".tif": "image/tiff",
|
|
185375
|
-
".tiff": "image/tiff",
|
|
185376
|
-
".webp": "image/webp",
|
|
185377
|
-
".ico": "image/x-icon",
|
|
185378
|
-
".heic": "image/heic",
|
|
185379
|
-
".heif": "image/heif",
|
|
185380
|
-
".avif": "image/avif",
|
|
185381
|
-
".svgz": "image/svg+xml"
|
|
185382
|
-
});
|
|
185383
|
-
const VIDEO_MIME_BY_SUFFIX = Object.freeze({
|
|
185384
|
-
".mp4": "video/mp4",
|
|
185385
|
-
".mpg": "video/mpeg",
|
|
185386
|
-
".mpeg": "video/mpeg",
|
|
185387
|
-
".mkv": "video/x-matroska",
|
|
185388
|
-
".avi": "video/x-msvideo",
|
|
185389
|
-
".mov": "video/quicktime",
|
|
185390
|
-
".ogv": "video/ogg",
|
|
185391
|
-
".wmv": "video/x-ms-wmv",
|
|
185392
|
-
".webm": "video/webm",
|
|
185393
|
-
".m4v": "video/x-m4v",
|
|
185394
|
-
".flv": "video/x-flv",
|
|
185395
|
-
".3gp": "video/3gpp",
|
|
185396
|
-
".3g2": "video/3gpp2"
|
|
185397
|
-
});
|
|
185398
|
-
const TEXT_MIME_BY_SUFFIX = Object.freeze({ ".svg": "image/svg+xml" });
|
|
185399
|
-
const NON_TEXT_SUFFIXES = new Set([
|
|
185400
|
-
".icns",
|
|
185401
|
-
".psd",
|
|
185402
|
-
".ai",
|
|
185403
|
-
".eps",
|
|
185404
|
-
".pdf",
|
|
185405
|
-
".doc",
|
|
185406
|
-
".docx",
|
|
185407
|
-
".dot",
|
|
185408
|
-
".dotx",
|
|
185409
|
-
".rtf",
|
|
185410
|
-
".odt",
|
|
185411
|
-
".xls",
|
|
185412
|
-
".xlsx",
|
|
185413
|
-
".xlsm",
|
|
185414
|
-
".xlt",
|
|
185415
|
-
".xltx",
|
|
185416
|
-
".xltm",
|
|
185417
|
-
".ods",
|
|
185418
|
-
".ppt",
|
|
185419
|
-
".pptx",
|
|
185420
|
-
".pptm",
|
|
185421
|
-
".pps",
|
|
185422
|
-
".ppsx",
|
|
185423
|
-
".odp",
|
|
185424
|
-
".pages",
|
|
185425
|
-
".numbers",
|
|
185426
|
-
".key",
|
|
185427
|
-
".zip",
|
|
185428
|
-
".rar",
|
|
185429
|
-
".7z",
|
|
185430
|
-
".tar",
|
|
185431
|
-
".gz",
|
|
185432
|
-
".tgz",
|
|
185433
|
-
".bz2",
|
|
185434
|
-
".xz",
|
|
185435
|
-
".zst",
|
|
185436
|
-
".lz",
|
|
185437
|
-
".lz4",
|
|
185438
|
-
".br",
|
|
185439
|
-
".cab",
|
|
185440
|
-
".ar",
|
|
185441
|
-
".deb",
|
|
185442
|
-
".rpm",
|
|
185443
|
-
".mp3",
|
|
185444
|
-
".wav",
|
|
185445
|
-
".flac",
|
|
185446
|
-
".ogg",
|
|
185447
|
-
".oga",
|
|
185448
|
-
".opus",
|
|
185449
|
-
".aac",
|
|
185450
|
-
".m4a",
|
|
185451
|
-
".wma",
|
|
185452
|
-
".ttf",
|
|
185453
|
-
".otf",
|
|
185454
|
-
".woff",
|
|
185455
|
-
".woff2",
|
|
185456
|
-
".exe",
|
|
185457
|
-
".dll",
|
|
185458
|
-
".so",
|
|
185459
|
-
".dylib",
|
|
185460
|
-
".bin",
|
|
185461
|
-
".apk",
|
|
185462
|
-
".ipa",
|
|
185463
|
-
".jar",
|
|
185464
|
-
".class",
|
|
185465
|
-
".pyc",
|
|
185466
|
-
".pyo",
|
|
185467
|
-
".wasm",
|
|
185468
|
-
".dmg",
|
|
185469
|
-
".iso",
|
|
185470
|
-
".img",
|
|
185471
|
-
".sqlite",
|
|
185472
|
-
".sqlite3",
|
|
185473
|
-
".db",
|
|
185474
|
-
".db3"
|
|
185475
|
-
]);
|
|
185476
|
-
const ASF_HEADER = Buffer.from([
|
|
185477
|
-
48,
|
|
185478
|
-
38,
|
|
185479
|
-
178,
|
|
185480
|
-
117,
|
|
185481
|
-
142,
|
|
185482
|
-
102,
|
|
185483
|
-
207,
|
|
185484
|
-
17,
|
|
185485
|
-
166,
|
|
185486
|
-
217,
|
|
185487
|
-
0,
|
|
185488
|
-
170,
|
|
185489
|
-
0,
|
|
185490
|
-
98,
|
|
185491
|
-
206,
|
|
185492
|
-
108
|
|
185493
|
-
]);
|
|
185494
|
-
const FTYP_IMAGE_BRANDS = Object.freeze({
|
|
185495
|
-
avif: "image/avif",
|
|
185496
|
-
avis: "image/avif",
|
|
185497
|
-
heic: "image/heic",
|
|
185498
|
-
heif: "image/heif",
|
|
185499
|
-
heix: "image/heif",
|
|
185500
|
-
hevc: "image/heic",
|
|
185501
|
-
mif1: "image/heif",
|
|
185502
|
-
msf1: "image/heif"
|
|
185503
|
-
});
|
|
185504
|
-
const FTYP_VIDEO_BRANDS = Object.freeze({
|
|
185505
|
-
isom: "video/mp4",
|
|
185506
|
-
iso2: "video/mp4",
|
|
185507
|
-
iso5: "video/mp4",
|
|
185508
|
-
mp41: "video/mp4",
|
|
185509
|
-
mp42: "video/mp4",
|
|
185510
|
-
avc1: "video/mp4",
|
|
185511
|
-
mp4v: "video/mp4",
|
|
185512
|
-
m4v: "video/x-m4v",
|
|
185513
|
-
qt: "video/quicktime",
|
|
185514
|
-
"3gp4": "video/3gpp",
|
|
185515
|
-
"3gp5": "video/3gpp",
|
|
185516
|
-
"3gp6": "video/3gpp",
|
|
185517
|
-
"3gp7": "video/3gpp",
|
|
185518
|
-
"3g2": "video/3gpp2"
|
|
185519
|
-
});
|
|
185520
|
-
function toBuffer(data) {
|
|
185521
|
-
return Buffer.isBuffer(data) ? data : Buffer.from(data.buffer, data.byteOffset, data.byteLength);
|
|
185522
|
-
}
|
|
185523
|
-
function startsWith(buf, prefix) {
|
|
185524
|
-
const needle = Buffer.isBuffer(prefix) ? prefix : Buffer.from(prefix);
|
|
185525
|
-
if (buf.length < needle.length) return false;
|
|
185526
|
-
for (let i = 0; i < needle.length; i += 1) if (buf[i] !== needle[i]) return false;
|
|
185527
|
-
return true;
|
|
185528
|
-
}
|
|
185529
|
-
function sniffFtypBrand(header) {
|
|
185530
|
-
if (header.length < 12) return null;
|
|
185531
|
-
if (header.subarray(4, 8).toString("latin1") !== "ftyp") return null;
|
|
185532
|
-
return header.subarray(8, 12).toString("latin1").toLowerCase().replaceAll(/[\s\u0000]+$/g, "").trim();
|
|
185533
|
-
}
|
|
185534
|
-
function sniffMediaFromMagic(data) {
|
|
185535
|
-
const buf = toBuffer(data);
|
|
185536
|
-
const header = buf.length > 512 ? buf.subarray(0, 512) : buf;
|
|
185537
|
-
if (startsWith(header, [
|
|
185538
|
-
137,
|
|
185539
|
-
80,
|
|
185540
|
-
78,
|
|
185541
|
-
71,
|
|
185542
|
-
13,
|
|
185543
|
-
10,
|
|
185544
|
-
26,
|
|
185545
|
-
10
|
|
185546
|
-
])) return {
|
|
185547
|
-
kind: "image",
|
|
185548
|
-
mimeType: "image/png"
|
|
185549
|
-
};
|
|
185550
|
-
if (startsWith(header, [
|
|
185551
|
-
255,
|
|
185552
|
-
216,
|
|
185553
|
-
255
|
|
185554
|
-
])) return {
|
|
185555
|
-
kind: "image",
|
|
185556
|
-
mimeType: "image/jpeg"
|
|
185557
|
-
};
|
|
185558
|
-
if (startsWith(header, Buffer.from("GIF87a")) || startsWith(header, Buffer.from("GIF89a"))) return {
|
|
185559
|
-
kind: "image",
|
|
185560
|
-
mimeType: "image/gif"
|
|
185561
|
-
};
|
|
185562
|
-
if (startsWith(header, Buffer.from("BM"))) return {
|
|
185563
|
-
kind: "image",
|
|
185564
|
-
mimeType: "image/bmp"
|
|
185565
|
-
};
|
|
185566
|
-
if (startsWith(header, [
|
|
185567
|
-
73,
|
|
185568
|
-
73,
|
|
185569
|
-
42,
|
|
185570
|
-
0
|
|
185571
|
-
]) || startsWith(header, [
|
|
185572
|
-
77,
|
|
185573
|
-
77,
|
|
185574
|
-
0,
|
|
185575
|
-
42
|
|
185576
|
-
])) return {
|
|
185577
|
-
kind: "image",
|
|
185578
|
-
mimeType: "image/tiff"
|
|
185579
|
-
};
|
|
185580
|
-
if (startsWith(header, [
|
|
185581
|
-
0,
|
|
185582
|
-
0,
|
|
185583
|
-
1,
|
|
185584
|
-
0
|
|
185585
|
-
])) return {
|
|
185586
|
-
kind: "image",
|
|
185587
|
-
mimeType: "image/x-icon"
|
|
185588
|
-
};
|
|
185589
|
-
if (startsWith(header, Buffer.from("RIFF")) && header.length >= 12) {
|
|
185590
|
-
const chunk = header.subarray(8, 12).toString("latin1");
|
|
185591
|
-
if (chunk === "WEBP") return {
|
|
185592
|
-
kind: "image",
|
|
185593
|
-
mimeType: "image/webp"
|
|
185594
|
-
};
|
|
185595
|
-
if (chunk === "AVI ") return {
|
|
185596
|
-
kind: "video",
|
|
185597
|
-
mimeType: "video/x-msvideo"
|
|
185598
|
-
};
|
|
185599
|
-
}
|
|
185600
|
-
if (startsWith(header, Buffer.from("FLV"))) return {
|
|
185601
|
-
kind: "video",
|
|
185602
|
-
mimeType: "video/x-flv"
|
|
185603
|
-
};
|
|
185604
|
-
if (startsWith(header, ASF_HEADER)) return {
|
|
185605
|
-
kind: "video",
|
|
185606
|
-
mimeType: "video/x-ms-wmv"
|
|
185607
|
-
};
|
|
185608
|
-
if (startsWith(header, [
|
|
185609
|
-
26,
|
|
185610
|
-
69,
|
|
185611
|
-
223,
|
|
185612
|
-
163
|
|
185613
|
-
])) {
|
|
185614
|
-
const lowered = header.toString("latin1").toLowerCase();
|
|
185615
|
-
if (lowered.includes("webm")) return {
|
|
185616
|
-
kind: "video",
|
|
185617
|
-
mimeType: "video/webm"
|
|
185618
|
-
};
|
|
185619
|
-
if (lowered.includes("matroska")) return {
|
|
185620
|
-
kind: "video",
|
|
185621
|
-
mimeType: "video/x-matroska"
|
|
185622
|
-
};
|
|
185623
|
-
}
|
|
185624
|
-
const brand = sniffFtypBrand(header);
|
|
185625
|
-
if (brand !== null && brand !== "") {
|
|
185626
|
-
if (brand in FTYP_IMAGE_BRANDS) return {
|
|
185627
|
-
kind: "image",
|
|
185628
|
-
mimeType: FTYP_IMAGE_BRANDS[brand]
|
|
185629
|
-
};
|
|
185630
|
-
if (brand in FTYP_VIDEO_BRANDS) return {
|
|
185631
|
-
kind: "video",
|
|
185632
|
-
mimeType: FTYP_VIDEO_BRANDS[brand]
|
|
185633
|
-
};
|
|
185634
|
-
}
|
|
185635
|
-
return null;
|
|
185636
|
-
}
|
|
185637
|
-
/**
|
|
185638
|
-
* Best-effort pixel-dimension reader for common raster formats.
|
|
185639
|
-
*
|
|
185640
|
-
* Inspects only the fixed region near the start of the file where each
|
|
185641
|
-
* format records its dimensions (the IHDR/DIB header, the RIFF chunk
|
|
185642
|
-
* after the `WEBP` tag, or the first JPEG SOFn segment). Returns `null`
|
|
185643
|
-
* for formats whose dimensions are not locatable from that region, or
|
|
185644
|
-
* when the supplied buffer is too short to cover it.
|
|
185645
|
-
*/
|
|
185646
|
-
function sniffImageDimensions(data) {
|
|
185647
|
-
const buf = toBuffer(data);
|
|
185648
|
-
if (startsWith(buf, [
|
|
185649
|
-
137,
|
|
185650
|
-
80,
|
|
185651
|
-
78,
|
|
185652
|
-
71,
|
|
185653
|
-
13,
|
|
185654
|
-
10,
|
|
185655
|
-
26,
|
|
185656
|
-
10
|
|
185657
|
-
]) && buf.length >= 24) return {
|
|
185658
|
-
width: buf.readUInt32BE(16),
|
|
185659
|
-
height: buf.readUInt32BE(20)
|
|
185660
|
-
};
|
|
185661
|
-
if ((startsWith(buf, Buffer.from("GIF87a")) || startsWith(buf, Buffer.from("GIF89a"))) && buf.length >= 10) return {
|
|
185662
|
-
width: buf.readUInt16LE(6),
|
|
185663
|
-
height: buf.readUInt16LE(8)
|
|
185664
|
-
};
|
|
185665
|
-
if (startsWith(buf, Buffer.from("BM")) && buf.length >= 26) return {
|
|
185666
|
-
width: buf.readInt32LE(18),
|
|
185667
|
-
height: Math.abs(buf.readInt32LE(22))
|
|
185668
|
-
};
|
|
185669
|
-
if (startsWith(buf, Buffer.from("RIFF")) && buf.length >= 30) {
|
|
185670
|
-
const fourCc = buf.subarray(12, 16).toString("latin1");
|
|
185671
|
-
if (fourCc === "VP8 ") return {
|
|
185672
|
-
width: buf.readUInt16LE(26) & 16383,
|
|
185673
|
-
height: buf.readUInt16LE(28) & 16383
|
|
185674
|
-
};
|
|
185675
|
-
if (fourCc === "VP8L" && buf.length >= 25) {
|
|
185676
|
-
const bits = buf.readUInt32LE(21);
|
|
185677
|
-
return {
|
|
185678
|
-
width: (bits & 16383) + 1,
|
|
185679
|
-
height: (bits >> 14 & 16383) + 1
|
|
185680
|
-
};
|
|
185681
|
-
}
|
|
185682
|
-
if (fourCc === "VP8X") return {
|
|
185683
|
-
width: 1 + (buf[24] | buf[25] << 8 | buf[26] << 16),
|
|
185684
|
-
height: 1 + (buf[27] | buf[28] << 8 | buf[29] << 16)
|
|
185685
|
-
};
|
|
185686
|
-
}
|
|
185687
|
-
if (startsWith(buf, [255, 216])) {
|
|
185688
|
-
let offset = 2;
|
|
185689
|
-
while (offset + 9 < buf.length) {
|
|
185690
|
-
if (buf[offset] !== 255) {
|
|
185691
|
-
offset += 1;
|
|
185692
|
-
continue;
|
|
185693
|
-
}
|
|
185694
|
-
const marker = buf[offset + 1];
|
|
185695
|
-
if (marker >= 192 && marker <= 207 && marker !== 196 && marker !== 200 && marker !== 204) return {
|
|
185696
|
-
height: buf.readUInt16BE(offset + 5),
|
|
185697
|
-
width: buf.readUInt16BE(offset + 7)
|
|
185698
|
-
};
|
|
185699
|
-
if (marker === 216 || marker === 217 || marker >= 208 && marker <= 215) {
|
|
185700
|
-
offset += 2;
|
|
185701
|
-
continue;
|
|
185702
|
-
}
|
|
185703
|
-
const segmentLength = buf.readUInt16BE(offset + 2);
|
|
185704
|
-
if (segmentLength < 2) break;
|
|
185705
|
-
offset += 2 + segmentLength;
|
|
185706
|
-
}
|
|
185707
|
-
}
|
|
185708
|
-
return null;
|
|
185709
|
-
}
|
|
185710
|
-
function getSuffix(path) {
|
|
185711
|
-
const idx = path.lastIndexOf(".");
|
|
185712
|
-
if (idx === -1) return "";
|
|
185713
|
-
if (idx <= Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\")) + 1) return "";
|
|
185714
|
-
return path.slice(idx).toLowerCase();
|
|
185715
|
-
}
|
|
185716
|
-
function detectFileType(path, header, type = "text") {
|
|
185717
|
-
const suffix = getSuffix(path);
|
|
185718
|
-
let mediaHint = null;
|
|
185719
|
-
if (suffix in TEXT_MIME_BY_SUFFIX) mediaHint = {
|
|
185720
|
-
kind: "text",
|
|
185721
|
-
mimeType: TEXT_MIME_BY_SUFFIX[suffix]
|
|
185722
|
-
};
|
|
185723
|
-
else if (suffix in IMAGE_MIME_BY_SUFFIX) mediaHint = {
|
|
185724
|
-
kind: "image",
|
|
185725
|
-
mimeType: IMAGE_MIME_BY_SUFFIX[suffix]
|
|
185726
|
-
};
|
|
185727
|
-
else if (suffix in VIDEO_MIME_BY_SUFFIX) mediaHint = {
|
|
185728
|
-
kind: "video",
|
|
185729
|
-
mimeType: VIDEO_MIME_BY_SUFFIX[suffix]
|
|
185730
|
-
};
|
|
185731
|
-
if (header !== void 0) {
|
|
185732
|
-
const buf = toBuffer(header);
|
|
185733
|
-
const sniffed = sniffMediaFromMagic(buf);
|
|
185734
|
-
if (sniffed) {
|
|
185735
|
-
if (type === "media") return sniffed;
|
|
185736
|
-
if (mediaHint) {
|
|
185737
|
-
if (sniffed.kind !== mediaHint.kind) return {
|
|
185738
|
-
kind: "unknown",
|
|
185739
|
-
mimeType: ""
|
|
185740
|
-
};
|
|
185741
|
-
return mediaHint;
|
|
185742
|
-
}
|
|
185743
|
-
return sniffed;
|
|
185744
|
-
}
|
|
185745
|
-
if (mediaHint?.kind === "image") return {
|
|
185746
|
-
kind: "unknown",
|
|
185747
|
-
mimeType: ""
|
|
185748
|
-
};
|
|
185749
|
-
if (type === "media" && mediaHint?.kind === "video") return mediaHint;
|
|
185750
|
-
if (buf.includes(0)) return {
|
|
185751
|
-
kind: "unknown",
|
|
185752
|
-
mimeType: ""
|
|
185753
|
-
};
|
|
185754
|
-
}
|
|
185755
|
-
if (mediaHint) return mediaHint;
|
|
185756
|
-
if (NON_TEXT_SUFFIXES.has(suffix)) return {
|
|
185757
|
-
kind: "unknown",
|
|
185758
|
-
mimeType: ""
|
|
185759
|
-
};
|
|
185760
|
-
return {
|
|
185761
|
-
kind: "text",
|
|
185762
|
-
mimeType: "text/plain"
|
|
185763
|
-
};
|
|
185764
|
-
}
|
|
185765
|
-
//#endregion
|
|
185766
|
-
//#region ../../packages/agent-core/src/utils/tokens.ts
|
|
185767
|
-
const messageTokenEstimateCache = /* @__PURE__ */ new WeakMap();
|
|
185768
|
-
/** Open assistant messages grow while streaming; completed history stays cached. */
|
|
185769
|
-
function invalidateMessageTokenEstimate(message) {
|
|
185770
|
-
messageTokenEstimateCache.delete(message);
|
|
185771
|
-
}
|
|
185772
|
-
/**
|
|
185773
|
-
* Estimate token count from text using a character-based heuristic.
|
|
185774
|
-
* - ASCII (~4 chars per token)
|
|
185775
|
-
* - CJK and other non-ASCII (~1 char per token)
|
|
185776
|
-
* The estimate is transient — the next LLM call returns the real count
|
|
185777
|
-
* and supersedes this value. Used to keep `tokenCountWithPending`
|
|
185778
|
-
* monotonic between LLM round-trips without paying for a tokenizer.
|
|
185779
|
-
*/
|
|
185780
|
-
function estimateTokens(text) {
|
|
185781
|
-
let asciiCount = 0;
|
|
185782
|
-
let nonAsciiCount = 0;
|
|
185783
|
-
for (const char of text) if (char.codePointAt(0) <= 127) asciiCount++;
|
|
185784
|
-
else nonAsciiCount++;
|
|
185785
|
-
return Math.ceil(asciiCount / 4) + nonAsciiCount;
|
|
185786
|
-
}
|
|
185787
|
-
function estimateTokensForMessages(messages) {
|
|
185788
|
-
let total = 0;
|
|
185789
|
-
for (const message of messages) total += estimateTokensForMessage(message);
|
|
185790
|
-
return total;
|
|
185791
|
-
}
|
|
185792
|
-
function estimateTokensForTools(tools) {
|
|
185793
|
-
let total = 0;
|
|
185794
|
-
for (const tool of tools) {
|
|
185795
|
-
total += estimateTokens(tool.name);
|
|
185796
|
-
total += estimateTokens(tool.description);
|
|
185797
|
-
total += estimateTokens(JSON.stringify(tool.parameters));
|
|
185798
|
-
}
|
|
185799
|
-
return total;
|
|
185800
|
-
}
|
|
185801
|
-
function estimateTokensForMessage(message) {
|
|
185802
|
-
const cached = messageTokenEstimateCache.get(message);
|
|
185803
|
-
if (cached !== void 0) return cached;
|
|
185804
|
-
let total = estimateTokens(message.role);
|
|
185805
|
-
total += estimateTokensForContentParts(message.content);
|
|
185806
|
-
if (message.toolCalls !== void 0) for (const call of message.toolCalls) {
|
|
185807
|
-
total += estimateTokens(call.name);
|
|
185808
|
-
total += estimateTokens(JSON.stringify(call.arguments));
|
|
185809
|
-
}
|
|
185810
|
-
messageTokenEstimateCache.set(message, total);
|
|
185811
|
-
return total;
|
|
185812
|
-
}
|
|
185813
|
-
function estimateTokensForContentParts(parts) {
|
|
185814
|
-
let total = 0;
|
|
185815
|
-
for (const part of parts) total += estimateTokensForContentPart(part);
|
|
185816
|
-
return total;
|
|
185817
|
-
}
|
|
185818
|
-
/**
|
|
185819
|
-
* Conservative transient fallback for media whose pixel dimensions or duration
|
|
185820
|
-
* are unavailable. Inline raster images use their transmitted dimensions below;
|
|
185821
|
-
* audio, video, remote images, and malformed image data keep this safe floor.
|
|
185822
|
-
* The next successful LLM round-trip replaces the estimate with reported usage.
|
|
185823
|
-
*/
|
|
185824
|
-
const MEDIA_TOKEN_ESTIMATE = 2e3;
|
|
185825
|
-
/** Enough header data for common JPEG metadata followed by the first SOF marker. */
|
|
185826
|
-
const MAX_IMAGE_HEADER_BYTES = 1024 * 1024;
|
|
185827
|
-
function imageDimensionsFromDataUrl(url) {
|
|
185828
|
-
const commaIndex = url.indexOf(",");
|
|
185829
|
-
if (commaIndex <= 0) return null;
|
|
185830
|
-
const metadata = url.slice(0, commaIndex).toLowerCase();
|
|
185831
|
-
if (!metadata.startsWith("data:image/") || !metadata.split(";").includes("base64")) return null;
|
|
185832
|
-
const maxBase64Chars = Math.ceil(MAX_IMAGE_HEADER_BYTES / 3) * 4;
|
|
185833
|
-
const encodedHeader = url.slice(commaIndex + 1, commaIndex + 1 + maxBase64Chars);
|
|
185834
|
-
if (encodedHeader.length === 0) return null;
|
|
185835
|
-
try {
|
|
185836
|
-
const dimensions = sniffImageDimensions(Buffer.from(encodedHeader, "base64"));
|
|
185837
|
-
if (dimensions === null || !Number.isSafeInteger(dimensions.width) || !Number.isSafeInteger(dimensions.height) || dimensions.width <= 0 || dimensions.height <= 0) return null;
|
|
185838
|
-
return dimensions;
|
|
185839
|
-
} catch {
|
|
185840
|
-
return null;
|
|
185841
|
-
}
|
|
185842
|
-
}
|
|
185843
|
-
function estimateImageTokensFromDimensions(width, height) {
|
|
185844
|
-
if (!Number.isSafeInteger(width) || !Number.isSafeInteger(height) || width <= 0 || height <= 0) return MEDIA_TOKEN_ESTIMATE;
|
|
185845
|
-
const patchSize = BigInt(32);
|
|
185846
|
-
const tokens = (BigInt(width) + patchSize - 1n) / patchSize * ((BigInt(height) + patchSize - 1n) / patchSize);
|
|
185847
|
-
return tokens > BigInt(Number.MAX_SAFE_INTEGER) ? Number.MAX_SAFE_INTEGER : Number(tokens);
|
|
185848
|
-
}
|
|
185849
|
-
function estimateImageTokens(url) {
|
|
185850
|
-
const dimensions = imageDimensionsFromDataUrl(url);
|
|
185851
|
-
return dimensions === null ? MEDIA_TOKEN_ESTIMATE : estimateImageTokensFromDimensions(dimensions.width, dimensions.height);
|
|
185852
|
-
}
|
|
185853
|
-
function estimateTokensForContentPart(part) {
|
|
185854
|
-
switch (part.type) {
|
|
185855
|
-
case "text": return estimateTokens(part.text);
|
|
185856
|
-
case "think": return estimateTokens(part.think);
|
|
185857
|
-
case "image_url": return estimateImageTokens(part.imageUrl.url);
|
|
185858
|
-
case "audio_url":
|
|
185859
|
-
case "video_url": return MEDIA_TOKEN_ESTIMATE;
|
|
185860
|
-
default: return 0;
|
|
185861
|
-
}
|
|
185862
|
-
}
|
|
185863
186215
|
//#endregion
|
|
185864
186216
|
//#region ../../node_modules/.pnpm/bmp-ts@1.0.9/node_modules/bmp-ts/dist/esm/header-types.js
|
|
185865
186217
|
var HeaderTypes, header_types_default;
|
|
@@ -230115,7 +230467,7 @@ function buildCompactionSummaryText(summary) {
|
|
|
230115
230467
|
const MAX_SESSION_COMPACTION_FAILURES = 2;
|
|
230116
230468
|
const DEFAULT_COMPACTION_MAX_COMPLETION_TOKENS = 128 * 1024;
|
|
230117
230469
|
const COMPACTION_SUMMARY_RESERVE_RATIO = .1;
|
|
230118
|
-
const BLUN_COMPACTION_REQUEST_BUDGET_BYTES =
|
|
230470
|
+
const BLUN_COMPACTION_REQUEST_BUDGET_BYTES = 48e4;
|
|
230119
230471
|
const MAX_HIERARCHICAL_COMPACTION_PASSES = 64;
|
|
230120
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:";
|
|
230121
230473
|
var CompactionTruncatedError = class extends Error {
|
|
@@ -230235,16 +230587,19 @@ var FullCompaction = class {
|
|
|
230235
230587
|
const projected = context.additionalMessages === void 0 ? messages : [...messages, ...context.additionalMessages];
|
|
230236
230588
|
const historyBudget = this.requestHistoryByteBudget(projected);
|
|
230237
230589
|
const historyThresholdReached = historyBudget !== void 0 && historyBudget.usedHistoryBytes >= historyBudget.thresholdHistoryBytes;
|
|
230590
|
+
const requestBudget = this.requestBodyByteBudget(projected, context);
|
|
230591
|
+
const requestThresholdReached = requestBudget !== void 0 && requestBudget.usedRequestBytesEstimate >= requestBudget.thresholdRequestBytes;
|
|
230238
230592
|
if (this.sessionCompactionFailures >= MAX_SESSION_COMPACTION_FAILURES) reason = "session_stopped";
|
|
230239
230593
|
else if (this.isCompacting) reason = "already_compacting";
|
|
230240
|
-
else if (thresholdTokens === void 0 && historyBudget === void 0) reason = "no_budget";
|
|
230241
|
-
else if (!historyThresholdReached && (thresholdTokens === void 0 || !Number.isFinite(usedTokens) || usedTokens < thresholdTokens)) reason = "below_threshold";
|
|
230594
|
+
else if (thresholdTokens === void 0 && historyBudget === void 0 && requestBudget === void 0) reason = "no_budget";
|
|
230595
|
+
else if (!historyThresholdReached && !requestThresholdReached && (thresholdTokens === void 0 || !Number.isFinite(usedTokens) || usedTokens < thresholdTokens)) reason = "below_threshold";
|
|
230242
230596
|
else if (!this.hasShrinkableHistory(projected)) reason = "nothing_to_compact";
|
|
230243
230597
|
return {
|
|
230244
230598
|
eligible: reason === "eligible",
|
|
230245
230599
|
usedTokens,
|
|
230246
230600
|
thresholdTokens,
|
|
230247
230601
|
...historyBudget,
|
|
230602
|
+
...requestBudget,
|
|
230248
230603
|
reason
|
|
230249
230604
|
};
|
|
230250
230605
|
}
|
|
@@ -230266,6 +230621,19 @@ var FullCompaction = class {
|
|
|
230266
230621
|
thresholdHistoryBytes: limit
|
|
230267
230622
|
};
|
|
230268
230623
|
}
|
|
230624
|
+
requestBodyByteBudget(messages, context) {
|
|
230625
|
+
const limit = this.agent.blunConfig?.loopControl?.maxRequestHistoryBytes;
|
|
230626
|
+
if (!this.agent.config.hasProvider || this.strategy.compactionBudgetTokens === void 0 || limit !== void 0 && (!Number.isSafeInteger(limit) || limit <= 0)) return void 0;
|
|
230627
|
+
const model = this.agent.activeResponderModel ?? this.agent.config.modelAlias;
|
|
230628
|
+
if (model === void 0 || this.agent.config.runtimeModel(model).provider.name !== "blun") return void 0;
|
|
230629
|
+
const systemPrompt = context.systemPrompt ?? this.agent.effectiveSystemPrompt;
|
|
230630
|
+
const tools = context.tools ?? this.agent.tools.loopTools;
|
|
230631
|
+
if (estimateBlunSerializedBodyBytes(systemPrompt, [], []) + 4096 >= BLUN_COMPACTION_REQUEST_BUDGET_BYTES) return void 0;
|
|
230632
|
+
return {
|
|
230633
|
+
usedRequestBytesEstimate: estimateBlunSerializedBodyBytes(systemPrompt, tools, messages) + 4096,
|
|
230634
|
+
thresholdRequestBytes: BLUN_COMPACTION_REQUEST_BUDGET_BYTES
|
|
230635
|
+
};
|
|
230636
|
+
}
|
|
230269
230637
|
requestProactiveCompaction(context = {}) {
|
|
230270
230638
|
const status = this.proactiveCompactionStatus(context);
|
|
230271
230639
|
if (status.eligible && !this.proactiveCompactionRequested) {
|
|
@@ -230274,7 +230642,9 @@ var FullCompaction = class {
|
|
|
230274
230642
|
used_tokens: status.usedTokens,
|
|
230275
230643
|
threshold_tokens: status.thresholdTokens,
|
|
230276
230644
|
used_history_bytes: status.usedHistoryBytes,
|
|
230277
|
-
threshold_history_bytes: status.thresholdHistoryBytes
|
|
230645
|
+
threshold_history_bytes: status.thresholdHistoryBytes,
|
|
230646
|
+
used_request_bytes_estimate: status.usedRequestBytesEstimate,
|
|
230647
|
+
threshold_request_bytes: status.thresholdRequestBytes
|
|
230278
230648
|
});
|
|
230279
230649
|
}
|
|
230280
230650
|
return status;
|
|
@@ -230403,7 +230773,9 @@ var FullCompaction = class {
|
|
|
230403
230773
|
const requestTokens = this.estimateCurrentRequestTokens(requestContext);
|
|
230404
230774
|
const budget = this.getCompactionBudgetTokens();
|
|
230405
230775
|
const historyBudget = this.requestHistoryByteBudget(projectedMessages);
|
|
230406
|
-
const
|
|
230776
|
+
const historyThresholdReached = historyBudget !== void 0 && historyBudget.usedHistoryBytes >= historyBudget.thresholdHistoryBytes;
|
|
230777
|
+
const requestBudget = this.requestBodyByteBudget(projectedMessages, requestContext);
|
|
230778
|
+
const proactive = (requestBudget !== void 0 && requestBudget.usedRequestBytesEstimate >= requestBudget.thresholdRequestBytes || historyThresholdReached || !this.isCompacting && budget !== void 0 && Number.isFinite(requestTokens) && requestTokens >= Math.max(1, Math.floor(budget * .9))) && this.hasShrinkableHistory(projectedMessages);
|
|
230407
230779
|
if (this.checkAutoCompaction(true, requestTokens, projectedMessages, proactive) && (proactive || this.strategy.shouldBlock(requestTokens))) await this.block(signal);
|
|
230408
230780
|
signal.throwIfAborted();
|
|
230409
230781
|
const compacted = this.agent.context.history !== historyBefore;
|
|
@@ -230613,7 +230985,7 @@ var FullCompaction = class {
|
|
|
230613
230985
|
dropOrphanResults: true
|
|
230614
230986
|
}), createUserMessage(requestInstruction)], capability));
|
|
230615
230987
|
};
|
|
230616
|
-
const estimateRequestBytes = (messages) =>
|
|
230988
|
+
const estimateRequestBytes = (messages) => estimateBlunSerializedBodyBytes(this.agent.effectiveSystemPrompt, compactionTools, messages) + 4096;
|
|
230617
230989
|
while (true) {
|
|
230618
230990
|
signal.throwIfAborted();
|
|
230619
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: {
|
|
@@ -234193,8 +234565,9 @@ function makeSyntheticToolResult(toolCallId) {
|
|
|
234193
234565
|
}
|
|
234194
234566
|
function mergeAdjacentUserMessages(history, onAnomaly) {
|
|
234195
234567
|
const out = [];
|
|
234196
|
-
|
|
234197
|
-
|
|
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);
|
|
234198
234571
|
if (message === null) continue;
|
|
234199
234572
|
const previous = out.at(-1);
|
|
234200
234573
|
if (canMergeUserMessage(message) && previous !== void 0 && canMergeUserMessage(previous)) {
|
|
@@ -234205,7 +234578,7 @@ function mergeAdjacentUserMessages(history, onAnomaly) {
|
|
|
234205
234578
|
}
|
|
234206
234579
|
return out.map(stripContextMetadata);
|
|
234207
234580
|
}
|
|
234208
|
-
function prepareMessageForProjection(message, onAnomaly) {
|
|
234581
|
+
function prepareMessageForProjection(message, onAnomaly, historical = false) {
|
|
234209
234582
|
if (message.partial === true) return null;
|
|
234210
234583
|
let content;
|
|
234211
234584
|
for (const [index, part] of message.content.entries()) {
|
|
@@ -234217,6 +234590,19 @@ function prepareMessageForProjection(message, onAnomaly) {
|
|
|
234217
234590
|
});
|
|
234218
234591
|
continue;
|
|
234219
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
|
+
}
|
|
234220
234606
|
content?.push(part);
|
|
234221
234607
|
}
|
|
234222
234608
|
const next = content === void 0 ? message : {
|
|
@@ -234226,6 +234612,14 @@ function prepareMessageForProjection(message, onAnomaly) {
|
|
|
234226
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 } });
|
|
234227
234613
|
return next.content.length === 0 && next.toolCalls.length === 0 ? null : next;
|
|
234228
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
|
+
}
|
|
234229
234623
|
function canMergeUserMessage(message) {
|
|
234230
234624
|
return message.role === "user" && message.origin?.kind === "user";
|
|
234231
234625
|
}
|
|
@@ -234290,6 +234684,8 @@ function checkedRemovalIndexes(indexes, length) {
|
|
|
234290
234684
|
}
|
|
234291
234685
|
var ContextMemory = class {
|
|
234292
234686
|
agent;
|
|
234687
|
+
mutationGeneration = randomUUID();
|
|
234688
|
+
mutationRevision = 0;
|
|
234293
234689
|
_history = [];
|
|
234294
234690
|
_tokenCount = 0;
|
|
234295
234691
|
tokenCountCoveredMessageCount = 0;
|
|
@@ -234301,6 +234697,15 @@ var ContextMemory = class {
|
|
|
234301
234697
|
constructor(agent) {
|
|
234302
234698
|
this.agent = agent;
|
|
234303
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
|
+
}
|
|
234304
234709
|
get lastAssistantAt() {
|
|
234305
234710
|
return this._lastAssistantAt;
|
|
234306
234711
|
}
|
|
@@ -234454,6 +234859,7 @@ var ContextMemory = class {
|
|
|
234454
234859
|
return removedMessages.size;
|
|
234455
234860
|
}
|
|
234456
234861
|
clear() {
|
|
234862
|
+
const changed = this._history.length > 0;
|
|
234457
234863
|
this.agent.records.logRecord({ type: "context.clear" });
|
|
234458
234864
|
this._history = [];
|
|
234459
234865
|
this._tokenCount = 0;
|
|
@@ -234465,6 +234871,7 @@ var ContextMemory = class {
|
|
|
234465
234871
|
this.agent.microCompaction.reset();
|
|
234466
234872
|
this.agent.injection.onContextClear();
|
|
234467
234873
|
this.agent.emitStatusUpdated();
|
|
234874
|
+
if (changed) this.publishMutation("clear");
|
|
234468
234875
|
}
|
|
234469
234876
|
undo(count) {
|
|
234470
234877
|
if (count <= 0) return;
|
|
@@ -234502,6 +234909,7 @@ var ContextMemory = class {
|
|
|
234502
234909
|
this.deferredMessages = [];
|
|
234503
234910
|
this.agent.microCompaction.reset(this._history.length);
|
|
234504
234911
|
this.agent.emitStatusUpdated();
|
|
234912
|
+
if (removedMessages.size > 0) this.publishMutation("undo");
|
|
234505
234913
|
if (!this.agent.records.restoring && (stoppedAtBoundary || removedUserCount < count)) throw new BlunError(ErrorCodes.REQUEST_INVALID, formatUndoUnavailableMessage(count, removedUserCount, stoppedAtBoundary), { details: {
|
|
234506
234914
|
reason: "undo_limit",
|
|
234507
234915
|
requestedCount: count,
|
|
@@ -234510,6 +234918,7 @@ var ContextMemory = class {
|
|
|
234510
234918
|
} });
|
|
234511
234919
|
}
|
|
234512
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");
|
|
234513
234922
|
let preservedToolTailCount = input.preservedToolTailCount;
|
|
234514
234923
|
if (this.agent.records.restoring === null && this.hasOpenToolExchange()) {
|
|
234515
234924
|
const start = this._history.findIndex((message) => message.role === "assistant" && message.toolCalls.some((call) => this.pendingToolResultIds.has(call.id)));
|
|
@@ -234546,25 +234955,75 @@ var ContextMemory = class {
|
|
|
234546
234955
|
elisionMessage,
|
|
234547
234956
|
...selection.tail
|
|
234548
234957
|
];
|
|
234549
|
-
|
|
234550
|
-
|
|
234958
|
+
let contextSummary = input.contextSummary ?? input.summary;
|
|
234959
|
+
let toolContinuity = this.agent.records.restoring === null ? void 0 : input.toolContinuity;
|
|
234960
|
+
let summaryMessage = {
|
|
234551
234961
|
role: "user",
|
|
234552
234962
|
content: [{
|
|
234553
234963
|
type: "text",
|
|
234554
234964
|
text: contextSummary
|
|
234555
234965
|
}],
|
|
234556
234966
|
toolCalls: [],
|
|
234557
|
-
origin: {
|
|
234967
|
+
origin: {
|
|
234968
|
+
kind: "compaction_summary",
|
|
234969
|
+
...toolContinuity === void 0 ? {} : { toolContinuity }
|
|
234970
|
+
}
|
|
234558
234971
|
};
|
|
234559
|
-
|
|
234972
|
+
let replacement = [
|
|
234560
234973
|
...keptMessages,
|
|
234561
234974
|
summaryMessage,
|
|
234562
234975
|
...preservedToolTail
|
|
234563
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
|
+
}
|
|
234564
235024
|
if (options.requireReduction && this.agent.records.restoring === null) {
|
|
234565
|
-
const previousHistoryTokens = estimateTokensForMessages(project(this.agent.microCompaction.compact(this._history), { dropOrphanResults: true }));
|
|
234566
235025
|
const nextHistoryTokens = estimateTokensForMessages(project(replacement, { dropOrphanResults: true }));
|
|
234567
|
-
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: {
|
|
234568
235027
|
reason: "non_reducing_summary",
|
|
234569
235028
|
contextUnchanged: true,
|
|
234570
235029
|
previousHistoryTokens,
|
|
@@ -234577,6 +235036,7 @@ var ContextMemory = class {
|
|
|
234577
235036
|
const result = {
|
|
234578
235037
|
summary: input.summary,
|
|
234579
235038
|
contextSummary,
|
|
235039
|
+
...toolContinuity === void 0 ? {} : { toolContinuity },
|
|
234580
235040
|
compactedCount: input.compactedCount,
|
|
234581
235041
|
tokensBefore: input.tokensBefore,
|
|
234582
235042
|
tokensAfter,
|
|
@@ -234593,6 +235053,7 @@ var ContextMemory = class {
|
|
|
234593
235053
|
this.agent.replayBuilder.patchLast("compaction", { result: {
|
|
234594
235054
|
summary: result.summary,
|
|
234595
235055
|
contextSummary: result.contextSummary,
|
|
235056
|
+
...result.toolContinuity === void 0 ? {} : { toolContinuity: result.toolContinuity },
|
|
234596
235057
|
compactedCount: result.compactedCount,
|
|
234597
235058
|
tokensBefore: result.tokensBefore,
|
|
234598
235059
|
tokensAfter: result.tokensAfter,
|
|
@@ -236200,20 +236661,75 @@ function fingerprintTitle(title) {
|
|
|
236200
236661
|
return createHash("sha256").update(title.trim().toLowerCase()).digest("hex");
|
|
236201
236662
|
}
|
|
236202
236663
|
async function loadRegister(mistakeDir = defaultMistakeDir()) {
|
|
236664
|
+
const target = join(mistakeDir, REGISTER_FILENAME);
|
|
236203
236665
|
try {
|
|
236204
236666
|
await mkdir(mistakeDir, { recursive: true });
|
|
236205
|
-
const
|
|
236206
|
-
|
|
236207
|
-
|
|
236208
|
-
|
|
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 {
|
|
236209
236672
|
version: 1,
|
|
236210
236673
|
entries: []
|
|
236211
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");
|
|
236212
236695
|
}
|
|
236213
236696
|
}
|
|
236214
236697
|
async function saveRegister(register, mistakeDir = defaultMistakeDir()) {
|
|
236215
|
-
|
|
236216
|
-
|
|
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}.`);
|
|
236217
236733
|
}
|
|
236218
236734
|
/**
|
|
236219
236735
|
* Findet einen Register-Eintrag anhand des Titels (Fingerabdruck).
|
|
@@ -238906,6 +239422,7 @@ var import_turn_tool_performance_policy = (/* @__PURE__ */ __commonJSMin(((expor
|
|
|
238906
239422
|
const DEFERRED_TOOL_LOADER_NAME = "ToolSearch";
|
|
238907
239423
|
const MAX_PERSISTENT_DEFERRED_TOOLS = 12;
|
|
238908
239424
|
const MAX_TOOL_SEARCH_QUERY_CHARS = 1e3;
|
|
239425
|
+
const MAX_TOOL_CATALOG_RESULT_BYTES = 4096;
|
|
238909
239426
|
const MAX_AUTO_RANKED_TOOLS = 6;
|
|
238910
239427
|
const deferredToolLoaders = /* @__PURE__ */ new WeakSet();
|
|
238911
239428
|
const TOOL_RANK_EMBEDDED_CONTENT_RE = /<(attached_documents?|attachment_content|document_content|file_content)\b[^>]*>[\s\S]*?<\/\1>/giu;
|
|
@@ -238976,6 +239493,32 @@ var import_turn_tool_performance_policy = (/* @__PURE__ */ __commonJSMin(((expor
|
|
|
238976
239493
|
"suchen"
|
|
238977
239494
|
]);
|
|
238978
239495
|
const TOOL_SEARCH_RELATED_TERM_GROUPS = Object.freeze([
|
|
239496
|
+
Object.freeze([
|
|
239497
|
+
"persist",
|
|
239498
|
+
"save",
|
|
239499
|
+
"speichere",
|
|
239500
|
+
"speichern",
|
|
239501
|
+
"store"
|
|
239502
|
+
]),
|
|
239503
|
+
Object.freeze([
|
|
239504
|
+
"erinnerung",
|
|
239505
|
+
"erinnerungen",
|
|
239506
|
+
"fact",
|
|
239507
|
+
"facts",
|
|
239508
|
+
"fakt",
|
|
239509
|
+
"fakten",
|
|
239510
|
+
"memory",
|
|
239511
|
+
"memories",
|
|
239512
|
+
"merk",
|
|
239513
|
+
"merken",
|
|
239514
|
+
"remember"
|
|
239515
|
+
]),
|
|
239516
|
+
Object.freeze([
|
|
239517
|
+
"note",
|
|
239518
|
+
"notes",
|
|
239519
|
+
"notiz",
|
|
239520
|
+
"notizen"
|
|
239521
|
+
]),
|
|
238979
239522
|
Object.freeze([
|
|
238980
239523
|
"checklist",
|
|
238981
239524
|
"list",
|
|
@@ -239124,6 +239667,27 @@ var import_turn_tool_performance_policy = (/* @__PURE__ */ __commonJSMin(((expor
|
|
|
239124
239667
|
for (const leaf of leaves) leafCounts.set(leaf, (leafCounts.get(leaf) || 0) + 1);
|
|
239125
239668
|
return names.map((name, index) => leafCounts.get(leaves[index]) === 1 ? leaves[index] : name).sort((left, right) => left.localeCompare(right));
|
|
239126
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
|
+
}
|
|
239127
239691
|
function normalizeDeferredToolQuery(value) {
|
|
239128
239692
|
const query = String(value ?? "").trim();
|
|
239129
239693
|
if (query.length <= MAX_TOOL_SEARCH_QUERY_CHARS) return query;
|
|
@@ -239173,22 +239737,39 @@ var import_turn_tool_performance_policy = (/* @__PURE__ */ __commonJSMin(((expor
|
|
|
239173
239737
|
function relatedSearchTerms(token) {
|
|
239174
239738
|
return TOOL_SEARCH_RELATED_TERM_GROUPS.find((terms) => terms.includes(token)) || [token];
|
|
239175
239739
|
}
|
|
239740
|
+
function withoutFencedCode(value) {
|
|
239741
|
+
const visibleLines = [];
|
|
239742
|
+
let fence = null;
|
|
239743
|
+
for (const line of String(value || "").split(/\r?\n/)) {
|
|
239744
|
+
const marker = line.match(/^ {0,3}(`{3,}|~{3,})/u)?.[1];
|
|
239745
|
+
if (fence) {
|
|
239746
|
+
if (marker?.[0] === fence[0] && marker.length >= fence.length && /^ {0,3}(?:`{3,}|~{3,})[ \t]*$/u.test(line)) fence = null;
|
|
239747
|
+
continue;
|
|
239748
|
+
}
|
|
239749
|
+
if (marker) {
|
|
239750
|
+
fence = marker;
|
|
239751
|
+
continue;
|
|
239752
|
+
}
|
|
239753
|
+
visibleLines.push(line);
|
|
239754
|
+
}
|
|
239755
|
+
return visibleLines.join("\n");
|
|
239756
|
+
}
|
|
239176
239757
|
function rankingIntentTexts(value) {
|
|
239177
239758
|
const text = String(value || "");
|
|
239178
239759
|
const channelBodies = [...text.matchAll(/(?:^|\r?\n)<channel\b[^>]*>\r?\n([\s\S]*?)\r?\n<\/channel>(?=\r?\n|$)/giu)].map((match) => match[1]);
|
|
239179
|
-
return (channelBodies.length > 0 ? channelBodies : [text]).map((intentText) => normalizeDeferredToolQuery(intentText.replace(TOOL_RANK_EMBEDDED_CONTENT_RE, " ")));
|
|
239760
|
+
return (channelBodies.length > 0 ? channelBodies : [text]).map((intentText) => normalizeDeferredToolQuery(withoutFencedCode(intentText.replace(TOOL_RANK_EMBEDDED_CONTENT_RE, " "))));
|
|
239180
239761
|
}
|
|
239181
239762
|
function rankingTokens(value) {
|
|
239182
239763
|
return [...new Set(String(value || "").normalize("NFKC").toLowerCase().match(/[\p{L}\p{N}]{3,}/gu) || [])].filter((token) => !TOOL_RANK_STOP_WORDS.has(token));
|
|
239183
239764
|
}
|
|
239184
|
-
function toolRankingDocument(tool) {
|
|
239765
|
+
function toolRankingDocument(tool, trustedToolNames) {
|
|
239185
239766
|
const name = String(tool?.name || "");
|
|
239186
239767
|
const leaf = name.split(/__|:/).at(-1) || name;
|
|
239187
239768
|
const splitToolName = (value) => String(value || "").replace(/([a-z0-9])([A-Z])/g, "$1 $2").replaceAll("_", " ");
|
|
239188
239769
|
const nameTokens = rankingTokens(`${splitToolName(name)} ${splitToolName(leaf)}`);
|
|
239189
239770
|
const descriptionTokens = rankingTokens(tool?.description);
|
|
239190
239771
|
const parameterText = [];
|
|
239191
|
-
const properties = tool?.parameters?.properties;
|
|
239772
|
+
const properties = /^mcp__/iu.test(name) && !trustedToolNames?.has(name) ? void 0 : tool?.parameters?.properties;
|
|
239192
239773
|
if (properties && typeof properties === "object") for (const [parameterName, definition] of Object.entries(properties)) parameterText.push(parameterName, definition?.description || "");
|
|
239193
239774
|
const exampleText = Array.isArray(tool?.examples) ? tool.examples.map((example) => example?.prompt || "").join(" ") : "";
|
|
239194
239775
|
return {
|
|
@@ -239220,7 +239801,7 @@ var import_turn_tool_performance_policy = (/* @__PURE__ */ __commonJSMin(((expor
|
|
|
239220
239801
|
const queryTokens = [...new Set(rankingIntentTexts(value).flatMap(rankingTokens))];
|
|
239221
239802
|
if (queryTokens.length === 0) return /* @__PURE__ */ new Set();
|
|
239222
239803
|
const ranked = (Array.isArray(tools) ? tools : []).map((tool) => {
|
|
239223
|
-
const document = toolRankingDocument(tool);
|
|
239804
|
+
const document = toolRankingDocument(tool, options.trustedToolNames);
|
|
239224
239805
|
if (!document.name) return null;
|
|
239225
239806
|
let score = 0;
|
|
239226
239807
|
let matchedTokens = 0;
|
|
@@ -239234,7 +239815,7 @@ var import_turn_tool_performance_policy = (/* @__PURE__ */ __commonJSMin(((expor
|
|
|
239234
239815
|
if (document.nameTokens.has(token)) exactNameMatches += 1;
|
|
239235
239816
|
else if (relatedSearchTerms(token).some((term) => document.nameTokens.has(term))) relatedNameMatches += 1;
|
|
239236
239817
|
}
|
|
239237
|
-
return matchedTokens >= 2 || exactNameMatches >= 1 && score >= 10 || relatedNameMatches >= 1 && score >= 5 ? {
|
|
239818
|
+
return matchedTokens >= 2 || exactNameMatches >= 1 && score >= 10 || queryTokens.length === 1 && relatedNameMatches >= 1 && score >= 5 ? {
|
|
239238
239819
|
name: document.name,
|
|
239239
239820
|
score,
|
|
239240
239821
|
matchedTokens,
|
|
@@ -239255,11 +239836,11 @@ var import_turn_tool_performance_policy = (/* @__PURE__ */ __commonJSMin(((expor
|
|
|
239255
239836
|
function searchRelatedDeferredTools(tools, query, options = {}) {
|
|
239256
239837
|
const normalized = normalizeDeferredToolQuery(query).toLowerCase();
|
|
239257
239838
|
if (!normalized || normalized.startsWith("select:")) return [];
|
|
239258
|
-
const tokens = normalized.
|
|
239839
|
+
const tokens = normalized.match(/\+?[\p{L}\p{N}_-]+/gu) || [];
|
|
239259
239840
|
const requestedNameTokens = tokens.filter((token) => token.startsWith("+")).map((token) => token.slice(1)).filter(Boolean);
|
|
239260
239841
|
const relaxRequiredNameTokens = options.relaxRequiredNameTokens === true && requestedNameTokens.length > 0;
|
|
239261
239842
|
const requiredNameTokens = relaxRequiredNameTokens ? [] : requestedNameTokens;
|
|
239262
|
-
const searchTokens = [...tokens.filter((token) => !token.startsWith("+")), ...relaxRequiredNameTokens ? requestedNameTokens : []].filter((token) => !TOOL_SEARCH_INTENT_WORDS.has(token));
|
|
239843
|
+
const searchTokens = [...tokens.filter((token) => !token.startsWith("+")), ...relaxRequiredNameTokens ? requestedNameTokens : []].filter((token) => !TOOL_SEARCH_INTENT_WORDS.has(token) && !TOOL_RANK_STOP_WORDS.has(token));
|
|
239263
239844
|
if (searchTokens.length < 2 && !TOOL_SEARCH_SINGLE_TERM_RELATED_FALLBACKS.has(searchTokens[0])) return [];
|
|
239264
239845
|
const minimumMatchedTokens = searchTokens.length === 1 ? 1 : Math.max(2, Math.ceil(searchTokens.length * .75));
|
|
239265
239846
|
const ranked = tools.map((tool) => {
|
|
@@ -239328,8 +239909,8 @@ var import_turn_tool_performance_policy = (/* @__PURE__ */ __commonJSMin(((expor
|
|
|
239328
239909
|
name: loaderName,
|
|
239329
239910
|
description: [
|
|
239330
239911
|
`Search ${deferredCount} deferred ${deferredCount === 1 ? "tool schema" : "tool schemas"} without loading all definitions.`,
|
|
239331
|
-
"Use select:leaf_name for one known tool, plain keywords to search,
|
|
239332
|
-
`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.`
|
|
239333
239914
|
].join("\n"),
|
|
239334
239915
|
parameters: {
|
|
239335
239916
|
type: "object",
|
|
@@ -239346,7 +239927,12 @@ var import_turn_tool_performance_policy = (/* @__PURE__ */ __commonJSMin(((expor
|
|
|
239346
239927
|
return {
|
|
239347
239928
|
description: query ? `Searching tool schemas for ${query}` : "Searching tool schemas",
|
|
239348
239929
|
approvalRule: loaderName,
|
|
239349
|
-
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
|
+
};
|
|
239350
239936
|
let matches = searchDeferredTools([...available.values()], query);
|
|
239351
239937
|
let relatedFallback = false;
|
|
239352
239938
|
if (matches.length === 0) {
|
|
@@ -250063,7 +250649,8 @@ function logStepTiming(log, turnId, step, response) {
|
|
|
250063
250649
|
inputOtherTokens: response.usage.inputOther,
|
|
250064
250650
|
cacheReadTokens: response.usage.inputCacheRead,
|
|
250065
250651
|
cacheCreationTokens: response.usage.inputCacheCreation,
|
|
250066
|
-
outputTokens: response.usage.output
|
|
250652
|
+
outputTokens: response.usage.output,
|
|
250653
|
+
...response.usage.outputReasoning === void 0 ? {} : { outputReasoningTokens: response.usage.outputReasoning }
|
|
250067
250654
|
});
|
|
250068
250655
|
}
|
|
250069
250656
|
function deriveStepStopReason(response) {
|
|
@@ -251051,6 +251638,7 @@ const MCP_OAUTH_AUTHORIZATION_URL_TOOL_UPDATE = "mcp.oauth.authorization_url";
|
|
|
251051
251638
|
const tokenUsageSchema = object({
|
|
251052
251639
|
inputOther: number$1(),
|
|
251053
251640
|
output: number$1(),
|
|
251641
|
+
outputReasoning: number$1().optional(),
|
|
251054
251642
|
inputCacheRead: number$1(),
|
|
251055
251643
|
inputCacheCreation: number$1()
|
|
251056
251644
|
});
|
|
@@ -251210,7 +251798,11 @@ const goalChangeStatsSchema = object({
|
|
|
251210
251798
|
wallClockMs: number$1()
|
|
251211
251799
|
});
|
|
251212
251800
|
const goalChangeSchema = object({
|
|
251213
|
-
kind: _enum([
|
|
251801
|
+
kind: _enum([
|
|
251802
|
+
"lifecycle",
|
|
251803
|
+
"completion",
|
|
251804
|
+
"edited"
|
|
251805
|
+
]),
|
|
251214
251806
|
status: goalStatusSchema.optional(),
|
|
251215
251807
|
reason: string().optional(),
|
|
251216
251808
|
stats: goalChangeStatsSchema.optional(),
|
|
@@ -251361,6 +251953,12 @@ const turnEndReasonSchema = _enum([
|
|
|
251361
251953
|
"failed",
|
|
251362
251954
|
"filtered"
|
|
251363
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
|
+
});
|
|
251364
251962
|
const agentStatusUpdatedEventSchema = object({
|
|
251365
251963
|
type: literal("agent.status.updated"),
|
|
251366
251964
|
model: string().optional(),
|
|
@@ -251680,6 +252278,7 @@ const eventSchema = discriminatedUnion("type", [
|
|
|
251680
252278
|
errorEventSchema,
|
|
251681
252279
|
warningEventSchema,
|
|
251682
252280
|
agentStatusUpdatedEventSchema,
|
|
252281
|
+
contextChangedEventSchema,
|
|
251683
252282
|
sessionMetaUpdatedEventSchema,
|
|
251684
252283
|
sessionCreatedEventSchema,
|
|
251685
252284
|
workspaceCreatedEventSchema,
|
|
@@ -265080,9 +265679,16 @@ var ToolCallDeduplicator = class {
|
|
|
265080
265679
|
//#region ../../packages/agent-core/src/agent/turn/tool-result-budget.ts
|
|
265081
265680
|
const TOOL_RESULT_MAX_CHARS = 5e4;
|
|
265082
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
|
+
}
|
|
265083
265688
|
async function budgetToolResultForModel(options) {
|
|
265084
265689
|
const text = persistableToolResultText(options.result.output);
|
|
265085
|
-
|
|
265690
|
+
const maxChars = toolResultMaxChars(options.maxContextTokens);
|
|
265691
|
+
if (text === void 0 || text.length <= maxChars) return options.result;
|
|
265086
265692
|
if (options.result.truncated === true) return options.result;
|
|
265087
265693
|
if (options.homedir === void 0) return options.result;
|
|
265088
265694
|
if (text.includes("\0") || Buffer.from(text, "utf8").toString("utf8") !== text || text.split("\n").some((line) => line.length > 2e3)) return options.result;
|
|
@@ -265093,7 +265699,7 @@ async function budgetToolResultForModel(options) {
|
|
|
265093
265699
|
toolCallId: options.toolCallId
|
|
265094
265700
|
}, text);
|
|
265095
265701
|
if (outputPath === void 0) return options.result;
|
|
265096
|
-
const output = renderPersistedToolResult(options.toolName, options.toolCallId, text, outputPath);
|
|
265702
|
+
const output = renderPersistedToolResult(options.toolName, options.toolCallId, text, outputPath, maxChars);
|
|
265097
265703
|
return options.result.isError === true ? {
|
|
265098
265704
|
...options.result,
|
|
265099
265705
|
output,
|
|
@@ -265125,9 +265731,9 @@ async function saveToolResult(options, text) {
|
|
|
265125
265731
|
return;
|
|
265126
265732
|
}
|
|
265127
265733
|
}
|
|
265128
|
-
function renderPersistedToolResult(toolName, toolCallId, text, outputPath) {
|
|
265734
|
+
function renderPersistedToolResult(toolName, toolCallId, text, outputPath, maxChars) {
|
|
265129
265735
|
const lines = [
|
|
265130
|
-
`Tool output exceeded ${String(
|
|
265736
|
+
`Tool output exceeded ${String(maxChars)} characters; showing a preview only.`,
|
|
265131
265737
|
`tool_name: ${toolName}`,
|
|
265132
265738
|
`tool_call_id: ${toolCallId}`,
|
|
265133
265739
|
`output_size_chars: ${String(text.length)}`,
|
|
@@ -267093,14 +267699,27 @@ function blunToolsForOrigin(tools, origin) {
|
|
|
267093
267699
|
* the ordinary permission pipeline.
|
|
267094
267700
|
*/
|
|
267095
267701
|
function blunSelectTurnTools(tools, maxContextTokens, loadedToolNames = /* @__PURE__ */ new Set(), requiredToolNames = /* @__PURE__ */ new Set(), selected = []) {
|
|
267096
|
-
|
|
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)) {
|
|
267097
267704
|
selected.splice(0, selected.length, ...tools);
|
|
267098
267705
|
return selected;
|
|
267099
267706
|
}
|
|
267100
|
-
|
|
267101
|
-
const
|
|
267102
|
-
const
|
|
267103
|
-
|
|
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
|
+
}
|
|
267104
267723
|
return selected;
|
|
267105
267724
|
}
|
|
267106
267725
|
const LLM_NOT_SET_MESSAGE = "LLM not set, send \"/login\" to login";
|
|
@@ -267590,6 +268209,7 @@ var TurnFlow = class {
|
|
|
267590
268209
|
const appendedMessage = this.agent.context.history.at(-1);
|
|
267591
268210
|
const turnAnchor = appendedMessage !== previousLastMessage && appendedMessage?.role === "user" && appendedMessage.origin === origin ? appendedMessage : void 0;
|
|
267592
268211
|
const startedAt = Date.now();
|
|
268212
|
+
const preRequestHookStartedAt = performance.now();
|
|
267593
268213
|
let ended;
|
|
267594
268214
|
let blockedByUserPromptHook = false;
|
|
267595
268215
|
let completedStopReason;
|
|
@@ -267615,6 +268235,13 @@ var TurnFlow = class {
|
|
|
267615
268235
|
this.agent.log.warn("Turn-start observation failed");
|
|
267616
268236
|
}
|
|
267617
268237
|
signal.throwIfAborted();
|
|
268238
|
+
if (this.agent.type === "main" && process.env["BLUN_DIAG_PRE_REQUEST_PHASES"] === "1") try {
|
|
268239
|
+
this.agent.log.info("turn pre-request phase", {
|
|
268240
|
+
turnId,
|
|
268241
|
+
phase: "turn-hooks",
|
|
268242
|
+
durationMs: Math.max(0, Math.round(performance.now() - preRequestHookStartedAt))
|
|
268243
|
+
});
|
|
268244
|
+
} catch {}
|
|
267618
268245
|
const stopReason = await this.runStepLoop(turnId, signal, input, origin, turnAnchor, (response) => {
|
|
267619
268246
|
completedResponse = response;
|
|
267620
268247
|
});
|
|
@@ -267726,6 +268353,10 @@ var TurnFlow = class {
|
|
|
267726
268353
|
signal.throwIfAborted();
|
|
267727
268354
|
const blockResult = renderUserPromptHookBlockResult(promptHookResults);
|
|
267728
268355
|
if (blockResult !== void 0) {
|
|
268356
|
+
this.agent.log.warn("turn blocked by UserPromptSubmit hook", {
|
|
268357
|
+
turnId,
|
|
268358
|
+
reason: blockResult.message
|
|
268359
|
+
});
|
|
267729
268360
|
this.agent.context.appendMessage({
|
|
267730
268361
|
role: "assistant",
|
|
267731
268362
|
content: [{
|
|
@@ -267784,9 +268415,26 @@ var TurnFlow = class {
|
|
|
267784
268415
|
let stopHookContinuationUsed = false;
|
|
267785
268416
|
let goalOutcomeMessageContinuationUsed = false;
|
|
267786
268417
|
const deduper = new ToolCallDeduplicator({ telemetry: this.agent.telemetry });
|
|
268418
|
+
const diagnosePreRequest = this.agent.type === "main" && process.env["BLUN_DIAG_PRE_REQUEST_PHASES"] === "1";
|
|
268419
|
+
const recordPreRequestPhase = (phase, startedAt) => {
|
|
268420
|
+
if (!diagnosePreRequest) return;
|
|
268421
|
+
try {
|
|
268422
|
+
this.agent.log.info("turn pre-request phase", {
|
|
268423
|
+
turnId,
|
|
268424
|
+
phase,
|
|
268425
|
+
durationMs: Math.max(0, Math.round(performance.now() - startedAt))
|
|
268426
|
+
});
|
|
268427
|
+
} catch {}
|
|
268428
|
+
};
|
|
268429
|
+
let phaseStartedAt = performance.now();
|
|
267787
268430
|
await this.agent.mcp?.waitForInitialLoad(signal);
|
|
268431
|
+
recordPreRequestPhase("mcp-initial-load", phaseStartedAt);
|
|
268432
|
+
phaseStartedAt = performance.now();
|
|
267788
268433
|
const personalMemoryRecall = await this.agent.injection.injectPersonalMemoryForTurn(turnId, input, origin, signal);
|
|
268434
|
+
recordPreRequestPhase("personal-memory-recall", phaseStartedAt);
|
|
268435
|
+
phaseStartedAt = performance.now();
|
|
267789
268436
|
await this.agent.injection.injectGoal();
|
|
268437
|
+
recordPreRequestPhase("goal-injection", phaseStartedAt);
|
|
267790
268438
|
this.setActiveSteerAcceptance(turnId, true);
|
|
267791
268439
|
const turnNeedsThinking = blunTurnNeedsTools(blunThinkingIntentInput(input), origin);
|
|
267792
268440
|
let toolInput = input;
|
|
@@ -267797,12 +268445,14 @@ var TurnFlow = class {
|
|
|
267797
268445
|
const raw = [...this.agent.context.history];
|
|
267798
268446
|
const history = personalMemoryRecall === void 0 ? raw : [...raw, personalMemoryRecall];
|
|
267799
268447
|
const selected = taskToolsNeeded ? history : greetingHistory(history, greetingAnchor);
|
|
268448
|
+
const projectionStartedAt = performance.now();
|
|
267800
268449
|
const projected = await this.historicalToolProjection.project(selected, turnAnchor, tools, {
|
|
267801
268450
|
turnId: String(turnId),
|
|
267802
268451
|
stepNumber: this.currentStep,
|
|
267803
268452
|
signal,
|
|
267804
268453
|
llm: turnLLM
|
|
267805
268454
|
});
|
|
268455
|
+
recordPreRequestPhase("historical-tool-projection", projectionStartedAt);
|
|
267806
268456
|
const current = this.agent.context.history;
|
|
267807
268457
|
if (current.length !== raw.length || current.some((message, index) => message !== raw[index])) {
|
|
267808
268458
|
const latest = personalMemoryRecall === void 0 ? current : [...current, personalMemoryRecall];
|
|
@@ -267813,7 +268463,7 @@ var TurnFlow = class {
|
|
|
267813
268463
|
partialContext = selected.length < history.length || projected.changed;
|
|
267814
268464
|
return projected.history;
|
|
267815
268465
|
};
|
|
267816
|
-
const turnLLM = this.agent.llmForTurn(turnNeedsThinking ? void 0 : "off");
|
|
268466
|
+
const turnLLM = this.agent.llmForTurn(turnNeedsThinking ? void 0 : "off", turnId);
|
|
267817
268467
|
const turnTools = this.agent.tools.captureTurnTools();
|
|
267818
268468
|
while (true) {
|
|
267819
268469
|
signal.throwIfAborted();
|
|
@@ -267823,18 +268473,22 @@ var TurnFlow = class {
|
|
|
267823
268473
|
try {
|
|
267824
268474
|
const selectedTools = [];
|
|
267825
268475
|
this.refreshSelectedTools = (snapshot) => {
|
|
268476
|
+
const selectionStartedAt = performance.now();
|
|
267826
268477
|
if (snapshot.messages.length > 0) toolInput = snapshot.messages.flatMap((message) => message.content);
|
|
267827
268478
|
const eligibleTools = blunToolsForOrigin(this.agent.injection.filterPersonalMemoryToolsForTurn(turnId, input, origin, turnTools()), origin);
|
|
267828
268479
|
const intent = blunThinkingIntentInput(toolInput);
|
|
267829
268480
|
taskToolsNeeded ||= blunTurnNeedsTools(intent, origin) || blunTurnHasAttachment(toolInput);
|
|
267830
268481
|
const required = (0, import_turn_tool_performance_policy.mediaToolNamesForTurnText)(blunExtractText(toolInput));
|
|
267831
268482
|
if (taskToolsNeeded) {
|
|
267832
|
-
|
|
267833
|
-
|
|
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 })) {
|
|
267834
268487
|
const tool = eligibleTools.find((candidate) => candidate.name === name);
|
|
267835
|
-
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);
|
|
267836
268489
|
}
|
|
267837
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)));
|
|
268491
|
+
recordPreRequestPhase("tool-selection", selectionStartedAt);
|
|
267838
268492
|
return selectedTools;
|
|
267839
268493
|
};
|
|
267840
268494
|
return (await runTurn({
|
|
@@ -267847,14 +268501,24 @@ var TurnFlow = class {
|
|
|
267847
268501
|
}, completion);
|
|
267848
268502
|
},
|
|
267849
268503
|
llm: turnLLM,
|
|
267850
|
-
buildMessages: async () =>
|
|
267851
|
-
|
|
267852
|
-
|
|
267853
|
-
|
|
267854
|
-
|
|
267855
|
-
|
|
267856
|
-
|
|
267857
|
-
|
|
268504
|
+
buildMessages: async () => {
|
|
268505
|
+
const startedAt = performance.now();
|
|
268506
|
+
const messages = this.agent.context.project(await turnHistory(selectedTools), { dropOrphanResults: true });
|
|
268507
|
+
recordPreRequestPhase("message-build", startedAt);
|
|
268508
|
+
return messages;
|
|
268509
|
+
},
|
|
268510
|
+
buildMessagesStrict: async () => {
|
|
268511
|
+
const startedAt = performance.now();
|
|
268512
|
+
const messages = this.agent.context.project(await turnHistory(selectedTools), {
|
|
268513
|
+
synthesizeMissing: true,
|
|
268514
|
+
dropOrphanResults: true,
|
|
268515
|
+
dedupeDuplicateToolCalls: true,
|
|
268516
|
+
dropLeadingNonUser: true,
|
|
268517
|
+
mergeConsecutiveAssistants: true
|
|
268518
|
+
});
|
|
268519
|
+
recordPreRequestPhase("message-build-strict", startedAt);
|
|
268520
|
+
return messages;
|
|
268521
|
+
},
|
|
267858
268522
|
dispatchEvent: this.buildDispatchEvent(turnId, signal, onFinalResponse, () => partialContext),
|
|
267859
268523
|
tools: selectedTools,
|
|
267860
268524
|
log: this.agent.log,
|
|
@@ -267871,8 +268535,10 @@ var TurnFlow = class {
|
|
|
267871
268535
|
},
|
|
267872
268536
|
hooks: {
|
|
267873
268537
|
beforeStep: async ({ signal: stepSignal, llm }) => {
|
|
268538
|
+
const injectionStartedAt = performance.now();
|
|
267874
268539
|
this.agent.microCompaction.detect();
|
|
267875
268540
|
await this.agent.injection.inject();
|
|
268541
|
+
recordPreRequestPhase("step-injection", injectionStartedAt);
|
|
267876
268542
|
stepSignal.throwIfAborted();
|
|
267877
268543
|
deduper.beginStep();
|
|
267878
268544
|
},
|
|
@@ -267910,6 +268576,17 @@ var TurnFlow = class {
|
|
|
267910
268576
|
signal.throwIfAborted();
|
|
267911
268577
|
if (stopBlock !== void 0) {
|
|
267912
268578
|
stopHookContinuationUsed = true;
|
|
268579
|
+
this.agent.log.warn("turn continuation blocked by Stop hook", {
|
|
268580
|
+
turnId,
|
|
268581
|
+
reason: stopBlock.reason
|
|
268582
|
+
});
|
|
268583
|
+
this.agent.emitEvent({
|
|
268584
|
+
type: "hook.result",
|
|
268585
|
+
turnId,
|
|
268586
|
+
hookEvent: "Stop",
|
|
268587
|
+
content: stopBlock.reason,
|
|
268588
|
+
blocked: true
|
|
268589
|
+
});
|
|
267913
268590
|
this.agent.context.appendUserMessage([{
|
|
267914
268591
|
type: "text",
|
|
267915
268592
|
text: stopBlock.reason
|
|
@@ -267949,6 +268626,7 @@ var TurnFlow = class {
|
|
|
267949
268626
|
});
|
|
267950
268627
|
return budgetToolResultForModel({
|
|
267951
268628
|
homedir: this.agent.homedir,
|
|
268629
|
+
maxContextTokens: this.agent.fullCompaction.getEffectiveMaxContextTokens(),
|
|
267952
268630
|
toolName: ctx.toolCall.name,
|
|
267953
268631
|
toolCallId: ctx.toolCall.id,
|
|
267954
268632
|
result: finalResult
|
|
@@ -268806,10 +269484,10 @@ var BashTool = class {
|
|
|
268806
269484
|
},
|
|
268807
269485
|
approvalRule: literalRulePattern(this.name, args.command),
|
|
268808
269486
|
matchesRule: (ruleArgs) => matchesGlobRuleSubject(ruleArgs, args.command),
|
|
268809
|
-
execute: ({ signal, onUpdate, onForegroundTaskStart }) => this.execution(args, signal, onUpdate, onForegroundTaskStart)
|
|
269487
|
+
execute: ({ signal, onUpdate, onForegroundTaskStart, executionOrigin }) => this.execution(args, signal, onUpdate, onForegroundTaskStart, executionOrigin)
|
|
268810
269488
|
};
|
|
268811
269489
|
}
|
|
268812
|
-
spawn(effectiveCwd, command) {
|
|
269490
|
+
spawn(effectiveCwd, command, executionOrigin) {
|
|
268813
269491
|
const shellCwd = this.isWindowsBash ? windowsPathToPosixPath(effectiveCwd) : effectiveCwd;
|
|
268814
269492
|
const shellArgs = [
|
|
268815
269493
|
this.kaos.osEnv.shellPath,
|
|
@@ -268826,9 +269504,11 @@ var BashTool = class {
|
|
|
268826
269504
|
...process.env,
|
|
268827
269505
|
...noninteractiveEnv
|
|
268828
269506
|
};
|
|
269507
|
+
delete mergedEnv["BLUN_SHELL"];
|
|
269508
|
+
if (executionOrigin === "operator_shell") mergedEnv["BLUN_SHELL"] = "operator-local";
|
|
268829
269509
|
return this.kaos.execWithEnv(shellArgs, mergedEnv);
|
|
268830
269510
|
}
|
|
268831
|
-
async execution(args, signal, onUpdate, onForegroundTaskStart) {
|
|
269511
|
+
async execution(args, signal, onUpdate, onForegroundTaskStart, executionOrigin) {
|
|
268832
269512
|
const validationError = this.validateRunRequest(args, signal);
|
|
268833
269513
|
if (validationError !== void 0) return validationError;
|
|
268834
269514
|
const startsInBackground = args.run_in_background === true;
|
|
@@ -268840,7 +269520,7 @@ var BashTool = class {
|
|
|
268840
269520
|
const builder = new ToolResultBuilder();
|
|
268841
269521
|
let proc;
|
|
268842
269522
|
try {
|
|
268843
|
-
proc = await this.spawn(effectiveCwd, command);
|
|
269523
|
+
proc = await this.spawn(effectiveCwd, command, executionOrigin);
|
|
268844
269524
|
} catch (error) {
|
|
268845
269525
|
return {
|
|
268846
269526
|
isError: true,
|
|
@@ -269204,14 +269884,14 @@ function classifySearchError(error) {
|
|
|
269204
269884
|
}
|
|
269205
269885
|
//#endregion
|
|
269206
269886
|
//#region ../../packages/agent-core/src/tools/builtin/search/codebase-search.md?raw
|
|
269207
|
-
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";
|
|
269208
269888
|
//#endregion
|
|
269209
269889
|
//#region ../../packages/agent-core/src/tools/builtin/search/codebase-search.ts
|
|
269210
269890
|
/**
|
|
269211
269891
|
* CodebaseSearchTool — semantic code search via the codebase-index.
|
|
269212
269892
|
*
|
|
269213
269893
|
* Shells out to `python codebase_index.py query <repo> "<frage>" --top N`
|
|
269214
|
-
* through
|
|
269894
|
+
* through asynchronous execFile. The script lives at
|
|
269215
269895
|
* `packages/codebase-index/codebase_index.py` relative to the workspace root.
|
|
269216
269896
|
*
|
|
269217
269897
|
* Unlike Grep (keyword/regex) or Glob (file-name patterns), this tool finds
|
|
@@ -269219,11 +269899,13 @@ var codebase_search_default = "Find code by **meaning**, not by keywords.\n\nThi
|
|
|
269219
269899
|
* to the query, so it can locate a keyboard handler even when the word
|
|
269220
269900
|
* "keyboard" never appears in the source.
|
|
269221
269901
|
*/
|
|
269902
|
+
const MAX_SEARCH_RESULTS = 100;
|
|
269222
269903
|
const CodebaseSearchInputSchema = object({
|
|
269223
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\"."),
|
|
269224
|
-
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.`)
|
|
269225
269906
|
});
|
|
269226
269907
|
const SCRIPT_TIMEOUT_MS = 6e4;
|
|
269908
|
+
const SCRIPT_MAX_BUFFER = 1024 * 1024;
|
|
269227
269909
|
function isScriptFile(path) {
|
|
269228
269910
|
try {
|
|
269229
269911
|
return statSync(path).isFile();
|
|
@@ -269262,45 +269944,72 @@ var CodebaseSearchTool = class {
|
|
|
269262
269944
|
},
|
|
269263
269945
|
approvalRule: literalRulePattern(this.name, args.query),
|
|
269264
269946
|
matchesRule: (ruleArgs) => matchesGlobRuleSubject(ruleArgs, args.query),
|
|
269265
|
-
execute: () =>
|
|
269947
|
+
execute: async (context) => {
|
|
269948
|
+
context.signal.throwIfAborted();
|
|
269949
|
+
return this.execution(args, context.signal);
|
|
269950
|
+
}
|
|
269266
269951
|
};
|
|
269267
269952
|
}
|
|
269268
|
-
execution(args) {
|
|
269953
|
+
async execution(args, signal) {
|
|
269269
269954
|
const builder = new ToolResultBuilder();
|
|
269270
|
-
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.");
|
|
269271
269957
|
try {
|
|
269272
|
-
const result =
|
|
269273
|
-
|
|
269274
|
-
|
|
269275
|
-
|
|
269276
|
-
|
|
269277
|
-
|
|
269278
|
-
|
|
269279
|
-
|
|
269280
|
-
|
|
269281
|
-
|
|
269282
|
-
|
|
269283
|
-
|
|
269284
|
-
|
|
269285
|
-
|
|
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
|
+
});
|
|
269286
269992
|
});
|
|
269287
|
-
|
|
269993
|
+
signal.throwIfAborted();
|
|
269994
|
+
if (result.error !== null && typeof result.error.code !== "number") {
|
|
269288
269995
|
const msg = result.error instanceof Error ? result.error.message : String(result.error);
|
|
269289
|
-
|
|
269996
|
+
builder.write(result.stdout + result.stderr);
|
|
269997
|
+
return builder.error(`Failed to run codebase_index.py: ${msg}`);
|
|
269290
269998
|
}
|
|
269291
269999
|
const stdout = result.stdout ?? "";
|
|
269292
270000
|
const stderr = result.stderr ?? "";
|
|
269293
|
-
const exitCode = result.
|
|
270001
|
+
const exitCode = result.error?.code ?? 0;
|
|
269294
270002
|
if (exitCode !== 0) {
|
|
269295
270003
|
const combined = stderr.trim().length > 0 ? `${stdout}${stdout.length > 0 ? "\n" : ""}Error: ${stderr.trim()}` : stdout;
|
|
269296
270004
|
builder.write(combined.length > 0 ? combined : `codebase_index.py exited with code ${String(exitCode)}`);
|
|
269297
|
-
return
|
|
270005
|
+
return builder.error(`Codebase search failed with exit code ${String(exitCode)}.`);
|
|
269298
270006
|
}
|
|
269299
270007
|
builder.write(stdout.length > 0 ? stdout : "No results found.");
|
|
269300
|
-
return
|
|
270008
|
+
return builder.ok();
|
|
269301
270009
|
} catch (error) {
|
|
270010
|
+
signal.throwIfAborted();
|
|
269302
270011
|
const msg = error instanceof Error ? error.message : String(error);
|
|
269303
|
-
return
|
|
270012
|
+
return builder.error(`Codebase search error: ${msg}`);
|
|
269304
270013
|
}
|
|
269305
270014
|
}
|
|
269306
270015
|
};
|
|
@@ -270540,6 +271249,7 @@ var ToolManager = class {
|
|
|
270540
271249
|
const result = await execution.execute({
|
|
270541
271250
|
turnId: "",
|
|
270542
271251
|
toolCallId: "shell-command",
|
|
271252
|
+
executionOrigin: "operator_shell",
|
|
270543
271253
|
signal: controller.signal,
|
|
270544
271254
|
onUpdate: (update) => {
|
|
270545
271255
|
if (update.kind === "stdout") stdout += update.text ?? "";
|
|
@@ -270628,6 +271338,9 @@ var ToolManager = class {
|
|
|
270628
271338
|
hasUserTool(name) {
|
|
270629
271339
|
return this.userTools.has(name);
|
|
270630
271340
|
}
|
|
271341
|
+
isUserTool(tool) {
|
|
271342
|
+
return this.userTools.get(tool.name) === tool;
|
|
271343
|
+
}
|
|
270631
271344
|
inheritUserTools(parent) {
|
|
270632
271345
|
for (const tool of parent.userTools.values()) {
|
|
270633
271346
|
if (!parent.enabledTools.has(tool.name)) continue;
|
|
@@ -271412,6 +272125,7 @@ var FallbackLLM = class {
|
|
|
271412
272125
|
throw new Error("Fallback request preparation requires a fresh request boundary.");
|
|
271413
272126
|
}
|
|
271414
272127
|
let requestParams = params;
|
|
272128
|
+
let messagesReady = false;
|
|
271415
272129
|
const rebuildRequestMessages = async () => {
|
|
271416
272130
|
const messages = await rebuildMessages();
|
|
271417
272131
|
const suffix = requestParams.boundaryMessageSuffix;
|
|
@@ -271420,7 +272134,14 @@ var FallbackLLM = class {
|
|
|
271420
272134
|
while (true) {
|
|
271421
272135
|
const candidate = this.current;
|
|
271422
272136
|
try {
|
|
271423
|
-
|
|
272137
|
+
const prepared = await this.prepareRequest?.(candidate, requestParams, rebuildRequestMessages);
|
|
272138
|
+
if (prepared !== void 0) if ("messagesReady" in prepared) {
|
|
272139
|
+
requestParams = prepared.params;
|
|
272140
|
+
messagesReady = true;
|
|
272141
|
+
} else {
|
|
272142
|
+
requestParams = prepared;
|
|
272143
|
+
messagesReady = false;
|
|
272144
|
+
}
|
|
271424
272145
|
} catch (error) {
|
|
271425
272146
|
if (!isFallbackCandidateError(error) && !isUnavailableFallbackCandidate(error)) throw error;
|
|
271426
272147
|
const nextIndex = this.findNextCandidateIndex();
|
|
@@ -271430,13 +272151,14 @@ var FallbackLLM = class {
|
|
|
271430
272151
|
...requestParams,
|
|
271431
272152
|
messages: await rebuildRequestMessages()
|
|
271432
272153
|
};
|
|
272154
|
+
messagesReady = false;
|
|
271433
272155
|
requestParams.signal.throwIfAborted();
|
|
271434
272156
|
this.currentIndex = nextIndex;
|
|
271435
272157
|
this.onModelChanged(this.current.alias);
|
|
271436
272158
|
continue;
|
|
271437
272159
|
}
|
|
271438
272160
|
requestParams.signal.throwIfAborted();
|
|
271439
|
-
const messages = await rebuildRequestMessages();
|
|
272161
|
+
const messages = messagesReady ? requestParams.messages : await rebuildRequestMessages();
|
|
271440
272162
|
requestParams.signal.throwIfAborted();
|
|
271441
272163
|
return {
|
|
271442
272164
|
...requestParams,
|
|
@@ -271538,8 +272260,13 @@ var LlmRequestLogger = class {
|
|
|
271538
272260
|
toolsEstimatedTokens = 0;
|
|
271539
272261
|
requestSequence = 0;
|
|
271540
272262
|
lastTurnRequest;
|
|
271541
|
-
|
|
272263
|
+
serializedPrefixKey;
|
|
272264
|
+
requestSignatures = /* @__PURE__ */ new Map();
|
|
272265
|
+
prefixComparisons = /* @__PURE__ */ new Map();
|
|
272266
|
+
lastSerializedRequest;
|
|
272267
|
+
constructor(log, serializedPrefixDiagnostic = process.env["BLUN_DIAG_SERIALIZED_PREFIX"] === "1") {
|
|
271542
272268
|
this.log = log;
|
|
272269
|
+
this.serializedPrefixKey = serializedPrefixDiagnostic ? randomBytes(32) : void 0;
|
|
271543
272270
|
}
|
|
271544
272271
|
logRequest(input) {
|
|
271545
272272
|
const sequence = ++this.requestSequence;
|
|
@@ -271556,6 +272283,10 @@ var LlmRequestLogger = class {
|
|
|
271556
272283
|
toolsHash: fingerprint(JSON.stringify(toolSignature(tools)))
|
|
271557
272284
|
};
|
|
271558
272285
|
const signature = JSON.stringify(config);
|
|
272286
|
+
if (this.serializedPrefixKey !== void 0) {
|
|
272287
|
+
this.requestSignatures.set(sequence, signature);
|
|
272288
|
+
if (this.requestSignatures.size > 32) this.requestSignatures.delete(this.requestSignatures.keys().next().value);
|
|
272289
|
+
}
|
|
271559
272290
|
if (signature !== this.lastConfigLogSignature) {
|
|
271560
272291
|
this.lastConfigLogSignature = signature;
|
|
271561
272292
|
this.configRevision++;
|
|
@@ -271585,6 +272316,20 @@ var LlmRequestLogger = class {
|
|
|
271585
272316
|
}
|
|
271586
272317
|
};
|
|
271587
272318
|
if (partialMessageCount > 0) requestFields.partialMessageCount = partialMessageCount;
|
|
272319
|
+
const source = input.systemPromptContributions;
|
|
272320
|
+
if (source?.version === 1 && [
|
|
272321
|
+
source.totalBytes,
|
|
272322
|
+
source.instructionBytes,
|
|
272323
|
+
source.skillListingBytes,
|
|
272324
|
+
source.runtimeMemoryBytes,
|
|
272325
|
+
source.otherBytes
|
|
272326
|
+
].every((value) => Number.isSafeInteger(value) && value >= 0) && source.instructionBytes + source.skillListingBytes + source.runtimeMemoryBytes + source.otherBytes === source.totalBytes && source.totalBytes === Buffer.byteLength(systemPrompt, "utf8")) requestFields.systemPromptSourceBytes = {
|
|
272327
|
+
totalBytes: source.totalBytes,
|
|
272328
|
+
instructionBytes: source.instructionBytes,
|
|
272329
|
+
skillListingBytes: source.skillListingBytes,
|
|
272330
|
+
runtimeMemoryBytes: source.runtimeMemoryBytes,
|
|
272331
|
+
otherBytes: source.otherBytes
|
|
272332
|
+
};
|
|
271588
272333
|
this.log.info("llm request", requestFields);
|
|
271589
272334
|
if (fields?.turnStep !== void 0 && /^\d+\.\d+$/.test(fields.turnStep)) {
|
|
271590
272335
|
const historyTextOrigins = summarizeRequestTextOrigins(messages);
|
|
@@ -271610,10 +272355,51 @@ var LlmRequestLogger = class {
|
|
|
271610
272355
|
getLastTurnRequest() {
|
|
271611
272356
|
return this.lastTurnRequest === void 0 ? void 0 : structuredClone(this.lastTurnRequest);
|
|
271612
272357
|
}
|
|
272358
|
+
get serializedPrefixDiagnosticEnabled() {
|
|
272359
|
+
return this.serializedPrefixKey !== void 0;
|
|
272360
|
+
}
|
|
272361
|
+
observeSerializedRequest(body, fields, sequence) {
|
|
272362
|
+
const key = this.serializedPrefixKey;
|
|
272363
|
+
if (key === void 0 || !/^\d+\.\d+$/.test(fields?.turnStep ?? "")) return;
|
|
272364
|
+
const signature = this.requestSignatures.get(sequence);
|
|
272365
|
+
if (signature === void 0) return;
|
|
272366
|
+
try {
|
|
272367
|
+
const bytes = Buffer.from(body, "utf8");
|
|
272368
|
+
const granularityBytes = 1024;
|
|
272369
|
+
const chunks = [];
|
|
272370
|
+
for (let start = 0; start + granularityBytes <= bytes.length; start += granularityBytes) chunks.push(createHmac("sha256", key).update(bytes.subarray(start, start + granularityBytes)).digest("hex"));
|
|
272371
|
+
const previous = this.lastSerializedRequest;
|
|
272372
|
+
if (previous !== void 0 && previous.signature === signature) {
|
|
272373
|
+
let common = 0;
|
|
272374
|
+
while (common < previous.chunks.length && common < chunks.length && previous.chunks[common] === chunks[common]) common++;
|
|
272375
|
+
this.prefixComparisons.set(sequence, {
|
|
272376
|
+
version: 1,
|
|
272377
|
+
granularityBytes,
|
|
272378
|
+
previousBytes: previous.bytes,
|
|
272379
|
+
currentBytes: bytes.length,
|
|
272380
|
+
commonPrefixBytesLowerBound: common * granularityBytes,
|
|
272381
|
+
previousSequence: previous.sequence,
|
|
272382
|
+
currentSequence: sequence
|
|
272383
|
+
});
|
|
272384
|
+
if (this.prefixComparisons.size > 32) this.prefixComparisons.delete(this.prefixComparisons.keys().next().value);
|
|
272385
|
+
}
|
|
272386
|
+
this.lastSerializedRequest = {
|
|
272387
|
+
sequence,
|
|
272388
|
+
signature,
|
|
272389
|
+
bytes: bytes.length,
|
|
272390
|
+
chunks
|
|
272391
|
+
};
|
|
272392
|
+
} catch {
|
|
272393
|
+
this.lastSerializedRequest = void 0;
|
|
272394
|
+
}
|
|
272395
|
+
}
|
|
271613
272396
|
logTransportAttempt(stats, fields, sequence) {
|
|
272397
|
+
const serializedPrefix = sequence === void 0 ? void 0 : this.prefixComparisons.get(sequence);
|
|
271614
272398
|
this.log.info("llm transport attempt", {
|
|
271615
272399
|
...fields,
|
|
271616
|
-
...stats
|
|
272400
|
+
...stats,
|
|
272401
|
+
...this.serializedPrefixKey === void 0 || sequence === void 0 ? {} : { requestSequence: sequence },
|
|
272402
|
+
...serializedPrefix === void 0 ? {} : { serializedPrefix }
|
|
271617
272403
|
});
|
|
271618
272404
|
if (sequence === void 0 || this.lastTurnRequest?.sequence !== sequence) return;
|
|
271619
272405
|
const breakdown = stats.requestBreakdown;
|
|
@@ -271635,6 +272421,11 @@ var LlmRequestLogger = class {
|
|
|
271635
272421
|
systemMessageBytes: breakdown.systemMessageBytes,
|
|
271636
272422
|
conversationMessageBytes: breakdown.conversationMessageBytes,
|
|
271637
272423
|
toolResultMessageBytes: breakdown.toolResultMessageBytes,
|
|
272424
|
+
...breakdown.toolResultByTool === void 0 ? {} : { toolResultByTool: breakdown.toolResultByTool.map((tool) => ({
|
|
272425
|
+
count: tool.count,
|
|
272426
|
+
bytes: tool.bytes,
|
|
272427
|
+
...tool.name === void 0 ? {} : { name: tool.name }
|
|
272428
|
+
})) },
|
|
271638
272429
|
toolSchemaBytes: breakdown.toolSchemaBytes,
|
|
271639
272430
|
otherBytes: breakdown.otherBytes,
|
|
271640
272431
|
...breakdown.toolArrayOverheadBytes === void 0 ? {} : { toolArrayOverheadBytes: breakdown.toolArrayOverheadBytes },
|
|
@@ -271696,7 +272487,8 @@ function copyContributions(value) {
|
|
|
271696
272487
|
version: source.version,
|
|
271697
272488
|
totalBytes: source.totalBytes,
|
|
271698
272489
|
generatedBytes: source.generatedBytes,
|
|
271699
|
-
files: source.files.map((file) => copyInstructionFileBytes(file))
|
|
272490
|
+
files: source.files.map((file) => copyInstructionFileBytes(file)),
|
|
272491
|
+
...source.notLoadedCandidates === void 0 ? {} : { notLoadedCandidates: [...source.notLoadedCandidates] }
|
|
271700
272492
|
} }
|
|
271701
272493
|
};
|
|
271702
272494
|
}
|
|
@@ -271792,7 +272584,11 @@ var Agent$1 = class {
|
|
|
271792
272584
|
errorMemory;
|
|
271793
272585
|
replayBuilder;
|
|
271794
272586
|
additionalDirs;
|
|
272587
|
+
systemPromptStartedAt = /* @__PURE__ */ new Date();
|
|
271795
272588
|
activeProfile;
|
|
272589
|
+
rawSystemPromptContext;
|
|
272590
|
+
profileSystemPromptText;
|
|
272591
|
+
agentsMdRequestWarningShown = false;
|
|
271796
272592
|
brandHome;
|
|
271797
272593
|
_activeResponderModel;
|
|
271798
272594
|
allowModelFallback = true;
|
|
@@ -271879,6 +272675,7 @@ var Agent$1 = class {
|
|
|
271879
272675
|
const retryScope = providerRetryScope(modelAlias, provider);
|
|
271880
272676
|
await this.providerRetryWait.wait(retryScope, generateOptions?.signal);
|
|
271881
272677
|
const callerTransportAttempt = generateOptions?.onTransportAttempt;
|
|
272678
|
+
const callerSerializedRequest = generateOptions?.onSerializedRequest;
|
|
271882
272679
|
const ownedGenerateOptions = {
|
|
271883
272680
|
...generateOptions,
|
|
271884
272681
|
transportMaxRetries: 0
|
|
@@ -271901,6 +272698,12 @@ var Agent$1 = class {
|
|
|
271901
272698
|
callerTransportAttempt?.(stats);
|
|
271902
272699
|
this.llmRequestLogger.logTransportAttempt(stats, requestLogFields, requestSequence);
|
|
271903
272700
|
},
|
|
272701
|
+
...callerSerializedRequest !== void 0 || this.llmRequestLogger.serializedPrefixDiagnosticEnabled ? { onSerializedRequest: (body) => {
|
|
272702
|
+
try {
|
|
272703
|
+
callerSerializedRequest?.(body);
|
|
272704
|
+
} catch {}
|
|
272705
|
+
this.llmRequestLogger.observeSerializedRequest(body, requestLogFields, requestSequence);
|
|
272706
|
+
} } : {},
|
|
271904
272707
|
onRequestStart: () => {
|
|
271905
272708
|
requestOptions?.onRequestStart?.();
|
|
271906
272709
|
requestStarted = true;
|
|
@@ -271926,7 +272729,7 @@ var Agent$1 = class {
|
|
|
271926
272729
|
get llm() {
|
|
271927
272730
|
return this.llmForTurn();
|
|
271928
272731
|
}
|
|
271929
|
-
llmForTurn(thinkingEffort) {
|
|
272732
|
+
llmForTurn(thinkingEffort, diagnosticTurnId) {
|
|
271930
272733
|
const selectedAlias = this.config.model;
|
|
271931
272734
|
const modelProvider = this.modelProvider;
|
|
271932
272735
|
if (modelProvider === void 0) throw new BlunError(ErrorCodes.MODEL_NOT_CONFIGURED, "Provider not set");
|
|
@@ -271940,7 +272743,9 @@ var Agent$1 = class {
|
|
|
271940
272743
|
tools: requestTools,
|
|
271941
272744
|
messages: await rebuildMessages()
|
|
271942
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));
|
|
271943
272747
|
let systemPrompt = this.effectiveSystemPrompt;
|
|
272748
|
+
const preflightStartedAt = performance.now();
|
|
271944
272749
|
const compacted = await this.fullCompaction.beforeStep(params.signal, {
|
|
271945
272750
|
messages: params.messages,
|
|
271946
272751
|
additionalMessages: steers.messages,
|
|
@@ -271949,17 +272754,38 @@ var Agent$1 = class {
|
|
|
271949
272754
|
rebuildSystemPrompt: () => systemPrompt = this.effectiveSystemPrompt,
|
|
271950
272755
|
tools: params.tools
|
|
271951
272756
|
});
|
|
272757
|
+
if (this.type === "main" && diagnosticTurnId !== void 0 && process.env["BLUN_DIAG_PRE_REQUEST_PHASES"] === "1") try {
|
|
272758
|
+
this.log.info("turn pre-request phase", {
|
|
272759
|
+
turnId: diagnosticTurnId,
|
|
272760
|
+
phase: "compaction-preflight",
|
|
272761
|
+
durationMs: Math.max(0, Math.round(performance.now() - preflightStartedAt))
|
|
272762
|
+
});
|
|
272763
|
+
} catch {}
|
|
271952
272764
|
const tools = params.tools.some((tool) => tool.name === "CompactConversation") && !this.fullCompaction.proactiveCompactionStatus({
|
|
271953
272765
|
messages: compacted ? await rebuildMessages() : params.messages,
|
|
271954
272766
|
additionalMessages: steers.messages,
|
|
271955
272767
|
systemPrompt,
|
|
271956
272768
|
tools: params.tools
|
|
271957
272769
|
}).eligible ? params.tools.filter((tool) => tool.name !== "CompactConversation") : params.tools;
|
|
271958
|
-
this.turn.commitPendingSteers(steers);
|
|
271959
|
-
|
|
272770
|
+
const steersCommitted = this.turn.commitPendingSteers(steers);
|
|
272771
|
+
if (compacted || steersCommitted) params = {
|
|
271960
272772
|
...params,
|
|
271961
|
-
|
|
271962
|
-
|
|
272773
|
+
messages: await rebuildMessages()
|
|
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
|
+
}
|
|
272782
|
+
return {
|
|
272783
|
+
params: {
|
|
272784
|
+
...params,
|
|
272785
|
+
systemPrompt,
|
|
272786
|
+
tools
|
|
272787
|
+
},
|
|
272788
|
+
messagesReady: true
|
|
271963
272789
|
};
|
|
271964
272790
|
}, (candidate, _params, error) => {
|
|
271965
272791
|
this.fullCompaction.observeContextOverflow(error, candidate.alias);
|
|
@@ -272031,8 +272857,14 @@ var Agent$1 = class {
|
|
|
272031
272857
|
}
|
|
272032
272858
|
useProfile(profile, context, brandHome) {
|
|
272033
272859
|
this.setActiveProfile(profile, brandHome);
|
|
272034
|
-
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
|
+
}
|
|
272035
272866
|
this.tools.setActiveTools(profile.tools);
|
|
272867
|
+
this.updateSystemPromptFromProfile(profile, this.fitProfileInstructions(profile, context));
|
|
272036
272868
|
}
|
|
272037
272869
|
setActiveProfile(profile, brandHome) {
|
|
272038
272870
|
this.activeProfile = profile;
|
|
@@ -272047,12 +272879,74 @@ var Agent$1 = class {
|
|
|
272047
272879
|
async refreshSystemPrompt() {
|
|
272048
272880
|
if (this.activeProfile === void 0) return;
|
|
272049
272881
|
const context = this.systemPromptContextProvider === void 0 ? await prepareSystemPromptContext(this.kaos, this.brandHome, { additionalDirs: this.additionalDirs }) : await this.systemPromptContextProvider();
|
|
272050
|
-
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;
|
|
272051
272944
|
}
|
|
272052
272945
|
updateSystemPromptFromProfile(profile, context) {
|
|
272053
272946
|
let contributions;
|
|
272054
272947
|
const systemPrompt = profile.systemPrompt({
|
|
272055
272948
|
osEnv: this.kaos.osEnv,
|
|
272949
|
+
now: this.systemPromptStartedAt,
|
|
272056
272950
|
cwd: this.config.cwd,
|
|
272057
272951
|
skills: this.skills?.registry,
|
|
272058
272952
|
cwdListing: context?.cwdListing,
|
|
@@ -272067,6 +272961,7 @@ var Agent$1 = class {
|
|
|
272067
272961
|
profileName: profile.name,
|
|
272068
272962
|
systemPrompt
|
|
272069
272963
|
});
|
|
272964
|
+
this.profileSystemPromptText = systemPrompt;
|
|
272070
272965
|
this.renderedPromptContributions = contributions === void 0 ? void 0 : {
|
|
272071
272966
|
text: systemPrompt,
|
|
272072
272967
|
value: structuredClone(contributions)
|
|
@@ -272243,6 +273138,9 @@ var Agent$1 = class {
|
|
|
272243
273138
|
},
|
|
272244
273139
|
startBtw: () => this.subagentHost.startBtw(),
|
|
272245
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(),
|
|
272246
273144
|
getGoal: () => this.goal.getGoal(),
|
|
272247
273145
|
pauseGoal: () => this.goal.pauseGoal(),
|
|
272248
273146
|
resumeGoal: () => this.goal.resumeGoal(),
|
|
@@ -336497,6 +337395,15 @@ var SessionAPIImpl = class {
|
|
|
336497
337395
|
async createGoal({ agentId, ...payload }) {
|
|
336498
337396
|
return (await this.getAgent(agentId)).createGoal(payload);
|
|
336499
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
|
+
}
|
|
336500
337407
|
async getGoal({ agentId, ...payload }) {
|
|
336501
337408
|
return (await this.getAgent(agentId, true)).getGoal(payload);
|
|
336502
337409
|
}
|
|
@@ -337741,6 +338648,15 @@ var BlunCore = class {
|
|
|
337741
338648
|
getGoal({ sessionId, ...payload }) {
|
|
337742
338649
|
return Promise.resolve(this.sessionApi(sessionId).getGoal(payload));
|
|
337743
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
|
+
}
|
|
337744
338660
|
pauseGoal({ sessionId, ...payload }) {
|
|
337745
338661
|
return Promise.resolve(this.sessionApi(sessionId).pauseGoal(payload));
|
|
337746
338662
|
}
|
|
@@ -344942,7 +345858,10 @@ function reduceWireRecords(records) {
|
|
|
344942
345858
|
text: record.summary
|
|
344943
345859
|
}],
|
|
344944
345860
|
toolCalls: [],
|
|
344945
|
-
origin: {
|
|
345861
|
+
origin: {
|
|
345862
|
+
kind: "compaction_summary",
|
|
345863
|
+
...record.toolContinuity === void 0 ? {} : { toolContinuity: record.toolContinuity }
|
|
345864
|
+
}
|
|
344946
345865
|
},
|
|
344947
345866
|
time: record.time
|
|
344948
345867
|
};
|
|
@@ -347193,6 +348112,24 @@ var Session = class {
|
|
|
347193
348112
|
this.ensureOpen();
|
|
347194
348113
|
return this.rpc.getGoal({ sessionId: this.id });
|
|
347195
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
|
+
}
|
|
347196
348133
|
async pauseGoal() {
|
|
347197
348134
|
this.ensureOpen();
|
|
347198
348135
|
return this.rpc.pauseGoal({ sessionId: this.id });
|
|
@@ -347752,6 +348689,39 @@ var BlunAuthFacade = class {
|
|
|
347752
348689
|
}
|
|
347753
348690
|
return this.toolkit.status(providerName, this.resolveRuntimeManagedAuth(providerName).oauthRef);
|
|
347754
348691
|
}
|
|
348692
|
+
async getCachedMemoryWorkspaceId() {
|
|
348693
|
+
const apiKey = nonEmpty(this.resolveManagedAuth(BLUN_PROVIDER_NAME$1).apiKey);
|
|
348694
|
+
if (apiKey !== void 0) {
|
|
348695
|
+
const provider = readConfigFileForUpdate(this.options.configPath).providers[BLUN_PROVIDER_NAME$1];
|
|
348696
|
+
if (provider?.apiKey !== apiKey || provider.memoryApiKeyHash !== memoryApiKeyHash(apiKey)) return;
|
|
348697
|
+
return provider.memoryWorkspaceId;
|
|
348698
|
+
}
|
|
348699
|
+
return this.toolkit.getCachedMemoryWorkspaceId(this.resolveRuntimeManagedAuth(BLUN_PROVIDER_NAME$1).oauthRef);
|
|
348700
|
+
}
|
|
348701
|
+
async cacheMemoryWorkspaceId(workspaceId) {
|
|
348702
|
+
const apiKey = nonEmpty(this.resolveManagedAuth(BLUN_PROVIDER_NAME$1).apiKey);
|
|
348703
|
+
if (apiKey !== void 0) {
|
|
348704
|
+
const hash = memoryApiKeyHash(apiKey);
|
|
348705
|
+
return mutateConfigFile(this.options.configPath, (config) => {
|
|
348706
|
+
const provider = config.providers[BLUN_PROVIDER_NAME$1];
|
|
348707
|
+
if (provider?.apiKey !== apiKey) return {
|
|
348708
|
+
config,
|
|
348709
|
+
result: false
|
|
348710
|
+
};
|
|
348711
|
+
if (provider.memoryApiKeyHash === hash && provider.memoryWorkspaceId !== void 0 && provider.memoryWorkspaceId !== workspaceId) return {
|
|
348712
|
+
config,
|
|
348713
|
+
result: false
|
|
348714
|
+
};
|
|
348715
|
+
provider.memoryApiKeyHash = hash;
|
|
348716
|
+
provider.memoryWorkspaceId = workspaceId;
|
|
348717
|
+
return {
|
|
348718
|
+
config,
|
|
348719
|
+
result: true
|
|
348720
|
+
};
|
|
348721
|
+
});
|
|
348722
|
+
}
|
|
348723
|
+
return this.toolkit.cacheMemoryWorkspaceId(workspaceId, this.resolveRuntimeManagedAuth(BLUN_PROVIDER_NAME$1).oauthRef);
|
|
348724
|
+
}
|
|
347755
348725
|
async login(providerName = BLUN_PROVIDER_NAME$1, options = {}) {
|
|
347756
348726
|
const auth = this.resolveManagedAuth(providerName);
|
|
347757
348727
|
const loginAuth = resolveBlunCodeLoginAuth({
|
|
@@ -348057,6 +349027,9 @@ function nonEmpty(value) {
|
|
|
348057
349027
|
const normalized = value?.trim();
|
|
348058
349028
|
return normalized === void 0 || normalized.length === 0 ? void 0 : normalized;
|
|
348059
349029
|
}
|
|
349030
|
+
function memoryApiKeyHash(apiKey) {
|
|
349031
|
+
return createHash("sha256").update(apiKey).digest("hex");
|
|
349032
|
+
}
|
|
348060
349033
|
function transitionAggregateError(message, primary, secondary) {
|
|
348061
349034
|
return new AggregateError([primary, secondary], message, { cause: primary });
|
|
348062
349035
|
}
|
|
@@ -348537,6 +349510,26 @@ var SDKRpcClientBase = class {
|
|
|
348537
349510
|
replace: input.replace
|
|
348538
349511
|
});
|
|
348539
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
|
+
}
|
|
348540
349533
|
async getGoal(input) {
|
|
348541
349534
|
return (await this.getRpc()).getGoal({
|
|
348542
349535
|
sessionId: input.sessionId,
|