@wolfx/oh-my-openagent 3.17.13 → 3.17.15
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/dist/features/background-agent/manager.d.ts +1 -0
- package/dist/features/background-agent/process-cleanup.d.ts +4 -0
- package/dist/features/run-continuation-state/types.d.ts +1 -1
- package/dist/features/skill-mcp-manager/types.d.ts +1 -0
- package/dist/index.js +314 -129
- package/dist/shared/bun-spawn-shim.d.ts +39 -0
- package/dist/shared/tmux/tmux-utils/spawn-process.d.ts +1 -1
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -2770,6 +2770,119 @@ var init_logger = __esm(() => {
|
|
|
2770
2770
|
buffer = [];
|
|
2771
2771
|
});
|
|
2772
2772
|
|
|
2773
|
+
// src/shared/bun-spawn-shim.ts
|
|
2774
|
+
import { spawn as nodeSpawn, spawnSync as nodeSpawnSync } from "child_process";
|
|
2775
|
+
import { Readable, Writable } from "stream";
|
|
2776
|
+
function emptyReadableStream() {
|
|
2777
|
+
return new ReadableStream({
|
|
2778
|
+
start(controller) {
|
|
2779
|
+
controller.close();
|
|
2780
|
+
}
|
|
2781
|
+
});
|
|
2782
|
+
}
|
|
2783
|
+
function toReadableStream(stream) {
|
|
2784
|
+
if (!stream)
|
|
2785
|
+
return emptyReadableStream();
|
|
2786
|
+
return Readable.toWeb(stream);
|
|
2787
|
+
}
|
|
2788
|
+
function emptyWritableStream() {
|
|
2789
|
+
return new Writable({
|
|
2790
|
+
write(_chunk, _encoding, callback) {
|
|
2791
|
+
callback();
|
|
2792
|
+
}
|
|
2793
|
+
});
|
|
2794
|
+
}
|
|
2795
|
+
function resolveCommand(cmdOrOpts, optsArg) {
|
|
2796
|
+
const isObj = !Array.isArray(cmdOrOpts);
|
|
2797
|
+
const opts = isObj ? cmdOrOpts : optsArg ?? {};
|
|
2798
|
+
return {
|
|
2799
|
+
cmd: isObj ? cmdOrOpts.cmd : cmdOrOpts,
|
|
2800
|
+
opts
|
|
2801
|
+
};
|
|
2802
|
+
}
|
|
2803
|
+
function resolveStdio(options) {
|
|
2804
|
+
if (options.stdio)
|
|
2805
|
+
return options.stdio;
|
|
2806
|
+
return [options.stdin ?? "ignore", options.stdout ?? "pipe", options.stderr ?? "inherit"];
|
|
2807
|
+
}
|
|
2808
|
+
function wrapNodeProcess(proc) {
|
|
2809
|
+
let exitCode = null;
|
|
2810
|
+
const exited = new Promise((resolve5, reject) => {
|
|
2811
|
+
proc.on("exit", (code) => {
|
|
2812
|
+
exitCode = code ?? 1;
|
|
2813
|
+
resolve5(exitCode);
|
|
2814
|
+
});
|
|
2815
|
+
proc.on("error", (error) => {
|
|
2816
|
+
if (exitCode === null) {
|
|
2817
|
+
exitCode = 1;
|
|
2818
|
+
reject(error);
|
|
2819
|
+
}
|
|
2820
|
+
});
|
|
2821
|
+
});
|
|
2822
|
+
return {
|
|
2823
|
+
get exitCode() {
|
|
2824
|
+
return exitCode;
|
|
2825
|
+
},
|
|
2826
|
+
exited,
|
|
2827
|
+
stdout: toReadableStream(proc.stdout),
|
|
2828
|
+
stderr: toReadableStream(proc.stderr),
|
|
2829
|
+
stdin: proc.stdin ?? emptyWritableStream(),
|
|
2830
|
+
kill(signal) {
|
|
2831
|
+
if (proc.killed || exitCode !== null)
|
|
2832
|
+
return;
|
|
2833
|
+
try {
|
|
2834
|
+
proc.kill(signal);
|
|
2835
|
+
} catch (error) {
|
|
2836
|
+
if (!String(error).includes("kill"))
|
|
2837
|
+
throw error;
|
|
2838
|
+
}
|
|
2839
|
+
},
|
|
2840
|
+
pid: proc.pid,
|
|
2841
|
+
ref() {
|
|
2842
|
+
proc.ref();
|
|
2843
|
+
},
|
|
2844
|
+
unref() {
|
|
2845
|
+
proc.unref();
|
|
2846
|
+
}
|
|
2847
|
+
};
|
|
2848
|
+
}
|
|
2849
|
+
function spawn2(cmdOrOpts, opts) {
|
|
2850
|
+
if (IS_BUN)
|
|
2851
|
+
return runtime.Bun.spawn(cmdOrOpts, opts);
|
|
2852
|
+
const { cmd, opts: options } = resolveCommand(cmdOrOpts, opts);
|
|
2853
|
+
const [bin, ...args] = cmd;
|
|
2854
|
+
const proc = nodeSpawn(bin, args, {
|
|
2855
|
+
cwd: options.cwd,
|
|
2856
|
+
env: options.env,
|
|
2857
|
+
stdio: resolveStdio(options),
|
|
2858
|
+
detached: options.detached
|
|
2859
|
+
});
|
|
2860
|
+
return wrapNodeProcess(proc);
|
|
2861
|
+
}
|
|
2862
|
+
function spawnSync(cmdOrOpts, opts) {
|
|
2863
|
+
if (IS_BUN)
|
|
2864
|
+
return runtime.Bun.spawnSync(cmdOrOpts, opts);
|
|
2865
|
+
const { cmd, opts: options } = resolveCommand(cmdOrOpts, opts);
|
|
2866
|
+
const [bin, ...args] = cmd;
|
|
2867
|
+
const result = nodeSpawnSync(bin, args, {
|
|
2868
|
+
cwd: options.cwd,
|
|
2869
|
+
env: options.env,
|
|
2870
|
+
stdio: resolveStdio(options)
|
|
2871
|
+
});
|
|
2872
|
+
return {
|
|
2873
|
+
exitCode: result.status ?? 1,
|
|
2874
|
+
stdout: result.stdout ?? undefined,
|
|
2875
|
+
stderr: result.stderr ?? undefined,
|
|
2876
|
+
success: (result.status ?? 1) === 0,
|
|
2877
|
+
pid: result.pid ?? -1
|
|
2878
|
+
};
|
|
2879
|
+
}
|
|
2880
|
+
var runtime, IS_BUN;
|
|
2881
|
+
var init_bun_spawn_shim = __esm(() => {
|
|
2882
|
+
runtime = globalThis;
|
|
2883
|
+
IS_BUN = typeof runtime.Bun !== "undefined";
|
|
2884
|
+
});
|
|
2885
|
+
|
|
2773
2886
|
// src/shared/agent-display-names.ts
|
|
2774
2887
|
function stripInvisibleAgentCharacters(agentName) {
|
|
2775
2888
|
return agentName.replace(INVISIBLE_AGENT_CHARACTERS_REGEX, "");
|
|
@@ -2873,12 +2986,11 @@ __export(exports_tmux_path_resolver, {
|
|
|
2873
2986
|
getTmuxPath: () => getTmuxPath,
|
|
2874
2987
|
getCachedTmuxPath: () => getCachedTmuxPath
|
|
2875
2988
|
});
|
|
2876
|
-
var {spawn: spawn9 } = globalThis.Bun;
|
|
2877
2989
|
async function findTmuxPath() {
|
|
2878
2990
|
const isWindows = process.platform === "win32";
|
|
2879
2991
|
const cmd = isWindows ? "where" : "which";
|
|
2880
2992
|
try {
|
|
2881
|
-
const proc =
|
|
2993
|
+
const proc = spawn2([cmd, "tmux"], {
|
|
2882
2994
|
stdout: "pipe",
|
|
2883
2995
|
stderr: "pipe"
|
|
2884
2996
|
});
|
|
@@ -2892,7 +3004,7 @@ async function findTmuxPath() {
|
|
|
2892
3004
|
if (!path6) {
|
|
2893
3005
|
return null;
|
|
2894
3006
|
}
|
|
2895
|
-
const verifyProc =
|
|
3007
|
+
const verifyProc = spawn2([path6, "-V"], {
|
|
2896
3008
|
stdout: "pipe",
|
|
2897
3009
|
stderr: "pipe"
|
|
2898
3010
|
});
|
|
@@ -2929,15 +3041,18 @@ function startBackgroundCheck() {
|
|
|
2929
3041
|
}
|
|
2930
3042
|
}
|
|
2931
3043
|
var tmuxPath = null, initPromise = null;
|
|
2932
|
-
var init_tmux_path_resolver = () => {
|
|
3044
|
+
var init_tmux_path_resolver = __esm(() => {
|
|
3045
|
+
init_bun_spawn_shim();
|
|
3046
|
+
});
|
|
2933
3047
|
|
|
2934
3048
|
// src/shared/tmux/tmux-utils/spawn-process.ts
|
|
2935
3049
|
var exports_spawn_process = {};
|
|
2936
3050
|
__export(exports_spawn_process, {
|
|
2937
|
-
spawn: () =>
|
|
3051
|
+
spawn: () => spawn2
|
|
3052
|
+
});
|
|
3053
|
+
var init_spawn_process = __esm(() => {
|
|
3054
|
+
init_bun_spawn_shim();
|
|
2938
3055
|
});
|
|
2939
|
-
var {spawn: spawn11 } = globalThis.Bun;
|
|
2940
|
-
var init_spawn_process = () => {};
|
|
2941
3056
|
|
|
2942
3057
|
// src/shared/tmux/tmux-utils/session-kill.ts
|
|
2943
3058
|
var exports_session_kill = {};
|
|
@@ -2948,7 +3063,7 @@ async function readStream2(stream) {
|
|
|
2948
3063
|
return stream ? new Response(stream).text() : "";
|
|
2949
3064
|
}
|
|
2950
3065
|
async function killTmuxSessionIfExists(sessionName) {
|
|
2951
|
-
const [{ log: log2 }, { isInsideTmux: isInsideTmux2 }, { getTmuxPath: getTmuxPath2 }, { spawn:
|
|
3066
|
+
const [{ log: log2 }, { isInsideTmux: isInsideTmux2 }, { getTmuxPath: getTmuxPath2 }, { spawn: spawn3 }] = await Promise.all([
|
|
2952
3067
|
Promise.resolve().then(() => (init_logger(), exports_logger)),
|
|
2953
3068
|
Promise.resolve().then(() => exports_environment),
|
|
2954
3069
|
Promise.resolve().then(() => (init_tmux_path_resolver(), exports_tmux_path_resolver)),
|
|
@@ -2963,7 +3078,7 @@ async function killTmuxSessionIfExists(sessionName) {
|
|
|
2963
3078
|
log2("[killTmuxSessionIfExists] SKIP: tmux not found", { sessionName });
|
|
2964
3079
|
return false;
|
|
2965
3080
|
}
|
|
2966
|
-
const hasSessionProcess =
|
|
3081
|
+
const hasSessionProcess = spawn3([tmux, "has-session", "-t", sessionName], {
|
|
2967
3082
|
stdout: "ignore",
|
|
2968
3083
|
stderr: "ignore"
|
|
2969
3084
|
});
|
|
@@ -2971,7 +3086,7 @@ async function killTmuxSessionIfExists(sessionName) {
|
|
|
2971
3086
|
log2("[killTmuxSessionIfExists] SKIP: session not found", { sessionName });
|
|
2972
3087
|
return false;
|
|
2973
3088
|
}
|
|
2974
|
-
const killSessionProcess =
|
|
3089
|
+
const killSessionProcess = spawn3([tmux, "kill-session", "-t", sessionName], {
|
|
2975
3090
|
stdout: "pipe",
|
|
2976
3091
|
stderr: "pipe"
|
|
2977
3092
|
});
|
|
@@ -15517,10 +15632,10 @@ var require_resolveCommand = __commonJS((exports, module) => {
|
|
|
15517
15632
|
}
|
|
15518
15633
|
return resolved;
|
|
15519
15634
|
}
|
|
15520
|
-
function
|
|
15635
|
+
function resolveCommand2(parsed) {
|
|
15521
15636
|
return resolveCommandAttempt(parsed) || resolveCommandAttempt(parsed, true);
|
|
15522
15637
|
}
|
|
15523
|
-
module.exports =
|
|
15638
|
+
module.exports = resolveCommand2;
|
|
15524
15639
|
});
|
|
15525
15640
|
|
|
15526
15641
|
// node_modules/cross-spawn/lib/util/escape.js
|
|
@@ -15588,19 +15703,19 @@ var require_readShebang = __commonJS((exports, module) => {
|
|
|
15588
15703
|
// node_modules/cross-spawn/lib/parse.js
|
|
15589
15704
|
var require_parse2 = __commonJS((exports, module) => {
|
|
15590
15705
|
var path15 = __require("path");
|
|
15591
|
-
var
|
|
15706
|
+
var resolveCommand2 = require_resolveCommand();
|
|
15592
15707
|
var escape2 = require_escape();
|
|
15593
15708
|
var readShebang = require_readShebang();
|
|
15594
15709
|
var isWin = process.platform === "win32";
|
|
15595
15710
|
var isExecutableRegExp = /\.(?:com|exe)$/i;
|
|
15596
15711
|
var isCmdShimRegExp = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;
|
|
15597
15712
|
function detectShebang(parsed) {
|
|
15598
|
-
parsed.file =
|
|
15713
|
+
parsed.file = resolveCommand2(parsed);
|
|
15599
15714
|
const shebang = parsed.file && readShebang(parsed.file);
|
|
15600
15715
|
if (shebang) {
|
|
15601
15716
|
parsed.args.unshift(parsed.file);
|
|
15602
15717
|
parsed.command = shebang;
|
|
15603
|
-
return
|
|
15718
|
+
return resolveCommand2(parsed);
|
|
15604
15719
|
}
|
|
15605
15720
|
return parsed.file;
|
|
15606
15721
|
}
|
|
@@ -15696,21 +15811,21 @@ var require_cross_spawn = __commonJS((exports, module) => {
|
|
|
15696
15811
|
var cp = __require("child_process");
|
|
15697
15812
|
var parse11 = require_parse2();
|
|
15698
15813
|
var enoent = require_enoent();
|
|
15699
|
-
function
|
|
15814
|
+
function spawn4(command, args, options) {
|
|
15700
15815
|
const parsed = parse11(command, args, options);
|
|
15701
15816
|
const spawned = cp.spawn(parsed.command, parsed.args, parsed.options);
|
|
15702
15817
|
enoent.hookChildProcess(spawned, parsed);
|
|
15703
15818
|
return spawned;
|
|
15704
15819
|
}
|
|
15705
|
-
function
|
|
15820
|
+
function spawnSync3(command, args, options) {
|
|
15706
15821
|
const parsed = parse11(command, args, options);
|
|
15707
15822
|
const result = cp.spawnSync(parsed.command, parsed.args, parsed.options);
|
|
15708
15823
|
result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
|
|
15709
15824
|
return result;
|
|
15710
15825
|
}
|
|
15711
|
-
module.exports =
|
|
15712
|
-
module.exports.spawn =
|
|
15713
|
-
module.exports.sync =
|
|
15826
|
+
module.exports = spawn4;
|
|
15827
|
+
module.exports.spawn = spawn4;
|
|
15828
|
+
module.exports.sync = spawnSync3;
|
|
15714
15829
|
module.exports._parse = parse11;
|
|
15715
15830
|
module.exports._enoent = enoent;
|
|
15716
15831
|
});
|
|
@@ -18576,7 +18691,7 @@ Both ${PLUGIN_NAME} and ${pluginName} scan ~/.config/opencode/skills/ and regist
|
|
|
18576
18691
|
3. Or uninstall ${PLUGIN_NAME} if you prefer ${pluginName}'s skill management`;
|
|
18577
18692
|
}
|
|
18578
18693
|
// src/shared/zip-extractor.ts
|
|
18579
|
-
|
|
18694
|
+
init_bun_spawn_shim();
|
|
18580
18695
|
import { release } from "os";
|
|
18581
18696
|
|
|
18582
18697
|
// src/shared/archive-entry-validator.ts
|
|
@@ -18635,7 +18750,7 @@ function validateArchiveEntries(entries, destDir) {
|
|
|
18635
18750
|
}
|
|
18636
18751
|
|
|
18637
18752
|
// src/shared/zip-entry-listing/python-zip-entry-listing.ts
|
|
18638
|
-
|
|
18753
|
+
init_bun_spawn_shim();
|
|
18639
18754
|
function isPythonZipListingAvailable() {
|
|
18640
18755
|
const proc = spawnSync(["python3", "--version"], {
|
|
18641
18756
|
stdout: "ignore",
|
|
@@ -18681,7 +18796,7 @@ async function listZipEntriesWithPython(archivePath) {
|
|
|
18681
18796
|
return JSON.parse(stdout);
|
|
18682
18797
|
}
|
|
18683
18798
|
// src/shared/zip-entry-listing/powershell-zip-entry-listing.ts
|
|
18684
|
-
|
|
18799
|
+
init_bun_spawn_shim();
|
|
18685
18800
|
function isPowerShellZipEntryRecord(value) {
|
|
18686
18801
|
if (!value || typeof value !== "object") {
|
|
18687
18802
|
return false;
|
|
@@ -18707,7 +18822,7 @@ function parsePowerShellZipEntryLine(line) {
|
|
|
18707
18822
|
};
|
|
18708
18823
|
}
|
|
18709
18824
|
async function listZipEntriesWithPowerShell(archivePath, escapePowerShellPath, extractor) {
|
|
18710
|
-
const proc =
|
|
18825
|
+
const proc = spawn2([
|
|
18711
18826
|
extractor,
|
|
18712
18827
|
"-Command",
|
|
18713
18828
|
[
|
|
@@ -18746,8 +18861,8 @@ async function listZipEntriesWithPowerShell(archivePath, escapePowerShellPath, e
|
|
|
18746
18861
|
return stdout.split(/\r?\n/).map((line) => line.trim()).filter(Boolean).map((line) => parsePowerShellZipEntryLine(line)).filter((entry) => entry !== null);
|
|
18747
18862
|
}
|
|
18748
18863
|
// src/shared/zip-entry-listing/tar-zip-entry-listing.ts
|
|
18864
|
+
init_bun_spawn_shim();
|
|
18749
18865
|
init_logger();
|
|
18750
|
-
var {spawn: spawn4 } = globalThis.Bun;
|
|
18751
18866
|
function parseTarListedZipEntry(line) {
|
|
18752
18867
|
const match = line.match(/^([^\s])\S*\s+\d+\s+\S+\s+\S+\s+\d+\s+\w+\s+\d+\s+(?:\d{2}:\d{2}|\d{4})\s+(.*)$/);
|
|
18753
18868
|
if (!match) {
|
|
@@ -18793,7 +18908,7 @@ function parseTarListingOutput(stdout) {
|
|
|
18793
18908
|
return parsedEntries;
|
|
18794
18909
|
}
|
|
18795
18910
|
async function listZipEntriesWithTar(archivePath) {
|
|
18796
|
-
const proc =
|
|
18911
|
+
const proc = spawn2(["tar", "-tvf", archivePath], {
|
|
18797
18912
|
stdout: "pipe",
|
|
18798
18913
|
stderr: "pipe"
|
|
18799
18914
|
});
|
|
@@ -18808,12 +18923,12 @@ async function listZipEntriesWithTar(archivePath) {
|
|
|
18808
18923
|
return parseTarListingOutput(stdout);
|
|
18809
18924
|
}
|
|
18810
18925
|
// src/shared/zip-entry-listing/zipinfo-zip-entry-listing.ts
|
|
18811
|
-
|
|
18926
|
+
init_bun_spawn_shim();
|
|
18812
18927
|
|
|
18813
18928
|
// src/shared/zip-entry-listing/read-zip-symlink-target.ts
|
|
18814
|
-
|
|
18929
|
+
init_bun_spawn_shim();
|
|
18815
18930
|
async function readZipSymlinkTarget(archivePath, entryPath) {
|
|
18816
|
-
const proc =
|
|
18931
|
+
const proc = spawn2(["unzip", "-p", archivePath, "--", entryPath], {
|
|
18817
18932
|
stdout: "pipe",
|
|
18818
18933
|
stderr: "pipe"
|
|
18819
18934
|
});
|
|
@@ -18841,7 +18956,7 @@ function parseZipInfoListedEntry(line) {
|
|
|
18841
18956
|
};
|
|
18842
18957
|
}
|
|
18843
18958
|
function isZipInfoZipListingAvailable() {
|
|
18844
|
-
const proc =
|
|
18959
|
+
const proc = spawnSync(["which", "zipinfo"], {
|
|
18845
18960
|
stdout: "ignore",
|
|
18846
18961
|
stderr: "ignore"
|
|
18847
18962
|
});
|
|
@@ -18854,7 +18969,7 @@ async function listZipEntriesWithZipInfo(archivePath) {
|
|
|
18854
18969
|
if (!isZipInfoZipListingAvailable()) {
|
|
18855
18970
|
throw new Error("zip entry listing requires zipinfo, but zipinfo is not installed");
|
|
18856
18971
|
}
|
|
18857
|
-
const proc =
|
|
18972
|
+
const proc = spawn2(["zipinfo", "-l", archivePath], {
|
|
18858
18973
|
stdout: "pipe",
|
|
18859
18974
|
stderr: "pipe"
|
|
18860
18975
|
});
|
|
@@ -18893,7 +19008,7 @@ function getWindowsBuildNumber() {
|
|
|
18893
19008
|
function isPwshAvailable() {
|
|
18894
19009
|
if (process.platform !== "win32")
|
|
18895
19010
|
return false;
|
|
18896
|
-
const result =
|
|
19011
|
+
const result = spawnSync(["where", "pwsh"], { stdout: "pipe", stderr: "pipe" });
|
|
18897
19012
|
return result.exitCode === 0;
|
|
18898
19013
|
}
|
|
18899
19014
|
function escapePowerShellPath(path5) {
|
|
@@ -18917,27 +19032,27 @@ async function extractZip(archivePath, destDir) {
|
|
|
18917
19032
|
const extractor = getWindowsZipExtractor();
|
|
18918
19033
|
switch (extractor) {
|
|
18919
19034
|
case "tar":
|
|
18920
|
-
proc =
|
|
19035
|
+
proc = spawn2(["tar", "-xf", archivePath, "-C", destDir], {
|
|
18921
19036
|
stdout: "ignore",
|
|
18922
19037
|
stderr: "pipe"
|
|
18923
19038
|
});
|
|
18924
19039
|
break;
|
|
18925
19040
|
case "pwsh":
|
|
18926
|
-
proc =
|
|
19041
|
+
proc = spawn2(["pwsh", "-Command", `Expand-Archive -Path '${escapePowerShellPath(archivePath)}' -DestinationPath '${escapePowerShellPath(destDir)}' -Force`], {
|
|
18927
19042
|
stdout: "ignore",
|
|
18928
19043
|
stderr: "pipe"
|
|
18929
19044
|
});
|
|
18930
19045
|
break;
|
|
18931
19046
|
case "powershell":
|
|
18932
19047
|
default:
|
|
18933
|
-
proc =
|
|
19048
|
+
proc = spawn2(["powershell", "-Command", `Expand-Archive -Path '${escapePowerShellPath(archivePath)}' -DestinationPath '${escapePowerShellPath(destDir)}' -Force`], {
|
|
18934
19049
|
stdout: "ignore",
|
|
18935
19050
|
stderr: "pipe"
|
|
18936
19051
|
});
|
|
18937
19052
|
break;
|
|
18938
19053
|
}
|
|
18939
19054
|
} else {
|
|
18940
|
-
proc =
|
|
19055
|
+
proc = spawn2(["unzip", "-o", archivePath, "-d", destDir], {
|
|
18941
19056
|
stdout: "ignore",
|
|
18942
19057
|
stderr: "pipe"
|
|
18943
19058
|
});
|
|
@@ -18965,9 +19080,9 @@ async function listZipEntries(archivePath) {
|
|
|
18965
19080
|
throw new Error("zip entry listing requires either python3 or zipinfo to inspect the archive safely");
|
|
18966
19081
|
}
|
|
18967
19082
|
// src/shared/binary-downloader.ts
|
|
19083
|
+
init_bun_spawn_shim();
|
|
18968
19084
|
import { chmodSync, existsSync as existsSync9, mkdirSync as mkdirSync3, unlinkSync as unlinkSync2 } from "fs";
|
|
18969
19085
|
import * as path5 from "path";
|
|
18970
|
-
var {spawn: spawn8 } = globalThis.Bun;
|
|
18971
19086
|
function isTarTraversalErrorOutput(output) {
|
|
18972
19087
|
return /path contains '\.\.'|member name contains '\.\.'|removing leading [`'\"]?\.\.\//i.test(output);
|
|
18973
19088
|
}
|
|
@@ -18992,7 +19107,7 @@ async function extractTarGz(archivePath, destDir, options) {
|
|
|
18992
19107
|
const entries = await listTarEntries(archivePath, options?.cwd);
|
|
18993
19108
|
validateArchiveEntries(entries, destDir);
|
|
18994
19109
|
const args = options?.args ?? ["tar", "-xzf", archivePath, "-C", destDir];
|
|
18995
|
-
const proc =
|
|
19110
|
+
const proc = spawn2(args, {
|
|
18996
19111
|
cwd: options?.cwd,
|
|
18997
19112
|
stdout: "pipe",
|
|
18998
19113
|
stderr: "pipe"
|
|
@@ -19042,7 +19157,7 @@ function parseTarEntry(line) {
|
|
|
19042
19157
|
};
|
|
19043
19158
|
}
|
|
19044
19159
|
async function listTarEntries(archivePath, cwd) {
|
|
19045
|
-
const proc =
|
|
19160
|
+
const proc = spawn2(["tar", "-tvzf", archivePath], {
|
|
19046
19161
|
cwd,
|
|
19047
19162
|
stdout: "pipe",
|
|
19048
19163
|
stderr: "pipe"
|
|
@@ -19612,6 +19727,7 @@ function toLogLabel(cacheLabel) {
|
|
|
19612
19727
|
}
|
|
19613
19728
|
function createJsonFileCacheStore(options) {
|
|
19614
19729
|
let memoryValue;
|
|
19730
|
+
let writtenInCurrentProcess = false;
|
|
19615
19731
|
function getCacheFilePath() {
|
|
19616
19732
|
return join10(options.getCacheDir(), options.filename);
|
|
19617
19733
|
}
|
|
@@ -19646,6 +19762,12 @@ function createJsonFileCacheStore(options) {
|
|
|
19646
19762
|
}
|
|
19647
19763
|
}
|
|
19648
19764
|
function has() {
|
|
19765
|
+
if (memoryValue !== undefined && memoryValue !== null) {
|
|
19766
|
+
return true;
|
|
19767
|
+
}
|
|
19768
|
+
if (writtenInCurrentProcess) {
|
|
19769
|
+
return true;
|
|
19770
|
+
}
|
|
19649
19771
|
return existsSync10(getCacheFilePath());
|
|
19650
19772
|
}
|
|
19651
19773
|
function write(value) {
|
|
@@ -19654,6 +19776,7 @@ function createJsonFileCacheStore(options) {
|
|
|
19654
19776
|
try {
|
|
19655
19777
|
writeFileSync2(cacheFile, options.serialize?.(value) ?? JSON.stringify(value, null, 2));
|
|
19656
19778
|
memoryValue = value;
|
|
19779
|
+
writtenInCurrentProcess = true;
|
|
19657
19780
|
log(`[${options.logPrefix}] ${options.cacheLabel} written`, options.describe(value));
|
|
19658
19781
|
} catch (error) {
|
|
19659
19782
|
log(`[${options.logPrefix}] Error writing ${toLogLabel(options.cacheLabel)}`, {
|
|
@@ -19663,6 +19786,7 @@ function createJsonFileCacheStore(options) {
|
|
|
19663
19786
|
}
|
|
19664
19787
|
function resetMemory() {
|
|
19665
19788
|
memoryValue = undefined;
|
|
19789
|
+
writtenInCurrentProcess = false;
|
|
19666
19790
|
}
|
|
19667
19791
|
return {
|
|
19668
19792
|
read,
|
|
@@ -19673,6 +19797,7 @@ function createJsonFileCacheStore(options) {
|
|
|
19673
19797
|
}
|
|
19674
19798
|
|
|
19675
19799
|
// src/shared/connected-providers-cache.ts
|
|
19800
|
+
var providerModelsCacheWrittenInCurrentProcess = false;
|
|
19676
19801
|
var CONNECTED_PROVIDERS_CACHE_FILE = "connected-providers.json";
|
|
19677
19802
|
var PROVIDER_MODELS_CACHE_FILE = "provider-models.json";
|
|
19678
19803
|
function isRecord(value) {
|
|
@@ -19712,6 +19837,9 @@ function createConnectedProvidersCacheStore(getCacheDir2 = getOmoOpenCodeCacheDi
|
|
|
19712
19837
|
return providerModelsCacheStore.read();
|
|
19713
19838
|
}
|
|
19714
19839
|
function hasProviderModelsCache() {
|
|
19840
|
+
if (providerModelsCacheWrittenInCurrentProcess) {
|
|
19841
|
+
return true;
|
|
19842
|
+
}
|
|
19715
19843
|
return providerModelsCacheStore.has();
|
|
19716
19844
|
}
|
|
19717
19845
|
function writeProviderModelsCache(data) {
|
|
@@ -19719,6 +19847,7 @@ function createConnectedProvidersCacheStore(getCacheDir2 = getOmoOpenCodeCacheDi
|
|
|
19719
19847
|
...data,
|
|
19720
19848
|
updatedAt: new Date().toISOString()
|
|
19721
19849
|
});
|
|
19850
|
+
providerModelsCacheWrittenInCurrentProcess = true;
|
|
19722
19851
|
}
|
|
19723
19852
|
async function updateConnectedProvidersCache(client) {
|
|
19724
19853
|
if (!client?.provider?.list) {
|
|
@@ -19767,6 +19896,7 @@ function createConnectedProvidersCacheStore(getCacheDir2 = getOmoOpenCodeCacheDi
|
|
|
19767
19896
|
function _resetMemCacheForTesting() {
|
|
19768
19897
|
connectedProvidersCacheStore.resetMemory();
|
|
19769
19898
|
providerModelsCacheStore.resetMemory();
|
|
19899
|
+
providerModelsCacheWrittenInCurrentProcess = false;
|
|
19770
19900
|
}
|
|
19771
19901
|
return {
|
|
19772
19902
|
readConnectedProvidersCache,
|
|
@@ -63825,10 +63955,11 @@ async function isServerRunning(serverUrl) {
|
|
|
63825
63955
|
return false;
|
|
63826
63956
|
}
|
|
63827
63957
|
// src/shared/tmux/tmux-utils/pane-dimensions.ts
|
|
63958
|
+
init_bun_spawn_shim();
|
|
63828
63959
|
init_tmux_path_resolver();
|
|
63829
63960
|
// src/shared/tmux/tmux-utils/pane-spawn.ts
|
|
63961
|
+
init_bun_spawn_shim();
|
|
63830
63962
|
init_tmux_path_resolver();
|
|
63831
|
-
var {spawn: spawn10 } = globalThis.Bun;
|
|
63832
63963
|
async function spawnTmuxPane(sessionId, description, config, serverUrl, targetPaneId, splitDirection = "-h") {
|
|
63833
63964
|
const { log: log2 } = await Promise.resolve().then(() => (init_logger(), exports_logger));
|
|
63834
63965
|
log2("[spawnTmuxPane] called", {
|
|
@@ -63871,7 +64002,7 @@ async function spawnTmuxPane(sessionId, description, config, serverUrl, targetPa
|
|
|
63871
64002
|
...targetPaneId ? ["-t", targetPaneId] : [],
|
|
63872
64003
|
opencodeCmd
|
|
63873
64004
|
];
|
|
63874
|
-
const proc =
|
|
64005
|
+
const proc = spawn2([tmux, ...args], { stdout: "pipe", stderr: "pipe" });
|
|
63875
64006
|
const exitCode = await proc.exited;
|
|
63876
64007
|
const stdout = await new Response(proc.stdout).text();
|
|
63877
64008
|
const paneId = stdout.trim();
|
|
@@ -63879,7 +64010,7 @@ async function spawnTmuxPane(sessionId, description, config, serverUrl, targetPa
|
|
|
63879
64010
|
return { success: false };
|
|
63880
64011
|
}
|
|
63881
64012
|
const title = `omo-subagent-${description.slice(0, 20)}`;
|
|
63882
|
-
const titleProc =
|
|
64013
|
+
const titleProc = spawn2([tmux, "select-pane", "-t", paneId, "-T", title], {
|
|
63883
64014
|
stdout: "ignore",
|
|
63884
64015
|
stderr: "pipe"
|
|
63885
64016
|
});
|
|
@@ -63904,7 +64035,7 @@ async function readStream(stream) {
|
|
|
63904
64035
|
return stream ? new Response(stream).text() : "";
|
|
63905
64036
|
}
|
|
63906
64037
|
async function closeTmuxPane(paneId) {
|
|
63907
|
-
const [{ log: log2 }, { isInsideTmux: isInsideTmux2 }, { getTmuxPath: getTmuxPath2 }, { spawn:
|
|
64038
|
+
const [{ log: log2 }, { isInsideTmux: isInsideTmux2 }, { getTmuxPath: getTmuxPath2 }, { spawn: spawn3 }] = await Promise.all([
|
|
63908
64039
|
Promise.resolve().then(() => (init_logger(), exports_logger)),
|
|
63909
64040
|
Promise.resolve().then(() => exports_environment),
|
|
63910
64041
|
Promise.resolve().then(() => (init_tmux_path_resolver(), exports_tmux_path_resolver)),
|
|
@@ -63920,14 +64051,14 @@ async function closeTmuxPane(paneId) {
|
|
|
63920
64051
|
return false;
|
|
63921
64052
|
}
|
|
63922
64053
|
log2("[closeTmuxPane] sending Ctrl+C for graceful shutdown", { paneId });
|
|
63923
|
-
const ctrlCProc =
|
|
64054
|
+
const ctrlCProc = spawn3([tmux, "send-keys", "-t", paneId, "C-c"], {
|
|
63924
64055
|
stdout: "ignore",
|
|
63925
64056
|
stderr: "ignore"
|
|
63926
64057
|
});
|
|
63927
64058
|
await ctrlCProc.exited;
|
|
63928
64059
|
await delay2(250);
|
|
63929
64060
|
log2("[closeTmuxPane] killing pane", { paneId });
|
|
63930
|
-
const killPaneProc =
|
|
64061
|
+
const killPaneProc = spawn3([tmux, "kill-pane", "-t", paneId], {
|
|
63931
64062
|
stdout: "pipe",
|
|
63932
64063
|
stderr: "pipe"
|
|
63933
64064
|
});
|
|
@@ -63950,8 +64081,8 @@ async function closeTmuxPane(paneId) {
|
|
|
63950
64081
|
return true;
|
|
63951
64082
|
}
|
|
63952
64083
|
// src/shared/tmux/tmux-utils/pane-replace.ts
|
|
64084
|
+
init_bun_spawn_shim();
|
|
63953
64085
|
init_tmux_path_resolver();
|
|
63954
|
-
var {spawn: spawn12 } = globalThis.Bun;
|
|
63955
64086
|
async function replaceTmuxPane(paneId, sessionId, description, config, serverUrl) {
|
|
63956
64087
|
const { log: log2 } = await Promise.resolve().then(() => (init_logger(), exports_logger));
|
|
63957
64088
|
log2("[replaceTmuxPane] called", { paneId, sessionId, description });
|
|
@@ -63966,7 +64097,7 @@ async function replaceTmuxPane(paneId, sessionId, description, config, serverUrl
|
|
|
63966
64097
|
return { success: false };
|
|
63967
64098
|
}
|
|
63968
64099
|
log2("[replaceTmuxPane] sending Ctrl+C for graceful shutdown", { paneId });
|
|
63969
|
-
const ctrlCProc =
|
|
64100
|
+
const ctrlCProc = spawn2([tmux, "send-keys", "-t", paneId, "C-c"], {
|
|
63970
64101
|
stdout: "pipe",
|
|
63971
64102
|
stderr: "pipe"
|
|
63972
64103
|
});
|
|
@@ -63974,7 +64105,7 @@ async function replaceTmuxPane(paneId, sessionId, description, config, serverUrl
|
|
|
63974
64105
|
const shell = process.env.SHELL || "/bin/sh";
|
|
63975
64106
|
const escapedUrl = shellEscapeForDoubleQuotedCommand(serverUrl);
|
|
63976
64107
|
const opencodeCmd = `${shell} -c "opencode attach ${escapedUrl} --session ${sessionId}"`;
|
|
63977
|
-
const proc =
|
|
64108
|
+
const proc = spawn2([tmux, "respawn-pane", "-k", "-t", paneId, opencodeCmd], {
|
|
63978
64109
|
stdout: "pipe",
|
|
63979
64110
|
stderr: "pipe"
|
|
63980
64111
|
});
|
|
@@ -63985,7 +64116,7 @@ async function replaceTmuxPane(paneId, sessionId, description, config, serverUrl
|
|
|
63985
64116
|
return { success: false };
|
|
63986
64117
|
}
|
|
63987
64118
|
const title = `omo-subagent-${description.slice(0, 20)}`;
|
|
63988
|
-
const titleProc =
|
|
64119
|
+
const titleProc = spawn2([tmux, "select-pane", "-t", paneId, "-T", title], {
|
|
63989
64120
|
stdout: "ignore",
|
|
63990
64121
|
stderr: "pipe"
|
|
63991
64122
|
});
|
|
@@ -64004,8 +64135,8 @@ async function replaceTmuxPane(paneId, sessionId, description, config, serverUrl
|
|
|
64004
64135
|
return { success: true, paneId };
|
|
64005
64136
|
}
|
|
64006
64137
|
// src/shared/tmux/tmux-utils/window-spawn.ts
|
|
64138
|
+
init_bun_spawn_shim();
|
|
64007
64139
|
init_tmux_path_resolver();
|
|
64008
|
-
var {spawn: spawn13 } = globalThis.Bun;
|
|
64009
64140
|
var ISOLATED_WINDOW_NAME = "omo-agents";
|
|
64010
64141
|
async function spawnTmuxWindow(sessionId, description, config, serverUrl) {
|
|
64011
64142
|
const { log: log2 } = await Promise.resolve().then(() => (init_logger(), exports_logger));
|
|
@@ -64048,7 +64179,7 @@ async function spawnTmuxWindow(sessionId, description, config, serverUrl) {
|
|
|
64048
64179
|
"#{pane_id}",
|
|
64049
64180
|
opencodeCmd
|
|
64050
64181
|
];
|
|
64051
|
-
const proc =
|
|
64182
|
+
const proc = spawn2([tmux, ...args], { stdout: "pipe", stderr: "pipe" });
|
|
64052
64183
|
const exitCode = await proc.exited;
|
|
64053
64184
|
const stdout = await new Response(proc.stdout).text();
|
|
64054
64185
|
const paneId = stdout.trim();
|
|
@@ -64058,7 +64189,7 @@ async function spawnTmuxWindow(sessionId, description, config, serverUrl) {
|
|
|
64058
64189
|
return { success: false };
|
|
64059
64190
|
}
|
|
64060
64191
|
const title = `omo-subagent-${description.slice(0, 20)}`;
|
|
64061
|
-
const titleProc =
|
|
64192
|
+
const titleProc = spawn2([tmux, "select-pane", "-t", paneId, "-T", title], {
|
|
64062
64193
|
stdout: "ignore",
|
|
64063
64194
|
stderr: "pipe"
|
|
64064
64195
|
});
|
|
@@ -64077,14 +64208,14 @@ async function spawnTmuxWindow(sessionId, description, config, serverUrl) {
|
|
|
64077
64208
|
return { success: true, paneId };
|
|
64078
64209
|
}
|
|
64079
64210
|
// src/shared/tmux/tmux-utils/session-spawn.ts
|
|
64211
|
+
init_bun_spawn_shim();
|
|
64080
64212
|
init_tmux_path_resolver();
|
|
64081
|
-
var {spawn: spawn14 } = globalThis.Bun;
|
|
64082
64213
|
var ISOLATED_SESSION_NAME_PREFIX = "omo-agents";
|
|
64083
64214
|
function getIsolatedSessionName(pid = process.pid) {
|
|
64084
64215
|
return `${ISOLATED_SESSION_NAME_PREFIX}-${pid}`;
|
|
64085
64216
|
}
|
|
64086
64217
|
async function getWindowDimensions(tmux, sourcePaneId) {
|
|
64087
|
-
const proc =
|
|
64218
|
+
const proc = spawn2([tmux, "display", "-p", "-t", sourcePaneId, "#{window_width},#{window_height}"], { stdout: "pipe", stderr: "pipe" });
|
|
64088
64219
|
const exitCode = await proc.exited;
|
|
64089
64220
|
const stdout = await new Response(proc.stdout).text();
|
|
64090
64221
|
if (exitCode !== 0)
|
|
@@ -64095,7 +64226,7 @@ async function getWindowDimensions(tmux, sourcePaneId) {
|
|
|
64095
64226
|
return { width, height };
|
|
64096
64227
|
}
|
|
64097
64228
|
async function sessionExists(tmux, sessionName) {
|
|
64098
|
-
const proc =
|
|
64229
|
+
const proc = spawn2([tmux, "has-session", "-t", sessionName], {
|
|
64099
64230
|
stdout: "ignore",
|
|
64100
64231
|
stderr: "ignore"
|
|
64101
64232
|
});
|
|
@@ -64164,7 +64295,7 @@ async function spawnTmuxSession(sessionId, description, config, serverUrl, sourc
|
|
|
64164
64295
|
mode: sessionAlreadyExists ? "new-window" : "new-session",
|
|
64165
64296
|
sessionName: isolatedSessionName
|
|
64166
64297
|
});
|
|
64167
|
-
const proc =
|
|
64298
|
+
const proc = spawn2([tmux, ...args], { stdout: "pipe", stderr: "pipe" });
|
|
64168
64299
|
const exitCode = await proc.exited;
|
|
64169
64300
|
const stdout = await new Response(proc.stdout).text();
|
|
64170
64301
|
const paneId = stdout.trim();
|
|
@@ -64174,7 +64305,7 @@ async function spawnTmuxSession(sessionId, description, config, serverUrl, sourc
|
|
|
64174
64305
|
return { success: false };
|
|
64175
64306
|
}
|
|
64176
64307
|
const title = `omo-subagent-${description.slice(0, 20)}`;
|
|
64177
|
-
const titleProc =
|
|
64308
|
+
const titleProc = spawn2([tmux, "select-pane", "-t", paneId, "-T", title], {
|
|
64178
64309
|
stdout: "ignore",
|
|
64179
64310
|
stderr: "pipe"
|
|
64180
64311
|
});
|
|
@@ -64204,8 +64335,8 @@ function isProcessAlive(pid) {
|
|
|
64204
64335
|
}
|
|
64205
64336
|
}
|
|
64206
64337
|
async function listOmoAgentSessionsViaTmux(tmux) {
|
|
64207
|
-
const { spawn:
|
|
64208
|
-
const proc =
|
|
64338
|
+
const { spawn: spawn3 } = await Promise.resolve().then(() => (init_spawn_process(), exports_spawn_process));
|
|
64339
|
+
const proc = spawn3([tmux, "list-sessions", "-F", "#{session_name}"], {
|
|
64209
64340
|
stdout: "pipe",
|
|
64210
64341
|
stderr: "pipe"
|
|
64211
64342
|
});
|
|
@@ -64271,8 +64402,8 @@ async function sweepStaleOmoAgentSessions() {
|
|
|
64271
64402
|
return sweepStaleOmoAgentSessionsWith(deps);
|
|
64272
64403
|
}
|
|
64273
64404
|
// src/shared/tmux/tmux-utils/layout.ts
|
|
64405
|
+
init_bun_spawn_shim();
|
|
64274
64406
|
init_tmux_path_resolver();
|
|
64275
|
-
var {spawn: spawn15 } = globalThis.Bun;
|
|
64276
64407
|
function clamp(value, min, max) {
|
|
64277
64408
|
return Math.max(min, Math.min(max, value));
|
|
64278
64409
|
}
|
|
@@ -64286,7 +64417,7 @@ function calculateMainPaneWidth(windowWidth, options) {
|
|
|
64286
64417
|
return clamp(Math.max(desiredMainPaneWidth, minMainPaneWidth), 0, maxMainPaneWidth);
|
|
64287
64418
|
}
|
|
64288
64419
|
async function applyLayout(tmux, layout, mainPaneSize, deps) {
|
|
64289
|
-
const spawnCommand = deps?.spawnCommand ??
|
|
64420
|
+
const spawnCommand = deps?.spawnCommand ?? spawn2;
|
|
64290
64421
|
const layoutProc = spawnCommand([tmux, "select-layout", layout], {
|
|
64291
64422
|
stdout: "ignore",
|
|
64292
64423
|
stderr: "ignore"
|
|
@@ -64305,7 +64436,7 @@ async function enforceMainPaneWidth(mainPaneId, windowWidth, mainPaneSizeOrOptio
|
|
|
64305
64436
|
return;
|
|
64306
64437
|
const options = typeof mainPaneSizeOrOptions === "number" ? { mainPaneSize: mainPaneSizeOrOptions } : mainPaneSizeOrOptions ?? {};
|
|
64307
64438
|
const mainWidth = calculateMainPaneWidth(windowWidth, options);
|
|
64308
|
-
const proc =
|
|
64439
|
+
const proc = spawn2([tmux, "resize-pane", "-t", mainPaneId, "-x", String(mainWidth)], {
|
|
64309
64440
|
stdout: "ignore",
|
|
64310
64441
|
stderr: "ignore"
|
|
64311
64442
|
});
|
|
@@ -66659,7 +66790,7 @@ async function injectContinuation(args) {
|
|
|
66659
66790
|
log(`[${HOOK_NAME}] Skipped injection: continuation stopped for session`, { sessionID });
|
|
66660
66791
|
return;
|
|
66661
66792
|
}
|
|
66662
|
-
const hasRunningBgTasks = backgroundManager ? backgroundManager.getTasksByParentSession(sessionID).some((task) => task.status === "running") : false;
|
|
66793
|
+
const hasRunningBgTasks = backgroundManager ? backgroundManager.getTasksByParentSession(sessionID).some((task) => task.status === "running" || task.status === "pending") : false;
|
|
66663
66794
|
if (hasRunningBgTasks) {
|
|
66664
66795
|
log(`[${HOOK_NAME}] Skipped injection: background tasks running`, { sessionID });
|
|
66665
66796
|
return;
|
|
@@ -66865,7 +66996,7 @@ async function handleSessionIdle(args) {
|
|
|
66865
66996
|
}
|
|
66866
66997
|
state2.abortDetectedAt = undefined;
|
|
66867
66998
|
}
|
|
66868
|
-
const hasRunningBgTasks = backgroundManager ? backgroundManager.getTasksByParentSession(sessionID).some((task) => task.status === "running") : false;
|
|
66999
|
+
const hasRunningBgTasks = backgroundManager ? backgroundManager.getTasksByParentSession(sessionID).some((task) => task.status === "running" || task.status === "pending") : false;
|
|
66869
67000
|
if (hasRunningBgTasks) {
|
|
66870
67001
|
log(`[${HOOK_NAME}] Skipped: background tasks running`, { sessionID });
|
|
66871
67002
|
return;
|
|
@@ -67655,6 +67786,14 @@ function getDefaultSoundPath(platform2) {
|
|
|
67655
67786
|
return "";
|
|
67656
67787
|
}
|
|
67657
67788
|
}
|
|
67789
|
+
async function runQuietNothrow(command) {
|
|
67790
|
+
const safeCommand = typeof command.nothrow === "function" ? command.nothrow() : command;
|
|
67791
|
+
if (typeof safeCommand.quiet === "function") {
|
|
67792
|
+
await safeCommand.quiet();
|
|
67793
|
+
return;
|
|
67794
|
+
}
|
|
67795
|
+
await safeCommand;
|
|
67796
|
+
}
|
|
67658
67797
|
async function sendSessionNotification(ctx, platform2, title, message) {
|
|
67659
67798
|
switch (platform2) {
|
|
67660
67799
|
case "darwin": {
|
|
@@ -67682,14 +67821,14 @@ async function sendSessionNotification(ctx, platform2, title, message) {
|
|
|
67682
67821
|
return;
|
|
67683
67822
|
const escapedTitle = escapeAppleScriptText(title);
|
|
67684
67823
|
const escapedMessage = escapeAppleScriptText(message);
|
|
67685
|
-
await ctx.$`${osascriptPath} -e ${'display notification "' + escapedMessage + '" with title "' + escapedTitle + '"'}
|
|
67824
|
+
await runQuietNothrow(ctx.$`${osascriptPath} -e ${'display notification "' + escapedMessage + '" with title "' + escapedTitle + '"'}`);
|
|
67686
67825
|
break;
|
|
67687
67826
|
}
|
|
67688
67827
|
case "linux": {
|
|
67689
67828
|
const notifySendPath = await getNotifySendPath();
|
|
67690
67829
|
if (!notifySendPath)
|
|
67691
67830
|
return;
|
|
67692
|
-
await ctx.$`${notifySendPath} ${title} ${message} 2>/dev/null
|
|
67831
|
+
await runQuietNothrow(ctx.$`${notifySendPath} ${title} ${message} 2>/dev/null`);
|
|
67693
67832
|
break;
|
|
67694
67833
|
}
|
|
67695
67834
|
case "win32": {
|
|
@@ -67697,7 +67836,7 @@ async function sendSessionNotification(ctx, platform2, title, message) {
|
|
|
67697
67836
|
if (!powershellPath)
|
|
67698
67837
|
return;
|
|
67699
67838
|
const toastScript = buildWindowsToastScript(title, message);
|
|
67700
|
-
await ctx.$`${powershellPath} -Command ${toastScript}
|
|
67839
|
+
await runQuietNothrow(ctx.$`${powershellPath} -Command ${toastScript}`);
|
|
67701
67840
|
break;
|
|
67702
67841
|
}
|
|
67703
67842
|
}
|
|
@@ -67708,17 +67847,17 @@ async function playSessionNotificationSound(ctx, platform2, soundPath) {
|
|
|
67708
67847
|
const afplayPath = await getAfplayPath();
|
|
67709
67848
|
if (!afplayPath)
|
|
67710
67849
|
return;
|
|
67711
|
-
ctx.$`${afplayPath} ${soundPath}
|
|
67850
|
+
await runQuietNothrow(ctx.$`${afplayPath} ${soundPath}`);
|
|
67712
67851
|
break;
|
|
67713
67852
|
}
|
|
67714
67853
|
case "linux": {
|
|
67715
67854
|
const paplayPath = await getPaplayPath();
|
|
67716
67855
|
if (paplayPath) {
|
|
67717
|
-
ctx.$`${paplayPath} ${soundPath} 2>/dev/null
|
|
67856
|
+
await runQuietNothrow(ctx.$`${paplayPath} ${soundPath} 2>/dev/null`);
|
|
67718
67857
|
} else {
|
|
67719
67858
|
const aplayPath = await getAplayPath();
|
|
67720
67859
|
if (aplayPath) {
|
|
67721
|
-
ctx.$`${aplayPath} ${soundPath} 2>/dev/null
|
|
67860
|
+
await runQuietNothrow(ctx.$`${aplayPath} ${soundPath} 2>/dev/null`);
|
|
67722
67861
|
}
|
|
67723
67862
|
}
|
|
67724
67863
|
break;
|
|
@@ -67728,7 +67867,7 @@ async function playSessionNotificationSound(ctx, platform2, soundPath) {
|
|
|
67728
67867
|
if (!powershellPath)
|
|
67729
67868
|
return;
|
|
67730
67869
|
const escaped = escapePowerShellSingleQuotedText(soundPath);
|
|
67731
|
-
ctx.$`${powershellPath} -Command ${"(New-Object Media.SoundPlayer '" + escaped + "').PlaySync()"}
|
|
67870
|
+
await runQuietNothrow(ctx.$`${powershellPath} -Command ${"(New-Object Media.SoundPlayer '" + escaped + "').PlaySync()"}`);
|
|
67732
67871
|
break;
|
|
67733
67872
|
}
|
|
67734
67873
|
}
|
|
@@ -82640,7 +82779,7 @@ var zod_default = exports_external;
|
|
|
82640
82779
|
import { existsSync as existsSync33 } from "fs";
|
|
82641
82780
|
|
|
82642
82781
|
// src/hooks/comment-checker/cli.ts
|
|
82643
|
-
|
|
82782
|
+
init_bun_spawn_shim();
|
|
82644
82783
|
import { createRequire as createRequire2 } from "module";
|
|
82645
82784
|
import { dirname as dirname6, join as join34 } from "path";
|
|
82646
82785
|
import { existsSync as existsSync32 } from "fs";
|
|
@@ -82846,7 +82985,7 @@ async function runCommentChecker(input, cliPath, customPrompt) {
|
|
|
82846
82985
|
if (customPrompt) {
|
|
82847
82986
|
args.push("--prompt", customPrompt);
|
|
82848
82987
|
}
|
|
82849
|
-
const proc =
|
|
82988
|
+
const proc = spawn2(args, {
|
|
82850
82989
|
stdin: "pipe",
|
|
82851
82990
|
stdout: "pipe",
|
|
82852
82991
|
stderr: "pipe"
|
|
@@ -88153,16 +88292,16 @@ import { join as join57 } from "path";
|
|
|
88153
88292
|
init_logger();
|
|
88154
88293
|
|
|
88155
88294
|
// src/shared/spawn-with-windows-hide.ts
|
|
88156
|
-
|
|
88157
|
-
import { spawn as
|
|
88158
|
-
import { Readable } from "stream";
|
|
88159
|
-
function
|
|
88295
|
+
init_bun_spawn_shim();
|
|
88296
|
+
import { spawn as nodeSpawn2 } from "child_process";
|
|
88297
|
+
import { Readable as Readable2 } from "stream";
|
|
88298
|
+
function toReadableStream2(stream) {
|
|
88160
88299
|
if (!stream) {
|
|
88161
88300
|
return;
|
|
88162
88301
|
}
|
|
88163
|
-
return
|
|
88302
|
+
return Readable2.toWeb(stream);
|
|
88164
88303
|
}
|
|
88165
|
-
function
|
|
88304
|
+
function wrapNodeProcess2(proc) {
|
|
88166
88305
|
let resolveExited;
|
|
88167
88306
|
let exitCode = null;
|
|
88168
88307
|
const exited = new Promise((resolve11) => {
|
|
@@ -88183,8 +88322,8 @@ function wrapNodeProcess(proc) {
|
|
|
88183
88322
|
return exitCode;
|
|
88184
88323
|
},
|
|
88185
88324
|
exited,
|
|
88186
|
-
stdout:
|
|
88187
|
-
stderr:
|
|
88325
|
+
stdout: toReadableStream2(proc.stdout),
|
|
88326
|
+
stderr: toReadableStream2(proc.stderr),
|
|
88188
88327
|
kill(signal) {
|
|
88189
88328
|
try {
|
|
88190
88329
|
if (!signal) {
|
|
@@ -88198,17 +88337,17 @@ function wrapNodeProcess(proc) {
|
|
|
88198
88337
|
}
|
|
88199
88338
|
function spawnWithWindowsHide(command, options) {
|
|
88200
88339
|
if (process.platform !== "win32") {
|
|
88201
|
-
return
|
|
88340
|
+
return spawn2(command, options);
|
|
88202
88341
|
}
|
|
88203
88342
|
const [cmd, ...args] = command;
|
|
88204
|
-
const proc =
|
|
88343
|
+
const proc = nodeSpawn2(cmd, args, {
|
|
88205
88344
|
cwd: options.cwd,
|
|
88206
88345
|
env: options.env,
|
|
88207
|
-
stdio: [options.stdin ?? "
|
|
88346
|
+
stdio: [options.stdin ?? "ignore", options.stdout ?? "pipe", options.stderr ?? "inherit"],
|
|
88208
88347
|
windowsHide: true,
|
|
88209
88348
|
shell: true
|
|
88210
88349
|
});
|
|
88211
|
-
return
|
|
88350
|
+
return wrapNodeProcess2(proc);
|
|
88212
88351
|
}
|
|
88213
88352
|
|
|
88214
88353
|
// src/shared/bun-install.ts
|
|
@@ -99494,6 +99633,7 @@ async function resolveRecentPromptContextForSession(ctx, sessionID) {
|
|
|
99494
99633
|
}
|
|
99495
99634
|
|
|
99496
99635
|
// src/hooks/atlas/boulder-continuation-injector.ts
|
|
99636
|
+
var ACTIVE_BACKGROUND_TASK_STATUSES = new Set(["pending", "running"]);
|
|
99497
99637
|
async function injectBoulderContinuation(input) {
|
|
99498
99638
|
const {
|
|
99499
99639
|
ctx,
|
|
@@ -99508,7 +99648,7 @@ async function injectBoulderContinuation(input) {
|
|
|
99508
99648
|
backgroundManager,
|
|
99509
99649
|
sessionState
|
|
99510
99650
|
} = input;
|
|
99511
|
-
const hasRunningBgTasks = backgroundManager ? backgroundManager.getTasksByParentSession(sessionID).some((t) => t.status
|
|
99651
|
+
const hasRunningBgTasks = backgroundManager ? backgroundManager.getTasksByParentSession(sessionID).some((t) => ACTIVE_BACKGROUND_TASK_STATUSES.has(t.status)) : false;
|
|
99512
99652
|
if (hasRunningBgTasks) {
|
|
99513
99653
|
log(`[${HOOK_NAME7}] Skipped injection: background tasks running`, { sessionID });
|
|
99514
99654
|
return "skipped_background_tasks";
|
|
@@ -102159,6 +102299,10 @@ function isModelInCooldown(model, state3, cooldownSeconds) {
|
|
|
102159
102299
|
function findNextAvailableFallback(state3, fallbackModels, cooldownSeconds) {
|
|
102160
102300
|
for (let i2 = state3.fallbackIndex + 1;i2 < fallbackModels.length; i2++) {
|
|
102161
102301
|
const candidate = fallbackModels[i2];
|
|
102302
|
+
if (candidate === state3.currentModel) {
|
|
102303
|
+
log(`[${HOOK_NAME11}] Skipping fallback model (same as current)`, { model: candidate, index: i2 });
|
|
102304
|
+
continue;
|
|
102305
|
+
}
|
|
102162
102306
|
if (!isModelInCooldown(candidate, state3, cooldownSeconds)) {
|
|
102163
102307
|
return candidate;
|
|
102164
102308
|
}
|
|
@@ -105385,9 +105529,9 @@ function getLanguageId(ext) {
|
|
|
105385
105529
|
return EXT_TO_LANG[ext] || "plaintext";
|
|
105386
105530
|
}
|
|
105387
105531
|
// src/tools/lsp/lsp-process.ts
|
|
105532
|
+
init_bun_spawn_shim();
|
|
105388
105533
|
init_logger();
|
|
105389
|
-
|
|
105390
|
-
import { spawn as nodeSpawn2 } from "child_process";
|
|
105534
|
+
import { spawn as nodeSpawn3 } from "child_process";
|
|
105391
105535
|
import { existsSync as existsSync67, statSync as statSync9 } from "fs";
|
|
105392
105536
|
function shouldUseNodeSpawn() {
|
|
105393
105537
|
return process.platform === "win32";
|
|
@@ -105406,7 +105550,7 @@ function validateCwd(cwd) {
|
|
|
105406
105550
|
return { valid: false, error: `Cannot access working directory: ${cwd} (${err instanceof Error ? err.message : String(err)})` };
|
|
105407
105551
|
}
|
|
105408
105552
|
}
|
|
105409
|
-
function
|
|
105553
|
+
function wrapNodeProcess3(proc) {
|
|
105410
105554
|
let resolveExited;
|
|
105411
105555
|
let exitCode = null;
|
|
105412
105556
|
const exitedPromise = new Promise((resolve14) => {
|
|
@@ -105507,16 +105651,16 @@ function spawnProcess(command, options) {
|
|
|
105507
105651
|
if (shouldUseNodeSpawn()) {
|
|
105508
105652
|
const [cmd, ...args] = command;
|
|
105509
105653
|
log("[LSP] Using Node.js child_process on Windows to avoid Bun spawn segfault");
|
|
105510
|
-
const proc2 =
|
|
105654
|
+
const proc2 = nodeSpawn3(cmd, args, {
|
|
105511
105655
|
cwd: options.cwd,
|
|
105512
105656
|
env: options.env,
|
|
105513
105657
|
stdio: ["pipe", "pipe", "pipe"],
|
|
105514
105658
|
windowsHide: true,
|
|
105515
105659
|
shell: true
|
|
105516
105660
|
});
|
|
105517
|
-
return
|
|
105661
|
+
return wrapNodeProcess3(proc2);
|
|
105518
105662
|
}
|
|
105519
|
-
const proc =
|
|
105663
|
+
const proc = spawn2(command, {
|
|
105520
105664
|
stdin: "pipe",
|
|
105521
105665
|
stdout: "pipe",
|
|
105522
105666
|
stderr: "pipe",
|
|
@@ -105535,7 +105679,7 @@ import { pathToFileURL } from "url";
|
|
|
105535
105679
|
|
|
105536
105680
|
// src/tools/lsp/lsp-client-transport.ts
|
|
105537
105681
|
var import_node = __toESM(require_main(), 1);
|
|
105538
|
-
import { Readable as
|
|
105682
|
+
import { Readable as Readable3, Writable as Writable2 } from "stream";
|
|
105539
105683
|
import { delimiter as delimiter2 } from "path";
|
|
105540
105684
|
init_logger();
|
|
105541
105685
|
|
|
@@ -105579,7 +105723,7 @@ class LSPClientTransport {
|
|
|
105579
105723
|
stderr: ${stderr}` : ""));
|
|
105580
105724
|
}
|
|
105581
105725
|
const stdoutReader = this.proc.stdout.getReader();
|
|
105582
|
-
const nodeReadable = new
|
|
105726
|
+
const nodeReadable = new Readable3({
|
|
105583
105727
|
async read() {
|
|
105584
105728
|
try {
|
|
105585
105729
|
const { done, value } = await stdoutReader.read();
|
|
@@ -105594,7 +105738,7 @@ stderr: ${stderr}` : ""));
|
|
|
105594
105738
|
}
|
|
105595
105739
|
});
|
|
105596
105740
|
const stdin = this.proc.stdin;
|
|
105597
|
-
const nodeWritable = new
|
|
105741
|
+
const nodeWritable = new Writable2({
|
|
105598
105742
|
write(chunk, _encoding, callback) {
|
|
105599
105743
|
try {
|
|
105600
105744
|
stdin.write(chunk);
|
|
@@ -119368,7 +119512,7 @@ function setSgCliPath(path13) {
|
|
|
119368
119512
|
resolvedCliPath2 = path13;
|
|
119369
119513
|
}
|
|
119370
119514
|
// src/tools/ast-grep/cli.ts
|
|
119371
|
-
|
|
119515
|
+
init_bun_spawn_shim();
|
|
119372
119516
|
import { existsSync as existsSync73 } from "fs";
|
|
119373
119517
|
|
|
119374
119518
|
// src/tools/ast-grep/cli-binary-path-resolution.ts
|
|
@@ -119502,7 +119646,7 @@ async function runSg(options) {
|
|
|
119502
119646
|
}
|
|
119503
119647
|
}
|
|
119504
119648
|
const timeout = DEFAULT_TIMEOUT_MS2;
|
|
119505
|
-
const proc =
|
|
119649
|
+
const proc = spawn2([cliPath, ...args], {
|
|
119506
119650
|
stdout: "pipe",
|
|
119507
119651
|
stderr: "pipe"
|
|
119508
119652
|
});
|
|
@@ -119565,7 +119709,7 @@ async function runSg(options) {
|
|
|
119565
119709
|
if (shouldSeparateWritePass && jsonResult.matches.length > 0) {
|
|
119566
119710
|
const writeArgs = args.filter((a) => a !== "--json=compact");
|
|
119567
119711
|
writeArgs.push("--update-all");
|
|
119568
|
-
const writeProc =
|
|
119712
|
+
const writeProc = spawn2([cliPath, ...writeArgs], {
|
|
119569
119713
|
stdout: "pipe",
|
|
119570
119714
|
stderr: "pipe"
|
|
119571
119715
|
});
|
|
@@ -119734,7 +119878,7 @@ ${hint}`;
|
|
|
119734
119878
|
import { resolve as resolve18 } from "path";
|
|
119735
119879
|
|
|
119736
119880
|
// src/shared/ripgrep-cli.ts
|
|
119737
|
-
import { spawnSync as
|
|
119881
|
+
import { spawnSync as spawnSync2 } from "child_process";
|
|
119738
119882
|
import { existsSync as existsSync75 } from "fs";
|
|
119739
119883
|
import { dirname as dirname23, join as join82 } from "path";
|
|
119740
119884
|
|
|
@@ -119844,7 +119988,7 @@ function findExecutable(name) {
|
|
|
119844
119988
|
const isWindows2 = process.platform === "win32";
|
|
119845
119989
|
const cmd = isWindows2 ? "where" : "which";
|
|
119846
119990
|
try {
|
|
119847
|
-
const result =
|
|
119991
|
+
const result = spawnSync2(cmd, [name], { encoding: "utf-8", timeout: 5000 });
|
|
119848
119992
|
if (result.status === 0 && result.stdout.trim()) {
|
|
119849
119993
|
return result.stdout.trim().split(`
|
|
119850
119994
|
`)[0];
|
|
@@ -119920,7 +120064,7 @@ async function resolveGrepCliWithAutoInstall() {
|
|
|
119920
120064
|
}
|
|
119921
120065
|
|
|
119922
120066
|
// src/tools/grep/cli.ts
|
|
119923
|
-
|
|
120067
|
+
init_bun_spawn_shim();
|
|
119924
120068
|
|
|
119925
120069
|
// src/tools/grep/constants.ts
|
|
119926
120070
|
var DEFAULT_MAX_DEPTH = 20;
|
|
@@ -120109,7 +120253,7 @@ async function runRgInternal(options, resolvedCli) {
|
|
|
120109
120253
|
}
|
|
120110
120254
|
const paths = options.paths?.length ? options.paths : ["."];
|
|
120111
120255
|
args.push(...paths);
|
|
120112
|
-
const proc =
|
|
120256
|
+
const proc = spawn2([cli.path, ...args], {
|
|
120113
120257
|
stdout: "pipe",
|
|
120114
120258
|
stderr: "pipe"
|
|
120115
120259
|
});
|
|
@@ -120173,7 +120317,7 @@ async function runRgCountInternal(options, resolvedCli) {
|
|
|
120173
120317
|
const paths = options.paths?.length ? options.paths : ["."];
|
|
120174
120318
|
args.push(...paths);
|
|
120175
120319
|
const timeout = Math.min(options.timeout ?? DEFAULT_TIMEOUT_MS3, DEFAULT_TIMEOUT_MS3);
|
|
120176
|
-
const proc =
|
|
120320
|
+
const proc = spawn2([cli.path, ...args], {
|
|
120177
120321
|
stdout: "pipe",
|
|
120178
120322
|
stderr: "pipe"
|
|
120179
120323
|
});
|
|
@@ -120293,8 +120437,8 @@ function createGrepTools(ctx) {
|
|
|
120293
120437
|
import { resolve as resolve20 } from "path";
|
|
120294
120438
|
|
|
120295
120439
|
// src/tools/glob/cli.ts
|
|
120440
|
+
init_bun_spawn_shim();
|
|
120296
120441
|
import { resolve as resolve19 } from "path";
|
|
120297
|
-
var {spawn: spawn19 } = globalThis.Bun;
|
|
120298
120442
|
|
|
120299
120443
|
// src/tools/glob/constants.ts
|
|
120300
120444
|
var DEFAULT_TIMEOUT_MS4 = 60000;
|
|
@@ -120390,7 +120534,7 @@ async function runRgFilesInternal(options, resolvedCli) {
|
|
|
120390
120534
|
cwd = paths[0] || ".";
|
|
120391
120535
|
command = [cli.path, ...args];
|
|
120392
120536
|
}
|
|
120393
|
-
const proc =
|
|
120537
|
+
const proc = spawn2(command, {
|
|
120394
120538
|
stdout: "pipe",
|
|
120395
120539
|
stderr: "pipe",
|
|
120396
120540
|
cwd
|
|
@@ -122078,7 +122222,8 @@ function createSkillMcpTool(options) {
|
|
|
122078
122222
|
serverName: args.mcp_name,
|
|
122079
122223
|
skillName: found.skill.name,
|
|
122080
122224
|
sessionID,
|
|
122081
|
-
scope: found.skill.scope
|
|
122225
|
+
scope: found.skill.scope,
|
|
122226
|
+
directory: toolContext.directory
|
|
122082
122227
|
};
|
|
122083
122228
|
const context = {
|
|
122084
122229
|
config: found.config,
|
|
@@ -128602,6 +128747,7 @@ function normalizeHashlineEdits(rawEdits) {
|
|
|
128602
128747
|
|
|
128603
128748
|
// src/tools/hashline-edit/formatter-trigger.ts
|
|
128604
128749
|
import path14 from "path";
|
|
128750
|
+
init_bun_spawn_shim();
|
|
128605
128751
|
var cachedFormattersByDirectory = new Map;
|
|
128606
128752
|
function getFormatterCacheKey(directory) {
|
|
128607
128753
|
return path14.resolve(directory);
|
|
@@ -128666,7 +128812,7 @@ async function runFormattersForFile(client2, directory, filePath) {
|
|
|
128666
128812
|
const cmd = buildFormatterCommand(formatter.command, filePath);
|
|
128667
128813
|
try {
|
|
128668
128814
|
log("[formatter-trigger] Running formatter", { command: cmd, file: filePath });
|
|
128669
|
-
const proc =
|
|
128815
|
+
const proc = spawn2(cmd, {
|
|
128670
128816
|
cwd: directory,
|
|
128671
128817
|
env: { ...process.env, ...formatter.environment },
|
|
128672
128818
|
stdout: "ignore",
|
|
@@ -130091,11 +130237,17 @@ async function tryFallbackRetry(args) {
|
|
|
130091
130237
|
}
|
|
130092
130238
|
|
|
130093
130239
|
// src/features/background-agent/process-cleanup.ts
|
|
130094
|
-
|
|
130240
|
+
var _scheduleForcedExitEnabled = true;
|
|
130241
|
+
function scheduleForcedExit(cleanupResult, exitCode, exitAfterCleanup = false) {
|
|
130242
|
+
if (!_scheduleForcedExitEnabled)
|
|
130243
|
+
return;
|
|
130095
130244
|
process.exitCode = exitCode;
|
|
130096
130245
|
const exitTimeout = setTimeout(() => process.exit(), 6000);
|
|
130097
130246
|
Promise.resolve(cleanupResult).finally(() => {
|
|
130098
130247
|
clearTimeout(exitTimeout);
|
|
130248
|
+
if (exitAfterCleanup) {
|
|
130249
|
+
process.exit(exitCode);
|
|
130250
|
+
}
|
|
130099
130251
|
});
|
|
130100
130252
|
}
|
|
130101
130253
|
function registerProcessSignal(signal, handler, exitAfter) {
|
|
@@ -130110,8 +130262,9 @@ function registerProcessSignal(signal, handler, exitAfter) {
|
|
|
130110
130262
|
}
|
|
130111
130263
|
function registerErrorEvent(signal, handler) {
|
|
130112
130264
|
const listener = (error92) => {
|
|
130265
|
+
process.off(signal, listener);
|
|
130113
130266
|
log(`[background-agent] ${signal} received during shutdown cleanup:`, error92);
|
|
130114
|
-
scheduleForcedExit(handler(error92), 1);
|
|
130267
|
+
scheduleForcedExit(handler(error92), 1, true);
|
|
130115
130268
|
};
|
|
130116
130269
|
process.on(signal, listener);
|
|
130117
130270
|
return listener;
|
|
@@ -130502,7 +130655,7 @@ async function checkAndInterruptStaleTasks(args) {
|
|
|
130502
130655
|
const sessionStatus = sessionStatuses?.[sessionID]?.type;
|
|
130503
130656
|
const sessionIsRunning = sessionStatus !== undefined && isActiveSessionStatus(sessionStatus);
|
|
130504
130657
|
const sessionMissing = sessionStatuses !== undefined && sessionStatus === undefined;
|
|
130505
|
-
const
|
|
130658
|
+
const runtime2 = now - startedAt.getTime();
|
|
130506
130659
|
if (sessionMissing) {
|
|
130507
130660
|
task.consecutiveMissedPolls = (task.consecutiveMissedPolls ?? 0) + 1;
|
|
130508
130661
|
} else if (sessionStatuses !== undefined) {
|
|
@@ -130515,13 +130668,13 @@ async function checkAndInterruptStaleTasks(args) {
|
|
|
130515
130668
|
if (sessionMissing && !sessionGone)
|
|
130516
130669
|
continue;
|
|
130517
130670
|
const effectiveTimeout = sessionGone ? sessionGoneTimeoutMs : messageStalenessMs;
|
|
130518
|
-
if (
|
|
130671
|
+
if (runtime2 <= effectiveTimeout)
|
|
130519
130672
|
continue;
|
|
130520
130673
|
if (sessionGone && await verifySessionExists(client2, sessionID, directory)) {
|
|
130521
130674
|
task.consecutiveMissedPolls = 0;
|
|
130522
130675
|
continue;
|
|
130523
130676
|
}
|
|
130524
|
-
const staleMinutes2 = Math.round(
|
|
130677
|
+
const staleMinutes2 = Math.round(runtime2 / 60000);
|
|
130525
130678
|
const reason2 = sessionGone ? "session gone from status registry" : "no activity";
|
|
130526
130679
|
task.status = "cancelled";
|
|
130527
130680
|
task.error = `Stale timeout (${reason2} for ${staleMinutes2}min since start). This is a FINAL cancellation - do NOT create a replacement task. If the timeout is too short, increase 'background_task.${sessionGone ? "sessionGoneTimeoutMs" : "staleTimeoutMs"}' in .opencode/${CONFIG_BASENAME}.json.`;
|
|
@@ -130542,7 +130695,7 @@ async function checkAndInterruptStaleTasks(args) {
|
|
|
130542
130695
|
}
|
|
130543
130696
|
if (sessionIsRunning)
|
|
130544
130697
|
continue;
|
|
130545
|
-
if (
|
|
130698
|
+
if (runtime2 < MIN_RUNTIME_BEFORE_STALE_MS)
|
|
130546
130699
|
continue;
|
|
130547
130700
|
const timeSinceLastUpdate = now - task.progress.lastUpdate.getTime();
|
|
130548
130701
|
const effectiveStaleTimeout = sessionGone ? sessionGoneTimeoutMs : staleTimeoutMs;
|
|
@@ -130950,6 +131103,7 @@ class BackgroundManager {
|
|
|
130950
131103
|
}
|
|
130951
131104
|
spawnReservation.commit();
|
|
130952
131105
|
this.markPreStartDescendantReservation(task);
|
|
131106
|
+
this.updateBackgroundTaskMarker(input.parentSessionId);
|
|
130953
131107
|
this.processKey(key);
|
|
130954
131108
|
return { ...task };
|
|
130955
131109
|
} catch (error92) {
|
|
@@ -130997,6 +131151,7 @@ class BackgroundManager {
|
|
|
130997
131151
|
if (item.task.sessionId) {
|
|
130998
131152
|
await this.abortSessionWithLogging(item.task.sessionId, "startTask error cleanup");
|
|
130999
131153
|
}
|
|
131154
|
+
this.updateBackgroundTaskMarker(item.task.parentSessionId);
|
|
131000
131155
|
this.markForNotification(item.task);
|
|
131001
131156
|
this.enqueueNotificationForParent(item.task.parentSessionId, () => this.notifyParentSession(item.task)).catch((err) => {
|
|
131002
131157
|
log("[background-agent] Failed to notify on startTask error:", err);
|
|
@@ -131251,6 +131406,15 @@ The fallback retry session is now created and can be inspected directly.
|
|
|
131251
131406
|
}
|
|
131252
131407
|
return tasks;
|
|
131253
131408
|
}
|
|
131409
|
+
updateBackgroundTaskMarker(parentSessionID) {
|
|
131410
|
+
const tasks = this.getTasksByParentSession(parentSessionID);
|
|
131411
|
+
const activeTasks = tasks.filter((t) => t.status === "running" || t.status === "pending");
|
|
131412
|
+
if (activeTasks.length > 0) {
|
|
131413
|
+
setContinuationMarkerSource(this.directory, parentSessionID, "background-task", "active", `${activeTasks.length} background task(s) active`);
|
|
131414
|
+
} else {
|
|
131415
|
+
setContinuationMarkerSource(this.directory, parentSessionID, "background-task", "idle");
|
|
131416
|
+
}
|
|
131417
|
+
}
|
|
131254
131418
|
getAllDescendantTasks(sessionID) {
|
|
131255
131419
|
const result = [];
|
|
131256
131420
|
const directChildren = this.getTasksByParentSession(sessionID);
|
|
@@ -131831,6 +131995,9 @@ The fallback retry session is now created and can be inspected directly.
|
|
|
131831
131995
|
if (task.sessionId) {
|
|
131832
131996
|
SessionCategoryRegistry.remove(task.sessionId);
|
|
131833
131997
|
}
|
|
131998
|
+
if (task.parentSessionId) {
|
|
131999
|
+
this.updateBackgroundTaskMarker(task.parentSessionId);
|
|
132000
|
+
}
|
|
131834
132001
|
this.markForNotification(task);
|
|
131835
132002
|
this.enqueueNotificationForParent(task.parentSessionId, () => this.notifyParentSession(task)).catch((err) => {
|
|
131836
132003
|
log("[background-agent] Error in notifyParentSession for errored task:", { taskId: task.id, error: err });
|
|
@@ -132065,6 +132232,9 @@ ${originalText}`;
|
|
|
132065
132232
|
SessionCategoryRegistry.remove(task.sessionId);
|
|
132066
132233
|
}
|
|
132067
132234
|
removeTaskToastTracking(task.id);
|
|
132235
|
+
if (task.parentSessionId) {
|
|
132236
|
+
this.updateBackgroundTaskMarker(task.parentSessionId);
|
|
132237
|
+
}
|
|
132068
132238
|
if (options?.skipNotification) {
|
|
132069
132239
|
this.cleanupPendingByParent(task);
|
|
132070
132240
|
this.scheduleTaskRemoval(task.id);
|
|
@@ -132144,6 +132314,9 @@ ${originalText}`;
|
|
|
132144
132314
|
await this.abortSessionWithLogging(task.sessionId, `task completion (${source})`);
|
|
132145
132315
|
SessionCategoryRegistry.remove(task.sessionId);
|
|
132146
132316
|
}
|
|
132317
|
+
if (task.parentSessionId) {
|
|
132318
|
+
this.updateBackgroundTaskMarker(task.parentSessionId);
|
|
132319
|
+
}
|
|
132147
132320
|
try {
|
|
132148
132321
|
await this.enqueueNotificationForParent(task.parentSessionId, () => this.notifyParentSession(task));
|
|
132149
132322
|
log(`[background-agent] Task completed via ${source}:`, task.id);
|
|
@@ -132327,6 +132500,9 @@ ${originalText}`;
|
|
|
132327
132500
|
}
|
|
132328
132501
|
}
|
|
132329
132502
|
this.cleanupPendingByParent(task);
|
|
132503
|
+
if (task.parentSessionId) {
|
|
132504
|
+
this.updateBackgroundTaskMarker(task.parentSessionId);
|
|
132505
|
+
}
|
|
132330
132506
|
this.markForNotification(task);
|
|
132331
132507
|
this.enqueueNotificationForParent(task.parentSessionId, () => this.notifyParentSession(task)).catch((err) => {
|
|
132332
132508
|
log("[background-agent] Error in notifyParentSession for stale-pruned task:", { taskId: task.id, error: err });
|
|
@@ -132381,6 +132557,9 @@ ${originalText}`;
|
|
|
132381
132557
|
if (task.sessionId) {
|
|
132382
132558
|
SessionCategoryRegistry.remove(task.sessionId);
|
|
132383
132559
|
}
|
|
132560
|
+
if (task.parentSessionId) {
|
|
132561
|
+
this.updateBackgroundTaskMarker(task.parentSessionId);
|
|
132562
|
+
}
|
|
132384
132563
|
this.markForNotification(task);
|
|
132385
132564
|
this.enqueueNotificationForParent(task.parentSessionId, () => this.notifyParentSession(task)).catch((err) => {
|
|
132386
132565
|
log("[background-agent] Error in notifyParentSession for crashed task:", { taskId: task.id, error: err });
|
|
@@ -132824,7 +133003,7 @@ async function findAvailablePort2(startPort = DEFAULT_PORT) {
|
|
|
132824
133003
|
}
|
|
132825
133004
|
|
|
132826
133005
|
// src/features/mcp-oauth/oauth-authorization-flow.ts
|
|
132827
|
-
import { spawn as
|
|
133006
|
+
import { spawn as spawn3 } from "child_process";
|
|
132828
133007
|
import { createHash as createHash2, randomBytes as randomBytes2 } from "crypto";
|
|
132829
133008
|
import { createServer } from "http";
|
|
132830
133009
|
function generateCodeVerifier() {
|
|
@@ -132905,7 +133084,7 @@ function openBrowser(url3) {
|
|
|
132905
133084
|
args = [url3];
|
|
132906
133085
|
}
|
|
132907
133086
|
try {
|
|
132908
|
-
const child =
|
|
133087
|
+
const child = spawn3(command, args, { stdio: "ignore", detached: true });
|
|
132909
133088
|
child.on("error", () => {});
|
|
132910
133089
|
child.unref();
|
|
132911
133090
|
} catch {}
|
|
@@ -137489,7 +137668,8 @@ async function createStdioClient(params) {
|
|
|
137489
137668
|
command,
|
|
137490
137669
|
args,
|
|
137491
137670
|
env: mergedEnv,
|
|
137492
|
-
stderr: "ignore"
|
|
137671
|
+
stderr: "ignore",
|
|
137672
|
+
...info.directory ? { cwd: info.directory } : {}
|
|
137493
137673
|
});
|
|
137494
137674
|
const client2 = stdioClientDependencies.createClient({ name: `skill-mcp-${info.skillName}-${info.serverName}`, version: "1.0.0" }, { capabilities: {} });
|
|
137495
137675
|
try {
|
|
@@ -137795,7 +137975,7 @@ function createModelFallbackControllerAccessor() {
|
|
|
137795
137975
|
};
|
|
137796
137976
|
}
|
|
137797
137977
|
// src/features/tmux-subagent/pane-state-querier.ts
|
|
137798
|
-
|
|
137978
|
+
init_bun_spawn_shim();
|
|
137799
137979
|
|
|
137800
137980
|
// src/features/tmux-subagent/pane-state-parser.ts
|
|
137801
137981
|
var MANDATORY_PANE_FIELD_COUNT = 8;
|
|
@@ -137884,7 +138064,7 @@ async function queryWindowState(sourcePaneId) {
|
|
|
137884
138064
|
const tmux3 = await getTmuxPath();
|
|
137885
138065
|
if (!tmux3)
|
|
137886
138066
|
return null;
|
|
137887
|
-
const proc =
|
|
138067
|
+
const proc = spawn2([
|
|
137888
138068
|
tmux3,
|
|
137889
138069
|
"list-panes",
|
|
137890
138070
|
"-t",
|
|
@@ -139420,7 +139600,7 @@ function resolveGateway(config4, event) {
|
|
|
139420
139600
|
}
|
|
139421
139601
|
|
|
139422
139602
|
// src/openclaw/dispatcher.ts
|
|
139423
|
-
|
|
139603
|
+
init_bun_spawn_shim();
|
|
139424
139604
|
var DEFAULT_HTTP_TIMEOUT_MS = 1e4;
|
|
139425
139605
|
var DEFAULT_COMMAND_TIMEOUT_MS = 5000;
|
|
139426
139606
|
var MIN_COMMAND_TIMEOUT_MS = 100;
|
|
@@ -139554,7 +139734,7 @@ async function wakeCommandGateway(gatewayName, gatewayConfig, variables) {
|
|
|
139554
139734
|
return _match;
|
|
139555
139735
|
return shellEscapeArg(value);
|
|
139556
139736
|
});
|
|
139557
|
-
const proc =
|
|
139737
|
+
const proc = spawn2(["sh", "-c", interpolated], {
|
|
139558
139738
|
env: { ...process.env },
|
|
139559
139739
|
stdout: "pipe",
|
|
139560
139740
|
stderr: "ignore",
|
|
@@ -139604,7 +139784,7 @@ function terminateCommandProcess(proc, signal) {
|
|
|
139604
139784
|
}
|
|
139605
139785
|
|
|
139606
139786
|
// src/openclaw/tmux.ts
|
|
139607
|
-
|
|
139787
|
+
init_bun_spawn_shim();
|
|
139608
139788
|
function getCurrentTmuxSession() {
|
|
139609
139789
|
const env = process.env.TMUX;
|
|
139610
139790
|
if (!env)
|
|
@@ -139614,7 +139794,7 @@ function getCurrentTmuxSession() {
|
|
|
139614
139794
|
}
|
|
139615
139795
|
async function captureTmuxPane(paneId, lines = 15) {
|
|
139616
139796
|
try {
|
|
139617
|
-
const proc =
|
|
139797
|
+
const proc = spawn2(["tmux", "capture-pane", "-p", "-t", paneId, "-S", `-${lines}`], {
|
|
139618
139798
|
stdout: "pipe",
|
|
139619
139799
|
stderr: "ignore"
|
|
139620
139800
|
});
|
|
@@ -139630,7 +139810,7 @@ async function captureTmuxPane(paneId, lines = 15) {
|
|
|
139630
139810
|
}
|
|
139631
139811
|
async function isTmuxAvailable() {
|
|
139632
139812
|
try {
|
|
139633
|
-
const proc =
|
|
139813
|
+
const proc = spawn2(["tmux", "-V"], {
|
|
139634
139814
|
stdout: "ignore",
|
|
139635
139815
|
stderr: "ignore"
|
|
139636
139816
|
});
|
|
@@ -140095,8 +140275,8 @@ function markReplyListenerStopped(state3, error92) {
|
|
|
140095
140275
|
}
|
|
140096
140276
|
|
|
140097
140277
|
// src/openclaw/reply-listener-process.ts
|
|
140278
|
+
init_bun_spawn_shim();
|
|
140098
140279
|
import { readFileSync as readFileSync61 } from "fs";
|
|
140099
|
-
var {spawn: spawn25 } = globalThis.Bun;
|
|
140100
140280
|
var REPLY_LISTENER_DAEMON_IDENTITY_MARKER = "--openclaw-reply-listener-daemon";
|
|
140101
140281
|
var REPLY_LISTENER_DAEMON_ENV_ALLOWLIST = [
|
|
140102
140282
|
"PATH",
|
|
@@ -140154,7 +140334,7 @@ async function isReplyListenerDaemonProcess(pid) {
|
|
|
140154
140334
|
const cmdline = readFileSync61(`/proc/${pid}/cmdline`, "utf-8");
|
|
140155
140335
|
return cmdline.includes(REPLY_LISTENER_DAEMON_IDENTITY_MARKER);
|
|
140156
140336
|
}
|
|
140157
|
-
const processInfo =
|
|
140337
|
+
const processInfo = spawn2(["ps", "-p", String(pid), "-o", "args="], {
|
|
140158
140338
|
stdout: "pipe",
|
|
140159
140339
|
stderr: "ignore"
|
|
140160
140340
|
});
|
|
@@ -140168,9 +140348,9 @@ async function isReplyListenerDaemonProcess(pid) {
|
|
|
140168
140348
|
}
|
|
140169
140349
|
|
|
140170
140350
|
// src/openclaw/reply-listener-spawn.ts
|
|
140171
|
-
|
|
140351
|
+
init_bun_spawn_shim();
|
|
140172
140352
|
function spawnReplyListenerDaemon(daemonScript, startupToken) {
|
|
140173
|
-
return
|
|
140353
|
+
return spawn2(["bun", "run", daemonScript, REPLY_LISTENER_DAEMON_IDENTITY_MARKER], {
|
|
140174
140354
|
detached: true,
|
|
140175
140355
|
stdio: ["ignore", "ignore", "ignore"],
|
|
140176
140356
|
cwd: process.cwd(),
|
|
@@ -153320,7 +153500,6 @@ init_agent_display_names();
|
|
|
153320
153500
|
init_agent_display_names();
|
|
153321
153501
|
|
|
153322
153502
|
// src/plugin/ultrawork-db-model-override.ts
|
|
153323
|
-
import { Database } from "bun:sqlite";
|
|
153324
153503
|
import { join as join101 } from "path";
|
|
153325
153504
|
import { existsSync as existsSync91 } from "fs";
|
|
153326
153505
|
function getDbPath() {
|
|
@@ -153399,7 +153578,13 @@ function retryViaMicrotask(db, messageId, targetModel, variant, attempt) {
|
|
|
153399
153578
|
});
|
|
153400
153579
|
}
|
|
153401
153580
|
function scheduleDeferredModelOverride(messageId, targetModel, variant) {
|
|
153402
|
-
queueMicrotask(() => {
|
|
153581
|
+
queueMicrotask(async () => {
|
|
153582
|
+
const sqliteModule = await import("bun:sqlite").catch(() => null);
|
|
153583
|
+
const Database = sqliteModule?.Database;
|
|
153584
|
+
if (typeof Database !== "function") {
|
|
153585
|
+
log("[ultrawork-db-override] bun:sqlite unavailable, skipping deferred override", { messageId });
|
|
153586
|
+
return;
|
|
153587
|
+
}
|
|
153403
153588
|
const dbPath = getDbPath();
|
|
153404
153589
|
if (!existsSync91(dbPath)) {
|
|
153405
153590
|
log("[ultrawork-db-override] DB not found, skipping deferred override");
|