blun-king-cli 9.1.607 → 9.1.609
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/LIESMICH.txt +1 -1
- package/README.md +1 -1
- package/blun.mjs +67 -10
- package/package.json +1 -1
- package/worker-host.mjs +47 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# BLUN King Changelog
|
|
2
2
|
|
|
3
|
+
## 9.1.609
|
|
4
|
+
|
|
5
|
+
- Open the existing effort picker with Ctrl+L while preserving the editor draft. Reuse the existing effort settings and model restrictions rather than adding a second configuration path.
|
|
6
|
+
- Preserve the existing busy-session rule: an effort change during active work is rejected, not queued for later. Ignore the shortcut during replay or editor takeover.
|
|
7
|
+
- These changes do not establish faster live model responses, lower billed token usage, or complete OpenClaw parity.
|
|
8
|
+
|
|
9
|
+
## 9.1.608
|
|
10
|
+
|
|
11
|
+
- Apply Telegram mention admission before unaddressed group messages enter the session context; preserve the explicit opt-out.
|
|
12
|
+
- Preserve custom multiple-choice selections and sequential question cancellation. Keep the goal footer on one shared refresh timer.
|
|
13
|
+
- Reduce Windows ACL transfer overhead without weakening permission validation. Bound recovery from temporary configuration replacement failures while retaining writer ownership.
|
|
14
|
+
- Verify disappearance of a concurrently removed Windows writer marker before retrying acquisition; unreadable existing markers still fail closed.
|
|
15
|
+
- These changes do not establish faster live model responses, lower billed token usage, or complete OpenClaw parity.
|
|
16
|
+
|
|
3
17
|
## 9.1.607
|
|
4
18
|
|
|
5
19
|
- Add opt-in last-selected-session restoration with resume_last_selected in tui.toml. Scope the selection to the verified account, runtime, agent and workspace. Keep ordinary startup unchanged and explicit session choices authoritative; unavailable selections fall back to a fresh session, not another session.
|
package/LIESMICH.txt
CHANGED
package/README.md
CHANGED
package/blun.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// BLUN_BUILD_INPUT_SHA256:
|
|
2
|
+
// BLUN_BUILD_INPUT_SHA256:5d42292f090cacd4506d9194f177756c6d8acc509f938ecc413c752522d368c2
|
|
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);
|
|
@@ -10449,7 +10449,18 @@ async function readOwner(lockDirectory) {
|
|
|
10449
10449
|
const marker = join(lockDirectory, name);
|
|
10450
10450
|
const stats = await lstat(marker);
|
|
10451
10451
|
if (!stats.isFile() || stats.isSymbolicLink() || stats.size > 2048) throw unavailable();
|
|
10452
|
-
|
|
10452
|
+
let content;
|
|
10453
|
+
try {
|
|
10454
|
+
content = await readFile(marker, "utf8");
|
|
10455
|
+
} catch (error) {
|
|
10456
|
+
if (process.platform === "win32" && codeOf(error) === "EPERM") try {
|
|
10457
|
+
await lstat(marker);
|
|
10458
|
+
} catch (inspectionError) {
|
|
10459
|
+
if (codeOf(inspectionError) === "ENOENT") throw inspectionError;
|
|
10460
|
+
}
|
|
10461
|
+
throw error;
|
|
10462
|
+
}
|
|
10463
|
+
const record = JSON.parse(content);
|
|
10453
10464
|
if (record === null || record.version !== 1 || record.ownerId !== match[1] || !Number.isSafeInteger(record.pid) || record.pid <= 0 || record.hostname !== hostname()) throw unavailable();
|
|
10454
10465
|
return {
|
|
10455
10466
|
name,
|
|
@@ -10641,6 +10652,22 @@ function isRecord$26(value) {
|
|
|
10641
10652
|
var init_utils$1 = __esmMin((() => {}));
|
|
10642
10653
|
//#endregion
|
|
10643
10654
|
//#region ../../packages/oauth/src/windows-command-worker.ts
|
|
10655
|
+
function prepareWindowsCommand(executable, args, platform = process.platform) {
|
|
10656
|
+
const target = args[0];
|
|
10657
|
+
if (platform !== "win32" || win32.basename(executable).toLowerCase() !== "icacls.exe" || !target || !win32.isAbsolute(target) || !win32.basename(target)) return { args };
|
|
10658
|
+
const save = args.length === 4 && args[1] === "/save" && args[3] === "/Q" && !!args[2] && win32.isAbsolute(args[2]);
|
|
10659
|
+
const repair = [
|
|
10660
|
+
"/inheritance:r",
|
|
10661
|
+
"/grant:r",
|
|
10662
|
+
"/remove",
|
|
10663
|
+
"/remove:d"
|
|
10664
|
+
].includes(args[1] ?? "") && args.at(-1) === "/Q";
|
|
10665
|
+
if (!save && !repair) return { args };
|
|
10666
|
+
return {
|
|
10667
|
+
args: [win32.basename(target), ...args.slice(1)],
|
|
10668
|
+
cwd: win32.dirname(target)
|
|
10669
|
+
};
|
|
10670
|
+
}
|
|
10644
10671
|
function retireWhenIdle(state) {
|
|
10645
10672
|
if (state.pending.size !== 0) return;
|
|
10646
10673
|
state.worker.unref();
|
|
@@ -10694,7 +10721,7 @@ function runWindowsCommand(executable, args) {
|
|
|
10694
10721
|
state.worker.postMessage({
|
|
10695
10722
|
id,
|
|
10696
10723
|
executable,
|
|
10697
|
-
|
|
10724
|
+
...prepareWindowsCommand(executable, [...args])
|
|
10698
10725
|
});
|
|
10699
10726
|
} catch (error) {
|
|
10700
10727
|
state.pending.delete(id);
|
|
@@ -10708,10 +10735,10 @@ var init_windows_command_worker = __esmMin((() => {
|
|
|
10708
10735
|
SOURCE = `
|
|
10709
10736
|
const { parentPort } = require('node:worker_threads');
|
|
10710
10737
|
const { execFileSync } = require('node:child_process');
|
|
10711
|
-
parentPort.on('message', ({ id, executable, args }) => {
|
|
10738
|
+
parentPort.on('message', ({ id, executable, args, cwd }) => {
|
|
10712
10739
|
try {
|
|
10713
10740
|
const stdout = execFileSync(executable, args, {
|
|
10714
|
-
encoding: 'utf8', shell: false, windowsHide: true,
|
|
10741
|
+
encoding: 'utf8', shell: false, windowsHide: true, cwd,
|
|
10715
10742
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
10716
10743
|
});
|
|
10717
10744
|
parentPort.postMessage({ id, stdout });
|
|
@@ -10950,7 +10977,7 @@ var init_windows_private_acl = __esmMin((() => {
|
|
|
10950
10977
|
return this.userSid;
|
|
10951
10978
|
}
|
|
10952
10979
|
async save(target) {
|
|
10953
|
-
const file = join(tmpdir(),
|
|
10980
|
+
const file = join(tmpdir(), `${randomBytes(16).toString("hex")}.txt`);
|
|
10954
10981
|
try {
|
|
10955
10982
|
await this.run("icacls.exe", [
|
|
10956
10983
|
target,
|
|
@@ -11081,7 +11108,7 @@ var init_windows_private_acl = __esmMin((() => {
|
|
|
11081
11108
|
return this.userSid;
|
|
11082
11109
|
}
|
|
11083
11110
|
transferPath() {
|
|
11084
|
-
return join(tmpdir(),
|
|
11111
|
+
return join(tmpdir(), `${randomBytes(16).toString("hex")}.txt`);
|
|
11085
11112
|
}
|
|
11086
11113
|
removeTransferFile(file) {
|
|
11087
11114
|
try {
|
|
@@ -16827,8 +16854,19 @@ async function mutateConfigFile(filePath, transform) {
|
|
|
16827
16854
|
try {
|
|
16828
16855
|
await writer.assertOwned();
|
|
16829
16856
|
const { config, result } = transform(readConfigFileForUpdate(canonical));
|
|
16830
|
-
|
|
16831
|
-
|
|
16857
|
+
for (let attempt = 0;; attempt += 1) {
|
|
16858
|
+
await writer.assertOwned();
|
|
16859
|
+
try {
|
|
16860
|
+
await writeConfigFile(canonical, config);
|
|
16861
|
+
break;
|
|
16862
|
+
} catch (error) {
|
|
16863
|
+
const failure = error;
|
|
16864
|
+
if (process.platform !== "win32" || attempt >= 9 || failure?.code !== "EPERM" || failure.syscall !== "rename" || typeof failure.dest !== "string" || resolve(failure.dest) !== canonical) throw error;
|
|
16865
|
+
await new Promise((resolve) => {
|
|
16866
|
+
setTimeout(resolve, 25);
|
|
16867
|
+
});
|
|
16868
|
+
}
|
|
16869
|
+
}
|
|
16832
16870
|
return result;
|
|
16833
16871
|
} finally {
|
|
16834
16872
|
await writer.release();
|
|
@@ -499423,6 +499461,7 @@ var CustomEditor = class extends Editor {
|
|
|
499423
499461
|
onToggleToolExpand;
|
|
499424
499462
|
onOpenExternalEditor;
|
|
499425
499463
|
onOpenSessionPicker;
|
|
499464
|
+
onOpenEffortPicker;
|
|
499426
499465
|
onCtrlS;
|
|
499427
499466
|
/** Return `true` to consume Ctrl+B; return `false`/`undefined` to fall through to the editor default (cursor-left). */
|
|
499428
499467
|
onCtrlB;
|
|
@@ -499611,6 +499650,10 @@ var CustomEditor = class extends Editor {
|
|
|
499611
499650
|
this.onOpenSessionPicker?.();
|
|
499612
499651
|
return;
|
|
499613
499652
|
}
|
|
499653
|
+
if (matchesKey(normalized, Key.ctrl("l"))) {
|
|
499654
|
+
this.onOpenEffortPicker?.();
|
|
499655
|
+
return;
|
|
499656
|
+
}
|
|
499614
499657
|
if (matchesKey(normalized, Key.ctrl("g"))) {
|
|
499615
499658
|
this.onOpenExternalEditor?.();
|
|
499616
499659
|
return;
|
|
@@ -525792,7 +525835,8 @@ var QuestionDialogComponent = class extends Container {
|
|
|
525792
525835
|
this.cursors[questionIdx] = optionIdx;
|
|
525793
525836
|
this.editingOther = false;
|
|
525794
525837
|
this.reviewMessage = void 0;
|
|
525795
|
-
|
|
525838
|
+
const togglingCommittedOther = question.multi_select && method === "space" && this.committedOtherValues[questionIdx] !== void 0;
|
|
525839
|
+
if (this.isOtherOption(questionIdx, optionIdx) && !togglingCommittedOther) {
|
|
525796
525840
|
this.enterOtherInput(questionIdx);
|
|
525797
525841
|
return;
|
|
525798
525842
|
}
|
|
@@ -531405,6 +531449,10 @@ var EditorKeyboardController = class {
|
|
|
531405
531449
|
this.clearPendingExit();
|
|
531406
531450
|
host.openSessionPickerShortcut();
|
|
531407
531451
|
};
|
|
531452
|
+
editor.onOpenEffortPicker = () => {
|
|
531453
|
+
this.clearPendingExit();
|
|
531454
|
+
host.openEffortPickerShortcut();
|
|
531455
|
+
};
|
|
531408
531456
|
editor.onOpenExternalEditor = () => {
|
|
531409
531457
|
host.track("shortcut_editor");
|
|
531410
531458
|
this.openExternalEditor();
|
|
@@ -545239,6 +545287,15 @@ var BlunTUI = class {
|
|
|
545239
545287
|
if (this.state.queuedMessages.some((item) => item.mode === "command" && item.text === "/sessions" && item.agentId === this.harness.interactiveAgentId && item.channelCommandEnvelope === void 0)) return;
|
|
545240
545288
|
this.runSlashCommand("/sessions");
|
|
545241
545289
|
}
|
|
545290
|
+
openEffortPickerShortcut() {
|
|
545291
|
+
if (this.editorReplacementActive || this.queueCommandRunning) return;
|
|
545292
|
+
if (this.state.appState.isReplaying) {
|
|
545293
|
+
this.showError(uiText("blunTui.input.replayBlocked"));
|
|
545294
|
+
return;
|
|
545295
|
+
}
|
|
545296
|
+
if (this.state.queuedMessages.some((item) => item.mode === "command" && item.text === "/effort" && item.agentId === this.harness.interactiveAgentId && item.channelCommandEnvelope === void 0)) return;
|
|
545297
|
+
this.runSlashCommand("/effort");
|
|
545298
|
+
}
|
|
545242
545299
|
async showSessionPicker(target) {
|
|
545243
545300
|
await this.openSessionPicker({
|
|
545244
545301
|
target,
|
package/package.json
CHANGED
package/worker-host.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// BLUN_BUILD_INPUT_SHA256:
|
|
2
|
+
// BLUN_BUILD_INPUT_SHA256:5d42292f090cacd4506d9194f177756c6d8acc509f938ecc413c752522d368c2
|
|
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);
|
|
@@ -10129,7 +10129,18 @@ async function readOwner(lockDirectory) {
|
|
|
10129
10129
|
const marker = join(lockDirectory, name);
|
|
10130
10130
|
const stats = await lstat(marker);
|
|
10131
10131
|
if (!stats.isFile() || stats.isSymbolicLink() || stats.size > 2048) throw unavailable();
|
|
10132
|
-
|
|
10132
|
+
let content;
|
|
10133
|
+
try {
|
|
10134
|
+
content = await readFile(marker, "utf8");
|
|
10135
|
+
} catch (error) {
|
|
10136
|
+
if (process.platform === "win32" && codeOf(error) === "EPERM") try {
|
|
10137
|
+
await lstat(marker);
|
|
10138
|
+
} catch (inspectionError) {
|
|
10139
|
+
if (codeOf(inspectionError) === "ENOENT") throw inspectionError;
|
|
10140
|
+
}
|
|
10141
|
+
throw error;
|
|
10142
|
+
}
|
|
10143
|
+
const record = JSON.parse(content);
|
|
10133
10144
|
if (record === null || record.version !== 1 || record.ownerId !== match[1] || !Number.isSafeInteger(record.pid) || record.pid <= 0 || record.hostname !== hostname()) throw unavailable();
|
|
10134
10145
|
return {
|
|
10135
10146
|
name,
|
|
@@ -10327,13 +10338,29 @@ function isRecord$9(value) {
|
|
|
10327
10338
|
}
|
|
10328
10339
|
//#endregion
|
|
10329
10340
|
//#region ../../packages/oauth/src/windows-command-worker.ts
|
|
10341
|
+
function prepareWindowsCommand(executable, args, platform = process.platform) {
|
|
10342
|
+
const target = args[0];
|
|
10343
|
+
if (platform !== "win32" || win32.basename(executable).toLowerCase() !== "icacls.exe" || !target || !win32.isAbsolute(target) || !win32.basename(target)) return { args };
|
|
10344
|
+
const save = args.length === 4 && args[1] === "/save" && args[3] === "/Q" && !!args[2] && win32.isAbsolute(args[2]);
|
|
10345
|
+
const repair = [
|
|
10346
|
+
"/inheritance:r",
|
|
10347
|
+
"/grant:r",
|
|
10348
|
+
"/remove",
|
|
10349
|
+
"/remove:d"
|
|
10350
|
+
].includes(args[1] ?? "") && args.at(-1) === "/Q";
|
|
10351
|
+
if (!save && !repair) return { args };
|
|
10352
|
+
return {
|
|
10353
|
+
args: [win32.basename(target), ...args.slice(1)],
|
|
10354
|
+
cwd: win32.dirname(target)
|
|
10355
|
+
};
|
|
10356
|
+
}
|
|
10330
10357
|
const SOURCE = `
|
|
10331
10358
|
const { parentPort } = require('node:worker_threads');
|
|
10332
10359
|
const { execFileSync } = require('node:child_process');
|
|
10333
|
-
parentPort.on('message', ({ id, executable, args }) => {
|
|
10360
|
+
parentPort.on('message', ({ id, executable, args, cwd }) => {
|
|
10334
10361
|
try {
|
|
10335
10362
|
const stdout = execFileSync(executable, args, {
|
|
10336
|
-
encoding: 'utf8', shell: false, windowsHide: true,
|
|
10363
|
+
encoding: 'utf8', shell: false, windowsHide: true, cwd,
|
|
10337
10364
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
10338
10365
|
});
|
|
10339
10366
|
parentPort.postMessage({ id, stdout });
|
|
@@ -10399,7 +10426,7 @@ function runWindowsCommand(executable, args) {
|
|
|
10399
10426
|
state.worker.postMessage({
|
|
10400
10427
|
id,
|
|
10401
10428
|
executable,
|
|
10402
|
-
|
|
10429
|
+
...prepareWindowsCommand(executable, [...args])
|
|
10403
10430
|
});
|
|
10404
10431
|
} catch (error) {
|
|
10405
10432
|
state.pending.delete(id);
|
|
@@ -10632,7 +10659,7 @@ var AsyncWindowsPrivateAcl = class {
|
|
|
10632
10659
|
return this.userSid;
|
|
10633
10660
|
}
|
|
10634
10661
|
async save(target) {
|
|
10635
|
-
const file = join(tmpdir(),
|
|
10662
|
+
const file = join(tmpdir(), `${randomBytes(16).toString("hex")}.txt`);
|
|
10636
10663
|
try {
|
|
10637
10664
|
await this.run("icacls.exe", [
|
|
10638
10665
|
target,
|
|
@@ -10763,7 +10790,7 @@ var WindowsPrivateAcl = class {
|
|
|
10763
10790
|
return this.userSid;
|
|
10764
10791
|
}
|
|
10765
10792
|
transferPath() {
|
|
10766
|
-
return join(tmpdir(),
|
|
10793
|
+
return join(tmpdir(), `${randomBytes(16).toString("hex")}.txt`);
|
|
10767
10794
|
}
|
|
10768
10795
|
removeTransferFile(file) {
|
|
10769
10796
|
try {
|
|
@@ -16368,8 +16395,19 @@ async function mutateConfigFile(filePath, transform) {
|
|
|
16368
16395
|
try {
|
|
16369
16396
|
await writer.assertOwned();
|
|
16370
16397
|
const { config, result } = transform(readConfigFileForUpdate(canonical));
|
|
16371
|
-
|
|
16372
|
-
|
|
16398
|
+
for (let attempt = 0;; attempt += 1) {
|
|
16399
|
+
await writer.assertOwned();
|
|
16400
|
+
try {
|
|
16401
|
+
await writeConfigFile(canonical, config);
|
|
16402
|
+
break;
|
|
16403
|
+
} catch (error) {
|
|
16404
|
+
const failure = error;
|
|
16405
|
+
if (process.platform !== "win32" || attempt >= 9 || failure?.code !== "EPERM" || failure.syscall !== "rename" || typeof failure.dest !== "string" || resolve(failure.dest) !== canonical) throw error;
|
|
16406
|
+
await new Promise((resolve) => {
|
|
16407
|
+
setTimeout(resolve, 25);
|
|
16408
|
+
});
|
|
16409
|
+
}
|
|
16410
|
+
}
|
|
16373
16411
|
return result;
|
|
16374
16412
|
} finally {
|
|
16375
16413
|
await writer.release();
|