@sma1lboy/kobe 0.6.9 → 0.7.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/dist/cli/index.js +1795 -1165
- package/package.json +2 -6
package/dist/cli/index.js
CHANGED
|
@@ -70,18 +70,14 @@ var init_package = __esm(() => {
|
|
|
70
70
|
package_default = {
|
|
71
71
|
$schema: "https://json.schemastore.org/package.json",
|
|
72
72
|
name: "@sma1lboy/kobe",
|
|
73
|
-
version: "0.
|
|
73
|
+
version: "0.7.0",
|
|
74
74
|
description: "TUI orchestrator for Claude Code (codename)",
|
|
75
75
|
type: "module",
|
|
76
76
|
packageManager: "bun@1.3.13",
|
|
77
77
|
bin: {
|
|
78
78
|
kobe: "dist/cli/index.js"
|
|
79
79
|
},
|
|
80
|
-
files: [
|
|
81
|
-
"dist",
|
|
82
|
-
"README.md",
|
|
83
|
-
"LICENSE"
|
|
84
|
-
],
|
|
80
|
+
files: ["dist", "README.md", "LICENSE"],
|
|
85
81
|
publishConfig: {
|
|
86
82
|
access: "public"
|
|
87
83
|
},
|
|
@@ -218,6 +214,10 @@ function isNewerSemver(latest, current) {
|
|
|
218
214
|
return false;
|
|
219
215
|
}
|
|
220
216
|
async function checkLatestVersion(opts = {}) {
|
|
217
|
+
const fake = process.env.KOBE_FAKE_UPDATE;
|
|
218
|
+
if (fake) {
|
|
219
|
+
return { current: CURRENT_VERSION, latest: fake, hasUpdate: isNewerSemver(fake, CURRENT_VERSION) };
|
|
220
|
+
}
|
|
221
221
|
if (isDev() && !opts.force)
|
|
222
222
|
return null;
|
|
223
223
|
const latest = await fetchLatestFromRegistry(PACKAGE_NAME);
|
|
@@ -3049,6 +3049,21 @@ class Orchestrator {
|
|
|
3049
3049
|
if (task.title === trimmed)
|
|
3050
3050
|
return;
|
|
3051
3051
|
await this.store.update(task.id, { title: trimmed });
|
|
3052
|
+
await this.followBranchToTitle(task, trimmed);
|
|
3053
|
+
}
|
|
3054
|
+
async followBranchToTitle(taskBefore, newTitle) {
|
|
3055
|
+
if (taskBefore.kind === "main" || !taskBefore.worktreePath)
|
|
3056
|
+
return;
|
|
3057
|
+
if (taskBefore.branch !== autoBranch(PLACEHOLDER_TASK_TITLE, taskBefore.id))
|
|
3058
|
+
return;
|
|
3059
|
+
const nextBranch = autoBranch(newTitle, taskBefore.id);
|
|
3060
|
+
if (nextBranch === taskBefore.branch)
|
|
3061
|
+
return;
|
|
3062
|
+
try {
|
|
3063
|
+
await this.setBranch(taskBefore.id, nextBranch);
|
|
3064
|
+
} catch (err) {
|
|
3065
|
+
console.error(`[kobe] follow-branch-to-title failed for ${taskBefore.id}:`, err);
|
|
3066
|
+
}
|
|
3052
3067
|
}
|
|
3053
3068
|
async setBranch(id, branch) {
|
|
3054
3069
|
const trimmed = branch.trim();
|
|
@@ -3272,8 +3287,13 @@ class KobeDaemonClient {
|
|
|
3272
3287
|
onChannel(channel, handler) {
|
|
3273
3288
|
return this.on(channel, (frame) => handler(frame.payload));
|
|
3274
3289
|
}
|
|
3275
|
-
subscribe(
|
|
3276
|
-
|
|
3290
|
+
subscribe(opts = {}) {
|
|
3291
|
+
const payload = {};
|
|
3292
|
+
if (opts.channels)
|
|
3293
|
+
payload.channels = opts.channels;
|
|
3294
|
+
if (opts.role)
|
|
3295
|
+
payload.role = opts.role;
|
|
3296
|
+
return this.request("subscribe", payload);
|
|
3277
3297
|
}
|
|
3278
3298
|
onLifecycle(name, handler) {
|
|
3279
3299
|
let set = this.lifecycleHandlers.get(name);
|
|
@@ -4216,6 +4236,13 @@ var init_history3 = __esm(() => {
|
|
|
4216
4236
|
});
|
|
4217
4237
|
|
|
4218
4238
|
// src/monitor/auto-title.ts
|
|
4239
|
+
function readerFor(vendor) {
|
|
4240
|
+
if (vendor === "codex")
|
|
4241
|
+
return readHistory2;
|
|
4242
|
+
if (vendor === "copilot")
|
|
4243
|
+
return readHistory3;
|
|
4244
|
+
return readHistory;
|
|
4245
|
+
}
|
|
4219
4246
|
async function originSessions(worktree, vendor) {
|
|
4220
4247
|
if (vendor === "codex") {
|
|
4221
4248
|
return { ids: await listSessionIdsForWorktree(worktree), read: readHistory2 };
|
|
@@ -4227,22 +4254,33 @@ async function originSessions(worktree, vendor) {
|
|
|
4227
4254
|
const ids = [...files].sort((a, b) => a.mtimeMs - b.mtimeMs).map((f) => f.sessionId);
|
|
4228
4255
|
return { ids, read: readHistory };
|
|
4229
4256
|
}
|
|
4257
|
+
function titleFromMessages(messages) {
|
|
4258
|
+
const firstUser = messages.find((m) => m.role === "user");
|
|
4259
|
+
if (!firstUser)
|
|
4260
|
+
return "";
|
|
4261
|
+
const text = firstUser.blocks.filter((b) => b.type === "text").map((b) => b.text).join(" ");
|
|
4262
|
+
return deriveTitleFromPrompt(text);
|
|
4263
|
+
}
|
|
4230
4264
|
async function deriveTitleFromSession(worktree, vendor = DEFAULT_TASK_VENDOR) {
|
|
4231
4265
|
if (!worktree)
|
|
4232
4266
|
return "";
|
|
4233
4267
|
const { ids, read } = await originSessions(worktree, vendor);
|
|
4234
4268
|
for (const sessionId of ids.slice(0, MAX_SESSIONS_SCANNED)) {
|
|
4235
|
-
const
|
|
4236
|
-
const firstUser = messages.find((m) => m.role === "user");
|
|
4237
|
-
if (!firstUser)
|
|
4238
|
-
continue;
|
|
4239
|
-
const text = firstUser.blocks.filter((b) => b.type === "text").map((b) => b.text).join(" ");
|
|
4240
|
-
const title = deriveTitleFromPrompt(text);
|
|
4269
|
+
const title = titleFromMessages(await read(sessionId));
|
|
4241
4270
|
if (title)
|
|
4242
4271
|
return title;
|
|
4243
4272
|
}
|
|
4244
4273
|
return "";
|
|
4245
4274
|
}
|
|
4275
|
+
async function deriveTitleFromSessionId(vendor, sessionId) {
|
|
4276
|
+
if (!sessionId)
|
|
4277
|
+
return "";
|
|
4278
|
+
try {
|
|
4279
|
+
return titleFromMessages(await readerFor(vendor)(sessionId));
|
|
4280
|
+
} catch {
|
|
4281
|
+
return "";
|
|
4282
|
+
}
|
|
4283
|
+
}
|
|
4246
4284
|
var MAX_SESSIONS_SCANNED = 8;
|
|
4247
4285
|
var init_auto_title = __esm(() => {
|
|
4248
4286
|
init_history();
|
|
@@ -4250,173 +4288,488 @@ var init_auto_title = __esm(() => {
|
|
|
4250
4288
|
init_history3();
|
|
4251
4289
|
});
|
|
4252
4290
|
|
|
4253
|
-
// src/
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4291
|
+
// src/tmux/client.ts
|
|
4292
|
+
var exports_client = {};
|
|
4293
|
+
__export(exports_client, {
|
|
4294
|
+
windowCount: () => windowCount,
|
|
4295
|
+
tmuxSessionName: () => tmuxSessionName,
|
|
4296
|
+
tmuxCommandSequence: () => tmuxCommandSequence,
|
|
4297
|
+
tmuxAvailable: () => tmuxAvailable,
|
|
4298
|
+
tmuxArgs: () => tmuxArgs,
|
|
4299
|
+
tagPaneRole: () => tagPaneRole,
|
|
4300
|
+
tagClaudePane: () => tagClaudePane,
|
|
4301
|
+
switchClientBeforeKill: () => switchClientBeforeKill,
|
|
4302
|
+
setWindowOption: () => setWindowOption,
|
|
4303
|
+
setSessionOption: () => setSessionOption,
|
|
4304
|
+
sessionExists: () => sessionExists,
|
|
4305
|
+
sendKeys: () => sendKeys,
|
|
4306
|
+
sendKeyName: () => sendKeyName,
|
|
4307
|
+
runTmuxSequenceCapturing: () => runTmuxSequenceCapturing,
|
|
4308
|
+
runTmuxSequence: () => runTmuxSequence,
|
|
4309
|
+
runTmuxCapturing: () => runTmuxCapturing,
|
|
4310
|
+
runTmux: () => runTmux,
|
|
4311
|
+
paneIdByRole: () => paneIdByRole,
|
|
4312
|
+
newWindow: () => newWindow,
|
|
4313
|
+
killSession: () => killSession,
|
|
4314
|
+
getSessionOptions: () => getSessionOptions,
|
|
4315
|
+
getSessionOption: () => getSessionOption,
|
|
4316
|
+
ensureFallbackSession: () => ensureFallbackSession,
|
|
4317
|
+
currentSessionName: () => currentSessionName,
|
|
4318
|
+
claudePaneIdStrict: () => claudePaneIdStrict,
|
|
4319
|
+
claudePaneId: () => claudePaneId,
|
|
4320
|
+
capturePaneById: () => capturePaneById,
|
|
4321
|
+
attachArgv: () => attachArgv,
|
|
4322
|
+
PANE_ROLE_OPTION: () => PANE_ROLE_OPTION,
|
|
4323
|
+
KOBE_TMUX_SOCKET: () => KOBE_TMUX_SOCKET,
|
|
4324
|
+
KOBE_HOME_SESSION: () => KOBE_HOME_SESSION,
|
|
4325
|
+
CLAUDE_ROLE_OPTION: () => CLAUDE_ROLE_OPTION,
|
|
4326
|
+
CHAT_TAB_SESSION_ID_OPTION: () => CHAT_TAB_SESSION_ID_OPTION
|
|
4327
|
+
});
|
|
4328
|
+
function tmuxArgs(...args) {
|
|
4329
|
+
return ["tmux", "-L", KOBE_TMUX_SOCKET, ...args];
|
|
4330
|
+
}
|
|
4331
|
+
function tmuxSessionName(taskId) {
|
|
4332
|
+
return `kobe-${taskId.replace(/[^A-Za-z0-9_-]/g, "")}`;
|
|
4333
|
+
}
|
|
4334
|
+
function attachArgv(name) {
|
|
4335
|
+
return tmuxArgs("attach-session", "-t", `=${name}`);
|
|
4336
|
+
}
|
|
4337
|
+
async function drainText(stream) {
|
|
4338
|
+
if (!stream)
|
|
4339
|
+
return "";
|
|
4258
4340
|
try {
|
|
4259
|
-
|
|
4341
|
+
return await new Response(stream).text();
|
|
4260
4342
|
} catch {
|
|
4261
|
-
|
|
4343
|
+
return "";
|
|
4262
4344
|
}
|
|
4263
|
-
return new Error(text);
|
|
4264
|
-
}
|
|
4265
|
-
function formatCrashEntry(kind, err, now = new Date) {
|
|
4266
|
-
const e = toError(err);
|
|
4267
|
-
return `[${now.toISOString()}] daemon ${kind}: ${e.stack ?? `${e.name}: ${e.message}`}
|
|
4268
|
-
`;
|
|
4269
|
-
}
|
|
4270
|
-
function formatDaemonError(subsystem, err, now = new Date) {
|
|
4271
|
-
const e = toError(err);
|
|
4272
|
-
return `[${now.toISOString()}] daemon error [${subsystem}]: ${e.stack ?? `${e.name}: ${e.message}`}
|
|
4273
|
-
`;
|
|
4274
4345
|
}
|
|
4275
|
-
function
|
|
4276
|
-
|
|
4346
|
+
async function runTmux(args) {
|
|
4347
|
+
const proc = Bun.spawn(tmuxArgs(...args), { stdin: "ignore", stdout: "ignore", stderr: "pipe" });
|
|
4348
|
+
const [errText, code] = await Promise.all([drainText(proc.stderr), proc.exited]);
|
|
4349
|
+
if (code !== 0 && errText.trim().length > 0) {
|
|
4350
|
+
console.error(`[kobe tmux] ${args.join(" ")} (${code}): ${errText.trim()}`);
|
|
4351
|
+
}
|
|
4352
|
+
return code;
|
|
4277
4353
|
}
|
|
4278
|
-
function
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
onRejection = (reason) => log(formatCrashEntry("unhandledRejection", reason));
|
|
4282
|
-
onException = (err) => log(formatCrashEntry("uncaughtException", err));
|
|
4283
|
-
process.on("unhandledRejection", onRejection);
|
|
4284
|
-
process.on("uncaughtException", onException);
|
|
4354
|
+
async function runTmuxQuiet(args) {
|
|
4355
|
+
const proc = Bun.spawn(tmuxArgs(...args), { stdin: "ignore", stdout: "ignore", stderr: "ignore" });
|
|
4356
|
+
return proc.exited;
|
|
4285
4357
|
}
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
let renamed = 0;
|
|
4291
|
-
for (const task of orch.listTasks()) {
|
|
4292
|
-
if (task.title !== PLACEHOLDER_TASK_TITLE || !task.worktreePath)
|
|
4358
|
+
function tmuxCommandSequence(commands) {
|
|
4359
|
+
const out = [];
|
|
4360
|
+
for (const cmd of commands) {
|
|
4361
|
+
if (cmd.length === 0)
|
|
4293
4362
|
continue;
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
continue;
|
|
4298
|
-
const current = orch.getTask(task.id);
|
|
4299
|
-
if (!current || current.title !== PLACEHOLDER_TASK_TITLE)
|
|
4300
|
-
continue;
|
|
4301
|
-
await orch.setTitle(task.id, title);
|
|
4302
|
-
renamed++;
|
|
4303
|
-
} catch (err) {
|
|
4304
|
-
logDaemonError("auto-title-poller", err);
|
|
4305
|
-
}
|
|
4363
|
+
if (out.length > 0)
|
|
4364
|
+
out.push(";");
|
|
4365
|
+
out.push(...cmd);
|
|
4306
4366
|
}
|
|
4307
|
-
return
|
|
4367
|
+
return out;
|
|
4308
4368
|
}
|
|
4309
|
-
function
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
let running = false;
|
|
4313
|
-
const tick = () => {
|
|
4314
|
-
if (running)
|
|
4315
|
-
return;
|
|
4316
|
-
running = true;
|
|
4317
|
-
runAutoTitlePass(orch).catch((err) => logDaemonError("auto-title-poller", err)).finally(() => {
|
|
4318
|
-
running = false;
|
|
4319
|
-
});
|
|
4320
|
-
};
|
|
4321
|
-
const timer = setInterval(tick, intervalMs);
|
|
4322
|
-
timer.unref?.();
|
|
4323
|
-
return () => clearInterval(timer);
|
|
4369
|
+
async function runTmuxSequence(commands) {
|
|
4370
|
+
const args = tmuxCommandSequence(commands);
|
|
4371
|
+
return args.length === 0 ? 0 : runTmux(args);
|
|
4324
4372
|
}
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
});
|
|
4330
|
-
|
|
4331
|
-
// src/daemon/event-bus.ts
|
|
4332
|
-
class DaemonEventBus {
|
|
4333
|
-
last = new Map;
|
|
4334
|
-
sinks = new Set;
|
|
4335
|
-
publish(channel, payload) {
|
|
4336
|
-
this.last.set(channel, payload);
|
|
4337
|
-
const event = { channel, payload };
|
|
4338
|
-
for (const sink of this.sinks)
|
|
4339
|
-
sink(event);
|
|
4340
|
-
}
|
|
4341
|
-
snapshot() {
|
|
4342
|
-
return [...this.last].map(([channel, payload]) => ({ channel, payload }));
|
|
4343
|
-
}
|
|
4344
|
-
onPublish(sink) {
|
|
4345
|
-
this.sinks.add(sink);
|
|
4346
|
-
return () => {
|
|
4347
|
-
this.sinks.delete(sink);
|
|
4348
|
-
};
|
|
4373
|
+
async function runTmuxCapturing(args) {
|
|
4374
|
+
const proc = Bun.spawn(tmuxArgs(...args), { stdin: "ignore", stdout: "pipe", stderr: "pipe" });
|
|
4375
|
+
const [stdout, errText, code] = await Promise.all([drainText(proc.stdout), drainText(proc.stderr), proc.exited]);
|
|
4376
|
+
if (code !== 0 && errText.trim().length > 0) {
|
|
4377
|
+
console.error(`[kobe tmux] ${args.join(" ")} (${code}): ${errText.trim()}`);
|
|
4349
4378
|
}
|
|
4379
|
+
return { code, stdout };
|
|
4350
4380
|
}
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
import { homedir as homedir6, tmpdir } from "os";
|
|
4355
|
-
import { join as join3 } from "path";
|
|
4356
|
-
function shortHomeTag(homeDir2) {
|
|
4357
|
-
return createHash2("sha1").update(homeDir2).digest("hex").slice(0, 8);
|
|
4358
|
-
}
|
|
4359
|
-
function fitSocketPath(naturalPath, homeDir2, role, pidTag) {
|
|
4360
|
-
if (Buffer.byteLength(naturalPath, "utf8") <= SOCKET_PATH_SAFETY_LIMIT)
|
|
4361
|
-
return naturalPath;
|
|
4362
|
-
const tag = shortHomeTag(homeDir2);
|
|
4363
|
-
const suffix = pidTag === undefined ? "" : `-${pidTag}`;
|
|
4364
|
-
const fallback = join3(tmpdir(), `kobe-${tag}-${role}${suffix}.sock`);
|
|
4365
|
-
if (Buffer.byteLength(fallback, "utf8") <= SOCKET_PATH_SAFETY_LIMIT)
|
|
4366
|
-
return fallback;
|
|
4367
|
-
throw new Error(`kobe socket path exceeds ${SOCKET_PATH_SAFETY_LIMIT} bytes even after fallback: ${fallback}`);
|
|
4381
|
+
async function runTmuxSequenceCapturing(commands) {
|
|
4382
|
+
const args = tmuxCommandSequence(commands);
|
|
4383
|
+
return args.length === 0 ? { code: 0, stdout: "" } : runTmuxCapturing(args);
|
|
4368
4384
|
}
|
|
4369
|
-
function
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
return
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
return fitSocketPath(join3(explicit, ".kobe", "daemon.sock"), explicit, "daemon");
|
|
4376
|
-
}
|
|
4377
|
-
const runtimeDir = process.env.XDG_RUNTIME_DIR;
|
|
4378
|
-
if (runtimeDir && runtimeDir.length > 0) {
|
|
4379
|
-
return fitSocketPath(join3(runtimeDir, "kobe.sock"), runtimeDir, "daemon");
|
|
4385
|
+
async function tmuxAvailable() {
|
|
4386
|
+
try {
|
|
4387
|
+
const proc = Bun.spawn(["tmux", "-V"], { stdin: "ignore", stdout: "ignore", stderr: "ignore" });
|
|
4388
|
+
return await proc.exited === 0;
|
|
4389
|
+
} catch {
|
|
4390
|
+
return false;
|
|
4380
4391
|
}
|
|
4381
|
-
const home = homedir6();
|
|
4382
|
-
return fitSocketPath(join3(home, ".kobe", "daemon.sock"), home, "daemon");
|
|
4383
4392
|
}
|
|
4384
|
-
function
|
|
4385
|
-
|
|
4386
|
-
if (override && override.length > 0)
|
|
4387
|
-
return override;
|
|
4388
|
-
return join3(homeDir2, ".kobe", "daemon.pid");
|
|
4393
|
+
async function sessionExists(name) {
|
|
4394
|
+
return await runTmuxQuiet(["has-session", "-t", `=${name}`]) === 0;
|
|
4389
4395
|
}
|
|
4390
|
-
function
|
|
4391
|
-
|
|
4396
|
+
async function windowCount(sessionName) {
|
|
4397
|
+
const { code, stdout } = await runTmuxCapturing(["list-windows", "-t", `=${sessionName}`, "-F", "#{window_id}"]);
|
|
4398
|
+
if (code !== 0)
|
|
4399
|
+
return 0;
|
|
4400
|
+
return stdout.split(`
|
|
4401
|
+
`).filter((l) => l.trim().length > 0).length;
|
|
4392
4402
|
}
|
|
4393
|
-
|
|
4394
|
-
|
|
4395
|
-
|
|
4396
|
-
// src/daemon/server.ts
|
|
4397
|
-
import { mkdir as mkdir3, readFile as readFile5, unlink as unlink4, writeFile as writeFile3 } from "fs/promises";
|
|
4398
|
-
import { createServer } from "net";
|
|
4399
|
-
import { dirname as dirname3 } from "path";
|
|
4400
|
-
function resolveIdleGraceMs() {
|
|
4401
|
-
const raw = process.env.KOBE_DAEMON_IDLE_GRACE_MS;
|
|
4402
|
-
if (raw === undefined)
|
|
4403
|
-
return DEFAULT_IDLE_GRACE_MS;
|
|
4404
|
-
const n = Number(raw);
|
|
4405
|
-
return Number.isFinite(n) && n >= 0 ? n : DEFAULT_IDLE_GRACE_MS;
|
|
4403
|
+
async function setSessionOption(session, option, value) {
|
|
4404
|
+
await runTmux(["set-option", "-t", session, option, value]);
|
|
4406
4405
|
}
|
|
4407
|
-
async function
|
|
4408
|
-
const
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
4413
|
-
const
|
|
4406
|
+
async function getSessionOption(session, option) {
|
|
4407
|
+
const { code, stdout } = await runTmuxCapturing(["show-options", "-v", "-t", session, option]);
|
|
4408
|
+
return code === 0 ? stdout.trim() : "";
|
|
4409
|
+
}
|
|
4410
|
+
async function getSessionOptions(session, options) {
|
|
4411
|
+
const values = Object.fromEntries(options.map((option) => [option, undefined]));
|
|
4412
|
+
const { code, stdout } = await runTmuxSequenceCapturing(options.map((option) => ["show-options", "-q", "-t", session, option]));
|
|
4413
|
+
if (code !== 0)
|
|
4414
|
+
return values;
|
|
4415
|
+
for (const line of stdout.split(`
|
|
4416
|
+
`)) {
|
|
4417
|
+
const idx = line.indexOf(" ");
|
|
4418
|
+
if (idx <= 0)
|
|
4419
|
+
continue;
|
|
4420
|
+
const option = line.slice(0, idx);
|
|
4421
|
+
if (option in values)
|
|
4422
|
+
values[option] = line.slice(idx + 1).trim();
|
|
4423
|
+
}
|
|
4424
|
+
return values;
|
|
4425
|
+
}
|
|
4426
|
+
async function tagPaneRole(paneId, role) {
|
|
4427
|
+
await runTmux(["set-option", "-p", "-t", paneId, PANE_ROLE_OPTION, role]);
|
|
4428
|
+
}
|
|
4429
|
+
async function setWindowOption(target, option, value) {
|
|
4430
|
+
await runTmux(["set-window-option", "-t", target, option, value]);
|
|
4431
|
+
}
|
|
4432
|
+
async function tagClaudePane(paneId) {
|
|
4433
|
+
await tagPaneRole(paneId, CLAUDE_ROLE_VALUE);
|
|
4434
|
+
}
|
|
4435
|
+
async function paneIdByRole(sessionName, role, fallbackFirst = false) {
|
|
4436
|
+
const { code, stdout } = await runTmuxCapturing([
|
|
4437
|
+
"list-panes",
|
|
4438
|
+
"-t",
|
|
4439
|
+
`=${sessionName}`,
|
|
4440
|
+
"-F",
|
|
4441
|
+
`#{pane_id} #{${PANE_ROLE_OPTION}}`
|
|
4442
|
+
]);
|
|
4443
|
+
if (code !== 0)
|
|
4444
|
+
return "";
|
|
4445
|
+
let firstId = "";
|
|
4446
|
+
for (const line of stdout.split(`
|
|
4447
|
+
`)) {
|
|
4448
|
+
const [id, paneRole] = line.split("\t");
|
|
4449
|
+
if (!id)
|
|
4450
|
+
continue;
|
|
4451
|
+
if (!firstId)
|
|
4452
|
+
firstId = id.trim();
|
|
4453
|
+
if (paneRole?.trim() === role)
|
|
4454
|
+
return id.trim();
|
|
4455
|
+
}
|
|
4456
|
+
return fallbackFirst ? firstId : "";
|
|
4457
|
+
}
|
|
4458
|
+
async function claudePaneId(sessionName) {
|
|
4459
|
+
return paneIdByRole(sessionName, CLAUDE_ROLE_VALUE, true);
|
|
4460
|
+
}
|
|
4461
|
+
async function claudePaneIdStrict(sessionName) {
|
|
4462
|
+
return paneIdByRole(sessionName, CLAUDE_ROLE_VALUE, false);
|
|
4463
|
+
}
|
|
4464
|
+
async function capturePaneById(paneId, lines) {
|
|
4465
|
+
if (!paneId)
|
|
4466
|
+
return "";
|
|
4467
|
+
const args = ["capture-pane", "-t", paneId, "-p"];
|
|
4468
|
+
if (typeof lines === "number" && lines > 0)
|
|
4469
|
+
args.push("-S", String(-lines));
|
|
4470
|
+
const { code, stdout } = await runTmuxCapturing(args);
|
|
4471
|
+
return code === 0 ? stdout : "";
|
|
4472
|
+
}
|
|
4473
|
+
async function sendKeys(target, text) {
|
|
4474
|
+
await runTmux(["send-keys", "-t", target, "-l", "--", text]);
|
|
4475
|
+
}
|
|
4476
|
+
async function sendKeyName(target, key) {
|
|
4477
|
+
await runTmux(["send-keys", "-t", target, key]);
|
|
4478
|
+
}
|
|
4479
|
+
async function newWindow(session, opts) {
|
|
4480
|
+
const args = ["new-window", "-t", `=${session}`, "-c", opts.cwd];
|
|
4481
|
+
if (opts.name)
|
|
4482
|
+
args.push("-n", opts.name);
|
|
4483
|
+
args.push(opts.command);
|
|
4484
|
+
await runTmux(args);
|
|
4485
|
+
}
|
|
4486
|
+
async function currentSessionName() {
|
|
4487
|
+
const args = ["display-message", "-p"];
|
|
4488
|
+
const target = process.env.TMUX_PANE;
|
|
4489
|
+
if (target && target.length > 0)
|
|
4490
|
+
args.push("-t", target);
|
|
4491
|
+
args.push("#{session_name}");
|
|
4492
|
+
const { code, stdout } = await runTmuxCapturing(args);
|
|
4493
|
+
const name = stdout.trim();
|
|
4494
|
+
return code === 0 && name.length > 0 ? name : null;
|
|
4495
|
+
}
|
|
4496
|
+
async function killSession(name) {
|
|
4497
|
+
if (await sessionExists(name))
|
|
4498
|
+
await runTmux(["kill-session", "-t", `=${name}`]);
|
|
4499
|
+
}
|
|
4500
|
+
async function ensureFallbackSession() {
|
|
4501
|
+
const name = KOBE_HOME_SESSION;
|
|
4502
|
+
if (!await sessionExists(name)) {
|
|
4503
|
+
await runTmux([
|
|
4504
|
+
"new-session",
|
|
4505
|
+
"-d",
|
|
4506
|
+
"-s",
|
|
4507
|
+
name,
|
|
4508
|
+
"-x",
|
|
4509
|
+
"220",
|
|
4510
|
+
"-y",
|
|
4511
|
+
"50",
|
|
4512
|
+
"sh",
|
|
4513
|
+
"-c",
|
|
4514
|
+
'clear; printf "\\n No active task\\n\\n Select a task from the sidebar to continue.\\n\\n"; exec ${SHELL:-sh}'
|
|
4515
|
+
]);
|
|
4516
|
+
}
|
|
4517
|
+
return name;
|
|
4518
|
+
}
|
|
4519
|
+
async function switchClientBeforeKill(killedName, nextSessionName) {
|
|
4520
|
+
const current = await currentSessionName();
|
|
4521
|
+
if (current !== killedName)
|
|
4522
|
+
return;
|
|
4523
|
+
if (nextSessionName && nextSessionName !== killedName && await sessionExists(nextSessionName)) {
|
|
4524
|
+
await runTmux(["switch-client", "-t", `=${nextSessionName}`]);
|
|
4525
|
+
return;
|
|
4526
|
+
}
|
|
4527
|
+
const fallback = await ensureFallbackSession();
|
|
4528
|
+
await runTmux(["switch-client", "-t", `=${fallback}`]);
|
|
4529
|
+
}
|
|
4530
|
+
var KOBE_TMUX_SOCKET, PANE_ROLE_OPTION = "@kobe_role", CLAUDE_ROLE_OPTION, CLAUDE_ROLE_VALUE = "claude", CHAT_TAB_SESSION_ID_OPTION = "@kobe_session_id", KOBE_HOME_SESSION = "kobe-home";
|
|
4531
|
+
var init_client2 = __esm(() => {
|
|
4532
|
+
KOBE_TMUX_SOCKET = process.env.KOBE_TMUX_SOCKET?.trim() || "kobe";
|
|
4533
|
+
CLAUDE_ROLE_OPTION = PANE_ROLE_OPTION;
|
|
4534
|
+
});
|
|
4535
|
+
|
|
4536
|
+
// src/tmux/chat-tab-naming.ts
|
|
4537
|
+
async function listChatTabWindows(session, runner = realRunner) {
|
|
4538
|
+
const { code, stdout } = await runner.capture([
|
|
4539
|
+
"list-windows",
|
|
4540
|
+
"-t",
|
|
4541
|
+
`=${session}`,
|
|
4542
|
+
"-F",
|
|
4543
|
+
`#{window_index} #{${CHAT_TAB_SESSION_ID_OPTION}}`
|
|
4544
|
+
]);
|
|
4545
|
+
if (code !== 0)
|
|
4546
|
+
return [];
|
|
4547
|
+
const out = [];
|
|
4548
|
+
for (const line of stdout.split(`
|
|
4549
|
+
`)) {
|
|
4550
|
+
const tab = line.indexOf("\t");
|
|
4551
|
+
const index = Number.parseInt((tab >= 0 ? line.slice(0, tab) : line).trim(), 10);
|
|
4552
|
+
if (!Number.isInteger(index))
|
|
4553
|
+
continue;
|
|
4554
|
+
out.push({ index, sessionId: tab >= 0 ? line.slice(tab + 1).trim() : "" });
|
|
4555
|
+
}
|
|
4556
|
+
return out;
|
|
4557
|
+
}
|
|
4558
|
+
async function windowNamedManually(session, index, runner) {
|
|
4559
|
+
const { code, stdout } = await runner.capture([
|
|
4560
|
+
"show-window-options",
|
|
4561
|
+
"-t",
|
|
4562
|
+
`=${session}:${index}`,
|
|
4563
|
+
"automatic-rename"
|
|
4564
|
+
]);
|
|
4565
|
+
return code === 0 && /\boff\b/.test(stdout);
|
|
4566
|
+
}
|
|
4567
|
+
async function renameWindow(session, index, title, runner) {
|
|
4568
|
+
return await runner.run(["rename-window", "-t", `=${session}:${index}`, "--", title]) === 0;
|
|
4569
|
+
}
|
|
4570
|
+
async function runChatTabNamingPass(orch, deps = realDeps) {
|
|
4571
|
+
let renamed = 0;
|
|
4572
|
+
for (const task of orch.listTasks()) {
|
|
4573
|
+
if (task.kind === "main" || !task.worktreePath)
|
|
4574
|
+
continue;
|
|
4575
|
+
const session = tmuxSessionName(task.id);
|
|
4576
|
+
const windows = await listChatTabWindows(session, deps.runner);
|
|
4577
|
+
if (windows.length === 0)
|
|
4578
|
+
continue;
|
|
4579
|
+
const originIndex = windows.reduce((min, w) => Math.min(min, w.index), Number.POSITIVE_INFINITY);
|
|
4580
|
+
const vendor = task.vendor ?? DEFAULT_TASK_VENDOR;
|
|
4581
|
+
for (const w of windows) {
|
|
4582
|
+
try {
|
|
4583
|
+
if (await windowNamedManually(session, w.index, deps.runner))
|
|
4584
|
+
continue;
|
|
4585
|
+
const title = w.sessionId ? await deps.titleFromSessionId(vendor, w.sessionId) : w.index === originIndex ? await deps.titleFromWorktree(task.worktreePath, vendor) : "";
|
|
4586
|
+
if (title && await renameWindow(session, w.index, title, deps.runner))
|
|
4587
|
+
renamed++;
|
|
4588
|
+
} catch {}
|
|
4589
|
+
}
|
|
4590
|
+
}
|
|
4591
|
+
return renamed;
|
|
4592
|
+
}
|
|
4593
|
+
var realRunner, realDeps;
|
|
4594
|
+
var init_chat_tab_naming = __esm(() => {
|
|
4595
|
+
init_auto_title();
|
|
4596
|
+
init_client2();
|
|
4597
|
+
realRunner = { capture: runTmuxCapturing, run: runTmux };
|
|
4598
|
+
realDeps = {
|
|
4599
|
+
runner: realRunner,
|
|
4600
|
+
titleFromSessionId: deriveTitleFromSessionId,
|
|
4601
|
+
titleFromWorktree: deriveTitleFromSession
|
|
4602
|
+
};
|
|
4603
|
+
});
|
|
4604
|
+
|
|
4605
|
+
// src/daemon/crash-log.ts
|
|
4606
|
+
function toError(err) {
|
|
4607
|
+
if (err instanceof Error)
|
|
4608
|
+
return err;
|
|
4609
|
+
let text;
|
|
4610
|
+
try {
|
|
4611
|
+
text = typeof err === "string" ? err : JSON.stringify(err);
|
|
4612
|
+
} catch {
|
|
4613
|
+
text = String(err);
|
|
4614
|
+
}
|
|
4615
|
+
return new Error(text);
|
|
4616
|
+
}
|
|
4617
|
+
function formatCrashEntry(kind, err, now = new Date) {
|
|
4618
|
+
const e = toError(err);
|
|
4619
|
+
return `[${now.toISOString()}] daemon ${kind}: ${e.stack ?? `${e.name}: ${e.message}`}
|
|
4620
|
+
`;
|
|
4621
|
+
}
|
|
4622
|
+
function formatDaemonError(subsystem, err, now = new Date) {
|
|
4623
|
+
const e = toError(err);
|
|
4624
|
+
return `[${now.toISOString()}] daemon error [${subsystem}]: ${e.stack ?? `${e.name}: ${e.message}`}
|
|
4625
|
+
`;
|
|
4626
|
+
}
|
|
4627
|
+
function logDaemonError(subsystem, err) {
|
|
4628
|
+
process.stderr.write(formatDaemonError(subsystem, err));
|
|
4629
|
+
}
|
|
4630
|
+
function installDaemonCrashHandlers(log = (l) => process.stderr.write(l)) {
|
|
4631
|
+
if (onRejection || onException)
|
|
4632
|
+
return;
|
|
4633
|
+
onRejection = (reason) => log(formatCrashEntry("unhandledRejection", reason));
|
|
4634
|
+
onException = (err) => log(formatCrashEntry("uncaughtException", err));
|
|
4635
|
+
process.on("unhandledRejection", onRejection);
|
|
4636
|
+
process.on("uncaughtException", onException);
|
|
4637
|
+
}
|
|
4638
|
+
var onRejection, onException;
|
|
4639
|
+
|
|
4640
|
+
// src/daemon/auto-title-poller.ts
|
|
4641
|
+
async function runAutoTitlePass(orch, derive = deriveTitleFromSession) {
|
|
4642
|
+
const renamed = [];
|
|
4643
|
+
for (const task of orch.listTasks()) {
|
|
4644
|
+
if (task.title !== PLACEHOLDER_TASK_TITLE || !task.worktreePath)
|
|
4645
|
+
continue;
|
|
4646
|
+
try {
|
|
4647
|
+
const title = await derive(task.worktreePath, task.vendor ?? DEFAULT_TASK_VENDOR);
|
|
4648
|
+
if (!title)
|
|
4649
|
+
continue;
|
|
4650
|
+
const current = orch.getTask(task.id);
|
|
4651
|
+
if (!current || current.title !== PLACEHOLDER_TASK_TITLE)
|
|
4652
|
+
continue;
|
|
4653
|
+
await orch.setTitle(task.id, title);
|
|
4654
|
+
renamed.push({ id: task.id, title });
|
|
4655
|
+
} catch (err) {
|
|
4656
|
+
logDaemonError("auto-title-poller", err);
|
|
4657
|
+
}
|
|
4658
|
+
}
|
|
4659
|
+
return renamed;
|
|
4660
|
+
}
|
|
4661
|
+
function startAutoTitlePoller(orch, intervalMs = DEFAULT_AUTO_TITLE_POLL_MS) {
|
|
4662
|
+
if (intervalMs <= 0)
|
|
4663
|
+
return () => {};
|
|
4664
|
+
let running = false;
|
|
4665
|
+
const tick = () => {
|
|
4666
|
+
if (running)
|
|
4667
|
+
return;
|
|
4668
|
+
running = true;
|
|
4669
|
+
runAutoTitlePass(orch).then(() => runChatTabNamingPass(orch)).catch((err) => logDaemonError("auto-title-poller", err)).finally(() => {
|
|
4670
|
+
running = false;
|
|
4671
|
+
});
|
|
4672
|
+
};
|
|
4673
|
+
const timer = setInterval(tick, intervalMs);
|
|
4674
|
+
timer.unref?.();
|
|
4675
|
+
return () => clearInterval(timer);
|
|
4676
|
+
}
|
|
4677
|
+
var DEFAULT_AUTO_TITLE_POLL_MS = 4000;
|
|
4678
|
+
var init_auto_title_poller = __esm(() => {
|
|
4679
|
+
init_auto_title();
|
|
4680
|
+
init_core();
|
|
4681
|
+
init_chat_tab_naming();
|
|
4682
|
+
});
|
|
4683
|
+
|
|
4684
|
+
// src/daemon/event-bus.ts
|
|
4685
|
+
class DaemonEventBus {
|
|
4686
|
+
last = new Map;
|
|
4687
|
+
sinks = new Set;
|
|
4688
|
+
publish(channel, payload) {
|
|
4689
|
+
this.last.set(channel, payload);
|
|
4690
|
+
const event = { channel, payload };
|
|
4691
|
+
for (const sink of this.sinks)
|
|
4692
|
+
sink(event);
|
|
4693
|
+
}
|
|
4694
|
+
snapshot() {
|
|
4695
|
+
return [...this.last].map(([channel, payload]) => ({ channel, payload }));
|
|
4696
|
+
}
|
|
4697
|
+
onPublish(sink) {
|
|
4698
|
+
this.sinks.add(sink);
|
|
4699
|
+
return () => {
|
|
4700
|
+
this.sinks.delete(sink);
|
|
4701
|
+
};
|
|
4702
|
+
}
|
|
4703
|
+
}
|
|
4704
|
+
|
|
4705
|
+
// src/daemon/paths.ts
|
|
4706
|
+
import { createHash as createHash2 } from "crypto";
|
|
4707
|
+
import { homedir as homedir6, tmpdir } from "os";
|
|
4708
|
+
import { join as join3 } from "path";
|
|
4709
|
+
function shortHomeTag(homeDir2) {
|
|
4710
|
+
return createHash2("sha1").update(homeDir2).digest("hex").slice(0, 8);
|
|
4711
|
+
}
|
|
4712
|
+
function fitSocketPath(naturalPath, homeDir2, role, pidTag) {
|
|
4713
|
+
if (Buffer.byteLength(naturalPath, "utf8") <= SOCKET_PATH_SAFETY_LIMIT)
|
|
4714
|
+
return naturalPath;
|
|
4715
|
+
const tag = shortHomeTag(homeDir2);
|
|
4716
|
+
const suffix = pidTag === undefined ? "" : `-${pidTag}`;
|
|
4717
|
+
const fallback = join3(tmpdir(), `kobe-${tag}-${role}${suffix}.sock`);
|
|
4718
|
+
if (Buffer.byteLength(fallback, "utf8") <= SOCKET_PATH_SAFETY_LIMIT)
|
|
4719
|
+
return fallback;
|
|
4720
|
+
throw new Error(`kobe socket path exceeds ${SOCKET_PATH_SAFETY_LIMIT} bytes even after fallback: ${fallback}`);
|
|
4721
|
+
}
|
|
4722
|
+
function defaultDaemonSocketPath(homeDir2) {
|
|
4723
|
+
const override = process.env.KOBE_DAEMON_SOCKET_PATH;
|
|
4724
|
+
if (override && override.length > 0)
|
|
4725
|
+
return override;
|
|
4726
|
+
const explicit = homeDir2 ?? process.env.KOBE_HOME_DIR;
|
|
4727
|
+
if (explicit && explicit.length > 0) {
|
|
4728
|
+
return fitSocketPath(join3(explicit, ".kobe", "daemon.sock"), explicit, "daemon");
|
|
4729
|
+
}
|
|
4730
|
+
const runtimeDir = process.env.XDG_RUNTIME_DIR;
|
|
4731
|
+
if (runtimeDir && runtimeDir.length > 0) {
|
|
4732
|
+
return fitSocketPath(join3(runtimeDir, "kobe.sock"), runtimeDir, "daemon");
|
|
4733
|
+
}
|
|
4734
|
+
const home = homedir6();
|
|
4735
|
+
return fitSocketPath(join3(home, ".kobe", "daemon.sock"), home, "daemon");
|
|
4736
|
+
}
|
|
4737
|
+
function defaultDaemonPidPath(homeDir2 = process.env.KOBE_HOME_DIR ?? homedir6()) {
|
|
4738
|
+
const override = process.env.KOBE_DAEMON_PID_PATH;
|
|
4739
|
+
if (override && override.length > 0)
|
|
4740
|
+
return override;
|
|
4741
|
+
return join3(homeDir2, ".kobe", "daemon.pid");
|
|
4742
|
+
}
|
|
4743
|
+
function defaultDaemonLogPath(homeDir2 = process.env.KOBE_HOME_DIR ?? homedir6()) {
|
|
4744
|
+
return join3(homeDir2, ".kobe", "daemon.log");
|
|
4745
|
+
}
|
|
4746
|
+
var SOCKET_PATH_SAFETY_LIMIT = 100;
|
|
4747
|
+
var init_paths2 = () => {};
|
|
4748
|
+
|
|
4749
|
+
// src/daemon/server.ts
|
|
4750
|
+
import { mkdir as mkdir3, readFile as readFile5, unlink as unlink4, writeFile as writeFile3 } from "fs/promises";
|
|
4751
|
+
import { createServer } from "net";
|
|
4752
|
+
import { dirname as dirname3 } from "path";
|
|
4753
|
+
function resolveIdleGraceMs() {
|
|
4754
|
+
const raw = process.env.KOBE_DAEMON_IDLE_GRACE_MS;
|
|
4755
|
+
if (raw === undefined)
|
|
4756
|
+
return DEFAULT_IDLE_GRACE_MS;
|
|
4757
|
+
const n = Number(raw);
|
|
4758
|
+
return Number.isFinite(n) && n >= 0 ? n : DEFAULT_IDLE_GRACE_MS;
|
|
4759
|
+
}
|
|
4760
|
+
async function startDaemonServer(orch, options = {}) {
|
|
4761
|
+
const socketPath = options.socketPath ?? defaultDaemonSocketPath(options.homeDir);
|
|
4762
|
+
const pidPath = options.pidPath ?? defaultDaemonPidPath(options.homeDir);
|
|
4763
|
+
const startedAt = options.startedAt ?? new Date;
|
|
4764
|
+
const clients = new Set;
|
|
4765
|
+
let nextClientId = 1;
|
|
4766
|
+
const idleGraceMs = resolveIdleGraceMs();
|
|
4414
4767
|
let idleTimer = null;
|
|
4415
4768
|
let stopping = false;
|
|
4416
|
-
function
|
|
4769
|
+
function guiCount() {
|
|
4417
4770
|
let n = 0;
|
|
4418
4771
|
for (const c of clients)
|
|
4419
|
-
if (c.
|
|
4772
|
+
if (c.holdsLifetime)
|
|
4420
4773
|
n++;
|
|
4421
4774
|
return n;
|
|
4422
4775
|
}
|
|
@@ -4427,12 +4780,12 @@ async function startDaemonServer(orch, options = {}) {
|
|
|
4427
4780
|
}
|
|
4428
4781
|
}
|
|
4429
4782
|
function maybeArmIdleShutdown() {
|
|
4430
|
-
if (stopping ||
|
|
4783
|
+
if (stopping || guiCount() > 0)
|
|
4431
4784
|
return;
|
|
4432
4785
|
cancelIdleTimer();
|
|
4433
4786
|
idleTimer = setTimeout(() => {
|
|
4434
4787
|
idleTimer = null;
|
|
4435
|
-
if (stopping ||
|
|
4788
|
+
if (stopping || guiCount() > 0)
|
|
4436
4789
|
return;
|
|
4437
4790
|
stopSoon().catch((err) => logDaemonError("daemon-idle-shutdown", err));
|
|
4438
4791
|
}, idleGraceMs);
|
|
@@ -4451,7 +4804,8 @@ async function startDaemonServer(orch, options = {}) {
|
|
|
4451
4804
|
connectedAt: new Date,
|
|
4452
4805
|
socket,
|
|
4453
4806
|
buffer: "",
|
|
4454
|
-
subscribed: false
|
|
4807
|
+
subscribed: false,
|
|
4808
|
+
holdsLifetime: false
|
|
4455
4809
|
};
|
|
4456
4810
|
clients.add(client);
|
|
4457
4811
|
socket.on("data", (chunk) => {
|
|
@@ -4461,7 +4815,7 @@ async function startDaemonServer(orch, options = {}) {
|
|
|
4461
4815
|
socket.on("error", () => {});
|
|
4462
4816
|
socket.on("close", () => {
|
|
4463
4817
|
clients.delete(client);
|
|
4464
|
-
if (client.
|
|
4818
|
+
if (client.holdsLifetime)
|
|
4465
4819
|
maybeArmIdleShutdown();
|
|
4466
4820
|
});
|
|
4467
4821
|
});
|
|
@@ -4549,7 +4903,7 @@ async function startDaemonServer(orch, options = {}) {
|
|
|
4549
4903
|
daemonPid: process.pid,
|
|
4550
4904
|
uptimeMs: Date.now() - startedAt.getTime(),
|
|
4551
4905
|
startedAt: startedAt.toISOString(),
|
|
4552
|
-
attachedClients:
|
|
4906
|
+
attachedClients: guiCount(),
|
|
4553
4907
|
taskCount: orch.listTasks().length,
|
|
4554
4908
|
socketPath
|
|
4555
4909
|
};
|
|
@@ -4649,7 +5003,10 @@ async function startDaemonServer(orch, options = {}) {
|
|
|
4649
5003
|
}
|
|
4650
5004
|
case "subscribe": {
|
|
4651
5005
|
client.subscribed = true;
|
|
4652
|
-
|
|
5006
|
+
const role = payload.role === "gui" ? "gui" : "pane";
|
|
5007
|
+
client.holdsLifetime = role === "gui";
|
|
5008
|
+
if (client.holdsLifetime)
|
|
5009
|
+
cancelIdleTimer();
|
|
4653
5010
|
for (const event of bus.snapshot()) {
|
|
4654
5011
|
writeFrame(client, { type: "event", name: event.channel, payload: event.payload });
|
|
4655
5012
|
}
|
|
@@ -5071,288 +5428,54 @@ var init_repo_cmd = __esm(() => {
|
|
|
5071
5428
|
`);
|
|
5072
5429
|
});
|
|
5073
5430
|
|
|
5074
|
-
// src/engine/interactive-command.ts
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
}
|
|
5078
|
-
function defaultEngineCommand(vendor) {
|
|
5079
|
-
return DEFAULT_COMMANDS[vendor ?? "claude"] ?? DEFAULT_COMMANDS.claude;
|
|
5080
|
-
}
|
|
5081
|
-
function parseEngineCommand(command) {
|
|
5082
|
-
const out = [];
|
|
5083
|
-
const re = /"([^"]*)"|'([^']*)'|(\S+)/g;
|
|
5084
|
-
for (let m = re.exec(command);m !== null; m = re.exec(command)) {
|
|
5085
|
-
out.push(m[1] ?? m[2] ?? m[3] ?? "");
|
|
5086
|
-
}
|
|
5087
|
-
return out;
|
|
5088
|
-
}
|
|
5089
|
-
function interactiveEngineCommand(vendor) {
|
|
5090
|
-
const v = vendor ?? "claude";
|
|
5091
|
-
const override = getPersistedString(engineCommandKey(v))?.trim();
|
|
5092
|
-
if (override) {
|
|
5093
|
-
const argv = parseEngineCommand(override);
|
|
5094
|
-
if (argv.length > 0)
|
|
5095
|
-
return argv;
|
|
5096
|
-
}
|
|
5097
|
-
return defaultEngineCommand(v);
|
|
5098
|
-
}
|
|
5099
|
-
var DEFAULT_COMMANDS, VENDOR_LABEL;
|
|
5100
|
-
var init_interactive_command = __esm(() => {
|
|
5101
|
-
init_repos();
|
|
5102
|
-
DEFAULT_COMMANDS = {
|
|
5103
|
-
claude: ["claude"],
|
|
5104
|
-
codex: ["codex"],
|
|
5105
|
-
copilot: ["copilot"]
|
|
5106
|
-
};
|
|
5107
|
-
VENDOR_LABEL = {
|
|
5108
|
-
claude: "Claude",
|
|
5109
|
-
codex: "Codex",
|
|
5110
|
-
copilot: "Copilot"
|
|
5111
|
-
};
|
|
5112
|
-
});
|
|
5113
|
-
|
|
5114
|
-
// src/tmux/client.ts
|
|
5115
|
-
var exports_client = {};
|
|
5116
|
-
__export(exports_client, {
|
|
5117
|
-
windowCount: () => windowCount,
|
|
5118
|
-
tmuxSessionName: () => tmuxSessionName,
|
|
5119
|
-
tmuxCommandSequence: () => tmuxCommandSequence,
|
|
5120
|
-
tmuxAvailable: () => tmuxAvailable,
|
|
5121
|
-
tmuxArgs: () => tmuxArgs,
|
|
5122
|
-
tagPaneRole: () => tagPaneRole,
|
|
5123
|
-
tagClaudePane: () => tagClaudePane,
|
|
5124
|
-
switchClientBeforeKill: () => switchClientBeforeKill,
|
|
5125
|
-
setWindowOption: () => setWindowOption,
|
|
5126
|
-
setSessionOption: () => setSessionOption,
|
|
5127
|
-
sessionExists: () => sessionExists,
|
|
5128
|
-
sendKeys: () => sendKeys,
|
|
5129
|
-
sendKeyName: () => sendKeyName,
|
|
5130
|
-
runTmuxSequenceCapturing: () => runTmuxSequenceCapturing,
|
|
5131
|
-
runTmuxSequence: () => runTmuxSequence,
|
|
5132
|
-
runTmuxCapturing: () => runTmuxCapturing,
|
|
5133
|
-
runTmux: () => runTmux,
|
|
5134
|
-
paneIdByRole: () => paneIdByRole,
|
|
5135
|
-
newWindow: () => newWindow,
|
|
5136
|
-
killSession: () => killSession,
|
|
5137
|
-
getSessionOptions: () => getSessionOptions,
|
|
5138
|
-
getSessionOption: () => getSessionOption,
|
|
5139
|
-
ensureFallbackSession: () => ensureFallbackSession,
|
|
5140
|
-
currentSessionName: () => currentSessionName,
|
|
5141
|
-
claudePaneIdStrict: () => claudePaneIdStrict,
|
|
5142
|
-
claudePaneId: () => claudePaneId,
|
|
5143
|
-
capturePaneById: () => capturePaneById,
|
|
5144
|
-
attachArgv: () => attachArgv,
|
|
5145
|
-
PANE_ROLE_OPTION: () => PANE_ROLE_OPTION,
|
|
5146
|
-
KOBE_TMUX_SOCKET: () => KOBE_TMUX_SOCKET,
|
|
5147
|
-
KOBE_HOME_SESSION: () => KOBE_HOME_SESSION,
|
|
5148
|
-
CLAUDE_ROLE_OPTION: () => CLAUDE_ROLE_OPTION
|
|
5149
|
-
});
|
|
5150
|
-
function tmuxArgs(...args) {
|
|
5151
|
-
return ["tmux", "-L", KOBE_TMUX_SOCKET, ...args];
|
|
5152
|
-
}
|
|
5153
|
-
function tmuxSessionName(taskId) {
|
|
5154
|
-
return `kobe-${taskId.replace(/[^A-Za-z0-9_-]/g, "")}`;
|
|
5155
|
-
}
|
|
5156
|
-
function attachArgv(name) {
|
|
5157
|
-
return tmuxArgs("attach-session", "-t", `=${name}`);
|
|
5158
|
-
}
|
|
5159
|
-
async function drainText(stream) {
|
|
5160
|
-
if (!stream)
|
|
5161
|
-
return "";
|
|
5162
|
-
try {
|
|
5163
|
-
return await new Response(stream).text();
|
|
5164
|
-
} catch {
|
|
5165
|
-
return "";
|
|
5166
|
-
}
|
|
5167
|
-
}
|
|
5168
|
-
async function runTmux(args) {
|
|
5169
|
-
const proc = Bun.spawn(tmuxArgs(...args), { stdin: "ignore", stdout: "ignore", stderr: "pipe" });
|
|
5170
|
-
const [errText, code] = await Promise.all([drainText(proc.stderr), proc.exited]);
|
|
5171
|
-
if (code !== 0 && errText.trim().length > 0) {
|
|
5172
|
-
console.error(`[kobe tmux] ${args.join(" ")} (${code}): ${errText.trim()}`);
|
|
5173
|
-
}
|
|
5174
|
-
return code;
|
|
5175
|
-
}
|
|
5176
|
-
async function runTmuxQuiet(args) {
|
|
5177
|
-
const proc = Bun.spawn(tmuxArgs(...args), { stdin: "ignore", stdout: "ignore", stderr: "ignore" });
|
|
5178
|
-
return proc.exited;
|
|
5179
|
-
}
|
|
5180
|
-
function tmuxCommandSequence(commands) {
|
|
5181
|
-
const out = [];
|
|
5182
|
-
for (const cmd of commands) {
|
|
5183
|
-
if (cmd.length === 0)
|
|
5184
|
-
continue;
|
|
5185
|
-
if (out.length > 0)
|
|
5186
|
-
out.push(";");
|
|
5187
|
-
out.push(...cmd);
|
|
5188
|
-
}
|
|
5189
|
-
return out;
|
|
5190
|
-
}
|
|
5191
|
-
async function runTmuxSequence(commands) {
|
|
5192
|
-
const args = tmuxCommandSequence(commands);
|
|
5193
|
-
return args.length === 0 ? 0 : runTmux(args);
|
|
5194
|
-
}
|
|
5195
|
-
async function runTmuxCapturing(args) {
|
|
5196
|
-
const proc = Bun.spawn(tmuxArgs(...args), { stdin: "ignore", stdout: "pipe", stderr: "pipe" });
|
|
5197
|
-
const [stdout, errText, code] = await Promise.all([drainText(proc.stdout), drainText(proc.stderr), proc.exited]);
|
|
5198
|
-
if (code !== 0 && errText.trim().length > 0) {
|
|
5199
|
-
console.error(`[kobe tmux] ${args.join(" ")} (${code}): ${errText.trim()}`);
|
|
5200
|
-
}
|
|
5201
|
-
return { code, stdout };
|
|
5202
|
-
}
|
|
5203
|
-
async function runTmuxSequenceCapturing(commands) {
|
|
5204
|
-
const args = tmuxCommandSequence(commands);
|
|
5205
|
-
return args.length === 0 ? { code: 0, stdout: "" } : runTmuxCapturing(args);
|
|
5206
|
-
}
|
|
5207
|
-
async function tmuxAvailable() {
|
|
5208
|
-
try {
|
|
5209
|
-
const proc = Bun.spawn(["tmux", "-V"], { stdin: "ignore", stdout: "ignore", stderr: "ignore" });
|
|
5210
|
-
return await proc.exited === 0;
|
|
5211
|
-
} catch {
|
|
5212
|
-
return false;
|
|
5213
|
-
}
|
|
5214
|
-
}
|
|
5215
|
-
async function sessionExists(name) {
|
|
5216
|
-
return await runTmuxQuiet(["has-session", "-t", `=${name}`]) === 0;
|
|
5217
|
-
}
|
|
5218
|
-
async function windowCount(sessionName) {
|
|
5219
|
-
const { code, stdout } = await runTmuxCapturing(["list-windows", "-t", `=${sessionName}`, "-F", "#{window_id}"]);
|
|
5220
|
-
if (code !== 0)
|
|
5221
|
-
return 0;
|
|
5222
|
-
return stdout.split(`
|
|
5223
|
-
`).filter((l) => l.trim().length > 0).length;
|
|
5224
|
-
}
|
|
5225
|
-
async function setSessionOption(session, option, value) {
|
|
5226
|
-
await runTmux(["set-option", "-t", session, option, value]);
|
|
5227
|
-
}
|
|
5228
|
-
async function getSessionOption(session, option) {
|
|
5229
|
-
const { code, stdout } = await runTmuxCapturing(["show-options", "-v", "-t", session, option]);
|
|
5230
|
-
return code === 0 ? stdout.trim() : "";
|
|
5231
|
-
}
|
|
5232
|
-
async function getSessionOptions(session, options) {
|
|
5233
|
-
const values = Object.fromEntries(options.map((option) => [option, undefined]));
|
|
5234
|
-
const { code, stdout } = await runTmuxSequenceCapturing(options.map((option) => ["show-options", "-q", "-t", session, option]));
|
|
5235
|
-
if (code !== 0)
|
|
5236
|
-
return values;
|
|
5237
|
-
for (const line of stdout.split(`
|
|
5238
|
-
`)) {
|
|
5239
|
-
const idx = line.indexOf(" ");
|
|
5240
|
-
if (idx <= 0)
|
|
5241
|
-
continue;
|
|
5242
|
-
const option = line.slice(0, idx);
|
|
5243
|
-
if (option in values)
|
|
5244
|
-
values[option] = line.slice(idx + 1).trim();
|
|
5245
|
-
}
|
|
5246
|
-
return values;
|
|
5247
|
-
}
|
|
5248
|
-
async function tagPaneRole(paneId, role) {
|
|
5249
|
-
await runTmux(["set-option", "-p", "-t", paneId, PANE_ROLE_OPTION, role]);
|
|
5250
|
-
}
|
|
5251
|
-
async function setWindowOption(target, option, value) {
|
|
5252
|
-
await runTmux(["set-window-option", "-t", target, option, value]);
|
|
5253
|
-
}
|
|
5254
|
-
async function tagClaudePane(paneId) {
|
|
5255
|
-
await tagPaneRole(paneId, CLAUDE_ROLE_VALUE);
|
|
5256
|
-
}
|
|
5257
|
-
async function paneIdByRole(sessionName, role, fallbackFirst = false) {
|
|
5258
|
-
const { code, stdout } = await runTmuxCapturing([
|
|
5259
|
-
"list-panes",
|
|
5260
|
-
"-t",
|
|
5261
|
-
`=${sessionName}`,
|
|
5262
|
-
"-F",
|
|
5263
|
-
`#{pane_id} #{${PANE_ROLE_OPTION}}`
|
|
5264
|
-
]);
|
|
5265
|
-
if (code !== 0)
|
|
5266
|
-
return "";
|
|
5267
|
-
let firstId = "";
|
|
5268
|
-
for (const line of stdout.split(`
|
|
5269
|
-
`)) {
|
|
5270
|
-
const [id, paneRole] = line.split("\t");
|
|
5271
|
-
if (!id)
|
|
5272
|
-
continue;
|
|
5273
|
-
if (!firstId)
|
|
5274
|
-
firstId = id.trim();
|
|
5275
|
-
if (paneRole?.trim() === role)
|
|
5276
|
-
return id.trim();
|
|
5277
|
-
}
|
|
5278
|
-
return fallbackFirst ? firstId : "";
|
|
5279
|
-
}
|
|
5280
|
-
async function claudePaneId(sessionName) {
|
|
5281
|
-
return paneIdByRole(sessionName, CLAUDE_ROLE_VALUE, true);
|
|
5282
|
-
}
|
|
5283
|
-
async function claudePaneIdStrict(sessionName) {
|
|
5284
|
-
return paneIdByRole(sessionName, CLAUDE_ROLE_VALUE, false);
|
|
5285
|
-
}
|
|
5286
|
-
async function capturePaneById(paneId, lines) {
|
|
5287
|
-
if (!paneId)
|
|
5288
|
-
return "";
|
|
5289
|
-
const args = ["capture-pane", "-t", paneId, "-p"];
|
|
5290
|
-
if (typeof lines === "number" && lines > 0)
|
|
5291
|
-
args.push("-S", String(-lines));
|
|
5292
|
-
const { code, stdout } = await runTmuxCapturing(args);
|
|
5293
|
-
return code === 0 ? stdout : "";
|
|
5294
|
-
}
|
|
5295
|
-
async function sendKeys(target, text) {
|
|
5296
|
-
await runTmux(["send-keys", "-t", target, "-l", "--", text]);
|
|
5297
|
-
}
|
|
5298
|
-
async function sendKeyName(target, key) {
|
|
5299
|
-
await runTmux(["send-keys", "-t", target, key]);
|
|
5300
|
-
}
|
|
5301
|
-
async function newWindow(session, opts) {
|
|
5302
|
-
const args = ["new-window", "-t", `=${session}`, "-c", opts.cwd];
|
|
5303
|
-
if (opts.name)
|
|
5304
|
-
args.push("-n", opts.name);
|
|
5305
|
-
args.push(opts.command);
|
|
5306
|
-
await runTmux(args);
|
|
5307
|
-
}
|
|
5308
|
-
async function currentSessionName() {
|
|
5309
|
-
const args = ["display-message", "-p"];
|
|
5310
|
-
const target = process.env.TMUX_PANE;
|
|
5311
|
-
if (target && target.length > 0)
|
|
5312
|
-
args.push("-t", target);
|
|
5313
|
-
args.push("#{session_name}");
|
|
5314
|
-
const { code, stdout } = await runTmuxCapturing(args);
|
|
5315
|
-
const name = stdout.trim();
|
|
5316
|
-
return code === 0 && name.length > 0 ? name : null;
|
|
5431
|
+
// src/engine/interactive-command.ts
|
|
5432
|
+
import { randomUUID } from "crypto";
|
|
5433
|
+
function engineCommandKey(vendor) {
|
|
5434
|
+
return `engineCommand.${vendor}`;
|
|
5317
5435
|
}
|
|
5318
|
-
|
|
5319
|
-
|
|
5320
|
-
await runTmux(["kill-session", "-t", `=${name}`]);
|
|
5436
|
+
function defaultEngineCommand(vendor) {
|
|
5437
|
+
return DEFAULT_COMMANDS[vendor ?? "claude"] ?? DEFAULT_COMMANDS.claude;
|
|
5321
5438
|
}
|
|
5322
|
-
|
|
5323
|
-
const
|
|
5324
|
-
|
|
5325
|
-
|
|
5326
|
-
|
|
5327
|
-
"-d",
|
|
5328
|
-
"-s",
|
|
5329
|
-
name,
|
|
5330
|
-
"-x",
|
|
5331
|
-
"220",
|
|
5332
|
-
"-y",
|
|
5333
|
-
"50",
|
|
5334
|
-
"sh",
|
|
5335
|
-
"-c",
|
|
5336
|
-
'clear; printf "\\n No active task\\n\\n Select a task from the sidebar to continue.\\n\\n"; exec ${SHELL:-sh}'
|
|
5337
|
-
]);
|
|
5439
|
+
function parseEngineCommand(command) {
|
|
5440
|
+
const out = [];
|
|
5441
|
+
const re = /"([^"]*)"|'([^']*)'|(\S+)/g;
|
|
5442
|
+
for (let m = re.exec(command);m !== null; m = re.exec(command)) {
|
|
5443
|
+
out.push(m[1] ?? m[2] ?? m[3] ?? "");
|
|
5338
5444
|
}
|
|
5339
|
-
return
|
|
5445
|
+
return out;
|
|
5340
5446
|
}
|
|
5341
|
-
|
|
5342
|
-
const
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
|
|
5447
|
+
function interactiveEngineCommand(vendor) {
|
|
5448
|
+
const v = vendor ?? "claude";
|
|
5449
|
+
const override = getPersistedString(engineCommandKey(v))?.trim();
|
|
5450
|
+
if (override) {
|
|
5451
|
+
const argv = parseEngineCommand(override);
|
|
5452
|
+
if (argv.length > 0)
|
|
5453
|
+
return argv;
|
|
5348
5454
|
}
|
|
5349
|
-
|
|
5350
|
-
await runTmux(["switch-client", "-t", `=${fallback}`]);
|
|
5455
|
+
return defaultEngineCommand(v);
|
|
5351
5456
|
}
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
|
|
5457
|
+
function withClaudeSessionId(argv, vendor) {
|
|
5458
|
+
if ((vendor ?? "claude") !== "claude")
|
|
5459
|
+
return { argv, sessionId: null };
|
|
5460
|
+
if (argv.some((a) => CLAUDE_SESSION_CONTROL_FLAGS.has(a)))
|
|
5461
|
+
return { argv, sessionId: null };
|
|
5462
|
+
const sessionId = randomUUID();
|
|
5463
|
+
return { argv: [...argv, "--session-id", sessionId], sessionId };
|
|
5464
|
+
}
|
|
5465
|
+
var DEFAULT_COMMANDS, VENDOR_LABEL, CLAUDE_SESSION_CONTROL_FLAGS;
|
|
5466
|
+
var init_interactive_command = __esm(() => {
|
|
5467
|
+
init_repos();
|
|
5468
|
+
DEFAULT_COMMANDS = {
|
|
5469
|
+
claude: ["claude"],
|
|
5470
|
+
codex: ["codex"],
|
|
5471
|
+
copilot: ["copilot"]
|
|
5472
|
+
};
|
|
5473
|
+
VENDOR_LABEL = {
|
|
5474
|
+
claude: "Claude",
|
|
5475
|
+
codex: "Codex",
|
|
5476
|
+
copilot: "Copilot"
|
|
5477
|
+
};
|
|
5478
|
+
CLAUDE_SESSION_CONTROL_FLAGS = new Set(["--session-id", "--resume", "-r", "--continue", "-c", "--from-pr"]);
|
|
5356
5479
|
});
|
|
5357
5480
|
|
|
5358
5481
|
// src/tmux/prompt-delivery.ts
|
|
@@ -5475,6 +5598,7 @@ __export(exports_tmux, {
|
|
|
5475
5598
|
tmuxAvailable: () => tmuxAvailable,
|
|
5476
5599
|
switchClientBeforeKill: () => switchClientBeforeKill,
|
|
5477
5600
|
sessionExists: () => sessionExists,
|
|
5601
|
+
refreshKobeWorkspacePanes: () => refreshKobeWorkspacePanes,
|
|
5478
5602
|
quickCreate: () => quickCreate,
|
|
5479
5603
|
openUpdateTab: () => openUpdateTab,
|
|
5480
5604
|
openSettingsTab: () => openSettingsTab,
|
|
@@ -5482,6 +5606,7 @@ __export(exports_tmux, {
|
|
|
5482
5606
|
newChatTab: () => newChatTab,
|
|
5483
5607
|
killSession: () => killSession,
|
|
5484
5608
|
ensureSession: () => ensureSession,
|
|
5609
|
+
currentSessionName: () => currentSessionName,
|
|
5485
5610
|
attachArgv: () => attachArgv,
|
|
5486
5611
|
PANE_VERSION_OPTION: () => PANE_VERSION_OPTION,
|
|
5487
5612
|
CHAT_TAB_SWITCH_BINDINGS: () => CHAT_TAB_SWITCH_BINDINGS,
|
|
@@ -5544,6 +5669,7 @@ async function ensureSessionImpl(opts) {
|
|
|
5544
5669
|
await runTmux(["kill-session", "-t", `=${opts.name}`]);
|
|
5545
5670
|
}
|
|
5546
5671
|
const inv = kobeCliInvocation();
|
|
5672
|
+
const launch = withClaudeSessionId(opts.command, opts.vendor);
|
|
5547
5673
|
const r0 = await runTmuxCapturing([
|
|
5548
5674
|
"new-session",
|
|
5549
5675
|
"-d",
|
|
@@ -5555,7 +5681,7 @@ async function ensureSessionImpl(opts) {
|
|
|
5555
5681
|
"-P",
|
|
5556
5682
|
"-F",
|
|
5557
5683
|
"#{pane_id}",
|
|
5558
|
-
engineLaunchLine(shellQuoteArgv(
|
|
5684
|
+
engineLaunchLine(shellQuoteArgv(launch.argv), {
|
|
5559
5685
|
initScript: opts.initScript,
|
|
5560
5686
|
markerPath: opts.initScript ? worktreeInitMarkerPath(opts.cwd) : undefined
|
|
5561
5687
|
})
|
|
@@ -5565,6 +5691,8 @@ async function ensureSessionImpl(opts) {
|
|
|
5565
5691
|
console.error("[kobe tmux] new-session returned no pane id; session creation failed");
|
|
5566
5692
|
return false;
|
|
5567
5693
|
}
|
|
5694
|
+
if (launch.sessionId)
|
|
5695
|
+
await setWindowOption(pane0, CHAT_TAB_SESSION_ID_OPTION, launch.sessionId);
|
|
5568
5696
|
await runTmuxSequence([
|
|
5569
5697
|
...opts.taskId ? [["set-option", "-t", opts.name, "@kobe_task", opts.taskId]] : [],
|
|
5570
5698
|
["set-option", "-t", opts.name, "@kobe_worktree", opts.cwd],
|
|
@@ -5706,6 +5834,58 @@ async function healKobePaneVersions(session, cwd, taskId, vendor) {
|
|
|
5706
5834
|
if (commands.length > 0)
|
|
5707
5835
|
await runTmuxSequence(commands);
|
|
5708
5836
|
}
|
|
5837
|
+
async function refreshKobeWorkspacePanes(session) {
|
|
5838
|
+
const sessionOptions = await getSessionOptions(session, ["@kobe_worktree", "@kobe_task", "@kobe_vendor"]);
|
|
5839
|
+
const cwd = sessionOptions["@kobe_worktree"] || process.cwd();
|
|
5840
|
+
const taskId = sessionOptions["@kobe_task"] || undefined;
|
|
5841
|
+
const vendor = sessionOptions["@kobe_vendor"] || undefined;
|
|
5842
|
+
const inv = kobeCliInvocation();
|
|
5843
|
+
const envPrefix = inheritedEnvPrefix();
|
|
5844
|
+
const { code, stdout } = await runTmuxCapturing([
|
|
5845
|
+
"list-panes",
|
|
5846
|
+
"-s",
|
|
5847
|
+
"-t",
|
|
5848
|
+
`=${session}`,
|
|
5849
|
+
"-F",
|
|
5850
|
+
`#{window_id} #{pane_id} #{@kobe_role} #{${PANE_VERSION_OPTION}}`
|
|
5851
|
+
]);
|
|
5852
|
+
if (code !== 0)
|
|
5853
|
+
return;
|
|
5854
|
+
const byWindow = new Map;
|
|
5855
|
+
for (const row of parseKobePaneRows(stdout)) {
|
|
5856
|
+
const panes = byWindow.get(row.windowId) ?? [];
|
|
5857
|
+
panes.push(row);
|
|
5858
|
+
byWindow.set(row.windowId, panes);
|
|
5859
|
+
}
|
|
5860
|
+
const commands = [];
|
|
5861
|
+
for (const panes of byWindow.values()) {
|
|
5862
|
+
const claudePane = panes.find((pane) => pane.role === "claude")?.paneId;
|
|
5863
|
+
const tasksPane = panes.find((pane) => pane.role === "tasks");
|
|
5864
|
+
const opsPane = panes.find((pane) => pane.role === "ops");
|
|
5865
|
+
if (tasksPane) {
|
|
5866
|
+
commands.push(["respawn-pane", "-k", "-t", tasksPane.paneId, "-c", cwd, keepAlive(envPrefix + tasksPaneCommand(inv))], ["set-option", "-p", "-t", tasksPane.paneId, "@kobe_role", "tasks"], ["set-option", "-p", "-t", tasksPane.paneId, PANE_VERSION_OPTION, CURRENT_VERSION]);
|
|
5867
|
+
}
|
|
5868
|
+
if (opsPane && claudePane) {
|
|
5869
|
+
commands.push([
|
|
5870
|
+
"respawn-pane",
|
|
5871
|
+
"-k",
|
|
5872
|
+
"-t",
|
|
5873
|
+
opsPane.paneId,
|
|
5874
|
+
"-c",
|
|
5875
|
+
cwd,
|
|
5876
|
+
keepAlive(envPrefix + opsPaneCommand({
|
|
5877
|
+
cwd,
|
|
5878
|
+
taskId,
|
|
5879
|
+
claudePaneId: claudePane,
|
|
5880
|
+
cliInvocation: inv,
|
|
5881
|
+
vendor
|
|
5882
|
+
}))
|
|
5883
|
+
], ["set-option", "-p", "-t", opsPane.paneId, "@kobe_role", "ops"], ["set-option", "-p", "-t", opsPane.paneId, PANE_VERSION_OPTION, CURRENT_VERSION]);
|
|
5884
|
+
}
|
|
5885
|
+
}
|
|
5886
|
+
if (commands.length > 0)
|
|
5887
|
+
await runTmuxSequence(commands);
|
|
5888
|
+
}
|
|
5709
5889
|
function inheritedEnvPrefix() {
|
|
5710
5890
|
const parts = [];
|
|
5711
5891
|
for (const key of ["KOBE_HOME_DIR", "KOBE_DAEMON_SOCKET_PATH", "KOBE_TMUX_SOCKET"]) {
|
|
@@ -5778,6 +5958,7 @@ async function newChatTab(session, vendorOverride) {
|
|
|
5778
5958
|
if (vendorOverride)
|
|
5779
5959
|
await rememberSessionVendor(session, taskId, vendorOverride);
|
|
5780
5960
|
const command = interactiveEngineCommand(vendor);
|
|
5961
|
+
const launch = withClaudeSessionId(command, vendor);
|
|
5781
5962
|
const inv = kobeCliInvocation();
|
|
5782
5963
|
const r = await runTmuxCapturing([
|
|
5783
5964
|
"new-window",
|
|
@@ -5788,11 +5969,13 @@ async function newChatTab(session, vendorOverride) {
|
|
|
5788
5969
|
"-P",
|
|
5789
5970
|
"-F",
|
|
5790
5971
|
"#{pane_id}",
|
|
5791
|
-
keepAlive(shellQuoteArgv(
|
|
5972
|
+
keepAlive(shellQuoteArgv(launch.argv))
|
|
5792
5973
|
]);
|
|
5793
5974
|
const claudePane = r.stdout.trim();
|
|
5794
5975
|
if (!claudePane)
|
|
5795
5976
|
return;
|
|
5977
|
+
if (launch.sessionId)
|
|
5978
|
+
await setWindowOption(claudePane, CHAT_TAB_SESSION_ID_OPTION, launch.sessionId);
|
|
5796
5979
|
await buildPanesAround(claudePane, { cwd, taskId, inv, vendor });
|
|
5797
5980
|
}
|
|
5798
5981
|
async function openSettingsTab(session) {
|
|
@@ -5944,7 +6127,8 @@ function readWorktreeChanges(worktreePath) {
|
|
|
5944
6127
|
const out = spawnSync3("git", ["status", "--porcelain=v1"], {
|
|
5945
6128
|
cwd: worktreePath,
|
|
5946
6129
|
encoding: "utf8",
|
|
5947
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
6130
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
6131
|
+
env: { ...process.env, GIT_OPTIONAL_LOCKS: "0" }
|
|
5948
6132
|
});
|
|
5949
6133
|
if (out.status !== 0 || !out.stdout)
|
|
5950
6134
|
return ZERO;
|
|
@@ -8440,6 +8624,7 @@ class RemoteOrchestrator {
|
|
|
8440
8624
|
connectionStateAcc;
|
|
8441
8625
|
setConnectionState;
|
|
8442
8626
|
ensureReachable;
|
|
8627
|
+
role;
|
|
8443
8628
|
constructor(client, options = {}) {
|
|
8444
8629
|
this.client = client;
|
|
8445
8630
|
const [tasks, setTasks] = createSignal([]);
|
|
@@ -8455,6 +8640,7 @@ class RemoteOrchestrator {
|
|
|
8455
8640
|
this.connectionStateAcc = connectionState;
|
|
8456
8641
|
this.setConnectionState = (next) => setConnectionState(() => next);
|
|
8457
8642
|
this.ensureReachable = options.ensureReachable ?? ensureDaemonReachable;
|
|
8643
|
+
this.role = options.role ?? "pane";
|
|
8458
8644
|
this.client.on("*", (frame) => this.handleEvent(frame.name, frame.payload));
|
|
8459
8645
|
this.client.onLifecycle("close", () => this.setConnectionState("disconnected"));
|
|
8460
8646
|
}
|
|
@@ -8475,7 +8661,7 @@ class RemoteOrchestrator {
|
|
|
8475
8661
|
}
|
|
8476
8662
|
if (hello.tasks)
|
|
8477
8663
|
this.setTasks(hello.tasks.map(deserializeTask));
|
|
8478
|
-
await this.client.subscribe();
|
|
8664
|
+
await this.client.subscribe({ role: this.role });
|
|
8479
8665
|
this.setConnectionState("online");
|
|
8480
8666
|
}
|
|
8481
8667
|
connectionStateSignal() {
|
|
@@ -12820,6 +13006,15 @@ var init_account_detect = __esm(() => {
|
|
|
12820
13006
|
};
|
|
12821
13007
|
});
|
|
12822
13008
|
|
|
13009
|
+
// src/tui/lib/editor-prefs.ts
|
|
13010
|
+
function normalizeEditorKind(value) {
|
|
13011
|
+
return value === "nano" || value === "custom" || value === "vim" ? value : DEFAULT_EDITOR_KIND;
|
|
13012
|
+
}
|
|
13013
|
+
var EDITOR_KINDS, EDITOR_KIND_KEY = "editor.kind", EDITOR_CUSTOM_KEY = "editor.customCommand", DEFAULT_EDITOR_KIND = "vim";
|
|
13014
|
+
var init_editor_prefs = __esm(() => {
|
|
13015
|
+
EDITOR_KINDS = ["vim", "nano", "custom"];
|
|
13016
|
+
});
|
|
13017
|
+
|
|
12823
13018
|
// src/tui/lib/settings-surface.ts
|
|
12824
13019
|
function normalizeSettingsSurface(value) {
|
|
12825
13020
|
return value === "taskpanel" ? "taskpanel" : "chattab";
|
|
@@ -13008,7 +13203,7 @@ function devRowCount(hasDaemon) {
|
|
|
13008
13203
|
return hasDaemon ? 2 : 1;
|
|
13009
13204
|
}
|
|
13010
13205
|
function generalRowCount(themeCount, focusAccentCount) {
|
|
13011
|
-
return themeCount + 1 + focusAccentCount +
|
|
13206
|
+
return themeCount + 1 + focusAccentCount + 6;
|
|
13012
13207
|
}
|
|
13013
13208
|
function bodyRowCount(section, themeCount, focusAccentCount, hasDaemon) {
|
|
13014
13209
|
if (section === "general")
|
|
@@ -13043,6 +13238,12 @@ function surfaceChattabRowIndex(themeCount, focusAccentCount) {
|
|
|
13043
13238
|
function surfaceTaskpanelRowIndex(themeCount, focusAccentCount) {
|
|
13044
13239
|
return surfaceChattabRowIndex(themeCount, focusAccentCount) + 1;
|
|
13045
13240
|
}
|
|
13241
|
+
function editorKindRowIndex(themeCount, focusAccentCount) {
|
|
13242
|
+
return surfaceTaskpanelRowIndex(themeCount, focusAccentCount) + 1;
|
|
13243
|
+
}
|
|
13244
|
+
function editorCustomRowIndex(themeCount, focusAccentCount) {
|
|
13245
|
+
return editorKindRowIndex(themeCount, focusAccentCount) + 1;
|
|
13246
|
+
}
|
|
13046
13247
|
var SECTIONS, FOCUS_ACCENT_LABEL;
|
|
13047
13248
|
var init_model = __esm(() => {
|
|
13048
13249
|
init_vendor();
|
|
@@ -13111,13 +13312,17 @@ function GeneralSettingsSection(props) {
|
|
|
13111
13312
|
const soundRow = () => soundRowIndex(props.themeNames().length, FOCUS_ACCENT_SLOTS.length);
|
|
13112
13313
|
const surfaceChattabRow = () => surfaceChattabRowIndex(props.themeNames().length, FOCUS_ACCENT_SLOTS.length);
|
|
13113
13314
|
const surfaceTaskpanelRow = () => surfaceTaskpanelRowIndex(props.themeNames().length, FOCUS_ACCENT_SLOTS.length);
|
|
13315
|
+
const editorKindRow = () => editorKindRowIndex(props.themeNames().length, FOCUS_ACCENT_SLOTS.length);
|
|
13316
|
+
const editorCustomRow = () => editorCustomRowIndex(props.themeNames().length, FOCUS_ACCENT_SLOTS.length);
|
|
13114
13317
|
const isTransparentRow = () => props.bodyRow() === transparentRowIndex(props.themeNames().length);
|
|
13115
13318
|
const isToastRow = () => props.bodyRow() === toastRow();
|
|
13116
13319
|
const isSoundRow = () => props.bodyRow() === soundRow();
|
|
13117
13320
|
const isSurfaceChattabRow = () => props.bodyRow() === surfaceChattabRow();
|
|
13118
13321
|
const isSurfaceTaskpanelRow = () => props.bodyRow() === surfaceTaskpanelRow();
|
|
13322
|
+
const isEditorKindRow = () => props.bodyRow() === editorKindRow();
|
|
13323
|
+
const isEditorCustomRow = () => props.bodyRow() === editorCustomRow();
|
|
13119
13324
|
return (() => {
|
|
13120
|
-
var _el$4 = createElement("box"), _el$5 = createElement("text"), _el$7 = createElement("text"), _el$9 = createElement("box"), _el$0 = createElement("box"), _el$1 = createElement("text"), _el$11 = createElement("text"), _el$13 = createElement("box"), _el$14 = createElement("text"), _el$15 = createElement("box"), _el$16 = createElement("text"), _el$18 = createElement("text"), _el$20 = createElement("box"), _el$21 = createElement("text"), _el$23 = createElement("text"), _el$25 = createElement("box"), _el$26 = createElement("text"), _el$27 = createTextNode(` Toast`), _el$28 = createElement("box"), _el$29 = createElement("text"), _el$30 = createTextNode(` Sound`), _el$31 = createElement("box"), _el$32 = createElement("text"), _el$34 = createElement("text"), _el$36 = createElement("box"), _el$37 = createElement("text"), _el$38 = createTextNode(` ChatTab (separate page)`), _el$39 = createElement("box"), _el$40 = createElement("text"), _el$41 = createTextNode(` Task panel (in-pane overlay)`);
|
|
13325
|
+
var _el$4 = createElement("box"), _el$5 = createElement("text"), _el$7 = createElement("text"), _el$9 = createElement("box"), _el$0 = createElement("box"), _el$1 = createElement("text"), _el$11 = createElement("text"), _el$13 = createElement("box"), _el$14 = createElement("text"), _el$15 = createElement("box"), _el$16 = createElement("text"), _el$18 = createElement("text"), _el$20 = createElement("box"), _el$21 = createElement("text"), _el$23 = createElement("text"), _el$25 = createElement("box"), _el$26 = createElement("text"), _el$27 = createTextNode(` Toast`), _el$28 = createElement("box"), _el$29 = createElement("text"), _el$30 = createTextNode(` Sound`), _el$31 = createElement("box"), _el$32 = createElement("text"), _el$34 = createElement("text"), _el$36 = createElement("box"), _el$37 = createElement("text"), _el$38 = createTextNode(` ChatTab (separate page)`), _el$39 = createElement("box"), _el$40 = createElement("text"), _el$41 = createTextNode(` Task panel (in-pane overlay)`), _el$42 = createElement("box"), _el$43 = createElement("text"), _el$45 = createElement("text"), _el$47 = createElement("box"), _el$48 = createElement("text"), _el$49 = createElement("box"), _el$50 = createElement("text");
|
|
13121
13326
|
insertNode(_el$4, _el$5);
|
|
13122
13327
|
insertNode(_el$4, _el$7);
|
|
13123
13328
|
insertNode(_el$4, _el$9);
|
|
@@ -13125,6 +13330,7 @@ function GeneralSettingsSection(props) {
|
|
|
13125
13330
|
insertNode(_el$4, _el$15);
|
|
13126
13331
|
insertNode(_el$4, _el$20);
|
|
13127
13332
|
insertNode(_el$4, _el$31);
|
|
13333
|
+
insertNode(_el$4, _el$42);
|
|
13128
13334
|
setProp(_el$4, "flexDirection", "column");
|
|
13129
13335
|
setProp(_el$4, "gap", 1);
|
|
13130
13336
|
insertNode(_el$5, createTextNode(`Theme`));
|
|
@@ -13139,33 +13345,33 @@ function GeneralSettingsSection(props) {
|
|
|
13139
13345
|
const isCursor = () => props.level() === "body" && props.bodyRow() === i();
|
|
13140
13346
|
const isSelected = () => name === themeCtx.selected;
|
|
13141
13347
|
return (() => {
|
|
13142
|
-
var _el$
|
|
13143
|
-
insertNode(_el$
|
|
13144
|
-
setProp(_el$
|
|
13145
|
-
setProp(_el$
|
|
13146
|
-
setProp(_el$
|
|
13147
|
-
setProp(_el$
|
|
13148
|
-
setProp(_el$
|
|
13348
|
+
var _el$51 = createElement("box"), _el$52 = createElement("text");
|
|
13349
|
+
insertNode(_el$51, _el$52);
|
|
13350
|
+
setProp(_el$51, "flexDirection", "row");
|
|
13351
|
+
setProp(_el$51, "gap", 1);
|
|
13352
|
+
setProp(_el$51, "paddingLeft", 1);
|
|
13353
|
+
setProp(_el$51, "paddingRight", 1);
|
|
13354
|
+
setProp(_el$51, "onMouseUp", () => {
|
|
13149
13355
|
props.setLevel("body");
|
|
13150
13356
|
props.setBodyRow(i());
|
|
13151
13357
|
props.setThemeCursor(i());
|
|
13152
|
-
|
|
13358
|
+
props.selectTheme(name);
|
|
13153
13359
|
});
|
|
13154
|
-
setProp(_el$
|
|
13155
|
-
insert(_el$
|
|
13156
|
-
insert(_el$
|
|
13360
|
+
setProp(_el$52, "wrapMode", "none");
|
|
13361
|
+
insert(_el$52, () => isSelected() ? "\u25CF " : " ", null);
|
|
13362
|
+
insert(_el$52, name, null);
|
|
13157
13363
|
effect((_p$) => {
|
|
13158
|
-
var _v$
|
|
13159
|
-
_v$
|
|
13160
|
-
_v$
|
|
13161
|
-
_v$
|
|
13364
|
+
var _v$40 = isCursor() ? theme.primary : undefined, _v$41 = isCursor() ? theme.selectedListItemText : isSelected() ? theme.accent : theme.text, _v$42 = isCursor() || isSelected() ? TextAttributes5.BOLD : undefined;
|
|
13365
|
+
_v$40 !== _p$.e && (_p$.e = setProp(_el$51, "backgroundColor", _v$40, _p$.e));
|
|
13366
|
+
_v$41 !== _p$.t && (_p$.t = setProp(_el$52, "fg", _v$41, _p$.t));
|
|
13367
|
+
_v$42 !== _p$.a && (_p$.a = setProp(_el$52, "attributes", _v$42, _p$.a));
|
|
13162
13368
|
return _p$;
|
|
13163
13369
|
}, {
|
|
13164
13370
|
e: undefined,
|
|
13165
13371
|
t: undefined,
|
|
13166
13372
|
a: undefined
|
|
13167
13373
|
});
|
|
13168
|
-
return _el$
|
|
13374
|
+
return _el$51;
|
|
13169
13375
|
})();
|
|
13170
13376
|
}
|
|
13171
13377
|
}));
|
|
@@ -13185,7 +13391,7 @@ function GeneralSettingsSection(props) {
|
|
|
13185
13391
|
setProp(_el$13, "onMouseUp", () => {
|
|
13186
13392
|
props.setLevel("body");
|
|
13187
13393
|
props.setBodyRow(transparentRowIndex(props.themeNames().length));
|
|
13188
|
-
|
|
13394
|
+
props.toggleTransparent();
|
|
13189
13395
|
});
|
|
13190
13396
|
setProp(_el$14, "wrapMode", "none");
|
|
13191
13397
|
insert(_el$14, () => themeCtx.transparentBackground ? "[x] on" : "[ ] off");
|
|
@@ -13204,32 +13410,32 @@ function GeneralSettingsSection(props) {
|
|
|
13204
13410
|
const isCursor = () => props.level() === "body" && props.bodyRow() === rowIndex();
|
|
13205
13411
|
const isSelected = () => themeCtx.focusAccent === slot;
|
|
13206
13412
|
return (() => {
|
|
13207
|
-
var _el$
|
|
13208
|
-
insertNode(_el$
|
|
13209
|
-
setProp(_el$
|
|
13210
|
-
setProp(_el$
|
|
13211
|
-
setProp(_el$
|
|
13212
|
-
setProp(_el$
|
|
13213
|
-
setProp(_el$
|
|
13413
|
+
var _el$53 = createElement("box"), _el$54 = createElement("text");
|
|
13414
|
+
insertNode(_el$53, _el$54);
|
|
13415
|
+
setProp(_el$53, "flexDirection", "row");
|
|
13416
|
+
setProp(_el$53, "gap", 1);
|
|
13417
|
+
setProp(_el$53, "paddingLeft", 1);
|
|
13418
|
+
setProp(_el$53, "paddingRight", 1);
|
|
13419
|
+
setProp(_el$53, "onMouseUp", () => {
|
|
13214
13420
|
props.setLevel("body");
|
|
13215
13421
|
props.setBodyRow(rowIndex());
|
|
13216
|
-
|
|
13422
|
+
props.selectFocusAccent(slot);
|
|
13217
13423
|
});
|
|
13218
|
-
setProp(_el$
|
|
13219
|
-
insert(_el$
|
|
13220
|
-
insert(_el$
|
|
13424
|
+
setProp(_el$54, "wrapMode", "none");
|
|
13425
|
+
insert(_el$54, () => isSelected() ? "\u25CF " : " ", null);
|
|
13426
|
+
insert(_el$54, () => FOCUS_ACCENT_LABEL[slot], null);
|
|
13221
13427
|
effect((_p$) => {
|
|
13222
|
-
var _v$
|
|
13223
|
-
_v$
|
|
13224
|
-
_v$
|
|
13225
|
-
_v$
|
|
13428
|
+
var _v$43 = isCursor() ? theme.primary : undefined, _v$44 = isCursor() ? theme.selectedListItemText : isSelected() ? theme.focusAccent : theme.text, _v$45 = isCursor() || isSelected() ? TextAttributes5.BOLD : undefined;
|
|
13429
|
+
_v$43 !== _p$.e && (_p$.e = setProp(_el$53, "backgroundColor", _v$43, _p$.e));
|
|
13430
|
+
_v$44 !== _p$.t && (_p$.t = setProp(_el$54, "fg", _v$44, _p$.t));
|
|
13431
|
+
_v$45 !== _p$.a && (_p$.a = setProp(_el$54, "attributes", _v$45, _p$.a));
|
|
13226
13432
|
return _p$;
|
|
13227
13433
|
}, {
|
|
13228
13434
|
e: undefined,
|
|
13229
13435
|
t: undefined,
|
|
13230
13436
|
a: undefined
|
|
13231
13437
|
});
|
|
13232
|
-
return _el$
|
|
13438
|
+
return _el$53;
|
|
13233
13439
|
})();
|
|
13234
13440
|
}
|
|
13235
13441
|
}), null);
|
|
@@ -13305,8 +13511,42 @@ function GeneralSettingsSection(props) {
|
|
|
13305
13511
|
insertNode(_el$40, _el$41);
|
|
13306
13512
|
setProp(_el$40, "wrapMode", "none");
|
|
13307
13513
|
insert(_el$40, () => props.settingsSurface() === "taskpanel" ? "[x]" : "[ ]", _el$41);
|
|
13514
|
+
insertNode(_el$42, _el$43);
|
|
13515
|
+
insertNode(_el$42, _el$45);
|
|
13516
|
+
insertNode(_el$42, _el$47);
|
|
13517
|
+
insertNode(_el$42, _el$49);
|
|
13518
|
+
setProp(_el$42, "flexDirection", "column");
|
|
13519
|
+
setProp(_el$42, "gap", 0);
|
|
13520
|
+
setProp(_el$42, "paddingTop", 1);
|
|
13521
|
+
insertNode(_el$43, createTextNode(`Editor`));
|
|
13522
|
+
insertNode(_el$45, createTextNode(`What \`e\` opens a file with in the file tree (enter stays the read-only preview). enter on the row below cycles vim / nano / custom; if the editor isn't installed it falls back to the preview.`));
|
|
13523
|
+
setProp(_el$45, "wrapMode", "word");
|
|
13524
|
+
insertNode(_el$47, _el$48);
|
|
13525
|
+
setProp(_el$47, "flexDirection", "row");
|
|
13526
|
+
setProp(_el$47, "gap", 1);
|
|
13527
|
+
setProp(_el$47, "paddingLeft", 1);
|
|
13528
|
+
setProp(_el$47, "paddingRight", 1);
|
|
13529
|
+
setProp(_el$47, "onMouseUp", () => {
|
|
13530
|
+
props.setLevel("body");
|
|
13531
|
+
props.setBodyRow(editorKindRow());
|
|
13532
|
+
props.cycleEditorKind();
|
|
13533
|
+
});
|
|
13534
|
+
setProp(_el$48, "wrapMode", "none");
|
|
13535
|
+
insert(_el$48, () => `editor: < ${props.editorKind()} > (enter to change)`);
|
|
13536
|
+
insertNode(_el$49, _el$50);
|
|
13537
|
+
setProp(_el$49, "flexDirection", "row");
|
|
13538
|
+
setProp(_el$49, "gap", 1);
|
|
13539
|
+
setProp(_el$49, "paddingLeft", 1);
|
|
13540
|
+
setProp(_el$49, "paddingRight", 1);
|
|
13541
|
+
setProp(_el$49, "onMouseUp", () => {
|
|
13542
|
+
props.setLevel("body");
|
|
13543
|
+
props.setBodyRow(editorCustomRow());
|
|
13544
|
+
props.editEditorCustom();
|
|
13545
|
+
});
|
|
13546
|
+
setProp(_el$50, "wrapMode", "none");
|
|
13547
|
+
insert(_el$50, () => `custom: ${props.editorCustomCommand().trim() || "(unset \u2014 enter to edit)"}`);
|
|
13308
13548
|
effect((_p$) => {
|
|
13309
|
-
var _v$4 = theme.text, _v$5 = TextAttributes5.BOLD, _v$6 = theme.textMuted, _v$7 = theme.text, _v$8 = TextAttributes5.BOLD, _v$9 = theme.textMuted, _v$0 = isTransparentRow() ? theme.primary : undefined, _v$1 = isTransparentRow() ? theme.selectedListItemText : themeCtx.transparentBackground ? theme.accent : theme.textMuted, _v$10 = TextAttributes5.BOLD, _v$11 = theme.text, _v$12 = TextAttributes5.BOLD, _v$13 = theme.textMuted, _v$14 = theme.text, _v$15 = TextAttributes5.BOLD, _v$16 = theme.textMuted, _v$17 = isToastRow() ? theme.primary : undefined, _v$18 = isToastRow() ? theme.selectedListItemText : props.toastEnabled() ? theme.accent : theme.textMuted, _v$19 = TextAttributes5.BOLD, _v$20 = isSoundRow() ? theme.primary : undefined, _v$21 = isSoundRow() ? theme.selectedListItemText : props.soundEnabled() ? theme.accent : theme.textMuted, _v$22 = TextAttributes5.BOLD, _v$23 = theme.text, _v$24 = TextAttributes5.BOLD, _v$25 = theme.textMuted, _v$26 = isSurfaceChattabRow() ? theme.primary : undefined, _v$27 = isSurfaceChattabRow() ? theme.selectedListItemText : props.settingsSurface() === "chattab" ? theme.accent : theme.textMuted, _v$28 = TextAttributes5.BOLD, _v$29 = isSurfaceTaskpanelRow() ? theme.primary : undefined, _v$30 = isSurfaceTaskpanelRow() ? theme.selectedListItemText : props.settingsSurface() === "taskpanel" ? theme.accent : theme.textMuted, _v$31 = TextAttributes5.BOLD;
|
|
13549
|
+
var _v$4 = theme.text, _v$5 = TextAttributes5.BOLD, _v$6 = theme.textMuted, _v$7 = theme.text, _v$8 = TextAttributes5.BOLD, _v$9 = theme.textMuted, _v$0 = isTransparentRow() ? theme.primary : undefined, _v$1 = isTransparentRow() ? theme.selectedListItemText : themeCtx.transparentBackground ? theme.accent : theme.textMuted, _v$10 = TextAttributes5.BOLD, _v$11 = theme.text, _v$12 = TextAttributes5.BOLD, _v$13 = theme.textMuted, _v$14 = theme.text, _v$15 = TextAttributes5.BOLD, _v$16 = theme.textMuted, _v$17 = isToastRow() ? theme.primary : undefined, _v$18 = isToastRow() ? theme.selectedListItemText : props.toastEnabled() ? theme.accent : theme.textMuted, _v$19 = TextAttributes5.BOLD, _v$20 = isSoundRow() ? theme.primary : undefined, _v$21 = isSoundRow() ? theme.selectedListItemText : props.soundEnabled() ? theme.accent : theme.textMuted, _v$22 = TextAttributes5.BOLD, _v$23 = theme.text, _v$24 = TextAttributes5.BOLD, _v$25 = theme.textMuted, _v$26 = isSurfaceChattabRow() ? theme.primary : undefined, _v$27 = isSurfaceChattabRow() ? theme.selectedListItemText : props.settingsSurface() === "chattab" ? theme.accent : theme.textMuted, _v$28 = TextAttributes5.BOLD, _v$29 = isSurfaceTaskpanelRow() ? theme.primary : undefined, _v$30 = isSurfaceTaskpanelRow() ? theme.selectedListItemText : props.settingsSurface() === "taskpanel" ? theme.accent : theme.textMuted, _v$31 = TextAttributes5.BOLD, _v$32 = theme.text, _v$33 = TextAttributes5.BOLD, _v$34 = theme.textMuted, _v$35 = isEditorKindRow() ? theme.primary : undefined, _v$36 = isEditorKindRow() ? theme.selectedListItemText : theme.accent, _v$37 = TextAttributes5.BOLD, _v$38 = isEditorCustomRow() ? theme.primary : undefined, _v$39 = isEditorCustomRow() ? theme.selectedListItemText : props.editorKind() === "custom" ? theme.text : theme.textMuted;
|
|
13310
13550
|
_v$4 !== _p$.e && (_p$.e = setProp(_el$5, "fg", _v$4, _p$.e));
|
|
13311
13551
|
_v$5 !== _p$.t && (_p$.t = setProp(_el$5, "attributes", _v$5, _p$.t));
|
|
13312
13552
|
_v$6 !== _p$.a && (_p$.a = setProp(_el$7, "fg", _v$6, _p$.a));
|
|
@@ -13337,6 +13577,14 @@ function GeneralSettingsSection(props) {
|
|
|
13337
13577
|
_v$29 !== _p$.B && (_p$.B = setProp(_el$39, "backgroundColor", _v$29, _p$.B));
|
|
13338
13578
|
_v$30 !== _p$.v && (_p$.v = setProp(_el$40, "fg", _v$30, _p$.v));
|
|
13339
13579
|
_v$31 !== _p$.k && (_p$.k = setProp(_el$40, "attributes", _v$31, _p$.k));
|
|
13580
|
+
_v$32 !== _p$.x && (_p$.x = setProp(_el$43, "fg", _v$32, _p$.x));
|
|
13581
|
+
_v$33 !== _p$.j && (_p$.j = setProp(_el$43, "attributes", _v$33, _p$.j));
|
|
13582
|
+
_v$34 !== _p$.q && (_p$.q = setProp(_el$45, "fg", _v$34, _p$.q));
|
|
13583
|
+
_v$35 !== _p$.z && (_p$.z = setProp(_el$47, "backgroundColor", _v$35, _p$.z));
|
|
13584
|
+
_v$36 !== _p$.P && (_p$.P = setProp(_el$48, "fg", _v$36, _p$.P));
|
|
13585
|
+
_v$37 !== _p$.H && (_p$.H = setProp(_el$48, "attributes", _v$37, _p$.H));
|
|
13586
|
+
_v$38 !== _p$.F && (_p$.F = setProp(_el$49, "backgroundColor", _v$38, _p$.F));
|
|
13587
|
+
_v$39 !== _p$.M && (_p$.M = setProp(_el$50, "fg", _v$39, _p$.M));
|
|
13340
13588
|
return _p$;
|
|
13341
13589
|
}, {
|
|
13342
13590
|
e: undefined,
|
|
@@ -13368,7 +13616,15 @@ function GeneralSettingsSection(props) {
|
|
|
13368
13616
|
C: undefined,
|
|
13369
13617
|
B: undefined,
|
|
13370
13618
|
v: undefined,
|
|
13371
|
-
k: undefined
|
|
13619
|
+
k: undefined,
|
|
13620
|
+
x: undefined,
|
|
13621
|
+
j: undefined,
|
|
13622
|
+
q: undefined,
|
|
13623
|
+
z: undefined,
|
|
13624
|
+
P: undefined,
|
|
13625
|
+
H: undefined,
|
|
13626
|
+
F: undefined,
|
|
13627
|
+
M: undefined
|
|
13372
13628
|
});
|
|
13373
13629
|
return _el$4;
|
|
13374
13630
|
})();
|
|
@@ -13378,47 +13634,47 @@ function EngineSettingsSection(props) {
|
|
|
13378
13634
|
theme
|
|
13379
13635
|
} = useTheme();
|
|
13380
13636
|
return (() => {
|
|
13381
|
-
var _el$
|
|
13382
|
-
insertNode(_el$
|
|
13383
|
-
insertNode(_el$
|
|
13384
|
-
insertNode(_el$
|
|
13385
|
-
setProp(_el$
|
|
13386
|
-
setProp(_el$
|
|
13387
|
-
insertNode(_el$
|
|
13388
|
-
insertNode(_el$
|
|
13389
|
-
setProp(_el$
|
|
13390
|
-
setProp(_el$
|
|
13391
|
-
setProp(_el$
|
|
13392
|
-
insert(_el$
|
|
13637
|
+
var _el$55 = createElement("box"), _el$56 = createElement("text"), _el$58 = createElement("text"), _el$60 = createElement("box");
|
|
13638
|
+
insertNode(_el$55, _el$56);
|
|
13639
|
+
insertNode(_el$55, _el$58);
|
|
13640
|
+
insertNode(_el$55, _el$60);
|
|
13641
|
+
setProp(_el$55, "flexDirection", "column");
|
|
13642
|
+
setProp(_el$55, "gap", 1);
|
|
13643
|
+
insertNode(_el$56, createTextNode(`Launch command`));
|
|
13644
|
+
insertNode(_el$58, createTextNode(`The command each engine's task pane runs. Override it when your binary isn't on PATH as \`claude\` / \`codex\` (e.g. it's \`cl\`) or to pass default flags. enter to edit \xB7 takes effect on the next task enter.`));
|
|
13645
|
+
setProp(_el$58, "wrapMode", "word");
|
|
13646
|
+
setProp(_el$60, "flexDirection", "column");
|
|
13647
|
+
setProp(_el$60, "gap", 0);
|
|
13648
|
+
insert(_el$60, createComponent2(For, {
|
|
13393
13649
|
get each() {
|
|
13394
13650
|
return props.vendors;
|
|
13395
13651
|
},
|
|
13396
13652
|
children: (vendor, i) => {
|
|
13397
13653
|
const isCursor = () => props.level() === "body" && props.bodyRow() === i();
|
|
13398
13654
|
return (() => {
|
|
13399
|
-
var _el$
|
|
13400
|
-
insertNode(_el$
|
|
13401
|
-
insertNode(_el$
|
|
13402
|
-
setProp(_el$
|
|
13403
|
-
setProp(_el$
|
|
13404
|
-
setProp(_el$
|
|
13405
|
-
setProp(_el$
|
|
13406
|
-
setProp(_el$
|
|
13655
|
+
var _el$61 = createElement("box"), _el$62 = createElement("text"), _el$63 = createElement("text");
|
|
13656
|
+
insertNode(_el$61, _el$62);
|
|
13657
|
+
insertNode(_el$61, _el$63);
|
|
13658
|
+
setProp(_el$61, "flexDirection", "row");
|
|
13659
|
+
setProp(_el$61, "gap", 1);
|
|
13660
|
+
setProp(_el$61, "paddingLeft", 1);
|
|
13661
|
+
setProp(_el$61, "paddingRight", 1);
|
|
13662
|
+
setProp(_el$61, "onMouseUp", () => {
|
|
13407
13663
|
props.setLevel("body");
|
|
13408
13664
|
props.setBodyRow(i());
|
|
13409
13665
|
props.editEngine(vendor);
|
|
13410
13666
|
});
|
|
13411
|
-
setProp(_el$
|
|
13412
|
-
insert(_el$
|
|
13413
|
-
setProp(_el$
|
|
13414
|
-
insert(_el$
|
|
13415
|
-
insert(_el$
|
|
13667
|
+
setProp(_el$62, "wrapMode", "none");
|
|
13668
|
+
insert(_el$62, () => VENDOR_LABEL[vendor]);
|
|
13669
|
+
setProp(_el$63, "wrapMode", "none");
|
|
13670
|
+
insert(_el$63, () => props.commandText(vendor), null);
|
|
13671
|
+
insert(_el$63, () => props.isDefault(vendor) ? " (default)" : "", null);
|
|
13416
13672
|
effect((_p$) => {
|
|
13417
|
-
var _v$
|
|
13418
|
-
_v$
|
|
13419
|
-
_v$
|
|
13420
|
-
_v$
|
|
13421
|
-
_v$
|
|
13673
|
+
var _v$49 = isCursor() ? theme.primary : undefined, _v$50 = isCursor() ? theme.selectedListItemText : theme.text, _v$51 = TextAttributes5.BOLD, _v$52 = isCursor() ? theme.selectedListItemText : props.isDefault(vendor) ? theme.textMuted : theme.accent;
|
|
13674
|
+
_v$49 !== _p$.e && (_p$.e = setProp(_el$61, "backgroundColor", _v$49, _p$.e));
|
|
13675
|
+
_v$50 !== _p$.t && (_p$.t = setProp(_el$62, "fg", _v$50, _p$.t));
|
|
13676
|
+
_v$51 !== _p$.a && (_p$.a = setProp(_el$62, "attributes", _v$51, _p$.a));
|
|
13677
|
+
_v$52 !== _p$.o && (_p$.o = setProp(_el$63, "fg", _v$52, _p$.o));
|
|
13422
13678
|
return _p$;
|
|
13423
13679
|
}, {
|
|
13424
13680
|
e: undefined,
|
|
@@ -13426,22 +13682,22 @@ function EngineSettingsSection(props) {
|
|
|
13426
13682
|
a: undefined,
|
|
13427
13683
|
o: undefined
|
|
13428
13684
|
});
|
|
13429
|
-
return _el$
|
|
13685
|
+
return _el$61;
|
|
13430
13686
|
})();
|
|
13431
13687
|
}
|
|
13432
13688
|
}));
|
|
13433
13689
|
effect((_p$) => {
|
|
13434
|
-
var _v$
|
|
13435
|
-
_v$
|
|
13436
|
-
_v$
|
|
13437
|
-
_v$
|
|
13690
|
+
var _v$46 = theme.text, _v$47 = TextAttributes5.BOLD, _v$48 = theme.textMuted;
|
|
13691
|
+
_v$46 !== _p$.e && (_p$.e = setProp(_el$56, "fg", _v$46, _p$.e));
|
|
13692
|
+
_v$47 !== _p$.t && (_p$.t = setProp(_el$56, "attributes", _v$47, _p$.t));
|
|
13693
|
+
_v$48 !== _p$.a && (_p$.a = setProp(_el$58, "fg", _v$48, _p$.a));
|
|
13438
13694
|
return _p$;
|
|
13439
13695
|
}, {
|
|
13440
13696
|
e: undefined,
|
|
13441
13697
|
t: undefined,
|
|
13442
13698
|
a: undefined
|
|
13443
13699
|
});
|
|
13444
|
-
return _el$
|
|
13700
|
+
return _el$55;
|
|
13445
13701
|
})();
|
|
13446
13702
|
}
|
|
13447
13703
|
function AccountsSettingsSection(props) {
|
|
@@ -13450,221 +13706,221 @@ function AccountsSettingsSection(props) {
|
|
|
13450
13706
|
} = useTheme();
|
|
13451
13707
|
const binaryLine = (s) => s.binary.found ? `Binary: ${s.binary.path}` : `Binary: ${s.binary.error}`;
|
|
13452
13708
|
return (() => {
|
|
13453
|
-
var _el$
|
|
13454
|
-
insertNode(_el$
|
|
13455
|
-
insertNode(_el$
|
|
13456
|
-
insertNode(_el$
|
|
13457
|
-
insertNode(_el$
|
|
13458
|
-
insertNode(_el$
|
|
13459
|
-
setProp(_el$
|
|
13460
|
-
setProp(_el$
|
|
13461
|
-
insertNode(_el$
|
|
13462
|
-
insertNode(_el$
|
|
13463
|
-
setProp(_el$
|
|
13464
|
-
insertNode(_el$
|
|
13465
|
-
setProp(_el$
|
|
13466
|
-
setProp(_el$
|
|
13467
|
-
insertNode(_el$
|
|
13468
|
-
insert(_el$
|
|
13709
|
+
var _el$64 = createElement("box"), _el$65 = createElement("text"), _el$67 = createElement("text"), _el$69 = createElement("box"), _el$70 = createElement("text"), _el$74 = createElement("box"), _el$75 = createElement("text"), _el$79 = createElement("box"), _el$80 = createElement("text");
|
|
13710
|
+
insertNode(_el$64, _el$65);
|
|
13711
|
+
insertNode(_el$64, _el$67);
|
|
13712
|
+
insertNode(_el$64, _el$69);
|
|
13713
|
+
insertNode(_el$64, _el$74);
|
|
13714
|
+
insertNode(_el$64, _el$79);
|
|
13715
|
+
setProp(_el$64, "flexDirection", "column");
|
|
13716
|
+
setProp(_el$64, "gap", 1);
|
|
13717
|
+
insertNode(_el$65, createTextNode(`Accounts`));
|
|
13718
|
+
insertNode(_el$67, createTextNode(`Read-only view of locally-detected engine accounts. Login flows land here later.`));
|
|
13719
|
+
setProp(_el$67, "wrapMode", "word");
|
|
13720
|
+
insertNode(_el$69, _el$70);
|
|
13721
|
+
setProp(_el$69, "flexDirection", "column");
|
|
13722
|
+
setProp(_el$69, "gap", 0);
|
|
13723
|
+
insertNode(_el$70, createTextNode(`claude-code`));
|
|
13724
|
+
insert(_el$69, createComponent2(Show, {
|
|
13469
13725
|
get when() {
|
|
13470
13726
|
return props.claudeStatus() === null;
|
|
13471
13727
|
},
|
|
13472
13728
|
get children() {
|
|
13473
|
-
var _el$
|
|
13474
|
-
insertNode(_el$
|
|
13475
|
-
effect((_$p) => setProp(_el$
|
|
13476
|
-
return _el$
|
|
13729
|
+
var _el$72 = createElement("text");
|
|
13730
|
+
insertNode(_el$72, createTextNode(`Checking\u2026`));
|
|
13731
|
+
effect((_$p) => setProp(_el$72, "fg", theme.textMuted, _$p));
|
|
13732
|
+
return _el$72;
|
|
13477
13733
|
}
|
|
13478
13734
|
}), null);
|
|
13479
|
-
insert(_el$
|
|
13735
|
+
insert(_el$69, createComponent2(Show, {
|
|
13480
13736
|
get when() {
|
|
13481
13737
|
return props.claudeStatus();
|
|
13482
13738
|
},
|
|
13483
13739
|
children: (s) => (() => {
|
|
13484
|
-
var _el$
|
|
13485
|
-
insertNode(_el$
|
|
13486
|
-
setProp(_el$
|
|
13487
|
-
setProp(_el$
|
|
13488
|
-
setProp(_el$
|
|
13489
|
-
insert(_el$
|
|
13490
|
-
insert(_el$
|
|
13740
|
+
var _el$84 = createElement("box"), _el$85 = createElement("text");
|
|
13741
|
+
insertNode(_el$84, _el$85);
|
|
13742
|
+
setProp(_el$84, "flexDirection", "column");
|
|
13743
|
+
setProp(_el$84, "gap", 0);
|
|
13744
|
+
setProp(_el$85, "wrapMode", "word");
|
|
13745
|
+
insert(_el$85, () => binaryLine(s()));
|
|
13746
|
+
insert(_el$84, () => {
|
|
13491
13747
|
const a = s().account;
|
|
13492
13748
|
if (a.kind === "oauth") {
|
|
13493
13749
|
const tail = [a.organization, a.billingType].filter((x) => !!x).join(" \xB7 ");
|
|
13494
13750
|
return (() => {
|
|
13495
|
-
var _el$
|
|
13496
|
-
setProp(_el$
|
|
13497
|
-
insert(_el$
|
|
13498
|
-
effect((_$p) => setProp(_el$
|
|
13499
|
-
return _el$
|
|
13751
|
+
var _el$86 = createElement("text");
|
|
13752
|
+
setProp(_el$86, "wrapMode", "word");
|
|
13753
|
+
insert(_el$86, () => `\u25CF Logged in: ${a.email}${tail ? ` (${tail})` : ""}`);
|
|
13754
|
+
effect((_$p) => setProp(_el$86, "fg", theme.success, _$p));
|
|
13755
|
+
return _el$86;
|
|
13500
13756
|
})();
|
|
13501
13757
|
}
|
|
13502
13758
|
return (() => {
|
|
13503
|
-
var _el$
|
|
13504
|
-
insertNode(_el$
|
|
13505
|
-
effect((_$p) => setProp(_el$
|
|
13506
|
-
return _el$
|
|
13759
|
+
var _el$87 = createElement("text");
|
|
13760
|
+
insertNode(_el$87, createTextNode(`\u25CB Not logged in`));
|
|
13761
|
+
effect((_$p) => setProp(_el$87, "fg", theme.textMuted, _$p));
|
|
13762
|
+
return _el$87;
|
|
13507
13763
|
})();
|
|
13508
13764
|
}, null);
|
|
13509
|
-
insert(_el$
|
|
13765
|
+
insert(_el$84, createComponent2(Show, {
|
|
13510
13766
|
get when() {
|
|
13511
13767
|
return s().accountError;
|
|
13512
13768
|
},
|
|
13513
13769
|
children: (err) => (() => {
|
|
13514
|
-
var _el$
|
|
13515
|
-
setProp(_el$
|
|
13516
|
-
insert(_el$
|
|
13517
|
-
effect((_$p) => setProp(_el$
|
|
13518
|
-
return _el$
|
|
13770
|
+
var _el$89 = createElement("text");
|
|
13771
|
+
setProp(_el$89, "wrapMode", "word");
|
|
13772
|
+
insert(_el$89, () => `! ${err()}`);
|
|
13773
|
+
effect((_$p) => setProp(_el$89, "fg", theme.warning, _$p));
|
|
13774
|
+
return _el$89;
|
|
13519
13775
|
})()
|
|
13520
13776
|
}), null);
|
|
13521
|
-
effect((_$p) => setProp(_el$
|
|
13522
|
-
return _el$
|
|
13777
|
+
effect((_$p) => setProp(_el$85, "fg", s().binary.found ? theme.textMuted : theme.warning, _$p));
|
|
13778
|
+
return _el$84;
|
|
13523
13779
|
})()
|
|
13524
13780
|
}), null);
|
|
13525
|
-
insertNode(_el$
|
|
13526
|
-
setProp(_el$
|
|
13527
|
-
setProp(_el$
|
|
13528
|
-
insertNode(_el$
|
|
13529
|
-
insert(_el$
|
|
13781
|
+
insertNode(_el$74, _el$75);
|
|
13782
|
+
setProp(_el$74, "flexDirection", "column");
|
|
13783
|
+
setProp(_el$74, "gap", 0);
|
|
13784
|
+
insertNode(_el$75, createTextNode(`codex`));
|
|
13785
|
+
insert(_el$74, createComponent2(Show, {
|
|
13530
13786
|
get when() {
|
|
13531
13787
|
return props.codexStatus() === null;
|
|
13532
13788
|
},
|
|
13533
13789
|
get children() {
|
|
13534
|
-
var _el$
|
|
13535
|
-
insertNode(_el$
|
|
13536
|
-
effect((_$p) => setProp(_el$
|
|
13537
|
-
return _el$
|
|
13790
|
+
var _el$77 = createElement("text");
|
|
13791
|
+
insertNode(_el$77, createTextNode(`Checking\u2026`));
|
|
13792
|
+
effect((_$p) => setProp(_el$77, "fg", theme.textMuted, _$p));
|
|
13793
|
+
return _el$77;
|
|
13538
13794
|
}
|
|
13539
13795
|
}), null);
|
|
13540
|
-
insert(_el$
|
|
13796
|
+
insert(_el$74, createComponent2(Show, {
|
|
13541
13797
|
get when() {
|
|
13542
13798
|
return props.codexStatus();
|
|
13543
13799
|
},
|
|
13544
13800
|
children: (s) => (() => {
|
|
13545
|
-
var _el$
|
|
13546
|
-
insertNode(_el$
|
|
13547
|
-
setProp(_el$
|
|
13548
|
-
setProp(_el$
|
|
13549
|
-
setProp(_el$
|
|
13550
|
-
insert(_el$
|
|
13551
|
-
insert(_el$
|
|
13801
|
+
var _el$90 = createElement("box"), _el$91 = createElement("text");
|
|
13802
|
+
insertNode(_el$90, _el$91);
|
|
13803
|
+
setProp(_el$90, "flexDirection", "column");
|
|
13804
|
+
setProp(_el$90, "gap", 0);
|
|
13805
|
+
setProp(_el$91, "wrapMode", "word");
|
|
13806
|
+
insert(_el$91, () => binaryLine(s()));
|
|
13807
|
+
insert(_el$90, () => {
|
|
13552
13808
|
const a = s().account;
|
|
13553
13809
|
if (a.kind === "chatgpt") {
|
|
13554
13810
|
return (() => {
|
|
13555
|
-
var _el$
|
|
13556
|
-
setProp(_el$
|
|
13557
|
-
insert(_el$
|
|
13558
|
-
effect((_$p) => setProp(_el$
|
|
13559
|
-
return _el$
|
|
13811
|
+
var _el$92 = createElement("text");
|
|
13812
|
+
setProp(_el$92, "wrapMode", "word");
|
|
13813
|
+
insert(_el$92, () => `\u25CF ChatGPT login: ${a.email}${a.plan ? ` (${a.plan})` : ""}`);
|
|
13814
|
+
effect((_$p) => setProp(_el$92, "fg", theme.success, _$p));
|
|
13815
|
+
return _el$92;
|
|
13560
13816
|
})();
|
|
13561
13817
|
}
|
|
13562
13818
|
if (a.kind === "apikey")
|
|
13563
13819
|
return (() => {
|
|
13564
|
-
var _el$
|
|
13565
|
-
insertNode(_el$
|
|
13566
|
-
effect((_$p) => setProp(_el$
|
|
13567
|
-
return _el$
|
|
13820
|
+
var _el$93 = createElement("text");
|
|
13821
|
+
insertNode(_el$93, createTextNode(`\u25CF API key configured`));
|
|
13822
|
+
effect((_$p) => setProp(_el$93, "fg", theme.success, _$p));
|
|
13823
|
+
return _el$93;
|
|
13568
13824
|
})();
|
|
13569
13825
|
return (() => {
|
|
13570
|
-
var _el$
|
|
13571
|
-
insertNode(_el$
|
|
13572
|
-
effect((_$p) => setProp(_el$
|
|
13573
|
-
return _el$
|
|
13826
|
+
var _el$95 = createElement("text");
|
|
13827
|
+
insertNode(_el$95, createTextNode(`\u25CB Not logged in`));
|
|
13828
|
+
effect((_$p) => setProp(_el$95, "fg", theme.textMuted, _$p));
|
|
13829
|
+
return _el$95;
|
|
13574
13830
|
})();
|
|
13575
13831
|
}, null);
|
|
13576
|
-
insert(_el$
|
|
13832
|
+
insert(_el$90, createComponent2(Show, {
|
|
13577
13833
|
get when() {
|
|
13578
13834
|
return s().accountError;
|
|
13579
13835
|
},
|
|
13580
13836
|
children: (err) => (() => {
|
|
13581
|
-
var _el$
|
|
13582
|
-
setProp(_el$
|
|
13583
|
-
insert(_el$
|
|
13584
|
-
effect((_$p) => setProp(_el$
|
|
13585
|
-
return _el$
|
|
13837
|
+
var _el$97 = createElement("text");
|
|
13838
|
+
setProp(_el$97, "wrapMode", "word");
|
|
13839
|
+
insert(_el$97, () => `! ${err()}`);
|
|
13840
|
+
effect((_$p) => setProp(_el$97, "fg", theme.warning, _$p));
|
|
13841
|
+
return _el$97;
|
|
13586
13842
|
})()
|
|
13587
13843
|
}), null);
|
|
13588
|
-
effect((_$p) => setProp(_el$
|
|
13589
|
-
return _el$
|
|
13844
|
+
effect((_$p) => setProp(_el$91, "fg", s().binary.found ? theme.textMuted : theme.warning, _$p));
|
|
13845
|
+
return _el$90;
|
|
13590
13846
|
})()
|
|
13591
13847
|
}), null);
|
|
13592
|
-
insertNode(_el$
|
|
13593
|
-
setProp(_el$
|
|
13594
|
-
setProp(_el$
|
|
13595
|
-
insertNode(_el$
|
|
13596
|
-
insert(_el$
|
|
13848
|
+
insertNode(_el$79, _el$80);
|
|
13849
|
+
setProp(_el$79, "flexDirection", "column");
|
|
13850
|
+
setProp(_el$79, "gap", 0);
|
|
13851
|
+
insertNode(_el$80, createTextNode(`copilot`));
|
|
13852
|
+
insert(_el$79, createComponent2(Show, {
|
|
13597
13853
|
get when() {
|
|
13598
13854
|
return props.copilotStatus() === null;
|
|
13599
13855
|
},
|
|
13600
13856
|
get children() {
|
|
13601
|
-
var _el$
|
|
13602
|
-
insertNode(_el$
|
|
13603
|
-
effect((_$p) => setProp(_el$
|
|
13604
|
-
return _el$
|
|
13857
|
+
var _el$82 = createElement("text");
|
|
13858
|
+
insertNode(_el$82, createTextNode(`Checking\u2026`));
|
|
13859
|
+
effect((_$p) => setProp(_el$82, "fg", theme.textMuted, _$p));
|
|
13860
|
+
return _el$82;
|
|
13605
13861
|
}
|
|
13606
13862
|
}), null);
|
|
13607
|
-
insert(_el$
|
|
13863
|
+
insert(_el$79, createComponent2(Show, {
|
|
13608
13864
|
get when() {
|
|
13609
13865
|
return props.copilotStatus();
|
|
13610
13866
|
},
|
|
13611
13867
|
children: (s) => (() => {
|
|
13612
|
-
var _el$
|
|
13613
|
-
insertNode(_el$
|
|
13614
|
-
setProp(_el$
|
|
13615
|
-
setProp(_el$
|
|
13616
|
-
setProp(_el$
|
|
13617
|
-
insert(_el$
|
|
13618
|
-
insert(_el$
|
|
13868
|
+
var _el$98 = createElement("box"), _el$99 = createElement("text");
|
|
13869
|
+
insertNode(_el$98, _el$99);
|
|
13870
|
+
setProp(_el$98, "flexDirection", "column");
|
|
13871
|
+
setProp(_el$98, "gap", 0);
|
|
13872
|
+
setProp(_el$99, "wrapMode", "word");
|
|
13873
|
+
insert(_el$99, () => binaryLine(s()));
|
|
13874
|
+
insert(_el$98, () => {
|
|
13619
13875
|
const a = s().account;
|
|
13620
13876
|
if (a.kind === "token")
|
|
13621
13877
|
return (() => {
|
|
13622
|
-
var _el$
|
|
13623
|
-
insert(_el$
|
|
13624
|
-
effect((_$p) => setProp(_el$
|
|
13625
|
-
return _el$
|
|
13878
|
+
var _el$100 = createElement("text");
|
|
13879
|
+
insert(_el$100, () => `\u25CF Token configured (${a.source})`);
|
|
13880
|
+
effect((_$p) => setProp(_el$100, "fg", theme.success, _$p));
|
|
13881
|
+
return _el$100;
|
|
13626
13882
|
})();
|
|
13627
13883
|
if (a.kind === "oauth")
|
|
13628
13884
|
return (() => {
|
|
13629
|
-
var _el$
|
|
13630
|
-
insertNode(_el$
|
|
13631
|
-
effect((_$p) => setProp(_el$
|
|
13632
|
-
return _el$
|
|
13885
|
+
var _el$101 = createElement("text");
|
|
13886
|
+
insertNode(_el$101, createTextNode(`\u25CF Copilot login detected`));
|
|
13887
|
+
effect((_$p) => setProp(_el$101, "fg", theme.success, _$p));
|
|
13888
|
+
return _el$101;
|
|
13633
13889
|
})();
|
|
13634
13890
|
return (() => {
|
|
13635
|
-
var _el$
|
|
13636
|
-
insertNode(_el$
|
|
13637
|
-
effect((_$p) => setProp(_el$
|
|
13638
|
-
return _el$
|
|
13891
|
+
var _el$103 = createElement("text");
|
|
13892
|
+
insertNode(_el$103, createTextNode(`\u25CB Not logged in`));
|
|
13893
|
+
effect((_$p) => setProp(_el$103, "fg", theme.textMuted, _$p));
|
|
13894
|
+
return _el$103;
|
|
13639
13895
|
})();
|
|
13640
13896
|
}, null);
|
|
13641
|
-
insert(_el$
|
|
13897
|
+
insert(_el$98, createComponent2(Show, {
|
|
13642
13898
|
get when() {
|
|
13643
13899
|
return s().accountError;
|
|
13644
13900
|
},
|
|
13645
13901
|
children: (err) => (() => {
|
|
13646
|
-
var _el$
|
|
13647
|
-
setProp(_el$
|
|
13648
|
-
insert(_el$
|
|
13649
|
-
effect((_$p) => setProp(_el$
|
|
13650
|
-
return _el$
|
|
13902
|
+
var _el$105 = createElement("text");
|
|
13903
|
+
setProp(_el$105, "wrapMode", "word");
|
|
13904
|
+
insert(_el$105, () => `! ${err()}`);
|
|
13905
|
+
effect((_$p) => setProp(_el$105, "fg", theme.warning, _$p));
|
|
13906
|
+
return _el$105;
|
|
13651
13907
|
})()
|
|
13652
13908
|
}), null);
|
|
13653
|
-
effect((_$p) => setProp(_el$
|
|
13654
|
-
return _el$
|
|
13909
|
+
effect((_$p) => setProp(_el$99, "fg", s().binary.found ? theme.textMuted : theme.warning, _$p));
|
|
13910
|
+
return _el$98;
|
|
13655
13911
|
})()
|
|
13656
13912
|
}), null);
|
|
13657
13913
|
effect((_p$) => {
|
|
13658
|
-
var _v$
|
|
13659
|
-
_v$
|
|
13660
|
-
_v$
|
|
13661
|
-
_v$
|
|
13662
|
-
_v$
|
|
13663
|
-
_v$
|
|
13664
|
-
_v$
|
|
13665
|
-
_v$
|
|
13666
|
-
_v$
|
|
13667
|
-
_v$
|
|
13914
|
+
var _v$53 = theme.text, _v$54 = TextAttributes5.BOLD, _v$55 = theme.textMuted, _v$56 = theme.text, _v$57 = TextAttributes5.BOLD, _v$58 = theme.text, _v$59 = TextAttributes5.BOLD, _v$60 = theme.text, _v$61 = TextAttributes5.BOLD;
|
|
13915
|
+
_v$53 !== _p$.e && (_p$.e = setProp(_el$65, "fg", _v$53, _p$.e));
|
|
13916
|
+
_v$54 !== _p$.t && (_p$.t = setProp(_el$65, "attributes", _v$54, _p$.t));
|
|
13917
|
+
_v$55 !== _p$.a && (_p$.a = setProp(_el$67, "fg", _v$55, _p$.a));
|
|
13918
|
+
_v$56 !== _p$.o && (_p$.o = setProp(_el$70, "fg", _v$56, _p$.o));
|
|
13919
|
+
_v$57 !== _p$.i && (_p$.i = setProp(_el$70, "attributes", _v$57, _p$.i));
|
|
13920
|
+
_v$58 !== _p$.n && (_p$.n = setProp(_el$75, "fg", _v$58, _p$.n));
|
|
13921
|
+
_v$59 !== _p$.s && (_p$.s = setProp(_el$75, "attributes", _v$59, _p$.s));
|
|
13922
|
+
_v$60 !== _p$.h && (_p$.h = setProp(_el$80, "fg", _v$60, _p$.h));
|
|
13923
|
+
_v$61 !== _p$.r && (_p$.r = setProp(_el$80, "attributes", _v$61, _p$.r));
|
|
13668
13924
|
return _p$;
|
|
13669
13925
|
}, {
|
|
13670
13926
|
e: undefined,
|
|
@@ -13677,7 +13933,7 @@ function AccountsSettingsSection(props) {
|
|
|
13677
13933
|
h: undefined,
|
|
13678
13934
|
r: undefined
|
|
13679
13935
|
});
|
|
13680
|
-
return _el$
|
|
13936
|
+
return _el$64;
|
|
13681
13937
|
})();
|
|
13682
13938
|
}
|
|
13683
13939
|
function DevSettingsSection(props) {
|
|
@@ -13687,58 +13943,58 @@ function DevSettingsSection(props) {
|
|
|
13687
13943
|
const resetIsCursor = () => props.level() === "body" && props.bodyRow() === 0;
|
|
13688
13944
|
const restartIsCursor = () => props.level() === "body" && props.bodyRow() === 1;
|
|
13689
13945
|
return (() => {
|
|
13690
|
-
var _el$
|
|
13691
|
-
insertNode(_el$
|
|
13692
|
-
insertNode(_el$
|
|
13693
|
-
insertNode(_el$
|
|
13694
|
-
setProp(_el$
|
|
13695
|
-
setProp(_el$
|
|
13696
|
-
insertNode(_el$
|
|
13697
|
-
insertNode(_el$
|
|
13698
|
-
setProp(_el$
|
|
13699
|
-
insertNode(_el$
|
|
13700
|
-
setProp(_el$
|
|
13701
|
-
setProp(_el$
|
|
13702
|
-
setProp(_el$
|
|
13703
|
-
setProp(_el$
|
|
13946
|
+
var _el$106 = createElement("box"), _el$107 = createElement("text"), _el$109 = createElement("text"), _el$111 = createElement("box"), _el$112 = createElement("text");
|
|
13947
|
+
insertNode(_el$106, _el$107);
|
|
13948
|
+
insertNode(_el$106, _el$109);
|
|
13949
|
+
insertNode(_el$106, _el$111);
|
|
13950
|
+
setProp(_el$106, "flexDirection", "column");
|
|
13951
|
+
setProp(_el$106, "gap", 1);
|
|
13952
|
+
insertNode(_el$107, createTextNode(`Reset UI state`));
|
|
13953
|
+
insertNode(_el$109, createTextNode(`Clears ~/.config/kobe/state.json and ~/.kobe/tasks.json, then quits kobe \u2014 relaunch to start fresh. Working session / Archive lists, pane sizes, theme, model picks all reset. Worktrees on disk and Claude Code session history are not touched.`));
|
|
13954
|
+
setProp(_el$109, "wrapMode", "word");
|
|
13955
|
+
insertNode(_el$111, _el$112);
|
|
13956
|
+
setProp(_el$111, "flexDirection", "row");
|
|
13957
|
+
setProp(_el$111, "paddingLeft", 1);
|
|
13958
|
+
setProp(_el$111, "paddingRight", 1);
|
|
13959
|
+
setProp(_el$111, "onMouseUp", () => {
|
|
13704
13960
|
props.setLevel("body");
|
|
13705
13961
|
props.setBodyRow(0);
|
|
13706
13962
|
props.confirmReset();
|
|
13707
13963
|
});
|
|
13708
|
-
insertNode(_el$
|
|
13709
|
-
insert(_el$
|
|
13964
|
+
insertNode(_el$112, createTextNode(`[enter] Reset`));
|
|
13965
|
+
insert(_el$106, createComponent2(Show, {
|
|
13710
13966
|
get when() {
|
|
13711
13967
|
return props.hasDaemon;
|
|
13712
13968
|
},
|
|
13713
13969
|
get children() {
|
|
13714
|
-
var _el$
|
|
13715
|
-
insertNode(_el$
|
|
13716
|
-
insertNode(_el$
|
|
13717
|
-
insertNode(_el$
|
|
13718
|
-
setProp(_el$
|
|
13719
|
-
setProp(_el$
|
|
13720
|
-
setProp(_el$
|
|
13721
|
-
insertNode(_el$
|
|
13722
|
-
insertNode(_el$
|
|
13723
|
-
setProp(_el$
|
|
13724
|
-
insertNode(_el$
|
|
13725
|
-
setProp(_el$
|
|
13726
|
-
setProp(_el$
|
|
13727
|
-
setProp(_el$
|
|
13728
|
-
setProp(_el$
|
|
13970
|
+
var _el$114 = createElement("box"), _el$115 = createElement("text"), _el$117 = createElement("text"), _el$119 = createElement("box"), _el$120 = createElement("text");
|
|
13971
|
+
insertNode(_el$114, _el$115);
|
|
13972
|
+
insertNode(_el$114, _el$117);
|
|
13973
|
+
insertNode(_el$114, _el$119);
|
|
13974
|
+
setProp(_el$114, "flexDirection", "column");
|
|
13975
|
+
setProp(_el$114, "gap", 0);
|
|
13976
|
+
setProp(_el$114, "paddingTop", 1);
|
|
13977
|
+
insertNode(_el$115, createTextNode(`Restart backend`));
|
|
13978
|
+
insertNode(_el$117, createTextNode(`Stops the kobe daemon and quits this kobe window so the next launch spawns a fresh daemon \u2014 picks up daemon / orchestrator / engine edits without a process kill. Other attached kobe windows will lose their connection too.`));
|
|
13979
|
+
setProp(_el$117, "wrapMode", "word");
|
|
13980
|
+
insertNode(_el$119, _el$120);
|
|
13981
|
+
setProp(_el$119, "flexDirection", "row");
|
|
13982
|
+
setProp(_el$119, "paddingLeft", 1);
|
|
13983
|
+
setProp(_el$119, "paddingRight", 1);
|
|
13984
|
+
setProp(_el$119, "onMouseUp", () => {
|
|
13729
13985
|
props.setLevel("body");
|
|
13730
13986
|
props.setBodyRow(1);
|
|
13731
13987
|
props.confirmRestartDaemon();
|
|
13732
13988
|
});
|
|
13733
|
-
insertNode(_el$
|
|
13989
|
+
insertNode(_el$120, createTextNode(`[enter] Restart`));
|
|
13734
13990
|
effect((_p$) => {
|
|
13735
|
-
var _v$
|
|
13736
|
-
_v$
|
|
13737
|
-
_v$
|
|
13738
|
-
_v$
|
|
13739
|
-
_v$
|
|
13740
|
-
_v$
|
|
13741
|
-
_v$
|
|
13991
|
+
var _v$62 = theme.text, _v$63 = TextAttributes5.BOLD, _v$64 = theme.textMuted, _v$65 = restartIsCursor() ? theme.primary : theme.backgroundElement, _v$66 = restartIsCursor() ? theme.selectedListItemText : theme.accent, _v$67 = TextAttributes5.BOLD;
|
|
13992
|
+
_v$62 !== _p$.e && (_p$.e = setProp(_el$115, "fg", _v$62, _p$.e));
|
|
13993
|
+
_v$63 !== _p$.t && (_p$.t = setProp(_el$115, "attributes", _v$63, _p$.t));
|
|
13994
|
+
_v$64 !== _p$.a && (_p$.a = setProp(_el$117, "fg", _v$64, _p$.a));
|
|
13995
|
+
_v$65 !== _p$.o && (_p$.o = setProp(_el$119, "backgroundColor", _v$65, _p$.o));
|
|
13996
|
+
_v$66 !== _p$.i && (_p$.i = setProp(_el$120, "fg", _v$66, _p$.i));
|
|
13997
|
+
_v$67 !== _p$.n && (_p$.n = setProp(_el$120, "attributes", _v$67, _p$.n));
|
|
13742
13998
|
return _p$;
|
|
13743
13999
|
}, {
|
|
13744
14000
|
e: undefined,
|
|
@@ -13748,17 +14004,17 @@ function DevSettingsSection(props) {
|
|
|
13748
14004
|
i: undefined,
|
|
13749
14005
|
n: undefined
|
|
13750
14006
|
});
|
|
13751
|
-
return _el$
|
|
14007
|
+
return _el$114;
|
|
13752
14008
|
}
|
|
13753
14009
|
}), null);
|
|
13754
14010
|
effect((_p$) => {
|
|
13755
|
-
var _v$
|
|
13756
|
-
_v$
|
|
13757
|
-
_v$
|
|
13758
|
-
_v$
|
|
13759
|
-
_v$
|
|
13760
|
-
_v$
|
|
13761
|
-
_v$
|
|
14011
|
+
var _v$68 = theme.text, _v$69 = TextAttributes5.BOLD, _v$70 = theme.textMuted, _v$71 = resetIsCursor() ? theme.primary : theme.backgroundElement, _v$72 = resetIsCursor() ? theme.selectedListItemText : theme.warning, _v$73 = TextAttributes5.BOLD;
|
|
14012
|
+
_v$68 !== _p$.e && (_p$.e = setProp(_el$107, "fg", _v$68, _p$.e));
|
|
14013
|
+
_v$69 !== _p$.t && (_p$.t = setProp(_el$107, "attributes", _v$69, _p$.t));
|
|
14014
|
+
_v$70 !== _p$.a && (_p$.a = setProp(_el$109, "fg", _v$70, _p$.a));
|
|
14015
|
+
_v$71 !== _p$.o && (_p$.o = setProp(_el$111, "backgroundColor", _v$71, _p$.o));
|
|
14016
|
+
_v$72 !== _p$.i && (_p$.i = setProp(_el$112, "fg", _v$72, _p$.i));
|
|
14017
|
+
_v$73 !== _p$.n && (_p$.n = setProp(_el$112, "attributes", _v$73, _p$.n));
|
|
13762
14018
|
return _p$;
|
|
13763
14019
|
}, {
|
|
13764
14020
|
e: undefined,
|
|
@@ -13768,7 +14024,7 @@ function DevSettingsSection(props) {
|
|
|
13768
14024
|
i: undefined,
|
|
13769
14025
|
n: undefined
|
|
13770
14026
|
});
|
|
13771
|
-
return _el$
|
|
14027
|
+
return _el$106;
|
|
13772
14028
|
})();
|
|
13773
14029
|
}
|
|
13774
14030
|
var init_sections = __esm(() => {
|
|
@@ -13837,9 +14093,40 @@ function SettingsDialog(props) {
|
|
|
13837
14093
|
function isSurfaceTaskpanelRow() {
|
|
13838
14094
|
return section() === "general" && bodyRow() === surfaceTaskpanelRowIndex(themeNames().length, FOCUS_ACCENT_SLOTS.length);
|
|
13839
14095
|
}
|
|
14096
|
+
function isEditorKindRow() {
|
|
14097
|
+
return section() === "general" && bodyRow() === editorKindRowIndex(themeNames().length, FOCUS_ACCENT_SLOTS.length);
|
|
14098
|
+
}
|
|
14099
|
+
function isEditorCustomRow() {
|
|
14100
|
+
return section() === "general" && bodyRow() === editorCustomRowIndex(themeNames().length, FOCUS_ACCENT_SLOTS.length);
|
|
14101
|
+
}
|
|
13840
14102
|
function settingsSurface() {
|
|
13841
14103
|
return normalizeSettingsSurface(props.kv.get(SETTINGS_SURFACE_KEY, DEFAULT_SETTINGS_SURFACE));
|
|
13842
14104
|
}
|
|
14105
|
+
function selectTheme(name) {
|
|
14106
|
+
if (themeCtx.selected === name)
|
|
14107
|
+
return;
|
|
14108
|
+
if (!themeCtx.set(name))
|
|
14109
|
+
return;
|
|
14110
|
+
props.kv.set("activeTheme", name);
|
|
14111
|
+
props.onVisualPrefsChange?.();
|
|
14112
|
+
}
|
|
14113
|
+
function setTransparentBackground(next) {
|
|
14114
|
+
if (themeCtx.transparentBackground === next)
|
|
14115
|
+
return;
|
|
14116
|
+
themeCtx.setTransparentBackground(next);
|
|
14117
|
+
props.kv.set("transparentBackground", next);
|
|
14118
|
+
props.onVisualPrefsChange?.();
|
|
14119
|
+
}
|
|
14120
|
+
function toggleTransparent() {
|
|
14121
|
+
setTransparentBackground(!themeCtx.transparentBackground);
|
|
14122
|
+
}
|
|
14123
|
+
function selectFocusAccent(slot) {
|
|
14124
|
+
if (themeCtx.focusAccent === slot)
|
|
14125
|
+
return;
|
|
14126
|
+
themeCtx.setFocusAccent(slot);
|
|
14127
|
+
props.kv.set("focusAccent", slot);
|
|
14128
|
+
props.onVisualPrefsChange?.();
|
|
14129
|
+
}
|
|
13843
14130
|
function selectSurface(surface) {
|
|
13844
14131
|
props.kv.set(SETTINGS_SURFACE_KEY, surface);
|
|
13845
14132
|
}
|
|
@@ -13873,6 +14160,30 @@ function SettingsDialog(props) {
|
|
|
13873
14160
|
return;
|
|
13874
14161
|
props.kv.set(engineCommandKey(vendor), next.trim());
|
|
13875
14162
|
}
|
|
14163
|
+
function editorKind() {
|
|
14164
|
+
return normalizeEditorKind(props.kv.get(EDITOR_KIND_KEY, DEFAULT_EDITOR_KIND));
|
|
14165
|
+
}
|
|
14166
|
+
function cycleEditorKind() {
|
|
14167
|
+
const i = EDITOR_KINDS.indexOf(editorKind());
|
|
14168
|
+
const next = EDITOR_KINDS[(i + 1) % EDITOR_KINDS.length];
|
|
14169
|
+
if (next)
|
|
14170
|
+
props.kv.set(EDITOR_KIND_KEY, next);
|
|
14171
|
+
}
|
|
14172
|
+
function editorCustomCommand() {
|
|
14173
|
+
const v = props.kv.get(EDITOR_CUSTOM_KEY, "");
|
|
14174
|
+
return typeof v === "string" ? v : "";
|
|
14175
|
+
}
|
|
14176
|
+
async function editEditorCustom() {
|
|
14177
|
+
const next = await RenameTaskDialog.show(dialog, editorCustomCommand(), {
|
|
14178
|
+
dialogTitle: "Custom editor command (use {file} for the path)"
|
|
14179
|
+
});
|
|
14180
|
+
if (next === undefined)
|
|
14181
|
+
return;
|
|
14182
|
+
const cmd = next.trim();
|
|
14183
|
+
props.kv.set(EDITOR_CUSTOM_KEY, cmd);
|
|
14184
|
+
if (cmd)
|
|
14185
|
+
props.kv.set(EDITOR_KIND_KEY, "custom");
|
|
14186
|
+
}
|
|
13876
14187
|
function enterBody() {
|
|
13877
14188
|
if (level() !== "sidebar" || bodyRowCount2() === 0)
|
|
13878
14189
|
return;
|
|
@@ -13909,14 +14220,14 @@ function SettingsDialog(props) {
|
|
|
13909
14220
|
function activateBodyRow() {
|
|
13910
14221
|
if (section() === "general") {
|
|
13911
14222
|
if (isTransparentRow()) {
|
|
13912
|
-
|
|
14223
|
+
toggleTransparent();
|
|
13913
14224
|
return;
|
|
13914
14225
|
}
|
|
13915
14226
|
const focusIdx = currentFocusAccentRow();
|
|
13916
14227
|
if (focusIdx !== null) {
|
|
13917
14228
|
const slot = FOCUS_ACCENT_SLOTS[focusIdx];
|
|
13918
14229
|
if (slot)
|
|
13919
|
-
|
|
14230
|
+
selectFocusAccent(slot);
|
|
13920
14231
|
return;
|
|
13921
14232
|
}
|
|
13922
14233
|
if (isToastRow()) {
|
|
@@ -13935,9 +14246,17 @@ function SettingsDialog(props) {
|
|
|
13935
14246
|
selectSurface("taskpanel");
|
|
13936
14247
|
return;
|
|
13937
14248
|
}
|
|
14249
|
+
if (isEditorKindRow()) {
|
|
14250
|
+
cycleEditorKind();
|
|
14251
|
+
return;
|
|
14252
|
+
}
|
|
14253
|
+
if (isEditorCustomRow()) {
|
|
14254
|
+
editEditorCustom();
|
|
14255
|
+
return;
|
|
14256
|
+
}
|
|
13938
14257
|
const name = themeNames()[bodyRow()];
|
|
13939
14258
|
if (name)
|
|
13940
|
-
|
|
14259
|
+
selectTheme(name);
|
|
13941
14260
|
return;
|
|
13942
14261
|
}
|
|
13943
14262
|
if (section() === "engines") {
|
|
@@ -13954,6 +14273,7 @@ function SettingsDialog(props) {
|
|
|
13954
14273
|
}
|
|
13955
14274
|
}
|
|
13956
14275
|
useBindings(() => ({
|
|
14276
|
+
enabled: !props.standalone || dialog.stack.length === 0,
|
|
13957
14277
|
bindings: [{
|
|
13958
14278
|
key: "down",
|
|
13959
14279
|
cmd: () => moveCursor(1)
|
|
@@ -13992,7 +14312,7 @@ function SettingsDialog(props) {
|
|
|
13992
14312
|
}
|
|
13993
14313
|
}, {
|
|
13994
14314
|
key: "t",
|
|
13995
|
-
cmd:
|
|
14315
|
+
cmd: toggleTransparent
|
|
13996
14316
|
}]
|
|
13997
14317
|
}));
|
|
13998
14318
|
return (() => {
|
|
@@ -14035,12 +14355,19 @@ function SettingsDialog(props) {
|
|
|
14035
14355
|
setBodyRow,
|
|
14036
14356
|
themeNames,
|
|
14037
14357
|
setThemeCursor,
|
|
14358
|
+
selectTheme,
|
|
14359
|
+
toggleTransparent,
|
|
14360
|
+
selectFocusAccent,
|
|
14038
14361
|
toastEnabled,
|
|
14039
14362
|
soundEnabled,
|
|
14040
14363
|
toggleToast,
|
|
14041
14364
|
toggleSound,
|
|
14042
14365
|
settingsSurface,
|
|
14043
|
-
selectSurface
|
|
14366
|
+
selectSurface,
|
|
14367
|
+
editorKind,
|
|
14368
|
+
cycleEditorKind,
|
|
14369
|
+
editorCustomCommand,
|
|
14370
|
+
editEditorCustom: () => void editEditorCustom()
|
|
14044
14371
|
});
|
|
14045
14372
|
}
|
|
14046
14373
|
}), null);
|
|
@@ -14122,6 +14449,7 @@ var init_settings_dialog = __esm(() => {
|
|
|
14122
14449
|
init_interactive_command();
|
|
14123
14450
|
init_vendor();
|
|
14124
14451
|
init_theme2();
|
|
14452
|
+
init_editor_prefs();
|
|
14125
14453
|
init_keymap();
|
|
14126
14454
|
init_dialog();
|
|
14127
14455
|
init_rename_task_dialog();
|
|
@@ -14129,12 +14457,20 @@ var init_settings_dialog = __esm(() => {
|
|
|
14129
14457
|
init_model();
|
|
14130
14458
|
init_sections();
|
|
14131
14459
|
SettingsDialog.show = (dialog, kv, orchestrator) => {
|
|
14460
|
+
let visualPrefsChanged = false;
|
|
14132
14461
|
return new Promise((resolve6) => {
|
|
14133
14462
|
dialog.replace(() => createComponent2(SettingsDialog, {
|
|
14134
14463
|
kv,
|
|
14135
14464
|
orchestrator,
|
|
14136
|
-
|
|
14137
|
-
|
|
14465
|
+
onVisualPrefsChange: () => {
|
|
14466
|
+
visualPrefsChanged = true;
|
|
14467
|
+
},
|
|
14468
|
+
onClose: () => resolve6({
|
|
14469
|
+
visualPrefsChanged
|
|
14470
|
+
})
|
|
14471
|
+
}), () => resolve6({
|
|
14472
|
+
visualPrefsChanged
|
|
14473
|
+
}));
|
|
14138
14474
|
});
|
|
14139
14475
|
};
|
|
14140
14476
|
});
|
|
@@ -14227,22 +14563,27 @@ var init_kv = __esm(() => {
|
|
|
14227
14563
|
init: () => {
|
|
14228
14564
|
const [store2, setStore2] = createStore(loadInitial());
|
|
14229
14565
|
let writeTimer = null;
|
|
14566
|
+
function writeNow(label) {
|
|
14567
|
+
const statePath2 = kvStatePath();
|
|
14568
|
+
try {
|
|
14569
|
+
mkdirSync4(dirname5(statePath2), {
|
|
14570
|
+
recursive: true
|
|
14571
|
+
});
|
|
14572
|
+
const tmp = `${statePath2}.tmp`;
|
|
14573
|
+
writeFileSync3(tmp, JSON.stringify(store2, null, 2), "utf8");
|
|
14574
|
+
renameSync2(tmp, statePath2);
|
|
14575
|
+
return true;
|
|
14576
|
+
} catch (err) {
|
|
14577
|
+
console.error(`[kobe] kv ${label} failed:`, err);
|
|
14578
|
+
return false;
|
|
14579
|
+
}
|
|
14580
|
+
}
|
|
14230
14581
|
function scheduleWrite() {
|
|
14231
14582
|
if (writeTimer)
|
|
14232
14583
|
clearTimeout(writeTimer);
|
|
14233
14584
|
writeTimer = setTimeout(() => {
|
|
14234
14585
|
writeTimer = null;
|
|
14235
|
-
|
|
14236
|
-
try {
|
|
14237
|
-
mkdirSync4(dirname5(statePath2), {
|
|
14238
|
-
recursive: true
|
|
14239
|
-
});
|
|
14240
|
-
const tmp = `${statePath2}.tmp`;
|
|
14241
|
-
writeFileSync3(tmp, JSON.stringify(store2, null, 2), "utf8");
|
|
14242
|
-
renameSync2(tmp, statePath2);
|
|
14243
|
-
} catch (err) {
|
|
14244
|
-
console.error("[kobe] kv write failed:", err);
|
|
14245
|
-
}
|
|
14586
|
+
writeNow("write");
|
|
14246
14587
|
}, WRITE_DEBOUNCE_MS);
|
|
14247
14588
|
}
|
|
14248
14589
|
const result = {
|
|
@@ -14264,6 +14605,13 @@ var init_kv = __esm(() => {
|
|
|
14264
14605
|
setStore2(key, value);
|
|
14265
14606
|
scheduleWrite();
|
|
14266
14607
|
},
|
|
14608
|
+
flush() {
|
|
14609
|
+
if (writeTimer) {
|
|
14610
|
+
clearTimeout(writeTimer);
|
|
14611
|
+
writeTimer = null;
|
|
14612
|
+
}
|
|
14613
|
+
return writeNow("flush");
|
|
14614
|
+
},
|
|
14267
14615
|
clear() {
|
|
14268
14616
|
for (const k of Object.keys(store2))
|
|
14269
14617
|
setStore2(k, undefined);
|
|
@@ -14415,36 +14763,6 @@ var init_worktree_opener = __esm(() => {
|
|
|
14415
14763
|
];
|
|
14416
14764
|
});
|
|
14417
14765
|
|
|
14418
|
-
// src/tui/panes/sidebar/git-head.ts
|
|
14419
|
-
import { spawnSync as spawnSync8 } from "child_process";
|
|
14420
|
-
function readCurrentBranch(repo) {
|
|
14421
|
-
if (!repo)
|
|
14422
|
-
return "";
|
|
14423
|
-
try {
|
|
14424
|
-
const out = spawnSync8("git", ["symbolic-ref", "--short", "HEAD"], {
|
|
14425
|
-
cwd: repo,
|
|
14426
|
-
encoding: "utf8",
|
|
14427
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
14428
|
-
});
|
|
14429
|
-
if (out.status === 0 && out.stdout) {
|
|
14430
|
-
const name = out.stdout.trim();
|
|
14431
|
-
if (name && name !== "HEAD")
|
|
14432
|
-
return name;
|
|
14433
|
-
}
|
|
14434
|
-
const head = spawnSync8("git", ["rev-parse", "--verify", "HEAD"], {
|
|
14435
|
-
cwd: repo,
|
|
14436
|
-
encoding: "utf8",
|
|
14437
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
14438
|
-
});
|
|
14439
|
-
if (head.status === 0)
|
|
14440
|
-
return "(detached)";
|
|
14441
|
-
return "";
|
|
14442
|
-
} catch {
|
|
14443
|
-
return "";
|
|
14444
|
-
}
|
|
14445
|
-
}
|
|
14446
|
-
var init_git_head = () => {};
|
|
14447
|
-
|
|
14448
14766
|
// src/tui/panes/sidebar/fuzzy.ts
|
|
14449
14767
|
function fuzzyMatch(query, haystack) {
|
|
14450
14768
|
if (!query)
|
|
@@ -15072,8 +15390,16 @@ var init_keybindings = __esm(() => {
|
|
|
15072
15390
|
scope: "files",
|
|
15073
15391
|
keys: ["return"],
|
|
15074
15392
|
category: "Files",
|
|
15075
|
-
description: "Open file",
|
|
15076
|
-
hint: { keys: "enter", label: "
|
|
15393
|
+
description: "Open file read-only preview",
|
|
15394
|
+
hint: { keys: "enter", label: "preview" }
|
|
15395
|
+
},
|
|
15396
|
+
{
|
|
15397
|
+
id: "files.edit",
|
|
15398
|
+
scope: "files",
|
|
15399
|
+
keys: ["e"],
|
|
15400
|
+
category: "Files",
|
|
15401
|
+
description: "Open file in the configured editor (vim / nano / custom)",
|
|
15402
|
+
hint: { keys: "e", label: "edit" }
|
|
15077
15403
|
},
|
|
15078
15404
|
{
|
|
15079
15405
|
id: "files.tab",
|
|
@@ -15355,6 +15681,13 @@ function truncatePathTail(path11, max) {
|
|
|
15355
15681
|
return path11;
|
|
15356
15682
|
return `\u2026${path11.slice(path11.length - Math.max(0, max - 1))}`;
|
|
15357
15683
|
}
|
|
15684
|
+
function abbrevHome(path11) {
|
|
15685
|
+
const home = process.env.HOME;
|
|
15686
|
+
if (home && (path11 === home || path11.startsWith(`${home}/`))) {
|
|
15687
|
+
return `~${path11.slice(home.length)}`;
|
|
15688
|
+
}
|
|
15689
|
+
return path11;
|
|
15690
|
+
}
|
|
15358
15691
|
function Sidebar(props) {
|
|
15359
15692
|
const {
|
|
15360
15693
|
theme
|
|
@@ -15408,14 +15741,15 @@ function Sidebar(props) {
|
|
|
15408
15741
|
onCleanup(() => clearInterval(spinnerInterval));
|
|
15409
15742
|
const rows = createMemo(() => buildRows(props.tasks(), view(), searchMode() ? searchQuery() : ""));
|
|
15410
15743
|
const flatIds = createMemo(() => flattenIds(rows()));
|
|
15744
|
+
const firstTaskFlatIndex = createMemo(() => {
|
|
15745
|
+
const r = rows();
|
|
15746
|
+
const idx = r.findIndex((row) => row.task.kind !== "main");
|
|
15747
|
+
return idx < 0 ? -1 : r[idx].flatIndex;
|
|
15748
|
+
});
|
|
15411
15749
|
const totalRows = createMemo(() => flattenIds(buildRows(props.tasks(), view(), "")).length);
|
|
15412
15750
|
const effectiveWidth = () => props.width ? props.width() : SIDEBAR_WIDTH;
|
|
15413
|
-
const
|
|
15414
|
-
const
|
|
15415
|
-
const titleBudget = createMemo(() => {
|
|
15416
|
-
const reserved = 9 + (showChangesCol() ? CHANGES_COLUMN_WIDTH + 1 : 0) + (showBranchCol() ? BRANCH_LABEL_MAX + 2 : 0);
|
|
15417
|
-
return Math.max(4, effectiveWidth() - reserved);
|
|
15418
|
-
});
|
|
15751
|
+
const titleBudget = createMemo(() => Math.max(6, effectiveWidth() - 9));
|
|
15752
|
+
const subtitleBudget = createMemo(() => Math.max(6, effectiveWidth() - 16));
|
|
15419
15753
|
const dims = useTerminalDimensions();
|
|
15420
15754
|
const [hover, setHover] = createSignal(null);
|
|
15421
15755
|
const [cursorIndex, setCursorIndex] = createSignal(-1);
|
|
@@ -15473,80 +15807,127 @@ function Sidebar(props) {
|
|
|
15473
15807
|
onSearchEnter: () => enterSearch(),
|
|
15474
15808
|
onSearchExit: (select) => exitSearch(select)
|
|
15475
15809
|
});
|
|
15476
|
-
|
|
15477
|
-
var _el$ = createElement("box"), _el$2 = createElement("
|
|
15810
|
+
const SectionHeader = (p) => (() => {
|
|
15811
|
+
var _el$ = createElement("box"), _el$2 = createElement("text"), _el$3 = createElement("text");
|
|
15478
15812
|
insertNode(_el$, _el$2);
|
|
15479
|
-
insertNode(_el$, _el$
|
|
15480
|
-
|
|
15481
|
-
|
|
15482
|
-
setProp(_el$, "
|
|
15483
|
-
setProp(_el$, "
|
|
15484
|
-
setProp(_el
|
|
15485
|
-
|
|
15486
|
-
setProp(_el$, "paddingLeft", 2);
|
|
15487
|
-
setProp(_el$, "paddingRight", 2);
|
|
15488
|
-
insertNode(_el$2, _el$3);
|
|
15489
|
-
insertNode(_el$2, _el$5);
|
|
15490
|
-
setProp(_el$2, "flexDirection", "row");
|
|
15491
|
-
setProp(_el$2, "gap", 1);
|
|
15492
|
-
setProp(_el$2, "paddingBottom", 1);
|
|
15493
|
-
setProp(_el$2, "paddingLeft", 1);
|
|
15494
|
-
insertNode(_el$3, createTextNode(`h`));
|
|
15813
|
+
insertNode(_el$, _el$3);
|
|
15814
|
+
setProp(_el$, "flexDirection", "row");
|
|
15815
|
+
setProp(_el$, "gap", 1);
|
|
15816
|
+
setProp(_el$, "paddingLeft", 1);
|
|
15817
|
+
setProp(_el$, "paddingRight", 1);
|
|
15818
|
+
setProp(_el$2, "wrapMode", "none");
|
|
15819
|
+
insert(_el$2, () => p.label);
|
|
15495
15820
|
setProp(_el$3, "wrapMode", "none");
|
|
15496
|
-
|
|
15497
|
-
|
|
15498
|
-
|
|
15821
|
+
insert(_el$3, () => "\u2500".repeat(Math.max(2, effectiveWidth() - 9 - p.label.length)));
|
|
15822
|
+
effect((_p$) => {
|
|
15823
|
+
var _v$ = p.topPad ? 1 : 0, _v$2 = theme.textMuted, _v$3 = TextAttributes8.BOLD, _v$4 = theme.border;
|
|
15824
|
+
_v$ !== _p$.e && (_p$.e = setProp(_el$, "paddingTop", _v$, _p$.e));
|
|
15825
|
+
_v$2 !== _p$.t && (_p$.t = setProp(_el$2, "fg", _v$2, _p$.t));
|
|
15826
|
+
_v$3 !== _p$.a && (_p$.a = setProp(_el$2, "attributes", _v$3, _p$.a));
|
|
15827
|
+
_v$4 !== _p$.o && (_p$.o = setProp(_el$3, "fg", _v$4, _p$.o));
|
|
15828
|
+
return _p$;
|
|
15829
|
+
}, {
|
|
15830
|
+
e: undefined,
|
|
15831
|
+
t: undefined,
|
|
15832
|
+
a: undefined,
|
|
15833
|
+
o: undefined
|
|
15834
|
+
});
|
|
15835
|
+
return _el$;
|
|
15836
|
+
})();
|
|
15837
|
+
return (() => {
|
|
15838
|
+
var _el$4 = createElement("box"), _el$5 = createElement("box"), _el$6 = createElement("text"), _el$18 = createElement("box"), _el$19 = createElement("scrollbox"), _el$20 = createElement("box"), _el$23 = createElement("box"), _el$24 = createElement("text");
|
|
15839
|
+
insertNode(_el$4, _el$5);
|
|
15840
|
+
insertNode(_el$4, _el$18);
|
|
15841
|
+
insertNode(_el$4, _el$19);
|
|
15842
|
+
insertNode(_el$4, _el$23);
|
|
15843
|
+
setProp(_el$4, "flexShrink", 0);
|
|
15844
|
+
setProp(_el$4, "flexDirection", "column");
|
|
15845
|
+
setProp(_el$4, "paddingTop", 1);
|
|
15846
|
+
setProp(_el$4, "paddingBottom", 1);
|
|
15847
|
+
setProp(_el$4, "paddingLeft", 0);
|
|
15848
|
+
setProp(_el$4, "paddingRight", 0);
|
|
15849
|
+
insertNode(_el$5, _el$6);
|
|
15850
|
+
setProp(_el$5, "flexDirection", "row");
|
|
15851
|
+
setProp(_el$5, "justifyContent", "space-between");
|
|
15852
|
+
setProp(_el$5, "gap", 1);
|
|
15853
|
+
setProp(_el$5, "paddingBottom", 1);
|
|
15854
|
+
setProp(_el$5, "paddingLeft", 1);
|
|
15855
|
+
setProp(_el$5, "paddingRight", 1);
|
|
15856
|
+
insertNode(_el$6, createTextNode(`KOBE`));
|
|
15857
|
+
setProp(_el$6, "wrapMode", "none");
|
|
15858
|
+
insert(_el$5, createComponent2(Show, {
|
|
15859
|
+
get when() {
|
|
15860
|
+
return props.headerStatus?.();
|
|
15861
|
+
},
|
|
15862
|
+
children: (status) => (() => {
|
|
15863
|
+
var _el$26 = createElement("text");
|
|
15864
|
+
setProp(_el$26, "wrapMode", "none");
|
|
15865
|
+
setProp(_el$26, "onMouseUp", () => props.onHeaderStatusClick?.());
|
|
15866
|
+
insert(_el$26, () => status().label);
|
|
15867
|
+
effect((_p$) => {
|
|
15868
|
+
var _v$11 = status().emphasize ? theme.warning : theme.textMuted, _v$12 = status().emphasize ? TextAttributes8.BOLD : TextAttributes8.DIM;
|
|
15869
|
+
_v$11 !== _p$.e && (_p$.e = setProp(_el$26, "fg", _v$11, _p$.e));
|
|
15870
|
+
_v$12 !== _p$.t && (_p$.t = setProp(_el$26, "attributes", _v$12, _p$.t));
|
|
15871
|
+
return _p$;
|
|
15872
|
+
}, {
|
|
15873
|
+
e: undefined,
|
|
15874
|
+
t: undefined
|
|
15875
|
+
});
|
|
15876
|
+
return _el$26;
|
|
15877
|
+
})()
|
|
15878
|
+
}), null);
|
|
15879
|
+
insert(_el$4, createComponent2(Show, {
|
|
15499
15880
|
get when() {
|
|
15500
15881
|
return searchMode();
|
|
15501
15882
|
},
|
|
15502
15883
|
get children() {
|
|
15503
|
-
var _el$
|
|
15504
|
-
insertNode(_el$
|
|
15505
|
-
insertNode(_el$
|
|
15506
|
-
insertNode(_el$
|
|
15507
|
-
setProp(_el$
|
|
15508
|
-
setProp(_el$
|
|
15509
|
-
setProp(_el$
|
|
15510
|
-
setProp(_el$
|
|
15511
|
-
insertNode(_el$
|
|
15512
|
-
setProp(_el$
|
|
15513
|
-
setProp(_el$0, "wrapMode", "none");
|
|
15514
|
-
insert(_el$0, searchQuery);
|
|
15515
|
-
insertNode(_el$1, createTextNode(`\u2588`));
|
|
15884
|
+
var _el$8 = createElement("box"), _el$9 = createElement("text"), _el$1 = createElement("text"), _el$10 = createElement("text");
|
|
15885
|
+
insertNode(_el$8, _el$9);
|
|
15886
|
+
insertNode(_el$8, _el$1);
|
|
15887
|
+
insertNode(_el$8, _el$10);
|
|
15888
|
+
setProp(_el$8, "flexDirection", "row");
|
|
15889
|
+
setProp(_el$8, "gap", 0);
|
|
15890
|
+
setProp(_el$8, "paddingBottom", 1);
|
|
15891
|
+
setProp(_el$8, "paddingLeft", 1);
|
|
15892
|
+
insertNode(_el$9, createTextNode(`/`));
|
|
15893
|
+
setProp(_el$9, "wrapMode", "none");
|
|
15516
15894
|
setProp(_el$1, "wrapMode", "none");
|
|
15517
|
-
insert(_el$
|
|
15895
|
+
insert(_el$1, searchQuery);
|
|
15896
|
+
insertNode(_el$10, createTextNode(`\u2588`));
|
|
15897
|
+
setProp(_el$10, "wrapMode", "none");
|
|
15898
|
+
insert(_el$8, createComponent2(Show, {
|
|
15518
15899
|
get when() {
|
|
15519
15900
|
return searchQuery().length === 0;
|
|
15520
15901
|
},
|
|
15521
15902
|
get children() {
|
|
15522
|
-
var _el$
|
|
15523
|
-
insertNode(_el$
|
|
15524
|
-
setProp(_el$
|
|
15525
|
-
effect((_$p) => setProp(_el$
|
|
15526
|
-
return _el$
|
|
15903
|
+
var _el$12 = createElement("text"), _el$13 = createTextNode(` fuzzy filter`);
|
|
15904
|
+
insertNode(_el$12, _el$13);
|
|
15905
|
+
setProp(_el$12, "wrapMode", "none");
|
|
15906
|
+
effect((_$p) => setProp(_el$12, "fg", theme.textMuted, _$p));
|
|
15907
|
+
return _el$12;
|
|
15527
15908
|
}
|
|
15528
15909
|
}), null);
|
|
15529
|
-
insert(_el$
|
|
15910
|
+
insert(_el$8, createComponent2(Show, {
|
|
15530
15911
|
get when() {
|
|
15531
15912
|
return searchQuery().length > 0;
|
|
15532
15913
|
},
|
|
15533
15914
|
get children() {
|
|
15534
|
-
var _el$
|
|
15535
|
-
insertNode(_el$
|
|
15536
|
-
insertNode(_el$
|
|
15537
|
-
setProp(_el$
|
|
15538
|
-
insert(_el$
|
|
15539
|
-
insert(_el$
|
|
15540
|
-
effect((_$p) => setProp(_el$
|
|
15541
|
-
return _el$
|
|
15915
|
+
var _el$15 = createElement("text"), _el$16 = createTextNode(` `), _el$17 = createTextNode(`/`);
|
|
15916
|
+
insertNode(_el$15, _el$16);
|
|
15917
|
+
insertNode(_el$15, _el$17);
|
|
15918
|
+
setProp(_el$15, "wrapMode", "none");
|
|
15919
|
+
insert(_el$15, () => flatIds().length, _el$17);
|
|
15920
|
+
insert(_el$15, totalRows, null);
|
|
15921
|
+
effect((_$p) => setProp(_el$15, "fg", theme.textMuted, _$p));
|
|
15922
|
+
return _el$15;
|
|
15542
15923
|
}
|
|
15543
15924
|
}), null);
|
|
15544
15925
|
effect((_p$) => {
|
|
15545
|
-
var { info: _v
|
|
15546
|
-
_v$ !== _p$.e && (_p$.e = setProp(_el$
|
|
15547
|
-
_v$
|
|
15548
|
-
_v$
|
|
15549
|
-
_v$
|
|
15926
|
+
var { info: _v$5, text: _v$6, info: _v$7 } = theme, _v$8 = TextAttributes8.BLINK;
|
|
15927
|
+
_v$5 !== _p$.e && (_p$.e = setProp(_el$9, "fg", _v$5, _p$.e));
|
|
15928
|
+
_v$6 !== _p$.t && (_p$.t = setProp(_el$1, "fg", _v$6, _p$.t));
|
|
15929
|
+
_v$7 !== _p$.a && (_p$.a = setProp(_el$10, "fg", _v$7, _p$.a));
|
|
15930
|
+
_v$8 !== _p$.o && (_p$.o = setProp(_el$10, "attributes", _v$8, _p$.o));
|
|
15550
15931
|
return _p$;
|
|
15551
15932
|
}, {
|
|
15552
15933
|
e: undefined,
|
|
@@ -15554,46 +15935,46 @@ function Sidebar(props) {
|
|
|
15554
15935
|
a: undefined,
|
|
15555
15936
|
o: undefined
|
|
15556
15937
|
});
|
|
15557
|
-
return _el$
|
|
15938
|
+
return _el$8;
|
|
15558
15939
|
}
|
|
15559
|
-
}), _el$
|
|
15560
|
-
setProp(_el$
|
|
15561
|
-
setProp(_el$
|
|
15562
|
-
setProp(_el$
|
|
15563
|
-
setProp(_el$
|
|
15564
|
-
insert(_el$
|
|
15940
|
+
}), _el$18);
|
|
15941
|
+
setProp(_el$18, "flexDirection", "row");
|
|
15942
|
+
setProp(_el$18, "gap", 2);
|
|
15943
|
+
setProp(_el$18, "paddingBottom", 1);
|
|
15944
|
+
setProp(_el$18, "paddingLeft", 1);
|
|
15945
|
+
insert(_el$18, createComponent2(For, {
|
|
15565
15946
|
each: VIEW_TABS,
|
|
15566
15947
|
children: (tab) => {
|
|
15567
15948
|
const active = () => view() === tab.view;
|
|
15568
15949
|
return (() => {
|
|
15569
|
-
var _el$
|
|
15570
|
-
setProp(_el$
|
|
15571
|
-
setProp(_el$
|
|
15572
|
-
insert(_el$
|
|
15950
|
+
var _el$27 = createElement("text");
|
|
15951
|
+
setProp(_el$27, "wrapMode", "none");
|
|
15952
|
+
setProp(_el$27, "onMouseUp", () => setView(tab.view));
|
|
15953
|
+
insert(_el$27, () => tab.label);
|
|
15573
15954
|
effect((_p$) => {
|
|
15574
|
-
var _v$
|
|
15575
|
-
_v$
|
|
15576
|
-
_v$
|
|
15955
|
+
var _v$13 = active() ? theme.primary : theme.textMuted, _v$14 = active() ? TextAttributes8.BOLD : undefined;
|
|
15956
|
+
_v$13 !== _p$.e && (_p$.e = setProp(_el$27, "fg", _v$13, _p$.e));
|
|
15957
|
+
_v$14 !== _p$.t && (_p$.t = setProp(_el$27, "attributes", _v$14, _p$.t));
|
|
15577
15958
|
return _p$;
|
|
15578
15959
|
}, {
|
|
15579
15960
|
e: undefined,
|
|
15580
15961
|
t: undefined
|
|
15581
15962
|
});
|
|
15582
|
-
return _el$
|
|
15963
|
+
return _el$27;
|
|
15583
15964
|
})();
|
|
15584
15965
|
}
|
|
15585
15966
|
}));
|
|
15586
|
-
insertNode(_el$
|
|
15587
|
-
setProp(_el$
|
|
15588
|
-
setProp(_el$
|
|
15967
|
+
insertNode(_el$19, _el$20);
|
|
15968
|
+
setProp(_el$19, "flexGrow", 1);
|
|
15969
|
+
setProp(_el$19, "verticalScrollbarOptions", {
|
|
15589
15970
|
trackOptions: {
|
|
15590
15971
|
foregroundColor: "transparent"
|
|
15591
15972
|
}
|
|
15592
15973
|
});
|
|
15593
|
-
setProp(_el$
|
|
15594
|
-
setProp(_el$
|
|
15595
|
-
setProp(_el$
|
|
15596
|
-
insert(_el$
|
|
15974
|
+
setProp(_el$20, "flexShrink", 0);
|
|
15975
|
+
setProp(_el$20, "gap", 0);
|
|
15976
|
+
setProp(_el$20, "paddingRight", 1);
|
|
15977
|
+
insert(_el$20, createComponent2(For, {
|
|
15597
15978
|
get each() {
|
|
15598
15979
|
return rows();
|
|
15599
15980
|
},
|
|
@@ -15633,175 +16014,290 @@ function Sidebar(props) {
|
|
|
15633
16014
|
return theme.textMuted;
|
|
15634
16015
|
}
|
|
15635
16016
|
};
|
|
15636
|
-
const branchLabel = createMemo(() => {
|
|
15637
|
-
if (!isMain)
|
|
15638
|
-
return "";
|
|
15639
|
-
branchTick();
|
|
15640
|
-
return readCurrentBranch(task.repo);
|
|
15641
|
-
});
|
|
15642
16017
|
const changes = createMemo(() => {
|
|
15643
16018
|
branchTick();
|
|
15644
16019
|
return readWorktreeChanges(task.worktreePath);
|
|
15645
16020
|
});
|
|
15646
16021
|
const titleText = isMain ? repoBasename(task.repo) : task.title;
|
|
16022
|
+
const loading = () => isLive() || task.status === "in_progress";
|
|
16023
|
+
const subtitleText = createMemo(() => {
|
|
16024
|
+
if (task.branch.length > 0)
|
|
16025
|
+
return truncateBranchLabel(task.branch, subtitleBudget());
|
|
16026
|
+
return STATUS_LABEL[task.status];
|
|
16027
|
+
});
|
|
16028
|
+
const barColor = () => isCursor() ? theme.focusAccent : isSelected() ? theme.primary : undefined;
|
|
16029
|
+
const barGlyph = () => isCursor() || isSelected() ? "\u258C" : " ";
|
|
16030
|
+
const showProjectsHeader = () => isMain && flatIndex === 0;
|
|
16031
|
+
const showTasksHeader = () => !isMain && flatIndex === firstTaskFlatIndex();
|
|
15647
16032
|
return (() => {
|
|
15648
|
-
var _el$
|
|
15649
|
-
insertNode(_el$
|
|
15650
|
-
|
|
15651
|
-
setProp(_el$
|
|
15652
|
-
setProp(_el$
|
|
15653
|
-
|
|
15654
|
-
|
|
15655
|
-
|
|
16033
|
+
var _el$28 = createElement("box"), _el$29 = createElement("box");
|
|
16034
|
+
insertNode(_el$28, _el$29);
|
|
16035
|
+
setProp(_el$28, "flexDirection", "column");
|
|
16036
|
+
setProp(_el$28, "gap", 0);
|
|
16037
|
+
setProp(_el$28, "paddingBottom", isMain ? 0 : 1);
|
|
16038
|
+
insert(_el$28, createComponent2(Show, {
|
|
16039
|
+
get when() {
|
|
16040
|
+
return showProjectsHeader();
|
|
16041
|
+
},
|
|
16042
|
+
get children() {
|
|
16043
|
+
return createComponent2(SectionHeader, {
|
|
16044
|
+
label: "PROJECTS"
|
|
16045
|
+
});
|
|
16046
|
+
}
|
|
16047
|
+
}), _el$29);
|
|
16048
|
+
insert(_el$28, createComponent2(Show, {
|
|
16049
|
+
get when() {
|
|
16050
|
+
return showTasksHeader();
|
|
16051
|
+
},
|
|
16052
|
+
get children() {
|
|
16053
|
+
return createComponent2(SectionHeader, {
|
|
16054
|
+
label: "TASKS",
|
|
16055
|
+
get topPad() {
|
|
16056
|
+
return firstTaskFlatIndex() > 0;
|
|
16057
|
+
}
|
|
16058
|
+
});
|
|
16059
|
+
}
|
|
16060
|
+
}), _el$29);
|
|
16061
|
+
setProp(_el$29, "flexDirection", "column");
|
|
16062
|
+
setProp(_el$29, "gap", 0);
|
|
16063
|
+
setProp(_el$29, "onMouseUp", () => {
|
|
15656
16064
|
props.onSelect(task.id);
|
|
15657
16065
|
if (props.activateOnClick)
|
|
15658
16066
|
props.onActivate?.(task.id);
|
|
15659
16067
|
});
|
|
15660
|
-
setProp(_el$
|
|
16068
|
+
setProp(_el$29, "onMouseOver", (e) => setHover({
|
|
15661
16069
|
task,
|
|
15662
16070
|
x: e.x,
|
|
15663
16071
|
y: e.y
|
|
15664
16072
|
}));
|
|
15665
|
-
setProp(_el$
|
|
15666
|
-
|
|
15667
|
-
|
|
15668
|
-
setProp(_el$28, "wrapMode", "none");
|
|
15669
|
-
setProp(_el$28, "flexGrow", 1);
|
|
15670
|
-
insert(_el$28, () => truncateTitle(titleText, titleBudget()));
|
|
15671
|
-
insert(_el$26, createComponent2(Show, {
|
|
15672
|
-
get when() {
|
|
15673
|
-
return showChangesCol();
|
|
15674
|
-
},
|
|
15675
|
-
get children() {
|
|
15676
|
-
var _el$29 = createElement("box");
|
|
15677
|
-
setProp(_el$29, "width", 5);
|
|
15678
|
-
setProp(_el$29, "flexShrink", 0);
|
|
15679
|
-
setProp(_el$29, "flexDirection", "row");
|
|
15680
|
-
setProp(_el$29, "justifyContent", "flex-end");
|
|
15681
|
-
setProp(_el$29, "gap", 1);
|
|
15682
|
-
insert(_el$29, createComponent2(Show, {
|
|
15683
|
-
get when() {
|
|
15684
|
-
return changes().added > 0;
|
|
15685
|
-
},
|
|
15686
|
-
get children() {
|
|
15687
|
-
var _el$30 = createElement("text"), _el$31 = createTextNode(`+`);
|
|
15688
|
-
insertNode(_el$30, _el$31);
|
|
15689
|
-
setProp(_el$30, "wrapMode", "none");
|
|
15690
|
-
insert(_el$30, () => changes().added, null);
|
|
15691
|
-
effect((_$p) => setProp(_el$30, "fg", isCursor() ? theme.selectedListItemText : theme.success, _$p));
|
|
15692
|
-
return _el$30;
|
|
15693
|
-
}
|
|
15694
|
-
}), null);
|
|
15695
|
-
insert(_el$29, createComponent2(Show, {
|
|
15696
|
-
get when() {
|
|
15697
|
-
return changes().deleted > 0;
|
|
15698
|
-
},
|
|
15699
|
-
get children() {
|
|
15700
|
-
var _el$32 = createElement("text"), _el$33 = createTextNode(`\u2212`);
|
|
15701
|
-
insertNode(_el$32, _el$33);
|
|
15702
|
-
setProp(_el$32, "wrapMode", "none");
|
|
15703
|
-
insert(_el$32, () => changes().deleted, null);
|
|
15704
|
-
effect((_$p) => setProp(_el$32, "fg", isCursor() ? theme.selectedListItemText : theme.error, _$p));
|
|
15705
|
-
return _el$32;
|
|
15706
|
-
}
|
|
15707
|
-
}), null);
|
|
15708
|
-
return _el$29;
|
|
15709
|
-
}
|
|
15710
|
-
}), null);
|
|
15711
|
-
insert(_el$26, createComponent2(Show, {
|
|
15712
|
-
get when() {
|
|
15713
|
-
return memo2(() => !!showBranchCol())() && (isMain && branchLabel().length > 0 || !isMain && (task.branch.length > 0 || task.pinned === true));
|
|
15714
|
-
},
|
|
16073
|
+
setProp(_el$29, "onMouseOut", () => setHover((h) => h?.task.id === task.id ? null : h));
|
|
16074
|
+
insert(_el$29, createComponent2(Show, {
|
|
16075
|
+
when: isMain,
|
|
15715
16076
|
get children() {
|
|
15716
|
-
var _el$
|
|
15717
|
-
|
|
15718
|
-
|
|
15719
|
-
setProp(_el$
|
|
15720
|
-
setProp(_el$
|
|
15721
|
-
setProp(_el$
|
|
15722
|
-
insert(_el$
|
|
16077
|
+
var _el$30 = createElement("box"), _el$31 = createElement("text"), _el$32 = createElement("box"), _el$33 = createElement("text"), _el$34 = createElement("text");
|
|
16078
|
+
insertNode(_el$30, _el$31);
|
|
16079
|
+
insertNode(_el$30, _el$32);
|
|
16080
|
+
setProp(_el$30, "flexDirection", "row");
|
|
16081
|
+
setProp(_el$30, "gap", 0);
|
|
16082
|
+
setProp(_el$31, "wrapMode", "none");
|
|
16083
|
+
insert(_el$31, barGlyph);
|
|
16084
|
+
insertNode(_el$32, _el$33);
|
|
16085
|
+
insertNode(_el$32, _el$34);
|
|
16086
|
+
setProp(_el$32, "flexDirection", "row");
|
|
16087
|
+
setProp(_el$32, "flexGrow", 1);
|
|
16088
|
+
setProp(_el$32, "paddingRight", 1);
|
|
16089
|
+
setProp(_el$32, "gap", 1);
|
|
16090
|
+
setProp(_el$33, "wrapMode", "none");
|
|
16091
|
+
insert(_el$33, (() => {
|
|
16092
|
+
var _c$2 = memo2(() => !!loading());
|
|
16093
|
+
return () => _c$2() ? IN_PROGRESS_SPINNER[spinnerFrame()] ?? IN_PROGRESS_SPINNER[0] : "\u2605";
|
|
16094
|
+
})());
|
|
16095
|
+
setProp(_el$34, "wrapMode", "none");
|
|
16096
|
+
setProp(_el$34, "flexGrow", 1);
|
|
16097
|
+
insert(_el$34, () => truncateTitle(titleText, titleBudget()));
|
|
16098
|
+
insert(_el$32, createComponent2(Show, {
|
|
15723
16099
|
get when() {
|
|
15724
|
-
return
|
|
16100
|
+
return loading();
|
|
15725
16101
|
},
|
|
15726
16102
|
get children() {
|
|
15727
16103
|
var _el$35 = createElement("text");
|
|
16104
|
+
insertNode(_el$35, createTextNode(`working`));
|
|
15728
16105
|
setProp(_el$35, "wrapMode", "none");
|
|
15729
|
-
|
|
15730
|
-
effect((_$p) => setProp(_el$35, "fg", isCursor() ? theme.selectedListItemText : theme.textMuted, _$p));
|
|
16106
|
+
effect((_$p) => setProp(_el$35, "fg", theme.primary, _$p));
|
|
15731
16107
|
return _el$35;
|
|
15732
16108
|
}
|
|
15733
16109
|
}), null);
|
|
15734
|
-
insert(_el$
|
|
15735
|
-
get when() {
|
|
15736
|
-
return !isMain && task.branch.length > 0;
|
|
15737
|
-
},
|
|
15738
|
-
get children() {
|
|
15739
|
-
var _el$36 = createElement("text");
|
|
15740
|
-
setProp(_el$36, "wrapMode", "none");
|
|
15741
|
-
insert(_el$36, () => truncateBranchLabel(task.branch));
|
|
15742
|
-
effect((_$p) => setProp(_el$36, "fg", isCursor() ? theme.selectedListItemText : theme.textMuted, _$p));
|
|
15743
|
-
return _el$36;
|
|
15744
|
-
}
|
|
15745
|
-
}), null);
|
|
15746
|
-
insert(_el$34, createComponent2(Show, {
|
|
16110
|
+
insert(_el$32, createComponent2(Show, {
|
|
15747
16111
|
get when() {
|
|
15748
|
-
return !
|
|
16112
|
+
return !loading();
|
|
15749
16113
|
},
|
|
15750
16114
|
get children() {
|
|
15751
16115
|
var _el$37 = createElement("text");
|
|
15752
|
-
insertNode(_el$37, createTextNode(`\u25B4`));
|
|
15753
16116
|
setProp(_el$37, "wrapMode", "none");
|
|
15754
|
-
|
|
16117
|
+
insert(_el$37, () => truncatePathTail(abbrevHome(task.repo), subtitleBudget()));
|
|
16118
|
+
effect((_p$) => {
|
|
16119
|
+
var _v$15 = theme.textMuted, _v$16 = TextAttributes8.DIM;
|
|
16120
|
+
_v$15 !== _p$.e && (_p$.e = setProp(_el$37, "fg", _v$15, _p$.e));
|
|
16121
|
+
_v$16 !== _p$.t && (_p$.t = setProp(_el$37, "attributes", _v$16, _p$.t));
|
|
16122
|
+
return _p$;
|
|
16123
|
+
}, {
|
|
16124
|
+
e: undefined,
|
|
16125
|
+
t: undefined
|
|
16126
|
+
});
|
|
15755
16127
|
return _el$37;
|
|
15756
16128
|
}
|
|
15757
16129
|
}), null);
|
|
15758
|
-
|
|
16130
|
+
effect((_p$) => {
|
|
16131
|
+
var _v$17 = barColor(), _v$18 = theme.primary, _v$19 = TextAttributes8.BOLD, _v$20 = theme.text, _v$21 = TextAttributes8.BOLD;
|
|
16132
|
+
_v$17 !== _p$.e && (_p$.e = setProp(_el$31, "fg", _v$17, _p$.e));
|
|
16133
|
+
_v$18 !== _p$.t && (_p$.t = setProp(_el$33, "fg", _v$18, _p$.t));
|
|
16134
|
+
_v$19 !== _p$.a && (_p$.a = setProp(_el$33, "attributes", _v$19, _p$.a));
|
|
16135
|
+
_v$20 !== _p$.o && (_p$.o = setProp(_el$34, "fg", _v$20, _p$.o));
|
|
16136
|
+
_v$21 !== _p$.i && (_p$.i = setProp(_el$34, "attributes", _v$21, _p$.i));
|
|
16137
|
+
return _p$;
|
|
16138
|
+
}, {
|
|
16139
|
+
e: undefined,
|
|
16140
|
+
t: undefined,
|
|
16141
|
+
a: undefined,
|
|
16142
|
+
o: undefined,
|
|
16143
|
+
i: undefined
|
|
16144
|
+
});
|
|
16145
|
+
return _el$30;
|
|
15759
16146
|
}
|
|
15760
16147
|
}), null);
|
|
15761
|
-
|
|
15762
|
-
|
|
15763
|
-
|
|
15764
|
-
|
|
15765
|
-
|
|
15766
|
-
|
|
15767
|
-
|
|
15768
|
-
|
|
15769
|
-
|
|
15770
|
-
|
|
15771
|
-
|
|
15772
|
-
|
|
15773
|
-
|
|
15774
|
-
|
|
15775
|
-
|
|
15776
|
-
|
|
16148
|
+
insert(_el$29, createComponent2(Show, {
|
|
16149
|
+
when: !isMain,
|
|
16150
|
+
get children() {
|
|
16151
|
+
return [(() => {
|
|
16152
|
+
var _el$38 = createElement("box"), _el$39 = createElement("text"), _el$40 = createElement("box"), _el$41 = createElement("text"), _el$42 = createElement("text");
|
|
16153
|
+
insertNode(_el$38, _el$39);
|
|
16154
|
+
insertNode(_el$38, _el$40);
|
|
16155
|
+
setProp(_el$38, "flexDirection", "row");
|
|
16156
|
+
setProp(_el$38, "gap", 0);
|
|
16157
|
+
setProp(_el$39, "wrapMode", "none");
|
|
16158
|
+
insert(_el$39, barGlyph);
|
|
16159
|
+
insertNode(_el$40, _el$41);
|
|
16160
|
+
insertNode(_el$40, _el$42);
|
|
16161
|
+
setProp(_el$40, "flexDirection", "row");
|
|
16162
|
+
setProp(_el$40, "flexGrow", 1);
|
|
16163
|
+
setProp(_el$40, "paddingRight", 1);
|
|
16164
|
+
setProp(_el$40, "gap", 1);
|
|
16165
|
+
setProp(_el$41, "wrapMode", "none");
|
|
16166
|
+
insert(_el$41, (() => {
|
|
16167
|
+
var _c$3 = memo2(() => !!loading());
|
|
16168
|
+
return () => _c$3() ? IN_PROGRESS_SPINNER[spinnerFrame()] ?? IN_PROGRESS_SPINNER[0] : badge.glyph;
|
|
16169
|
+
})());
|
|
16170
|
+
setProp(_el$42, "wrapMode", "none");
|
|
16171
|
+
setProp(_el$42, "flexGrow", 1);
|
|
16172
|
+
insert(_el$42, () => truncateTitle(titleText, titleBudget()));
|
|
16173
|
+
insert(_el$40, createComponent2(Show, {
|
|
16174
|
+
get when() {
|
|
16175
|
+
return loading();
|
|
16176
|
+
},
|
|
16177
|
+
get children() {
|
|
16178
|
+
var _el$43 = createElement("text");
|
|
16179
|
+
insertNode(_el$43, createTextNode(`working`));
|
|
16180
|
+
setProp(_el$43, "wrapMode", "none");
|
|
16181
|
+
effect((_$p) => setProp(_el$43, "fg", theme.primary, _$p));
|
|
16182
|
+
return _el$43;
|
|
16183
|
+
}
|
|
16184
|
+
}), null);
|
|
16185
|
+
effect((_p$) => {
|
|
16186
|
+
var _v$22 = barColor(), _v$23 = badgeColor(), _v$24 = TextAttributes8.BOLD, _v$25 = theme.text, _v$26 = isSelected() || isCursor() ? TextAttributes8.BOLD : undefined;
|
|
16187
|
+
_v$22 !== _p$.e && (_p$.e = setProp(_el$39, "fg", _v$22, _p$.e));
|
|
16188
|
+
_v$23 !== _p$.t && (_p$.t = setProp(_el$41, "fg", _v$23, _p$.t));
|
|
16189
|
+
_v$24 !== _p$.a && (_p$.a = setProp(_el$41, "attributes", _v$24, _p$.a));
|
|
16190
|
+
_v$25 !== _p$.o && (_p$.o = setProp(_el$42, "fg", _v$25, _p$.o));
|
|
16191
|
+
_v$26 !== _p$.i && (_p$.i = setProp(_el$42, "attributes", _v$26, _p$.i));
|
|
16192
|
+
return _p$;
|
|
16193
|
+
}, {
|
|
16194
|
+
e: undefined,
|
|
16195
|
+
t: undefined,
|
|
16196
|
+
a: undefined,
|
|
16197
|
+
o: undefined,
|
|
16198
|
+
i: undefined
|
|
16199
|
+
});
|
|
16200
|
+
return _el$38;
|
|
16201
|
+
})(), (() => {
|
|
16202
|
+
var _el$45 = createElement("box"), _el$46 = createElement("text"), _el$47 = createElement("box"), _el$48 = createElement("text");
|
|
16203
|
+
insertNode(_el$45, _el$46);
|
|
16204
|
+
insertNode(_el$45, _el$47);
|
|
16205
|
+
setProp(_el$45, "flexDirection", "row");
|
|
16206
|
+
setProp(_el$45, "gap", 0);
|
|
16207
|
+
setProp(_el$46, "wrapMode", "none");
|
|
16208
|
+
insert(_el$46, barGlyph);
|
|
16209
|
+
insertNode(_el$47, _el$48);
|
|
16210
|
+
setProp(_el$47, "flexDirection", "row");
|
|
16211
|
+
setProp(_el$47, "flexGrow", 1);
|
|
16212
|
+
setProp(_el$47, "paddingLeft", 2);
|
|
16213
|
+
setProp(_el$47, "paddingRight", 1);
|
|
16214
|
+
setProp(_el$47, "gap", 1);
|
|
16215
|
+
setProp(_el$48, "wrapMode", "none");
|
|
16216
|
+
setProp(_el$48, "flexGrow", 1);
|
|
16217
|
+
insert(_el$48, subtitleText);
|
|
16218
|
+
insert(_el$47, createComponent2(Show, {
|
|
16219
|
+
get when() {
|
|
16220
|
+
return task.pinned === true;
|
|
16221
|
+
},
|
|
16222
|
+
get children() {
|
|
16223
|
+
var _el$49 = createElement("text");
|
|
16224
|
+
insertNode(_el$49, createTextNode(`\u25B4`));
|
|
16225
|
+
setProp(_el$49, "wrapMode", "none");
|
|
16226
|
+
effect((_$p) => setProp(_el$49, "fg", theme.warning, _$p));
|
|
16227
|
+
return _el$49;
|
|
16228
|
+
}
|
|
16229
|
+
}), null);
|
|
16230
|
+
insert(_el$47, createComponent2(Show, {
|
|
16231
|
+
get when() {
|
|
16232
|
+
return changes().added > 0;
|
|
16233
|
+
},
|
|
16234
|
+
get children() {
|
|
16235
|
+
var _el$51 = createElement("text"), _el$52 = createTextNode(`+`);
|
|
16236
|
+
insertNode(_el$51, _el$52);
|
|
16237
|
+
setProp(_el$51, "wrapMode", "none");
|
|
16238
|
+
insert(_el$51, () => changes().added, null);
|
|
16239
|
+
effect((_$p) => setProp(_el$51, "fg", theme.success, _$p));
|
|
16240
|
+
return _el$51;
|
|
16241
|
+
}
|
|
16242
|
+
}), null);
|
|
16243
|
+
insert(_el$47, createComponent2(Show, {
|
|
16244
|
+
get when() {
|
|
16245
|
+
return changes().deleted > 0;
|
|
16246
|
+
},
|
|
16247
|
+
get children() {
|
|
16248
|
+
var _el$53 = createElement("text"), _el$54 = createTextNode(`\u2212`);
|
|
16249
|
+
insertNode(_el$53, _el$54);
|
|
16250
|
+
setProp(_el$53, "wrapMode", "none");
|
|
16251
|
+
insert(_el$53, () => changes().deleted, null);
|
|
16252
|
+
effect((_$p) => setProp(_el$53, "fg", theme.error, _$p));
|
|
16253
|
+
return _el$53;
|
|
16254
|
+
}
|
|
16255
|
+
}), null);
|
|
16256
|
+
effect((_p$) => {
|
|
16257
|
+
var _v$27 = barColor(), _v$28 = theme.textMuted, _v$29 = TextAttributes8.DIM;
|
|
16258
|
+
_v$27 !== _p$.e && (_p$.e = setProp(_el$46, "fg", _v$27, _p$.e));
|
|
16259
|
+
_v$28 !== _p$.t && (_p$.t = setProp(_el$48, "fg", _v$28, _p$.t));
|
|
16260
|
+
_v$29 !== _p$.a && (_p$.a = setProp(_el$48, "attributes", _v$29, _p$.a));
|
|
16261
|
+
return _p$;
|
|
16262
|
+
}, {
|
|
16263
|
+
e: undefined,
|
|
16264
|
+
t: undefined,
|
|
16265
|
+
a: undefined
|
|
16266
|
+
});
|
|
16267
|
+
return _el$45;
|
|
16268
|
+
})()];
|
|
16269
|
+
}
|
|
16270
|
+
}), null);
|
|
16271
|
+
effect((_$p) => setProp(_el$29, "backgroundColor", isCursor() ? theme.backgroundElement : undefined, _$p));
|
|
16272
|
+
return _el$28;
|
|
15777
16273
|
})();
|
|
15778
16274
|
}
|
|
15779
16275
|
}), null);
|
|
15780
|
-
insert(_el$
|
|
16276
|
+
insert(_el$20, createComponent2(Show, {
|
|
15781
16277
|
get when() {
|
|
15782
16278
|
return flatIds().length === 0;
|
|
15783
16279
|
},
|
|
15784
16280
|
get children() {
|
|
15785
|
-
var _el$
|
|
15786
|
-
insertNode(_el$
|
|
15787
|
-
setProp(_el$
|
|
15788
|
-
setProp(_el$
|
|
15789
|
-
insert(_el$
|
|
16281
|
+
var _el$21 = createElement("box"), _el$22 = createElement("text");
|
|
16282
|
+
insertNode(_el$21, _el$22);
|
|
16283
|
+
setProp(_el$21, "paddingTop", 1);
|
|
16284
|
+
setProp(_el$21, "paddingLeft", 1);
|
|
16285
|
+
insert(_el$22, (() => {
|
|
15790
16286
|
var _c$ = memo2(() => !!(searchMode() && searchQuery().trim().length > 0));
|
|
15791
16287
|
return () => _c$() ? "No matching tasks \u2014 esc to clear." : view() === "active" ? "No active tasks." : "No archived tasks.";
|
|
15792
16288
|
})());
|
|
15793
|
-
effect((_$p) => setProp(_el$
|
|
15794
|
-
return _el$
|
|
16289
|
+
effect((_$p) => setProp(_el$22, "fg", theme.textMuted, _$p));
|
|
16290
|
+
return _el$21;
|
|
15795
16291
|
}
|
|
15796
16292
|
}), null);
|
|
15797
|
-
insertNode(_el$
|
|
15798
|
-
setProp(_el$
|
|
15799
|
-
setProp(_el$
|
|
15800
|
-
setProp(_el$
|
|
15801
|
-
insertNode(_el$
|
|
15802
|
-
setProp(_el$
|
|
15803
|
-
setProp(_el$
|
|
15804
|
-
insert(_el
|
|
16293
|
+
insertNode(_el$23, _el$24);
|
|
16294
|
+
setProp(_el$23, "flexShrink", 0);
|
|
16295
|
+
setProp(_el$23, "paddingTop", 1);
|
|
16296
|
+
setProp(_el$23, "paddingLeft", 1);
|
|
16297
|
+
insertNode(_el$24, createTextNode(`+ New task`));
|
|
16298
|
+
setProp(_el$24, "wrapMode", "none");
|
|
16299
|
+
setProp(_el$24, "onMouseUp", () => props.onAddTask?.());
|
|
16300
|
+
insert(_el$4, createComponent2(Show, {
|
|
15805
16301
|
get when() {
|
|
15806
16302
|
return hover();
|
|
15807
16303
|
},
|
|
@@ -15831,43 +16327,43 @@ function Sidebar(props) {
|
|
|
15831
16327
|
const left = createMemo(() => Math.max(0, Math.min(h().x + 2, dims().width - boxW() - 1)));
|
|
15832
16328
|
const top = createMemo(() => Math.max(0, Math.min(h().y + 1, dims().height - boxH() - 1)));
|
|
15833
16329
|
return (() => {
|
|
15834
|
-
var _el$
|
|
15835
|
-
setProp(_el$
|
|
15836
|
-
setProp(_el$
|
|
15837
|
-
setProp(_el$
|
|
15838
|
-
setProp(_el$
|
|
15839
|
-
setProp(_el$
|
|
15840
|
-
setProp(_el$
|
|
15841
|
-
insert(_el$
|
|
16330
|
+
var _el$55 = createElement("box");
|
|
16331
|
+
setProp(_el$55, "position", "absolute");
|
|
16332
|
+
setProp(_el$55, "zIndex", 2600);
|
|
16333
|
+
setProp(_el$55, "flexDirection", "column");
|
|
16334
|
+
setProp(_el$55, "border", true);
|
|
16335
|
+
setProp(_el$55, "paddingLeft", 1);
|
|
16336
|
+
setProp(_el$55, "paddingRight", 1);
|
|
16337
|
+
insert(_el$55, createComponent2(For, {
|
|
15842
16338
|
get each() {
|
|
15843
16339
|
return lines();
|
|
15844
16340
|
},
|
|
15845
16341
|
children: (l) => (() => {
|
|
15846
|
-
var _el$
|
|
15847
|
-
setProp(_el$
|
|
15848
|
-
insert(_el$
|
|
15849
|
-
var _c$
|
|
15850
|
-
return () => _c$
|
|
16342
|
+
var _el$56 = createElement("text");
|
|
16343
|
+
setProp(_el$56, "wrapMode", "none");
|
|
16344
|
+
insert(_el$56, (() => {
|
|
16345
|
+
var _c$4 = memo2(() => !!l.dim);
|
|
16346
|
+
return () => _c$4() ? truncatePathTail(l.text, innerW()) : truncateTitle(l.text, innerW());
|
|
15851
16347
|
})());
|
|
15852
16348
|
effect((_p$) => {
|
|
15853
|
-
var _v$
|
|
15854
|
-
_v$
|
|
15855
|
-
_v$
|
|
16349
|
+
var _v$35 = l.dim ? theme.textMuted : theme.text, _v$36 = l.bold ? TextAttributes8.BOLD : l.dim ? TextAttributes8.DIM : undefined;
|
|
16350
|
+
_v$35 !== _p$.e && (_p$.e = setProp(_el$56, "fg", _v$35, _p$.e));
|
|
16351
|
+
_v$36 !== _p$.t && (_p$.t = setProp(_el$56, "attributes", _v$36, _p$.t));
|
|
15856
16352
|
return _p$;
|
|
15857
16353
|
}, {
|
|
15858
16354
|
e: undefined,
|
|
15859
16355
|
t: undefined
|
|
15860
16356
|
});
|
|
15861
|
-
return _el$
|
|
16357
|
+
return _el$56;
|
|
15862
16358
|
})()
|
|
15863
16359
|
}));
|
|
15864
16360
|
effect((_p$) => {
|
|
15865
|
-
var _v$
|
|
15866
|
-
_v$
|
|
15867
|
-
_v$
|
|
15868
|
-
_v$
|
|
15869
|
-
_v$
|
|
15870
|
-
_v$
|
|
16361
|
+
var _v$30 = left(), _v$31 = top(), _v$32 = boxW(), _v$33 = theme.focusAccent, _v$34 = theme.backgroundElement;
|
|
16362
|
+
_v$30 !== _p$.e && (_p$.e = setProp(_el$55, "left", _v$30, _p$.e));
|
|
16363
|
+
_v$31 !== _p$.t && (_p$.t = setProp(_el$55, "top", _v$31, _p$.t));
|
|
16364
|
+
_v$32 !== _p$.a && (_p$.a = setProp(_el$55, "width", _v$32, _p$.a));
|
|
16365
|
+
_v$33 !== _p$.o && (_p$.o = setProp(_el$55, "borderColor", _v$33, _p$.o));
|
|
16366
|
+
_v$34 !== _p$.i && (_p$.i = setProp(_el$55, "backgroundColor", _v$34, _p$.i));
|
|
15871
16367
|
return _p$;
|
|
15872
16368
|
}, {
|
|
15873
16369
|
e: undefined,
|
|
@@ -15876,31 +16372,27 @@ function Sidebar(props) {
|
|
|
15876
16372
|
o: undefined,
|
|
15877
16373
|
i: undefined
|
|
15878
16374
|
});
|
|
15879
|
-
return _el$
|
|
16375
|
+
return _el$55;
|
|
15880
16376
|
})();
|
|
15881
16377
|
}
|
|
15882
16378
|
}), null);
|
|
15883
16379
|
effect((_p$) => {
|
|
15884
|
-
var _v$
|
|
15885
|
-
_v$
|
|
15886
|
-
_v$
|
|
15887
|
-
_v$
|
|
15888
|
-
_v$
|
|
15889
|
-
_v$9 !== _p$.i && (_p$.i = setProp(_el$5, "attributes", _v$9, _p$.i));
|
|
15890
|
-
_v$0 !== _p$.n && (_p$.n = setProp(_el$23, "fg", _v$0, _p$.n));
|
|
16380
|
+
var _v$9 = props.width ? props.width() : SIDEBAR_WIDTH, _v$0 = focusedAccessor() ? theme.focusAccent : theme.textMuted, _v$1 = TextAttributes8.BOLD, _v$10 = theme.textMuted;
|
|
16381
|
+
_v$9 !== _p$.e && (_p$.e = setProp(_el$4, "width", _v$9, _p$.e));
|
|
16382
|
+
_v$0 !== _p$.t && (_p$.t = setProp(_el$6, "fg", _v$0, _p$.t));
|
|
16383
|
+
_v$1 !== _p$.a && (_p$.a = setProp(_el$6, "attributes", _v$1, _p$.a));
|
|
16384
|
+
_v$10 !== _p$.o && (_p$.o = setProp(_el$24, "fg", _v$10, _p$.o));
|
|
15891
16385
|
return _p$;
|
|
15892
16386
|
}, {
|
|
15893
16387
|
e: undefined,
|
|
15894
16388
|
t: undefined,
|
|
15895
16389
|
a: undefined,
|
|
15896
|
-
o: undefined
|
|
15897
|
-
i: undefined,
|
|
15898
|
-
n: undefined
|
|
16390
|
+
o: undefined
|
|
15899
16391
|
});
|
|
15900
|
-
return _el
|
|
16392
|
+
return _el$4;
|
|
15901
16393
|
})();
|
|
15902
16394
|
}
|
|
15903
|
-
var SIDEBAR_WIDTH = 32, STATUS_BADGE, IN_PROGRESS_SPINNER, SPINNER_FRAME_MS = 100, VIEW_TABS, MAIN_BRANCH_POLL_MS = 2000,
|
|
16395
|
+
var SIDEBAR_WIDTH = 32, STATUS_BADGE, STATUS_LABEL, IN_PROGRESS_SPINNER, SPINNER_FRAME_MS = 100, VIEW_TABS, MAIN_BRANCH_POLL_MS = 2000, BRANCH_LABEL_MAX = 16;
|
|
15904
16396
|
var init_Sidebar = __esm(() => {
|
|
15905
16397
|
init_solid();
|
|
15906
16398
|
init_solid();
|
|
@@ -15914,7 +16406,6 @@ var init_Sidebar = __esm(() => {
|
|
|
15914
16406
|
init_dev();
|
|
15915
16407
|
init_theme2();
|
|
15916
16408
|
init_theme2();
|
|
15917
|
-
init_git_head();
|
|
15918
16409
|
init_groups();
|
|
15919
16410
|
init_keys();
|
|
15920
16411
|
init_worktree_changes();
|
|
@@ -15944,6 +16435,14 @@ var init_Sidebar = __esm(() => {
|
|
|
15944
16435
|
tone: "error"
|
|
15945
16436
|
}
|
|
15946
16437
|
};
|
|
16438
|
+
STATUS_LABEL = {
|
|
16439
|
+
done: "done",
|
|
16440
|
+
in_review: "in review",
|
|
16441
|
+
in_progress: "working",
|
|
16442
|
+
backlog: "backlog",
|
|
16443
|
+
canceled: "canceled",
|
|
16444
|
+
error: "error"
|
|
16445
|
+
};
|
|
15947
16446
|
IN_PROGRESS_SPINNER = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
15948
16447
|
VIEW_TABS = [{
|
|
15949
16448
|
view: "active",
|
|
@@ -16049,7 +16548,18 @@ function TasksShell(props) {
|
|
|
16049
16548
|
return;
|
|
16050
16549
|
}
|
|
16051
16550
|
}
|
|
16052
|
-
SettingsDialog.show(dialog, kv, props.orch ?? undefined);
|
|
16551
|
+
const result = await SettingsDialog.show(dialog, kv, props.orch ?? undefined);
|
|
16552
|
+
if (!result.visualPrefsChanged)
|
|
16553
|
+
return;
|
|
16554
|
+
if (!kv.flush())
|
|
16555
|
+
return;
|
|
16556
|
+
try {
|
|
16557
|
+
const session = await currentSessionName();
|
|
16558
|
+
if (session)
|
|
16559
|
+
await refreshKobeWorkspacePanes(session);
|
|
16560
|
+
} catch (err) {
|
|
16561
|
+
console.error("[kobe tasks] failed to refresh workspace panes:", err);
|
|
16562
|
+
}
|
|
16053
16563
|
}
|
|
16054
16564
|
async function openUpdate() {
|
|
16055
16565
|
const info = updateInfo();
|
|
@@ -16284,6 +16794,18 @@ function TasksShell(props) {
|
|
|
16284
16794
|
await runTmux(["switch-client", "-t", `=${name}`]);
|
|
16285
16795
|
props.orch?.setActiveTask(id).catch(() => {});
|
|
16286
16796
|
}
|
|
16797
|
+
const headerStatus = createMemo(() => {
|
|
16798
|
+
const info = updateInfo();
|
|
16799
|
+
if (info?.hasUpdate)
|
|
16800
|
+
return {
|
|
16801
|
+
label: `v${info.latest} \u2191`,
|
|
16802
|
+
emphasize: true
|
|
16803
|
+
};
|
|
16804
|
+
return {
|
|
16805
|
+
label: `v${CURRENT_VERSION}`,
|
|
16806
|
+
emphasize: false
|
|
16807
|
+
};
|
|
16808
|
+
});
|
|
16287
16809
|
return (() => {
|
|
16288
16810
|
var _el$ = createElement("box"), _el$2 = createElement("box");
|
|
16289
16811
|
insertNode(_el$, _el$2);
|
|
@@ -16299,6 +16821,8 @@ function TasksShell(props) {
|
|
|
16299
16821
|
onSelect: setSelectedId,
|
|
16300
16822
|
onActivate: (id) => void switchTo(id),
|
|
16301
16823
|
activateOnClick: true,
|
|
16824
|
+
headerStatus,
|
|
16825
|
+
onHeaderStatusClick: () => void openUpdate(),
|
|
16302
16826
|
width: () => dimensions().width,
|
|
16303
16827
|
onAddTask: () => void createTask(),
|
|
16304
16828
|
onRenameRequest: (id) => void renameTask(id),
|
|
@@ -16306,24 +16830,15 @@ function TasksShell(props) {
|
|
|
16306
16830
|
onArchiveRequest: (id) => void archiveTask(id),
|
|
16307
16831
|
focused: () => dialog.stack.length === 0
|
|
16308
16832
|
}));
|
|
16309
|
-
insert(_el$, createComponent2(ShortcutHints, {
|
|
16310
|
-
updateInfo,
|
|
16311
|
-
onOpenUpdate: () => void openUpdate()
|
|
16312
|
-
}), null);
|
|
16833
|
+
insert(_el$, createComponent2(ShortcutHints, {}), null);
|
|
16313
16834
|
effect((_$p) => setProp(_el$, "backgroundColor", theme.background, _$p));
|
|
16314
16835
|
return _el$;
|
|
16315
16836
|
})();
|
|
16316
16837
|
}
|
|
16317
|
-
function ShortcutHints(
|
|
16838
|
+
function ShortcutHints() {
|
|
16318
16839
|
const {
|
|
16319
16840
|
theme
|
|
16320
16841
|
} = useTheme();
|
|
16321
|
-
const updateLabel = createMemo(() => {
|
|
16322
|
-
const info = props.updateInfo();
|
|
16323
|
-
if (!info)
|
|
16324
|
-
return `v${CURRENT_VERSION}`;
|
|
16325
|
-
return info.hasUpdate ? `v${info.latest} available` : `v${CURRENT_VERSION} latest`;
|
|
16326
|
-
});
|
|
16327
16842
|
const HINTS = [{
|
|
16328
16843
|
k: "\u23CE",
|
|
16329
16844
|
label: "open"
|
|
@@ -16373,111 +16888,63 @@ function ShortcutHints(props) {
|
|
|
16373
16888
|
k: "\u2303Q",
|
|
16374
16889
|
label: "detach"
|
|
16375
16890
|
}];
|
|
16891
|
+
const LABEL_COL_MAX = 18;
|
|
16892
|
+
const labelColWidth = Math.min(LABEL_COL_MAX, Math.max(...HINTS.map((h) => h.label.length)));
|
|
16893
|
+
const clipLabel = (s) => s.length <= labelColWidth ? s : `${s.slice(0, Math.max(0, labelColWidth - 1))}\u2026`;
|
|
16376
16894
|
return (() => {
|
|
16377
|
-
var _el$3 = createElement("box"), _el$4 = createElement("text")
|
|
16895
|
+
var _el$3 = createElement("box"), _el$4 = createElement("text");
|
|
16378
16896
|
insertNode(_el$3, _el$4);
|
|
16379
|
-
insertNode(_el$3, _el$6);
|
|
16380
|
-
insertNode(_el$3, _el$12);
|
|
16381
16897
|
setProp(_el$3, "flexShrink", 0);
|
|
16382
16898
|
setProp(_el$3, "flexDirection", "column");
|
|
16383
16899
|
setProp(_el$3, "paddingLeft", 1);
|
|
16384
16900
|
setProp(_el$3, "paddingRight", 1);
|
|
16385
16901
|
setProp(_el$3, "paddingTop", 1);
|
|
16386
16902
|
setProp(_el$3, "gap", 0);
|
|
16387
|
-
insertNode(_el$4, createTextNode(`\u2500\u2500
|
|
16903
|
+
insertNode(_el$4, createTextNode(`\u2500\u2500 keys \u2500\u2500`));
|
|
16388
16904
|
setProp(_el$4, "wrapMode", "none");
|
|
16389
|
-
insertNode(_el$6, _el$7);
|
|
16390
|
-
setProp(_el$6, "flexDirection", "row");
|
|
16391
|
-
setProp(_el$6, "gap", 1);
|
|
16392
|
-
setProp(_el$7, "wrapMode", "none");
|
|
16393
|
-
setProp(_el$7, "onMouseUp", () => {
|
|
16394
|
-
if (props.updateInfo()?.hasUpdate)
|
|
16395
|
-
props.onOpenUpdate();
|
|
16396
|
-
});
|
|
16397
|
-
insert(_el$7, updateLabel);
|
|
16398
|
-
insert(_el$3, createComponent2(Show, {
|
|
16399
|
-
get when() {
|
|
16400
|
-
return props.updateInfo()?.hasUpdate;
|
|
16401
|
-
},
|
|
16402
|
-
get children() {
|
|
16403
|
-
var _el$8 = createElement("box"), _el$9 = createElement("box"), _el$0 = createElement("text"), _el$10 = createElement("text");
|
|
16404
|
-
insertNode(_el$8, _el$9);
|
|
16405
|
-
insertNode(_el$8, _el$10);
|
|
16406
|
-
setProp(_el$8, "flexDirection", "row");
|
|
16407
|
-
setProp(_el$8, "gap", 1);
|
|
16408
|
-
setProp(_el$8, "onMouseUp", () => props.onOpenUpdate());
|
|
16409
|
-
insertNode(_el$9, _el$0);
|
|
16410
|
-
setProp(_el$9, "width", 10);
|
|
16411
|
-
setProp(_el$9, "flexShrink", 0);
|
|
16412
|
-
insertNode(_el$0, createTextNode(`[U]`));
|
|
16413
|
-
setProp(_el$0, "wrapMode", "none");
|
|
16414
|
-
insertNode(_el$10, createTextNode(`update page`));
|
|
16415
|
-
setProp(_el$10, "wrapMode", "none");
|
|
16416
|
-
effect((_p$) => {
|
|
16417
|
-
var _v$ = theme.accent, _v$2 = TextAttributes9.BOLD, _v$3 = theme.accent, _v$4 = TextAttributes9.DIM;
|
|
16418
|
-
_v$ !== _p$.e && (_p$.e = setProp(_el$0, "fg", _v$, _p$.e));
|
|
16419
|
-
_v$2 !== _p$.t && (_p$.t = setProp(_el$0, "attributes", _v$2, _p$.t));
|
|
16420
|
-
_v$3 !== _p$.a && (_p$.a = setProp(_el$10, "fg", _v$3, _p$.a));
|
|
16421
|
-
_v$4 !== _p$.o && (_p$.o = setProp(_el$10, "attributes", _v$4, _p$.o));
|
|
16422
|
-
return _p$;
|
|
16423
|
-
}, {
|
|
16424
|
-
e: undefined,
|
|
16425
|
-
t: undefined,
|
|
16426
|
-
a: undefined,
|
|
16427
|
-
o: undefined
|
|
16428
|
-
});
|
|
16429
|
-
return _el$8;
|
|
16430
|
-
}
|
|
16431
|
-
}), _el$12);
|
|
16432
|
-
insertNode(_el$12, createTextNode(`\u2500\u2500 keys \u2500\u2500`));
|
|
16433
|
-
setProp(_el$12, "wrapMode", "none");
|
|
16434
16905
|
insert(_el$3, createComponent2(For, {
|
|
16435
16906
|
each: HINTS,
|
|
16436
16907
|
children: (h) => (() => {
|
|
16437
|
-
var _el$
|
|
16438
|
-
insertNode(_el$
|
|
16439
|
-
insertNode(_el$
|
|
16440
|
-
setProp(_el$
|
|
16441
|
-
setProp(_el$
|
|
16442
|
-
|
|
16443
|
-
|
|
16444
|
-
setProp(_el$
|
|
16445
|
-
|
|
16446
|
-
insertNode(_el$
|
|
16447
|
-
|
|
16448
|
-
|
|
16449
|
-
|
|
16450
|
-
|
|
16908
|
+
var _el$6 = createElement("box"), _el$7 = createElement("box"), _el$8 = createElement("text"), _el$9 = createTextNode(`[`), _el$0 = createTextNode(`]`), _el$1 = createElement("box"), _el$10 = createElement("text");
|
|
16909
|
+
insertNode(_el$6, _el$7);
|
|
16910
|
+
insertNode(_el$6, _el$1);
|
|
16911
|
+
setProp(_el$6, "flexDirection", "row");
|
|
16912
|
+
setProp(_el$6, "gap", 1);
|
|
16913
|
+
setProp(_el$6, "justifyContent", "space-between");
|
|
16914
|
+
insertNode(_el$7, _el$8);
|
|
16915
|
+
setProp(_el$7, "width", 10);
|
|
16916
|
+
setProp(_el$7, "flexShrink", 0);
|
|
16917
|
+
insertNode(_el$8, _el$9);
|
|
16918
|
+
insertNode(_el$8, _el$0);
|
|
16919
|
+
setProp(_el$8, "wrapMode", "none");
|
|
16920
|
+
insert(_el$8, () => h.k, _el$0);
|
|
16921
|
+
insertNode(_el$1, _el$10);
|
|
16922
|
+
setProp(_el$1, "width", labelColWidth);
|
|
16923
|
+
setProp(_el$1, "flexShrink", 0);
|
|
16924
|
+
setProp(_el$10, "wrapMode", "none");
|
|
16925
|
+
insert(_el$10, () => clipLabel(h.label));
|
|
16451
16926
|
effect((_p$) => {
|
|
16452
|
-
var _v$
|
|
16453
|
-
_v$
|
|
16454
|
-
_v$
|
|
16455
|
-
_v$
|
|
16927
|
+
var _v$3 = theme.accent, _v$4 = TextAttributes9.BOLD, _v$5 = theme.textMuted;
|
|
16928
|
+
_v$3 !== _p$.e && (_p$.e = setProp(_el$8, "fg", _v$3, _p$.e));
|
|
16929
|
+
_v$4 !== _p$.t && (_p$.t = setProp(_el$8, "attributes", _v$4, _p$.t));
|
|
16930
|
+
_v$5 !== _p$.a && (_p$.a = setProp(_el$10, "fg", _v$5, _p$.a));
|
|
16456
16931
|
return _p$;
|
|
16457
16932
|
}, {
|
|
16458
16933
|
e: undefined,
|
|
16459
16934
|
t: undefined,
|
|
16460
16935
|
a: undefined
|
|
16461
16936
|
});
|
|
16462
|
-
return _el$
|
|
16937
|
+
return _el$6;
|
|
16463
16938
|
})()
|
|
16464
16939
|
}), null);
|
|
16465
16940
|
effect((_p$) => {
|
|
16466
|
-
var _v$
|
|
16467
|
-
_v$
|
|
16468
|
-
_v$
|
|
16469
|
-
_v$7 !== _p$.a && (_p$.a = setProp(_el$7, "fg", _v$7, _p$.a));
|
|
16470
|
-
_v$8 !== _p$.o && (_p$.o = setProp(_el$7, "attributes", _v$8, _p$.o));
|
|
16471
|
-
_v$9 !== _p$.i && (_p$.i = setProp(_el$12, "fg", _v$9, _p$.i));
|
|
16472
|
-
_v$0 !== _p$.n && (_p$.n = setProp(_el$12, "attributes", _v$0, _p$.n));
|
|
16941
|
+
var _v$ = theme.textMuted, _v$2 = TextAttributes9.DIM;
|
|
16942
|
+
_v$ !== _p$.e && (_p$.e = setProp(_el$4, "fg", _v$, _p$.e));
|
|
16943
|
+
_v$2 !== _p$.t && (_p$.t = setProp(_el$4, "attributes", _v$2, _p$.t));
|
|
16473
16944
|
return _p$;
|
|
16474
16945
|
}, {
|
|
16475
16946
|
e: undefined,
|
|
16476
|
-
t: undefined
|
|
16477
|
-
a: undefined,
|
|
16478
|
-
o: undefined,
|
|
16479
|
-
i: undefined,
|
|
16480
|
-
n: undefined
|
|
16947
|
+
t: undefined
|
|
16481
16948
|
});
|
|
16482
16949
|
return _el$3;
|
|
16483
16950
|
})();
|
|
@@ -16606,13 +17073,29 @@ function SettingsPage(props) {
|
|
|
16606
17073
|
const {
|
|
16607
17074
|
theme
|
|
16608
17075
|
} = themeCtx;
|
|
17076
|
+
let visualPrefsChanged = false;
|
|
17077
|
+
let exiting = false;
|
|
16609
17078
|
onMount(() => {
|
|
16610
17079
|
themeCtx.setTransparentBackground(props.transparent);
|
|
16611
17080
|
if (props.focusAccent)
|
|
16612
17081
|
themeCtx.setFocusAccent(props.focusAccent);
|
|
16613
17082
|
});
|
|
16614
|
-
function exit() {
|
|
16615
|
-
|
|
17083
|
+
async function exit() {
|
|
17084
|
+
if (exiting)
|
|
17085
|
+
return;
|
|
17086
|
+
exiting = true;
|
|
17087
|
+
try {
|
|
17088
|
+
const flushed = kv.flush();
|
|
17089
|
+
if (flushed && visualPrefsChanged) {
|
|
17090
|
+
const session = await currentSessionName();
|
|
17091
|
+
if (session)
|
|
17092
|
+
await refreshKobeWorkspacePanes(session);
|
|
17093
|
+
}
|
|
17094
|
+
} catch (err) {
|
|
17095
|
+
console.error("[kobe settings] failed to refresh workspace panes:", err);
|
|
17096
|
+
} finally {
|
|
17097
|
+
process.exit(0);
|
|
17098
|
+
}
|
|
16616
17099
|
}
|
|
16617
17100
|
useBindings(() => ({
|
|
16618
17101
|
enabled: dialog.stack.length === 0,
|
|
@@ -16628,15 +17111,23 @@ function SettingsPage(props) {
|
|
|
16628
17111
|
}]
|
|
16629
17112
|
}));
|
|
16630
17113
|
return (() => {
|
|
16631
|
-
var _el$ = createElement("
|
|
16632
|
-
setProp(_el$, "flexDirection", "column");
|
|
17114
|
+
var _el$ = createElement("scrollbox");
|
|
16633
17115
|
setProp(_el$, "flexGrow", 1);
|
|
16634
17116
|
setProp(_el$, "paddingTop", 1);
|
|
17117
|
+
setProp(_el$, "verticalScrollbarOptions", {
|
|
17118
|
+
trackOptions: {
|
|
17119
|
+
foregroundColor: "transparent"
|
|
17120
|
+
}
|
|
17121
|
+
});
|
|
16635
17122
|
insert(_el$, createComponent2(SettingsDialog, {
|
|
16636
17123
|
kv,
|
|
16637
17124
|
get orchestrator() {
|
|
16638
17125
|
return props.orchestrator ?? undefined;
|
|
16639
17126
|
},
|
|
17127
|
+
standalone: true,
|
|
17128
|
+
onVisualPrefsChange: () => {
|
|
17129
|
+
visualPrefsChanged = true;
|
|
17130
|
+
},
|
|
16640
17131
|
onClose: exit
|
|
16641
17132
|
}));
|
|
16642
17133
|
effect((_$p) => setProp(_el$, "backgroundColor", theme.background, _$p));
|
|
@@ -16719,6 +17210,7 @@ var init_host2 = __esm(() => {
|
|
|
16719
17210
|
init_loader();
|
|
16720
17211
|
init_keymap();
|
|
16721
17212
|
init_persisted_ui_prefs();
|
|
17213
|
+
init_tmux();
|
|
16722
17214
|
init_dialog();
|
|
16723
17215
|
});
|
|
16724
17216
|
|
|
@@ -16863,7 +17355,7 @@ var exports_host4 = {};
|
|
|
16863
17355
|
__export(exports_host4, {
|
|
16864
17356
|
startUpdateHost: () => startUpdateHost
|
|
16865
17357
|
});
|
|
16866
|
-
import { spawn as spawn4, spawnSync as
|
|
17358
|
+
import { spawn as spawn4, spawnSync as spawnSync8 } from "child_process";
|
|
16867
17359
|
import { TextAttributes as TextAttributes10 } from "@opentui/core";
|
|
16868
17360
|
function openExternalUrl(url) {
|
|
16869
17361
|
if (!url)
|
|
@@ -16969,7 +17461,7 @@ kobe ${CURRENT_VERSION} -> latest
|
|
|
16969
17461
|
process.stdout.write(`running: ${UPDATE_COMMAND}
|
|
16970
17462
|
|
|
16971
17463
|
`);
|
|
16972
|
-
const result =
|
|
17464
|
+
const result = spawnSync8("sh", ["-c", UPDATE_COMMAND], {
|
|
16973
17465
|
stdio: "inherit"
|
|
16974
17466
|
});
|
|
16975
17467
|
const code = result.status ?? (result.error ? 1 : 0);
|
|
@@ -17416,6 +17908,63 @@ var init_activity = __esm(() => {
|
|
|
17416
17908
|
init_history3();
|
|
17417
17909
|
});
|
|
17418
17910
|
|
|
17911
|
+
// src/tmux/editor-launch.ts
|
|
17912
|
+
function firstToken(cmd) {
|
|
17913
|
+
return cmd.trim().split(/\s+/)[0] ?? "";
|
|
17914
|
+
}
|
|
17915
|
+
function buildEditorCommand(kind, customCommand, absPath, envEditor) {
|
|
17916
|
+
const file = shellQuote(absPath);
|
|
17917
|
+
if (kind === "vim")
|
|
17918
|
+
return { bin: "vim", command: `vim ${file}` };
|
|
17919
|
+
if (kind === "nano")
|
|
17920
|
+
return { bin: "nano", command: `nano ${file}` };
|
|
17921
|
+
const tmpl = (customCommand.trim() || (envEditor ?? "").trim()).trim();
|
|
17922
|
+
if (!tmpl)
|
|
17923
|
+
return null;
|
|
17924
|
+
const bin = firstToken(tmpl);
|
|
17925
|
+
if (!bin)
|
|
17926
|
+
return null;
|
|
17927
|
+
const command = tmpl.includes(FILE_PLACEHOLDER) ? tmpl.split(FILE_PLACEHOLDER).join(file) : `${tmpl} ${file}`;
|
|
17928
|
+
return { bin, command };
|
|
17929
|
+
}
|
|
17930
|
+
function resolveEditorCommand(absPath) {
|
|
17931
|
+
const kind = normalizeEditorKind(getPersistedString(EDITOR_KIND_KEY));
|
|
17932
|
+
const custom = getPersistedString(EDITOR_CUSTOM_KEY) ?? "";
|
|
17933
|
+
const env = process.env.VISUAL ?? process.env.EDITOR ?? "";
|
|
17934
|
+
return buildEditorCommand(kind, custom, absPath, env);
|
|
17935
|
+
}
|
|
17936
|
+
async function binaryAvailable(bin) {
|
|
17937
|
+
try {
|
|
17938
|
+
const proc = Bun.spawn(["sh", "-c", `command -v ${shellQuote(bin)} >/dev/null 2>&1`], {
|
|
17939
|
+
stdin: "ignore",
|
|
17940
|
+
stdout: "ignore",
|
|
17941
|
+
stderr: "ignore"
|
|
17942
|
+
});
|
|
17943
|
+
return await proc.exited === 0;
|
|
17944
|
+
} catch {
|
|
17945
|
+
return false;
|
|
17946
|
+
}
|
|
17947
|
+
}
|
|
17948
|
+
async function openInEditor(session, worktree, absPath) {
|
|
17949
|
+
const resolved = resolveEditorCommand(absPath);
|
|
17950
|
+
if (!resolved)
|
|
17951
|
+
return false;
|
|
17952
|
+
if (!await binaryAvailable(resolved.bin))
|
|
17953
|
+
return false;
|
|
17954
|
+
await newWindow(session, { cwd: worktree, command: resolved.command, name: editorWindowLabel(absPath) });
|
|
17955
|
+
return true;
|
|
17956
|
+
}
|
|
17957
|
+
function editorWindowLabel(absPath) {
|
|
17958
|
+
const base = absPath.slice(absPath.lastIndexOf("/") + 1).trim();
|
|
17959
|
+
return base.length > 0 ? base : "edit";
|
|
17960
|
+
}
|
|
17961
|
+
var FILE_PLACEHOLDER = "{file}";
|
|
17962
|
+
var init_editor_launch = __esm(() => {
|
|
17963
|
+
init_repos();
|
|
17964
|
+
init_editor_prefs();
|
|
17965
|
+
init_client2();
|
|
17966
|
+
});
|
|
17967
|
+
|
|
17419
17968
|
// src/tui/panes/filetree/git.ts
|
|
17420
17969
|
import { spawn as nodeSpawn } from "child_process";
|
|
17421
17970
|
async function runGit(args, cwd) {
|
|
@@ -17570,7 +18119,8 @@ var init_git2 = __esm(() => {
|
|
|
17570
18119
|
const child = nodeSpawn("git", [...args], {
|
|
17571
18120
|
cwd,
|
|
17572
18121
|
shell: false,
|
|
17573
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
18122
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
18123
|
+
env: { ...process.env, GIT_OPTIONAL_LOCKS: "0" }
|
|
17574
18124
|
});
|
|
17575
18125
|
let stdout = "";
|
|
17576
18126
|
let stderr = "";
|
|
@@ -17621,6 +18171,7 @@ function useFileTreeBindings(opts) {
|
|
|
17621
18171
|
opts.setTab(next);
|
|
17622
18172
|
},
|
|
17623
18173
|
"files.open": () => opts.openCurrent(),
|
|
18174
|
+
"files.edit": () => opts.editCurrent?.(),
|
|
17624
18175
|
"files.mention": () => opts.mentionCurrent?.(),
|
|
17625
18176
|
"files.createPR": () => opts.createPR?.(),
|
|
17626
18177
|
"files.openExternal": () => opts.openExternal(),
|
|
@@ -17715,10 +18266,16 @@ function summarizeGitError(raw) {
|
|
|
17715
18266
|
return raw.slice(colon + 2).trim() || "git command failed";
|
|
17716
18267
|
return raw.trim() || "git command failed";
|
|
17717
18268
|
}
|
|
18269
|
+
function truncatePathTail2(path11, max) {
|
|
18270
|
+
if (max <= 0 || path11.length <= max)
|
|
18271
|
+
return path11;
|
|
18272
|
+
return `\u2026${path11.slice(path11.length - Math.max(0, max - 1))}`;
|
|
18273
|
+
}
|
|
17718
18274
|
function FileTree(props) {
|
|
17719
18275
|
const {
|
|
17720
18276
|
theme
|
|
17721
18277
|
} = useTheme();
|
|
18278
|
+
const dims = useTerminalDimensions();
|
|
17722
18279
|
const focusedAccessor = () => props.focused ? props.focused() : true;
|
|
17723
18280
|
const [tab, setTab] = createSignal("all");
|
|
17724
18281
|
const [cursorIndex, setCursorIndex] = createSignal(0);
|
|
@@ -17883,6 +18440,11 @@ function FileTree(props) {
|
|
|
17883
18440
|
deleted
|
|
17884
18441
|
};
|
|
17885
18442
|
});
|
|
18443
|
+
const pathBudget = createMemo(() => {
|
|
18444
|
+
const w = statWidths();
|
|
18445
|
+
const stats = (w.added > 0 ? w.added + 1 : 0) + (w.deleted > 0 ? w.deleted + 1 : 0);
|
|
18446
|
+
return Math.max(8, dims().width - 6 - stats);
|
|
18447
|
+
});
|
|
17886
18448
|
function moveDown() {
|
|
17887
18449
|
const r = rows();
|
|
17888
18450
|
if (r.length === 0)
|
|
@@ -17975,6 +18537,16 @@ function FileTree(props) {
|
|
|
17975
18537
|
return;
|
|
17976
18538
|
props.onMention?.(row.path);
|
|
17977
18539
|
}
|
|
18540
|
+
function editCurrent() {
|
|
18541
|
+
const r = rows();
|
|
18542
|
+
const i = cursorIndex();
|
|
18543
|
+
if (i < 0 || i >= r.length)
|
|
18544
|
+
return;
|
|
18545
|
+
const row = r[i];
|
|
18546
|
+
if (!row || row.kind === "dir")
|
|
18547
|
+
return;
|
|
18548
|
+
props.onEditFile?.(row.path);
|
|
18549
|
+
}
|
|
17978
18550
|
function refresh() {
|
|
17979
18551
|
setRefreshTick((n) => n + 1);
|
|
17980
18552
|
props.onRefresh?.();
|
|
@@ -18001,6 +18573,7 @@ function FileTree(props) {
|
|
|
18001
18573
|
currentTab: tab,
|
|
18002
18574
|
openCurrent,
|
|
18003
18575
|
mentionCurrent,
|
|
18576
|
+
editCurrent,
|
|
18004
18577
|
createPR: props.onCreatePR,
|
|
18005
18578
|
openExternal,
|
|
18006
18579
|
refresh,
|
|
@@ -18037,8 +18610,8 @@ function FileTree(props) {
|
|
|
18037
18610
|
setProp(_el$, "flexGrow", 1);
|
|
18038
18611
|
setProp(_el$, "paddingTop", 1);
|
|
18039
18612
|
setProp(_el$, "paddingBottom", 1);
|
|
18040
|
-
setProp(_el$, "paddingLeft",
|
|
18041
|
-
setProp(_el$, "paddingRight",
|
|
18613
|
+
setProp(_el$, "paddingLeft", 0);
|
|
18614
|
+
setProp(_el$, "paddingRight", 0);
|
|
18042
18615
|
insert(_el$, createComponent2(Show, {
|
|
18043
18616
|
get when() {
|
|
18044
18617
|
return props.onCreatePR;
|
|
@@ -18085,20 +18658,20 @@ function FileTree(props) {
|
|
|
18085
18658
|
children: (t) => {
|
|
18086
18659
|
const isActive = () => tab() === t;
|
|
18087
18660
|
return (() => {
|
|
18088
|
-
var _el$
|
|
18089
|
-
setProp(_el$
|
|
18090
|
-
setProp(_el$
|
|
18091
|
-
insert(_el$
|
|
18661
|
+
var _el$26 = createElement("text");
|
|
18662
|
+
setProp(_el$26, "wrapMode", "none");
|
|
18663
|
+
setProp(_el$26, "onMouseUp", () => setTab(t));
|
|
18664
|
+
insert(_el$26, () => TAB_LABEL[t]);
|
|
18092
18665
|
effect((_p$) => {
|
|
18093
18666
|
var _v$6 = isActive() ? theme.primary : theme.textMuted, _v$7 = isActive() ? TextAttributes11.BOLD : undefined;
|
|
18094
|
-
_v$6 !== _p$.e && (_p$.e = setProp(_el$
|
|
18095
|
-
_v$7 !== _p$.t && (_p$.t = setProp(_el$
|
|
18667
|
+
_v$6 !== _p$.e && (_p$.e = setProp(_el$26, "fg", _v$6, _p$.e));
|
|
18668
|
+
_v$7 !== _p$.t && (_p$.t = setProp(_el$26, "attributes", _v$7, _p$.t));
|
|
18096
18669
|
return _p$;
|
|
18097
18670
|
}, {
|
|
18098
18671
|
e: undefined,
|
|
18099
18672
|
t: undefined
|
|
18100
18673
|
});
|
|
18101
|
-
return _el$
|
|
18674
|
+
return _el$26;
|
|
18102
18675
|
})();
|
|
18103
18676
|
}
|
|
18104
18677
|
}));
|
|
@@ -18107,19 +18680,19 @@ function FileTree(props) {
|
|
|
18107
18680
|
return props.cornerBadge?.();
|
|
18108
18681
|
},
|
|
18109
18682
|
children: (badge) => (() => {
|
|
18110
|
-
var _el$
|
|
18111
|
-
setProp(_el$
|
|
18112
|
-
insert(_el$
|
|
18683
|
+
var _el$27 = createElement("text");
|
|
18684
|
+
setProp(_el$27, "wrapMode", "none");
|
|
18685
|
+
insert(_el$27, () => badge().text);
|
|
18113
18686
|
effect((_p$) => {
|
|
18114
18687
|
var _v$8 = badge().active ? theme.accent : theme.textMuted, _v$9 = badge().active ? TextAttributes11.BOLD : undefined;
|
|
18115
|
-
_v$8 !== _p$.e && (_p$.e = setProp(_el$
|
|
18116
|
-
_v$9 !== _p$.t && (_p$.t = setProp(_el$
|
|
18688
|
+
_v$8 !== _p$.e && (_p$.e = setProp(_el$27, "fg", _v$8, _p$.e));
|
|
18689
|
+
_v$9 !== _p$.t && (_p$.t = setProp(_el$27, "attributes", _v$9, _p$.t));
|
|
18117
18690
|
return _p$;
|
|
18118
18691
|
}, {
|
|
18119
18692
|
e: undefined,
|
|
18120
18693
|
t: undefined
|
|
18121
18694
|
});
|
|
18122
|
-
return _el$
|
|
18695
|
+
return _el$27;
|
|
18123
18696
|
})()
|
|
18124
18697
|
}), null);
|
|
18125
18698
|
insert(_el$, createComponent2(Show, {
|
|
@@ -18231,15 +18804,23 @@ function FileTree(props) {
|
|
|
18231
18804
|
},
|
|
18232
18805
|
children: (row, index) => {
|
|
18233
18806
|
const isCursor = () => index() === cursorIndex();
|
|
18807
|
+
const bar = (() => {
|
|
18808
|
+
var _el$28 = createElement("text");
|
|
18809
|
+
setProp(_el$28, "wrapMode", "none");
|
|
18810
|
+
insert(_el$28, () => isCursor() ? "\u258C" : " ");
|
|
18811
|
+
effect((_$p) => setProp(_el$28, "fg", isCursor() ? theme.focusAccent : undefined, _$p));
|
|
18812
|
+
return _el$28;
|
|
18813
|
+
})();
|
|
18814
|
+
const rowBg = () => isCursor() ? theme.backgroundElement : undefined;
|
|
18234
18815
|
if (row.kind === "dir") {
|
|
18235
18816
|
const indent = " ".repeat(row.depth);
|
|
18236
18817
|
const marker = row.expanded ? "\u25BE" : "\u25B8";
|
|
18237
18818
|
return (() => {
|
|
18238
|
-
var _el$
|
|
18239
|
-
insertNode(_el$
|
|
18240
|
-
setProp(_el$
|
|
18241
|
-
setProp(_el$
|
|
18242
|
-
setProp(_el$
|
|
18819
|
+
var _el$29 = createElement("box"), _el$30 = createElement("box"), _el$31 = createElement("text");
|
|
18820
|
+
insertNode(_el$29, _el$30);
|
|
18821
|
+
setProp(_el$29, "flexDirection", "row");
|
|
18822
|
+
setProp(_el$29, "gap", 0);
|
|
18823
|
+
setProp(_el$29, "onMouseUp", () => {
|
|
18243
18824
|
setCursorIndex(index());
|
|
18244
18825
|
setExpandedDirs((prev) => {
|
|
18245
18826
|
const next = new Set(prev);
|
|
@@ -18250,45 +18831,53 @@ function FileTree(props) {
|
|
|
18250
18831
|
return next;
|
|
18251
18832
|
});
|
|
18252
18833
|
});
|
|
18253
|
-
|
|
18254
|
-
|
|
18834
|
+
insert(_el$29, bar, _el$30);
|
|
18835
|
+
insertNode(_el$30, _el$31);
|
|
18836
|
+
setProp(_el$30, "flexGrow", 1);
|
|
18837
|
+
setProp(_el$30, "paddingRight", 1);
|
|
18838
|
+
setProp(_el$31, "wrapMode", "none");
|
|
18839
|
+
insert(_el$31, () => `${indent}${marker} ${row.name}/`);
|
|
18255
18840
|
effect((_p$) => {
|
|
18256
|
-
var _v$0 =
|
|
18257
|
-
_v$0 !== _p$.e && (_p$.e = setProp(_el$
|
|
18258
|
-
_v$1 !== _p$.t && (_p$.t = setProp(_el$
|
|
18259
|
-
_v$10 !== _p$.a && (_p$.a = setProp(_el$
|
|
18841
|
+
var _v$0 = rowBg(), _v$1 = theme.textMuted, _v$10 = TextAttributes11.BOLD;
|
|
18842
|
+
_v$0 !== _p$.e && (_p$.e = setProp(_el$29, "backgroundColor", _v$0, _p$.e));
|
|
18843
|
+
_v$1 !== _p$.t && (_p$.t = setProp(_el$31, "fg", _v$1, _p$.t));
|
|
18844
|
+
_v$10 !== _p$.a && (_p$.a = setProp(_el$31, "attributes", _v$10, _p$.a));
|
|
18260
18845
|
return _p$;
|
|
18261
18846
|
}, {
|
|
18262
18847
|
e: undefined,
|
|
18263
18848
|
t: undefined,
|
|
18264
18849
|
a: undefined
|
|
18265
18850
|
});
|
|
18266
|
-
return _el$
|
|
18851
|
+
return _el$29;
|
|
18267
18852
|
})();
|
|
18268
18853
|
}
|
|
18269
18854
|
if (row.kind === "file") {
|
|
18270
18855
|
const indent = " ".repeat(row.depth);
|
|
18271
18856
|
return (() => {
|
|
18272
|
-
var _el$
|
|
18273
|
-
insertNode(_el$
|
|
18274
|
-
setProp(_el$
|
|
18275
|
-
setProp(_el$
|
|
18276
|
-
setProp(_el$
|
|
18857
|
+
var _el$32 = createElement("box"), _el$33 = createElement("box"), _el$34 = createElement("text");
|
|
18858
|
+
insertNode(_el$32, _el$33);
|
|
18859
|
+
setProp(_el$32, "flexDirection", "row");
|
|
18860
|
+
setProp(_el$32, "gap", 0);
|
|
18861
|
+
setProp(_el$32, "onMouseUp", () => {
|
|
18277
18862
|
setCursorIndex(index());
|
|
18278
18863
|
props.onOpenFile(row.path);
|
|
18279
18864
|
});
|
|
18280
|
-
|
|
18281
|
-
|
|
18865
|
+
insert(_el$32, bar, _el$33);
|
|
18866
|
+
insertNode(_el$33, _el$34);
|
|
18867
|
+
setProp(_el$33, "flexGrow", 1);
|
|
18868
|
+
setProp(_el$33, "paddingRight", 1);
|
|
18869
|
+
setProp(_el$34, "wrapMode", "none");
|
|
18870
|
+
insert(_el$34, () => `${indent} ${row.name}`);
|
|
18282
18871
|
effect((_p$) => {
|
|
18283
|
-
var _v$11 =
|
|
18284
|
-
_v$11 !== _p$.e && (_p$.e = setProp(_el$
|
|
18285
|
-
_v$12 !== _p$.t && (_p$.t = setProp(_el$
|
|
18872
|
+
var _v$11 = rowBg(), _v$12 = theme.text;
|
|
18873
|
+
_v$11 !== _p$.e && (_p$.e = setProp(_el$32, "backgroundColor", _v$11, _p$.e));
|
|
18874
|
+
_v$12 !== _p$.t && (_p$.t = setProp(_el$34, "fg", _v$12, _p$.t));
|
|
18286
18875
|
return _p$;
|
|
18287
18876
|
}, {
|
|
18288
18877
|
e: undefined,
|
|
18289
18878
|
t: undefined
|
|
18290
18879
|
});
|
|
18291
|
-
return _el$
|
|
18880
|
+
return _el$32;
|
|
18292
18881
|
})();
|
|
18293
18882
|
}
|
|
18294
18883
|
const tone = statusToken(row.status);
|
|
@@ -18310,64 +18899,84 @@ function FileTree(props) {
|
|
|
18310
18899
|
const addedText = row.added == null ? " ".repeat(w.added) : `+${row.added}`.padStart(w.added);
|
|
18311
18900
|
const deletedText = row.deleted == null ? " ".repeat(w.deleted) : `-${row.deleted}`.padStart(w.deleted);
|
|
18312
18901
|
return (() => {
|
|
18313
|
-
var _el$
|
|
18314
|
-
insertNode(_el$
|
|
18315
|
-
|
|
18316
|
-
setProp(_el$
|
|
18317
|
-
setProp(_el$
|
|
18318
|
-
setProp(_el$29, "paddingLeft", 1);
|
|
18319
|
-
setProp(_el$29, "paddingRight", 1);
|
|
18320
|
-
setProp(_el$29, "onMouseUp", () => {
|
|
18902
|
+
var _el$35 = createElement("box"), _el$36 = createElement("box"), _el$37 = createElement("text"), _el$38 = createElement("text");
|
|
18903
|
+
insertNode(_el$35, _el$36);
|
|
18904
|
+
setProp(_el$35, "flexDirection", "row");
|
|
18905
|
+
setProp(_el$35, "gap", 0);
|
|
18906
|
+
setProp(_el$35, "onMouseUp", () => {
|
|
18321
18907
|
setCursorIndex(index());
|
|
18322
18908
|
props.onOpenFile(row.path);
|
|
18323
18909
|
});
|
|
18324
|
-
|
|
18325
|
-
|
|
18326
|
-
|
|
18327
|
-
setProp(_el$
|
|
18328
|
-
|
|
18329
|
-
|
|
18910
|
+
insert(_el$35, bar, _el$36);
|
|
18911
|
+
insertNode(_el$36, _el$37);
|
|
18912
|
+
insertNode(_el$36, _el$38);
|
|
18913
|
+
setProp(_el$36, "flexDirection", "row");
|
|
18914
|
+
setProp(_el$36, "flexGrow", 1);
|
|
18915
|
+
setProp(_el$36, "gap", 1);
|
|
18916
|
+
setProp(_el$36, "paddingRight", 1);
|
|
18917
|
+
setProp(_el$37, "wrapMode", "none");
|
|
18918
|
+
insert(_el$37, () => row.status);
|
|
18919
|
+
setProp(_el$38, "wrapMode", "none");
|
|
18920
|
+
setProp(_el$38, "flexGrow", 1);
|
|
18921
|
+
insert(_el$38, () => truncatePathTail2(row.path, pathBudget()));
|
|
18922
|
+
insert(_el$36, createComponent2(Show, {
|
|
18330
18923
|
get when() {
|
|
18331
18924
|
return w.added > 0;
|
|
18332
18925
|
},
|
|
18333
18926
|
get children() {
|
|
18334
|
-
var _el$
|
|
18335
|
-
setProp(_el$
|
|
18336
|
-
insert(_el$
|
|
18337
|
-
effect((_$p) => setProp(_el$
|
|
18338
|
-
return _el$
|
|
18927
|
+
var _el$39 = createElement("text");
|
|
18928
|
+
setProp(_el$39, "wrapMode", "none");
|
|
18929
|
+
insert(_el$39, addedText);
|
|
18930
|
+
effect((_$p) => setProp(_el$39, "fg", theme.success, _$p));
|
|
18931
|
+
return _el$39;
|
|
18339
18932
|
}
|
|
18340
18933
|
}), null);
|
|
18341
|
-
insert(_el$
|
|
18934
|
+
insert(_el$36, createComponent2(Show, {
|
|
18342
18935
|
get when() {
|
|
18343
18936
|
return w.deleted > 0;
|
|
18344
18937
|
},
|
|
18345
18938
|
get children() {
|
|
18346
|
-
var _el$
|
|
18347
|
-
setProp(_el$
|
|
18348
|
-
insert(_el$
|
|
18349
|
-
effect((_$p) => setProp(_el$
|
|
18350
|
-
return _el$
|
|
18939
|
+
var _el$40 = createElement("text");
|
|
18940
|
+
setProp(_el$40, "wrapMode", "none");
|
|
18941
|
+
insert(_el$40, deletedText);
|
|
18942
|
+
effect((_$p) => setProp(_el$40, "fg", theme.error, _$p));
|
|
18943
|
+
return _el$40;
|
|
18351
18944
|
}
|
|
18352
18945
|
}), null);
|
|
18353
18946
|
effect((_p$) => {
|
|
18354
|
-
var _v$13 =
|
|
18355
|
-
_v$13 !== _p$.e && (_p$.e = setProp(_el$
|
|
18356
|
-
_v$14 !== _p$.t && (_p$.t = setProp(_el$
|
|
18357
|
-
_v$15 !== _p$.a && (_p$.a = setProp(_el$
|
|
18947
|
+
var _v$13 = rowBg(), _v$14 = statusColor(), _v$15 = theme.text;
|
|
18948
|
+
_v$13 !== _p$.e && (_p$.e = setProp(_el$35, "backgroundColor", _v$13, _p$.e));
|
|
18949
|
+
_v$14 !== _p$.t && (_p$.t = setProp(_el$37, "fg", _v$14, _p$.t));
|
|
18950
|
+
_v$15 !== _p$.a && (_p$.a = setProp(_el$38, "fg", _v$15, _p$.a));
|
|
18358
18951
|
return _p$;
|
|
18359
18952
|
}, {
|
|
18360
18953
|
e: undefined,
|
|
18361
18954
|
t: undefined,
|
|
18362
18955
|
a: undefined
|
|
18363
18956
|
});
|
|
18364
|
-
return _el$
|
|
18957
|
+
return _el$35;
|
|
18365
18958
|
})();
|
|
18366
18959
|
}
|
|
18367
18960
|
}));
|
|
18368
18961
|
return _el$22;
|
|
18369
18962
|
}
|
|
18370
18963
|
}), null);
|
|
18964
|
+
insert(_el$, createComponent2(Show, {
|
|
18965
|
+
get when() {
|
|
18966
|
+
return props.worktreePath() != null;
|
|
18967
|
+
},
|
|
18968
|
+
get children() {
|
|
18969
|
+
var _el$23 = createElement("box"), _el$24 = createElement("text");
|
|
18970
|
+
insertNode(_el$23, _el$24);
|
|
18971
|
+
setProp(_el$23, "flexDirection", "row");
|
|
18972
|
+
setProp(_el$23, "paddingTop", 1);
|
|
18973
|
+
setProp(_el$23, "flexShrink", 0);
|
|
18974
|
+
insertNode(_el$24, createTextNode(`\u21B5 preview \xB7 e edit`));
|
|
18975
|
+
setProp(_el$24, "wrapMode", "none");
|
|
18976
|
+
effect((_$p) => setProp(_el$24, "fg", theme.textMuted, _$p));
|
|
18977
|
+
return _el$23;
|
|
18978
|
+
}
|
|
18979
|
+
}), null);
|
|
18371
18980
|
return _el$;
|
|
18372
18981
|
})();
|
|
18373
18982
|
}
|
|
@@ -18382,6 +18991,7 @@ var init_FileTree = __esm(() => {
|
|
|
18382
18991
|
init_solid();
|
|
18383
18992
|
init_solid();
|
|
18384
18993
|
init_solid();
|
|
18994
|
+
init_solid();
|
|
18385
18995
|
init_dev();
|
|
18386
18996
|
init_theme2();
|
|
18387
18997
|
init_git2();
|
|
@@ -18402,15 +19012,16 @@ var init_filetree = __esm(() => {
|
|
|
18402
19012
|
});
|
|
18403
19013
|
|
|
18404
19014
|
// src/tui/ops/pr-prompt.ts
|
|
18405
|
-
import { spawnSync as
|
|
19015
|
+
import { spawnSync as spawnSync9 } from "child_process";
|
|
18406
19016
|
import { promises as fs4 } from "fs";
|
|
18407
19017
|
import path11 from "path";
|
|
18408
19018
|
function git2(cwd, args) {
|
|
18409
19019
|
try {
|
|
18410
|
-
const out =
|
|
19020
|
+
const out = spawnSync9("git", args.slice(), {
|
|
18411
19021
|
cwd,
|
|
18412
19022
|
encoding: "utf8",
|
|
18413
|
-
timeout: GIT_TIMEOUT_MS
|
|
19023
|
+
timeout: GIT_TIMEOUT_MS,
|
|
19024
|
+
env: { ...process.env, GIT_OPTIONAL_LOCKS: "0" }
|
|
18414
19025
|
});
|
|
18415
19026
|
if (out.error)
|
|
18416
19027
|
return null;
|
|
@@ -18611,6 +19222,17 @@ function OpsShell(props) {
|
|
|
18611
19222
|
name: basename5(rel)
|
|
18612
19223
|
});
|
|
18613
19224
|
}
|
|
19225
|
+
function openEditor(rel) {
|
|
19226
|
+
if (!props.taskId) {
|
|
19227
|
+
openPreview(rel);
|
|
19228
|
+
return;
|
|
19229
|
+
}
|
|
19230
|
+
const abs = `${props.worktree}/${rel}`;
|
|
19231
|
+
openInEditor(tmuxSessionName(props.taskId), props.worktree, abs).then((launched) => {
|
|
19232
|
+
if (!launched)
|
|
19233
|
+
openPreview(rel);
|
|
19234
|
+
});
|
|
19235
|
+
}
|
|
18614
19236
|
function injectMention(rel) {
|
|
18615
19237
|
if (!props.targetPane)
|
|
18616
19238
|
return;
|
|
@@ -18631,6 +19253,7 @@ function OpsShell(props) {
|
|
|
18631
19253
|
worktreePath: () => props.worktree,
|
|
18632
19254
|
focused: () => true,
|
|
18633
19255
|
onOpenFile: openPreview,
|
|
19256
|
+
onEditFile: openEditor,
|
|
18634
19257
|
onMention: injectMention,
|
|
18635
19258
|
onCreatePR: () => void createPR(),
|
|
18636
19259
|
cornerBadge,
|
|
@@ -18706,7 +19329,11 @@ async function gitDiff(worktree, relPath) {
|
|
|
18706
19329
|
cwd: worktree,
|
|
18707
19330
|
stdin: "ignore",
|
|
18708
19331
|
stdout: "pipe",
|
|
18709
|
-
stderr: "ignore"
|
|
19332
|
+
stderr: "ignore",
|
|
19333
|
+
env: {
|
|
19334
|
+
...process.env,
|
|
19335
|
+
GIT_OPTIONAL_LOCKS: "0"
|
|
19336
|
+
}
|
|
18710
19337
|
});
|
|
18711
19338
|
const text = await new Response(proc.stdout).text();
|
|
18712
19339
|
await proc.exited;
|
|
@@ -18933,6 +19560,7 @@ var init_host5 = __esm(() => {
|
|
|
18933
19560
|
init_turn_detector();
|
|
18934
19561
|
init_activity();
|
|
18935
19562
|
init_client2();
|
|
19563
|
+
init_editor_launch();
|
|
18936
19564
|
init_solid();
|
|
18937
19565
|
init_dev();
|
|
18938
19566
|
init_theme2();
|
|
@@ -19005,7 +19633,7 @@ async function startDirectTmux() {
|
|
|
19005
19633
|
return;
|
|
19006
19634
|
}
|
|
19007
19635
|
const client = await connectOrStartDaemon();
|
|
19008
|
-
const orchestrator = new RemoteOrchestrator(client);
|
|
19636
|
+
const orchestrator = new RemoteOrchestrator(client, { role: "gui" });
|
|
19009
19637
|
try {
|
|
19010
19638
|
process.env.KOBE_DAEMON_SOCKET_PATH = client.socketPath;
|
|
19011
19639
|
await orchestrator.init();
|
|
@@ -19848,7 +20476,7 @@ function repoBasename2(repo) {
|
|
|
19848
20476
|
}
|
|
19849
20477
|
|
|
19850
20478
|
// src/tui/component/top-bar.tsx
|
|
19851
|
-
import { spawnSync as
|
|
20479
|
+
import { spawnSync as spawnSync10 } from "child_process";
|
|
19852
20480
|
import { TextAttributes as TextAttributes16 } from "@opentui/core";
|
|
19853
20481
|
function TopBar(props) {
|
|
19854
20482
|
const {
|
|
@@ -19877,7 +20505,7 @@ function TopBar(props) {
|
|
|
19877
20505
|
`);
|
|
19878
20506
|
process.stderr.write(`running: ${UPDATE_COMMAND}
|
|
19879
20507
|
`);
|
|
19880
|
-
const result =
|
|
20508
|
+
const result = spawnSync10("sh", ["-c", UPDATE_COMMAND], {
|
|
19881
20509
|
stdio: "inherit"
|
|
19882
20510
|
});
|
|
19883
20511
|
if (result.error) {
|
|
@@ -21229,7 +21857,9 @@ async function startApp() {
|
|
|
21229
21857
|
});
|
|
21230
21858
|
} else {
|
|
21231
21859
|
const client = await connectOrStartDaemon();
|
|
21232
|
-
orchestrator = new RemoteOrchestrator(client
|
|
21860
|
+
orchestrator = new RemoteOrchestrator(client, {
|
|
21861
|
+
role: "gui"
|
|
21862
|
+
});
|
|
21233
21863
|
process.env.KOBE_DAEMON_SOCKET_PATH = client.socketPath;
|
|
21234
21864
|
await orchestrator.init();
|
|
21235
21865
|
}
|