@sma1lboy/kobe 0.7.3 → 0.7.5
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 +965 -318
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -70,7 +70,7 @@ 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.7.
|
|
73
|
+
version: "0.7.5",
|
|
74
74
|
description: "TUI orchestrator for Claude Code (codename)",
|
|
75
75
|
type: "module",
|
|
76
76
|
packageManager: "bun@1.3.13",
|
|
@@ -2325,6 +2325,254 @@ var init_dev = __esm(() => {
|
|
|
2325
2325
|
}
|
|
2326
2326
|
});
|
|
2327
2327
|
|
|
2328
|
+
// src/cli/invocation.ts
|
|
2329
|
+
import { fileURLToPath } from "url";
|
|
2330
|
+
function kobeCliInvocation() {
|
|
2331
|
+
const isBuilt = import.meta.url.endsWith(".js");
|
|
2332
|
+
if (isBuilt)
|
|
2333
|
+
return ["kobe"];
|
|
2334
|
+
const entry = fileURLToPath(new URL("./index.ts", import.meta.url));
|
|
2335
|
+
const preload = fileURLToPath(import.meta.resolve("@opentui/solid/preload"));
|
|
2336
|
+
return [process.execPath, "--preload", preload, "--conditions=browser", entry];
|
|
2337
|
+
}
|
|
2338
|
+
var init_invocation = () => {};
|
|
2339
|
+
|
|
2340
|
+
// src/tmux/session-layout.ts
|
|
2341
|
+
function shellQuote(s) {
|
|
2342
|
+
return `'${s.replace(/'/g, "'\\''")}'`;
|
|
2343
|
+
}
|
|
2344
|
+
function shellQuoteArgv(argv) {
|
|
2345
|
+
return argv.map(shellQuote).join(" ");
|
|
2346
|
+
}
|
|
2347
|
+
function keepAlive(cmd) {
|
|
2348
|
+
return `${cmd}; exec "\${SHELL:-/bin/sh}"`;
|
|
2349
|
+
}
|
|
2350
|
+
function shQuote(s) {
|
|
2351
|
+
return `'${s.replace(/'/g, "'\\''")}'`;
|
|
2352
|
+
}
|
|
2353
|
+
function homeWelcomeCommand() {
|
|
2354
|
+
const msg = "\\n No task selected\\n\\n Press N to create a task, or pick one on the left.\\n\\n";
|
|
2355
|
+
return `clear; printf ${shQuote(msg)}; exec "\${SHELL:-/bin/sh}"`;
|
|
2356
|
+
}
|
|
2357
|
+
function engineLaunchLine(engineCmd, init) {
|
|
2358
|
+
const tail = keepAlive(engineCmd);
|
|
2359
|
+
const script = init?.initScript?.trim();
|
|
2360
|
+
if (!script)
|
|
2361
|
+
return tail;
|
|
2362
|
+
const group = ["{", script, "}"].join(`
|
|
2363
|
+
`);
|
|
2364
|
+
if (init?.markerPath) {
|
|
2365
|
+
const marker = shQuote(init.markerPath);
|
|
2366
|
+
const markerDir = shQuote(markerDirOf(init.markerPath));
|
|
2367
|
+
return [
|
|
2368
|
+
`if [ ! -f ${marker} ]; then`,
|
|
2369
|
+
group,
|
|
2370
|
+
`if [ $? -eq 0 ]; then mkdir -p ${markerDir} && : > ${marker}; fi`,
|
|
2371
|
+
"fi",
|
|
2372
|
+
tail
|
|
2373
|
+
].join(`
|
|
2374
|
+
`);
|
|
2375
|
+
}
|
|
2376
|
+
return [group, tail].join(`
|
|
2377
|
+
`);
|
|
2378
|
+
}
|
|
2379
|
+
function markerDirOf(p) {
|
|
2380
|
+
const i = p.lastIndexOf("/");
|
|
2381
|
+
return i <= 0 ? "." : p.slice(0, i);
|
|
2382
|
+
}
|
|
2383
|
+
function fallbackOpsScript(cwd) {
|
|
2384
|
+
return `cd ${shellQuote(cwd)} && while :; do clear; printf "\\033[1m# %s\\033[0m\\n\\n" ${shellQuote(cwd)}; git status --short --branch 2>/dev/null | sed 's/^/ /' || true; printf "\\n"; if command -v lsd >/dev/null 2>&1; then lsd --tree --git -I node_modules -I .git --depth 2 .; elif command -v eza >/dev/null 2>&1; then eza --tree --git -L 2 -I 'node_modules|.git' .; elif command -v tree >/dev/null 2>&1; then tree -L 2 -I 'node_modules|.git'; else ls -la; fi; sleep 2; done`;
|
|
2385
|
+
}
|
|
2386
|
+
function previewWindowCommand(args) {
|
|
2387
|
+
const wt = shellQuote(args.worktree);
|
|
2388
|
+
const file = shellQuote(args.relPath);
|
|
2389
|
+
const inv = args.cliInvocation.map(shellQuote).join(" ");
|
|
2390
|
+
const fallback = `cd ${wt} && if ! git diff --quiet HEAD -- ${file} 2>/dev/null; then ` + `git diff HEAD -- ${file} | { delta --paging=always 2>/dev/null || less -R; }; ` + `else bat --style=plain --paging=always ${file} 2>/dev/null || \${PAGER:-less} ${file} 2>/dev/null || cat ${file}; fi`;
|
|
2391
|
+
return `${inv} ops --worktree ${wt} --preview ${file} || { ${fallback}; }`;
|
|
2392
|
+
}
|
|
2393
|
+
function updatePageCommand(args) {
|
|
2394
|
+
return `${shellQuoteArgv([...args.cliInvocation, "update-page"])}`;
|
|
2395
|
+
}
|
|
2396
|
+
function tasksPaneCommand(cliInvocation, opts = {}) {
|
|
2397
|
+
const argv = [...cliInvocation, "tasks"];
|
|
2398
|
+
if (opts.initialTaskId)
|
|
2399
|
+
argv.push("--initial-task-id", opts.initialTaskId);
|
|
2400
|
+
return shellQuoteArgv(argv);
|
|
2401
|
+
}
|
|
2402
|
+
function opsPaneCommand(args) {
|
|
2403
|
+
if (args.taskId && args.claudePaneId) {
|
|
2404
|
+
const inv = args.cliInvocation.map(shellQuote).join(" ");
|
|
2405
|
+
const vendorFlag = args.vendor ? ` --vendor ${shellQuote(args.vendor)}` : "";
|
|
2406
|
+
return `KOBE_FILETREE_WATCH=1 ${inv} ops --task-id ${shellQuote(args.taskId)} --worktree ${shellQuote(args.cwd)} ` + `--target-pane ${shellQuote(args.claudePaneId)}${vendorFlag} || { ${fallbackOpsScript(args.cwd)}; }`;
|
|
2407
|
+
}
|
|
2408
|
+
return fallbackOpsScript(args.cwd);
|
|
2409
|
+
}
|
|
2410
|
+
var TASKS_PANE_WIDTH = 32, CLAUDE_PANE_PERCENT = 60, OPS_PANE_PERCENT = 50;
|
|
2411
|
+
|
|
2412
|
+
// src/engine/claude-code-local/hook-adapter.ts
|
|
2413
|
+
import { existsSync } from "fs";
|
|
2414
|
+
import { appendFile, mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
2415
|
+
import { dirname as dirname3, join as join3 } from "path";
|
|
2416
|
+
function isObject(v) {
|
|
2417
|
+
return !!v && typeof v === "object" && !Array.isArray(v);
|
|
2418
|
+
}
|
|
2419
|
+
async function readJsonObject(path3) {
|
|
2420
|
+
try {
|
|
2421
|
+
const parsed = JSON.parse(await readFile2(path3, "utf8"));
|
|
2422
|
+
return isObject(parsed) ? parsed : {};
|
|
2423
|
+
} catch {
|
|
2424
|
+
return {};
|
|
2425
|
+
}
|
|
2426
|
+
}
|
|
2427
|
+
function isKobeWorktreeSyncGroup(group) {
|
|
2428
|
+
if (!isObject(group) || !Array.isArray(group.hooks))
|
|
2429
|
+
return false;
|
|
2430
|
+
return group.hooks.some((h) => isObject(h) && typeof h.command === "string" && h.command.includes(WORKTREE_SYNC_MARKER));
|
|
2431
|
+
}
|
|
2432
|
+
function mergeWorktreeSyncHook(current, command) {
|
|
2433
|
+
const { hooks: rawHooks, ...restSettings } = current;
|
|
2434
|
+
const { WorktreeCreate, ...otherHooks } = isObject(rawHooks) ? rawHooks : {};
|
|
2435
|
+
const prior = Array.isArray(WorktreeCreate) ? WorktreeCreate : [];
|
|
2436
|
+
const kept = prior.filter((g) => !isKobeWorktreeSyncGroup(g));
|
|
2437
|
+
if (command !== null)
|
|
2438
|
+
kept.push({ hooks: [{ type: "command", command }] });
|
|
2439
|
+
const nextHooks = { ...otherHooks };
|
|
2440
|
+
if (kept.length > 0)
|
|
2441
|
+
nextHooks.WorktreeCreate = kept;
|
|
2442
|
+
return Object.keys(nextHooks).length > 0 ? { ...restSettings, hooks: nextHooks } : { ...restSettings };
|
|
2443
|
+
}
|
|
2444
|
+
function buildClaudeHooks(taskId, inv = kobeCliInvocation()) {
|
|
2445
|
+
const out = {};
|
|
2446
|
+
for (const { event, matcher, verb } of EVENT_MAP) {
|
|
2447
|
+
const command = shellQuoteArgv([...inv, "hook", verb, "--task-id", taskId]);
|
|
2448
|
+
const group = { hooks: [{ type: "command", command }] };
|
|
2449
|
+
if (matcher)
|
|
2450
|
+
group.matcher = matcher;
|
|
2451
|
+
out[event] = [group];
|
|
2452
|
+
}
|
|
2453
|
+
return out;
|
|
2454
|
+
}
|
|
2455
|
+
function mergeClaudeHooks(existing, kobeHooks) {
|
|
2456
|
+
const merged = { ...existing };
|
|
2457
|
+
for (const event of KOBE_HOOK_EVENTS)
|
|
2458
|
+
merged[event] = kobeHooks[event];
|
|
2459
|
+
return merged;
|
|
2460
|
+
}
|
|
2461
|
+
|
|
2462
|
+
class ClaudeHookAdapter {
|
|
2463
|
+
vendor = "claude";
|
|
2464
|
+
supportsHooks() {
|
|
2465
|
+
return true;
|
|
2466
|
+
}
|
|
2467
|
+
supportsWorktreeSync() {
|
|
2468
|
+
return true;
|
|
2469
|
+
}
|
|
2470
|
+
async installWorktreeSyncHook(settingsFilePath) {
|
|
2471
|
+
await this.editWorktreeSyncHook(settingsFilePath, true);
|
|
2472
|
+
}
|
|
2473
|
+
async removeWorktreeSyncHook(settingsFilePath) {
|
|
2474
|
+
await this.editWorktreeSyncHook(settingsFilePath, false);
|
|
2475
|
+
}
|
|
2476
|
+
async editWorktreeSyncHook(settingsFilePath, install) {
|
|
2477
|
+
const current = await readJsonObject(settingsFilePath);
|
|
2478
|
+
const command = install ? shellQuoteArgv([...kobeCliInvocation(), "hook", "worktree-created"]) : null;
|
|
2479
|
+
const next = mergeWorktreeSyncHook(current, command);
|
|
2480
|
+
await mkdir2(dirname3(settingsFilePath), { recursive: true });
|
|
2481
|
+
await writeFile2(settingsFilePath, `${JSON.stringify(next, null, 2)}
|
|
2482
|
+
`);
|
|
2483
|
+
}
|
|
2484
|
+
async installTaskHooks(ctx) {
|
|
2485
|
+
try {
|
|
2486
|
+
const claudeDir = join3(ctx.worktreeDir, ".claude");
|
|
2487
|
+
const settingsPath = join3(claudeDir, "settings.local.json");
|
|
2488
|
+
await mkdir2(claudeDir, { recursive: true });
|
|
2489
|
+
let current = {};
|
|
2490
|
+
try {
|
|
2491
|
+
const raw = await readFile2(settingsPath, "utf8");
|
|
2492
|
+
const parsed = JSON.parse(raw);
|
|
2493
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed))
|
|
2494
|
+
current = parsed;
|
|
2495
|
+
} catch {}
|
|
2496
|
+
const existingHooks = current.hooks && typeof current.hooks === "object" && !Array.isArray(current.hooks) ? current.hooks : {};
|
|
2497
|
+
current.hooks = mergeClaudeHooks(existingHooks, buildClaudeHooks(ctx.taskId));
|
|
2498
|
+
await writeFile2(settingsPath, `${JSON.stringify(current, null, 2)}
|
|
2499
|
+
`);
|
|
2500
|
+
await hideFromGit(ctx.worktreeDir, ".claude/settings.local.json");
|
|
2501
|
+
} catch {}
|
|
2502
|
+
}
|
|
2503
|
+
}
|
|
2504
|
+
async function hideFromGit(worktreeDir, relPath) {
|
|
2505
|
+
if (hiddenWorktrees.has(worktreeDir))
|
|
2506
|
+
return;
|
|
2507
|
+
try {
|
|
2508
|
+
const proc = Bun.spawn(["git", "-C", worktreeDir, "rev-parse", "--git-common-dir"], {
|
|
2509
|
+
stdout: "pipe",
|
|
2510
|
+
stderr: "ignore"
|
|
2511
|
+
});
|
|
2512
|
+
const [out, code] = await Promise.all([new Response(proc.stdout).text(), proc.exited]);
|
|
2513
|
+
if (code !== 0)
|
|
2514
|
+
return;
|
|
2515
|
+
let commonDir = out.trim();
|
|
2516
|
+
if (!commonDir)
|
|
2517
|
+
return;
|
|
2518
|
+
if (!commonDir.startsWith("/"))
|
|
2519
|
+
commonDir = join3(worktreeDir, commonDir);
|
|
2520
|
+
const excludePath = join3(commonDir, "info", "exclude");
|
|
2521
|
+
const existing = existsSync(excludePath) ? await readFile2(excludePath, "utf8") : "";
|
|
2522
|
+
if (existing.split(`
|
|
2523
|
+
`).some((l) => l.trim() === relPath)) {
|
|
2524
|
+
hiddenWorktrees.add(worktreeDir);
|
|
2525
|
+
return;
|
|
2526
|
+
}
|
|
2527
|
+
await mkdir2(join3(commonDir, "info"), { recursive: true });
|
|
2528
|
+
await appendFile(excludePath, `${existing.endsWith(`
|
|
2529
|
+
`) || existing === "" ? "" : `
|
|
2530
|
+
`}${relPath}
|
|
2531
|
+
`);
|
|
2532
|
+
hiddenWorktrees.add(worktreeDir);
|
|
2533
|
+
} catch {}
|
|
2534
|
+
}
|
|
2535
|
+
var EVENT_MAP, KOBE_HOOK_EVENTS, WORKTREE_SYNC_MARKER = "worktree-created", hiddenWorktrees;
|
|
2536
|
+
var init_hook_adapter = __esm(() => {
|
|
2537
|
+
init_invocation();
|
|
2538
|
+
EVENT_MAP = [
|
|
2539
|
+
{ event: "SessionStart", verb: "session-start" },
|
|
2540
|
+
{ event: "UserPromptSubmit", verb: "turn-start" },
|
|
2541
|
+
{ event: "Stop", verb: "turn-complete" },
|
|
2542
|
+
{ event: "StopFailure", verb: "turn-failed" },
|
|
2543
|
+
{ event: "Notification", matcher: "permission_prompt", verb: "awaiting-input" },
|
|
2544
|
+
{ event: "SessionEnd", verb: "session-end" }
|
|
2545
|
+
];
|
|
2546
|
+
KOBE_HOOK_EVENTS = EVENT_MAP.map((e) => e.event);
|
|
2547
|
+
hiddenWorktrees = new Set;
|
|
2548
|
+
});
|
|
2549
|
+
|
|
2550
|
+
// src/engine/hook-adapter.ts
|
|
2551
|
+
function createEngineHookAdapter(vendor) {
|
|
2552
|
+
if (vendor === "claude")
|
|
2553
|
+
return new ClaudeHookAdapter;
|
|
2554
|
+
return new NoopHookAdapter(vendor);
|
|
2555
|
+
}
|
|
2556
|
+
|
|
2557
|
+
class NoopHookAdapter {
|
|
2558
|
+
vendor;
|
|
2559
|
+
constructor(vendor) {
|
|
2560
|
+
this.vendor = vendor;
|
|
2561
|
+
}
|
|
2562
|
+
supportsHooks() {
|
|
2563
|
+
return false;
|
|
2564
|
+
}
|
|
2565
|
+
async installTaskHooks() {}
|
|
2566
|
+
supportsWorktreeSync() {
|
|
2567
|
+
return false;
|
|
2568
|
+
}
|
|
2569
|
+
async installWorktreeSyncHook() {}
|
|
2570
|
+
async removeWorktreeSyncHook() {}
|
|
2571
|
+
}
|
|
2572
|
+
var init_hook_adapter2 = __esm(() => {
|
|
2573
|
+
init_hook_adapter();
|
|
2574
|
+
});
|
|
2575
|
+
|
|
2328
2576
|
// src/orchestrator/errors.ts
|
|
2329
2577
|
var IllegalTransitionError, TaskNotFoundError, CannotDeleteMainTaskError, DIRTY_WORKTREE_CODE = "DIRTY_WORKTREE", DirtyWorktreeError, WorktreeRemoveFailedError;
|
|
2330
2578
|
var init_errors = __esm(() => {
|
|
@@ -3003,8 +3251,10 @@ class Orchestrator {
|
|
|
3003
3251
|
const task = this.requireTask(id);
|
|
3004
3252
|
if (task.kind === "main")
|
|
3005
3253
|
return task.repo;
|
|
3006
|
-
if (task.worktreePath)
|
|
3254
|
+
if (task.worktreePath) {
|
|
3255
|
+
await this.installEngineHooks(task);
|
|
3007
3256
|
return task.worktreePath;
|
|
3257
|
+
}
|
|
3008
3258
|
const inflight = this.worktreeLocks.get(task.id);
|
|
3009
3259
|
if (inflight) {
|
|
3010
3260
|
await inflight;
|
|
@@ -3028,6 +3278,7 @@ class Orchestrator {
|
|
|
3028
3278
|
worktreePath: info.path,
|
|
3029
3279
|
branch
|
|
3030
3280
|
});
|
|
3281
|
+
await this.installEngineHooks(this.requireTask(task.id));
|
|
3031
3282
|
} catch (err) {
|
|
3032
3283
|
this.slugs.cancel(task.repo, slug);
|
|
3033
3284
|
throw err;
|
|
@@ -3152,14 +3403,29 @@ class Orchestrator {
|
|
|
3152
3403
|
if (!input.worktreePath)
|
|
3153
3404
|
throw new Error("adoptWorktree: worktreePath is required");
|
|
3154
3405
|
const target = canonPath(input.worktreePath);
|
|
3406
|
+
const inflight = this.adoptLocks.get(target);
|
|
3407
|
+
if (inflight)
|
|
3408
|
+
return inflight;
|
|
3409
|
+
const work = this.adoptWorktreeLocked(input, target);
|
|
3410
|
+
this.adoptLocks.set(target, work);
|
|
3411
|
+
try {
|
|
3412
|
+
return await work;
|
|
3413
|
+
} finally {
|
|
3414
|
+
this.adoptLocks.delete(target);
|
|
3415
|
+
}
|
|
3416
|
+
}
|
|
3417
|
+
async adoptWorktreeLocked(input, target) {
|
|
3418
|
+
const existing = this.store.list().find((t) => t.worktreePath && canonPath(t.worktreePath) === target);
|
|
3419
|
+
if (existing) {
|
|
3420
|
+
if (input.ifExists === "return")
|
|
3421
|
+
return existing;
|
|
3422
|
+
throw new Error(`adoptWorktree: ${input.worktreePath} is already adopted as a task`);
|
|
3423
|
+
}
|
|
3155
3424
|
const candidates = await this.worktrees.listAll(input.repo);
|
|
3156
3425
|
const match = candidates.find((wt) => canonPath(wt.path) === target);
|
|
3157
3426
|
if (!match) {
|
|
3158
3427
|
throw new Error(`adoptWorktree: ${input.worktreePath} is not an adoptable git worktree of ${input.repo} (unknown, detached, or the main checkout)`);
|
|
3159
3428
|
}
|
|
3160
|
-
const alreadyLinked = this.store.list().some((t) => t.worktreePath && canonPath(t.worktreePath) === target);
|
|
3161
|
-
if (alreadyLinked)
|
|
3162
|
-
throw new Error(`adoptWorktree: ${input.worktreePath} is already adopted as a task`);
|
|
3163
3429
|
const branch = input.branch?.trim() || match.branch;
|
|
3164
3430
|
const title = (input.title ?? basename2(match.path)).trim() || PLACEHOLDER_TASK_TITLE;
|
|
3165
3431
|
return this.store.create({
|
|
@@ -3172,7 +3438,16 @@ class Orchestrator {
|
|
|
3172
3438
|
vendor: input.vendor ?? DEFAULT_TASK_VENDOR
|
|
3173
3439
|
});
|
|
3174
3440
|
}
|
|
3441
|
+
async installEngineHooks(task) {
|
|
3442
|
+
if (task.kind === "main" || !task.worktreePath)
|
|
3443
|
+
return;
|
|
3444
|
+
await createEngineHookAdapter(task.vendor ?? DEFAULT_TASK_VENDOR).installTaskHooks({
|
|
3445
|
+
worktreeDir: task.worktreePath,
|
|
3446
|
+
taskId: task.id
|
|
3447
|
+
});
|
|
3448
|
+
}
|
|
3175
3449
|
pendingBaseRefs = new Map;
|
|
3450
|
+
adoptLocks = new Map;
|
|
3176
3451
|
requireTask(id) {
|
|
3177
3452
|
const task = this.store.get(id);
|
|
3178
3453
|
if (!task)
|
|
@@ -3194,6 +3469,7 @@ function canonPath(p) {
|
|
|
3194
3469
|
var PLACEHOLDER_TASK_TITLE = "(new task)";
|
|
3195
3470
|
var init_core = __esm(() => {
|
|
3196
3471
|
init_dev();
|
|
3472
|
+
init_hook_adapter2();
|
|
3197
3473
|
init_errors();
|
|
3198
3474
|
init_slug_allocator();
|
|
3199
3475
|
});
|
|
@@ -3202,6 +3478,11 @@ var init_core = __esm(() => {
|
|
|
3202
3478
|
function isProtocolCompatible(args) {
|
|
3203
3479
|
return args.remoteVersion >= args.localMin && args.localVersion >= args.remoteMin;
|
|
3204
3480
|
}
|
|
3481
|
+
function isDaemonVersionStale(daemonVersion, clientVersion) {
|
|
3482
|
+
if (!daemonVersion)
|
|
3483
|
+
return false;
|
|
3484
|
+
return daemonVersion !== clientVersion;
|
|
3485
|
+
}
|
|
3205
3486
|
function serializeTask(task) {
|
|
3206
3487
|
return {
|
|
3207
3488
|
id: task.id,
|
|
@@ -3225,13 +3506,13 @@ function frameToLine(frame) {
|
|
|
3225
3506
|
}
|
|
3226
3507
|
var DAEMON_PROTOCOL_VERSION = 2, MIN_COMPATIBLE_PROTOCOL_VERSION = 2, CHANNEL_NAMES;
|
|
3227
3508
|
var init_protocol = __esm(() => {
|
|
3228
|
-
CHANNEL_NAMES = ["task.snapshot", "active-task", "update"];
|
|
3509
|
+
CHANNEL_NAMES = ["task.snapshot", "active-task", "update", "engine-state"];
|
|
3229
3510
|
});
|
|
3230
3511
|
|
|
3231
3512
|
// src/daemon/paths.ts
|
|
3232
3513
|
import { createHash as createHash2 } from "crypto";
|
|
3233
3514
|
import { homedir as homedir3, tmpdir } from "os";
|
|
3234
|
-
import { join as
|
|
3515
|
+
import { join as join4 } from "path";
|
|
3235
3516
|
function shortHomeTag(homeDir2) {
|
|
3236
3517
|
return createHash2("sha1").update(homeDir2).digest("hex").slice(0, 8);
|
|
3237
3518
|
}
|
|
@@ -3240,7 +3521,7 @@ function fitSocketPath(naturalPath, homeDir2, role, pidTag) {
|
|
|
3240
3521
|
return naturalPath;
|
|
3241
3522
|
const tag = shortHomeTag(homeDir2);
|
|
3242
3523
|
const suffix = pidTag === undefined ? "" : `-${pidTag}`;
|
|
3243
|
-
const fallback =
|
|
3524
|
+
const fallback = join4(tmpdir(), `kobe-${tag}-${role}${suffix}.sock`);
|
|
3244
3525
|
if (Buffer.byteLength(fallback, "utf8") <= SOCKET_PATH_SAFETY_LIMIT)
|
|
3245
3526
|
return fallback;
|
|
3246
3527
|
throw new Error(`kobe socket path exceeds ${SOCKET_PATH_SAFETY_LIMIT} bytes even after fallback: ${fallback}`);
|
|
@@ -3251,33 +3532,33 @@ function defaultDaemonSocketPath(homeDir2) {
|
|
|
3251
3532
|
return override;
|
|
3252
3533
|
const explicit = homeDir2 ?? process.env.KOBE_HOME_DIR;
|
|
3253
3534
|
if (explicit && explicit.length > 0) {
|
|
3254
|
-
return fitSocketPath(
|
|
3535
|
+
return fitSocketPath(join4(explicit, ".kobe", "daemon.sock"), explicit, "daemon");
|
|
3255
3536
|
}
|
|
3256
3537
|
const runtimeDir = process.env.XDG_RUNTIME_DIR;
|
|
3257
3538
|
if (runtimeDir && runtimeDir.length > 0) {
|
|
3258
|
-
return fitSocketPath(
|
|
3539
|
+
return fitSocketPath(join4(runtimeDir, "kobe.sock"), runtimeDir, "daemon");
|
|
3259
3540
|
}
|
|
3260
3541
|
const home = homedir3();
|
|
3261
|
-
return fitSocketPath(
|
|
3542
|
+
return fitSocketPath(join4(home, ".kobe", "daemon.sock"), home, "daemon");
|
|
3262
3543
|
}
|
|
3263
3544
|
function defaultDaemonPidPath(homeDir2 = process.env.KOBE_HOME_DIR ?? homedir3()) {
|
|
3264
3545
|
const override = process.env.KOBE_DAEMON_PID_PATH;
|
|
3265
3546
|
if (override && override.length > 0)
|
|
3266
3547
|
return override;
|
|
3267
|
-
return
|
|
3548
|
+
return join4(homeDir2, ".kobe", "daemon.pid");
|
|
3268
3549
|
}
|
|
3269
3550
|
function defaultDaemonLogPath(homeDir2 = process.env.KOBE_HOME_DIR ?? homedir3()) {
|
|
3270
|
-
return
|
|
3551
|
+
return join4(homeDir2, ".kobe", "daemon.log");
|
|
3271
3552
|
}
|
|
3272
3553
|
function defaultClientLogPath(homeDir2 = process.env.KOBE_HOME_DIR ?? homedir3()) {
|
|
3273
|
-
return
|
|
3554
|
+
return join4(homeDir2, ".kobe", "client.log");
|
|
3274
3555
|
}
|
|
3275
3556
|
var SOCKET_PATH_SAFETY_LIMIT = 100;
|
|
3276
3557
|
var init_paths2 = () => {};
|
|
3277
3558
|
|
|
3278
3559
|
// src/client/client-log.ts
|
|
3279
|
-
import { appendFile, mkdir as
|
|
3280
|
-
import { dirname as
|
|
3560
|
+
import { appendFile as appendFile2, mkdir as mkdir3 } from "fs/promises";
|
|
3561
|
+
import { dirname as dirname4 } from "path";
|
|
3281
3562
|
function setClientLogContext(ctx) {
|
|
3282
3563
|
context = ctx;
|
|
3283
3564
|
}
|
|
@@ -3309,11 +3590,11 @@ function append(line) {
|
|
|
3309
3590
|
const path3 = defaultClientLogPath();
|
|
3310
3591
|
writeChain = writeChain.then(async () => {
|
|
3311
3592
|
try {
|
|
3312
|
-
await
|
|
3593
|
+
await appendFile2(path3, line);
|
|
3313
3594
|
} catch (err) {
|
|
3314
3595
|
if (err?.code === "ENOENT") {
|
|
3315
|
-
await
|
|
3316
|
-
await
|
|
3596
|
+
await mkdir3(dirname4(path3), { recursive: true });
|
|
3597
|
+
await appendFile2(path3, line);
|
|
3317
3598
|
} else {
|
|
3318
3599
|
throw err;
|
|
3319
3600
|
}
|
|
@@ -3515,6 +3796,37 @@ var init_client = __esm(() => {
|
|
|
3515
3796
|
init_client_log();
|
|
3516
3797
|
});
|
|
3517
3798
|
|
|
3799
|
+
// src/engine/hook-events.ts
|
|
3800
|
+
function isEngineActivityKind(v) {
|
|
3801
|
+
return ENGINE_ACTIVITY_KINDS.includes(v);
|
|
3802
|
+
}
|
|
3803
|
+
function reduceActivity(_prev, kind, detail) {
|
|
3804
|
+
switch (kind) {
|
|
3805
|
+
case "session-start":
|
|
3806
|
+
case "session-end":
|
|
3807
|
+
return "idle";
|
|
3808
|
+
case "turn-start":
|
|
3809
|
+
return "running";
|
|
3810
|
+
case "turn-complete":
|
|
3811
|
+
return "turn_complete";
|
|
3812
|
+
case "turn-failed":
|
|
3813
|
+
return detail?.failure === "rate_limit" || detail?.failure === "billing" ? "rate_limited" : "error";
|
|
3814
|
+
case "awaiting-input":
|
|
3815
|
+
return detail?.waiting === "permission" ? "permission_needed" : "running";
|
|
3816
|
+
}
|
|
3817
|
+
}
|
|
3818
|
+
var ENGINE_ACTIVITY_KINDS;
|
|
3819
|
+
var init_hook_events = __esm(() => {
|
|
3820
|
+
ENGINE_ACTIVITY_KINDS = [
|
|
3821
|
+
"session-start",
|
|
3822
|
+
"turn-start",
|
|
3823
|
+
"turn-complete",
|
|
3824
|
+
"turn-failed",
|
|
3825
|
+
"awaiting-input",
|
|
3826
|
+
"session-end"
|
|
3827
|
+
];
|
|
3828
|
+
});
|
|
3829
|
+
|
|
3518
3830
|
// src/engine/claude-code-local/normalize.ts
|
|
3519
3831
|
function normalizeClaudeContent(content) {
|
|
3520
3832
|
if (typeof content === "string") {
|
|
@@ -3562,7 +3874,7 @@ function normalizeClaudeContent(content) {
|
|
|
3562
3874
|
}
|
|
3563
3875
|
|
|
3564
3876
|
// src/engine/claude-code-local/history.ts
|
|
3565
|
-
import { appendFile as
|
|
3877
|
+
import { appendFile as appendFile3, mkdir as mkdir4, readFile as readFile3, readdir, stat, unlink as unlink2, writeFile as writeFile3 } from "fs/promises";
|
|
3566
3878
|
import { homedir as homedir4 } from "os";
|
|
3567
3879
|
import path3 from "path";
|
|
3568
3880
|
function encodeCwd(cwd) {
|
|
@@ -3633,7 +3945,7 @@ function parseJsonl(raw, sessionId) {
|
|
|
3633
3945
|
} catch {
|
|
3634
3946
|
continue;
|
|
3635
3947
|
}
|
|
3636
|
-
if (!
|
|
3948
|
+
if (!isObject2(parsed))
|
|
3637
3949
|
continue;
|
|
3638
3950
|
const msg = extractMessage(parsed, sessionId);
|
|
3639
3951
|
if (msg)
|
|
@@ -3642,7 +3954,7 @@ function parseJsonl(raw, sessionId) {
|
|
|
3642
3954
|
return out;
|
|
3643
3955
|
}
|
|
3644
3956
|
function extractMessage(record, fallbackSessionId) {
|
|
3645
|
-
const inner =
|
|
3957
|
+
const inner = isObject2(record.message) ? record.message : record;
|
|
3646
3958
|
const role = inner.role;
|
|
3647
3959
|
if (role !== "user" && role !== "assistant" && role !== "system")
|
|
3648
3960
|
return null;
|
|
@@ -3655,7 +3967,7 @@ function extractMessage(record, fallbackSessionId) {
|
|
|
3655
3967
|
return usage ? { role, blocks, timestamp: ts, sessionId: sid, usage } : { role, blocks, timestamp: ts, sessionId: sid };
|
|
3656
3968
|
}
|
|
3657
3969
|
function extractUsage(v) {
|
|
3658
|
-
if (!
|
|
3970
|
+
if (!isObject2(v))
|
|
3659
3971
|
return;
|
|
3660
3972
|
const inTok = typeof v.input_tokens === "number" ? v.input_tokens : undefined;
|
|
3661
3973
|
const outTok = typeof v.output_tokens === "number" ? v.output_tokens : undefined;
|
|
@@ -3670,7 +3982,7 @@ function extractUsage(v) {
|
|
|
3670
3982
|
...cacheCreate !== undefined ? { cache_creation_input_tokens: cacheCreate } : {}
|
|
3671
3983
|
};
|
|
3672
3984
|
}
|
|
3673
|
-
function
|
|
3985
|
+
function isObject2(v) {
|
|
3674
3986
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
3675
3987
|
}
|
|
3676
3988
|
var defaultDeps;
|
|
@@ -3687,7 +3999,7 @@ var init_history = __esm(() => {
|
|
|
3687
3999
|
}
|
|
3688
4000
|
},
|
|
3689
4001
|
async readFile(p) {
|
|
3690
|
-
return await
|
|
4002
|
+
return await readFile3(p, "utf8");
|
|
3691
4003
|
},
|
|
3692
4004
|
async pathExists(p) {
|
|
3693
4005
|
try {
|
|
@@ -3714,7 +4026,7 @@ function normalizeCodexContent(raw) {
|
|
|
3714
4026
|
blocks.push({ type: "text", text: item });
|
|
3715
4027
|
continue;
|
|
3716
4028
|
}
|
|
3717
|
-
if (!
|
|
4029
|
+
if (!isObject3(item))
|
|
3718
4030
|
continue;
|
|
3719
4031
|
const t = typeof item.type === "string" ? item.type : undefined;
|
|
3720
4032
|
if (t === "input_text" || t === "output_text") {
|
|
@@ -3728,7 +4040,7 @@ function normalizeCodexContent(raw) {
|
|
|
3728
4040
|
}
|
|
3729
4041
|
return blocks;
|
|
3730
4042
|
}
|
|
3731
|
-
function
|
|
4043
|
+
function isObject3(v) {
|
|
3732
4044
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
3733
4045
|
}
|
|
3734
4046
|
|
|
@@ -3778,7 +4090,7 @@ function validPositive(v) {
|
|
|
3778
4090
|
}
|
|
3779
4091
|
|
|
3780
4092
|
// src/engine/codex-local/history.ts
|
|
3781
|
-
import { readFile as
|
|
4093
|
+
import { readFile as readFile4, readdir as readdir2, stat as stat2, unlink as unlink3 } from "fs/promises";
|
|
3782
4094
|
import { homedir as homedir5 } from "os";
|
|
3783
4095
|
import path4 from "path";
|
|
3784
4096
|
async function listRolloutFiles(deps = defaultDeps2) {
|
|
@@ -3913,11 +4225,11 @@ function parseJsonl2(raw, sessionId) {
|
|
|
3913
4225
|
} catch {
|
|
3914
4226
|
continue;
|
|
3915
4227
|
}
|
|
3916
|
-
if (!
|
|
4228
|
+
if (!isObject4(parsed))
|
|
3917
4229
|
continue;
|
|
3918
4230
|
if (parsed.type !== "response_item")
|
|
3919
4231
|
continue;
|
|
3920
|
-
const payload =
|
|
4232
|
+
const payload = isObject4(parsed.payload) ? parsed.payload : undefined;
|
|
3921
4233
|
if (!payload)
|
|
3922
4234
|
continue;
|
|
3923
4235
|
const ts = typeof parsed.timestamp === "string" ? parsed.timestamp : new Date().toISOString();
|
|
@@ -4034,7 +4346,7 @@ function textFromReasoningValue(value) {
|
|
|
4034
4346
|
parts.push(entry);
|
|
4035
4347
|
continue;
|
|
4036
4348
|
}
|
|
4037
|
-
if (!
|
|
4349
|
+
if (!isObject4(entry))
|
|
4038
4350
|
continue;
|
|
4039
4351
|
const text = typeof entry.text === "string" ? entry.text : "";
|
|
4040
4352
|
if (text.length > 0)
|
|
@@ -4076,14 +4388,14 @@ function deriveCodexUsageMetrics(raw) {
|
|
|
4076
4388
|
} catch {
|
|
4077
4389
|
continue;
|
|
4078
4390
|
}
|
|
4079
|
-
if (!
|
|
4391
|
+
if (!isObject4(parsed))
|
|
4080
4392
|
continue;
|
|
4081
4393
|
const timestampMs = typeof parsed.timestamp === "string" ? parseTimestampMs(parsed.timestamp) : null;
|
|
4082
4394
|
if (parsed.type === "response_item")
|
|
4083
4395
|
continue;
|
|
4084
4396
|
if (parsed.type !== "turn.completed")
|
|
4085
4397
|
continue;
|
|
4086
|
-
const usage =
|
|
4398
|
+
const usage = isObject4(parsed.usage) ? parsed.usage : undefined;
|
|
4087
4399
|
if (!usage)
|
|
4088
4400
|
continue;
|
|
4089
4401
|
const snapshot = codexUsageToSnapshot(usage);
|
|
@@ -4102,7 +4414,7 @@ function parseTimestampMs(value) {
|
|
|
4102
4414
|
const ms = new Date(value).getTime();
|
|
4103
4415
|
return Number.isFinite(ms) ? ms : null;
|
|
4104
4416
|
}
|
|
4105
|
-
function
|
|
4417
|
+
function isObject4(v) {
|
|
4106
4418
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
4107
4419
|
}
|
|
4108
4420
|
var defaultDeps2, UUID_AT_END, MAX_WORKTREE_SCAN = 200, MAX_MTIME_SCAN = 12;
|
|
@@ -4120,7 +4432,7 @@ var init_history2 = __esm(() => {
|
|
|
4120
4432
|
}
|
|
4121
4433
|
},
|
|
4122
4434
|
async readFile(p) {
|
|
4123
|
-
return await
|
|
4435
|
+
return await readFile4(p, "utf8");
|
|
4124
4436
|
},
|
|
4125
4437
|
stat: stat2
|
|
4126
4438
|
};
|
|
@@ -4129,16 +4441,16 @@ var init_history2 = __esm(() => {
|
|
|
4129
4441
|
|
|
4130
4442
|
// src/engine/copilot-local/usage.ts
|
|
4131
4443
|
function copilotUsageToSnapshot(value) {
|
|
4132
|
-
if (!
|
|
4444
|
+
if (!isObject5(value))
|
|
4133
4445
|
return;
|
|
4134
|
-
const modelMetrics =
|
|
4446
|
+
const modelMetrics = isObject5(value.modelMetrics) ? value.modelMetrics : undefined;
|
|
4135
4447
|
if (!modelMetrics)
|
|
4136
4448
|
return;
|
|
4137
4449
|
let input = 0;
|
|
4138
4450
|
let output = 0;
|
|
4139
4451
|
let cached = 0;
|
|
4140
4452
|
for (const metrics of Object.values(modelMetrics)) {
|
|
4141
|
-
if (!
|
|
4453
|
+
if (!isObject5(metrics) || !isObject5(metrics.usage))
|
|
4142
4454
|
continue;
|
|
4143
4455
|
input += numberOr2(metrics.usage.inputTokens, 0);
|
|
4144
4456
|
output += numberOr2(metrics.usage.outputTokens, 0);
|
|
@@ -4154,7 +4466,7 @@ function copilotUsageToSnapshot(value) {
|
|
|
4154
4466
|
...context2 > 0 ? { context_tokens: context2 } : {}
|
|
4155
4467
|
};
|
|
4156
4468
|
}
|
|
4157
|
-
function
|
|
4469
|
+
function isObject5(v) {
|
|
4158
4470
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
4159
4471
|
}
|
|
4160
4472
|
function numberOr2(value, fallback) {
|
|
@@ -4162,7 +4474,7 @@ function numberOr2(value, fallback) {
|
|
|
4162
4474
|
}
|
|
4163
4475
|
|
|
4164
4476
|
// src/engine/copilot-local/history.ts
|
|
4165
|
-
import { readFile as
|
|
4477
|
+
import { readFile as readFile5, readdir as readdir3, rm, stat as stat3 } from "fs/promises";
|
|
4166
4478
|
import { homedir as homedir6 } from "os";
|
|
4167
4479
|
import path5 from "path";
|
|
4168
4480
|
async function listSessionDirs(deps = defaultDeps3) {
|
|
@@ -4259,10 +4571,10 @@ function parseEvents(raw, fallbackSessionId) {
|
|
|
4259
4571
|
} catch {
|
|
4260
4572
|
continue;
|
|
4261
4573
|
}
|
|
4262
|
-
if (!
|
|
4574
|
+
if (!isObject6(record) || typeof record.type !== "string")
|
|
4263
4575
|
continue;
|
|
4264
4576
|
const timestamp = typeof record.timestamp === "string" ? record.timestamp : new Date().toISOString();
|
|
4265
|
-
const data =
|
|
4577
|
+
const data = isObject6(record.data) ? record.data : {};
|
|
4266
4578
|
if (record.type === "session.start") {
|
|
4267
4579
|
const sid = typeof data.sessionId === "string" ? data.sessionId : undefined;
|
|
4268
4580
|
if (sid)
|
|
@@ -4285,7 +4597,7 @@ function parseEvents(raw, fallbackSessionId) {
|
|
|
4285
4597
|
blocks.push({ type: "text", text });
|
|
4286
4598
|
const toolRequests = Array.isArray(data.toolRequests) ? data.toolRequests : [];
|
|
4287
4599
|
for (const req of toolRequests) {
|
|
4288
|
-
if (!
|
|
4600
|
+
if (!isObject6(req))
|
|
4289
4601
|
continue;
|
|
4290
4602
|
const callId = typeof req.id === "string" ? req.id : typeof req.toolCallId === "string" ? req.toolCallId : "tool";
|
|
4291
4603
|
const name = typeof req.name === "string" ? req.name : typeof req.toolName === "string" ? req.toolName : "tool";
|
|
@@ -4322,7 +4634,7 @@ function parseEvents(raw, fallbackSessionId) {
|
|
|
4322
4634
|
}
|
|
4323
4635
|
return { messages, usageMetrics, firstUserMessage };
|
|
4324
4636
|
}
|
|
4325
|
-
function
|
|
4637
|
+
function isObject6(v) {
|
|
4326
4638
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
4327
4639
|
}
|
|
4328
4640
|
var defaultDeps3, PREVIEW_CHAR_CAP = 200;
|
|
@@ -4342,7 +4654,7 @@ var init_history3 = __esm(() => {
|
|
|
4342
4654
|
}
|
|
4343
4655
|
},
|
|
4344
4656
|
async readFile(p) {
|
|
4345
|
-
return await
|
|
4657
|
+
return await readFile5(p, "utf8");
|
|
4346
4658
|
},
|
|
4347
4659
|
stat: stat3,
|
|
4348
4660
|
async rm(p) {
|
|
@@ -4404,90 +4716,6 @@ var init_auto_title = __esm(() => {
|
|
|
4404
4716
|
init_history3();
|
|
4405
4717
|
});
|
|
4406
4718
|
|
|
4407
|
-
// src/cli/invocation.ts
|
|
4408
|
-
import { fileURLToPath } from "url";
|
|
4409
|
-
function kobeCliInvocation() {
|
|
4410
|
-
const isBuilt = import.meta.url.endsWith(".js");
|
|
4411
|
-
if (isBuilt)
|
|
4412
|
-
return ["kobe"];
|
|
4413
|
-
const entry = fileURLToPath(new URL("./index.ts", import.meta.url));
|
|
4414
|
-
const preload = fileURLToPath(import.meta.resolve("@opentui/solid/preload"));
|
|
4415
|
-
return [process.execPath, "--preload", preload, "--conditions=browser", entry];
|
|
4416
|
-
}
|
|
4417
|
-
var init_invocation = () => {};
|
|
4418
|
-
|
|
4419
|
-
// src/tmux/session-layout.ts
|
|
4420
|
-
function shellQuote(s) {
|
|
4421
|
-
return `'${s.replace(/'/g, "'\\''")}'`;
|
|
4422
|
-
}
|
|
4423
|
-
function shellQuoteArgv(argv) {
|
|
4424
|
-
return argv.map(shellQuote).join(" ");
|
|
4425
|
-
}
|
|
4426
|
-
function keepAlive(cmd) {
|
|
4427
|
-
return `${cmd}; exec "\${SHELL:-/bin/sh}"`;
|
|
4428
|
-
}
|
|
4429
|
-
function shQuote(s) {
|
|
4430
|
-
return `'${s.replace(/'/g, "'\\''")}'`;
|
|
4431
|
-
}
|
|
4432
|
-
function homeWelcomeCommand() {
|
|
4433
|
-
const msg = "\\n No task selected\\n\\n Press N to create a task, or pick one on the left.\\n\\n";
|
|
4434
|
-
return `clear; printf ${shQuote(msg)}; exec "\${SHELL:-/bin/sh}"`;
|
|
4435
|
-
}
|
|
4436
|
-
function engineLaunchLine(engineCmd, init) {
|
|
4437
|
-
const tail = keepAlive(engineCmd);
|
|
4438
|
-
const script = init?.initScript?.trim();
|
|
4439
|
-
if (!script)
|
|
4440
|
-
return tail;
|
|
4441
|
-
const group = ["{", script, "}"].join(`
|
|
4442
|
-
`);
|
|
4443
|
-
if (init?.markerPath) {
|
|
4444
|
-
const marker = shQuote(init.markerPath);
|
|
4445
|
-
const markerDir = shQuote(markerDirOf(init.markerPath));
|
|
4446
|
-
return [
|
|
4447
|
-
`if [ ! -f ${marker} ]; then`,
|
|
4448
|
-
group,
|
|
4449
|
-
`if [ $? -eq 0 ]; then mkdir -p ${markerDir} && : > ${marker}; fi`,
|
|
4450
|
-
"fi",
|
|
4451
|
-
tail
|
|
4452
|
-
].join(`
|
|
4453
|
-
`);
|
|
4454
|
-
}
|
|
4455
|
-
return [group, tail].join(`
|
|
4456
|
-
`);
|
|
4457
|
-
}
|
|
4458
|
-
function markerDirOf(p) {
|
|
4459
|
-
const i = p.lastIndexOf("/");
|
|
4460
|
-
return i <= 0 ? "." : p.slice(0, i);
|
|
4461
|
-
}
|
|
4462
|
-
function fallbackOpsScript(cwd) {
|
|
4463
|
-
return `cd ${shellQuote(cwd)} && while :; do clear; printf "\\033[1m# %s\\033[0m\\n\\n" ${shellQuote(cwd)}; git status --short --branch 2>/dev/null | sed 's/^/ /' || true; printf "\\n"; if command -v lsd >/dev/null 2>&1; then lsd --tree --git -I node_modules -I .git --depth 2 .; elif command -v eza >/dev/null 2>&1; then eza --tree --git -L 2 -I 'node_modules|.git' .; elif command -v tree >/dev/null 2>&1; then tree -L 2 -I 'node_modules|.git'; else ls -la; fi; sleep 2; done`;
|
|
4464
|
-
}
|
|
4465
|
-
function previewWindowCommand(args) {
|
|
4466
|
-
const wt = shellQuote(args.worktree);
|
|
4467
|
-
const file = shellQuote(args.relPath);
|
|
4468
|
-
const inv = args.cliInvocation.map(shellQuote).join(" ");
|
|
4469
|
-
const fallback = `cd ${wt} && if ! git diff --quiet HEAD -- ${file} 2>/dev/null; then ` + `git diff HEAD -- ${file} | { delta --paging=always 2>/dev/null || less -R; }; ` + `else bat --style=plain --paging=always ${file} 2>/dev/null || \${PAGER:-less} ${file} 2>/dev/null || cat ${file}; fi`;
|
|
4470
|
-
return `${inv} ops --worktree ${wt} --preview ${file} || { ${fallback}; }`;
|
|
4471
|
-
}
|
|
4472
|
-
function updatePageCommand(args) {
|
|
4473
|
-
return `${shellQuoteArgv([...args.cliInvocation, "update-page"])}`;
|
|
4474
|
-
}
|
|
4475
|
-
function tasksPaneCommand(cliInvocation, opts = {}) {
|
|
4476
|
-
const argv = [...cliInvocation, "tasks"];
|
|
4477
|
-
if (opts.initialTaskId)
|
|
4478
|
-
argv.push("--initial-task-id", opts.initialTaskId);
|
|
4479
|
-
return shellQuoteArgv(argv);
|
|
4480
|
-
}
|
|
4481
|
-
function opsPaneCommand(args) {
|
|
4482
|
-
if (args.taskId && args.claudePaneId) {
|
|
4483
|
-
const inv = args.cliInvocation.map(shellQuote).join(" ");
|
|
4484
|
-
const vendorFlag = args.vendor ? ` --vendor ${shellQuote(args.vendor)}` : "";
|
|
4485
|
-
return `KOBE_FILETREE_WATCH=1 ${inv} ops --task-id ${shellQuote(args.taskId)} --worktree ${shellQuote(args.cwd)} ` + `--target-pane ${shellQuote(args.claudePaneId)}${vendorFlag} || { ${fallbackOpsScript(args.cwd)}; }`;
|
|
4486
|
-
}
|
|
4487
|
-
return fallbackOpsScript(args.cwd);
|
|
4488
|
-
}
|
|
4489
|
-
var TASKS_PANE_WIDTH = 32, CLAUDE_PANE_PERCENT = 60, OPS_PANE_PERCENT = 50;
|
|
4490
|
-
|
|
4491
4719
|
// src/tmux/client.ts
|
|
4492
4720
|
var exports_client = {};
|
|
4493
4721
|
__export(exports_client, {
|
|
@@ -4967,9 +5195,9 @@ class DaemonEventBus {
|
|
|
4967
5195
|
}
|
|
4968
5196
|
|
|
4969
5197
|
// src/daemon/server.ts
|
|
4970
|
-
import { mkdir as
|
|
5198
|
+
import { mkdir as mkdir5, readFile as readFile6, unlink as unlink4, writeFile as writeFile4 } from "fs/promises";
|
|
4971
5199
|
import { createServer } from "net";
|
|
4972
|
-
import { dirname as
|
|
5200
|
+
import { dirname as dirname5 } from "path";
|
|
4973
5201
|
function resolveIdleGraceMs() {
|
|
4974
5202
|
const raw = process.env.KOBE_DAEMON_IDLE_GRACE_MS;
|
|
4975
5203
|
if (raw === undefined)
|
|
@@ -4977,6 +5205,13 @@ function resolveIdleGraceMs() {
|
|
|
4977
5205
|
const n = Number(raw);
|
|
4978
5206
|
return Number.isFinite(n) && n >= 0 ? n : DEFAULT_IDLE_GRACE_MS;
|
|
4979
5207
|
}
|
|
5208
|
+
function resolveEngineStateTtlMs() {
|
|
5209
|
+
const raw = process.env.KOBE_ENGINE_STATE_TTL_MS;
|
|
5210
|
+
if (raw === undefined)
|
|
5211
|
+
return DEFAULT_ENGINE_STATE_TTL_MS;
|
|
5212
|
+
const n = Number(raw);
|
|
5213
|
+
return Number.isFinite(n) && n > 0 ? n : DEFAULT_ENGINE_STATE_TTL_MS;
|
|
5214
|
+
}
|
|
4980
5215
|
async function startDaemonServer(orch, options = {}) {
|
|
4981
5216
|
const socketPath = options.socketPath ?? defaultDaemonSocketPath(options.homeDir);
|
|
4982
5217
|
const pidPath = options.pidPath ?? defaultDaemonPidPath(options.homeDir);
|
|
@@ -5017,8 +5252,30 @@ async function startDaemonServer(orch, options = {}) {
|
|
|
5017
5252
|
bus.onPublish((event) => {
|
|
5018
5253
|
broadcast(clients, { type: "event", name: event.channel, payload: event.payload });
|
|
5019
5254
|
});
|
|
5020
|
-
|
|
5021
|
-
|
|
5255
|
+
const activity = new Map;
|
|
5256
|
+
const ACTIVITY_STALE_MS = resolveEngineStateTtlMs();
|
|
5257
|
+
function reportActivity(taskId, kind, detail) {
|
|
5258
|
+
const prev = activity.get(taskId);
|
|
5259
|
+
if (prev?.lapse)
|
|
5260
|
+
clearTimeout(prev.lapse);
|
|
5261
|
+
const state = reduceActivity(prev?.state, kind, detail);
|
|
5262
|
+
const at = Date.now();
|
|
5263
|
+
const entry = { state, detail, at };
|
|
5264
|
+
if (state !== "idle") {
|
|
5265
|
+
entry.lapse = setTimeout(() => {
|
|
5266
|
+
const cur = activity.get(taskId);
|
|
5267
|
+
if (cur && cur.at === at) {
|
|
5268
|
+
activity.set(taskId, { state: "idle", at: Date.now() });
|
|
5269
|
+
bus.publish("engine-state", { taskId, state: "idle", at: Date.now() });
|
|
5270
|
+
}
|
|
5271
|
+
}, ACTIVITY_STALE_MS);
|
|
5272
|
+
entry.lapse.unref?.();
|
|
5273
|
+
}
|
|
5274
|
+
activity.set(taskId, entry);
|
|
5275
|
+
bus.publish("engine-state", { taskId, state, ...detail ? { detail } : {}, at });
|
|
5276
|
+
}
|
|
5277
|
+
await mkdir5(dirname5(socketPath), { recursive: true });
|
|
5278
|
+
await mkdir5(dirname5(pidPath), { recursive: true });
|
|
5022
5279
|
await unlink4(socketPath).catch(() => {});
|
|
5023
5280
|
const server = createServer((socket) => {
|
|
5024
5281
|
const client = {
|
|
@@ -5088,7 +5345,7 @@ async function startDaemonServer(orch, options = {}) {
|
|
|
5088
5345
|
resolve2();
|
|
5089
5346
|
});
|
|
5090
5347
|
});
|
|
5091
|
-
await
|
|
5348
|
+
await writeFile4(pidPath, `${process.pid}
|
|
5092
5349
|
`, "utf8");
|
|
5093
5350
|
async function stopSoon() {
|
|
5094
5351
|
if (stopping)
|
|
@@ -5117,6 +5374,7 @@ async function startDaemonServer(orch, options = {}) {
|
|
|
5117
5374
|
return {
|
|
5118
5375
|
protocolVersion: DAEMON_PROTOCOL_VERSION,
|
|
5119
5376
|
minProtocolVersion: MIN_COMPATIBLE_PROTOCOL_VERSION,
|
|
5377
|
+
kobeVersion: CURRENT_VERSION,
|
|
5120
5378
|
capabilities: [...CHANNEL_NAMES],
|
|
5121
5379
|
daemonPid: process.pid,
|
|
5122
5380
|
clientId: client.id,
|
|
@@ -5126,6 +5384,7 @@ async function startDaemonServer(orch, options = {}) {
|
|
|
5126
5384
|
case "daemon.status":
|
|
5127
5385
|
return {
|
|
5128
5386
|
daemonPid: process.pid,
|
|
5387
|
+
kobeVersion: CURRENT_VERSION,
|
|
5129
5388
|
uptimeMs: Date.now() - startedAt.getTime(),
|
|
5130
5389
|
startedAt: startedAt.toISOString(),
|
|
5131
5390
|
attachedClients: guiCount(),
|
|
@@ -5181,6 +5440,12 @@ async function startDaemonServer(orch, options = {}) {
|
|
|
5181
5440
|
case "task.delete": {
|
|
5182
5441
|
const taskId = requireString(payload, "taskId");
|
|
5183
5442
|
await orch.deleteTask(taskId, { force: optionalBoolean(payload, "force") });
|
|
5443
|
+
const gone = activity.get(taskId);
|
|
5444
|
+
if (gone?.lapse)
|
|
5445
|
+
clearTimeout(gone.lapse);
|
|
5446
|
+
activity.delete(taskId);
|
|
5447
|
+
if (gone)
|
|
5448
|
+
bus.publish("engine-state", { taskId, state: "idle", at: Date.now() });
|
|
5184
5449
|
return {};
|
|
5185
5450
|
}
|
|
5186
5451
|
case "task.pin": {
|
|
@@ -5218,7 +5483,8 @@ async function startDaemonServer(orch, options = {}) {
|
|
|
5218
5483
|
worktreePath: requireString(payload, "worktreePath"),
|
|
5219
5484
|
branch: optionalString(payload, "branch"),
|
|
5220
5485
|
vendor: optionalVendor(payload, "vendor"),
|
|
5221
|
-
title: optionalString(payload, "title")
|
|
5486
|
+
title: optionalString(payload, "title"),
|
|
5487
|
+
ifExists: optionalString(payload, "ifExists") === "return" ? "return" : "error"
|
|
5222
5488
|
});
|
|
5223
5489
|
return { task: serializeTask(task) };
|
|
5224
5490
|
}
|
|
@@ -5226,6 +5492,15 @@ async function startDaemonServer(orch, options = {}) {
|
|
|
5226
5492
|
bus.publish("active-task", { taskId: optionalString(payload, "taskId") ?? null });
|
|
5227
5493
|
return {};
|
|
5228
5494
|
}
|
|
5495
|
+
case "engine.reportEvent": {
|
|
5496
|
+
const taskId = requireString(payload, "taskId");
|
|
5497
|
+
const kind = requireString(payload, "kind");
|
|
5498
|
+
if (!isEngineActivityKind(kind))
|
|
5499
|
+
throw new Error(`unknown engine event kind: ${kind}`);
|
|
5500
|
+
const detail = optionalActivityDetail(payload);
|
|
5501
|
+
reportActivity(taskId, kind, detail);
|
|
5502
|
+
return {};
|
|
5503
|
+
}
|
|
5229
5504
|
case "subscribe": {
|
|
5230
5505
|
client.subscribed = true;
|
|
5231
5506
|
const role = payload.role === "gui" ? "gui" : "pane";
|
|
@@ -5236,6 +5511,15 @@ async function startDaemonServer(orch, options = {}) {
|
|
|
5236
5511
|
for (const event of bus.snapshot()) {
|
|
5237
5512
|
writeFrame(client, { type: "event", name: event.channel, payload: event.payload });
|
|
5238
5513
|
}
|
|
5514
|
+
for (const [taskId, entry] of activity) {
|
|
5515
|
+
if (entry.state === "idle")
|
|
5516
|
+
continue;
|
|
5517
|
+
writeFrame(client, {
|
|
5518
|
+
type: "event",
|
|
5519
|
+
name: "engine-state",
|
|
5520
|
+
payload: { taskId, state: entry.state, ...entry.detail ? { detail: entry.detail } : {}, at: entry.at }
|
|
5521
|
+
});
|
|
5522
|
+
}
|
|
5239
5523
|
return {};
|
|
5240
5524
|
}
|
|
5241
5525
|
default:
|
|
@@ -5286,7 +5570,7 @@ async function startDaemonServer(orch, options = {}) {
|
|
|
5286
5570
|
}
|
|
5287
5571
|
async function readPidFile(pidPath) {
|
|
5288
5572
|
try {
|
|
5289
|
-
const raw = await
|
|
5573
|
+
const raw = await readFile6(pidPath, "utf8");
|
|
5290
5574
|
const pid = Number(raw.trim());
|
|
5291
5575
|
return Number.isFinite(pid) ? pid : null;
|
|
5292
5576
|
} catch {
|
|
@@ -5337,13 +5621,29 @@ function optionalVendor(payload, key) {
|
|
|
5337
5621
|
}
|
|
5338
5622
|
return value;
|
|
5339
5623
|
}
|
|
5340
|
-
|
|
5624
|
+
function optionalActivityDetail(payload) {
|
|
5625
|
+
const raw = payload.detail;
|
|
5626
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
5627
|
+
return;
|
|
5628
|
+
const d = raw;
|
|
5629
|
+
const out = {};
|
|
5630
|
+
if (d.failure === "rate_limit" || d.failure === "billing" || d.failure === "other")
|
|
5631
|
+
out.failure = d.failure;
|
|
5632
|
+
if (d.waiting === "permission" || d.waiting === "input")
|
|
5633
|
+
out.waiting = d.waiting;
|
|
5634
|
+
if (typeof d.note === "string")
|
|
5635
|
+
out.note = d.note;
|
|
5636
|
+
return Object.keys(out).length > 0 ? out : undefined;
|
|
5637
|
+
}
|
|
5638
|
+
var DEFAULT_UPDATE_POLL_MS, DEFAULT_IDLE_GRACE_MS = 3000, DEFAULT_ENGINE_STATE_TTL_MS;
|
|
5341
5639
|
var init_server = __esm(() => {
|
|
5640
|
+
init_hook_events();
|
|
5342
5641
|
init_version();
|
|
5343
5642
|
init_auto_title_poller();
|
|
5344
5643
|
init_paths2();
|
|
5345
5644
|
init_protocol();
|
|
5346
5645
|
DEFAULT_UPDATE_POLL_MS = 6 * 60 * 60 * 1000;
|
|
5646
|
+
DEFAULT_ENGINE_STATE_TTL_MS = 10 * 60 * 1000;
|
|
5347
5647
|
});
|
|
5348
5648
|
|
|
5349
5649
|
// src/daemon/lifecycle.ts
|
|
@@ -5411,14 +5711,14 @@ __export(exports_daemon_process, {
|
|
|
5411
5711
|
connectIfRunning: () => connectIfRunning
|
|
5412
5712
|
});
|
|
5413
5713
|
import { spawn } from "child_process";
|
|
5414
|
-
import { closeSync, existsSync, mkdirSync as mkdirSync2, openSync } from "fs";
|
|
5415
|
-
import { dirname as
|
|
5714
|
+
import { closeSync, existsSync as existsSync2, mkdirSync as mkdirSync2, openSync } from "fs";
|
|
5715
|
+
import { dirname as dirname6, resolve as resolve2 } from "path";
|
|
5416
5716
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
5417
5717
|
function spawnDetachedDaemon(command, args, env, logPath) {
|
|
5418
5718
|
let stdio = "ignore";
|
|
5419
5719
|
let logFd;
|
|
5420
5720
|
try {
|
|
5421
|
-
mkdirSync2(
|
|
5721
|
+
mkdirSync2(dirname6(logPath), { recursive: true });
|
|
5422
5722
|
logFd = openSync(logPath, "a");
|
|
5423
5723
|
stdio = ["ignore", logFd, logFd];
|
|
5424
5724
|
} catch {
|
|
@@ -5485,12 +5785,12 @@ function resolveKobeSpawn(subcommand) {
|
|
|
5485
5785
|
if (here.startsWith("/$bunfs") || here.startsWith("B:\\~BUN")) {
|
|
5486
5786
|
return [process.execPath, ...subcommand];
|
|
5487
5787
|
}
|
|
5488
|
-
const dir =
|
|
5788
|
+
const dir = dirname6(here);
|
|
5489
5789
|
const sourceEntry = resolve2(dir, "../cli/index.ts");
|
|
5490
|
-
if (
|
|
5790
|
+
if (existsSync2(sourceEntry))
|
|
5491
5791
|
return [process.execPath, sourceEntry, ...subcommand];
|
|
5492
5792
|
const distEntry = resolve2(dir, "../cli/index.js");
|
|
5493
|
-
if (
|
|
5793
|
+
if (existsSync2(distEntry))
|
|
5494
5794
|
return [process.execPath, distEntry, ...subcommand];
|
|
5495
5795
|
throw new Error(`kobe: could not locate kobe entry near ${dir}; expected ../cli/index.{ts,js}`);
|
|
5496
5796
|
}
|
|
@@ -5581,14 +5881,14 @@ async function runRepoSubcommand(args) {
|
|
|
5581
5881
|
return;
|
|
5582
5882
|
}
|
|
5583
5883
|
const { getRepoInitOverride: getRepoInitOverride2, setRepoInitOverride: setRepoInitOverride2, resolveRepoRoot: resolveRepoRoot2 } = await Promise.resolve().then(() => (init_repos(), exports_repos));
|
|
5584
|
-
const { existsSync:
|
|
5585
|
-
const { join:
|
|
5884
|
+
const { existsSync: existsSync3 } = await import("fs");
|
|
5885
|
+
const { join: join5 } = await import("path");
|
|
5586
5886
|
if (verb === "show") {
|
|
5587
5887
|
const [pathArg] = rest.filter((a) => !a.startsWith("-"));
|
|
5588
5888
|
const repo = resolveRepoRoot2(resolve3(process.cwd(), pathArg ?? "."));
|
|
5589
5889
|
const override = getRepoInitOverride2(repo);
|
|
5590
|
-
const hasFileScript =
|
|
5591
|
-
const hasFilePrompt =
|
|
5890
|
+
const hasFileScript = existsSync3(join5(repo, ".kobe", "init.sh"));
|
|
5891
|
+
const hasFilePrompt = existsSync3(join5(repo, ".kobe", "init-prompt.md"));
|
|
5592
5892
|
console.log(`repo: ${repo}`);
|
|
5593
5893
|
console.log(` .kobe/init.sh: ${hasFileScript ? "present (wins)" : "absent"}`);
|
|
5594
5894
|
console.log(` .kobe/init-prompt.md: ${hasFilePrompt ? "present (wins)" : "absent"}`);
|
|
@@ -6247,14 +6547,14 @@ var exports_repo_init = {};
|
|
|
6247
6547
|
__export(exports_repo_init, {
|
|
6248
6548
|
resolveRepoInit: () => resolveRepoInit
|
|
6249
6549
|
});
|
|
6250
|
-
import { existsSync as
|
|
6251
|
-
import { join as
|
|
6550
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
|
|
6551
|
+
import { join as join5 } from "path";
|
|
6252
6552
|
function repoFileScript(worktreePath) {
|
|
6253
|
-
return
|
|
6553
|
+
return existsSync3(join5(worktreePath, INIT_SCRIPT_REL)) ? `sh ${INIT_SCRIPT_REL}` : undefined;
|
|
6254
6554
|
}
|
|
6255
6555
|
function repoFilePrompt(worktreePath) {
|
|
6256
|
-
const p =
|
|
6257
|
-
if (!
|
|
6556
|
+
const p = join5(worktreePath, INIT_PROMPT_REL);
|
|
6557
|
+
if (!existsSync3(p))
|
|
6258
6558
|
return;
|
|
6259
6559
|
try {
|
|
6260
6560
|
const text = readFileSync3(p, "utf8");
|
|
@@ -6275,8 +6575,8 @@ function resolveRepoInit(repoRoot, worktreePath) {
|
|
|
6275
6575
|
var INIT_SCRIPT_REL, INIT_PROMPT_REL;
|
|
6276
6576
|
var init_repo_init = __esm(() => {
|
|
6277
6577
|
init_repos();
|
|
6278
|
-
INIT_SCRIPT_REL =
|
|
6279
|
-
INIT_PROMPT_REL =
|
|
6578
|
+
INIT_SCRIPT_REL = join5(".kobe", "init.sh");
|
|
6579
|
+
INIT_PROMPT_REL = join5(".kobe", "init-prompt.md");
|
|
6280
6580
|
});
|
|
6281
6581
|
|
|
6282
6582
|
// src/tui/panes/sidebar/worktree-changes.ts
|
|
@@ -7288,9 +7588,9 @@ var init_schema = () => {};
|
|
|
7288
7588
|
|
|
7289
7589
|
// src/tui/context/theme/loader.ts
|
|
7290
7590
|
import { readFileSync as readFileSync4, readdirSync } from "fs";
|
|
7291
|
-
import { join as
|
|
7591
|
+
import { join as join6 } from "path";
|
|
7292
7592
|
function userThemesDir() {
|
|
7293
|
-
return
|
|
7593
|
+
return join6(kobeStateDir(), "themes");
|
|
7294
7594
|
}
|
|
7295
7595
|
function loadUserThemes() {
|
|
7296
7596
|
const dir = userThemesDir();
|
|
@@ -7304,7 +7604,7 @@ function loadUserThemes() {
|
|
|
7304
7604
|
for (const file of entries) {
|
|
7305
7605
|
if (!file.endsWith(".json"))
|
|
7306
7606
|
continue;
|
|
7307
|
-
const path6 =
|
|
7607
|
+
const path6 = join6(dir, file);
|
|
7308
7608
|
let parsed;
|
|
7309
7609
|
try {
|
|
7310
7610
|
const text = readFileSync4(path6, "utf8");
|
|
@@ -7334,8 +7634,8 @@ var exports_theme = {};
|
|
|
7334
7634
|
__export(exports_theme, {
|
|
7335
7635
|
runThemeSubcommand: () => runThemeSubcommand
|
|
7336
7636
|
});
|
|
7337
|
-
import { existsSync as
|
|
7338
|
-
import { basename as basename3, join as
|
|
7637
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync5, readdirSync as readdirSync2, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
|
|
7638
|
+
import { basename as basename3, join as join7, resolve as resolve5 } from "path";
|
|
7339
7639
|
function fail2(message) {
|
|
7340
7640
|
process.stderr.write(`kobe theme: ${message}
|
|
7341
7641
|
`);
|
|
@@ -7366,7 +7666,7 @@ function listThemes() {
|
|
|
7366
7666
|
} else {
|
|
7367
7667
|
for (const f of userFiles) {
|
|
7368
7668
|
const name = f.slice(0, -".json".length);
|
|
7369
|
-
const path6 =
|
|
7669
|
+
const path6 = join7(dir, f);
|
|
7370
7670
|
const overridesBundled = BUNDLED_NAMES.includes(name) ? " (overrides built-in)" : "";
|
|
7371
7671
|
lines.push(` ${name}${overridesBundled} ${path6}`);
|
|
7372
7672
|
}
|
|
@@ -7456,8 +7756,8 @@ async function addTheme(args) {
|
|
|
7456
7756
|
}
|
|
7457
7757
|
const dir = userThemesDir();
|
|
7458
7758
|
mkdirSync3(dir, { recursive: true });
|
|
7459
|
-
const dest =
|
|
7460
|
-
if (
|
|
7759
|
+
const dest = join7(dir, `${name}.json`);
|
|
7760
|
+
if (existsSync4(dest) && !opts.force) {
|
|
7461
7761
|
fail2(`${dest} already exists (pass --force to overwrite)`);
|
|
7462
7762
|
}
|
|
7463
7763
|
writeFileSync2(dest, `${JSON.stringify(result.theme, null, 2)}
|
|
@@ -7474,8 +7774,8 @@ function removeTheme(args) {
|
|
|
7474
7774
|
if (BUNDLED_NAMES.includes(name)) {
|
|
7475
7775
|
fail2(`"${name}" is a built-in theme and cannot be removed`);
|
|
7476
7776
|
}
|
|
7477
|
-
const dest =
|
|
7478
|
-
if (!
|
|
7777
|
+
const dest = join7(userThemesDir(), `${name}.json`);
|
|
7778
|
+
if (!existsSync4(dest)) {
|
|
7479
7779
|
fail2(`no user theme named "${name}" (looked for ${dest})`);
|
|
7480
7780
|
}
|
|
7481
7781
|
unlinkSync(dest);
|
|
@@ -7658,9 +7958,9 @@ var init_daemon_cmd = __esm(() => {
|
|
|
7658
7958
|
});
|
|
7659
7959
|
|
|
7660
7960
|
// src/lib/skill-install.ts
|
|
7661
|
-
import { existsSync as
|
|
7961
|
+
import { existsSync as existsSync5, readFileSync as readFileSync6 } from "fs";
|
|
7662
7962
|
import { homedir as homedir9 } from "os";
|
|
7663
|
-
import { join as
|
|
7963
|
+
import { join as join8 } from "path";
|
|
7664
7964
|
function npxSkillsArgv(opts = {}) {
|
|
7665
7965
|
return ["skills", "add", SKILL_SOURCE_SLUG, "--skill", "kobe", "--agent", opts.agent ?? DEFAULT_SKILL_AGENT];
|
|
7666
7966
|
}
|
|
@@ -7670,14 +7970,14 @@ function npxSkillsCommand(opts = {}) {
|
|
|
7670
7970
|
function kobeSkillPaths(opts = {}) {
|
|
7671
7971
|
const home = opts.home ?? homedir9();
|
|
7672
7972
|
const cwd = opts.cwd ?? process.cwd();
|
|
7673
|
-
return [
|
|
7973
|
+
return [join8(home, SKILL_REL_PATH), join8(cwd, SKILL_REL_PATH)];
|
|
7674
7974
|
}
|
|
7675
7975
|
function parseSkillVersion(content) {
|
|
7676
7976
|
const m = content.match(/kobe-skill-version:\s*(\d+)/);
|
|
7677
7977
|
return m ? Number.parseInt(m[1], 10) : null;
|
|
7678
7978
|
}
|
|
7679
7979
|
function kobeSkillState(opts) {
|
|
7680
|
-
const path6 = kobeSkillPaths(opts).find((p) =>
|
|
7980
|
+
const path6 = kobeSkillPaths(opts).find((p) => existsSync5(p));
|
|
7681
7981
|
if (!path6) {
|
|
7682
7982
|
return { installed: false, installedVersion: null, currentVersion: KOBE_SKILL_VERSION, stale: false };
|
|
7683
7983
|
}
|
|
@@ -7729,9 +8029,9 @@ __export(exports_maintenance, {
|
|
|
7729
8029
|
runReloadSubcommand: () => runReloadSubcommand,
|
|
7730
8030
|
runDoctorSubcommand: () => runDoctorSubcommand
|
|
7731
8031
|
});
|
|
7732
|
-
import { existsSync as
|
|
8032
|
+
import { existsSync as existsSync6, readFileSync as readFileSync7, statSync } from "fs";
|
|
7733
8033
|
import { unlink as unlink6 } from "fs/promises";
|
|
7734
|
-
import { join as
|
|
8034
|
+
import { join as join9 } from "path";
|
|
7735
8035
|
import { createInterface } from "readline";
|
|
7736
8036
|
function isProcessAlive2(pid) {
|
|
7737
8037
|
try {
|
|
@@ -7828,7 +8128,7 @@ async function runDoctorSubcommand(argv = []) {
|
|
|
7828
8128
|
const socketPath = defaultDaemonSocketPath();
|
|
7829
8129
|
const pidPath = defaultDaemonPidPath();
|
|
7830
8130
|
const logPath = defaultDaemonLogPath();
|
|
7831
|
-
const tasksPath =
|
|
8131
|
+
const tasksPath = join9(kobeStateDir(), "tasks.json");
|
|
7832
8132
|
const statePath2 = kvStatePath();
|
|
7833
8133
|
const out = ["kobe doctor", ` home: ${homeDir()}`, ` socket: ${socketPath}`, ""];
|
|
7834
8134
|
const status = await probeDaemonStatus(socketPath);
|
|
@@ -7838,6 +8138,13 @@ async function runDoctorSubcommand(argv = []) {
|
|
|
7838
8138
|
const tasks = typeof status.taskCount === "number" ? status.taskCount : "?";
|
|
7839
8139
|
const clients = typeof status.attachedClients === "number" ? status.attachedClients : "?";
|
|
7840
8140
|
out.push(`daemon: \u2713 running (pid ${pid}, up ${up}, ${tasks} task(s), ${clients} client(s))`);
|
|
8141
|
+
const daemonVersion = typeof status.kobeVersion === "string" ? status.kobeVersion : undefined;
|
|
8142
|
+
if (daemonVersion && daemonVersion !== CURRENT_VERSION) {
|
|
8143
|
+
out.push(` \u26A0 stale build: daemon is v${daemonVersion}, you launched v${CURRENT_VERSION}`);
|
|
8144
|
+
out.push(" \u2192 run `kobe daemon restart`, then `kobe reload` in any open kobe sessions");
|
|
8145
|
+
} else if (daemonVersion) {
|
|
8146
|
+
out.push(` build: v${daemonVersion}`);
|
|
8147
|
+
}
|
|
7841
8148
|
} else {
|
|
7842
8149
|
const pid = await readPidFile(pidPath);
|
|
7843
8150
|
if (pid && isProcessAlive2(pid)) {
|
|
@@ -7849,7 +8156,7 @@ async function runDoctorSubcommand(argv = []) {
|
|
|
7849
8156
|
} else {
|
|
7850
8157
|
out.push("daemon: \u2717 not running (no pidfile)");
|
|
7851
8158
|
}
|
|
7852
|
-
if (
|
|
8159
|
+
if (existsSync6(socketPath))
|
|
7853
8160
|
out.push(` orphan socket file present: ${socketPath}`);
|
|
7854
8161
|
const tail = tailFile(logPath, 8);
|
|
7855
8162
|
if (tail) {
|
|
@@ -7940,7 +8247,7 @@ async function runResetSubcommand(argv) {
|
|
|
7940
8247
|
const yes = argv.includes("--yes") || argv.includes("-y");
|
|
7941
8248
|
const socketPath = defaultDaemonSocketPath();
|
|
7942
8249
|
const pidPath = defaultDaemonPidPath();
|
|
7943
|
-
const tasksPath =
|
|
8250
|
+
const tasksPath = join9(kobeStateDir(), "tasks.json");
|
|
7944
8251
|
const statePath2 = kvStatePath();
|
|
7945
8252
|
console.log("kobe reset will:");
|
|
7946
8253
|
console.log(" \u2022 stop the kobe daemon (graceful \u2192 SIGTERM \u2192 SIGKILL)");
|
|
@@ -8041,6 +8348,7 @@ var init_maintenance = __esm(() => {
|
|
|
8041
8348
|
init_env();
|
|
8042
8349
|
init_skill_install();
|
|
8043
8350
|
init_client2();
|
|
8351
|
+
init_version();
|
|
8044
8352
|
});
|
|
8045
8353
|
|
|
8046
8354
|
// src/cli/skill-cmd.ts
|
|
@@ -8143,6 +8451,189 @@ var init_skill_cmd = __esm(() => {
|
|
|
8143
8451
|
SKILL_VERBS = ["install", "status", "command"];
|
|
8144
8452
|
});
|
|
8145
8453
|
|
|
8454
|
+
// src/cli/hook-cmd.ts
|
|
8455
|
+
var exports_hook_cmd = {};
|
|
8456
|
+
__export(exports_hook_cmd, {
|
|
8457
|
+
runHookSubcommand: () => runHookSubcommand
|
|
8458
|
+
});
|
|
8459
|
+
import { homedir as homedir10 } from "os";
|
|
8460
|
+
import { dirname as dirname7, join as join10, resolve as resolve6 } from "path";
|
|
8461
|
+
async function readStdinPayload() {
|
|
8462
|
+
try {
|
|
8463
|
+
const text = await Promise.race([
|
|
8464
|
+
Bun.stdin.text(),
|
|
8465
|
+
new Promise((resolve7) => setTimeout(() => resolve7(""), 500))
|
|
8466
|
+
]);
|
|
8467
|
+
if (!text.trim())
|
|
8468
|
+
return {};
|
|
8469
|
+
const parsed = JSON.parse(text);
|
|
8470
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
8471
|
+
} catch {
|
|
8472
|
+
return {};
|
|
8473
|
+
}
|
|
8474
|
+
}
|
|
8475
|
+
function failureFromErrorType(errorType) {
|
|
8476
|
+
if (typeof errorType !== "string")
|
|
8477
|
+
return "other";
|
|
8478
|
+
if (errorType === "rate_limit" || errorType === "overloaded")
|
|
8479
|
+
return "rate_limit";
|
|
8480
|
+
if (errorType === "billing_error")
|
|
8481
|
+
return "billing";
|
|
8482
|
+
return "other";
|
|
8483
|
+
}
|
|
8484
|
+
function flagValue(argv, name) {
|
|
8485
|
+
for (let i = 0;i < argv.length; i++) {
|
|
8486
|
+
if (argv[i] === name)
|
|
8487
|
+
return argv[i + 1];
|
|
8488
|
+
if (argv[i].startsWith(`${name}=`))
|
|
8489
|
+
return argv[i].slice(name.length + 1);
|
|
8490
|
+
}
|
|
8491
|
+
return;
|
|
8492
|
+
}
|
|
8493
|
+
async function runHookSubcommand(argv) {
|
|
8494
|
+
const [verb, ...rest] = argv;
|
|
8495
|
+
if (verb === "setup") {
|
|
8496
|
+
await runHookSetup(rest);
|
|
8497
|
+
return;
|
|
8498
|
+
}
|
|
8499
|
+
try {
|
|
8500
|
+
if (verb === "worktree-created") {
|
|
8501
|
+
await reportWorktreeCreated();
|
|
8502
|
+
return;
|
|
8503
|
+
}
|
|
8504
|
+
if (!verb || !isEngineActivityKind(verb))
|
|
8505
|
+
return;
|
|
8506
|
+
const taskId = flagValue(rest, "--task-id");
|
|
8507
|
+
if (!taskId)
|
|
8508
|
+
return;
|
|
8509
|
+
const payload = await readStdinPayload();
|
|
8510
|
+
let detail;
|
|
8511
|
+
if (verb === "turn-failed") {
|
|
8512
|
+
detail = { failure: failureFromErrorType(payload.error_type) };
|
|
8513
|
+
} else if (verb === "awaiting-input") {
|
|
8514
|
+
detail = { waiting: "permission" };
|
|
8515
|
+
}
|
|
8516
|
+
const client = await connectIfRunning();
|
|
8517
|
+
if (!client)
|
|
8518
|
+
return;
|
|
8519
|
+
try {
|
|
8520
|
+
await client.request("engine.reportEvent", { taskId, kind: verb, ...detail ? { detail } : {} });
|
|
8521
|
+
} finally {
|
|
8522
|
+
client.close();
|
|
8523
|
+
}
|
|
8524
|
+
} catch {}
|
|
8525
|
+
}
|
|
8526
|
+
async function reportWorktreeCreated() {
|
|
8527
|
+
const payload = await readStdinPayload();
|
|
8528
|
+
const worktreePath = typeof payload.worktree_path === "string" ? payload.worktree_path : undefined;
|
|
8529
|
+
if (!worktreePath)
|
|
8530
|
+
return;
|
|
8531
|
+
const repo = await deriveRepoRoot(worktreePath);
|
|
8532
|
+
if (!repo)
|
|
8533
|
+
return;
|
|
8534
|
+
const client = await connectIfRunning();
|
|
8535
|
+
if (!client)
|
|
8536
|
+
return;
|
|
8537
|
+
try {
|
|
8538
|
+
await client.request("worktree.adopt", { repo, worktreePath, ifExists: "return" });
|
|
8539
|
+
} finally {
|
|
8540
|
+
client.close();
|
|
8541
|
+
}
|
|
8542
|
+
}
|
|
8543
|
+
async function deriveRepoRoot(worktreePath) {
|
|
8544
|
+
try {
|
|
8545
|
+
const proc = Bun.spawn(["git", "-C", worktreePath, "rev-parse", "--path-format=absolute", "--git-common-dir"], {
|
|
8546
|
+
stdout: "pipe",
|
|
8547
|
+
stderr: "ignore"
|
|
8548
|
+
});
|
|
8549
|
+
const [out, code] = await Promise.all([new Response(proc.stdout).text(), proc.exited]);
|
|
8550
|
+
if (code !== 0)
|
|
8551
|
+
return;
|
|
8552
|
+
const commonDir = out.trim();
|
|
8553
|
+
return commonDir ? dirname7(commonDir) : undefined;
|
|
8554
|
+
} catch {
|
|
8555
|
+
return;
|
|
8556
|
+
}
|
|
8557
|
+
}
|
|
8558
|
+
function syncSettingsPath(scope) {
|
|
8559
|
+
if (scope.kind === "repo")
|
|
8560
|
+
return join10(resolve6(scope.path), ".claude", "settings.json");
|
|
8561
|
+
return join10(homedir10(), ".claude", "settings.json");
|
|
8562
|
+
}
|
|
8563
|
+
function worktreeSyncAdapters() {
|
|
8564
|
+
return ALL_VENDORS.map((v) => createEngineHookAdapter(v)).filter((a) => a.supportsWorktreeSync());
|
|
8565
|
+
}
|
|
8566
|
+
function persistedSyncPath(stored) {
|
|
8567
|
+
if (!stored || stored === "off")
|
|
8568
|
+
return;
|
|
8569
|
+
if (stored === "global")
|
|
8570
|
+
return syncSettingsPath({ kind: "global" });
|
|
8571
|
+
if (stored.startsWith("repo:"))
|
|
8572
|
+
return syncSettingsPath({ kind: "repo", path: stored.slice(5) });
|
|
8573
|
+
return stored;
|
|
8574
|
+
}
|
|
8575
|
+
async function runHookSetup(argv) {
|
|
8576
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
8577
|
+
process.stdout.write([
|
|
8578
|
+
"Usage: kobe hook setup [--global | --repo <path> | --off]",
|
|
8579
|
+
"",
|
|
8580
|
+
"Install (or remove with --off) the hook that syncs an external",
|
|
8581
|
+
"`claude --worktree` into kobe as a task. Default: --global (~/.claude).",
|
|
8582
|
+
""
|
|
8583
|
+
].join(`
|
|
8584
|
+
`));
|
|
8585
|
+
return;
|
|
8586
|
+
}
|
|
8587
|
+
const off = argv.includes("--off");
|
|
8588
|
+
const repoIdx = argv.indexOf("--repo");
|
|
8589
|
+
const repoPath = repoIdx !== -1 ? argv[repoIdx + 1] : undefined;
|
|
8590
|
+
if (repoIdx !== -1 && !repoPath) {
|
|
8591
|
+
process.stderr.write(`kobe hook setup: --repo requires a path
|
|
8592
|
+
`);
|
|
8593
|
+
process.exit(2);
|
|
8594
|
+
}
|
|
8595
|
+
const adapters = worktreeSyncAdapters();
|
|
8596
|
+
if (adapters.length === 0) {
|
|
8597
|
+
process.stdout.write(`kobe hook setup: no engine supports external worktree sync \u2014 nothing to do
|
|
8598
|
+
`);
|
|
8599
|
+
return;
|
|
8600
|
+
}
|
|
8601
|
+
const prevPath = persistedSyncPath(getPersistedString(SYNC_SETTING_KEY));
|
|
8602
|
+
if (off) {
|
|
8603
|
+
if (prevPath) {
|
|
8604
|
+
for (const a of adapters)
|
|
8605
|
+
await a.removeWorktreeSyncHook(prevPath);
|
|
8606
|
+
}
|
|
8607
|
+
setPersistedString(SYNC_SETTING_KEY, "off");
|
|
8608
|
+
process.stdout.write(`kobe hook setup: external worktree sync disabled${prevPath ? ` (removed from ${prevPath})` : ""}
|
|
8609
|
+
`);
|
|
8610
|
+
return;
|
|
8611
|
+
}
|
|
8612
|
+
const scope = repoPath ? { kind: "repo", path: repoPath } : { kind: "global" };
|
|
8613
|
+
const path6 = syncSettingsPath(scope);
|
|
8614
|
+
if (prevPath && prevPath !== path6) {
|
|
8615
|
+
for (const a of adapters)
|
|
8616
|
+
await a.removeWorktreeSyncHook(prevPath);
|
|
8617
|
+
}
|
|
8618
|
+
for (const a of adapters)
|
|
8619
|
+
await a.installWorktreeSyncHook(path6);
|
|
8620
|
+
setPersistedString(SYNC_SETTING_KEY, path6);
|
|
8621
|
+
process.stdout.write([
|
|
8622
|
+
`kobe hook setup: external worktree sync enabled (${scope.kind}) \u2014 wrote ${path6}`,
|
|
8623
|
+
"New `claude --worktree` worktrees will appear as kobe tasks.",
|
|
8624
|
+
""
|
|
8625
|
+
].join(`
|
|
8626
|
+
`));
|
|
8627
|
+
}
|
|
8628
|
+
var SYNC_SETTING_KEY = "externalWorktreeSync";
|
|
8629
|
+
var init_hook_cmd = __esm(() => {
|
|
8630
|
+
init_daemon_process();
|
|
8631
|
+
init_hook_adapter2();
|
|
8632
|
+
init_hook_events();
|
|
8633
|
+
init_repos();
|
|
8634
|
+
init_vendor();
|
|
8635
|
+
});
|
|
8636
|
+
|
|
8146
8637
|
// ../../node_modules/.bun/entities@7.0.1/node_modules/entities/dist/esm/decode-codepoint.js
|
|
8147
8638
|
function replaceCodePoint(codePoint) {
|
|
8148
8639
|
var _a2;
|
|
@@ -9428,6 +9919,10 @@ class RemoteOrchestrator {
|
|
|
9428
9919
|
setActiveTaskSig;
|
|
9429
9920
|
updateAcc;
|
|
9430
9921
|
setUpdateSig;
|
|
9922
|
+
daemonVersionAcc;
|
|
9923
|
+
setDaemonVersionSig;
|
|
9924
|
+
engineStateAcc;
|
|
9925
|
+
setEngineStateSig;
|
|
9431
9926
|
connectionStateAcc;
|
|
9432
9927
|
setConnectionState;
|
|
9433
9928
|
ensureReachable;
|
|
@@ -9438,6 +9933,8 @@ class RemoteOrchestrator {
|
|
|
9438
9933
|
const [tasks, setTasks] = createSignal([]);
|
|
9439
9934
|
const [activeTask, setActiveTask] = createSignal(null);
|
|
9440
9935
|
const [update, setUpdate] = createSignal(null);
|
|
9936
|
+
const [daemonVersion, setDaemonVersion] = createSignal(null);
|
|
9937
|
+
const [engineState, setEngineState] = createSignal(new Map);
|
|
9441
9938
|
const [connectionState, setConnectionState] = createSignal("online");
|
|
9442
9939
|
this.tasksAcc = tasks;
|
|
9443
9940
|
this.setTasks = (next) => setTasks(() => next);
|
|
@@ -9445,6 +9942,10 @@ class RemoteOrchestrator {
|
|
|
9445
9942
|
this.setActiveTaskSig = (next) => setActiveTask(() => next);
|
|
9446
9943
|
this.updateAcc = update;
|
|
9447
9944
|
this.setUpdateSig = (next) => setUpdate(() => next);
|
|
9945
|
+
this.daemonVersionAcc = daemonVersion;
|
|
9946
|
+
this.setDaemonVersionSig = (next) => setDaemonVersion(() => next);
|
|
9947
|
+
this.engineStateAcc = engineState;
|
|
9948
|
+
this.setEngineStateSig = (next) => setEngineState(() => next);
|
|
9448
9949
|
this.connectionStateAcc = connectionState;
|
|
9449
9950
|
this.setConnectionState = (next) => setConnectionState(() => next);
|
|
9450
9951
|
this.ensureReachable = options.ensureReachable ?? ensureDaemonReachable;
|
|
@@ -9497,6 +9998,7 @@ class RemoteOrchestrator {
|
|
|
9497
9998
|
})) {
|
|
9498
9999
|
throw new Error(`kobe daemon is protocol v${daemonVersion} (min v${daemonMin}); this client is v${DAEMON_PROTOCOL_VERSION} (min v${MIN_COMPATIBLE_PROTOCOL_VERSION}). Restart the daemon (\`kobe daemon restart\`) or upgrade kobe.`);
|
|
9499
10000
|
}
|
|
10001
|
+
this.setDaemonVersionSig(typeof hello.kobeVersion === "string" ? hello.kobeVersion : null);
|
|
9500
10002
|
if (hello.tasks)
|
|
9501
10003
|
this.setTasks(hello.tasks.map(deserializeTask));
|
|
9502
10004
|
await this.client.subscribe({ role: this.role });
|
|
@@ -9523,6 +10025,15 @@ class RemoteOrchestrator {
|
|
|
9523
10025
|
updateSignal() {
|
|
9524
10026
|
return this.updateAcc;
|
|
9525
10027
|
}
|
|
10028
|
+
daemonVersionSignal() {
|
|
10029
|
+
return this.daemonVersionAcc;
|
|
10030
|
+
}
|
|
10031
|
+
daemonStaleSignal() {
|
|
10032
|
+
return () => isDaemonVersionStale(this.daemonVersionAcc() ?? undefined, CURRENT_VERSION);
|
|
10033
|
+
}
|
|
10034
|
+
engineStateSignal() {
|
|
10035
|
+
return this.engineStateAcc;
|
|
10036
|
+
}
|
|
9526
10037
|
listTasks() {
|
|
9527
10038
|
return this.tasksAcc();
|
|
9528
10039
|
}
|
|
@@ -9613,6 +10124,18 @@ class RemoteOrchestrator {
|
|
|
9613
10124
|
this.setUpdateSig(info ?? null);
|
|
9614
10125
|
return;
|
|
9615
10126
|
}
|
|
10127
|
+
if (name === "engine-state") {
|
|
10128
|
+
const p = payload;
|
|
10129
|
+
if (typeof p?.taskId !== "string" || typeof p.state !== "string")
|
|
10130
|
+
return;
|
|
10131
|
+
const next = new Map(this.engineStateAcc());
|
|
10132
|
+
if (p.state === "idle")
|
|
10133
|
+
next.delete(p.taskId);
|
|
10134
|
+
else
|
|
10135
|
+
next.set(p.taskId, { state: p.state, detail: p.detail, at: typeof p.at === "number" ? p.at : 0 });
|
|
10136
|
+
this.setEngineStateSig(next);
|
|
10137
|
+
return;
|
|
10138
|
+
}
|
|
9616
10139
|
}
|
|
9617
10140
|
}
|
|
9618
10141
|
function deserializeTask(s) {
|
|
@@ -9635,6 +10158,7 @@ function deserializeTask(s) {
|
|
|
9635
10158
|
var init_remote_orchestrator = __esm(() => {
|
|
9636
10159
|
init_dev();
|
|
9637
10160
|
init_protocol();
|
|
10161
|
+
init_version();
|
|
9638
10162
|
init_client_log();
|
|
9639
10163
|
init_daemon_process();
|
|
9640
10164
|
});
|
|
@@ -11298,7 +11822,7 @@ function addTheme2(name, theme) {
|
|
|
11298
11822
|
}
|
|
11299
11823
|
function resolveTheme(theme, mode = "dark") {
|
|
11300
11824
|
const defs = theme.defs ?? {};
|
|
11301
|
-
function
|
|
11825
|
+
function resolve7(c, chain = []) {
|
|
11302
11826
|
if (typeof c === "string") {
|
|
11303
11827
|
if (c === "transparent" || c === "none")
|
|
11304
11828
|
return RGBA.fromInts(0, 0, 0, 0);
|
|
@@ -11310,13 +11834,13 @@ function resolveTheme(theme, mode = "dark") {
|
|
|
11310
11834
|
const next = defs[c] ?? theme.theme[c];
|
|
11311
11835
|
if (next === undefined)
|
|
11312
11836
|
return RGBA.fromInts(0, 0, 0);
|
|
11313
|
-
return
|
|
11837
|
+
return resolve7(next, [...chain, c]);
|
|
11314
11838
|
}
|
|
11315
|
-
return
|
|
11839
|
+
return resolve7(c[mode], chain);
|
|
11316
11840
|
}
|
|
11317
11841
|
const out = {};
|
|
11318
11842
|
for (const [k, v] of Object.entries(theme.theme)) {
|
|
11319
|
-
out[k] =
|
|
11843
|
+
out[k] = resolve7(v);
|
|
11320
11844
|
}
|
|
11321
11845
|
const text = out.text ?? RGBA.fromHex("#ffffff");
|
|
11322
11846
|
const background = out.background ?? RGBA.fromHex("#000000");
|
|
@@ -12095,7 +12619,7 @@ function findAvailableFolderName(parentDir, base) {
|
|
|
12095
12619
|
return trimmed;
|
|
12096
12620
|
}
|
|
12097
12621
|
function cloneRepo(url, target, onProgress) {
|
|
12098
|
-
return new Promise((
|
|
12622
|
+
return new Promise((resolve7) => {
|
|
12099
12623
|
let stderrBuf = "";
|
|
12100
12624
|
try {
|
|
12101
12625
|
const child = spawn2("git", ["clone", "--progress", url, target], {
|
|
@@ -12112,18 +12636,18 @@ function cloneRepo(url, target, onProgress) {
|
|
|
12112
12636
|
}
|
|
12113
12637
|
});
|
|
12114
12638
|
child.on("error", (err) => {
|
|
12115
|
-
|
|
12639
|
+
resolve7({ ok: false, error: err.message });
|
|
12116
12640
|
});
|
|
12117
12641
|
child.on("close", (code) => {
|
|
12118
12642
|
if (code === 0) {
|
|
12119
|
-
|
|
12643
|
+
resolve7({ ok: true, path: target });
|
|
12120
12644
|
return;
|
|
12121
12645
|
}
|
|
12122
12646
|
const tail = stderrBuf.split(/[\r\n]+/).filter((s) => s.trim().length > 0).pop() ?? `git clone exited with ${code}`;
|
|
12123
|
-
|
|
12647
|
+
resolve7({ ok: false, error: tail });
|
|
12124
12648
|
});
|
|
12125
12649
|
} catch (err) {
|
|
12126
|
-
|
|
12650
|
+
resolve7({ ok: false, error: err instanceof Error ? err.message : String(err) });
|
|
12127
12651
|
}
|
|
12128
12652
|
});
|
|
12129
12653
|
}
|
|
@@ -13186,7 +13710,7 @@ var init_dialog2 = __esm(() => {
|
|
|
13186
13710
|
|
|
13187
13711
|
// src/tui/component/new-task-dialog/index.tsx
|
|
13188
13712
|
function show(dialog, defaultRepo, savedRepos, options) {
|
|
13189
|
-
return new Promise((
|
|
13713
|
+
return new Promise((resolve7) => {
|
|
13190
13714
|
dialog.replace(() => createComponent2(NewTaskDialogView, {
|
|
13191
13715
|
defaultRepo,
|
|
13192
13716
|
savedRepos,
|
|
@@ -13199,9 +13723,9 @@ function show(dialog, defaultRepo, savedRepos, options) {
|
|
|
13199
13723
|
get discoverAdoptable() {
|
|
13200
13724
|
return options?.discoverAdoptable;
|
|
13201
13725
|
},
|
|
13202
|
-
onSubmit: (v) =>
|
|
13203
|
-
onCancel: () =>
|
|
13204
|
-
}), () =>
|
|
13726
|
+
onSubmit: (v) => resolve7(v),
|
|
13727
|
+
onCancel: () => resolve7(undefined)
|
|
13728
|
+
}), () => resolve7(undefined));
|
|
13205
13729
|
dialog.setSize("medium");
|
|
13206
13730
|
});
|
|
13207
13731
|
}
|
|
@@ -13293,15 +13817,15 @@ var init_dialog3 = __esm(() => {
|
|
|
13293
13817
|
|
|
13294
13818
|
// src/tui/component/rename-task-dialog/index.tsx
|
|
13295
13819
|
function show2(dialog, currentTitle, opts = {}) {
|
|
13296
|
-
return new Promise((
|
|
13820
|
+
return new Promise((resolve7) => {
|
|
13297
13821
|
dialog.replace(() => createComponent2(RenameTaskDialogView, {
|
|
13298
13822
|
currentTitle,
|
|
13299
13823
|
get dialogTitle() {
|
|
13300
13824
|
return opts.dialogTitle;
|
|
13301
13825
|
},
|
|
13302
|
-
onSubmit: (v) =>
|
|
13303
|
-
onCancel: () =>
|
|
13304
|
-
}), () =>
|
|
13826
|
+
onSubmit: (v) => resolve7(v),
|
|
13827
|
+
onCancel: () => resolve7(undefined)
|
|
13828
|
+
}), () => resolve7(undefined));
|
|
13305
13829
|
});
|
|
13306
13830
|
}
|
|
13307
13831
|
var RenameTaskDialog;
|
|
@@ -13315,8 +13839,8 @@ var init_rename_task_dialog = __esm(() => {
|
|
|
13315
13839
|
|
|
13316
13840
|
// src/engine/claude-code-local/binary.ts
|
|
13317
13841
|
import { spawnSync as spawnSync5 } from "child_process";
|
|
13318
|
-
import { existsSync as
|
|
13319
|
-
import { homedir as
|
|
13842
|
+
import { existsSync as existsSync8, statSync as statSync3 } from "fs";
|
|
13843
|
+
import { homedir as homedir12 } from "os";
|
|
13320
13844
|
import path7 from "path";
|
|
13321
13845
|
async function findClaudeBinary(deps = defaultDeps4) {
|
|
13322
13846
|
const checked = [];
|
|
@@ -13389,7 +13913,7 @@ var init_binary = __esm(() => {
|
|
|
13389
13913
|
return process.env[name];
|
|
13390
13914
|
},
|
|
13391
13915
|
home() {
|
|
13392
|
-
return
|
|
13916
|
+
return homedir12();
|
|
13393
13917
|
},
|
|
13394
13918
|
which(name) {
|
|
13395
13919
|
const cmd = process.platform === "win32" ? "where" : "which";
|
|
@@ -13402,7 +13926,7 @@ var init_binary = __esm(() => {
|
|
|
13402
13926
|
return;
|
|
13403
13927
|
if (first.startsWith("claude:") && first.includes("aliased to")) {
|
|
13404
13928
|
const aliasTarget = first.split("aliased to")[1]?.trim();
|
|
13405
|
-
return aliasTarget &&
|
|
13929
|
+
return aliasTarget && existsSync8(aliasTarget) ? aliasTarget : undefined;
|
|
13406
13930
|
}
|
|
13407
13931
|
return first;
|
|
13408
13932
|
},
|
|
@@ -13419,8 +13943,8 @@ var init_binary = __esm(() => {
|
|
|
13419
13943
|
|
|
13420
13944
|
// src/engine/codex-local/binary.ts
|
|
13421
13945
|
import { spawnSync as spawnSync6 } from "child_process";
|
|
13422
|
-
import { existsSync as
|
|
13423
|
-
import { homedir as
|
|
13946
|
+
import { existsSync as existsSync9, statSync as statSync4 } from "fs";
|
|
13947
|
+
import { homedir as homedir13 } from "os";
|
|
13424
13948
|
import path8 from "path";
|
|
13425
13949
|
async function findCodexBinary(deps = defaultDeps5) {
|
|
13426
13950
|
const checked = [];
|
|
@@ -13477,7 +14001,7 @@ var init_binary2 = __esm(() => {
|
|
|
13477
14001
|
return process.env[name];
|
|
13478
14002
|
},
|
|
13479
14003
|
home() {
|
|
13480
|
-
return
|
|
14004
|
+
return homedir13();
|
|
13481
14005
|
},
|
|
13482
14006
|
which(name) {
|
|
13483
14007
|
const cmd = process.platform === "win32" ? "where" : "which";
|
|
@@ -13490,7 +14014,7 @@ var init_binary2 = __esm(() => {
|
|
|
13490
14014
|
return;
|
|
13491
14015
|
if (first.startsWith("codex:") && first.includes("aliased to")) {
|
|
13492
14016
|
const aliasTarget = first.split("aliased to")[1]?.trim();
|
|
13493
|
-
return aliasTarget &&
|
|
14017
|
+
return aliasTarget && existsSync9(aliasTarget) ? aliasTarget : undefined;
|
|
13494
14018
|
}
|
|
13495
14019
|
return first;
|
|
13496
14020
|
},
|
|
@@ -13507,8 +14031,8 @@ var init_binary2 = __esm(() => {
|
|
|
13507
14031
|
|
|
13508
14032
|
// src/engine/copilot-local/binary.ts
|
|
13509
14033
|
import { spawnSync as spawnSync7 } from "child_process";
|
|
13510
|
-
import { existsSync as
|
|
13511
|
-
import { homedir as
|
|
14034
|
+
import { existsSync as existsSync10, statSync as statSync5 } from "fs";
|
|
14035
|
+
import { homedir as homedir14 } from "os";
|
|
13512
14036
|
import path9 from "path";
|
|
13513
14037
|
async function findCopilotBinary(deps = defaultDeps6) {
|
|
13514
14038
|
const checked = [];
|
|
@@ -13589,7 +14113,7 @@ var init_binary3 = __esm(() => {
|
|
|
13589
14113
|
return process.env[name];
|
|
13590
14114
|
},
|
|
13591
14115
|
home() {
|
|
13592
|
-
return
|
|
14116
|
+
return homedir14();
|
|
13593
14117
|
},
|
|
13594
14118
|
which(name) {
|
|
13595
14119
|
const cmd = process.platform === "win32" ? "where" : "which";
|
|
@@ -13602,7 +14126,7 @@ var init_binary3 = __esm(() => {
|
|
|
13602
14126
|
return;
|
|
13603
14127
|
if (first.startsWith("copilot:") && first.includes("aliased to")) {
|
|
13604
14128
|
const aliasTarget = first.split("aliased to")[1]?.trim();
|
|
13605
|
-
return aliasTarget &&
|
|
14129
|
+
return aliasTarget && existsSync10(aliasTarget) ? aliasTarget : undefined;
|
|
13606
14130
|
}
|
|
13607
14131
|
return first;
|
|
13608
14132
|
},
|
|
@@ -13614,7 +14138,7 @@ var init_binary3 = __esm(() => {
|
|
|
13614
14138
|
|
|
13615
14139
|
// src/engine/account-detect.ts
|
|
13616
14140
|
import { readFileSync as readFileSync8, statSync as statSync6 } from "fs";
|
|
13617
|
-
import { homedir as
|
|
14141
|
+
import { homedir as homedir15 } from "os";
|
|
13618
14142
|
import path10 from "path";
|
|
13619
14143
|
function claudeGlobalConfigPath(env, home) {
|
|
13620
14144
|
const override = env("CLAUDE_CONFIG_DIR")?.trim();
|
|
@@ -13832,7 +14356,7 @@ var init_account_detect = __esm(() => {
|
|
|
13832
14356
|
return process.env[name];
|
|
13833
14357
|
},
|
|
13834
14358
|
home() {
|
|
13835
|
-
return
|
|
14359
|
+
return homedir15();
|
|
13836
14360
|
},
|
|
13837
14361
|
findClaudeBinary() {
|
|
13838
14362
|
return findClaudeBinary();
|
|
@@ -13971,18 +14495,18 @@ var init_dialog_confirm = __esm(() => {
|
|
|
13971
14495
|
init_keymap();
|
|
13972
14496
|
init_dialog();
|
|
13973
14497
|
DialogConfirm.show = (dialog, title, message, label, confirmLabel, options) => {
|
|
13974
|
-
return new Promise((
|
|
14498
|
+
return new Promise((resolve7) => {
|
|
13975
14499
|
dialog.replace(() => createComponent2(DialogConfirm, {
|
|
13976
14500
|
title,
|
|
13977
14501
|
message,
|
|
13978
|
-
onConfirm: () =>
|
|
13979
|
-
onCancel: () =>
|
|
14502
|
+
onConfirm: () => resolve7(true),
|
|
14503
|
+
onCancel: () => resolve7(false),
|
|
13980
14504
|
label,
|
|
13981
14505
|
confirmLabel,
|
|
13982
14506
|
get initialActive() {
|
|
13983
14507
|
return options?.initialActive;
|
|
13984
14508
|
}
|
|
13985
|
-
}), () =>
|
|
14509
|
+
}), () => resolve7(undefined));
|
|
13986
14510
|
dialog.setSize("small");
|
|
13987
14511
|
});
|
|
13988
14512
|
};
|
|
@@ -13990,7 +14514,7 @@ var init_dialog_confirm = __esm(() => {
|
|
|
13990
14514
|
|
|
13991
14515
|
// src/tui/component/settings-dialog/actions.ts
|
|
13992
14516
|
import { unlinkSync as unlinkSync2 } from "fs";
|
|
13993
|
-
import { join as
|
|
14517
|
+
import { join as join12 } from "path";
|
|
13994
14518
|
function hasRestartableDaemon(orchestrator) {
|
|
13995
14519
|
return orchestrator instanceof RemoteOrchestrator;
|
|
13996
14520
|
}
|
|
@@ -14007,7 +14531,7 @@ async function confirmResetState(dialog, kv, renderer) {
|
|
|
14007
14531
|
return;
|
|
14008
14532
|
kv.clear();
|
|
14009
14533
|
try {
|
|
14010
|
-
unlinkSync2(
|
|
14534
|
+
unlinkSync2(join12(homeDir(), ".kobe", "tasks.json"));
|
|
14011
14535
|
} catch (err) {
|
|
14012
14536
|
if (err.code !== "ENOENT") {
|
|
14013
14537
|
console.error("kobe: failed to delete tasks.json during reset:", err);
|
|
@@ -15298,23 +15822,89 @@ var init_settings_dialog = __esm(() => {
|
|
|
15298
15822
|
init_sections();
|
|
15299
15823
|
SettingsDialog.show = (dialog, kv, orchestrator) => {
|
|
15300
15824
|
let visualPrefsChanged = false;
|
|
15301
|
-
return new Promise((
|
|
15825
|
+
return new Promise((resolve7) => {
|
|
15302
15826
|
dialog.replace(() => createComponent2(SettingsDialog, {
|
|
15303
15827
|
kv,
|
|
15304
15828
|
orchestrator,
|
|
15305
15829
|
onVisualPrefsChange: () => {
|
|
15306
15830
|
visualPrefsChanged = true;
|
|
15307
15831
|
},
|
|
15308
|
-
onClose: () =>
|
|
15832
|
+
onClose: () => resolve7({
|
|
15309
15833
|
visualPrefsChanged
|
|
15310
15834
|
})
|
|
15311
|
-
}), () =>
|
|
15835
|
+
}), () => resolve7({
|
|
15312
15836
|
visualPrefsChanged
|
|
15313
15837
|
}));
|
|
15314
15838
|
});
|
|
15315
15839
|
};
|
|
15316
15840
|
});
|
|
15317
15841
|
|
|
15842
|
+
// src/tui/component/version-skew-banner.tsx
|
|
15843
|
+
import { TextAttributes as TextAttributes7 } from "@opentui/core";
|
|
15844
|
+
function versionSkewHint(daemonVersion, clientVersion) {
|
|
15845
|
+
const daemon = daemonVersion ? `v${daemonVersion}` : "an older build";
|
|
15846
|
+
return `daemon is ${daemon} \u2014 you launched v${clientVersion}. Run \`kobe daemon restart\` then \`kobe reload\``;
|
|
15847
|
+
}
|
|
15848
|
+
function VersionSkewBanner(props) {
|
|
15849
|
+
const {
|
|
15850
|
+
theme
|
|
15851
|
+
} = useTheme();
|
|
15852
|
+
const ruleWidth = () => Math.max(4, props.width() - 2);
|
|
15853
|
+
return createComponent2(Show, {
|
|
15854
|
+
get when() {
|
|
15855
|
+
return props.stale();
|
|
15856
|
+
},
|
|
15857
|
+
get children() {
|
|
15858
|
+
var _el$ = createElement("box"), _el$2 = createElement("text"), _el$3 = createElement("box"), _el$4 = createElement("text"), _el$6 = createElement("box"), _el$7 = createElement("text");
|
|
15859
|
+
insertNode(_el$, _el$2);
|
|
15860
|
+
insertNode(_el$, _el$3);
|
|
15861
|
+
insertNode(_el$, _el$6);
|
|
15862
|
+
setProp(_el$, "flexDirection", "column");
|
|
15863
|
+
setProp(_el$, "flexShrink", 0);
|
|
15864
|
+
setProp(_el$, "paddingLeft", 1);
|
|
15865
|
+
setProp(_el$, "paddingRight", 1);
|
|
15866
|
+
setProp(_el$, "paddingBottom", 1);
|
|
15867
|
+
setProp(_el$2, "wrapMode", "none");
|
|
15868
|
+
insert(_el$2, () => "\u2594".repeat(ruleWidth()));
|
|
15869
|
+
insertNode(_el$3, _el$4);
|
|
15870
|
+
setProp(_el$3, "flexDirection", "row");
|
|
15871
|
+
setProp(_el$3, "gap", 1);
|
|
15872
|
+
insertNode(_el$4, createTextNode(`\u26A0 DAEMON OUT OF DATE`));
|
|
15873
|
+
setProp(_el$4, "wrapMode", "none");
|
|
15874
|
+
insertNode(_el$6, _el$7);
|
|
15875
|
+
setProp(_el$6, "flexDirection", "row");
|
|
15876
|
+
setProp(_el$6, "gap", 1);
|
|
15877
|
+
setProp(_el$7, "wrapMode", "word");
|
|
15878
|
+
insert(_el$7, () => versionSkewHint(props.daemonVersion(), props.clientVersion));
|
|
15879
|
+
effect((_p$) => {
|
|
15880
|
+
var { warning: _v$, warning: _v$2 } = theme, _v$3 = TextAttributes7.BOLD, _v$4 = theme.text;
|
|
15881
|
+
_v$ !== _p$.e && (_p$.e = setProp(_el$2, "fg", _v$, _p$.e));
|
|
15882
|
+
_v$2 !== _p$.t && (_p$.t = setProp(_el$4, "fg", _v$2, _p$.t));
|
|
15883
|
+
_v$3 !== _p$.a && (_p$.a = setProp(_el$4, "attributes", _v$3, _p$.a));
|
|
15884
|
+
_v$4 !== _p$.o && (_p$.o = setProp(_el$7, "fg", _v$4, _p$.o));
|
|
15885
|
+
return _p$;
|
|
15886
|
+
}, {
|
|
15887
|
+
e: undefined,
|
|
15888
|
+
t: undefined,
|
|
15889
|
+
a: undefined,
|
|
15890
|
+
o: undefined
|
|
15891
|
+
});
|
|
15892
|
+
return _el$;
|
|
15893
|
+
}
|
|
15894
|
+
});
|
|
15895
|
+
}
|
|
15896
|
+
var init_version_skew_banner = __esm(() => {
|
|
15897
|
+
init_solid();
|
|
15898
|
+
init_solid();
|
|
15899
|
+
init_solid();
|
|
15900
|
+
init_solid();
|
|
15901
|
+
init_solid();
|
|
15902
|
+
init_solid();
|
|
15903
|
+
init_solid();
|
|
15904
|
+
init_dev();
|
|
15905
|
+
init_theme2();
|
|
15906
|
+
});
|
|
15907
|
+
|
|
15318
15908
|
// src/tui/context/focus.tsx
|
|
15319
15909
|
function FocusProvider(props) {
|
|
15320
15910
|
const [focused, setFocusedSignal] = createSignal(props.initial ?? "sidebar");
|
|
@@ -15378,7 +15968,7 @@ var init_focus = __esm(() => {
|
|
|
15378
15968
|
|
|
15379
15969
|
// src/tui/context/kv.tsx
|
|
15380
15970
|
import { mkdirSync as mkdirSync4, readFileSync as readFileSync9, renameSync as renameSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
15381
|
-
import { dirname as
|
|
15971
|
+
import { dirname as dirname8 } from "path";
|
|
15382
15972
|
function loadInitial() {
|
|
15383
15973
|
const statePath2 = kvStatePath();
|
|
15384
15974
|
try {
|
|
@@ -15406,7 +15996,7 @@ var init_kv = __esm(() => {
|
|
|
15406
15996
|
function writeNow(label) {
|
|
15407
15997
|
const statePath2 = kvStatePath();
|
|
15408
15998
|
try {
|
|
15409
|
-
mkdirSync4(
|
|
15999
|
+
mkdirSync4(dirname8(statePath2), {
|
|
15410
16000
|
recursive: true
|
|
15411
16001
|
});
|
|
15412
16002
|
const tmp = `${statePath2}.tmp`;
|
|
@@ -15461,7 +16051,7 @@ var init_kv = __esm(() => {
|
|
|
15461
16051
|
}
|
|
15462
16052
|
const statePath2 = kvStatePath();
|
|
15463
16053
|
try {
|
|
15464
|
-
mkdirSync4(
|
|
16054
|
+
mkdirSync4(dirname8(statePath2), {
|
|
15465
16055
|
recursive: true
|
|
15466
16056
|
});
|
|
15467
16057
|
const tmp = `${statePath2}.tmp`;
|
|
@@ -15497,8 +16087,8 @@ var init_persisted_ui_prefs = __esm(() => {
|
|
|
15497
16087
|
|
|
15498
16088
|
// src/tui/lib/worktree-opener.ts
|
|
15499
16089
|
import { spawn as spawn3 } from "child_process";
|
|
15500
|
-
import { existsSync as
|
|
15501
|
-
import { basename as basename4, delimiter, isAbsolute, join as
|
|
16090
|
+
import { existsSync as existsSync11 } from "fs";
|
|
16091
|
+
import { basename as basename4, delimiter, isAbsolute, join as join13 } from "path";
|
|
15502
16092
|
function executableOnPath(command, env, exists) {
|
|
15503
16093
|
if (isAbsolute(command))
|
|
15504
16094
|
return exists(command);
|
|
@@ -15506,7 +16096,7 @@ function executableOnPath(command, env, exists) {
|
|
|
15506
16096
|
for (const dir of pathEnv.split(delimiter)) {
|
|
15507
16097
|
if (!dir)
|
|
15508
16098
|
continue;
|
|
15509
|
-
if (exists(
|
|
16099
|
+
if (exists(join13(dir, command)))
|
|
15510
16100
|
return true;
|
|
15511
16101
|
}
|
|
15512
16102
|
return false;
|
|
@@ -15526,7 +16116,7 @@ function labelForOverride(command) {
|
|
|
15526
16116
|
function detectWorktreeOpener(deps = {}) {
|
|
15527
16117
|
const env = deps.env ?? process.env;
|
|
15528
16118
|
const platform = deps.platform ?? process.platform;
|
|
15529
|
-
const exists = deps.exists ??
|
|
16119
|
+
const exists = deps.exists ?? existsSync11;
|
|
15530
16120
|
const override = env.KOBE_OPEN_EDITOR?.trim();
|
|
15531
16121
|
if (override) {
|
|
15532
16122
|
return { id: "env", label: labelForOverride(override), command: override, args: [] };
|
|
@@ -15664,7 +16254,7 @@ function flattenIds(rows) {
|
|
|
15664
16254
|
var init_groups = () => {};
|
|
15665
16255
|
|
|
15666
16256
|
// src/tui/context/command-palette.tsx
|
|
15667
|
-
import { TextAttributes as
|
|
16257
|
+
import { TextAttributes as TextAttributes8 } from "@opentui/core";
|
|
15668
16258
|
function CommandPaletteProvider(props) {
|
|
15669
16259
|
const dialog = useDialog();
|
|
15670
16260
|
const [commands, setCommands] = createSignal([]);
|
|
@@ -15813,7 +16403,7 @@ function CommandPaletteDialog(props) {
|
|
|
15813
16403
|
}
|
|
15814
16404
|
}), null);
|
|
15815
16405
|
effect((_p$) => {
|
|
15816
|
-
var _v$ =
|
|
16406
|
+
var _v$ = TextAttributes8.BOLD, _v$2 = theme.text, _v$3 = theme.textMuted;
|
|
15817
16407
|
_v$ !== _p$.e && (_p$.e = setProp(_el$3, "attributes", _v$, _p$.e));
|
|
15818
16408
|
_v$2 !== _p$.t && (_p$.t = setProp(_el$3, "fg", _v$2, _p$.t));
|
|
15819
16409
|
_v$3 !== _p$.a && (_p$.a = setProp(_el$5, "fg", _v$3, _p$.a));
|
|
@@ -16497,7 +17087,7 @@ var init_keys = __esm(() => {
|
|
|
16497
17087
|
});
|
|
16498
17088
|
|
|
16499
17089
|
// src/tui/panes/sidebar/Sidebar.tsx
|
|
16500
|
-
import { TextAttributes as
|
|
17090
|
+
import { TextAttributes as TextAttributes9 } from "@opentui/core";
|
|
16501
17091
|
function truncateBranchLabel(branch, max = BRANCH_LABEL_MAX) {
|
|
16502
17092
|
if (branch.length <= max)
|
|
16503
17093
|
return branch;
|
|
@@ -16662,7 +17252,7 @@ function Sidebar(props) {
|
|
|
16662
17252
|
setProp(_el$3, "wrapMode", "none");
|
|
16663
17253
|
insert(_el$3, () => "\u2500".repeat(Math.max(2, effectiveWidth() - 9 - p.label.length)));
|
|
16664
17254
|
effect((_p$) => {
|
|
16665
|
-
var _v$ = p.topPad ? 1 : 0, _v$2 = theme.textMuted, _v$3 =
|
|
17255
|
+
var _v$ = p.topPad ? 1 : 0, _v$2 = theme.textMuted, _v$3 = TextAttributes9.BOLD, _v$4 = theme.border;
|
|
16666
17256
|
_v$ !== _p$.e && (_p$.e = setProp(_el$, "paddingTop", _v$, _p$.e));
|
|
16667
17257
|
_v$2 !== _p$.t && (_p$.t = setProp(_el$2, "fg", _v$2, _p$.t));
|
|
16668
17258
|
_v$3 !== _p$.a && (_p$.a = setProp(_el$2, "attributes", _v$3, _p$.a));
|
|
@@ -16707,7 +17297,7 @@ function Sidebar(props) {
|
|
|
16707
17297
|
setProp(_el$26, "onMouseUp", () => props.onHeaderStatusClick?.());
|
|
16708
17298
|
insert(_el$26, () => status().label);
|
|
16709
17299
|
effect((_p$) => {
|
|
16710
|
-
var _v$11 = status().emphasize ? theme.warning : theme.textMuted, _v$12 = status().emphasize ?
|
|
17300
|
+
var _v$11 = status().emphasize ? theme.warning : theme.textMuted, _v$12 = status().emphasize ? TextAttributes9.BOLD : TextAttributes9.DIM;
|
|
16711
17301
|
_v$11 !== _p$.e && (_p$.e = setProp(_el$26, "fg", _v$11, _p$.e));
|
|
16712
17302
|
_v$12 !== _p$.t && (_p$.t = setProp(_el$26, "attributes", _v$12, _p$.t));
|
|
16713
17303
|
return _p$;
|
|
@@ -16765,7 +17355,7 @@ function Sidebar(props) {
|
|
|
16765
17355
|
}
|
|
16766
17356
|
}), null);
|
|
16767
17357
|
effect((_p$) => {
|
|
16768
|
-
var { info: _v$5, text: _v$6, info: _v$7 } = theme, _v$8 =
|
|
17358
|
+
var { info: _v$5, text: _v$6, info: _v$7 } = theme, _v$8 = TextAttributes9.BLINK;
|
|
16769
17359
|
_v$5 !== _p$.e && (_p$.e = setProp(_el$9, "fg", _v$5, _p$.e));
|
|
16770
17360
|
_v$6 !== _p$.t && (_p$.t = setProp(_el$1, "fg", _v$6, _p$.t));
|
|
16771
17361
|
_v$7 !== _p$.a && (_p$.a = setProp(_el$10, "fg", _v$7, _p$.a));
|
|
@@ -16794,7 +17384,7 @@ function Sidebar(props) {
|
|
|
16794
17384
|
setProp(_el$27, "onMouseUp", () => setView(tab.view));
|
|
16795
17385
|
insert(_el$27, () => tab.label);
|
|
16796
17386
|
effect((_p$) => {
|
|
16797
|
-
var _v$13 = active() ? theme.primary : theme.textMuted, _v$14 = active() ?
|
|
17387
|
+
var _v$13 = active() ? theme.primary : theme.textMuted, _v$14 = active() ? TextAttributes9.BOLD : undefined;
|
|
16798
17388
|
_v$13 !== _p$.e && (_p$.e = setProp(_el$27, "fg", _v$13, _p$.e));
|
|
16799
17389
|
_v$14 !== _p$.t && (_p$.t = setProp(_el$27, "attributes", _v$14, _p$.t));
|
|
16800
17390
|
return _p$;
|
|
@@ -16861,7 +17451,34 @@ function Sidebar(props) {
|
|
|
16861
17451
|
return readWorktreeChanges(task.worktreePath);
|
|
16862
17452
|
});
|
|
16863
17453
|
const titleText = isMain ? repoBasename(task.repo) : task.title;
|
|
16864
|
-
const
|
|
17454
|
+
const activity = () => props.engineState?.().get(task.id)?.state;
|
|
17455
|
+
const loading = () => activity() === "running" || isLive() || !isMain && task.status === "in_progress";
|
|
17456
|
+
const activityChip = () => {
|
|
17457
|
+
switch (activity()) {
|
|
17458
|
+
case "rate_limited":
|
|
17459
|
+
return {
|
|
17460
|
+
text: "limited",
|
|
17461
|
+
tone: "warning"
|
|
17462
|
+
};
|
|
17463
|
+
case "permission_needed":
|
|
17464
|
+
return {
|
|
17465
|
+
text: "approve?",
|
|
17466
|
+
tone: "warning"
|
|
17467
|
+
};
|
|
17468
|
+
case "error":
|
|
17469
|
+
return {
|
|
17470
|
+
text: "error",
|
|
17471
|
+
tone: "error"
|
|
17472
|
+
};
|
|
17473
|
+
case "turn_complete":
|
|
17474
|
+
return {
|
|
17475
|
+
text: "done",
|
|
17476
|
+
tone: "primary"
|
|
17477
|
+
};
|
|
17478
|
+
default:
|
|
17479
|
+
return null;
|
|
17480
|
+
}
|
|
17481
|
+
};
|
|
16865
17482
|
const subtitleText = createMemo(() => {
|
|
16866
17483
|
if (task.branch.length > 0)
|
|
16867
17484
|
return truncateBranchLabel(task.branch, subtitleBudget());
|
|
@@ -16958,7 +17575,7 @@ function Sidebar(props) {
|
|
|
16958
17575
|
setProp(_el$37, "wrapMode", "none");
|
|
16959
17576
|
insert(_el$37, () => truncatePathTail(abbrevHome(task.repo), subtitleBudget()));
|
|
16960
17577
|
effect((_p$) => {
|
|
16961
|
-
var _v$15 = theme.textMuted, _v$16 =
|
|
17578
|
+
var _v$15 = theme.textMuted, _v$16 = TextAttributes9.DIM;
|
|
16962
17579
|
_v$15 !== _p$.e && (_p$.e = setProp(_el$37, "fg", _v$15, _p$.e));
|
|
16963
17580
|
_v$16 !== _p$.t && (_p$.t = setProp(_el$37, "attributes", _v$16, _p$.t));
|
|
16964
17581
|
return _p$;
|
|
@@ -16970,7 +17587,7 @@ function Sidebar(props) {
|
|
|
16970
17587
|
}
|
|
16971
17588
|
}), null);
|
|
16972
17589
|
effect((_p$) => {
|
|
16973
|
-
var _v$17 = barColor(), _v$18 = theme.primary, _v$19 =
|
|
17590
|
+
var _v$17 = barColor(), _v$18 = theme.primary, _v$19 = TextAttributes9.BOLD, _v$20 = theme.text, _v$21 = TextAttributes9.BOLD;
|
|
16974
17591
|
_v$17 !== _p$.e && (_p$.e = setProp(_el$31, "fg", _v$17, _p$.e));
|
|
16975
17592
|
_v$18 !== _p$.t && (_p$.t = setProp(_el$33, "fg", _v$18, _p$.t));
|
|
16976
17593
|
_v$19 !== _p$.a && (_p$.a = setProp(_el$33, "attributes", _v$19, _p$.a));
|
|
@@ -17024,8 +17641,20 @@ function Sidebar(props) {
|
|
|
17024
17641
|
return _el$43;
|
|
17025
17642
|
}
|
|
17026
17643
|
}), null);
|
|
17644
|
+
insert(_el$40, createComponent2(Show, {
|
|
17645
|
+
get when() {
|
|
17646
|
+
return memo2(() => !!!loading())() && activityChip();
|
|
17647
|
+
},
|
|
17648
|
+
children: (chip) => (() => {
|
|
17649
|
+
var _el$55 = createElement("text");
|
|
17650
|
+
setProp(_el$55, "wrapMode", "none");
|
|
17651
|
+
insert(_el$55, () => chip().text);
|
|
17652
|
+
effect((_$p) => setProp(_el$55, "fg", chip().tone === "error" ? theme.error : chip().tone === "warning" ? theme.warning : theme.primary, _$p));
|
|
17653
|
+
return _el$55;
|
|
17654
|
+
})()
|
|
17655
|
+
}), null);
|
|
17027
17656
|
effect((_p$) => {
|
|
17028
|
-
var _v$22 = barColor(), _v$23 = badgeColor(), _v$24 =
|
|
17657
|
+
var _v$22 = barColor(), _v$23 = badgeColor(), _v$24 = TextAttributes9.BOLD, _v$25 = theme.text, _v$26 = isSelected() || isCursor() ? TextAttributes9.BOLD : undefined;
|
|
17029
17658
|
_v$22 !== _p$.e && (_p$.e = setProp(_el$39, "fg", _v$22, _p$.e));
|
|
17030
17659
|
_v$23 !== _p$.t && (_p$.t = setProp(_el$41, "fg", _v$23, _p$.t));
|
|
17031
17660
|
_v$24 !== _p$.a && (_p$.a = setProp(_el$41, "attributes", _v$24, _p$.a));
|
|
@@ -17096,7 +17725,7 @@ function Sidebar(props) {
|
|
|
17096
17725
|
}
|
|
17097
17726
|
}), null);
|
|
17098
17727
|
effect((_p$) => {
|
|
17099
|
-
var _v$27 = barColor(), _v$28 = theme.textMuted, _v$29 =
|
|
17728
|
+
var _v$27 = barColor(), _v$28 = theme.textMuted, _v$29 = TextAttributes9.DIM;
|
|
17100
17729
|
_v$27 !== _p$.e && (_p$.e = setProp(_el$46, "fg", _v$27, _p$.e));
|
|
17101
17730
|
_v$28 !== _p$.t && (_p$.t = setProp(_el$48, "fg", _v$28, _p$.t));
|
|
17102
17731
|
_v$29 !== _p$.a && (_p$.a = setProp(_el$48, "attributes", _v$29, _p$.a));
|
|
@@ -17169,43 +17798,43 @@ function Sidebar(props) {
|
|
|
17169
17798
|
const left = createMemo(() => Math.max(0, Math.min(h().x + 2, dims().width - boxW() - 1)));
|
|
17170
17799
|
const top = createMemo(() => Math.max(0, Math.min(h().y + 1, dims().height - boxH() - 1)));
|
|
17171
17800
|
return (() => {
|
|
17172
|
-
var _el$
|
|
17173
|
-
setProp(_el$
|
|
17174
|
-
setProp(_el$
|
|
17175
|
-
setProp(_el$
|
|
17176
|
-
setProp(_el$
|
|
17177
|
-
setProp(_el$
|
|
17178
|
-
setProp(_el$
|
|
17179
|
-
insert(_el$
|
|
17801
|
+
var _el$56 = createElement("box");
|
|
17802
|
+
setProp(_el$56, "position", "absolute");
|
|
17803
|
+
setProp(_el$56, "zIndex", 2600);
|
|
17804
|
+
setProp(_el$56, "flexDirection", "column");
|
|
17805
|
+
setProp(_el$56, "border", true);
|
|
17806
|
+
setProp(_el$56, "paddingLeft", 1);
|
|
17807
|
+
setProp(_el$56, "paddingRight", 1);
|
|
17808
|
+
insert(_el$56, createComponent2(For, {
|
|
17180
17809
|
get each() {
|
|
17181
17810
|
return lines();
|
|
17182
17811
|
},
|
|
17183
17812
|
children: (l) => (() => {
|
|
17184
|
-
var _el$
|
|
17185
|
-
setProp(_el$
|
|
17186
|
-
insert(_el$
|
|
17813
|
+
var _el$57 = createElement("text");
|
|
17814
|
+
setProp(_el$57, "wrapMode", "none");
|
|
17815
|
+
insert(_el$57, (() => {
|
|
17187
17816
|
var _c$4 = memo2(() => !!l.dim);
|
|
17188
17817
|
return () => _c$4() ? truncatePathTail(l.text, innerW()) : truncateTitle(l.text, innerW());
|
|
17189
17818
|
})());
|
|
17190
17819
|
effect((_p$) => {
|
|
17191
|
-
var _v$35 = l.dim ? theme.textMuted : theme.text, _v$36 = l.bold ?
|
|
17192
|
-
_v$35 !== _p$.e && (_p$.e = setProp(_el$
|
|
17193
|
-
_v$36 !== _p$.t && (_p$.t = setProp(_el$
|
|
17820
|
+
var _v$35 = l.dim ? theme.textMuted : theme.text, _v$36 = l.bold ? TextAttributes9.BOLD : l.dim ? TextAttributes9.DIM : undefined;
|
|
17821
|
+
_v$35 !== _p$.e && (_p$.e = setProp(_el$57, "fg", _v$35, _p$.e));
|
|
17822
|
+
_v$36 !== _p$.t && (_p$.t = setProp(_el$57, "attributes", _v$36, _p$.t));
|
|
17194
17823
|
return _p$;
|
|
17195
17824
|
}, {
|
|
17196
17825
|
e: undefined,
|
|
17197
17826
|
t: undefined
|
|
17198
17827
|
});
|
|
17199
|
-
return _el$
|
|
17828
|
+
return _el$57;
|
|
17200
17829
|
})()
|
|
17201
17830
|
}));
|
|
17202
17831
|
effect((_p$) => {
|
|
17203
17832
|
var _v$30 = left(), _v$31 = top(), _v$32 = boxW(), _v$33 = theme.focusAccent, _v$34 = theme.backgroundElement;
|
|
17204
|
-
_v$30 !== _p$.e && (_p$.e = setProp(_el$
|
|
17205
|
-
_v$31 !== _p$.t && (_p$.t = setProp(_el$
|
|
17206
|
-
_v$32 !== _p$.a && (_p$.a = setProp(_el$
|
|
17207
|
-
_v$33 !== _p$.o && (_p$.o = setProp(_el$
|
|
17208
|
-
_v$34 !== _p$.i && (_p$.i = setProp(_el$
|
|
17833
|
+
_v$30 !== _p$.e && (_p$.e = setProp(_el$56, "left", _v$30, _p$.e));
|
|
17834
|
+
_v$31 !== _p$.t && (_p$.t = setProp(_el$56, "top", _v$31, _p$.t));
|
|
17835
|
+
_v$32 !== _p$.a && (_p$.a = setProp(_el$56, "width", _v$32, _p$.a));
|
|
17836
|
+
_v$33 !== _p$.o && (_p$.o = setProp(_el$56, "borderColor", _v$33, _p$.o));
|
|
17837
|
+
_v$34 !== _p$.i && (_p$.i = setProp(_el$56, "backgroundColor", _v$34, _p$.i));
|
|
17209
17838
|
return _p$;
|
|
17210
17839
|
}, {
|
|
17211
17840
|
e: undefined,
|
|
@@ -17214,12 +17843,12 @@ function Sidebar(props) {
|
|
|
17214
17843
|
o: undefined,
|
|
17215
17844
|
i: undefined
|
|
17216
17845
|
});
|
|
17217
|
-
return _el$
|
|
17846
|
+
return _el$56;
|
|
17218
17847
|
})();
|
|
17219
17848
|
}
|
|
17220
17849
|
}), null);
|
|
17221
17850
|
effect((_p$) => {
|
|
17222
|
-
var _v$9 = props.width ? props.width() : SIDEBAR_WIDTH, _v$0 = focusedAccessor() ? theme.focusAccent : theme.textMuted, _v$1 =
|
|
17851
|
+
var _v$9 = props.width ? props.width() : SIDEBAR_WIDTH, _v$0 = focusedAccessor() ? theme.focusAccent : theme.textMuted, _v$1 = TextAttributes9.BOLD, _v$10 = theme.textMuted;
|
|
17223
17852
|
_v$9 !== _p$.e && (_p$.e = setProp(_el$4, "width", _v$9, _p$.e));
|
|
17224
17853
|
_v$0 !== _p$.t && (_p$.t = setProp(_el$6, "fg", _v$0, _p$.t));
|
|
17225
17854
|
_v$1 !== _p$.a && (_p$.a = setProp(_el$6, "attributes", _v$1, _p$.a));
|
|
@@ -17300,8 +17929,8 @@ var exports_host = {};
|
|
|
17300
17929
|
__export(exports_host, {
|
|
17301
17930
|
startTasksPane: () => startTasksPane
|
|
17302
17931
|
});
|
|
17303
|
-
import { existsSync as
|
|
17304
|
-
import { TextAttributes as
|
|
17932
|
+
import { existsSync as existsSync12 } from "fs";
|
|
17933
|
+
import { TextAttributes as TextAttributes10 } from "@opentui/core";
|
|
17305
17934
|
function TasksShell(props) {
|
|
17306
17935
|
const themeCtx = useTheme();
|
|
17307
17936
|
const {
|
|
@@ -17535,7 +18164,7 @@ function TasksShell(props) {
|
|
|
17535
18164
|
async function openSelectedWorktree(id) {
|
|
17536
18165
|
const task = props.tasks().find((t) => t.id === id);
|
|
17537
18166
|
let worktree = task?.worktreePath;
|
|
17538
|
-
if (!worktree || !
|
|
18167
|
+
if (!worktree || !existsSync12(worktree)) {
|
|
17539
18168
|
if (!props.orch) {
|
|
17540
18169
|
console.error("[kobe tasks] no daemon; cannot materialise worktree");
|
|
17541
18170
|
return;
|
|
@@ -17548,7 +18177,7 @@ function TasksShell(props) {
|
|
|
17548
18177
|
}
|
|
17549
18178
|
await props.reload();
|
|
17550
18179
|
}
|
|
17551
|
-
if (!worktree || !
|
|
18180
|
+
if (!worktree || !existsSync12(worktree))
|
|
17552
18181
|
return;
|
|
17553
18182
|
const opener = detectWorktreeOpener();
|
|
17554
18183
|
if (!opener) {
|
|
@@ -17599,7 +18228,7 @@ function TasksShell(props) {
|
|
|
17599
18228
|
const exists = await sessionExists(name);
|
|
17600
18229
|
if (exists) {
|
|
17601
18230
|
const cwd2 = await getSessionOption(name, "@kobe_worktree") || task?.worktreePath || "";
|
|
17602
|
-
if (cwd2 &&
|
|
18231
|
+
if (cwd2 && existsSync12(cwd2)) {
|
|
17603
18232
|
await ensureSession({
|
|
17604
18233
|
name,
|
|
17605
18234
|
cwd: cwd2,
|
|
@@ -17613,7 +18242,7 @@ function TasksShell(props) {
|
|
|
17613
18242
|
return;
|
|
17614
18243
|
}
|
|
17615
18244
|
let cwd = task?.worktreePath;
|
|
17616
|
-
if (!cwd || !
|
|
18245
|
+
if (!cwd || !existsSync12(cwd)) {
|
|
17617
18246
|
if (!props.orch) {
|
|
17618
18247
|
console.error("[kobe tasks] no daemon; cannot materialise worktree");
|
|
17619
18248
|
return;
|
|
@@ -17626,7 +18255,7 @@ function TasksShell(props) {
|
|
|
17626
18255
|
}
|
|
17627
18256
|
await props.reload();
|
|
17628
18257
|
}
|
|
17629
|
-
if (!cwd || !
|
|
18258
|
+
if (!cwd || !existsSync12(cwd))
|
|
17630
18259
|
return;
|
|
17631
18260
|
const init2 = task?.repo ? resolveRepoInit(task.repo, cwd) : {};
|
|
17632
18261
|
const ready = await ensureSession({
|
|
@@ -17657,11 +18286,19 @@ function TasksShell(props) {
|
|
|
17657
18286
|
emphasize: false
|
|
17658
18287
|
};
|
|
17659
18288
|
});
|
|
18289
|
+
const daemonStale = () => props.orch?.daemonStaleSignal()() ?? false;
|
|
18290
|
+
const daemonVersion = () => props.orch?.daemonVersionSignal()() ?? null;
|
|
17660
18291
|
return (() => {
|
|
17661
18292
|
var _el$ = createElement("box"), _el$2 = createElement("box");
|
|
17662
18293
|
insertNode(_el$, _el$2);
|
|
17663
18294
|
setProp(_el$, "flexDirection", "column");
|
|
17664
18295
|
setProp(_el$, "flexGrow", 1);
|
|
18296
|
+
insert(_el$, createComponent2(VersionSkewBanner, {
|
|
18297
|
+
stale: daemonStale,
|
|
18298
|
+
daemonVersion,
|
|
18299
|
+
clientVersion: CURRENT_VERSION,
|
|
18300
|
+
width: () => dimensions().width
|
|
18301
|
+
}), _el$2);
|
|
17665
18302
|
setProp(_el$2, "flexGrow", 1);
|
|
17666
18303
|
setProp(_el$2, "flexShrink", 1);
|
|
17667
18304
|
insert(_el$2, createComponent2(Sidebar, {
|
|
@@ -17675,6 +18312,9 @@ function TasksShell(props) {
|
|
|
17675
18312
|
headerStatus,
|
|
17676
18313
|
onHeaderStatusClick: () => void openUpdate(),
|
|
17677
18314
|
width: () => dimensions().width,
|
|
18315
|
+
get engineState() {
|
|
18316
|
+
return memo2(() => !!props.orch)() ? props.orch.engineStateSignal() : undefined;
|
|
18317
|
+
},
|
|
17678
18318
|
onAddTask: () => void createTask(),
|
|
17679
18319
|
onRenameRequest: (id) => void renameTask(id),
|
|
17680
18320
|
onDeleteRequest: (id) => void deleteTask(id),
|
|
@@ -17775,7 +18415,7 @@ function ShortcutHints() {
|
|
|
17775
18415
|
setProp(_el$10, "wrapMode", "none");
|
|
17776
18416
|
insert(_el$10, () => clipLabel(h.label));
|
|
17777
18417
|
effect((_p$) => {
|
|
17778
|
-
var _v$3 = theme.accent, _v$4 =
|
|
18418
|
+
var _v$3 = theme.accent, _v$4 = TextAttributes10.BOLD, _v$5 = theme.textMuted;
|
|
17779
18419
|
_v$3 !== _p$.e && (_p$.e = setProp(_el$8, "fg", _v$3, _p$.e));
|
|
17780
18420
|
_v$4 !== _p$.t && (_p$.t = setProp(_el$8, "attributes", _v$4, _p$.t));
|
|
17781
18421
|
_v$5 !== _p$.a && (_p$.a = setProp(_el$10, "fg", _v$5, _p$.a));
|
|
@@ -17789,7 +18429,7 @@ function ShortcutHints() {
|
|
|
17789
18429
|
})()
|
|
17790
18430
|
}), null);
|
|
17791
18431
|
effect((_p$) => {
|
|
17792
|
-
var _v$ = theme.textMuted, _v$2 =
|
|
18432
|
+
var _v$ = theme.textMuted, _v$2 = TextAttributes10.DIM;
|
|
17793
18433
|
_v$ !== _p$.e && (_p$.e = setProp(_el$4, "fg", _v$, _p$.e));
|
|
17794
18434
|
_v$2 !== _p$.t && (_p$.t = setProp(_el$4, "attributes", _v$2, _p$.t));
|
|
17795
18435
|
return _p$;
|
|
@@ -17894,6 +18534,7 @@ var init_host = __esm(() => {
|
|
|
17894
18534
|
init_solid();
|
|
17895
18535
|
init_solid();
|
|
17896
18536
|
init_solid();
|
|
18537
|
+
init_solid();
|
|
17897
18538
|
init_client2();
|
|
17898
18539
|
init_solid();
|
|
17899
18540
|
init_dev();
|
|
@@ -17911,6 +18552,7 @@ var init_host = __esm(() => {
|
|
|
17911
18552
|
init_new_task_dialog();
|
|
17912
18553
|
init_rename_task_dialog();
|
|
17913
18554
|
init_settings_dialog();
|
|
18555
|
+
init_version_skew_banner();
|
|
17914
18556
|
init_focus();
|
|
17915
18557
|
init_kv();
|
|
17916
18558
|
init_theme2();
|
|
@@ -18219,7 +18861,7 @@ __export(exports_host4, {
|
|
|
18219
18861
|
startUpdateHost: () => startUpdateHost
|
|
18220
18862
|
});
|
|
18221
18863
|
import { spawn as spawn4, spawnSync as spawnSync8 } from "child_process";
|
|
18222
|
-
import { TextAttributes as
|
|
18864
|
+
import { TextAttributes as TextAttributes11 } from "@opentui/core";
|
|
18223
18865
|
function openExternalUrl(url) {
|
|
18224
18866
|
if (!url)
|
|
18225
18867
|
return false;
|
|
@@ -18244,13 +18886,13 @@ function releaseBodyLines(body) {
|
|
|
18244
18886
|
function waitForKeypress() {
|
|
18245
18887
|
if (!process.stdin.isTTY)
|
|
18246
18888
|
return Promise.resolve();
|
|
18247
|
-
return new Promise((
|
|
18889
|
+
return new Promise((resolve7) => {
|
|
18248
18890
|
const stdin = process.stdin;
|
|
18249
18891
|
const done = () => {
|
|
18250
18892
|
stdin.off("data", done);
|
|
18251
18893
|
stdin.setRawMode?.(false);
|
|
18252
18894
|
stdin.pause();
|
|
18253
|
-
|
|
18895
|
+
resolve7();
|
|
18254
18896
|
};
|
|
18255
18897
|
stdin.setRawMode?.(true);
|
|
18256
18898
|
stdin.resume();
|
|
@@ -18316,7 +18958,7 @@ function UpdatePage() {
|
|
|
18316
18958
|
}
|
|
18317
18959
|
async function runUpdater() {
|
|
18318
18960
|
setStatus("Leaving the TUI page and running the updater in this tmux window...");
|
|
18319
|
-
await new Promise((
|
|
18961
|
+
await new Promise((resolve7) => setTimeout(resolve7, 30));
|
|
18320
18962
|
renderer?.destroy();
|
|
18321
18963
|
process.stdout.write(`
|
|
18322
18964
|
kobe ${CURRENT_VERSION} -> latest
|
|
@@ -18447,7 +19089,7 @@ kobe update failed with exit code ${code}.
|
|
|
18447
19089
|
setProp(_el$32, "wrapMode", "word");
|
|
18448
19090
|
insert(_el$32, () => action.detail);
|
|
18449
19091
|
effect((_p$) => {
|
|
18450
|
-
var _v$12 = selected() === action.id ? theme.primary : undefined, _v$13 = selected() === action.id ? theme.selectedListItemText : theme.accent, _v$14 =
|
|
19092
|
+
var _v$12 = selected() === action.id ? theme.primary : undefined, _v$13 = selected() === action.id ? theme.selectedListItemText : theme.accent, _v$14 = TextAttributes11.BOLD, _v$15 = selected() === action.id ? theme.selectedListItemText : theme.text, _v$16 = selected() === action.id ? theme.selectedListItemText : theme.textMuted;
|
|
18451
19093
|
_v$12 !== _p$.e && (_p$.e = setProp(_el$25, "backgroundColor", _v$12, _p$.e));
|
|
18452
19094
|
_v$13 !== _p$.t && (_p$.t = setProp(_el$27, "fg", _v$13, _p$.t));
|
|
18453
19095
|
_v$14 !== _p$.a && (_p$.a = setProp(_el$27, "attributes", _v$14, _p$.a));
|
|
@@ -18525,7 +19167,7 @@ kobe update failed with exit code ${code}.
|
|
|
18525
19167
|
})()
|
|
18526
19168
|
}), null);
|
|
18527
19169
|
effect((_p$) => {
|
|
18528
|
-
var { background: _v$, text: _v$2 } = theme, _v$3 =
|
|
19170
|
+
var { background: _v$, text: _v$2 } = theme, _v$3 = TextAttributes11.BOLD, _v$4 = theme.textMuted, _v$5 = theme.textMuted, _v$6 = theme.text, _v$7 = TextAttributes11.BOLD, _v$8 = theme.textMuted, _v$9 = info()?.hasUpdate ? theme.warning : theme.success, _v$0 = TextAttributes11.BOLD, _v$1 = theme.textMuted, _v$10 = TextAttributes11.DIM, _v$11 = {
|
|
18529
19171
|
trackOptions: {
|
|
18530
19172
|
backgroundColor: theme.background,
|
|
18531
19173
|
foregroundColor: theme.borderActive
|
|
@@ -18623,7 +19265,7 @@ var init_host4 = __esm(() => {
|
|
|
18623
19265
|
});
|
|
18624
19266
|
|
|
18625
19267
|
// src/engine/turn-detector.ts
|
|
18626
|
-
import { readFile as
|
|
19268
|
+
import { readFile as readFile7 } from "fs/promises";
|
|
18627
19269
|
|
|
18628
19270
|
class EngineTurnDetector {
|
|
18629
19271
|
supportsCompletionMarkers() {
|
|
@@ -18646,7 +19288,7 @@ function latestClaudeCompletionMarkerFromJsonl(raw, sourceId = "claude", fallbac
|
|
|
18646
19288
|
const record = parseJsonLine(line);
|
|
18647
19289
|
if (!record)
|
|
18648
19290
|
continue;
|
|
18649
|
-
const inner =
|
|
19291
|
+
const inner = isObject7(record.message) ? record.message : record;
|
|
18650
19292
|
if (inner.role !== "assistant")
|
|
18651
19293
|
continue;
|
|
18652
19294
|
if (!("content" in inner))
|
|
@@ -18688,7 +19330,7 @@ function parseJsonLine(line) {
|
|
|
18688
19330
|
return null;
|
|
18689
19331
|
try {
|
|
18690
19332
|
const parsed = JSON.parse(trimmed);
|
|
18691
|
-
return
|
|
19333
|
+
return isObject7(parsed) ? parsed : null;
|
|
18692
19334
|
} catch {
|
|
18693
19335
|
return null;
|
|
18694
19336
|
}
|
|
@@ -18697,7 +19339,7 @@ function timestampFromRecord(record, fallback) {
|
|
|
18697
19339
|
const ts = typeof record.timestamp === "string" ? Date.parse(record.timestamp) : Number.NaN;
|
|
18698
19340
|
return Number.isFinite(ts) ? ts : fallback;
|
|
18699
19341
|
}
|
|
18700
|
-
function
|
|
19342
|
+
function isObject7(v) {
|
|
18701
19343
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
18702
19344
|
}
|
|
18703
19345
|
var ClaudeTurnDetector, CodexTurnDetector, UnknownTurnDetector;
|
|
@@ -18710,7 +19352,7 @@ var init_turn_detector = __esm(() => {
|
|
|
18710
19352
|
const files = await listSessionFilesForWorktree(worktree);
|
|
18711
19353
|
let latest = null;
|
|
18712
19354
|
for (const file of files.slice(0, 4)) {
|
|
18713
|
-
const raw = await
|
|
19355
|
+
const raw = await readFile7(file.path, "utf8").catch(() => "");
|
|
18714
19356
|
const marker = latestClaudeCompletionMarkerFromJsonl(raw, file.path, file.mtimeMs);
|
|
18715
19357
|
if (marker && (!latest || marker.timestampMs > latest.timestampMs))
|
|
18716
19358
|
latest = marker;
|
|
@@ -18729,7 +19371,7 @@ var init_turn_detector = __esm(() => {
|
|
|
18729
19371
|
if (scanned >= 12)
|
|
18730
19372
|
break;
|
|
18731
19373
|
scanned++;
|
|
18732
|
-
const raw = await
|
|
19374
|
+
const raw = await readFile7(file, "utf8").catch(() => "");
|
|
18733
19375
|
if (!raw || rolloutCwd(raw) !== worktree)
|
|
18734
19376
|
continue;
|
|
18735
19377
|
return latestCodexCompletionMarkerFromJsonl(raw, file);
|
|
@@ -18978,7 +19620,7 @@ var gitWrapper;
|
|
|
18978
19620
|
var init_git2 = __esm(() => {
|
|
18979
19621
|
gitWrapper = {
|
|
18980
19622
|
spawn(args, cwd) {
|
|
18981
|
-
return new Promise((
|
|
19623
|
+
return new Promise((resolve7, reject) => {
|
|
18982
19624
|
const child = nodeSpawn("git", [...args], {
|
|
18983
19625
|
cwd,
|
|
18984
19626
|
shell: false,
|
|
@@ -18997,7 +19639,7 @@ var init_git2 = __esm(() => {
|
|
|
18997
19639
|
});
|
|
18998
19640
|
child.on("error", reject);
|
|
18999
19641
|
child.on("close", (status, signal) => {
|
|
19000
|
-
|
|
19642
|
+
resolve7({ stdout, stderr, status, signal });
|
|
19001
19643
|
});
|
|
19002
19644
|
});
|
|
19003
19645
|
}
|
|
@@ -19051,14 +19693,14 @@ var init_keys2 = __esm(() => {
|
|
|
19051
19693
|
|
|
19052
19694
|
// src/tui/panes/filetree/open-external.ts
|
|
19053
19695
|
import { spawn as spawn5 } from "child_process";
|
|
19054
|
-
import { existsSync as
|
|
19696
|
+
import { existsSync as existsSync13 } from "fs";
|
|
19055
19697
|
import { platform } from "os";
|
|
19056
19698
|
function openExternally(absPath) {
|
|
19057
19699
|
if (!absPath)
|
|
19058
19700
|
return;
|
|
19059
19701
|
const plat = platform();
|
|
19060
19702
|
if (plat === "linux") {
|
|
19061
|
-
if (
|
|
19703
|
+
if (existsSync13("/proc/sys/fs/binfmt_misc/WSLInterop") || process.env.WSL_DISTRO_NAME) {
|
|
19062
19704
|
spawnDetached("wslview", [absPath], () => {
|
|
19063
19705
|
const child = spawn5("wslpath", ["-w", absPath], { stdio: ["ignore", "pipe", "ignore"] });
|
|
19064
19706
|
let out = "";
|
|
@@ -19097,7 +19739,7 @@ var init_open_external = () => {};
|
|
|
19097
19739
|
|
|
19098
19740
|
// src/tui/panes/filetree/FileTree.tsx
|
|
19099
19741
|
import { watch } from "fs";
|
|
19100
|
-
import { TextAttributes as
|
|
19742
|
+
import { TextAttributes as TextAttributes12 } from "@opentui/core";
|
|
19101
19743
|
function statusToken(s) {
|
|
19102
19744
|
switch (s) {
|
|
19103
19745
|
case "M":
|
|
@@ -19496,7 +20138,7 @@ function FileTree(props) {
|
|
|
19496
20138
|
insertNode(_el$6, createTextNode(`create PR`));
|
|
19497
20139
|
setProp(_el$6, "wrapMode", "none");
|
|
19498
20140
|
effect((_p$) => {
|
|
19499
|
-
var _v$ = theme.accent, _v$2 =
|
|
20141
|
+
var _v$ = theme.accent, _v$2 = TextAttributes12.BOLD, _v$3 = theme.text;
|
|
19500
20142
|
_v$ !== _p$.e && (_p$.e = setProp(_el$4, "fg", _v$, _p$.e));
|
|
19501
20143
|
_v$2 !== _p$.t && (_p$.t = setProp(_el$4, "attributes", _v$2, _p$.t));
|
|
19502
20144
|
_v$3 !== _p$.a && (_p$.a = setProp(_el$6, "fg", _v$3, _p$.a));
|
|
@@ -19526,7 +20168,7 @@ function FileTree(props) {
|
|
|
19526
20168
|
setProp(_el$26, "onMouseUp", () => setTab(t));
|
|
19527
20169
|
insert(_el$26, () => TAB_LABEL[t]);
|
|
19528
20170
|
effect((_p$) => {
|
|
19529
|
-
var _v$6 = isActive() ? theme.primary : theme.textMuted, _v$7 = isActive() ?
|
|
20171
|
+
var _v$6 = isActive() ? theme.primary : theme.textMuted, _v$7 = isActive() ? TextAttributes12.BOLD : undefined;
|
|
19530
20172
|
_v$6 !== _p$.e && (_p$.e = setProp(_el$26, "fg", _v$6, _p$.e));
|
|
19531
20173
|
_v$7 !== _p$.t && (_p$.t = setProp(_el$26, "attributes", _v$7, _p$.t));
|
|
19532
20174
|
return _p$;
|
|
@@ -19547,7 +20189,7 @@ function FileTree(props) {
|
|
|
19547
20189
|
setProp(_el$27, "wrapMode", "none");
|
|
19548
20190
|
insert(_el$27, () => badge().text);
|
|
19549
20191
|
effect((_p$) => {
|
|
19550
|
-
var _v$8 = badge().active ? theme.accent : theme.textMuted, _v$9 = badge().active ?
|
|
20192
|
+
var _v$8 = badge().active ? theme.accent : theme.textMuted, _v$9 = badge().active ? TextAttributes12.BOLD : undefined;
|
|
19551
20193
|
_v$8 !== _p$.e && (_p$.e = setProp(_el$27, "fg", _v$8, _p$.e));
|
|
19552
20194
|
_v$9 !== _p$.t && (_p$.t = setProp(_el$27, "attributes", _v$9, _p$.t));
|
|
19553
20195
|
return _p$;
|
|
@@ -19701,7 +20343,7 @@ function FileTree(props) {
|
|
|
19701
20343
|
setProp(_el$31, "wrapMode", "none");
|
|
19702
20344
|
insert(_el$31, () => `${indent}${marker} ${row.name}/`);
|
|
19703
20345
|
effect((_p$) => {
|
|
19704
|
-
var _v$0 = rowBg(), _v$1 = theme.textMuted, _v$10 =
|
|
20346
|
+
var _v$0 = rowBg(), _v$1 = theme.textMuted, _v$10 = TextAttributes12.BOLD;
|
|
19705
20347
|
_v$0 !== _p$.e && (_p$.e = setProp(_el$29, "backgroundColor", _v$0, _p$.e));
|
|
19706
20348
|
_v$1 !== _p$.t && (_p$.t = setProp(_el$31, "fg", _v$1, _p$.t));
|
|
19707
20349
|
_v$10 !== _p$.a && (_p$.a = setProp(_el$31, "attributes", _v$10, _p$.a));
|
|
@@ -20449,7 +21091,7 @@ __export(exports_direct, {
|
|
|
20449
21091
|
startDirectTmux: () => startDirectTmux,
|
|
20450
21092
|
chooseInitialTask: () => chooseInitialTask
|
|
20451
21093
|
});
|
|
20452
|
-
import { resolve as
|
|
21094
|
+
import { resolve as resolve7 } from "path";
|
|
20453
21095
|
function chooseInitialTask(tasks, choice = {}) {
|
|
20454
21096
|
const byId = (id) => id ? tasks.find((t) => t.id === id) : undefined;
|
|
20455
21097
|
const active = byId(choice.activeTaskId);
|
|
@@ -20485,7 +21127,7 @@ async function ensureRepos(orchestrator) {
|
|
|
20485
21127
|
normalizeSavedRepos();
|
|
20486
21128
|
let repos = [...getSavedRepos()];
|
|
20487
21129
|
if (repos.length === 0) {
|
|
20488
|
-
const added = addSavedRepo(
|
|
21130
|
+
const added = addSavedRepo(resolve7(process.cwd()));
|
|
20489
21131
|
repos = [added.path];
|
|
20490
21132
|
}
|
|
20491
21133
|
for (const repo of repos) {
|
|
@@ -20495,7 +21137,7 @@ async function ensureRepos(orchestrator) {
|
|
|
20495
21137
|
console.error(`[kobe] ensureMainTask failed for ${repo}:`, err);
|
|
20496
21138
|
}
|
|
20497
21139
|
}
|
|
20498
|
-
return repos[0] ??
|
|
21140
|
+
return repos[0] ?? resolve7(process.cwd());
|
|
20499
21141
|
}
|
|
20500
21142
|
async function startDirectTmux() {
|
|
20501
21143
|
setClientLogContext("gui");
|
|
@@ -20581,7 +21223,7 @@ var init_direct = __esm(() => {
|
|
|
20581
21223
|
});
|
|
20582
21224
|
|
|
20583
21225
|
// src/tui/component/help-dialog.tsx
|
|
20584
|
-
import { TextAttributes as
|
|
21226
|
+
import { TextAttributes as TextAttributes13 } from "@opentui/core";
|
|
20585
21227
|
function groupBindings(keymap) {
|
|
20586
21228
|
const groups = new Map;
|
|
20587
21229
|
const order = [];
|
|
@@ -20685,7 +21327,7 @@ function HelpDialog() {
|
|
|
20685
21327
|
}
|
|
20686
21328
|
}), null);
|
|
20687
21329
|
effect((_p$) => {
|
|
20688
|
-
var _v$5 = theme.accent, _v$6 =
|
|
21330
|
+
var _v$5 = theme.accent, _v$6 = TextAttributes13.BOLD;
|
|
20689
21331
|
_v$5 !== _p$.e && (_p$.e = setProp(_el$0, "fg", _v$5, _p$.e));
|
|
20690
21332
|
_v$6 !== _p$.t && (_p$.t = setProp(_el$0, "attributes", _v$6, _p$.t));
|
|
20691
21333
|
return _p$;
|
|
@@ -20697,7 +21339,7 @@ function HelpDialog() {
|
|
|
20697
21339
|
})()
|
|
20698
21340
|
}));
|
|
20699
21341
|
effect((_p$) => {
|
|
20700
|
-
var _v$ =
|
|
21342
|
+
var _v$ = TextAttributes13.BOLD, _v$2 = theme.text, _v$3 = theme.textMuted, _v$4 = {
|
|
20701
21343
|
trackOptions: {
|
|
20702
21344
|
backgroundColor: theme.backgroundDialog,
|
|
20703
21345
|
foregroundColor: theme.borderActive
|
|
@@ -20737,7 +21379,7 @@ var init_help_dialog = __esm(() => {
|
|
|
20737
21379
|
});
|
|
20738
21380
|
|
|
20739
21381
|
// src/tui/component/pane-header.tsx
|
|
20740
|
-
import { TextAttributes as
|
|
21382
|
+
import { TextAttributes as TextAttributes14 } from "@opentui/core";
|
|
20741
21383
|
function PaneHeader(props) {
|
|
20742
21384
|
const {
|
|
20743
21385
|
theme
|
|
@@ -20767,7 +21409,7 @@ function PaneHeader(props) {
|
|
|
20767
21409
|
setProp(_el$3, "wrapMode", "none");
|
|
20768
21410
|
insert(_el$3, () => props.ordinal);
|
|
20769
21411
|
effect((_p$) => {
|
|
20770
|
-
var _v$ = titleColor(), _v$2 =
|
|
21412
|
+
var _v$ = titleColor(), _v$2 = TextAttributes14.BOLD;
|
|
20771
21413
|
_v$ !== _p$.e && (_p$.e = setProp(_el$3, "fg", _v$, _p$.e));
|
|
20772
21414
|
_v$2 !== _p$.t && (_p$.t = setProp(_el$3, "attributes", _v$2, _p$.t));
|
|
20773
21415
|
return _p$;
|
|
@@ -20818,7 +21460,7 @@ function PaneHeader(props) {
|
|
|
20818
21460
|
}
|
|
20819
21461
|
}), null);
|
|
20820
21462
|
effect((_p$) => {
|
|
20821
|
-
var _v$3 = titleColor(), _v$4 =
|
|
21463
|
+
var _v$3 = titleColor(), _v$4 = TextAttributes14.BOLD;
|
|
20822
21464
|
_v$3 !== _p$.e && (_p$.e = setProp(_el$4, "fg", _v$3, _p$.e));
|
|
20823
21465
|
_v$4 !== _p$.t && (_p$.t = setProp(_el$4, "attributes", _v$4, _p$.t));
|
|
20824
21466
|
return _p$;
|
|
@@ -20943,7 +21585,7 @@ var init_resizable_edge = __esm(() => {
|
|
|
20943
21585
|
});
|
|
20944
21586
|
|
|
20945
21587
|
// src/tui/component/status-bar.tsx
|
|
20946
|
-
import { TextAttributes as
|
|
21588
|
+
import { TextAttributes as TextAttributes15 } from "@opentui/core";
|
|
20947
21589
|
function Hotkey(props) {
|
|
20948
21590
|
const {
|
|
20949
21591
|
theme
|
|
@@ -20962,7 +21604,7 @@ function Hotkey(props) {
|
|
|
20962
21604
|
setProp(_el$5, "wrapMode", "none");
|
|
20963
21605
|
insert(_el$5, () => props.label);
|
|
20964
21606
|
effect((_p$) => {
|
|
20965
|
-
var _v$ = theme.accent, _v$2 =
|
|
21607
|
+
var _v$ = theme.accent, _v$2 = TextAttributes15.BOLD, _v$3 = theme.textMuted;
|
|
20966
21608
|
_v$ !== _p$.e && (_p$.e = setProp(_el$2, "fg", _v$, _p$.e));
|
|
20967
21609
|
_v$2 !== _p$.t && (_p$.t = setProp(_el$2, "attributes", _v$2, _p$.t));
|
|
20968
21610
|
_v$3 !== _p$.a && (_p$.a = setProp(_el$5, "fg", _v$3, _p$.a));
|
|
@@ -21050,7 +21692,7 @@ function StatusBar() {
|
|
|
21050
21692
|
insertNode(_el$0, createTextNode(`Press Ctrl+C again to exit`));
|
|
21051
21693
|
setProp(_el$0, "wrapMode", "none");
|
|
21052
21694
|
effect((_p$) => {
|
|
21053
|
-
var _v$4 = theme.warning, _v$5 =
|
|
21695
|
+
var _v$4 = theme.warning, _v$5 = TextAttributes15.BOLD;
|
|
21054
21696
|
_v$4 !== _p$.e && (_p$.e = setProp(_el$0, "fg", _v$4, _p$.e));
|
|
21055
21697
|
_v$5 !== _p$.t && (_p$.t = setProp(_el$0, "attributes", _v$5, _p$.t));
|
|
21056
21698
|
return _p$;
|
|
@@ -21062,7 +21704,7 @@ function StatusBar() {
|
|
|
21062
21704
|
}
|
|
21063
21705
|
}), null);
|
|
21064
21706
|
effect((_p$) => {
|
|
21065
|
-
var _v$6 = theme.primary, _v$7 =
|
|
21707
|
+
var _v$6 = theme.primary, _v$7 = TextAttributes15.BOLD;
|
|
21066
21708
|
_v$6 !== _p$.e && (_p$.e = setProp(_el$8, "fg", _v$6, _p$.e));
|
|
21067
21709
|
_v$7 !== _p$.t && (_p$.t = setProp(_el$8, "attributes", _v$7, _p$.t));
|
|
21068
21710
|
return _p$;
|
|
@@ -21092,9 +21734,9 @@ var pulse_default = "../pulse-n3cq1btw.wav";
|
|
|
21092
21734
|
var init_pulse = () => {};
|
|
21093
21735
|
|
|
21094
21736
|
// src/tui/lib/sound.ts
|
|
21095
|
-
import { existsSync as
|
|
21737
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync5 } from "fs";
|
|
21096
21738
|
import { tmpdir as tmpdir2 } from "os";
|
|
21097
|
-
import { basename as basename6, isAbsolute as isAbsolute2, join as
|
|
21739
|
+
import { basename as basename6, isAbsolute as isAbsolute2, join as join14, resolve as resolve8 } from "path";
|
|
21098
21740
|
function args(player, file, volume) {
|
|
21099
21741
|
if (player === "ffplay")
|
|
21100
21742
|
return [player, "-autoexit", "-nodisp", "-af", `volume=${volume}`, file];
|
|
@@ -21117,13 +21759,13 @@ function pickPlayer() {
|
|
|
21117
21759
|
return cachedPlayer;
|
|
21118
21760
|
const path12 = process.env.PATH ?? "";
|
|
21119
21761
|
const segments = path12.split(":").filter(Boolean);
|
|
21120
|
-
cachedPlayer = PLAYERS.find((p) => segments.some((dir) =>
|
|
21762
|
+
cachedPlayer = PLAYERS.find((p) => segments.some((dir) => existsSync14(join14(dir, p)))) ?? null;
|
|
21121
21763
|
return cachedPlayer;
|
|
21122
21764
|
}
|
|
21123
21765
|
async function ensureAsset() {
|
|
21124
21766
|
cachedPath ??= (async () => {
|
|
21125
21767
|
mkdirSync5(DIR, { recursive: true });
|
|
21126
|
-
const dest =
|
|
21768
|
+
const dest = join14(DIR, basename6(pulseAsset));
|
|
21127
21769
|
const out = Bun.file(dest);
|
|
21128
21770
|
if (await out.exists())
|
|
21129
21771
|
return dest;
|
|
@@ -21152,8 +21794,8 @@ function pulse(volume = 0.4) {
|
|
|
21152
21794
|
var pulseAsset, DIR, PLAYERS, cachedPlayer, cachedPath;
|
|
21153
21795
|
var init_sound = __esm(() => {
|
|
21154
21796
|
init_pulse();
|
|
21155
|
-
pulseAsset = isAbsolute2(pulse_default) ? pulse_default :
|
|
21156
|
-
DIR =
|
|
21797
|
+
pulseAsset = isAbsolute2(pulse_default) ? pulse_default : resolve8(import.meta.dir, pulse_default);
|
|
21798
|
+
DIR = join14(tmpdir2(), "kobe-sfx");
|
|
21157
21799
|
PLAYERS = [
|
|
21158
21800
|
"ffplay",
|
|
21159
21801
|
"mpv",
|
|
@@ -21251,7 +21893,7 @@ var init_notifications = __esm(() => {
|
|
|
21251
21893
|
});
|
|
21252
21894
|
|
|
21253
21895
|
// src/tui/component/toast-overlay.tsx
|
|
21254
|
-
import { TextAttributes as
|
|
21896
|
+
import { TextAttributes as TextAttributes16 } from "@opentui/core";
|
|
21255
21897
|
function ToastOverlay() {
|
|
21256
21898
|
const {
|
|
21257
21899
|
theme
|
|
@@ -21294,7 +21936,7 @@ function ToastOverlay() {
|
|
|
21294
21936
|
setProp(_el$4, "wrapMode", "none");
|
|
21295
21937
|
insert(_el$4, () => toast.title);
|
|
21296
21938
|
effect((_p$) => {
|
|
21297
|
-
var _v$3 = bg(), _v$4 = fg(), _v$5 =
|
|
21939
|
+
var _v$3 = bg(), _v$4 = fg(), _v$5 = TextAttributes16.BOLD, _v$6 = fg();
|
|
21298
21940
|
_v$3 !== _p$.e && (_p$.e = setProp(_el$2, "backgroundColor", _v$3, _p$.e));
|
|
21299
21941
|
_v$4 !== _p$.t && (_p$.t = setProp(_el$3, "fg", _v$4, _p$.t));
|
|
21300
21942
|
_v$5 !== _p$.a && (_p$.a = setProp(_el$3, "attributes", _v$5, _p$.a));
|
|
@@ -21354,7 +21996,7 @@ function repoBasename2(repo) {
|
|
|
21354
21996
|
|
|
21355
21997
|
// src/tui/component/top-bar.tsx
|
|
21356
21998
|
import { spawnSync as spawnSync10 } from "child_process";
|
|
21357
|
-
import { TextAttributes as
|
|
21999
|
+
import { TextAttributes as TextAttributes17 } from "@opentui/core";
|
|
21358
22000
|
function TopBar(props) {
|
|
21359
22001
|
const {
|
|
21360
22002
|
theme
|
|
@@ -21429,7 +22071,7 @@ function TopBar(props) {
|
|
|
21429
22071
|
insertNode(_el$7, createTextNode(`[Update]`));
|
|
21430
22072
|
setProp(_el$7, "onMouseUp", () => void confirmUpdate());
|
|
21431
22073
|
effect((_p$) => {
|
|
21432
|
-
var _v$ = theme.warning, _v$2 =
|
|
22074
|
+
var _v$ = theme.warning, _v$2 = TextAttributes17.BOLD;
|
|
21433
22075
|
_v$ !== _p$.e && (_p$.e = setProp(_el$7, "fg", _v$, _p$.e));
|
|
21434
22076
|
_v$2 !== _p$.t && (_p$.t = setProp(_el$7, "attributes", _v$2, _p$.t));
|
|
21435
22077
|
return _p$;
|
|
@@ -21465,7 +22107,7 @@ function TopBar(props) {
|
|
|
21465
22107
|
insertNode(_el$12, createTextNode(`daemon disconnected`));
|
|
21466
22108
|
setProp(_el$12, "wrapMode", "none");
|
|
21467
22109
|
effect((_p$) => {
|
|
21468
|
-
var _v$6 = theme.error, _v$7 =
|
|
22110
|
+
var _v$6 = theme.error, _v$7 = TextAttributes17.BOLD;
|
|
21469
22111
|
_v$6 !== _p$.e && (_p$.e = setProp(_el$12, "fg", _v$6, _p$.e));
|
|
21470
22112
|
_v$7 !== _p$.t && (_p$.t = setProp(_el$12, "attributes", _v$7, _p$.t));
|
|
21471
22113
|
return _p$;
|
|
@@ -21495,7 +22137,7 @@ function TopBar(props) {
|
|
|
21495
22137
|
setProp(_el$15, "wrapMode", "none");
|
|
21496
22138
|
insert(_el$15, () => label().repoName);
|
|
21497
22139
|
effect((_p$) => {
|
|
21498
|
-
var _v$8 = label().branch ? theme.textMuted : theme.text, _v$9 = label().branch ? undefined :
|
|
22140
|
+
var _v$8 = label().branch ? theme.textMuted : theme.text, _v$9 = label().branch ? undefined : TextAttributes17.BOLD;
|
|
21499
22141
|
_v$8 !== _p$.e && (_p$.e = setProp(_el$15, "fg", _v$8, _p$.e));
|
|
21500
22142
|
_v$9 !== _p$.t && (_p$.t = setProp(_el$15, "attributes", _v$9, _p$.t));
|
|
21501
22143
|
return _p$;
|
|
@@ -21527,7 +22169,7 @@ function TopBar(props) {
|
|
|
21527
22169
|
setProp(_el$18, "wrapMode", "none");
|
|
21528
22170
|
insert(_el$18, () => label().branch);
|
|
21529
22171
|
effect((_p$) => {
|
|
21530
|
-
var _v$0 = theme.text, _v$1 =
|
|
22172
|
+
var _v$0 = theme.text, _v$1 = TextAttributes17.BOLD;
|
|
21531
22173
|
_v$0 !== _p$.e && (_p$.e = setProp(_el$18, "fg", _v$0, _p$.e));
|
|
21532
22174
|
_v$1 !== _p$.t && (_p$.t = setProp(_el$18, "attributes", _v$1, _p$.t));
|
|
21533
22175
|
return _p$;
|
|
@@ -21550,7 +22192,7 @@ function TopBar(props) {
|
|
|
21550
22192
|
setProp(_el$11, "gap", 2);
|
|
21551
22193
|
setProp(_el$11, "justifyContent", "flex-end");
|
|
21552
22194
|
effect((_p$) => {
|
|
21553
|
-
var _v$3 = theme.primary, _v$4 =
|
|
22195
|
+
var _v$3 = theme.primary, _v$4 = TextAttributes17.BOLD, _v$5 = theme.textMuted;
|
|
21554
22196
|
_v$3 !== _p$.e && (_p$.e = setProp(_el$3, "fg", _v$3, _p$.e));
|
|
21555
22197
|
_v$4 !== _p$.t && (_p$.t = setProp(_el$3, "attributes", _v$4, _p$.t));
|
|
21556
22198
|
_v$5 !== _p$.a && (_p$.a = setProp(_el$5, "fg", _v$5, _p$.a));
|
|
@@ -21679,7 +22321,7 @@ var init_use_theme_persistence = __esm(() => {
|
|
|
21679
22321
|
});
|
|
21680
22322
|
|
|
21681
22323
|
// src/monitor/cost.ts
|
|
21682
|
-
import { readFile as
|
|
22324
|
+
import { readFile as readFile8 } from "fs/promises";
|
|
21683
22325
|
async function summarizeTaskCost(opts) {
|
|
21684
22326
|
const files = await listSessionFilesForWorktree(opts.worktree);
|
|
21685
22327
|
const base = {
|
|
@@ -21701,7 +22343,7 @@ async function summarizeTaskCost(opts) {
|
|
|
21701
22343
|
for (const file of files) {
|
|
21702
22344
|
let raw;
|
|
21703
22345
|
try {
|
|
21704
|
-
raw = await
|
|
22346
|
+
raw = await readFile8(file.path, "utf8");
|
|
21705
22347
|
} catch {
|
|
21706
22348
|
continue;
|
|
21707
22349
|
}
|
|
@@ -22212,7 +22854,7 @@ var exports_app = {};
|
|
|
22212
22854
|
__export(exports_app, {
|
|
22213
22855
|
startApp: () => startApp
|
|
22214
22856
|
});
|
|
22215
|
-
import { homedir as
|
|
22857
|
+
import { homedir as homedir16 } from "os";
|
|
22216
22858
|
function Shell(props) {
|
|
22217
22859
|
const themeCtx = useTheme();
|
|
22218
22860
|
const {
|
|
@@ -22720,7 +23362,7 @@ async function startApp() {
|
|
|
22720
23362
|
} of loadUserThemes()) {
|
|
22721
23363
|
addTheme2(name, theme);
|
|
22722
23364
|
}
|
|
22723
|
-
const homeDir2 = process.env.KOBE_HOME_DIR ??
|
|
23365
|
+
const homeDir2 = process.env.KOBE_HOME_DIR ?? homedir16();
|
|
22724
23366
|
let orchestrator;
|
|
22725
23367
|
if (process.env.KOBE_NO_DAEMON === "1") {
|
|
22726
23368
|
const store2 = new TaskIndexStore({
|
|
@@ -22833,7 +23475,7 @@ var init_tui = __esm(() => {
|
|
|
22833
23475
|
// src/cli/index.ts
|
|
22834
23476
|
init_path_glob();
|
|
22835
23477
|
init_vendor();
|
|
22836
|
-
import { resolve as
|
|
23478
|
+
import { resolve as resolve9 } from "path";
|
|
22837
23479
|
|
|
22838
23480
|
// src/cli/usage.ts
|
|
22839
23481
|
init_version();
|
|
@@ -22882,7 +23524,7 @@ Usage: kobe add [path]
|
|
|
22882
23524
|
`);
|
|
22883
23525
|
process.exit(2);
|
|
22884
23526
|
}
|
|
22885
|
-
const target =
|
|
23527
|
+
const target = resolve9(process.cwd(), arg && arg.length > 0 ? arg : ".");
|
|
22886
23528
|
const { addSavedRepo: addSavedRepo2 } = await Promise.resolve().then(() => (init_repos(), exports_repos));
|
|
22887
23529
|
const result = addSavedRepo2(target);
|
|
22888
23530
|
if (result.added) {
|
|
@@ -22981,7 +23623,7 @@ async function runAdoptSubcommand(args2) {
|
|
|
22981
23623
|
}
|
|
22982
23624
|
}
|
|
22983
23625
|
const { resolveRepoRoot: resolveRepoRoot2 } = await Promise.resolve().then(() => (init_repos(), exports_repos));
|
|
22984
|
-
const repo = resolveRepoRoot2(
|
|
23626
|
+
const repo = resolveRepoRoot2(resolve9(process.cwd(), repoArg && repoArg.length > 0 ? repoArg : "."));
|
|
22985
23627
|
const vendor = coerceVendorId(vendorArg);
|
|
22986
23628
|
const orch = await openLocalOrchestrator();
|
|
22987
23629
|
const worktrees = await orch.discoverAdoptableWorktrees(repo);
|
|
@@ -23119,6 +23761,11 @@ async function main() {
|
|
|
23119
23761
|
await runSkillSubcommand2(rest);
|
|
23120
23762
|
return;
|
|
23121
23763
|
}
|
|
23764
|
+
if (subcommand === "hook") {
|
|
23765
|
+
const { runHookSubcommand: runHookSubcommand2 } = await Promise.resolve().then(() => (init_hook_cmd(), exports_hook_cmd));
|
|
23766
|
+
await runHookSubcommand2(rest);
|
|
23767
|
+
return;
|
|
23768
|
+
}
|
|
23122
23769
|
if (subcommand === "new-chattab") {
|
|
23123
23770
|
const flags = parseOpsFlags(rest);
|
|
23124
23771
|
const session = flags.session;
|