blun-king-cli 9.1.536 → 9.1.561

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.
Files changed (129) hide show
  1. package/LIESMICH.txt +13 -869
  2. package/README.md +41 -833
  3. package/bin/assistant-message-offload-policy.cjs +3 -1
  4. package/bin/compaction-transaction-policy.cjs +122 -0
  5. package/bin/context-performance-policy.cjs +2 -5
  6. package/bin/context-pressure-policy.cjs +20 -0
  7. package/bin/cron-run-output.cjs +45 -0
  8. package/bin/cron-run-store.cjs +145 -0
  9. package/bin/default-model-output-budget-policy.cjs +28 -0
  10. package/bin/durable-task-resume-policy.cjs +130 -0
  11. package/bin/durable-task-resume-runtime.cjs +117 -0
  12. package/bin/durable-task-resume-store.cjs +88 -0
  13. package/bin/editable-tool-approval-policy.cjs +540 -0
  14. package/bin/editable-tool-approval-runtime.cjs +99 -0
  15. package/bin/file-observation-policy.cjs +133 -0
  16. package/bin/html-to-research-markdown.cjs +146 -0
  17. package/bin/launcher-runtime.js +0 -1
  18. package/bin/micro-compaction-policy.cjs +64 -0
  19. package/bin/mnemo-connect-heartbeat.cjs +1 -3
  20. package/bin/programmatic-tool-runtime.mjs +330 -4
  21. package/bin/read-continuation-policy.cjs +36 -5
  22. package/bin/retry-checkpoint-policy.cjs +13 -0
  23. package/bin/scoped-cron-run-policy.cjs +358 -0
  24. package/bin/session-checkpoint-policy.cjs +25 -0
  25. package/bin/startup-preferences.cjs +4 -3
  26. package/bin/structured-agent-swarm-output.cjs +325 -0
  27. package/bin/subagent-context-fork-policy.cjs +155 -0
  28. package/bin/subagent-skill-policy.cjs +204 -0
  29. package/bin/telegram-approval-relay.cjs +2 -1
  30. package/bin/tool-file-persistence.cjs +141 -0
  31. package/bin/tool-result-offload-policy.cjs +25 -33
  32. package/bin/turn-thinking-policy.cjs +2 -26
  33. package/bin/update-notice.js +30 -18
  34. package/bin/user-message-offload-policy.cjs +3 -1
  35. package/blun.mjs +1564 -640
  36. package/codebase-index/README.md +12 -0
  37. package/codebase-index/codebase_index.py +129 -18
  38. package/package.json +23 -58
  39. package/telegram-plugin/bin/telegram-mnemo-capture.cjs +1 -3
  40. package/telegram-plugin/bin/telegram-typing-keepalive.cjs +89 -0
  41. package/telegram-plugin/dist/bridge.mjs +8 -1
  42. package/CHANGELOG.md +0 -321
  43. package/agent-spine-plugin/CHANGELOG.md +0 -406
  44. package/agent-spine-plugin/CONTRIBUTING.md +0 -52
  45. package/agent-spine-plugin/README.md +0 -344
  46. package/agent-spine-plugin/SECURITY.md +0 -47
  47. package/agent-spine-plugin/docs/acceptance.md +0 -61
  48. package/agent-spine-plugin/docs/architecture.md +0 -183
  49. package/agent-spine-plugin/docs/attention.md +0 -121
  50. package/agent-spine-plugin/docs/automatic-continuity.md +0 -79
  51. package/agent-spine-plugin/docs/channel-runtime.md +0 -92
  52. package/agent-spine-plugin/docs/coordination.md +0 -138
  53. package/agent-spine-plugin/docs/feed-transport.md +0 -99
  54. package/agent-spine-plugin/docs/gateway-runtime.md +0 -116
  55. package/agent-spine-plugin/docs/harness-reference.md +0 -45
  56. package/agent-spine-plugin/docs/host-integration.md +0 -129
  57. package/agent-spine-plugin/docs/https-transport.md +0 -116
  58. package/agent-spine-plugin/docs/learning.md +0 -133
  59. package/agent-spine-plugin/docs/object-transport.md +0 -93
  60. package/agent-spine-plugin/docs/peer-transport.md +0 -88
  61. package/agent-spine-plugin/docs/preflight-recall.md +0 -69
  62. package/agent-spine-plugin/docs/preservation-contract.md +0 -53
  63. package/agent-spine-plugin/docs/quality-gates.md +0 -50
  64. package/agent-spine-plugin/docs/relationships.md +0 -73
  65. package/agent-spine-plugin/docs/releasing.md +0 -83
  66. package/agent-spine-plugin/docs/roadmap.md +0 -307
  67. package/agent-spine-plugin/docs/selfstarter.md +0 -88
  68. package/agent-spine-plugin/docs/session-briefing.md +0 -74
  69. package/agent-spine-plugin/docs/shared-memory.md +0 -259
  70. package/agent-spine-plugin/docs/source-roots.md +0 -86
  71. package/agent-spine-plugin/docs/sqlite-transport.md +0 -76
  72. package/agent-spine-plugin/scripts/check-hosts.js +0 -195
  73. package/agent-spine-plugin/scripts/check-install.js +0 -569
  74. package/agent-spine-plugin/scripts/check-syntax.js +0 -29
  75. package/agent-spine-plugin/scripts/github-actions.js +0 -11
  76. package/agent-spine-plugin/scripts/release-check.js +0 -128
  77. package/agent-spine-plugin/scripts/run-acceptance.js +0 -19
  78. package/agent-spine-plugin/scripts/run-checks.js +0 -46
  79. package/agent-spine-plugin/scripts/run-tests-hermetic.js +0 -73
  80. package/agent-spine-plugin/spine-example/1-identity.md +0 -12
  81. package/agent-spine-plugin/spine-example/2-voice.md +0 -6
  82. package/agent-spine-plugin/spine-example/3-conduct.md +0 -8
  83. package/agent-spine-plugin/spine-example/4-history.md +0 -4
  84. package/bin/empty-response-retry-policy.cjs +0 -29
  85. package/bin/fredrik-glm-provider.cjs +0 -256
  86. package/bin/package-regression-policy.cjs +0 -77
  87. package/fredrik-glm-profile.toml.example +0 -26
  88. package/release-planned-removals.json +0 -15
  89. package/scripts/check-active-profile-plugin-startup.js +0 -36
  90. package/scripts/check-active-work-steer-regression.js +0 -46
  91. package/scripts/check-approval-observability-regression.js +0 -111
  92. package/scripts/check-approval-queue-shortcuts-regression.js +0 -65
  93. package/scripts/check-bundled-agent-spine-regression.js +0 -48
  94. package/scripts/check-codebase-search-packaging-regression.js +0 -92
  95. package/scripts/check-copy-command-regression.js +0 -74
  96. package/scripts/check-current-turn-read-pin-mutation-regression.js +0 -72
  97. package/scripts/check-current-turn-read-pin-regression.js +0 -94
  98. package/scripts/check-deepseek-native-max-regression.js +0 -49
  99. package/scripts/check-empty-response-effort-downgrade-regression.js +0 -48
  100. package/scripts/check-fredrik-glm-mutation-regression.js +0 -18
  101. package/scripts/check-fredrik-glm-regression.js +0 -169
  102. package/scripts/check-historical-tool-result-preview-regression.js +0 -77
  103. package/scripts/check-history-pressure-offload-regression.js +0 -77
  104. package/scripts/check-mcp-startup-wait-budget.js +0 -48
  105. package/scripts/check-package-regression.js +0 -38
  106. package/scripts/check-plugin-startup-regression.js +0 -53
  107. package/scripts/check-programmatic-context-isolation-regression.js +0 -193
  108. package/scripts/check-programmatic-tool-regression.js +0 -294
  109. package/scripts/check-queue-controls-regression.js +0 -189
  110. package/scripts/check-release-metadata.js +0 -103
  111. package/scripts/check-reload-agent-spine-regression.js +0 -76
  112. package/scripts/check-resume-replay-regression.js +0 -102
  113. package/scripts/check-session-cancel-regression.js +0 -43
  114. package/scripts/check-session-picker-resume-metrics-regression.js +0 -97
  115. package/scripts/check-session-start-hook-context-regression.js +0 -228
  116. package/scripts/check-shell-terminal-isolation-regression.js +0 -81
  117. package/scripts/check-slash-escape-regression.js +0 -89
  118. package/scripts/check-startup-swarm-command-regression.js +0 -24
  119. package/scripts/check-structured-subagent-output-regression.js +0 -331
  120. package/scripts/check-telegram-bridge-watchdog.js +0 -60
  121. package/scripts/check-telegram-direct-work-resume-regression.js +0 -53
  122. package/scripts/check-telegram-loop-exactly-once-regression.js +0 -71
  123. package/scripts/check-todo-loop-regression.js +0 -78
  124. package/scripts/check-todo-progress-regression.js +0 -416
  125. package/scripts/check-todo-recovery-catalog-regression.js +0 -50
  126. package/scripts/check-tool-schema-capacity-regression.js +0 -40
  127. package/scripts/programmatic-tool-runtime.test.mjs +0 -365
  128. package/scripts/structured-subagent-output.test.cjs +0 -170
  129. /package/{scripts → bin}/fix-node-pty-perms.js +0 -0
