opencode-mux 0.1.0
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/LICENSE +21 -0
- package/README.md +173 -0
- package/dist/args.d.ts +12 -0
- package/dist/args.js +114 -0
- package/dist/args.js.map +1 -0
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +15 -0
- package/dist/bin.js.map +1 -0
- package/dist/cli.d.ts +62 -0
- package/dist/cli.js +300 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +28 -0
- package/dist/config.js +119 -0
- package/dist/config.js.map +1 -0
- package/dist/exec.d.ts +12 -0
- package/dist/exec.js +28 -0
- package/dist/exec.js.map +1 -0
- package/dist/server.d.ts +20 -0
- package/dist/server.js +29 -0
- package/dist/server.js.map +1 -0
- package/dist/session.d.ts +22 -0
- package/dist/session.js +42 -0
- package/dist/session.js.map +1 -0
- package/dist/theme/builtin.d.ts +10 -0
- package/dist/theme/builtin.js +39 -0
- package/dist/theme/builtin.js.map +1 -0
- package/dist/theme.d.ts +26 -0
- package/dist/theme.js +250 -0
- package/dist/theme.js.map +1 -0
- package/dist/tmux.d.ts +37 -0
- package/dist/tmux.js +108 -0
- package/dist/tmux.js.map +1 -0
- package/dist/tracker.d.ts +49 -0
- package/dist/tracker.js +75 -0
- package/dist/tracker.js.map +1 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +2 -0
- package/dist/version.js.map +1 -0
- package/dist/watch.d.ts +34 -0
- package/dist/watch.js +166 -0
- package/dist/watch.js.map +1 -0
- package/package.json +33 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { appendFileSync, closeSync, mkdirSync, openSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
import { parentFromPassThrough, parseArgs } from "./args.js";
|
|
6
|
+
import { loadConfig } from "./config.js";
|
|
7
|
+
import { nodeExec } from "./exec.js";
|
|
8
|
+
import { connectServer } from "./server.js";
|
|
9
|
+
import { currentPane, shellQuote, tmuxAdapter } from "./tmux.js";
|
|
10
|
+
import { createThemeStyles } from "./theme.js";
|
|
11
|
+
import { PaneTracker } from "./tracker.js";
|
|
12
|
+
import { VERSION } from "./version.js";
|
|
13
|
+
import { createWatcher, defaultPaneArgv } from "./watch.js";
|
|
14
|
+
/** Real subprocess launcher with optional file redirects (never throws). */
|
|
15
|
+
export function nodeSpawn(command, args, opts = {}) {
|
|
16
|
+
let outFd;
|
|
17
|
+
let errFd;
|
|
18
|
+
try {
|
|
19
|
+
outFd = opts.stdoutFile !== undefined ? openSync(opts.stdoutFile, "a") : undefined;
|
|
20
|
+
errFd = opts.stderrFile !== undefined ? openSync(opts.stderrFile, "a") : undefined;
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
try {
|
|
24
|
+
if (outFd !== undefined)
|
|
25
|
+
closeSync(outFd);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// already closed
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
pid: null,
|
|
32
|
+
done: Promise.resolve({ ok: false, code: null, error: String(error), stdout: "", stderr: "" }),
|
|
33
|
+
kill: () => { },
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
const child = spawn(command, args, {
|
|
37
|
+
stdio: opts.inherit ? "inherit" : ["ignore", outFd ?? "pipe", errFd ?? "pipe"],
|
|
38
|
+
});
|
|
39
|
+
let stdout = "";
|
|
40
|
+
let stderr = "";
|
|
41
|
+
child.stdout?.setEncoding("utf8");
|
|
42
|
+
child.stderr?.setEncoding("utf8");
|
|
43
|
+
child.stdout?.on("data", (chunk) => {
|
|
44
|
+
stdout += chunk;
|
|
45
|
+
});
|
|
46
|
+
child.stderr?.on("data", (chunk) => {
|
|
47
|
+
stderr += chunk;
|
|
48
|
+
});
|
|
49
|
+
const closeFds = () => {
|
|
50
|
+
try {
|
|
51
|
+
if (outFd !== undefined)
|
|
52
|
+
closeSync(outFd);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
// already closed
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
if (errFd !== undefined)
|
|
59
|
+
closeSync(errFd);
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// already closed
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
const done = new Promise((resolve) => {
|
|
66
|
+
child.on("error", (error) => {
|
|
67
|
+
closeFds();
|
|
68
|
+
resolve({ ok: false, code: null, error: String(error), stdout, stderr });
|
|
69
|
+
});
|
|
70
|
+
child.on("close", (code) => {
|
|
71
|
+
closeFds();
|
|
72
|
+
resolve({ ok: code === 0, code, error: null, stdout, stderr });
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
return {
|
|
76
|
+
pid: child.pid ?? null,
|
|
77
|
+
done,
|
|
78
|
+
kill: () => {
|
|
79
|
+
child.kill();
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
export function usageText() {
|
|
84
|
+
return [
|
|
85
|
+
"opencode-mux — drop-in opencode wrapper that opens tmux panes for subagent sessions",
|
|
86
|
+
"",
|
|
87
|
+
"Usage:",
|
|
88
|
+
" opencode-mux [mux options] [opencode arguments...]",
|
|
89
|
+
"",
|
|
90
|
+
"Mux options:",
|
|
91
|
+
" --config <path> config file (default ~/.config/opencode-mux.conf)",
|
|
92
|
+
" --layout <name> pane layout: main-vertical | main-horizontal | tiled | even-horizontal | even-vertical (default main-vertical)",
|
|
93
|
+
" --main-pane-size <pct> main pane size for main-* layouts, percent of window (20-80, default 60)",
|
|
94
|
+
" --close <mode> pane lifecycle: auto | keep (default auto)",
|
|
95
|
+
" --grace <seconds> close delay after a session finishes (default 1)",
|
|
96
|
+
" --parent <id> only watch children of this session",
|
|
97
|
+
" --session-name <name> tmux session name (default mux)",
|
|
98
|
+
" -h, --help show this help and exit",
|
|
99
|
+
" --version print the version and exit",
|
|
100
|
+
"",
|
|
101
|
+
"All other arguments are passed through to opencode unchanged.",
|
|
102
|
+
"",
|
|
103
|
+
].join("\n");
|
|
104
|
+
}
|
|
105
|
+
export function watchLogPath(env) {
|
|
106
|
+
const state = env.XDG_STATE_HOME !== undefined && env.XDG_STATE_HOME !== "" ? env.XDG_STATE_HOME : join(homedir(), ".local", "state");
|
|
107
|
+
return join(state, "opencode-mux", "watch.log");
|
|
108
|
+
}
|
|
109
|
+
/** Parses "2.0.5" or "opencode v2.0.5" into the major version; junk → null. */
|
|
110
|
+
export function parseMajorVersion(version) {
|
|
111
|
+
const match = /(?:^|\s)v?(\d+)\./.exec(version.trim());
|
|
112
|
+
return match === null ? null : Number(match[1]);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Maps an opencode version to the client protocol generation it speaks: 2.0.0–2.0.5
|
|
116
|
+
* serve GET /api/status (legacy), 2.0.6+ serve GET /api/info (new). Each client
|
|
117
|
+
* generation's Service.ensure() probes only its own endpoint and stops a mismatched
|
|
118
|
+
* registered server, so the binary's generation must select the matching client.
|
|
119
|
+
* Returns null for unsupported or unparseable versions.
|
|
120
|
+
*/
|
|
121
|
+
export function serviceGeneration(version) {
|
|
122
|
+
const match = /(?:^|\s)v?(\d+)\.(\d+)\.(\d+)/.exec(version.trim());
|
|
123
|
+
if (match === null)
|
|
124
|
+
return null;
|
|
125
|
+
const major = Number(match[1]);
|
|
126
|
+
if (major !== 2)
|
|
127
|
+
return null;
|
|
128
|
+
const minor = Number(match[2]);
|
|
129
|
+
return minor === 0 && Number(match[3]) < 6 ? "legacy" : "new";
|
|
130
|
+
}
|
|
131
|
+
/** Re-emits resolved CLI flags as mux argv (for the watcher child process). */
|
|
132
|
+
export function flagsToArgv(flags) {
|
|
133
|
+
const argv = [];
|
|
134
|
+
if (flags.layout !== undefined)
|
|
135
|
+
argv.push("--layout", flags.layout);
|
|
136
|
+
if (flags.mainPaneSize !== undefined)
|
|
137
|
+
argv.push("--main-pane-size", String(flags.mainPaneSize));
|
|
138
|
+
if (flags.closePanes !== undefined)
|
|
139
|
+
argv.push("--close", flags.closePanes);
|
|
140
|
+
if (flags.graceSeconds !== undefined)
|
|
141
|
+
argv.push("--grace", String(flags.graceSeconds));
|
|
142
|
+
if (flags.parent !== undefined)
|
|
143
|
+
argv.push("--parent", flags.parent ?? "");
|
|
144
|
+
if (flags.sessionName !== undefined)
|
|
145
|
+
argv.push("--session-name", flags.sessionName);
|
|
146
|
+
return argv;
|
|
147
|
+
}
|
|
148
|
+
/** argv for the spawned watcher process: marker + config path + explicit flags. */
|
|
149
|
+
export function buildWatcherArgv(opts) {
|
|
150
|
+
return [
|
|
151
|
+
"--mux-watch",
|
|
152
|
+
...(opts.configPath !== undefined ? ["--config", opts.configPath] : []),
|
|
153
|
+
...flagsToArgv(opts.flags),
|
|
154
|
+
];
|
|
155
|
+
}
|
|
156
|
+
/** argv the re-exec'd instance runs inside the fresh tmux session. */
|
|
157
|
+
export function buildReexecArgv(entryPath, originalArgv) {
|
|
158
|
+
return [entryPath, ...originalArgv];
|
|
159
|
+
}
|
|
160
|
+
/** tmux new-session argv that boots the detached session and its command. */
|
|
161
|
+
export function buildNewSessionCommand(input) {
|
|
162
|
+
return [
|
|
163
|
+
"new-session",
|
|
164
|
+
"-d",
|
|
165
|
+
"-e",
|
|
166
|
+
"MUX_OWNED_SESSION=1",
|
|
167
|
+
"-s",
|
|
168
|
+
input.sessionName,
|
|
169
|
+
"-c",
|
|
170
|
+
input.cwd,
|
|
171
|
+
...buildReexecArgv(input.entryPath, input.originalArgv).map(shellQuote),
|
|
172
|
+
];
|
|
173
|
+
}
|
|
174
|
+
async function resolveConfig(parsed, env) {
|
|
175
|
+
if (parsed.flags.parent === undefined) {
|
|
176
|
+
const inferred = parentFromPassThrough(parsed.passThrough);
|
|
177
|
+
if (inferred !== null)
|
|
178
|
+
parsed.flags.parent = inferred;
|
|
179
|
+
}
|
|
180
|
+
return loadConfig({ path: parsed.configPath, flags: parsed.flags, env });
|
|
181
|
+
}
|
|
182
|
+
async function runWatch(parsed, env, deps, generation) {
|
|
183
|
+
const targetPane = currentPane(env);
|
|
184
|
+
if (targetPane === null) {
|
|
185
|
+
process.stderr.write("opencode-mux: watcher requires TMUX_PANE (run inside tmux)\n");
|
|
186
|
+
return 1;
|
|
187
|
+
}
|
|
188
|
+
const config = await resolveConfig(parsed, env);
|
|
189
|
+
const logFile = watchLogPath(env);
|
|
190
|
+
mkdirSync(dirname(logFile), { recursive: true });
|
|
191
|
+
const append = (line) => {
|
|
192
|
+
try {
|
|
193
|
+
appendFileSync(logFile, `[${new Date().toISOString()}] ${line}\n`);
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
// log failures are non-fatal
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
const { client } = await (deps.connectServer ?? connectServer)({ generation });
|
|
200
|
+
const tracker = new PaneTracker({ graceMs: config.graceSeconds * 1000, closePanes: config.closePanes });
|
|
201
|
+
const watcher = createWatcher({
|
|
202
|
+
client,
|
|
203
|
+
tmux: tmuxAdapter(nodeExec()),
|
|
204
|
+
tracker,
|
|
205
|
+
log: append,
|
|
206
|
+
targetPane,
|
|
207
|
+
layout: config.layout,
|
|
208
|
+
mainPaneSize: config.mainPaneSize,
|
|
209
|
+
themeStyles: createThemeStyles({ env, cwd: deps.cwd ?? process.cwd() }),
|
|
210
|
+
parentID: config.parent,
|
|
211
|
+
paneArgv: defaultPaneArgv,
|
|
212
|
+
tickEveryMs: 500,
|
|
213
|
+
});
|
|
214
|
+
const controller = new AbortController();
|
|
215
|
+
const onSignal = () => controller.abort();
|
|
216
|
+
process.on("SIGINT", onSignal);
|
|
217
|
+
process.on("SIGTERM", onSignal);
|
|
218
|
+
try {
|
|
219
|
+
await watcher.start(controller.signal);
|
|
220
|
+
}
|
|
221
|
+
finally {
|
|
222
|
+
process.off("SIGINT", onSignal);
|
|
223
|
+
process.off("SIGTERM", onSignal);
|
|
224
|
+
}
|
|
225
|
+
return 0;
|
|
226
|
+
}
|
|
227
|
+
export async function main(argv, deps) {
|
|
228
|
+
const parsed = parseArgs(argv);
|
|
229
|
+
if (parsed.help) {
|
|
230
|
+
process.stdout.write(usageText());
|
|
231
|
+
return 0;
|
|
232
|
+
}
|
|
233
|
+
if (parsed.version) {
|
|
234
|
+
process.stdout.write(`opencode-mux ${VERSION}\n`);
|
|
235
|
+
return 0;
|
|
236
|
+
}
|
|
237
|
+
const tmuxCommand = deps.tmuxCommand ?? "tmux";
|
|
238
|
+
const opencodeCommand = deps.opencodeCommand ?? "opencode";
|
|
239
|
+
const nodeCommand = deps.nodeCommand ?? "node";
|
|
240
|
+
const env = deps.env;
|
|
241
|
+
const tmuxCheck = await deps.spawn(tmuxCommand, ["-V"]).done;
|
|
242
|
+
if (!tmuxCheck.ok) {
|
|
243
|
+
process.stderr.write("opencode-mux: tmux is required but was not found on PATH.\nInstall it with: apt install tmux (Debian/Ubuntu) or brew install tmux (macOS)\n");
|
|
244
|
+
return 1;
|
|
245
|
+
}
|
|
246
|
+
const opencodeCheck = await deps.spawn(opencodeCommand, ["--version"]).done;
|
|
247
|
+
if (!opencodeCheck.ok) {
|
|
248
|
+
process.stderr.write("opencode-mux: opencode is required but was not found on PATH.\nInstall or upgrade it: https://opencode.ai/v2/docs/\n");
|
|
249
|
+
return 1;
|
|
250
|
+
}
|
|
251
|
+
const versionText = opencodeCheck.stdout.trim() || opencodeCheck.stderr.trim();
|
|
252
|
+
if (parseMajorVersion(versionText) !== 2) {
|
|
253
|
+
process.stderr.write(`opencode-mux: opencode v2 is required, found version "${versionText || "unknown"}".\nUpgrade it: https://opencode.ai/v2/docs/\n`);
|
|
254
|
+
return 1;
|
|
255
|
+
}
|
|
256
|
+
const generation = serviceGeneration(versionText);
|
|
257
|
+
if (generation === null) {
|
|
258
|
+
process.stderr.write(`opencode-mux: unsupported opencode version "${versionText || "unknown"}" (expected a 2.x.y release).\nUpgrade it: https://opencode.ai/v2/docs/\n`);
|
|
259
|
+
return 1;
|
|
260
|
+
}
|
|
261
|
+
if (parsed.watch)
|
|
262
|
+
return runWatch(parsed, env, deps, generation);
|
|
263
|
+
const config = await resolveConfig(parsed, env);
|
|
264
|
+
const insideTmux = env.TMUX !== undefined && env.TMUX !== "" && env.TMUX_PANE !== undefined && env.TMUX_PANE !== "";
|
|
265
|
+
if (!insideTmux) {
|
|
266
|
+
const created = await deps
|
|
267
|
+
.spawn(tmuxCommand, buildNewSessionCommand({
|
|
268
|
+
entryPath: deps.entryPath,
|
|
269
|
+
originalArgv: argv,
|
|
270
|
+
sessionName: config.sessionName,
|
|
271
|
+
cwd: deps.cwd ?? process.cwd(),
|
|
272
|
+
}))
|
|
273
|
+
.done;
|
|
274
|
+
if (!created.ok) {
|
|
275
|
+
process.stderr.write(`opencode-mux: failed to start tmux session: ${created.error ?? "unknown error"}\n`);
|
|
276
|
+
return 1;
|
|
277
|
+
}
|
|
278
|
+
// Session-scoped appearance, so the mux looks coherent regardless of the
|
|
279
|
+
// user's global config. These touch only our own session — never -g.
|
|
280
|
+
// Failures are non-fatal: attach proceeds and the exit code is unchanged.
|
|
281
|
+
await deps.spawn(tmuxCommand, ["set-option", "-t", config.sessionName, "status", "off"]).done;
|
|
282
|
+
await deps.spawn(tmuxCommand, ["set-option", "-t", config.sessionName, "mouse", "on"]).done;
|
|
283
|
+
const attached = await deps.spawn(tmuxCommand, ["attach", "-t", config.sessionName], { inherit: true }).done;
|
|
284
|
+
return attached.ok ? 0 : attached.code ?? 1;
|
|
285
|
+
}
|
|
286
|
+
const logFile = watchLogPath(env);
|
|
287
|
+
mkdirSync(dirname(logFile), { recursive: true });
|
|
288
|
+
const watcher = deps.spawn(nodeCommand, [deps.entryPath, ...buildWatcherArgv({ configPath: parsed.configPath, flags: parsed.flags })], {
|
|
289
|
+
stdoutFile: logFile,
|
|
290
|
+
stderrFile: logFile,
|
|
291
|
+
});
|
|
292
|
+
const tui = await deps.spawn(opencodeCommand, parsed.passThrough, { inherit: true }).done;
|
|
293
|
+
watcher.kill();
|
|
294
|
+
await watcher.done;
|
|
295
|
+
if (env.MUX_OWNED_SESSION === "1") {
|
|
296
|
+
await deps.spawn(tmuxCommand, ["kill-session", "-t", config.sessionName]).done;
|
|
297
|
+
}
|
|
298
|
+
return tui.ok ? 0 : tui.code ?? 1;
|
|
299
|
+
}
|
|
300
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type Layout = "main-vertical" | "main-horizontal" | "tiled" | "even-horizontal" | "even-vertical";
|
|
2
|
+
export type ClosePanes = "auto" | "keep";
|
|
3
|
+
export interface MuxConfig {
|
|
4
|
+
sessionName: string;
|
|
5
|
+
layout: Layout;
|
|
6
|
+
closePanes: ClosePanes;
|
|
7
|
+
graceSeconds: number;
|
|
8
|
+
mainPaneSize: number;
|
|
9
|
+
parent: string | null;
|
|
10
|
+
}
|
|
11
|
+
export interface CliFlags {
|
|
12
|
+
layout?: Layout;
|
|
13
|
+
closePanes?: ClosePanes;
|
|
14
|
+
graceSeconds?: number;
|
|
15
|
+
mainPaneSize?: number;
|
|
16
|
+
parent?: string | null;
|
|
17
|
+
sessionName?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare const DEFAULT_CONFIG: MuxConfig;
|
|
20
|
+
/** Serialized default config, written when the config file is missing. */
|
|
21
|
+
export declare function defaultConfText(): string;
|
|
22
|
+
export declare function parseConfText(text: string): Partial<MuxConfig>;
|
|
23
|
+
export declare function configPath(env?: NodeJS.ProcessEnv): string;
|
|
24
|
+
export declare function loadConfig(opts?: {
|
|
25
|
+
path?: string;
|
|
26
|
+
flags?: CliFlags;
|
|
27
|
+
env?: NodeJS.ProcessEnv;
|
|
28
|
+
}): Promise<MuxConfig>;
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
export const DEFAULT_CONFIG = {
|
|
5
|
+
sessionName: "mux",
|
|
6
|
+
layout: "main-vertical",
|
|
7
|
+
closePanes: "auto",
|
|
8
|
+
graceSeconds: 1,
|
|
9
|
+
mainPaneSize: 60,
|
|
10
|
+
parent: null,
|
|
11
|
+
};
|
|
12
|
+
/** Serialized default config, written when the config file is missing. */
|
|
13
|
+
export function defaultConfText() {
|
|
14
|
+
return [
|
|
15
|
+
"# opencode-mux configuration",
|
|
16
|
+
"# This file was created automatically with defaults.",
|
|
17
|
+
`session_name=${DEFAULT_CONFIG.sessionName}`,
|
|
18
|
+
`layout=${DEFAULT_CONFIG.layout}`,
|
|
19
|
+
`main_pane_size=${DEFAULT_CONFIG.mainPaneSize}`,
|
|
20
|
+
`close_panes=${DEFAULT_CONFIG.closePanes}`,
|
|
21
|
+
`grace=${DEFAULT_CONFIG.graceSeconds}`,
|
|
22
|
+
`parent=${DEFAULT_CONFIG.parent ?? ""}`,
|
|
23
|
+
"",
|
|
24
|
+
].join("\n");
|
|
25
|
+
}
|
|
26
|
+
const LAYOUTS = new Set(["main-vertical", "main-horizontal", "tiled", "even-horizontal", "even-vertical"]);
|
|
27
|
+
const CLOSE_MODES = new Set(["auto", "keep"]);
|
|
28
|
+
export function parseConfText(text) {
|
|
29
|
+
const out = {};
|
|
30
|
+
for (const rawLine of text.split(/\r?\n/)) {
|
|
31
|
+
const line = rawLine.trim();
|
|
32
|
+
if (line === "" || line.startsWith("#"))
|
|
33
|
+
continue;
|
|
34
|
+
const eq = line.indexOf("=");
|
|
35
|
+
if (eq === -1)
|
|
36
|
+
continue; // malformed line: ignore
|
|
37
|
+
const key = line.slice(0, eq).trim();
|
|
38
|
+
const value = line.slice(eq + 1).trim();
|
|
39
|
+
switch (key) {
|
|
40
|
+
case "session_name":
|
|
41
|
+
if (value !== "")
|
|
42
|
+
out.sessionName = value;
|
|
43
|
+
break;
|
|
44
|
+
case "layout":
|
|
45
|
+
if (LAYOUTS.has(value)) {
|
|
46
|
+
out.layout = value;
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
throw new Error(`opencode-mux: invalid layout "${value}" (expected main-vertical | main-horizontal | tiled | even-horizontal | even-vertical)`);
|
|
50
|
+
}
|
|
51
|
+
break;
|
|
52
|
+
case "close_panes":
|
|
53
|
+
if (CLOSE_MODES.has(value)) {
|
|
54
|
+
out.closePanes = value;
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
throw new Error(`opencode-mux: invalid close_panes "${value}" (expected auto | keep)`);
|
|
58
|
+
}
|
|
59
|
+
break;
|
|
60
|
+
case "main_pane_size": {
|
|
61
|
+
const n = Number(value);
|
|
62
|
+
if (!Number.isFinite(n) || n < 20 || n > 80) {
|
|
63
|
+
throw new Error(`opencode-mux: invalid main_pane_size "${value}" (expected a number between 20 and 80)`);
|
|
64
|
+
}
|
|
65
|
+
out.mainPaneSize = Math.floor(n);
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
case "grace": {
|
|
69
|
+
const n = Number(value);
|
|
70
|
+
if (!Number.isFinite(n) || n < 0) {
|
|
71
|
+
throw new Error(`opencode-mux: invalid grace "${value}" (expected a non-negative number of seconds)`);
|
|
72
|
+
}
|
|
73
|
+
out.graceSeconds = Math.floor(n);
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
case "parent":
|
|
77
|
+
out.parent = value === "" ? null : value;
|
|
78
|
+
break;
|
|
79
|
+
default:
|
|
80
|
+
break; // unknown keys are ignored for forward compatibility
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return out;
|
|
84
|
+
}
|
|
85
|
+
export function configPath(env = process.env) {
|
|
86
|
+
const xdg = env.XDG_CONFIG_HOME;
|
|
87
|
+
const base = xdg && xdg !== "" ? xdg : join(homedir(), ".config");
|
|
88
|
+
return join(base, "opencode-mux.conf");
|
|
89
|
+
}
|
|
90
|
+
export async function loadConfig(opts = {}) {
|
|
91
|
+
const path = opts.path ?? configPath(opts.env ?? process.env);
|
|
92
|
+
let fromFile = {};
|
|
93
|
+
try {
|
|
94
|
+
fromFile = parseConfText(await readFile(path, "utf8"));
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
if (error.code !== "ENOENT")
|
|
98
|
+
throw error;
|
|
99
|
+
// The config file is optional: create it with defaults when missing
|
|
100
|
+
// (best effort — a read-only environment still runs on defaults).
|
|
101
|
+
try {
|
|
102
|
+
await mkdir(dirname(path), { recursive: true });
|
|
103
|
+
await writeFile(path, defaultConfText(), "utf8");
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
// ignore write failures
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
const flags = opts.flags ?? {};
|
|
110
|
+
return {
|
|
111
|
+
sessionName: flags.sessionName ?? fromFile.sessionName ?? DEFAULT_CONFIG.sessionName,
|
|
112
|
+
layout: flags.layout ?? fromFile.layout ?? DEFAULT_CONFIG.layout,
|
|
113
|
+
closePanes: flags.closePanes ?? fromFile.closePanes ?? DEFAULT_CONFIG.closePanes,
|
|
114
|
+
graceSeconds: flags.graceSeconds ?? fromFile.graceSeconds ?? DEFAULT_CONFIG.graceSeconds,
|
|
115
|
+
mainPaneSize: flags.mainPaneSize ?? fromFile.mainPaneSize ?? DEFAULT_CONFIG.mainPaneSize,
|
|
116
|
+
parent: flags.parent !== undefined ? flags.parent : (fromFile.parent ?? DEFAULT_CONFIG.parent),
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/exec.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface ExecResult {
|
|
2
|
+
ok: boolean;
|
|
3
|
+
code: number | null;
|
|
4
|
+
stdout: string;
|
|
5
|
+
stderr: string;
|
|
6
|
+
error: string | null;
|
|
7
|
+
}
|
|
8
|
+
export interface Exec {
|
|
9
|
+
run(command: string, args: string[]): Promise<ExecResult>;
|
|
10
|
+
}
|
|
11
|
+
/** Real subprocess runner; never throws — failures are returned as results. */
|
|
12
|
+
export declare function nodeExec(): Exec;
|
package/dist/exec.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
/** Real subprocess runner; never throws — failures are returned as results. */
|
|
3
|
+
export function nodeExec() {
|
|
4
|
+
return {
|
|
5
|
+
run(command, args) {
|
|
6
|
+
return new Promise((resolve) => {
|
|
7
|
+
const child = spawn(command, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
8
|
+
let stdout = "";
|
|
9
|
+
let stderr = "";
|
|
10
|
+
child.stdout.setEncoding("utf8");
|
|
11
|
+
child.stderr.setEncoding("utf8");
|
|
12
|
+
child.stdout.on("data", (chunk) => {
|
|
13
|
+
stdout += chunk;
|
|
14
|
+
});
|
|
15
|
+
child.stderr.on("data", (chunk) => {
|
|
16
|
+
stderr += chunk;
|
|
17
|
+
});
|
|
18
|
+
child.on("error", (err) => {
|
|
19
|
+
resolve({ ok: false, code: null, stdout, stderr, error: String(err) });
|
|
20
|
+
});
|
|
21
|
+
child.on("close", (code) => {
|
|
22
|
+
resolve({ ok: code === 0, code, stdout, stderr, error: null });
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=exec.js.map
|
package/dist/exec.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exec.js","sourceRoot":"","sources":["../src/exec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAc3C,+EAA+E;AAC/E,MAAM,UAAU,QAAQ;IACtB,OAAO;QACL,GAAG,CAAC,OAAO,EAAE,IAAI;YACf,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;gBAC7B,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;gBAC1E,IAAI,MAAM,GAAG,EAAE,CAAC;gBAChB,IAAI,MAAM,GAAG,EAAE,CAAC;gBAChB,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;gBACjC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;gBACjC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;oBACxC,MAAM,IAAI,KAAK,CAAC;gBAClB,CAAC,CAAC,CAAC;gBACH,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;oBACxC,MAAM,IAAI,KAAK,CAAC;gBAClB,CAAC,CAAC,CAAC;gBACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;oBACxB,OAAO,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACzE,CAAC,CAAC,CAAC;gBACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;oBACzB,OAAO,CAAC,EAAE,EAAE,EAAE,IAAI,KAAK,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;gBACjE,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Service } from "@opencode/client/service";
|
|
2
|
+
import type { OpenCodeClient, OpenCodeEvent, SessionInfo } from "@opencode/client";
|
|
3
|
+
/** Client protocol generation, matched to the daemon's service protocol. */
|
|
4
|
+
export type ServiceGeneration = "legacy" | "new";
|
|
5
|
+
export interface ConnectServerDeps {
|
|
6
|
+
/** Selects the SDK line whose Service.ensure() speaks the daemon's protocol (/api/status vs /api/info). */
|
|
7
|
+
generation?: ServiceGeneration;
|
|
8
|
+
ensure?: typeof Service.ensure;
|
|
9
|
+
headers?: typeof Service.headers;
|
|
10
|
+
}
|
|
11
|
+
export interface ServerConnection {
|
|
12
|
+
url: string;
|
|
13
|
+
client: OpenCodeClient;
|
|
14
|
+
}
|
|
15
|
+
/** Connects to the shared local opencode service (injectable for tests). */
|
|
16
|
+
export declare function connectServer(deps?: ConnectServerDeps): Promise<ServerConnection>;
|
|
17
|
+
/** Adopts already-existing child sessions; parentID null means watch all. */
|
|
18
|
+
export declare function childSessions(client: OpenCodeClient, parentID: string | null): Promise<SessionInfo[]>;
|
|
19
|
+
/** Live event stream; ends when the server restarts (watcher exits, next launch resumes). */
|
|
20
|
+
export declare function events(client: OpenCodeClient, signal: AbortSignal): Promise<AsyncIterable<OpenCodeEvent>>;
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { OpenCode } from "@opencode/client";
|
|
2
|
+
import { Service } from "@opencode/client/service";
|
|
3
|
+
import { OpenCode as LegacyOpenCode } from "@opencode/client-legacy";
|
|
4
|
+
import { Service as LegacyService } from "@opencode/client-legacy/service";
|
|
5
|
+
import { isChildSession } from "./session.js";
|
|
6
|
+
/** Connects to the shared local opencode service (injectable for tests). */
|
|
7
|
+
export async function connectServer(deps = {}) {
|
|
8
|
+
const legacy = deps.generation === "legacy";
|
|
9
|
+
const service = legacy ? LegacyService : Service;
|
|
10
|
+
const ensure = deps.ensure ?? service.ensure;
|
|
11
|
+
const headers = deps.headers ?? service.headers;
|
|
12
|
+
const endpoint = await ensure();
|
|
13
|
+
// Legacy 2.0.5's generated client has the same public session/event surface as 2.0.6
|
|
14
|
+
// but different internal RpcClient typings; adapt with a narrow cast at the boundary.
|
|
15
|
+
const client = legacy
|
|
16
|
+
? LegacyOpenCode.make({ baseUrl: endpoint.url, headers: headers(endpoint) })
|
|
17
|
+
: OpenCode.make({ baseUrl: endpoint.url, headers: headers(endpoint) });
|
|
18
|
+
return { url: endpoint.url, client };
|
|
19
|
+
}
|
|
20
|
+
/** Adopts already-existing child sessions; parentID null means watch all. */
|
|
21
|
+
export async function childSessions(client, parentID) {
|
|
22
|
+
const response = await client.session.list(parentID === null ? {} : { parentID });
|
|
23
|
+
return response.data.filter(isChildSession);
|
|
24
|
+
}
|
|
25
|
+
/** Live event stream; ends when the server restarts (watcher exits, next launch resumes). */
|
|
26
|
+
export async function events(client, signal) {
|
|
27
|
+
return client.event.subscribe({ signal });
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAEnD,OAAO,EAAE,QAAQ,IAAI,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAiB9C,4EAA4E;AAC5E,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAA0B,EAAE;IAC9D,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,KAAK,QAAQ,CAAC;IAC5C,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC;IACjD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;IAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;IAChD,MAAM,QAAQ,GAAG,MAAM,MAAM,EAAE,CAAC;IAChC,qFAAqF;IACrF,sFAAsF;IACtF,MAAM,MAAM,GAAG,MAAM;QACnB,CAAC,CAAE,cAAc,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE,CAA+B;QAC3G,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACzE,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC;AACvC,CAAC;AAED,6EAA6E;AAC7E,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAsB,EAAE,QAAuB;IACjF,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;IAClF,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;AAC9C,CAAC;AAED,6FAA6F;AAC7F,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,MAAsB,EAAE,MAAmB;IACtE,OAAO,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { OpenCodeEvent, SessionInfo } from "@opencode/client";
|
|
2
|
+
export type EventClass = {
|
|
3
|
+
kind: "created";
|
|
4
|
+
sessionID: string;
|
|
5
|
+
parentID?: string;
|
|
6
|
+
title?: string;
|
|
7
|
+
slug: string;
|
|
8
|
+
} | {
|
|
9
|
+
kind: "terminal";
|
|
10
|
+
sessionID: string;
|
|
11
|
+
} | {
|
|
12
|
+
kind: "busy";
|
|
13
|
+
sessionID: string;
|
|
14
|
+
} | {
|
|
15
|
+
kind: "other";
|
|
16
|
+
};
|
|
17
|
+
/** Classifies an SDK event into what the watcher reacts to. */
|
|
18
|
+
export declare function classifyEvent(event: OpenCodeEvent): EventClass;
|
|
19
|
+
/** True when the session is a subagent session (has a parent). */
|
|
20
|
+
export declare function isChildSession(info: SessionInfo): boolean;
|
|
21
|
+
/** Pane label: non-empty title, otherwise the fallback (slug or session id). */
|
|
22
|
+
export declare function childTitle(title: string | undefined, fallback: string): string;
|
package/dist/session.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/** Classifies an SDK event into what the watcher reacts to. */
|
|
2
|
+
export function classifyEvent(event) {
|
|
3
|
+
switch (event.type) {
|
|
4
|
+
case "session.created":
|
|
5
|
+
return {
|
|
6
|
+
kind: "created",
|
|
7
|
+
sessionID: event.data.sessionID,
|
|
8
|
+
parentID: event.data.parentID,
|
|
9
|
+
title: event.data.title,
|
|
10
|
+
slug: event.data.slug,
|
|
11
|
+
};
|
|
12
|
+
case "session.idle":
|
|
13
|
+
case "session.deleted":
|
|
14
|
+
return { kind: "terminal", sessionID: event.data.sessionID };
|
|
15
|
+
case "session.execution.started":
|
|
16
|
+
return { kind: "busy", sessionID: event.data.sessionID };
|
|
17
|
+
case "session.execution.succeeded":
|
|
18
|
+
case "session.execution.failed":
|
|
19
|
+
case "session.execution.interrupted":
|
|
20
|
+
// The daemon's turn-lifecycle signal (session.idle is deprecated and
|
|
21
|
+
// session.status is client-derived): opencode's own app reducer derives
|
|
22
|
+
// session busy/idle from these exact events.
|
|
23
|
+
return { kind: "terminal", sessionID: event.data.sessionID };
|
|
24
|
+
case "session.status":
|
|
25
|
+
if (event.data.status.type === "idle")
|
|
26
|
+
return { kind: "terminal", sessionID: event.data.sessionID };
|
|
27
|
+
if (event.data.status.type === "busy")
|
|
28
|
+
return { kind: "busy", sessionID: event.data.sessionID };
|
|
29
|
+
return { kind: "other" };
|
|
30
|
+
default:
|
|
31
|
+
return { kind: "other" };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/** True when the session is a subagent session (has a parent). */
|
|
35
|
+
export function isChildSession(info) {
|
|
36
|
+
return info.parentID !== undefined;
|
|
37
|
+
}
|
|
38
|
+
/** Pane label: non-empty title, otherwise the fallback (slug or session id). */
|
|
39
|
+
export function childTitle(title, fallback) {
|
|
40
|
+
return title !== undefined && title !== "" ? title : fallback;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAQA,+DAA+D;AAC/D,MAAM,UAAU,aAAa,CAAC,KAAoB;IAChD,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,iBAAiB;YACpB,OAAO;gBACL,IAAI,EAAE,SAAS;gBACf,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,SAAS;gBAC/B,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ;gBAC7B,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK;gBACvB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI;aACtB,CAAC;QACJ,KAAK,cAAc,CAAC;QACpB,KAAK,iBAAiB;YACpB,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;QAC/D,KAAK,2BAA2B;YAC9B,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;QAC3D,KAAK,6BAA6B,CAAC;QACnC,KAAK,0BAA0B,CAAC;QAChC,KAAK,+BAA+B;YAClC,qEAAqE;YACrE,wEAAwE;YACxE,6CAA6C;YAC7C,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;QAC/D,KAAK,gBAAgB;YACnB,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,MAAM;gBAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpG,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,MAAM;gBAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YAChG,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAC3B;YACE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IAC7B,CAAC;AACH,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,cAAc,CAAC,IAAiB;IAC9C,OAAO,IAAI,CAAC,QAAQ,KAAK,SAAS,CAAC;AACrC,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,UAAU,CAAC,KAAyB,EAAE,QAAgB;IACpE,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC;AAChE,CAAC"}
|