deskbuddy 0.2.0-beta.43 → 0.2.0-beta.47
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/{chunk-ET52BEIS.js → chunk-JPCZVBK6.js} +595 -139
- package/dist/cli.js +1579 -277
- package/dist/{enable-AF2A67ZD.js → enable-OICEMNUF.js} +1 -1
- package/dist/hook.cjs +99 -0
- package/dist/ocTranslate.mjs +18 -2
- package/dist/opencode.mjs +48 -5
- package/hook/hook-debug.log +36 -0
- package/hook/hook.cjs +99 -0
- package/hook/ocTranslate.d.mts +3 -0
- package/hook/ocTranslate.mjs +18 -2
- package/hook/opencode.d.mts +12 -1
- package/hook/opencode.mjs +48 -5
- package/package.json +1 -1
|
@@ -203,7 +203,10 @@ function loadConfig() {
|
|
|
203
203
|
cozeApp: typeof parsed.cozeApp === "boolean" ? parsed.cozeApp : void 0,
|
|
204
204
|
cozeCdpPort: portOrUndefined(parsed.cozeCdpPort),
|
|
205
205
|
chatgptAppPort: typeof parsed.chatgptAppPort === "boolean" ? parsed.chatgptAppPort : void 0,
|
|
206
|
-
chatgptCdpPort: portOrUndefined(parsed.chatgptCdpPort)
|
|
206
|
+
chatgptCdpPort: portOrUndefined(parsed.chatgptCdpPort),
|
|
207
|
+
focusSessionOnRemote: typeof parsed.focusSessionOnRemote === "boolean" ? parsed.focusSessionOnRemote : void 0,
|
|
208
|
+
focusSessionOnRemoteWindows: typeof parsed.focusSessionOnRemoteWindows === "boolean" ? parsed.focusSessionOnRemoteWindows : void 0,
|
|
209
|
+
focusSessionInApp: typeof parsed.focusSessionInApp === "boolean" ? parsed.focusSessionInApp : void 0
|
|
207
210
|
};
|
|
208
211
|
} catch {
|
|
209
212
|
return fallback;
|
|
@@ -1433,6 +1436,13 @@ async function refreshRegistry() {
|
|
|
1433
1436
|
} catch {
|
|
1434
1437
|
}
|
|
1435
1438
|
}
|
|
1439
|
+
var DEFAULT_TITLE_SOURCES = ["git-branch", "project"];
|
|
1440
|
+
function titleSources(registry, tool) {
|
|
1441
|
+
const fromRegistry = registry?.tools?.[tool]?.titleSources;
|
|
1442
|
+
if (fromRegistry?.length) return fromRegistry;
|
|
1443
|
+
const builtin = FALLBACK.tools[tool]?.titleSources;
|
|
1444
|
+
return builtin?.length ? builtin : DEFAULT_TITLE_SOURCES;
|
|
1445
|
+
}
|
|
1436
1446
|
|
|
1437
1447
|
// src/adapters/ccHook.ts
|
|
1438
1448
|
import { chmodSync, existsSync as existsSync6, mkdirSync as mkdirSync6, readFileSync as readFileSync7, renameSync as renameSync4, rmSync as rmSync3, statSync, writeFileSync as writeFileSync6 } from "fs";
|
|
@@ -2475,6 +2485,324 @@ function rememberTitle(titles, info) {
|
|
|
2475
2485
|
titles.set(info.id, t.slice(0, 100));
|
|
2476
2486
|
}
|
|
2477
2487
|
|
|
2488
|
+
// src/daemon/gate/options.ts
|
|
2489
|
+
import { homedir as homedir3 } from "os";
|
|
2490
|
+
|
|
2491
|
+
// src/daemon/gate/claudeLabels.ts
|
|
2492
|
+
var CC_MERGE_MAX = 8;
|
|
2493
|
+
var CC_LABEL_MAX_WIDTH = 160;
|
|
2494
|
+
var CC_VALUE_MAX = 256;
|
|
2495
|
+
var CC_SUGGESTIONS_MAX = 64;
|
|
2496
|
+
var CC_TEXT = {
|
|
2497
|
+
yes: "Yes",
|
|
2498
|
+
no: "No",
|
|
2499
|
+
noTell: "No, and tell Claude what to do differently",
|
|
2500
|
+
readHead: "Yes, allow reading from ",
|
|
2501
|
+
fromProject: " from this project",
|
|
2502
|
+
duringSession: " during this session",
|
|
2503
|
+
forSession: " for this session",
|
|
2504
|
+
alwaysAccessHead: "Yes, and always allow access to ",
|
|
2505
|
+
accessHead: "Yes, and allow access to ",
|
|
2506
|
+
allowHead: "Yes, and allow ",
|
|
2507
|
+
accessAnd: " access and",
|
|
2508
|
+
and: " and",
|
|
2509
|
+
commands: " commands",
|
|
2510
|
+
dontAskHead: "Yes, and don't ask again for ",
|
|
2511
|
+
/** 可编辑前缀项(单条子命令):标签 + `: ` + 前缀(弯撇号 U+2019) */
|
|
2512
|
+
dontAskPrefix: "Yes, and don\u2019t ask again for: ",
|
|
2513
|
+
switchHead: "Yes, and switch to ",
|
|
2514
|
+
claudeFolderProject: "Yes, and allow Claude to edit files in this project's .claude folder for this session",
|
|
2515
|
+
claudeFolderHome: "Yes, and allow Claude to edit files in its ~/.claude folder for this session",
|
|
2516
|
+
autoMode: "Yes, and switch to auto mode",
|
|
2517
|
+
autoModeNote: "\xB7 auto mode handles these prompts for you"
|
|
2518
|
+
};
|
|
2519
|
+
var CC_MODE_TEXT = {
|
|
2520
|
+
acceptEdits: "accept edits (auto-approve file edits and common file commands)"
|
|
2521
|
+
};
|
|
2522
|
+
function isWide(cp) {
|
|
2523
|
+
return cp >= 4352 && cp <= 4447 || cp >= 11904 && cp <= 12350 || cp >= 12353 && cp <= 13311 || cp >= 13312 && cp <= 19903 || cp >= 19968 && cp <= 40959 || cp >= 40960 && cp <= 42191 || cp >= 44032 && cp <= 55203 || cp >= 63744 && cp <= 64255 || cp >= 65072 && cp <= 65103 || cp >= 65280 && cp <= 65376 || cp >= 65504 && cp <= 65510;
|
|
2524
|
+
}
|
|
2525
|
+
function plainChars(s) {
|
|
2526
|
+
for (const ch of s) {
|
|
2527
|
+
const cp = ch.codePointAt(0);
|
|
2528
|
+
if (cp >= 32 && cp <= 126) continue;
|
|
2529
|
+
if (isWide(cp)) continue;
|
|
2530
|
+
return false;
|
|
2531
|
+
}
|
|
2532
|
+
return true;
|
|
2533
|
+
}
|
|
2534
|
+
function displayWidth(s) {
|
|
2535
|
+
let w = 0;
|
|
2536
|
+
for (const ch of s) w += isWide(ch.codePointAt(0)) ? 2 : 1;
|
|
2537
|
+
return w;
|
|
2538
|
+
}
|
|
2539
|
+
function shownAsIs(s) {
|
|
2540
|
+
return s.length > 0 && s.length <= CC_VALUE_MAX && s.trim() === s && !/\s\s/.test(s) && !s.startsWith('"') && !s.endsWith('"') && plainChars(s);
|
|
2541
|
+
}
|
|
2542
|
+
function listItemAsIs(s) {
|
|
2543
|
+
return shownAsIs(s) && !s.includes(",") && !s.includes(";") && !s.includes(" and ") && !s.startsWith("and ") && !s.endsWith(" and");
|
|
2544
|
+
}
|
|
2545
|
+
function joinAnd(items) {
|
|
2546
|
+
if (items.length <= 2) return items.join(" and ");
|
|
2547
|
+
return `${items.slice(0, -1).join(", ")}, and ${items[items.length - 1]}`;
|
|
2548
|
+
}
|
|
2549
|
+
var uniq = (a) => [...new Set(a)];
|
|
2550
|
+
function distinctShown(raw, show) {
|
|
2551
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2552
|
+
for (const r of raw) {
|
|
2553
|
+
const k = show(r).normalize("NFC");
|
|
2554
|
+
if (seen.has(k)) return false;
|
|
2555
|
+
seen.add(k);
|
|
2556
|
+
}
|
|
2557
|
+
return true;
|
|
2558
|
+
}
|
|
2559
|
+
var isObj = (x) => x !== null && typeof x === "object" && !Array.isArray(x);
|
|
2560
|
+
var ruleOut = (r) => ({ toolName: r.toolName, ruleContent: r.ruleContent });
|
|
2561
|
+
var addRulesOut = (rules, destination) => ({ type: "addRules", rules: rules.map(ruleOut), behavior: "allow", destination });
|
|
2562
|
+
var addDirsOut = (directories, destination) => ({ type: "addDirectories", directories, destination });
|
|
2563
|
+
var DESTS = /* @__PURE__ */ new Set(["localSettings", "session"]);
|
|
2564
|
+
function readShown(rc) {
|
|
2565
|
+
if (rc.includes("\\")) return null;
|
|
2566
|
+
const s = rc.replace(/\/\*\*$/, "").replace(/^\.\//, "").replace(/^\/\//, "/");
|
|
2567
|
+
return s ? s : null;
|
|
2568
|
+
}
|
|
2569
|
+
function commandShown(rc) {
|
|
2570
|
+
const s = rc.endsWith(":*") || rc.endsWith(" *") ? rc.slice(0, -2) : rc;
|
|
2571
|
+
if (!s || /[<>]/.test(s)) return null;
|
|
2572
|
+
return s;
|
|
2573
|
+
}
|
|
2574
|
+
function shellApplies(sugg, tool) {
|
|
2575
|
+
if (sugg.length > CC_SUGGESTIONS_MAX) return null;
|
|
2576
|
+
const out = [];
|
|
2577
|
+
for (const s of sugg) {
|
|
2578
|
+
if (!isObj(s)) return null;
|
|
2579
|
+
if (s.type === "addRules") {
|
|
2580
|
+
if (s.behavior !== "allow" || !DESTS.has(s.destination)) continue;
|
|
2581
|
+
if (!Array.isArray(s.rules)) return null;
|
|
2582
|
+
const rules = [];
|
|
2583
|
+
for (const r of s.rules) {
|
|
2584
|
+
if (!isObj(r) || typeof r.toolName !== "string" || r.ruleContent !== void 0 && typeof r.ruleContent !== "string") return null;
|
|
2585
|
+
if (r.toolName === tool) {
|
|
2586
|
+
if (typeof r.ruleContent !== "string" || !r.ruleContent) continue;
|
|
2587
|
+
if (commandShown(r.ruleContent) === null) return null;
|
|
2588
|
+
rules.push(ruleOut(r));
|
|
2589
|
+
} else if (r.toolName === "Read") {
|
|
2590
|
+
if (typeof r.ruleContent !== "string" || !r.ruleContent) continue;
|
|
2591
|
+
if (readShown(r.ruleContent) === null) return null;
|
|
2592
|
+
rules.push(ruleOut(r));
|
|
2593
|
+
}
|
|
2594
|
+
}
|
|
2595
|
+
if (rules.length) out.push(addRulesOut(rules, s.destination));
|
|
2596
|
+
} else if (s.type === "addDirectories") {
|
|
2597
|
+
if (!DESTS.has(s.destination)) continue;
|
|
2598
|
+
if (!Array.isArray(s.directories)) return null;
|
|
2599
|
+
const dirs = s.directories.filter((d) => typeof d === "string" && d.trim() !== "");
|
|
2600
|
+
if (dirs.length !== s.directories.length) return null;
|
|
2601
|
+
if (dirs.length) out.push(addDirsOut(dirs, s.destination));
|
|
2602
|
+
}
|
|
2603
|
+
}
|
|
2604
|
+
return out;
|
|
2605
|
+
}
|
|
2606
|
+
function shellRowLabel(applies, tool, cwdShown) {
|
|
2607
|
+
const rules = applies.filter((s) => s.type === "addRules").flatMap((s) => s.rules);
|
|
2608
|
+
const dirsRaw = applies.filter((s) => s.type === "addDirectories").flatMap((s) => s.directories);
|
|
2609
|
+
if (rules.length + dirsRaw.length > CC_MERGE_MAX) return null;
|
|
2610
|
+
const dirs = uniq(dirsRaw);
|
|
2611
|
+
const reads = uniq(rules.filter((r) => r.toolName === "Read").map((r) => r.ruleContent));
|
|
2612
|
+
const cmds = uniq(rules.filter((r) => r.toolName === tool).map((r) => r.ruleContent));
|
|
2613
|
+
const readShow = (r) => readShown(r);
|
|
2614
|
+
const cmdShow = (r) => commandShown(r);
|
|
2615
|
+
const pathRaw = [...reads, ...dirs];
|
|
2616
|
+
const pathShow = (r) => reads.includes(r) ? readShow(r) : r;
|
|
2617
|
+
if (!distinctShown(pathRaw, pathShow) || !distinctShown(cmds, cmdShow)) return null;
|
|
2618
|
+
const R = cmds.map(cmdShow);
|
|
2619
|
+
const E = reads.map(readShow);
|
|
2620
|
+
const K = dirs;
|
|
2621
|
+
if (![...R, ...E, ...K].every(listItemAsIs)) return null;
|
|
2622
|
+
if (displayWidth([...R, ...E, ...K].join(" and ")) > CC_LABEL_MAX_WIDTH) return null;
|
|
2623
|
+
const hasDir = K.length > 0;
|
|
2624
|
+
const hasRead = E.length > 0;
|
|
2625
|
+
const hasCmd = R.length > 0;
|
|
2626
|
+
if (hasRead && !hasDir && !hasCmd) return CC_TEXT.readHead + joinAnd(E) + CC_TEXT.fromProject;
|
|
2627
|
+
if (!hasCmd && (hasDir || hasRead)) return CC_TEXT.alwaysAccessHead + joinAnd([...K, ...E]) + CC_TEXT.fromProject;
|
|
2628
|
+
if (hasCmd && !hasDir && !hasRead) {
|
|
2629
|
+
if (cwdShown === null) return null;
|
|
2630
|
+
return CC_TEXT.dontAskHead + joinAnd(R) + CC_TEXT.commands + " in " + cwdShown;
|
|
2631
|
+
}
|
|
2632
|
+
if (hasCmd) {
|
|
2633
|
+
const paths = [...K, ...E];
|
|
2634
|
+
if (paths.length === 1 && R.length === 1) return CC_TEXT.accessHead + paths[0] + CC_TEXT.and + " " + R[0] + CC_TEXT.commands;
|
|
2635
|
+
return CC_TEXT.allowHead + joinAnd(paths) + CC_TEXT.accessAnd + " " + joinAnd(R) + CC_TEXT.commands;
|
|
2636
|
+
}
|
|
2637
|
+
return null;
|
|
2638
|
+
}
|
|
2639
|
+
function projectSlug(p) {
|
|
2640
|
+
return p.replace(/[^a-zA-Z0-9]/g, "-");
|
|
2641
|
+
}
|
|
2642
|
+
function sessionRoot(cwd, transcriptPath) {
|
|
2643
|
+
if (typeof cwd !== "string" || !cwd || typeof transcriptPath !== "string" || !transcriptPath) return null;
|
|
2644
|
+
if (!shownAsIs(cwd) || /[\u0000-\u001f]/.test(cwd)) return null;
|
|
2645
|
+
const parts = transcriptPath.split(/[\\/]/);
|
|
2646
|
+
const dir2 = parts.length >= 2 ? parts[parts.length - 2] : "";
|
|
2647
|
+
const slug = projectSlug(cwd);
|
|
2648
|
+
if (slug.length <= 200 ? dir2 !== slug : !dir2.startsWith(`${slug.slice(0, 200)}-`)) return null;
|
|
2649
|
+
return cwd;
|
|
2650
|
+
}
|
|
2651
|
+
var CC_AUTO_LABEL = `${CC_TEXT.autoMode} ${CC_TEXT.autoModeNote}`;
|
|
2652
|
+
var CC_AUTO_DESC = "\u5141\u8BB8\u8FD9\u4E00\u6B21\uFF0C\u5E76\u628A\u6574\u4E2A\u4F1A\u8BDD\u5207\u5230\u81EA\u52A8\u6A21\u5F0F\uFF1A\u4E4B\u540E\u8FD9\u7C7B\u786E\u8BA4\u7531 Claude \u81EA\u5DF1\u5224\u65AD\u653E\u884C\uFF0C\u4E0D\u518D\u9010\u6761\u95EE\u4F60";
|
|
2653
|
+
var CC_AUTO_MODE_UPDATE = { type: "setMode", mode: "auto", destination: "session" };
|
|
2654
|
+
function yesRowNo(middle, action, opts = {}) {
|
|
2655
|
+
const options = [{ id: "allow", label: CC_TEXT.yes, kind: "allow" }];
|
|
2656
|
+
const actions = { allow: { decision: "allow" } };
|
|
2657
|
+
if (middle && action) {
|
|
2658
|
+
options.push(middle);
|
|
2659
|
+
actions[middle.id] = action;
|
|
2660
|
+
}
|
|
2661
|
+
if (opts.auto) {
|
|
2662
|
+
options.push({ id: "auto", label: CC_AUTO_LABEL, description: CC_AUTO_DESC, kind: "allow_session" });
|
|
2663
|
+
actions.auto = { decision: "allow", updatedPermissions: [{ ...CC_AUTO_MODE_UPDATE }] };
|
|
2664
|
+
}
|
|
2665
|
+
if (opts.noTell) options.push({ id: "deny", label: CC_TEXT.noTell, kind: "deny" });
|
|
2666
|
+
else options.push({ id: "deny", label: CC_TEXT.no, description: CC_TEXT.noTell, kind: "deny", input: true });
|
|
2667
|
+
actions.deny = { decision: "deny" };
|
|
2668
|
+
return { options, actions };
|
|
2669
|
+
}
|
|
2670
|
+
function claudeShellLabels(tool, sugg, auto, ctx = {}) {
|
|
2671
|
+
if (isObj(ctx.toolInput) && "_host" in ctx.toolInput) return null;
|
|
2672
|
+
const applies = shellApplies(sugg, tool);
|
|
2673
|
+
if (applies === null || applies.length === 0) return null;
|
|
2674
|
+
const mixed = applies.some((s) => s.type === "addDirectories" || s.rules?.some((r) => r.toolName !== tool));
|
|
2675
|
+
const cmds = uniq(applies.flatMap((s) => s.type === "addRules" ? s.rules : []).filter((r) => r.toolName === tool).map((r) => r.ruleContent));
|
|
2676
|
+
const autoOpt = tool === "Bash" && auto;
|
|
2677
|
+
if (mixed) {
|
|
2678
|
+
const label3 = shellRowLabel(applies, tool, null);
|
|
2679
|
+
if (label3 === null) return null;
|
|
2680
|
+
const kind2 = applies.some((s) => s.destination === "localSettings") ? "allow_always" : "allow_session";
|
|
2681
|
+
const id = cmds.length ? "always" : applies.some((s) => s.type === "addDirectories") ? "dir" : "read";
|
|
2682
|
+
return yesRowNo({ id, label: label3, kind: kind2 }, { decision: "allow", updatedPermissions: applies }, { auto: autoOpt });
|
|
2683
|
+
}
|
|
2684
|
+
if (tool === "PowerShell") return null;
|
|
2685
|
+
if (cmds.length === 1) {
|
|
2686
|
+
if (sugg.length !== 1) return null;
|
|
2687
|
+
const raw = sugg[0];
|
|
2688
|
+
if (!Array.isArray(raw.rules) || raw.rules.length !== 1) return null;
|
|
2689
|
+
const s = applies[0];
|
|
2690
|
+
const rules = s.rules;
|
|
2691
|
+
if (s.destination !== "localSettings" || rules.length !== 1) return null;
|
|
2692
|
+
const rc = rules[0].ruleContent;
|
|
2693
|
+
if (!isObj(raw.rules[0]) || raw.rules[0].toolName !== tool || raw.rules[0].ruleContent !== rc) return null;
|
|
2694
|
+
if (!rc.endsWith(" *") || rc.trim() === "*") return null;
|
|
2695
|
+
return yesRowNo(
|
|
2696
|
+
{ id: "always", label: CC_TEXT.dontAskPrefix + rc, kind: "allow_always" },
|
|
2697
|
+
{ decision: "allow", updatedPermissions: [addRulesOut([{ toolName: tool, ruleContent: rc }], "localSettings")] },
|
|
2698
|
+
{ auto: autoOpt }
|
|
2699
|
+
);
|
|
2700
|
+
}
|
|
2701
|
+
const root = sessionRoot(ctx.cwd, ctx.transcriptPath);
|
|
2702
|
+
if (root === null) return null;
|
|
2703
|
+
const label2 = shellRowLabel(applies, tool, root);
|
|
2704
|
+
if (label2 === null) return null;
|
|
2705
|
+
const kind = applies.some((s) => s.destination === "localSettings") ? "allow_always" : "allow_session";
|
|
2706
|
+
return yesRowNo({ id: "always", label: label2, kind }, { decision: "allow", updatedPermissions: applies }, { auto: autoOpt });
|
|
2707
|
+
}
|
|
2708
|
+
function underDir(file3, dir2, platform) {
|
|
2709
|
+
const fold = platform === "darwin" || platform === "win32" ? (s) => s.toLowerCase() : (s) => s;
|
|
2710
|
+
return fold(file3).startsWith(fold(dir2.replace(/\/+$/, "")) + "/");
|
|
2711
|
+
}
|
|
2712
|
+
function claudeFileLabels(toolName, sugg, ctx = {}) {
|
|
2713
|
+
const read2 = toolName === "Read";
|
|
2714
|
+
if (read2 && ctx.permissionMode === "auto") return null;
|
|
2715
|
+
if (sugg.length === 0 || sugg.length > CC_SUGGESTIONS_MAX || !sugg.every(isObj)) return null;
|
|
2716
|
+
const sg = sugg;
|
|
2717
|
+
const file3 = isObj(ctx.toolInput) ? ctx.toolInput.file_path ?? ctx.toolInput.notebook_path : void 0;
|
|
2718
|
+
if (!read2 && typeof file3 === "string") {
|
|
2719
|
+
const platform = ctx.platform ?? process.platform;
|
|
2720
|
+
const home = ctx.home;
|
|
2721
|
+
const root = sessionRoot(ctx.cwd, ctx.transcriptPath);
|
|
2722
|
+
const absPosix = file3.startsWith("/") && !file3.split("/").includes("..");
|
|
2723
|
+
const inHome = !!home && absPosix && underDir(file3, `${home}/.claude`, platform);
|
|
2724
|
+
const inProject = !!root && absPosix && underDir(file3, `${root}/.claude`, platform);
|
|
2725
|
+
const claudeSegment = /(^|[\\/])\.claude([\\/]|$)/i.test(file3);
|
|
2726
|
+
if (claudeSegment && !inHome && !inProject) return null;
|
|
2727
|
+
if (inHome || inProject) {
|
|
2728
|
+
const content = inHome ? "~/.claude/**" : "/.claude/**";
|
|
2729
|
+
const want = { type: "addRules", rules: [{ toolName: "Edit", ruleContent: content }], behavior: "allow", destination: "session" };
|
|
2730
|
+
const s = sg.length === 1 ? sg[0] : null;
|
|
2731
|
+
const r = s && Array.isArray(s.rules) && s.rules.length === 1 && isObj(s.rules[0]) ? s.rules[0] : null;
|
|
2732
|
+
if (!s || s.type !== "addRules" || s.behavior !== "allow" || s.destination !== "session" || !r || r.toolName !== "Edit" || r.ruleContent !== content) return null;
|
|
2733
|
+
return yesRowNo(
|
|
2734
|
+
{ id: "session", label: inHome ? CC_TEXT.claudeFolderHome : CC_TEXT.claudeFolderProject, kind: "allow_session" },
|
|
2735
|
+
{ decision: "allow", updatedPermissions: [want] }
|
|
2736
|
+
);
|
|
2737
|
+
}
|
|
2738
|
+
}
|
|
2739
|
+
const rows = [];
|
|
2740
|
+
for (const s of sg) {
|
|
2741
|
+
if (s.destination !== "session") return null;
|
|
2742
|
+
if (s.type === "setMode") {
|
|
2743
|
+
if (read2 || s.mode !== "acceptEdits") return null;
|
|
2744
|
+
} else if (s.type === "addDirectories") {
|
|
2745
|
+
if (read2) return null;
|
|
2746
|
+
} else if (s.type === "addRules") {
|
|
2747
|
+
if (s.behavior !== "allow") return null;
|
|
2748
|
+
} else return null;
|
|
2749
|
+
}
|
|
2750
|
+
if (sg.filter((s) => s.type === "setMode").length > 1 || sg.filter((s) => s.type === "addDirectories").length > 1) return null;
|
|
2751
|
+
if (sg.some((s) => s.type === "setMode")) {
|
|
2752
|
+
rows.push({ label: CC_TEXT.switchHead + CC_MODE_TEXT.acceptEdits + CC_TEXT.forSession, applies: [{ type: "setMode", destination: "session", mode: "acceptEdits" }] });
|
|
2753
|
+
}
|
|
2754
|
+
const dirSugg = sg.find((s) => s.type === "addDirectories");
|
|
2755
|
+
if (dirSugg) {
|
|
2756
|
+
const dirsIn = Array.isArray(dirSugg.directories) ? dirSugg.directories : null;
|
|
2757
|
+
if (!dirsIn || dirsIn.some((d) => typeof d !== "string" || d.trim() === "")) return null;
|
|
2758
|
+
const dirs = uniq(dirsIn);
|
|
2759
|
+
if (dirs.length === 0 || !dirs.every(listItemAsIs) || !distinctShown(dirs, (d) => d)) return null;
|
|
2760
|
+
if (dirs.length <= CC_MERGE_MAX && displayWidth(dirs.join(", ")) <= CC_LABEL_MAX_WIDTH)
|
|
2761
|
+
rows.push({ label: CC_TEXT.alwaysAccessHead + dirs.join(", ") + CC_TEXT.forSession, applies: [{ type: "addDirectories", destination: "session", directories: dirs }] });
|
|
2762
|
+
}
|
|
2763
|
+
const ruleSuggs = sg.filter((s) => s.type === "addRules");
|
|
2764
|
+
if (ruleSuggs.length) {
|
|
2765
|
+
const applies = [];
|
|
2766
|
+
const reads = [];
|
|
2767
|
+
for (const s of ruleSuggs) {
|
|
2768
|
+
if (!Array.isArray(s.rules)) return null;
|
|
2769
|
+
const keep = [];
|
|
2770
|
+
for (const r of s.rules) {
|
|
2771
|
+
if (!isObj(r) || r.toolName !== "Read" || typeof r.ruleContent !== "string" || readShown(r.ruleContent) === null) return null;
|
|
2772
|
+
keep.push(ruleOut(r));
|
|
2773
|
+
reads.push(r.ruleContent);
|
|
2774
|
+
}
|
|
2775
|
+
if (keep.length) applies.push(addRulesOut(keep, s.destination));
|
|
2776
|
+
}
|
|
2777
|
+
if (reads.length === 0) return null;
|
|
2778
|
+
const u = uniq(reads);
|
|
2779
|
+
const shown = u.map((r) => readShown(r));
|
|
2780
|
+
if (!distinctShown(u, (r) => readShown(r)) || !shown.every(listItemAsIs)) return null;
|
|
2781
|
+
if (reads.length <= CC_MERGE_MAX && displayWidth(shown.join(" and ")) <= CC_LABEL_MAX_WIDTH)
|
|
2782
|
+
rows.push({ label: CC_TEXT.readHead + joinAnd(shown) + CC_TEXT.duringSession, applies });
|
|
2783
|
+
}
|
|
2784
|
+
if (rows.length === 0) return null;
|
|
2785
|
+
const label2 = rows.map((r) => r.label).join("; ");
|
|
2786
|
+
return yesRowNo({ id: "session", label: label2, kind: "allow_session" }, { decision: "allow", updatedPermissions: rows.flatMap((r) => r.applies) });
|
|
2787
|
+
}
|
|
2788
|
+
function claudeWebFetchLabels(sugg, ctx = {}) {
|
|
2789
|
+
if (sugg.length !== 1 || !isObj(sugg[0])) return null;
|
|
2790
|
+
const s = sugg[0];
|
|
2791
|
+
if (s.type !== "addRules" || s.behavior !== "allow" || s.destination !== "localSettings" || !Array.isArray(s.rules) || s.rules.length !== 1) return null;
|
|
2792
|
+
const r = s.rules[0];
|
|
2793
|
+
if (!isObj(r) || r.toolName !== "WebFetch" || typeof r.ruleContent !== "string" || !r.ruleContent.startsWith("domain:")) return null;
|
|
2794
|
+
const host = r.ruleContent.slice("domain:".length);
|
|
2795
|
+
const url = isObj(ctx.toolInput) ? ctx.toolInput.url : void 0;
|
|
2796
|
+
let urlHost = null;
|
|
2797
|
+
try {
|
|
2798
|
+
urlHost = typeof url === "string" ? new URL(url).hostname : null;
|
|
2799
|
+
} catch {
|
|
2800
|
+
urlHost = null;
|
|
2801
|
+
}
|
|
2802
|
+
if (!host || host !== urlHost || host.includes("*") || !shownAsIs(host)) return null;
|
|
2803
|
+
return yesRowNo({ id: "always", label: CC_TEXT.dontAskHead + host, kind: "allow_always" }, { decision: "allow", updatedPermissions: [addRulesOut([{ toolName: "WebFetch", ruleContent: r.ruleContent }], "localSettings")] }, { noTell: true });
|
|
2804
|
+
}
|
|
2805
|
+
|
|
2478
2806
|
// src/daemon/gate/options.ts
|
|
2479
2807
|
var OPTIONS_MAX = 16;
|
|
2480
2808
|
var OPTION_LABEL_MAX = 2e3;
|
|
@@ -2514,95 +2842,40 @@ function checkOptions(set, limits = {}) {
|
|
|
2514
2842
|
return { options: out, actions };
|
|
2515
2843
|
}
|
|
2516
2844
|
var CLAUDE_TEXT = {
|
|
2517
|
-
yes:
|
|
2518
|
-
no:
|
|
2519
|
-
noInput:
|
|
2845
|
+
yes: CC_TEXT.yes,
|
|
2846
|
+
no: CC_TEXT.no,
|
|
2847
|
+
noInput: CC_TEXT.noTell,
|
|
2520
2848
|
/** 单条 Bash 前缀规则:`Yes, and don’t ask again for: <规则>`(注意是弯撇号 U+2019) */
|
|
2521
|
-
dontAskPrefix:
|
|
2849
|
+
dontAskPrefix: CC_TEXT.dontAskPrefix,
|
|
2522
2850
|
/** 编辑类 setMode acceptEdits:整句作 label(101 字,用户拍板不拆;不含快捷键提示 `(shift+tab)`) */
|
|
2523
|
-
acceptEdits:
|
|
2851
|
+
acceptEdits: CC_TEXT.switchHead + CC_MODE_TEXT.acceptEdits + CC_TEXT.forSession,
|
|
2524
2852
|
/** Bash 的切 auto 模式(只在默认 / acceptEdits 模式下出现;非 workflow 来源时界面上带 ` · auto mode handles these prompts for you`) */
|
|
2525
|
-
autoMode:
|
|
2853
|
+
autoMode: CC_AUTO_LABEL,
|
|
2526
2854
|
/** 设备上给「切 auto 模式」的说明(问题表 272:它会把整个会话切过去,要写清楚) */
|
|
2527
|
-
autoModeDesc:
|
|
2528
|
-
/**
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
dirAccessTail: " from this project"
|
|
2855
|
+
autoModeDesc: CC_AUTO_DESC,
|
|
2856
|
+
/** Bash 碰到工作区外的目录(2.1.295 实测,问题表 272):`Yes, and always allow access to <目录> from this project` */
|
|
2857
|
+
dirAccessHead: CC_TEXT.alwaysAccessHead,
|
|
2858
|
+
dirAccessTail: CC_TEXT.fromProject,
|
|
2859
|
+
/** Bash 读工作区外的路径(问题表 278,2.1.295 实测 `ls /tmp | wc -l`):`Yes, allow reading from <目录> from this project` */
|
|
2860
|
+
readAccessHead: CC_TEXT.readHead
|
|
2534
2861
|
};
|
|
2535
|
-
var
|
|
2536
|
-
var CLAUDE_EDIT_TOOLS = /* @__PURE__ */ new Set(["Edit", "Write", "MultiEdit", "NotebookEdit"]);
|
|
2537
|
-
function claudeYesNo(middle, action, auto = false) {
|
|
2538
|
-
const options = [{ id: "allow", label: CLAUDE_TEXT.yes, kind: "allow" }];
|
|
2539
|
-
const actions = { allow: { decision: "allow" } };
|
|
2540
|
-
if (middle && action) {
|
|
2541
|
-
options.push(middle);
|
|
2542
|
-
actions[middle.id] = action;
|
|
2543
|
-
}
|
|
2544
|
-
if (auto) {
|
|
2545
|
-
options.push({ id: "auto", label: CLAUDE_TEXT.autoMode, description: CLAUDE_TEXT.autoModeDesc, kind: "allow_session" });
|
|
2546
|
-
actions.auto = { decision: "allow", updatedPermissions: [{ ...CLAUDE_AUTO_MODE_UPDATE }] };
|
|
2547
|
-
}
|
|
2548
|
-
options.push({ id: "deny", label: CLAUDE_TEXT.no, description: CLAUDE_TEXT.noInput, kind: "deny", input: true });
|
|
2549
|
-
actions.deny = { decision: "deny" };
|
|
2550
|
-
return { options, actions };
|
|
2551
|
-
}
|
|
2552
|
-
function claudeDirAccess(sugg) {
|
|
2553
|
-
if (sugg.length < 1 || sugg.length > 2) return null;
|
|
2554
|
-
let dir2 = null;
|
|
2555
|
-
let mode = 0;
|
|
2556
|
-
for (const x of sugg) {
|
|
2557
|
-
const s = x;
|
|
2558
|
-
if (s && s.type === "addDirectories" && s.destination === "session" && Array.isArray(s.directories) && s.directories.length === 1 && typeof s.directories[0] === "string" && s.directories[0]) {
|
|
2559
|
-
if (dir2 !== null) return null;
|
|
2560
|
-
dir2 = s.directories[0];
|
|
2561
|
-
} else if (s && s.type === "setMode" && s.mode === "acceptEdits" && s.destination === "session") mode++;
|
|
2562
|
-
else return null;
|
|
2563
|
-
}
|
|
2564
|
-
if (!dir2 || mode > 1 || /[\u0000-\u001f\u007f]/.test(dir2)) return null;
|
|
2565
|
-
return dir2;
|
|
2566
|
-
}
|
|
2862
|
+
var CLAUDE_FILE_TOOLS = /* @__PURE__ */ new Set(["Edit", "Write", "MultiEdit", "NotebookEdit", "Read"]);
|
|
2567
2863
|
function claudeOptions(toolName, suggestions, ctx = {}) {
|
|
2568
|
-
const
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
{ decision: "allow", updatedPermissions: sugg },
|
|
2579
|
-
auto
|
|
2580
|
-
)
|
|
2581
|
-
);
|
|
2582
|
-
}
|
|
2583
|
-
if (sugg.length !== 1) return null;
|
|
2584
|
-
const s = sugg[0];
|
|
2585
|
-
if (!s || s.type !== "addRules" || s.behavior !== "allow" || s.destination !== "localSettings") return null;
|
|
2586
|
-
const rules = Array.isArray(s.rules) ? s.rules : [];
|
|
2587
|
-
if (rules.length !== 1 || rules[0]?.toolName !== "Bash") return null;
|
|
2588
|
-
const rc = rules[0].ruleContent;
|
|
2589
|
-
if (typeof rc !== "string" || !rc.endsWith(" *") || rc.trim() === "*") return null;
|
|
2590
|
-
return checkOptions(
|
|
2591
|
-
claudeYesNo({ id: "always", label: CLAUDE_TEXT.dontAskPrefix + rc, kind: "allow_always" }, { decision: "allow", updatedPermissions: [s] }, auto)
|
|
2592
|
-
);
|
|
2593
|
-
}
|
|
2594
|
-
if (CLAUDE_EDIT_TOOLS.has(toolName)) {
|
|
2595
|
-
if (sugg.length !== 1) return null;
|
|
2596
|
-
const s = sugg[0];
|
|
2597
|
-
if (!s || s.type !== "setMode" || s.mode !== "acceptEdits" || s.destination !== "session") return null;
|
|
2598
|
-
return checkOptions(
|
|
2599
|
-
claudeYesNo(
|
|
2600
|
-
{ id: "session", label: CLAUDE_TEXT.acceptEdits, kind: "allow_session" },
|
|
2601
|
-
{ decision: "allow", updatedPermissions: [s] }
|
|
2602
|
-
)
|
|
2603
|
-
);
|
|
2864
|
+
const fallback = (auto) => {
|
|
2865
|
+
const set = checkOptions(yesRowNo(null, null, { auto }));
|
|
2866
|
+
return set && Array.isArray(suggestions) && suggestions.length > 0 ? { ...set, pcAllowAmbiguous: true } : set;
|
|
2867
|
+
};
|
|
2868
|
+
const lctx = { cwd: ctx.cwd, toolInput: ctx.toolInput, transcriptPath: ctx.transcriptPath, permissionMode: ctx.permissionMode, home: ctx.home ?? homedir3(), platform: ctx.platform };
|
|
2869
|
+
if (toolName === "Bash" || toolName === "PowerShell") {
|
|
2870
|
+
const auto = toolName === "Bash" && Array.isArray(suggestions) && ctx.autoModeAllowed === true && (ctx.permissionMode === "default" || ctx.permissionMode === "acceptEdits");
|
|
2871
|
+
if (!Array.isArray(suggestions)) return fallback(false);
|
|
2872
|
+
if (suggestions.length === 0) return fallback(auto);
|
|
2873
|
+
return checkOptions(claudeShellLabels(toolName, suggestions, auto, lctx)) ?? fallback(auto);
|
|
2604
2874
|
}
|
|
2605
|
-
|
|
2875
|
+
const sugg = Array.isArray(suggestions) ? suggestions : [];
|
|
2876
|
+
if (CLAUDE_FILE_TOOLS.has(toolName)) return checkOptions(claudeFileLabels(toolName, sugg, lctx)) ?? fallback(false);
|
|
2877
|
+
if (toolName === "WebFetch") return checkOptions(claudeWebFetchLabels(sugg, lctx)) ?? fallback(false);
|
|
2878
|
+
return fallback(false);
|
|
2606
2879
|
}
|
|
2607
2880
|
var CODEX_TEXT = {
|
|
2608
2881
|
mcpAllow: "Allow",
|
|
@@ -3747,7 +4020,7 @@ function resolveAlias(sessionId, now = Date.now()) {
|
|
|
3747
4020
|
// src/wrap/shim.ts
|
|
3748
4021
|
import { execFile as execFile3, execFileSync as execFileSync7 } from "child_process";
|
|
3749
4022
|
import { chmodSync as chmodSync3, existsSync as existsSync14, mkdirSync as mkdirSync16, readdirSync as readdirSync6, readFileSync as readFileSync17, rmdirSync, rmSync as rmSync9, writeFileSync as writeFileSync16 } from "fs";
|
|
3750
|
-
import { homedir as
|
|
4023
|
+
import { homedir as homedir4 } from "os";
|
|
3751
4024
|
import { delimiter, join as join15, resolve as resolve4 } from "path";
|
|
3752
4025
|
var SHIM_FALLBACK_EXIT = 213;
|
|
3753
4026
|
var WIN_SHIM_ENABLED = true;
|
|
@@ -4073,7 +4346,7 @@ function psWinWhere(exec = execFileSync7) {
|
|
|
4073
4346
|
function defaultShimEnv(nodePath, cliPath) {
|
|
4074
4347
|
const env = process.env;
|
|
4075
4348
|
const isolated = !!env.VITEST || !!env.DESKBUDDY_HOME;
|
|
4076
|
-
const rcHome = env.DESKBUDDY_RC_HOME || (isolated ? null :
|
|
4349
|
+
const rcHome = env.DESKBUDDY_RC_HOME || (isolated ? null : homedir4());
|
|
4077
4350
|
return {
|
|
4078
4351
|
platform: process.platform,
|
|
4079
4352
|
binDir: shimDir(),
|
|
@@ -4497,11 +4770,11 @@ function launchPending(runId) {
|
|
|
4497
4770
|
// src/core/title.ts
|
|
4498
4771
|
import { closeSync as closeSync3, existsSync as existsSync15, openSync as openSync3, readFileSync as readFileSync20, readSync as readSync3, statSync as statSync7 } from "fs";
|
|
4499
4772
|
import { createRequire as createRequire2 } from "module";
|
|
4500
|
-
import { homedir as
|
|
4773
|
+
import { homedir as homedir6 } from "os";
|
|
4501
4774
|
import { basename as basename3, dirname as dirname10, isAbsolute, join as join18 } from "path";
|
|
4502
4775
|
|
|
4503
4776
|
// src/core/dirFilter.ts
|
|
4504
|
-
import { homedir as
|
|
4777
|
+
import { homedir as homedir5, tmpdir as tmpdir2 } from "os";
|
|
4505
4778
|
import { posix, win32 as win323 } from "path";
|
|
4506
4779
|
function norm(p, win) {
|
|
4507
4780
|
if (win) return win323.resolve(p).replace(/[\\/]+$/, "").toLowerCase();
|
|
@@ -4514,7 +4787,7 @@ function isAutoWorkspace(p, opts = {}) {
|
|
|
4514
4787
|
if (!p) return false;
|
|
4515
4788
|
const win = (opts.platform ?? process.platform) === "win32";
|
|
4516
4789
|
const P = win ? win323 : posix;
|
|
4517
|
-
const home = norm(opts.home ??
|
|
4790
|
+
const home = norm(opts.home ?? homedir5(), win);
|
|
4518
4791
|
const full = norm(p, win);
|
|
4519
4792
|
const name = P.basename(full);
|
|
4520
4793
|
const parent = P.dirname(full);
|
|
@@ -4527,7 +4800,7 @@ function isReportableDir(p, opts = {}) {
|
|
|
4527
4800
|
const P = win ? win323 : posix;
|
|
4528
4801
|
const full = norm(p, win);
|
|
4529
4802
|
if (full === norm(P.parse(P.resolve(p)).root, win)) return false;
|
|
4530
|
-
if (full === norm(opts.home ??
|
|
4803
|
+
if (full === norm(opts.home ?? homedir5(), win)) return false;
|
|
4531
4804
|
const tmps = [opts.tmp ?? tmpdir2()];
|
|
4532
4805
|
if (!win) tmps.push("/tmp", "/private/tmp", "/var/folders", "/private/var/folders");
|
|
4533
4806
|
for (const t of tmps) if (t && isUnder(full, norm(t, win), win)) return false;
|
|
@@ -4536,6 +4809,7 @@ function isReportableDir(p, opts = {}) {
|
|
|
4536
4809
|
|
|
4537
4810
|
// src/core/title.ts
|
|
4538
4811
|
var TRANSCRIPT_TAIL_BYTES = 64 * 1024;
|
|
4812
|
+
var GIT_LOOKUP_MAX_UP = 5;
|
|
4539
4813
|
var SESSION_TITLE_MAX = 100;
|
|
4540
4814
|
function cleanTitle(text) {
|
|
4541
4815
|
if (typeof text !== "string") return "";
|
|
@@ -4543,9 +4817,21 @@ function cleanTitle(text) {
|
|
|
4543
4817
|
return Array.from(flat).slice(0, SESSION_TITLE_MAX).join("").trimEnd();
|
|
4544
4818
|
}
|
|
4545
4819
|
var requireHere = createRequire2(import.meta.url);
|
|
4820
|
+
function loadNodeSqlite() {
|
|
4821
|
+
const orig = process.emitWarning;
|
|
4822
|
+
process.emitWarning = function(...args) {
|
|
4823
|
+
if (String(args[0] ?? "").includes("SQLite")) return;
|
|
4824
|
+
return orig.apply(process, args);
|
|
4825
|
+
};
|
|
4826
|
+
try {
|
|
4827
|
+
return requireHere("node:sqlite");
|
|
4828
|
+
} finally {
|
|
4829
|
+
process.emitWarning = orig;
|
|
4830
|
+
}
|
|
4831
|
+
}
|
|
4546
4832
|
var QODER_DATA_DIRS = { qoder_cn: "com.qodercn.app.stable", qoder: "com.qoder.app.stable" };
|
|
4547
4833
|
var QODER_APP_DIR_ENV = { qoder_cn: "DESKBUDDY_QODER_CN_APP_DIR", qoder: "DESKBUDDY_QODER_APP_DIR" };
|
|
4548
|
-
function qoderDbPaths(tool, platform = process.platform, home =
|
|
4834
|
+
function qoderDbPaths(tool, platform = process.platform, home = homedir6(), env = process.env) {
|
|
4549
4835
|
let root;
|
|
4550
4836
|
if (platform === "darwin") root = join18(home, "Library", "Application Support");
|
|
4551
4837
|
else if (platform === "win32") root = env.APPDATA || join18(home, "AppData", "Roaming");
|
|
@@ -4554,11 +4840,157 @@ function qoderDbPaths(tool, platform = process.platform, home = homedir5(), env
|
|
|
4554
4840
|
const tools = one ? [tool] : ["qoder_cn", "qoder"];
|
|
4555
4841
|
return tools.map((t) => join18(env[QODER_APP_DIR_ENV[t] ?? ""] || join18(root, QODER_DATA_DIRS[t] ?? ""), "main.sqlite"));
|
|
4556
4842
|
}
|
|
4843
|
+
function readQoderSessionTitle(sessionId, paths = qoderDbPaths(null), load = loadNodeSqlite) {
|
|
4844
|
+
if (!sessionId) return null;
|
|
4845
|
+
const existing = paths.filter((p) => existsSync15(p));
|
|
4846
|
+
if (existing.length === 0) return null;
|
|
4847
|
+
let mod;
|
|
4848
|
+
try {
|
|
4849
|
+
mod = load();
|
|
4850
|
+
} catch {
|
|
4851
|
+
return null;
|
|
4852
|
+
}
|
|
4853
|
+
for (const p of existing) {
|
|
4854
|
+
let db;
|
|
4855
|
+
try {
|
|
4856
|
+
db = new mod.DatabaseSync(p, { readOnly: true });
|
|
4857
|
+
const row = db.prepare("select title from chat_sessions where session_id = ?").get(sessionId);
|
|
4858
|
+
const t = cleanTitle(row?.title);
|
|
4859
|
+
if (t) return t;
|
|
4860
|
+
} catch {
|
|
4861
|
+
} finally {
|
|
4862
|
+
try {
|
|
4863
|
+
db?.close();
|
|
4864
|
+
} catch {
|
|
4865
|
+
}
|
|
4866
|
+
}
|
|
4867
|
+
}
|
|
4868
|
+
return null;
|
|
4869
|
+
}
|
|
4870
|
+
function readTailLines(path, bytes) {
|
|
4871
|
+
let fd;
|
|
4872
|
+
try {
|
|
4873
|
+
const size = statSync7(path).size;
|
|
4874
|
+
if (size <= 0) return [];
|
|
4875
|
+
const len = Math.min(size, bytes);
|
|
4876
|
+
const buf = Buffer.alloc(len);
|
|
4877
|
+
fd = openSync3(path, "r");
|
|
4878
|
+
readSync3(fd, buf, 0, len, size - len);
|
|
4879
|
+
return buf.toString("utf8").split("\n");
|
|
4880
|
+
} catch {
|
|
4881
|
+
return [];
|
|
4882
|
+
} finally {
|
|
4883
|
+
if (fd !== void 0) {
|
|
4884
|
+
try {
|
|
4885
|
+
closeSync3(fd);
|
|
4886
|
+
} catch {
|
|
4887
|
+
}
|
|
4888
|
+
}
|
|
4889
|
+
}
|
|
4890
|
+
}
|
|
4891
|
+
function readAiTitle(transcriptPath) {
|
|
4892
|
+
if (!transcriptPath) return null;
|
|
4893
|
+
const lines = readTailLines(transcriptPath, TRANSCRIPT_TAIL_BYTES);
|
|
4894
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
4895
|
+
const line = lines[i];
|
|
4896
|
+
if (!line.includes('"ai-title"')) continue;
|
|
4897
|
+
try {
|
|
4898
|
+
const obj = JSON.parse(line);
|
|
4899
|
+
if (obj?.type === "ai-title") {
|
|
4900
|
+
const title = String(obj.aiTitle ?? "").trim();
|
|
4901
|
+
if (title !== "") return title;
|
|
4902
|
+
}
|
|
4903
|
+
} catch {
|
|
4904
|
+
}
|
|
4905
|
+
}
|
|
4906
|
+
return null;
|
|
4907
|
+
}
|
|
4908
|
+
function readCodexThreadName(sessionId, home) {
|
|
4909
|
+
if (!sessionId) return null;
|
|
4910
|
+
const indexPath = join18(home || codexHome(), "session_index.jsonl");
|
|
4911
|
+
const lines = readTailLines(indexPath, TRANSCRIPT_TAIL_BYTES);
|
|
4912
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
4913
|
+
const line = lines[i];
|
|
4914
|
+
if (!line.includes(sessionId)) continue;
|
|
4915
|
+
try {
|
|
4916
|
+
const obj = JSON.parse(line);
|
|
4917
|
+
if (obj?.id === sessionId) {
|
|
4918
|
+
const name = String(obj.thread_name ?? "").trim();
|
|
4919
|
+
if (name !== "") return name;
|
|
4920
|
+
}
|
|
4921
|
+
} catch {
|
|
4922
|
+
}
|
|
4923
|
+
}
|
|
4924
|
+
return null;
|
|
4925
|
+
}
|
|
4926
|
+
function readGitHead(dir2) {
|
|
4927
|
+
try {
|
|
4928
|
+
const dotGit = join18(dir2, ".git");
|
|
4929
|
+
let headPath = join18(dotGit, "HEAD");
|
|
4930
|
+
if (!statSync7(dotGit).isDirectory()) {
|
|
4931
|
+
const m = /^gitdir:\s*(.+)$/m.exec(readFileSync20(dotGit, "utf8"));
|
|
4932
|
+
if (!m) return null;
|
|
4933
|
+
const gitdir = m[1].trim();
|
|
4934
|
+
headPath = join18(isAbsolute(gitdir) ? gitdir : join18(dir2, gitdir), "HEAD");
|
|
4935
|
+
}
|
|
4936
|
+
return readFileSync20(headPath, "utf8").trim();
|
|
4937
|
+
} catch {
|
|
4938
|
+
return null;
|
|
4939
|
+
}
|
|
4940
|
+
}
|
|
4941
|
+
function readGitBranch(cwd, maxUp = GIT_LOOKUP_MAX_UP) {
|
|
4942
|
+
if (!cwd) return null;
|
|
4943
|
+
let dir2 = cwd;
|
|
4944
|
+
for (let up = 0; up <= maxUp; up++) {
|
|
4945
|
+
const head = readGitHead(dir2);
|
|
4946
|
+
if (head !== null) {
|
|
4947
|
+
const ref = /^ref:\s*refs\/heads\/(.+)$/.exec(head);
|
|
4948
|
+
if (!ref) return null;
|
|
4949
|
+
return ref[1].trim() || null;
|
|
4950
|
+
}
|
|
4951
|
+
const parent = dirname10(dir2);
|
|
4952
|
+
if (parent === dir2) break;
|
|
4953
|
+
dir2 = parent;
|
|
4954
|
+
}
|
|
4955
|
+
return null;
|
|
4956
|
+
}
|
|
4957
|
+
function resolveTitle(sources, ctx) {
|
|
4958
|
+
for (const source of sources ?? []) {
|
|
4959
|
+
let value = null;
|
|
4960
|
+
switch (source) {
|
|
4961
|
+
case "cc-ai-title":
|
|
4962
|
+
value = readAiTitle(ctx.transcriptPath);
|
|
4963
|
+
break;
|
|
4964
|
+
case "codex-thread-name":
|
|
4965
|
+
value = readCodexThreadName(ctx.sessionId, ctx.codexHome);
|
|
4966
|
+
break;
|
|
4967
|
+
case "git-branch":
|
|
4968
|
+
value = readGitBranch(ctx.cwd);
|
|
4969
|
+
break;
|
|
4970
|
+
case "first-prompt":
|
|
4971
|
+
value = ctx.firstPrompt || null;
|
|
4972
|
+
break;
|
|
4973
|
+
case "qoder-session-title":
|
|
4974
|
+
value = readQoderSessionTitle(ctx.sessionId, ctx.qoderDbPaths ?? qoderDbPaths(ctx.tool), ctx.loadSqlite);
|
|
4975
|
+
break;
|
|
4976
|
+
case "oc-session-title":
|
|
4977
|
+
value = typeof ctx.ocSessionTitle === "string" ? ctx.ocSessionTitle.trim() || null : null;
|
|
4978
|
+
break;
|
|
4979
|
+
case "project":
|
|
4980
|
+
value = ctx.cwd && !isAutoWorkspace(ctx.cwd) ? basename3(ctx.cwd) || null : null;
|
|
4981
|
+
break;
|
|
4982
|
+
default:
|
|
4983
|
+
value = null;
|
|
4984
|
+
}
|
|
4985
|
+
if (value) return value;
|
|
4986
|
+
}
|
|
4987
|
+
return "";
|
|
4988
|
+
}
|
|
4557
4989
|
|
|
4558
4990
|
// src/daemon/locate.ts
|
|
4559
4991
|
import { execFile as execFile4, execFileSync as execFileSync9 } from "child_process";
|
|
4560
4992
|
import { accessSync, closeSync as closeSync4, constants, existsSync as existsSync17, lstatSync, openSync as openSync4, readFileSync as readFileSync22, readSync as readSync4, realpathSync as realpathSync2, statSync as statSync8 } from "fs";
|
|
4561
|
-
import { homedir as
|
|
4993
|
+
import { homedir as homedir7 } from "os";
|
|
4562
4994
|
import { delimiter as delimiter2, dirname as dirname11, join as join20, win32 as win325 } from "path";
|
|
4563
4995
|
|
|
4564
4996
|
// src/core/agentEnv.ts
|
|
@@ -4856,7 +5288,7 @@ function qoderWorker(d, worker, appBin) {
|
|
|
4856
5288
|
return { file: d.nodePath, prefixArgs: [worker] };
|
|
4857
5289
|
}
|
|
4858
5290
|
var defaultLocateDeps = () => ({
|
|
4859
|
-
home:
|
|
5291
|
+
home: homedir7(),
|
|
4860
5292
|
path: process.env.PATH ?? "",
|
|
4861
5293
|
nodePath: process.execPath,
|
|
4862
5294
|
isExecutable: (p) => {
|
|
@@ -5540,7 +5972,7 @@ function markElectronBroken(v = true) {
|
|
|
5540
5972
|
electronBroken = v;
|
|
5541
5973
|
}
|
|
5542
5974
|
var requireHere2 = createRequire3(import.meta.url);
|
|
5543
|
-
function
|
|
5975
|
+
function loadNodeSqlite2() {
|
|
5544
5976
|
const orig = process.emitWarning;
|
|
5545
5977
|
process.emitWarning = function(...args) {
|
|
5546
5978
|
if (String(args[0] ?? "").includes("SQLite")) return;
|
|
@@ -5626,7 +6058,7 @@ function savePendingFile(jobs) {
|
|
|
5626
6058
|
var defaultWbAppDbDeps = () => ({
|
|
5627
6059
|
dbPath: () => workbuddyDbPath(),
|
|
5628
6060
|
configDir: () => dirname12(workbuddySettingsPath()),
|
|
5629
|
-
loadSqlite:
|
|
6061
|
+
loadSqlite: loadNodeSqlite2,
|
|
5630
6062
|
electron: () => defaultWbElectron(),
|
|
5631
6063
|
runElectron: (bin, script, input) => new Promise((resolve7, reject) => {
|
|
5632
6064
|
const env = { ...process.env, ELECTRON_RUN_AS_NODE: "1" };
|
|
@@ -5909,6 +6341,52 @@ var WsCdpClient = class {
|
|
|
5909
6341
|
|
|
5910
6342
|
// src/daemon/workbuddyApp/keeper.ts
|
|
5911
6343
|
import { posix as posix2, win32 as win326 } from "path";
|
|
6344
|
+
|
|
6345
|
+
// src/daemon/userIdle.ts
|
|
6346
|
+
function parseHidIdleMs(out) {
|
|
6347
|
+
const m = /"HIDIdleTime"\s*=\s*(\d+)/.exec(out);
|
|
6348
|
+
return m ? Math.floor(Number(m[1]) / 1e6) : null;
|
|
6349
|
+
}
|
|
6350
|
+
var WIN_PRESENCE_PS = String.raw`Add-Type @"
|
|
6351
|
+
using System; using System.Runtime.InteropServices;
|
|
6352
|
+
public class DbUserIdle {
|
|
6353
|
+
[StructLayout(LayoutKind.Sequential)] public struct LII { public uint cbSize; public uint dwTime; }
|
|
6354
|
+
[DllImport("user32.dll")] public static extern bool GetLastInputInfo(ref LII p);
|
|
6355
|
+
[DllImport("kernel32.dll")] public static extern uint GetTickCount();
|
|
6356
|
+
[DllImport("user32.dll")] public static extern IntPtr GetForegroundWindow();
|
|
6357
|
+
[DllImport("user32.dll")] public static extern uint GetWindowThreadProcessId(IntPtr h, out uint pid);
|
|
6358
|
+
}
|
|
6359
|
+
"@
|
|
6360
|
+
$l = New-Object DbUserIdle+LII; $l.cbSize = 8
|
|
6361
|
+
if (-not [DbUserIdle]::GetLastInputInfo([ref]$l)) { exit 1 }
|
|
6362
|
+
$idle = (([uint64][DbUserIdle]::GetTickCount()) - [uint64]$l.dwTime + 4294967296) % 4294967296
|
|
6363
|
+
$fp = [uint32]0; [void][DbUserIdle]::GetWindowThreadProcessId([DbUserIdle]::GetForegroundWindow(), [ref]$fp)
|
|
6364
|
+
$n = ''; try { $n = (Get-Process -Id $fp -ErrorAction Stop).ProcessName } catch {}
|
|
6365
|
+
Write-Output ("{0}|{1}" -f $idle, $n)`;
|
|
6366
|
+
function parseWinPresence(code, stdout2) {
|
|
6367
|
+
const m = /^(\d+)\|(.*)$/m.exec(stdout2.trim());
|
|
6368
|
+
if (code !== 0 || !m) return null;
|
|
6369
|
+
return { idleMs: Number(m[1]), front: m[2].trim() };
|
|
6370
|
+
}
|
|
6371
|
+
async function macIdleMs(exec) {
|
|
6372
|
+
const r = await exec("ioreg", ["-c", "IOHIDSystem", "-d", "4"]);
|
|
6373
|
+
return r.code === 0 ? parseHidIdleMs(r.stdout) : null;
|
|
6374
|
+
}
|
|
6375
|
+
async function winPresence(exec) {
|
|
6376
|
+
const r = await exec("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", WIN_PRESENCE_PS], 15e3);
|
|
6377
|
+
return parseWinPresence(r.code, r.stdout);
|
|
6378
|
+
}
|
|
6379
|
+
async function userIdleMs(exec, platform = process.platform) {
|
|
6380
|
+
try {
|
|
6381
|
+
if (platform === "darwin") return await macIdleMs(exec);
|
|
6382
|
+
if (platform === "win32") return (await winPresence(exec))?.idleMs ?? null;
|
|
6383
|
+
} catch {
|
|
6384
|
+
return null;
|
|
6385
|
+
}
|
|
6386
|
+
return null;
|
|
6387
|
+
}
|
|
6388
|
+
|
|
6389
|
+
// src/daemon/workbuddyApp/keeper.ts
|
|
5912
6390
|
var DEFAULT_CDP_PORT = 39217;
|
|
5913
6391
|
var ENV_NAME = "WORKBUDDY_REMOTE_DEBUGGING_PORT";
|
|
5914
6392
|
var RESTART_GAP_MS = 30 * 60 * 1e3;
|
|
@@ -5989,26 +6467,6 @@ var filePersist = {
|
|
|
5989
6467
|
}
|
|
5990
6468
|
}
|
|
5991
6469
|
};
|
|
5992
|
-
function parseHidIdleMs(out) {
|
|
5993
|
-
const m = /"HIDIdleTime"\s*=\s*(\d+)/.exec(out);
|
|
5994
|
-
return m ? Math.floor(Number(m[1]) / 1e6) : null;
|
|
5995
|
-
}
|
|
5996
|
-
var WIN_PRESENCE_PS = String.raw`Add-Type @"
|
|
5997
|
-
using System; using System.Runtime.InteropServices;
|
|
5998
|
-
public class DbUserIdle {
|
|
5999
|
-
[StructLayout(LayoutKind.Sequential)] public struct LII { public uint cbSize; public uint dwTime; }
|
|
6000
|
-
[DllImport("user32.dll")] public static extern bool GetLastInputInfo(ref LII p);
|
|
6001
|
-
[DllImport("kernel32.dll")] public static extern uint GetTickCount();
|
|
6002
|
-
[DllImport("user32.dll")] public static extern IntPtr GetForegroundWindow();
|
|
6003
|
-
[DllImport("user32.dll")] public static extern uint GetWindowThreadProcessId(IntPtr h, out uint pid);
|
|
6004
|
-
}
|
|
6005
|
-
"@
|
|
6006
|
-
$l = New-Object DbUserIdle+LII; $l.cbSize = 8
|
|
6007
|
-
if (-not [DbUserIdle]::GetLastInputInfo([ref]$l)) { exit 1 }
|
|
6008
|
-
$idle = (([uint64][DbUserIdle]::GetTickCount()) - [uint64]$l.dwTime + 4294967296) % 4294967296
|
|
6009
|
-
$fp = [uint32]0; [void][DbUserIdle]::GetWindowThreadProcessId([DbUserIdle]::GetForegroundWindow(), [ref]$fp)
|
|
6010
|
-
$n = ''; try { $n = (Get-Process -Id $fp -ErrorAction Stop).ProcessName } catch {}
|
|
6011
|
-
Write-Output ("{0}|{1}" -f $idle, $n)`;
|
|
6012
6470
|
var WAKE_LAUNCH_GAP_MS = 60 * 1e3;
|
|
6013
6471
|
var APP_PATH_TTL_MS = 5 * 60 * 1e3;
|
|
6014
6472
|
function defaultWorkbuddyAppPath() {
|
|
@@ -6263,7 +6721,7 @@ var CdpKeeper = class {
|
|
|
6263
6721
|
if (this.#d.userAway) return await this.#d.userAway();
|
|
6264
6722
|
const exec = this.#exec();
|
|
6265
6723
|
if (this.#platform() === "darwin") {
|
|
6266
|
-
const idle =
|
|
6724
|
+
const idle = await macIdleMs(exec);
|
|
6267
6725
|
if (idle === null || idle < AWAY_IDLE_MS) return false;
|
|
6268
6726
|
const asn = (await exec("lsappinfo", ["front"])).stdout.trim();
|
|
6269
6727
|
if (!asn) return false;
|
|
@@ -6271,10 +6729,9 @@ var CdpKeeper = class {
|
|
|
6271
6729
|
return !!name.trim() && !/WorkBuddy/i.test(name);
|
|
6272
6730
|
}
|
|
6273
6731
|
if (this.#platform() === "win32") {
|
|
6274
|
-
const
|
|
6275
|
-
|
|
6276
|
-
|
|
6277
|
-
return Number(m[1]) >= AWAY_IDLE_MS && !/^WorkBuddy$/i.test(m[2].trim());
|
|
6732
|
+
const p = await winPresence(exec);
|
|
6733
|
+
if (!p) return false;
|
|
6734
|
+
return p.idleMs >= AWAY_IDLE_MS && !/^WorkBuddy$/i.test(p.front);
|
|
6278
6735
|
}
|
|
6279
6736
|
} catch {
|
|
6280
6737
|
return false;
|
|
@@ -8535,7 +8992,7 @@ function runHook(node, input, agentPid, tool = "dumate") {
|
|
|
8535
8992
|
|
|
8536
8993
|
// src/daemon/qoderApp/keeper.ts
|
|
8537
8994
|
import { existsSync as existsSync20, mkdirSync as mkdirSync22, readdirSync as readdirSync12, readFileSync as readFileSync25, renameSync as renameSync16, writeFileSync as writeFileSync22 } from "fs";
|
|
8538
|
-
import { homedir as
|
|
8995
|
+
import { homedir as homedir8 } from "os";
|
|
8539
8996
|
import { join as join24, win32 as win327 } from "path";
|
|
8540
8997
|
var WAKE_LAUNCH_GAP_MS2 = 60 * 1e3;
|
|
8541
8998
|
var RESTART_GAP_MS2 = 30 * 60 * 1e3;
|
|
@@ -8594,10 +9051,6 @@ function hasMainProc(psOut, brand) {
|
|
|
8594
9051
|
}
|
|
8595
9052
|
return false;
|
|
8596
9053
|
}
|
|
8597
|
-
function parseHidIdleMs2(out) {
|
|
8598
|
-
const m = /"HIDIdleTime"\s*=\s*(\d+)/.exec(out);
|
|
8599
|
-
return m ? Math.floor(Number(m[1]) / 1e6) : null;
|
|
8600
|
-
}
|
|
8601
9054
|
function parseLsappBundle(out) {
|
|
8602
9055
|
const m = /"CFBundleIdentifier"\s*=\s*"([^"]+)"/.exec(out);
|
|
8603
9056
|
return m ? m[1] : null;
|
|
@@ -8836,7 +9289,7 @@ var QoderCdpKeeper = class {
|
|
|
8836
9289
|
}
|
|
8837
9290
|
if (this.#platform() !== "darwin") return null;
|
|
8838
9291
|
const name = this.#d.brand.macApp.split("/").pop() ?? "";
|
|
8839
|
-
for (const p of [this.#d.brand.macApp, join24(
|
|
9292
|
+
for (const p of [this.#d.brand.macApp, join24(homedir8(), "Applications", name)]) if (existsSync20(p)) return p;
|
|
8840
9293
|
return null;
|
|
8841
9294
|
}
|
|
8842
9295
|
/** 一轮:健康检查 → 活着核对属主。🔴 平时不重启 App;只有端口无响应满 HUNG_RESTART_MS 时按节流与在场规则重启 */
|
|
@@ -8878,10 +9331,9 @@ var QoderCdpKeeper = class {
|
|
|
8878
9331
|
async userAway() {
|
|
8879
9332
|
if (this.#isWin() && !this.#d.frontBundle && !this.#d.idleMs) {
|
|
8880
9333
|
try {
|
|
8881
|
-
const
|
|
8882
|
-
|
|
8883
|
-
|
|
8884
|
-
return Number(m[1]) >= USER_IDLE_MS && !!m[2].trim() && !this.#d.brand.win.fgName.test(m[2].trim());
|
|
9334
|
+
const p = await winPresence(this.#exec());
|
|
9335
|
+
if (!p) return false;
|
|
9336
|
+
return p.idleMs >= USER_IDLE_MS && !!p.front && !this.#d.brand.win.fgName.test(p.front);
|
|
8885
9337
|
} catch {
|
|
8886
9338
|
return false;
|
|
8887
9339
|
}
|
|
@@ -8904,8 +9356,7 @@ var QoderCdpKeeper = class {
|
|
|
8904
9356
|
return parseLsappBundle((await exec("lsappinfo", ["info", "-only", "bundleid", asn])).stdout);
|
|
8905
9357
|
}
|
|
8906
9358
|
async #defaultIdle() {
|
|
8907
|
-
|
|
8908
|
-
return r.code === 0 ? parseHidIdleMs2(r.stdout) : null;
|
|
9359
|
+
return macIdleMs(this.#exec());
|
|
8909
9360
|
}
|
|
8910
9361
|
/** 主进程(macOS;只认唯一一个;没有 / 认不出 / 多个 → null) */
|
|
8911
9362
|
async #brandMain() {
|
|
@@ -10272,12 +10723,12 @@ function migrateLegacyQoder(out, detect = () => detectTools()) {
|
|
|
10272
10723
|
// src/daemon/loginGuide.ts
|
|
10273
10724
|
import { execFile as execFile9, execFileSync as execFileSync13 } from "child_process";
|
|
10274
10725
|
import { chmodSync as chmodSync9, existsSync as existsSync27, mkdirSync as mkdirSync26, readFileSync as readFileSync30, writeFileSync as writeFileSync26 } from "fs";
|
|
10275
|
-
import { homedir as
|
|
10726
|
+
import { homedir as homedir10 } from "os";
|
|
10276
10727
|
import { join as join35 } from "path";
|
|
10277
10728
|
|
|
10278
10729
|
// src/daemon/executor.ts
|
|
10279
10730
|
import { execFile as execFile7, execFileSync as execFileSync11 } from "child_process";
|
|
10280
|
-
import { homedir as
|
|
10731
|
+
import { homedir as homedir9 } from "os";
|
|
10281
10732
|
import { join as join33 } from "path";
|
|
10282
10733
|
|
|
10283
10734
|
// src/core/codebuddyDirs.ts
|
|
@@ -10371,7 +10822,7 @@ var TOOL_BINARY = {
|
|
|
10371
10822
|
opencode: "opencode",
|
|
10372
10823
|
deepseek_harness: "dsh"
|
|
10373
10824
|
};
|
|
10374
|
-
function buildSpawnPlan(cmd, cwd, gate, home =
|
|
10825
|
+
function buildSpawnPlan(cmd, cwd, gate, home = homedir9(), configDir, platform = process.platform) {
|
|
10375
10826
|
const file3 = TOOL_BINARY[cmd.tool];
|
|
10376
10827
|
if (!file3) return null;
|
|
10377
10828
|
switch (cmd.tool) {
|
|
@@ -10951,7 +11402,7 @@ var defaultCheckDeps = () => ({
|
|
|
10951
11402
|
run: defaultProbeRun,
|
|
10952
11403
|
env: process.env,
|
|
10953
11404
|
childPath: () => childPath(),
|
|
10954
|
-
home:
|
|
11405
|
+
home: homedir10(),
|
|
10955
11406
|
codexConfig: () => {
|
|
10956
11407
|
try {
|
|
10957
11408
|
return readFileSync30(join35(codexHome(), "config.toml"), "utf8");
|
|
@@ -10963,7 +11414,7 @@ var defaultCheckDeps = () => ({
|
|
|
10963
11414
|
workbuddyKind: () => locateWorkbuddy()?.kind ?? null,
|
|
10964
11415
|
// 与设备任务唤起 App 同一个 locate(locateWorkbuddyAppExe:注册表卸载项 / App Paths / 开始菜单快捷方式…);App 自带 CLI 找得到也算
|
|
10965
11416
|
workbuddyAppInstalled: () => locateWorkbuddyAppExe() !== null || locateWorkbuddyApp() !== null,
|
|
10966
|
-
workbuddyAuthFile: () => workbuddyAuthFile(
|
|
11417
|
+
workbuddyAuthFile: () => workbuddyAuthFile(homedir10(), process.platform, process.env.LOCALAPPDATA ?? ""),
|
|
10967
11418
|
exists: (p) => existsSync27(p)
|
|
10968
11419
|
});
|
|
10969
11420
|
function daemonCheckDeps(base = defaultLocateDeps(), exeHintsAsync = winWorkbuddyLocatorHints) {
|
|
@@ -10986,7 +11437,7 @@ var SAFE_ARGS = /* @__PURE__ */ new Set(["auth", "login"]);
|
|
|
10986
11437
|
var defaultCommandDeps = () => ({
|
|
10987
11438
|
locate: (tool) => locate(tool),
|
|
10988
11439
|
locateWorkbuddyTui: () => locateWorkbuddyTui(),
|
|
10989
|
-
home:
|
|
11440
|
+
home: homedir10()
|
|
10990
11441
|
});
|
|
10991
11442
|
var WORKBUDDY_LOGIN_HINT = "\uFF08\u5982\u679C\u5148\u5F39\u51FA\u4FE1\u4EFB\u6846\uFF0C\u9009 1 \u56DE\u8F66\uFF1B\u51FA\u73B0 Select login method \u65F6\u9009 Log in via Chinese Site \u56DE\u8F66\uFF0C\u5230\u6D4F\u89C8\u5668\u5B8C\u6210\u767B\u5F55\uFF1B\u82E5\u53EA\u770B\u5230\u8F93\u5165\u6846\uFF0C\u8F93\u5165 /login \u56DE\u8F66\uFF09";
|
|
10992
11443
|
var WORKBUDDY_NEED_STANDALONE = "\u53EA\u88C5\u4E86 WorkBuddy App\uFF0C\u5B83\u81EA\u5E26\u7684\u547D\u4EE4\u884C\u7528\u4E0D\u4E86 App \u7684\u767B\u5F55\uFF1B\u8BBE\u5907\u4E0A\u65B0\u5EFA / \u56DE\u590D\u4EFB\u52A1\u9700\u8981\u72EC\u7ACB\u7248\u547D\u4EE4\u884C\uFF08\u8FD0\u884C deskbuddy workbuddy-setup \u5B89\u88C5\uFF09";
|
|
@@ -11112,7 +11563,7 @@ var defaultLoginOpenDeps = () => ({
|
|
|
11112
11563
|
});
|
|
11113
11564
|
async function installCodebuddyHooks(log) {
|
|
11114
11565
|
try {
|
|
11115
|
-
const { installTools: installTools2 } = await import("./enable-
|
|
11566
|
+
const { installTools: installTools2 } = await import("./enable-OICEMNUF.js");
|
|
11116
11567
|
installTools2(["workbuddy"], () => {
|
|
11117
11568
|
}, null, { auto: true });
|
|
11118
11569
|
} catch (e) {
|
|
@@ -11626,7 +12077,7 @@ function defaultOfferDeps(log) {
|
|
|
11626
12077
|
}),
|
|
11627
12078
|
openLogin: () => defaultOpenLogin(platform),
|
|
11628
12079
|
installHooks: async () => {
|
|
11629
|
-
const { installTools: installTools2 } = await import("./enable-
|
|
12080
|
+
const { installTools: installTools2 } = await import("./enable-OICEMNUF.js");
|
|
11630
12081
|
installTools2(["workbuddy"], (l) => log(`[WorkBuddy \u72EC\u7ACB\u7248] ${l}`), null, { auto: true });
|
|
11631
12082
|
},
|
|
11632
12083
|
log: (l) => log(`[WorkBuddy \u72EC\u7ACB\u7248] ${l}`),
|
|
@@ -11962,6 +12413,7 @@ export {
|
|
|
11962
12413
|
detectTools,
|
|
11963
12414
|
loadRegistry,
|
|
11964
12415
|
refreshRegistry,
|
|
12416
|
+
titleSources,
|
|
11965
12417
|
waitModeFor,
|
|
11966
12418
|
shQuote,
|
|
11967
12419
|
winCmdPath,
|
|
@@ -12002,8 +12454,10 @@ export {
|
|
|
12002
12454
|
isAppSession,
|
|
12003
12455
|
stateDir,
|
|
12004
12456
|
readState,
|
|
12457
|
+
renameRetrying,
|
|
12005
12458
|
writeState,
|
|
12006
12459
|
retireState,
|
|
12460
|
+
removeState,
|
|
12007
12461
|
STALE_NO_PID_LOG,
|
|
12008
12462
|
readAliveStates,
|
|
12009
12463
|
writeNotice,
|
|
@@ -12045,11 +12499,13 @@ export {
|
|
|
12045
12499
|
isReportableDir,
|
|
12046
12500
|
cleanTitle,
|
|
12047
12501
|
qoderDbPaths,
|
|
12502
|
+
resolveTitle,
|
|
12048
12503
|
findWbTranscript,
|
|
12049
12504
|
wbTranscriptInfo,
|
|
12050
12505
|
registerWorkbuddySession,
|
|
12051
12506
|
flushPendingWorkbuddy,
|
|
12052
12507
|
connectCdp,
|
|
12508
|
+
userIdleMs,
|
|
12053
12509
|
DEFAULT_CDP_PORT,
|
|
12054
12510
|
defaultExec,
|
|
12055
12511
|
APP_PORT_HUNG_REASON,
|