@@ -0,0 +1,141 @@
1
+ 'use strict';
2
+
3
+ const { randomBytes } = require('node:crypto');
4
+ const fs = require('node:fs/promises');
5
+ const path = require('node:path');
6
+
7
+ const WINDOWS_RENAME_RETRY_CODES = new Set(['EACCES', 'EBUSY', 'EPERM']);
8
+ const DEFAULT_WINDOWS_RENAME_DELAYS_MS = Object.freeze([10, 25, 50, 100]);
9
+
10
+ function isAbortError(error) {
11
+ return error instanceof Error && error.name === 'AbortError';
12
+ }
13
+
14
+ function throwIfAborted(signal) {
15
+ if (!signal?.aborted) return;
16
+ const error = new Error('Atomic tool write aborted before publication.');
17
+ error.name = 'AbortError';
18
+ throw error;
19
+ }
20
+
21
+ function isMissing(error) {
22
+ return error?.code === 'ENOENT' || error?.code === 'ENOTDIR';
23
+ }
24
+
25
+ async function existingFileMode(filePath, statFile) {
26
+ try {
27
+ const info = await statFile(filePath);
28
+ if (!info.isFile()) throw Object.assign(new Error(`Cannot replace non-file target: ${filePath}`), { code: 'EISDIR' });
29
+ return typeof info.mode === 'number' ? info.mode & 0o777 : undefined;
30
+ } catch (error) {
31
+ if (isMissing(error)) return undefined;
32
+ throw error;
33
+ }
34
+ }
35
+
36
+ async function resolvePublicationPath(filePath, operations) {
37
+ try {
38
+ return await operations.realpathFile(filePath);
39
+ } catch (error) {
40
+ if (!isMissing(error)) throw error;
41
+ }
42
+
43
+ try {
44
+ const linkInfo = await operations.lstatFile(filePath);
45
+ if (linkInfo.isSymbolicLink()) {
46
+ throw Object.assign(new Error(`Refused atomic replacement through dangling symbolic link: ${filePath}`), { code: 'ELOOP' });
47
+ }
48
+ } catch (error) {
49
+ if (!isMissing(error)) throw error;
50
+ }
51
+
52
+ const realParent = await operations.realpathFile(path.dirname(filePath));
53
+ return path.join(realParent, path.basename(filePath));
54
+ }
55
+
56
+ async function renameWithWindowsRetry(source, target, options) {
57
+ const delays = options.platform === 'win32'
58
+ ? options.windowsRenameDelaysMs
59
+ : [];
60
+ let attempt = 0;
61
+ while (true) {
62
+ try {
63
+ await options.renameFile(source, target);
64
+ return;
65
+ } catch (error) {
66
+ const delayMs = delays[attempt];
67
+ if (delayMs === undefined || !WINDOWS_RENAME_RETRY_CODES.has(error?.code)) throw error;
68
+ attempt += 1;
69
+ throwIfAborted(options.signal);
70
+ await options.sleep(delayMs);
71
+ }
72
+ }
73
+ }
74
+
75
+ async function writeToolTextAtomic(filePath, content, options = {}) {
76
+ if (typeof filePath !== 'string' || filePath.length === 0) throw new TypeError('filePath must be a non-empty string');
77
+ if (typeof content !== 'string' && !Buffer.isBuffer(content)) throw new TypeError('content must be a string or Buffer');
78
+
79
+ const openFile = options.openFile || fs.open;
80
+ const renameFile = options.renameFile || fs.rename;
81
+ const unlinkFile = options.unlinkFile || fs.unlink;
82
+ const statFile = options.statFile || fs.stat;
83
+ const lstatFile = options.lstatFile || fs.lstat;
84
+ const realpathFile = options.realpathFile || fs.realpath;
85
+ const syncHandle = options.syncHandle || ((handle) => handle.sync());
86
+ const sleep = options.sleep || ((delayMs) => new Promise((resolve) => setTimeout(resolve, delayMs)));
87
+ const signal = options.signal;
88
+ const platform = options.platform || process.platform;
89
+ const windowsRenameDelaysMs = options.windowsRenameDelaysMs || DEFAULT_WINDOWS_RENAME_DELAYS_MS;
90
+
91
+ throwIfAborted(signal);
92
+ const publicationPath = await resolvePublicationPath(filePath, { lstatFile, realpathFile });
93
+ const mode = await existingFileMode(publicationPath, statFile);
94
+ const suffix = `${process.pid}.${randomBytes(6).toString('hex')}`;
95
+ const temporaryPath = path.join(path.dirname(publicationPath), `.${path.basename(publicationPath)}.${suffix}.tmp`);
96
+ let handle;
97
+ let published = false;
98
+
99
+ try {
100
+ handle = await openFile(temporaryPath, 'wx', mode ?? 0o666);
101
+ await handle.writeFile(content, typeof content === 'string' ? { encoding: 'utf8', signal } : { signal });
102
+ await syncHandle(handle);
103
+ if (mode !== undefined && platform !== 'win32') await handle.chmod(mode);
104
+ await handle.close();
105
+ handle = undefined;
106
+
107
+ throwIfAborted(signal);
108
+ await renameWithWindowsRetry(temporaryPath, publicationPath, {
109
+ platform,
110
+ renameFile,
111
+ signal,
112
+ sleep,
113
+ windowsRenameDelaysMs,
114
+ });
115
+ published = true;
116
+ return { bytesWritten: Buffer.byteLength(content) };
117
+ } finally {
118
+ if (handle !== undefined) {
119
+ try {
120
+ await handle.close();
121
+ } catch {}
122
+ }
123
+ if (!published) {
124
+ try {
125
+ await unlinkFile(temporaryPath);
126
+ } catch (error) {
127
+ if (!isMissing(error)) {
128
+ // The primary write error remains authoritative; stale temp names are unique and never read.
129
+ }
130
+ }
131
+ }
132
+ }
133
+ }
134
+
135
+ module.exports = {
136
+ DEFAULT_WINDOWS_RENAME_DELAYS_MS,
137
+ WINDOWS_RENAME_RETRY_CODES,
138
+ renameWithWindowsRetry,
139
+ resolvePublicationPath,
140
+ writeToolTextAtomic,
141
+ };
@@ -1,5 +1,10 @@
1
1
  'use strict';
