blun-king-cli 9.1.480 → 9.1.482
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.
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
function quotedPattern(pattern) {
|
|
4
|
+
return `'${pattern.replaceAll("\\", "\\\\").replaceAll("'", "\\'")}'`;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function globPatternError(pattern) {
|
|
8
|
+
if (typeof pattern !== "string") return "Invalid glob pattern";
|
|
9
|
+
if (!pattern.replaceAll("\\", "/").split("/").includes("..")) return undefined;
|
|
10
|
+
return `Path traversal not allowed in glob pattern ${quotedPattern(pattern)}`;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
module.exports = { globPatternError };
|
|
@@ -23,6 +23,19 @@ function shouldRequestSubagentHandoff(stopReason, attempts) {
|
|
|
23
23
|
&& attempts < MAX_SUBAGENT_HANDOFF_ATTEMPTS;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
function isSubagentMaxTokensTurnError(error) {
|
|
27
|
+
if (typeof error !== "object" || error === null) return false;
|
|
28
|
+
const details = typeof error.details === "object" && error.details !== null
|
|
29
|
+
? error.details
|
|
30
|
+
: {};
|
|
31
|
+
if (details.emptyResponseKind === "length") return true;
|
|
32
|
+
if (details.finishReason === "truncated" || details.rawFinishReason === "length") return true;
|
|
33
|
+
|
|
34
|
+
const message = typeof error.message === "string" ? error.message : "";
|
|
35
|
+
return /\bmax[_ -]?tokens?\b/iu.test(message)
|
|
36
|
+
&& /(?:\bno\b|\bwithout\b|did not produce)[^\n.]*\btool(?: call)?\b/iu.test(message);
|
|
37
|
+
}
|
|
38
|
+
|
|
26
39
|
function boundedPartialHandoff(partialSummary) {
|
|
27
40
|
const normalized = typeof partialSummary === "string" ? partialSummary.trim() : "";
|
|
28
41
|
if (normalized.length <= MAX_PARTIAL_HANDOFF_CHARS) return normalized;
|
|
@@ -51,5 +64,6 @@ module.exports = {
|
|
|
51
64
|
SUBAGENT_MAX_TOKENS_ERROR,
|
|
52
65
|
SUBAGENT_MAX_TOKENS_HANDOFF_PROMPT,
|
|
53
66
|
buildSubagentMaxTokensFailure,
|
|
67
|
+
isSubagentMaxTokensTurnError,
|
|
54
68
|
shouldRequestSubagentHandoff,
|
|
55
69
|
};
|
|
@@ -14,6 +14,7 @@ const TOOL_RESULT_HISTORICAL_REPLACEMENT_BUDGET_CHARS = 600;
|
|
|
14
14
|
const TOOL_RESULT_SUCCESS_KEEP_RECENT_MESSAGES = 12;
|
|
15
15
|
const TOOL_RESULT_HISTORICAL_SUCCESS_MARKER = '[Old tool result content cleared]';
|
|
16
16
|
const TOOL_RESULT_REPEAT_MARKER = '[Repeated tool result omitted]';
|
|
17
|
+
const READ_CONTINUATION_LINE_OFFSET_RE = /^Continue reading with line_offset=(\d+)\. Do not assume you have reached the end of the file\.$/mu;
|
|
17
18
|
|
|
18
19
|
function shouldOffloadToolResult(textLength) {
|
|
19
20
|
return Number.isFinite(textLength) && textLength > TOOL_RESULT_MAX_CHARS;
|
|
@@ -32,6 +33,12 @@ function createToolResultPreview(text) {
|
|
|
32
33
|
return `${text.slice(0, headChars)}\n\n[... ${String(omittedChars)} characters omitted ...]\n\n${text.slice(-tailChars)}`;
|
|
33
34
|
}
|
|
34
35
|
|
|
36
|
+
function readContinuationLineOffset(text) {
|
|
37
|
+
if (typeof text !== 'string') return undefined;
|
|
38
|
+
const value = Number(text.match(READ_CONTINUATION_LINE_OFFSET_RE)?.[1]);
|
|
39
|
+
return Number.isSafeInteger(value) && value >= 1 ? value : undefined;
|
|
40
|
+
}
|
|
41
|
+
|
|
35
42
|
function isPersistedToolResultReference(content) {
|
|
36
43
|
if (!Array.isArray(content)) return false;
|
|
37
44
|
|
|
@@ -89,10 +96,14 @@ function compactPersistedToolResultReference(content) {
|
|
|
89
96
|
const outputPath = lines.find((line) => line.startsWith('output_path: '));
|
|
90
97
|
if (outputPath === undefined) return part;
|
|
91
98
|
const recoveryLines = [TOOL_RESULT_OFFLOAD_MARKER];
|
|
92
|
-
for (const prefix of ['tool_name: ', 'output_size_chars: ']) {
|
|
99
|
+
for (const prefix of ['tool_name: ', 'output_size_chars: ', 'next_line_offset: ']) {
|
|
93
100
|
const line = lines.find((candidate) => candidate.startsWith(prefix));
|
|
94
101
|
if (line !== undefined) recoveryLines.push(line);
|
|
95
102
|
}
|
|
103
|
+
if (recoveryLines.some((line) => line.startsWith('next_line_offset: '))) {
|
|
104
|
+
const nextStep = lines.find((line) => line.startsWith('next_step: '));
|
|
105
|
+
if (nextStep !== undefined) recoveryLines.push(nextStep);
|
|
106
|
+
}
|
|
96
107
|
recoveryLines.push(outputPath);
|
|
97
108
|
const text = recoveryLines.join('\n');
|
|
98
109
|
if (text === part.text) return part;
|
|
@@ -298,6 +309,7 @@ module.exports = {
|
|
|
298
309
|
dedupeRepeatedSuccessfulToolResults,
|
|
299
310
|
freshToolResultIds,
|
|
300
311
|
isPersistedToolResultReference,
|
|
312
|
+
readContinuationLineOffset,
|
|
301
313
|
selectHistoricalToolResultOffloads,
|
|
302
314
|
selectToolResultBatchOffloads,
|
|
303
315
|
shouldKeepFreshToolResult,
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
function quotedPath(path) {
|
|
4
|
+
return `'${path.replaceAll("\\", "\\\\").replaceAll("'", "\\'")}'`;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function unsupportedUserHomePathError(path) {
|
|
8
|
+
if (typeof path !== "string" || !path.startsWith("~")) return undefined;
|
|
9
|
+
if (path === "~" || path.startsWith("~/") || path.startsWith("~\\")) return undefined;
|
|
10
|
+
return `Named home-directory paths are not supported: ${quotedPath(path)}. Use '~/' for the current user or './' for a literal path.`;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
module.exports = { unsupportedUserHomePathError };
|
package/blun.mjs
CHANGED
|
@@ -14,6 +14,8 @@ import agentResumeSnapshot from "./bin/agent-resume-snapshot.cjs";
|
|
|
14
14
|
import sessionResumeCheckpoint from "./bin/session-resume-checkpoint.cjs";
|
|
15
15
|
import sessionScrollbackArchive from "./bin/session-scrollback-archive.cjs";
|
|
16
16
|
import sessionReplayWindowPolicy from "./bin/session-replay-window-policy.cjs";
|
|
17
|
+
import globPatternPolicy from "./bin/glob-pattern-policy.cjs";
|
|
18
|
+
import userHomePathPolicy from "./bin/user-home-path-policy.cjs";
|
|
17
19
|
import crypto$1, { createHash, randomBytes, randomInt, randomUUID, timingSafeEqual } from "node:crypto";
|
|
18
20
|
import * as fs$16 from "node:fs";
|
|
19
21
|
import Kt, { accessSync, appendFileSync, chmodSync, closeSync, constants, copyFileSync, createReadStream, createWriteStream, existsSync, fsyncSync, linkSync, lstatSync, mkdirSync, openSync, promises, readFileSync, readSync, readdirSync, realpathSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync, writeSync } from "node:fs";
|
|
@@ -52,6 +54,8 @@ const { createAgentResumeSnapshot, restoreAgentResumeSnapshot } = agentResumeSna
|
|
|
52
54
|
const { loadResumeCheckpoint, writeResumeCheckpoint } = sessionResumeCheckpoint;
|
|
53
55
|
const { SessionScrollbackArchive, sessionScrollbackArchiveDirectory } = sessionScrollbackArchive;
|
|
54
56
|
const { replayWindowStartIndex } = sessionReplayWindowPolicy;
|
|
57
|
+
const { globPatternError } = globPatternPolicy;
|
|
58
|
+
const { unsupportedUserHomePathError } = userHomePathPolicy;
|
|
55
59
|
import { EventEmitter as EventEmitter$1 } from "node:events";
|
|
56
60
|
import { StringDecoder } from "node:string_decoder";
|
|
57
61
|
import co from "node:assert";
|
|
@@ -77727,6 +77731,8 @@ function relativeOutsideMessage(path, operation) {
|
|
|
77727
77731
|
return `"${path}" is not an absolute path. You must provide an absolute path to ${operation === "write" ? "write or edit a file" : operation === "search" ? "search" : "read a file"} outside the working directory.`;
|
|
77728
77732
|
}
|
|
77729
77733
|
function resolvePathAccess(path, cwd, config, options) {
|
|
77734
|
+
const homePathError = unsupportedUserHomePathError(path);
|
|
77735
|
+
if (homePathError !== void 0) throw new PathSecurityError("PATH_INVALID", path, path, homePathError);
|
|
77730
77736
|
const pathClass = options.pathClass ?? DEFAULT_PATH_CLASS;
|
|
77731
77737
|
const expandedPath = expandUserPath$1(normalizeUserPath(path, pathClass), options.homeDir, pathClass);
|
|
77732
77738
|
const rawIsAbsolute = isAbsolute$2(expandedPath);
|
|
@@ -252363,6 +252369,7 @@ async function runChildTurnToCompletion(child, signal) {
|
|
|
252363
252369
|
const turnEnded = completion.event;
|
|
252364
252370
|
if (turnEnded.reason !== "completed") {
|
|
252365
252371
|
if (turnEnded.reason === "filtered") throw new Error("Subagent turn blocked by provider safety policy");
|
|
252372
|
+
if (isSubagentMaxTokensTurnError(turnEnded.error)) return "max_tokens";
|
|
252366
252373
|
if (turnEnded.error?.code === ErrorCodes.PROVIDER_RATE_LIMIT) throw providerRateLimitErrorFromPayload(turnEnded.error);
|
|
252367
252374
|
if (turnEnded.error === void 0) throw new Error(`Subagent turn ${turnEnded.reason}`);
|
|
252368
252375
|
const error = new Error(`[${turnEnded.error.code}] ${turnEnded.error.message}`);
|
|
@@ -252406,7 +252413,7 @@ function shouldSuppressQueuedAttemptFailureEvent(options, error) {
|
|
|
252406
252413
|
if (isProviderRateLimitError(error)) return true;
|
|
252407
252414
|
return isAbortError$4(error) || options.signal.aborted;
|
|
252408
252415
|
}
|
|
252409
|
-
var DEFAULT_SUBAGENT_TIMEOUT_MS, resolveSubagentTimeoutMs, runAgentWithTimeoutContinuation, buildSubagentUsageDelta, inheritSubagentAllowedTools, inheritSubagentLifecycleTools, SUBAGENT_MAX_TOKENS_ERROR, SUBAGENT_MAX_TOKENS_HANDOFF_PROMPT, buildSubagentMaxTokensFailure, shouldRequestSubagentHandoff, SUMMARY_MIN_LENGTH, SUMMARY_CONTINUATION_ATTEMPTS, HOOK_TEXT_PREVIEW_LENGTH, TOOL_CALL_DISABLED_MESSAGE, SUBAGENT_PROMPT_ORIGIN, SIDE_QUESTION_SYSTEM_REMINDER, SessionSubagentHost;
|
|
252416
|
+
var DEFAULT_SUBAGENT_TIMEOUT_MS, resolveSubagentTimeoutMs, runAgentWithTimeoutContinuation, buildSubagentUsageDelta, inheritSubagentAllowedTools, inheritSubagentLifecycleTools, SUBAGENT_MAX_TOKENS_ERROR, SUBAGENT_MAX_TOKENS_HANDOFF_PROMPT, buildSubagentMaxTokensFailure, isSubagentMaxTokensTurnError, shouldRequestSubagentHandoff, SUMMARY_MIN_LENGTH, SUMMARY_CONTINUATION_ATTEMPTS, HOOK_TEXT_PREVIEW_LENGTH, TOOL_CALL_DISABLED_MESSAGE, SUBAGENT_PROMPT_ORIGIN, SIDE_QUESTION_SYSTEM_REMINDER, SessionSubagentHost;
|
|
252410
252417
|
var init_subagent_host = __esmMin((() => {
|
|
252411
252418
|
init_src$4();
|
|
252412
252419
|
init_errors$8();
|
|
@@ -252425,6 +252432,7 @@ var init_subagent_host = __esmMin((() => {
|
|
|
252425
252432
|
SUBAGENT_MAX_TOKENS_ERROR,
|
|
252426
252433
|
SUBAGENT_MAX_TOKENS_HANDOFF_PROMPT,
|
|
252427
252434
|
buildSubagentMaxTokensFailure,
|
|
252435
|
+
isSubagentMaxTokensTurnError,
|
|
252428
252436
|
shouldRequestSubagentHandoff
|
|
252429
252437
|
} = createRequire(import.meta.url)("./bin/subagent-max-tokens-handoff-policy.cjs"));
|
|
252430
252438
|
SUMMARY_MIN_LENGTH = 200;
|
|
@@ -258611,6 +258619,11 @@ glob_default = "Find files by glob pattern, sorted by modification time with the
|
|
|
258611
258619
|
}
|
|
258612
258620
|
async execution(args, signal, searchRoots) {
|
|
258613
258621
|
const searchRoot = searchRoots[0] ?? this.workspace.workspaceDir;
|
|
258622
|
+
const patternError = globPatternError(args.pattern);
|
|
258623
|
+
if (patternError !== void 0) return {
|
|
258624
|
+
isError: true,
|
|
258625
|
+
output: patternError
|
|
258626
|
+
};
|
|
258614
258627
|
try {
|
|
258615
258628
|
if (((await this.kaos.stat(searchRoot)).stMode & S_IFMT$2) !== S_IFDIR$1) return {
|
|
258616
258629
|
isError: true,
|
|
@@ -261019,6 +261032,7 @@ async function persistHistoricalToolResultForModel(options, knownText) {
|
|
|
261019
261032
|
};
|
|
261020
261033
|
}
|
|
261021
261034
|
function renderHistoricalToolResultReference(toolName, toolCallId, text, outputPath, storageMode) {
|
|
261035
|
+
const nextLineOffset = toolName === "Read" ? readContinuationLineOffset(text) : void 0;
|
|
261022
261036
|
return [
|
|
261023
261037
|
TOOL_RESULT_OFFLOAD_MARKER,
|
|
261024
261038
|
"An older tool result was archived to keep the active context fast.",
|
|
@@ -261027,14 +261041,15 @@ function renderHistoricalToolResultReference(toolName, toolCallId, text, outputP
|
|
|
261027
261041
|
`tool_call_id: ${toolCallId}`,
|
|
261028
261042
|
`output_size_chars: ${String(text.length)}`,
|
|
261029
261043
|
`output_size_bytes: ${String(Buffer.byteLength(text, "utf8"))}`,
|
|
261044
|
+
...(nextLineOffset === void 0 ? [] : [`next_line_offset: ${String(nextLineOffset)}`]),
|
|
261030
261045
|
`output_path: ${outputPath}`,
|
|
261031
|
-
`next_step: Use Read with output_path using n_lines <= ${String(TOOL_RESULT_RECOVERY_PAGE_LINES)}; advance line_offset between calls.`
|
|
261046
|
+
nextLineOffset === void 0 ? `next_step: Use Read with output_path using n_lines <= ${String(TOOL_RESULT_RECOVERY_PAGE_LINES)}; advance line_offset between calls.` : `next_step: Continue the original Read with line_offset=${String(nextLineOffset)}; do not restart at the beginning.`
|
|
261032
261047
|
].join("\n");
|
|
261033
261048
|
}
|
|
261034
261049
|
function safeToolResultFileStem(toolName, toolCallId) {
|
|
261035
261050
|
return `${toolName}-${toolCallId}`.replace(/[^a-zA-Z0-9._-]+/g, "_").replace(/^_+|_+$/g, "").slice(0, 80) || "tool-result";
|
|
261036
261051
|
}
|
|
261037
|
-
var TOOL_RESULT_MAX_CHARS, TOOL_RESULT_PREVIEW_CHARS, TOOL_RESULT_RECOVERY_PAGE_LINES, TOOL_RESULT_OFFLOAD_MARKER, TOOL_RESULT_HISTORICAL_KEEP_RECENT_MESSAGES, shouldKeepFreshToolResult, shouldOffloadToolResult, createToolResultPreview, compactPersistedToolResultReference, compactHistoricalSuccessfulToolResults, dedupeRepeatedSuccessfulToolResults, selectToolResultBatchOffloads, selectHistoricalToolResultOffloads, buildToolResultOffloadTelemetry;
|
|
261052
|
+
var TOOL_RESULT_MAX_CHARS, TOOL_RESULT_PREVIEW_CHARS, TOOL_RESULT_RECOVERY_PAGE_LINES, TOOL_RESULT_OFFLOAD_MARKER, TOOL_RESULT_HISTORICAL_KEEP_RECENT_MESSAGES, shouldKeepFreshToolResult, shouldOffloadToolResult, createToolResultPreview, compactPersistedToolResultReference, compactHistoricalSuccessfulToolResults, dedupeRepeatedSuccessfulToolResults, readContinuationLineOffset, selectToolResultBatchOffloads, selectHistoricalToolResultOffloads, buildToolResultOffloadTelemetry;
|
|
261038
261053
|
var init_tool_result_budget = __esmMin((() => {
|
|
261039
261054
|
init_dist$6();
|
|
261040
261055
|
const toolResultOffloadPolicy = createRequire(import.meta.url)("./bin/tool-result-offload-policy.cjs");
|
|
@@ -261051,6 +261066,7 @@ var init_tool_result_budget = __esmMin((() => {
|
|
|
261051
261066
|
compactHistoricalSuccessfulToolResults = toolResultOffloadPolicy.compactHistoricalSuccessfulToolResults;
|
|
261052
261067
|
dedupeRepeatedSuccessfulToolResults = toolResultOffloadPolicy.dedupeRepeatedSuccessfulToolResults;
|
|
261053
261068
|
freshToolResultIds = toolResultOffloadPolicy.freshToolResultIds;
|
|
261069
|
+
readContinuationLineOffset = toolResultOffloadPolicy.readContinuationLineOffset;
|
|
261054
261070
|
selectToolResultBatchOffloads = toolResultOffloadPolicy.selectToolResultBatchOffloads;
|
|
261055
261071
|
selectHistoricalToolResultOffloads = toolResultOffloadPolicy.selectHistoricalToolResultOffloads;
|
|
261056
261072
|
}));
|
|
@@ -517648,6 +517664,7 @@ var BlunTUI = class {
|
|
|
517648
517664
|
const items = this.state.queuedMessages.slice(0, batchEnd < 0 ? this.state.queuedMessages.length : batchEnd);
|
|
517649
517665
|
if (items.length === 0) return false;
|
|
517650
517666
|
this.state.queuedMessages = this.state.queuedMessages.slice(items.length);
|
|
517667
|
+
this.updateQueueDisplay();
|
|
517651
517668
|
const transcriptRendered = items.map((queued) => queued.channelTranscriptRendered === true);
|
|
517652
517669
|
const renderTranscripts = () => {
|
|
517653
517670
|
items.forEach((queued, index) => {
|
|
@@ -517915,6 +517932,7 @@ var BlunTUI = class {
|
|
|
517915
517932
|
}
|
|
517916
517933
|
const items = this.state.queuedMessages.slice(0, prefixLength);
|
|
517917
517934
|
this.state.queuedMessages = this.state.queuedMessages.slice(prefixLength);
|
|
517935
|
+
this.updateQueueDisplay();
|
|
517918
517936
|
const turnId = this.streamingUI.getTurnContext().turnId;
|
|
517919
517937
|
const inFlight = {
|
|
517920
517938
|
items,
|