blun-king-cli 9.1.480 → 9.1.481

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
  };
@@ -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,
@@ -517648,6 +517661,7 @@ var BlunTUI = class {
517648
517661
  const items = this.state.queuedMessages.slice(0, batchEnd < 0 ? this.state.queuedMessages.length : batchEnd);
517649
517662
  if (items.length === 0) return false;
517650
517663
  this.state.queuedMessages = this.state.queuedMessages.slice(items.length);
517664
+ this.updateQueueDisplay();
517651
517665
  const transcriptRendered = items.map((queued) => queued.channelTranscriptRendered === true);
517652
517666
  const renderTranscripts = () => {
517653
517667
  items.forEach((queued, index) => {
@@ -517915,6 +517929,7 @@ var BlunTUI = class {
517915
517929
  }
517916
517930
  const items = this.state.queuedMessages.slice(0, prefixLength);
517917
517931
  this.state.queuedMessages = this.state.queuedMessages.slice(prefixLength);
517932
+ this.updateQueueDisplay();
517918
517933
  const turnId = this.streamingUI.getTurnContext().turnId;
517919
517934
  const inFlight = {
517920
517935
  items,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blun-king-cli",
3
- "version": "9.1.480",
3
+ "version": "9.1.481",
4
4
  "description": "BLUN CLI - your own AI agent with a Telegram channel. Get it done. With BLUN.",
5
5
  "license": "MIT",
6
6
  "bin": {