2
2
 
3
+ const {
4
+ DEFAULT_CONTEXT_PRESSURE_RATIO,
5
+ hasContextPressure,
6
+ } = require('./context-pressure-policy.cjs');
7
+
3
8
  const TOOL_RESULT_MAX_CHARS = 12_000;
4
9
  const TOOL_RESULT_PREVIEW_CHARS = 2_000;
5
10
  const TOOL_RESULT_HISTORICAL_PREVIEW_CHARS = 400;
@@ -16,10 +21,17 @@ const TOOL_RESULT_HISTORICAL_REPLACEMENT_BUDGET_CHARS = 1_000;
16
21
  const TOOL_RESULT_SUCCESS_KEEP_RECENT_MESSAGES = 12;
17
22
  const TOOL_RESULT_HISTORICAL_SUCCESS_MARKER = '[Old tool result content cleared]';
18
23
  const TOOL_RESULT_REPEAT_MARKER = '[Repeated tool result omitted]';
24
+ const TOOL_RESULT_OFFLOAD_PRESSURE_RATIO = DEFAULT_CONTEXT_PRESSURE_RATIO;
19
25
  const READ_CONTINUATION_LINE_OFFSET_RE = /^Continue reading with line_offset=(\d+)\. Do not assume you have reached the end of the file\.$/mu;
20
26
 
21
- function shouldOffloadToolResult(textLength) {
22
- return Number.isFinite(textLength) && textLength > TOOL_RESULT_MAX_CHARS;
27
+ function hasToolResultOffloadPressure(options = {}) {
28
+ return hasContextPressure(options);
29
+ }
30
+
31
+ function shouldOffloadToolResult(textLength, options = {}) {
32
+ return Number.isFinite(textLength)
33
+ && textLength > TOOL_RESULT_MAX_CHARS
34
+ && hasToolResultOffloadPressure(options);
23
35
  }
24
36
 
25
37
  function shouldKeepFreshToolResult(toolName) {
@@ -154,33 +166,9 @@ function compactPersistedToolResultReference(content) {
154
166
  return changed ? compacted : content;
155
167
  }
156
168
 
157
- function compactHistoricalSuccessfulToolResults(messages) {
158
- if (!Array.isArray(messages) || messages.length === 0) return messages;
159
-
160
- const recentStart = Math.max(0, messages.length - TOOL_RESULT_SUCCESS_KEEP_RECENT_MESSAGES);
161
- const freshIds = freshToolResultIds(messages);
162
- let changed = false;
163
- const projected = messages.map((message, index) => {
164
- if (
165
- index >= recentStart
166
- || message?.role !== 'tool'
167
- || freshIds.has(message.toolCallId)
168
- || message.isError === true
169
- || !Array.isArray(message.content)
170
- || isPersistedToolResultReference(message.content)
171
- || !message.content.every((part) => part?.type === 'text' && typeof part.text === 'string')
172
- ) return message;
173
-
174
- const textChars = message.content.reduce((total, part) => total + part.text.length, 0);
175
- if (textChars <= TOOL_RESULT_HISTORICAL_SUCCESS_MARKER.length) return message;
176
- changed = true;
177
- return {
178
- ...message,
179
- content: [{ type: 'text', text: TOOL_RESULT_HISTORICAL_SUCCESS_MARKER }],
180
- };
181
- });
182
-
183
- return changed ? projected : messages;
169
+ function compactHistoricalSuccessfulToolResults(messages, options = {}) {
170
+ void options;
171
+ return messages;
184
172
  }
185
173
 
186
174
  function toolCallSignaturesById(messages) {
@@ -269,10 +257,12 @@ function dedupeRepeatedSuccessfulToolResults(sourceMessages, projectedMessages =
269
257
  ...projectedMessage,
270
258
  content: [{ type: 'text', text: reference }],
271
259
  };
272
- projected[newest.index] = {
273
- ...projected[newest.index],
274
- content: sourceMessages[newest.index].content,
275
- };
260
+ if (projected[newest.index] !== sourceMessages[newest.index]) {
261
+ projected[newest.index] = {
262
+ ...projected[newest.index],
263
+ content: sourceMessages[newest.index].content,
264
+ };
265
+ }
276
266
  changed = true;
277
267
  }
278
268
 
@@ -326,6 +316,7 @@ function selectHistoricalToolResultOffloads(textLengths) {
326
316
  }
327
317
 
328
318
  module.exports = {
319
+ TOOL_RESULT_OFFLOAD_PRESSURE_RATIO,
329
320
  TOOL_RESULT_BATCH_MAX_CHARS,
330
321
  TOOL_RESULT_BATCH_MIN_ITEM_CHARS,
331
322
  TOOL_RESULT_BATCH_REPLACEMENT_BUDGET_CHARS,
@@ -349,6 +340,7 @@ module.exports = {
349
340
  currentUserTurnStartIndex,
350
341
  dedupeRepeatedSuccessfulToolResults,
351
342
  freshToolResultIds,
343
+ hasToolResultOffloadPressure,
352
344
  isPersistedToolResultReference,
353
345
  readContinuationLineOffset,
354
346
  selectHistoricalToolResultOffloads,
@@ -7,9 +7,6 @@ const BOSNIAN_STANDALONE_CHAT = /^(?:zdravo|pozdrav|hvala|ćao|cao)[.!?]*$/iu;
7
7
  const IDENTITY_CHAT = /^(?:wer bist du|who are you|wie geht(?: es dir)?|how are you|na|kako si|kako je king|ko si ti|ko stoji iza tebe)[.!?]*$/iu;
8
8
  const STATUS_ONLY_CHECK_IN = /(?:\bstandabfrage\b|\bstatusabfrage\b|\bkurzes?\s+update\b|\bwo\s+stehst\s+du\b|\bwie\s+weit\s+bist\s+du\b|\bwhere\s+are\s+you\b|\bquick\s+status\b)/iu;
9
9
  const STATUS_FOLLOW_UP_ACTION = /\b(?:aendere|arbeite|baue|build|change|delete|deploy|deploye|fahr|fix|fixe|implement|implementiere|install|installiere|loesche|mach|patch|pruefe|repariere|run|schreibe|setze|start|starte|stop|stoppe|test|teste|write)\b/iu;
10
- const STANDALONE_CHAT_COMPLETION_TOKENS = 1024;
11
- const ADAPTIVE_LOW_COMPLETION_TOKENS = 4096;
12
- const STANDARD_TURN_MAX_COMPLETION_TOKENS = 24_576;
13
10
 
14
11
  function selectThinkingEffortForTurn(text, originKind) {
15
12
  if (originKind !== "user") return undefined;
@@ -45,25 +42,8 @@ function selectThinkingEffortForWorkStep(_stepNumber, _previousToolOutcome) {
45
42
  }
46
43
 
47
44
  function capCompletionBudgetForAdaptiveEffort(budget, thinkingEffort) {
48
- if ((thinkingEffort !== "off" && thinkingEffort !== "low") || budget === undefined) return budget;
49
- const configuredCap = budget.hardCap ?? budget.fallback;
50
- const adaptiveCap = thinkingEffort === "off"
51
- ? STANDALONE_CHAT_COMPLETION_TOKENS
52
- : ADAPTIVE_LOW_COMPLETION_TOKENS;
53
- return {
54
- ...budget,
55
- hardCap: Math.min(
56
- configuredCap ?? adaptiveCap,
57
- adaptiveCap,
58
- ),
59
- };
60
- }
61
-
62
- function capTurnCompletionTokens(maxOutputSize) {
63
- if (!Number.isFinite(maxOutputSize) || maxOutputSize <= 0) {
64
- return STANDARD_TURN_MAX_COMPLETION_TOKENS;
65
- }
66
- return Math.min(Math.floor(maxOutputSize), STANDARD_TURN_MAX_COMPLETION_TOKENS);
45
+ void thinkingEffort;
46
+ return budget;
67
47
  }
68
48
 
69
49
  function selectThinkingEffortForBufferedSteer(text, originKind) {
@@ -77,12 +57,8 @@ function selectThinkingEffortForBufferedSteer(text, originKind) {
77
57
 
78
58
  module.exports = {
79
59
  ACTIONABLE_PROMPT,
80
- ADAPTIVE_LOW_COMPLETION_TOKENS,
81
60
  EXPLICIT_THINKING_INTENT,
82
- STANDALONE_CHAT_COMPLETION_TOKENS,
83
- STANDARD_TURN_MAX_COMPLETION_TOKENS,
84
61
  capCompletionBudgetForAdaptiveEffort,
85
- capTurnCompletionTokens,
86
62
  selectThinkingEffortForBufferedSteer,
87
63
  selectThinkingEffortForWorkStep,
88
64
  selectThinkingEffortForTurn,
@@ -82,6 +82,15 @@ const ENDPOINT_LIMITS = new Map([
82
82
  [FALLBACK_MANIFEST_URL, 64 * 1024],
83
83
  ]);
84
84
 
85
+ function isInternalPackagePinned(packageRoot) {
86
+ try {
87
+ const manifest = JSON.parse(fs.readFileSync(path.join(packageRoot, 'package.json'), 'utf8'));
88
+ return manifest?.blunUpdateChannel === 'internal';
89
+ } catch {
90
+ return false;
91
+ }
92
+ }
93
+
85
94
  function parseSemver(value) {
86
95
  if (typeof value !== 'string' || value.length > 128) return undefined;
87
96
  const match = SEMVER_PATTERN.exec(value);
@@ -1393,6 +1402,12 @@ async function runUpdateFlow(options, explicitUpdate) {
1393
1402
  const now = (options.now || Date.now)();
1394
1403
 
1395
1404
  const packageRoot = path.resolve(options.packageRoot || path.resolve(__dirname, '..'));
1405
+ if (isInternalPackagePinned(packageRoot)) {
1406
+ if (explicitUpdate) explicitNoTarget(stdout, 'current', currentVersion, uiLocale);
1407
+ return explicitUpdate
1408
+ ? { kind: 'current', reason: 'internal_channel' }
1409
+ : { kind: 'continue', reason: 'internal_channel' };
1410
+ }
1396
1411
  let leaseResult;
1397
1412
  const ownsNoticeLease = options.noticeLease === undefined;
1398
1413
  if (ownsNoticeLease) {
@@ -1484,20 +1499,6 @@ async function runUpdateFlow(options, explicitUpdate) {
1484
1499
  ? explicitFailure(stderr, 'lease_unavailable', undefined, uiLocale)
1485
1500
  : { kind: 'continue', reason: 'lease_unavailable' };
1486
1501
  }
1487
- if (!options.installVersion) {
1488
- installerSession = await (options.prepareInstaller || preparePinnedInstaller)(
1489
- release.version,
1490
- { blunDir, packageRoot },
1491
- );
1492
- if (!installerSession?.ready) {
1493
- if (explicitUpdate) {
1494
- return explicitFailure(stderr, 'installer_unavailable', undefined, uiLocale);
1495
- }
1496
- return installerSession?.reason === 'failed'
1497
- ? { kind: 'continue', reason: 'installer_unavailable' }
1498
- : { kind: 'update_in_progress' };
1499
- }
1500
- }
1501
1502
  let action;
1502
1503
  if (explicitUpdate || options.autoInstall === true) {
1503
1504
  action = 'install';
@@ -1515,10 +1516,6 @@ async function runUpdateFlow(options, explicitUpdate) {
1515
1516
  }
1516
1517
  }
1517
1518
  if (action !== 'install') {
1518
- if (installerSession?.ready) {
1519
- await installerSession.cancel();
1520
- installerSession = undefined;
1521
- }
1522
1519
  if (action === 'skip-once') {
1523
1520
  return { kind: 'continue', reason: 'skipped_once' };
1524
1521
  }
@@ -1537,6 +1534,20 @@ async function runUpdateFlow(options, explicitUpdate) {
1537
1534
  }
1538
1535
  return { kind: 'continue', reason: 'postponed' };
1539
1536
  }
1537
+ if (!options.installVersion) {
1538
+ installerSession = await (options.prepareInstaller || preparePinnedInstaller)(
1539
+ release.version,
1540
+ { blunDir, packageRoot },
1541
+ );
1542
+ if (!installerSession?.ready) {
1543
+ if (explicitUpdate) {
1544
+ return explicitFailure(stderr, 'installer_unavailable', undefined, uiLocale);
1545
+ }
1546
+ return installerSession?.reason === 'failed'
1547
+ ? { kind: 'continue', reason: 'installer_unavailable' }
1548
+ : { kind: 'update_in_progress' };
1549
+ }
1550
+ }
1540
1551
 
1541
1552
  const updateProgress = createUpdateProgress(stdout);
1542
1553
  updateProgress(1, copy.updateChecked);
@@ -1636,6 +1647,7 @@ module.exports = {
1636
1647
  compareSemver,
1637
1648
  createInstallInvocation,
1638
1649
  installPinnedVersion,
1650
+ isInternalPackagePinned,
1639
1651
  preparePinnedInstaller,
1640
1652
  isInteractiveUpdateStart,
1641
1653
  loadReleaseSources,
@@ -4,6 +4,7 @@ const {
4
4
  hasHistoricalOffloadPressure,
5
5
  historyTextChars,
6
6
  } = require('./history-offload-pressure-policy.cjs');
7
+ const { hasContextPressure } = require('./context-pressure-policy.cjs');
7
8
 
8
9
  const USER_MESSAGE_MAX_CHARS = 200_000;
9
10
  const HISTORICAL_USER_MESSAGE_MAX_CHARS = 4_000;
@@ -30,7 +31,8 @@ function shouldOffloadHistoricalUserMessage(options = {}) {
30
31
  || historyIndex >= historyLength
31
32
  ) return false;
32
33
  const cutoff = Math.max(0, historyLength - USER_MESSAGE_KEEP_RECENT_MESSAGES);
33
- return hasHistoricalOffloadPressure({ historyLength, historyChars })
34
+ return hasContextPressure(options)
35
+ && hasHistoricalOffloadPressure({ historyLength, historyChars })
34
36
  && historyIndex < cutoff
35
37
  && textChars > HISTORICAL_USER_MESSAGE_MAX_CHARS;
36
38
  }