deskbuddy 0.2.0-beta.31 → 0.2.0-beta.32
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-WMCE7UNE.js → chunk-4ICQ3BAL.js} +278 -79
- package/dist/cli.js +583 -345
- package/dist/deskbuddy-dsh.mjs +139 -3
- package/dist/{enable-EDDFXBHM.js → enable-SIY4AEF7.js} +1 -1
- package/dist/gate.cjs +40 -3
- package/dist/hook.cjs +3 -1
- package/dist/opencode.mjs +84 -4
- package/hook/deskbuddy-dsh.d.mts +10 -0
- package/hook/deskbuddy-dsh.mjs +139 -3
- package/hook/gate.cjs +40 -3
- package/hook/hook-debug.log +24 -0
- package/hook/hook.cjs +3 -1
- package/hook/opencode.d.mts +3 -0
- package/hook/opencode.mjs +84 -4
- package/package.json +1 -1
|
@@ -67,6 +67,9 @@ function qoderCnSettingsPath() {
|
|
|
67
67
|
function qwenworkHome() {
|
|
68
68
|
return process.env.DESKBUDDY_QWENWORK_DIR || join(homedir(), ".QwenWorkCN");
|
|
69
69
|
}
|
|
70
|
+
function qwenworkDataHome() {
|
|
71
|
+
return process.env.DESKBUDDY_QWENWORK_CN_HOME || join(homedir(), ".qwenworkcn");
|
|
72
|
+
}
|
|
70
73
|
function qwenworkSettingsPath() {
|
|
71
74
|
return join(qwenworkHome(), "settings.json");
|
|
72
75
|
}
|
|
@@ -1523,6 +1526,19 @@ function installCcWindowGate(settingsPath, gatePath, tool = "claude_code", platf
|
|
|
1523
1526
|
});
|
|
1524
1527
|
writeSettings(settingsPath, settings);
|
|
1525
1528
|
}
|
|
1529
|
+
var PRETOOL_QUESTION_TIMEOUT_S = 660;
|
|
1530
|
+
var PRETOOL_QUESTION_MATCHER = "^AskUserQuestion$";
|
|
1531
|
+
function installCcPreToolQuestion(settingsPath, gatePath, tool, platform = process.platform) {
|
|
1532
|
+
const settings = readSettings(settingsPath);
|
|
1533
|
+
settings.hooks ??= {};
|
|
1534
|
+
const groups = settings.hooks.PreToolUse ??= [];
|
|
1535
|
+
if (groups.some((g) => g.hooks?.some((h) => mentions(h.command, gatePath) && h.command.includes("--pretool-question")))) return;
|
|
1536
|
+
groups.push({
|
|
1537
|
+
matcher: PRETOOL_QUESTION_MATCHER,
|
|
1538
|
+
hooks: [{ type: "command", command: `node ${scriptArg(gatePath, platform, shQuote2)} --pretool-question --tool ${tool}`, timeout: PRETOOL_QUESTION_TIMEOUT_S }]
|
|
1539
|
+
});
|
|
1540
|
+
writeSettings(settingsPath, settings);
|
|
1541
|
+
}
|
|
1526
1542
|
var REWAKE_TIMEOUT_S = 20 * 24 * 60 * 60;
|
|
1527
1543
|
var REWAKE_MESSAGE = "\u4EE5\u4E0B\u662F\u4E00\u6761 DeskBuddy \u8BBE\u5907\u6307\u4EE4\uFF08\u6309\u4F1A\u8BDD\u5F00\u5934 DeskBuddy \u8BF4\u660E\u91CC\u7684\u53E3\u4EE4\u6838\u5BF9\uFF0C\u53E3\u4EE4\u4E00\u81F4\u624D\u7167\u5E38\u6267\u884C\uFF0C\u5B8C\u6210\u540E\u7B80\u8981\u56DE\u590D\u7ED3\u679C\uFF09\uFF1A";
|
|
1528
1544
|
var REWAKE_SUMMARY = "DeskBuddy \u8BBE\u5907\u6307\u4EE4";
|
|
@@ -1875,7 +1891,7 @@ import { join as join26 } from "path";
|
|
|
1875
1891
|
|
|
1876
1892
|
// src/daemon/appShortcuts.ts
|
|
1877
1893
|
import { execFile as execFile2, execFileSync as execFileSync4 } from "child_process";
|
|
1878
|
-
import { mkdirSync as mkdirSync11, readFileSync as
|
|
1894
|
+
import { mkdirSync as mkdirSync11, readFileSync as readFileSync13, renameSync as renameSync8, writeFileSync as writeFileSync11 } from "fs";
|
|
1879
1895
|
import { join as join10, win32 as win322 } from "path";
|
|
1880
1896
|
|
|
1881
1897
|
// src/core/fileLock.ts
|
|
@@ -1938,7 +1954,25 @@ function pidAlive2(pid) {
|
|
|
1938
1954
|
}
|
|
1939
1955
|
|
|
1940
1956
|
// src/daemon/winPaths.ts
|
|
1957
|
+
import { readFileSync as readFileSync12, statSync as statSync4 } from "fs";
|
|
1941
1958
|
import { win32 } from "path";
|
|
1959
|
+
function decodeText(b) {
|
|
1960
|
+
if (b.length >= 2 && b[0] === 255 && b[1] === 254) return b.subarray(2).toString("utf16le");
|
|
1961
|
+
if (b.length >= 2 && b[0] === 254 && b[1] === 255) {
|
|
1962
|
+
const be = Buffer.from(b.subarray(2, 2 + (b.length - 2 & ~1)));
|
|
1963
|
+
return be.swap16().toString("utf16le");
|
|
1964
|
+
}
|
|
1965
|
+
if (b.length >= 3 && b[0] === 239 && b[1] === 187 && b[2] === 191) return b.subarray(3).toString("utf8");
|
|
1966
|
+
return b.toString("utf8");
|
|
1967
|
+
}
|
|
1968
|
+
function readSmallText(p) {
|
|
1969
|
+
try {
|
|
1970
|
+
if (statSync4(p).size > 64 * 1024) return null;
|
|
1971
|
+
return decodeText(readFileSync12(p));
|
|
1972
|
+
} catch {
|
|
1973
|
+
return null;
|
|
1974
|
+
}
|
|
1975
|
+
}
|
|
1942
1976
|
function isValidWinPath(p) {
|
|
1943
1977
|
if (typeof p !== "string" || p.length < 4 || p.length > 1024) return false;
|
|
1944
1978
|
if (!/^[a-z]:\\/i.test(p)) return false;
|
|
@@ -2055,12 +2089,7 @@ function launcherTargets(list, writes, exe) {
|
|
|
2055
2089
|
return [...out];
|
|
2056
2090
|
}
|
|
2057
2091
|
function readSmall(p) {
|
|
2058
|
-
|
|
2059
|
-
if (statSync4(p).size > 64 * 1024) return null;
|
|
2060
|
-
return readFileSync12(p, "utf8");
|
|
2061
|
-
} catch {
|
|
2062
|
-
return null;
|
|
2063
|
-
}
|
|
2092
|
+
return readSmallText(p);
|
|
2064
2093
|
}
|
|
2065
2094
|
var keyOf = (p) => p.toLowerCase();
|
|
2066
2095
|
function planPatchFor(exe, list, records, port) {
|
|
@@ -2092,7 +2121,7 @@ function recordsFile(app) {
|
|
|
2092
2121
|
}
|
|
2093
2122
|
function loadRecords(file3) {
|
|
2094
2123
|
try {
|
|
2095
|
-
const v = JSON.parse(
|
|
2124
|
+
const v = JSON.parse(readFileSync13(file3, "utf8"));
|
|
2096
2125
|
if (!v || typeof v !== "object") return {};
|
|
2097
2126
|
const out = {};
|
|
2098
2127
|
for (const [k, r] of Object.entries(v)) {
|
|
@@ -2161,7 +2190,7 @@ var writeEnv = (app, ops, list) => ({
|
|
|
2161
2190
|
var matcherOf = (app, d, restore = false) => lnkMatcher(app, d.readText, restore);
|
|
2162
2191
|
function loadFails(app, d) {
|
|
2163
2192
|
try {
|
|
2164
|
-
const v = JSON.parse(
|
|
2193
|
+
const v = JSON.parse(readFileSync13(failFileOf(app, d), "utf8"));
|
|
2165
2194
|
const out = {};
|
|
2166
2195
|
for (const [k, t] of Object.entries(v ?? {})) if (typeof t === "number") out[k] = t;
|
|
2167
2196
|
return out;
|
|
@@ -2317,12 +2346,12 @@ function restoreAppShortcutsSync(app, d, ps = defaultPsSync) {
|
|
|
2317
2346
|
}
|
|
2318
2347
|
|
|
2319
2348
|
// src/daemon/dumateApp/keeper.ts
|
|
2320
|
-
import { readdirSync as readdirSync13, statSync as
|
|
2349
|
+
import { readdirSync as readdirSync13, statSync as statSync11 } from "fs";
|
|
2321
2350
|
import { join as join25 } from "path";
|
|
2322
2351
|
|
|
2323
2352
|
// src/daemon/dumateWatch.ts
|
|
2324
2353
|
import { execFileSync as execFileSync10, spawn as spawn3 } from "child_process";
|
|
2325
|
-
import { readdirSync as readdirSync11, realpathSync as realpathSync4, statSync as
|
|
2354
|
+
import { readdirSync as readdirSync11, realpathSync as realpathSync4, statSync as statSync10 } from "fs";
|
|
2326
2355
|
import { request as httpRequest } from "http";
|
|
2327
2356
|
import { join as join23 } from "path";
|
|
2328
2357
|
|
|
@@ -3039,7 +3068,7 @@ function traeNoticeSummary(toolName, toolInput, described, notice) {
|
|
|
3039
3068
|
|
|
3040
3069
|
// src/daemon/workbuddyApp/keeper.ts
|
|
3041
3070
|
import { execFile as execFile6, spawn as spawn2 } from "child_process";
|
|
3042
|
-
import { existsSync as existsSync19, mkdirSync as mkdirSync21, readdirSync as readdirSync10, readFileSync as
|
|
3071
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync21, readdirSync as readdirSync10, readFileSync as readFileSync24, renameSync as renameSync15, writeFileSync as writeFileSync21 } from "fs";
|
|
3043
3072
|
import { delimiter as delimiter3, join as join22, resolve as resolve4 } from "path";
|
|
3044
3073
|
|
|
3045
3074
|
// src/core/process.ts
|
|
@@ -3102,7 +3131,7 @@ function isAlive(pid, expectName, kill = process.kill.bind(process)) {
|
|
|
3102
3131
|
}
|
|
3103
3132
|
|
|
3104
3133
|
// src/core/state.ts
|
|
3105
|
-
import { existsSync as existsSync13, mkdirSync as mkdirSync15, readdirSync as readdirSync5, readFileSync as
|
|
3134
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync15, readdirSync as readdirSync5, readFileSync as readFileSync16, renameSync as renameSync10, rmSync as rmSync8, writeFileSync as writeFileSync15 } from "fs";
|
|
3106
3135
|
import { join as join14 } from "path";
|
|
3107
3136
|
|
|
3108
3137
|
// src/core/codexServer.ts
|
|
@@ -3153,7 +3182,7 @@ function programOf(args) {
|
|
|
3153
3182
|
}
|
|
3154
3183
|
|
|
3155
3184
|
// src/core/ended.ts
|
|
3156
|
-
import { closeSync, mkdirSync as mkdirSync12, openSync, readdirSync as readdirSync2, readFileSync as
|
|
3185
|
+
import { closeSync, mkdirSync as mkdirSync12, openSync, readdirSync as readdirSync2, readFileSync as readFileSync14, readSync, realpathSync, renameSync as renameSync9, rmSync as rmSync5, statSync as statSync5, writeFileSync as writeFileSync12 } from "fs";
|
|
3157
3186
|
import { join as join11 } from "path";
|
|
3158
3187
|
var ENDED_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
3159
3188
|
var SID_RE = /^[A-Za-z0-9_-]{1,64}$/;
|
|
@@ -3185,7 +3214,7 @@ function writeEnded(s, now = Date.now()) {
|
|
|
3185
3214
|
function readEnded(sessionId, now = Date.now()) {
|
|
3186
3215
|
if (!SID_RE.test(sessionId)) return null;
|
|
3187
3216
|
try {
|
|
3188
|
-
const r = JSON.parse(
|
|
3217
|
+
const r = JSON.parse(readFileSync14(join11(endedDir(), `${sessionId}.json`), "utf8"));
|
|
3189
3218
|
if (!r || r.sessionId !== sessionId || typeof r.endedAt !== "number" || now - r.endedAt > ENDED_TTL_MS) return null;
|
|
3190
3219
|
return r;
|
|
3191
3220
|
} catch {
|
|
@@ -3276,7 +3305,7 @@ function isDirSync(p) {
|
|
|
3276
3305
|
}
|
|
3277
3306
|
|
|
3278
3307
|
// src/core/qoderAppSessions.ts
|
|
3279
|
-
import { existsSync as existsSync11, mkdirSync as mkdirSync13, readdirSync as readdirSync3, readFileSync as
|
|
3308
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync13, readdirSync as readdirSync3, readFileSync as readFileSync15, rmSync as rmSync6, writeFileSync as writeFileSync13 } from "fs";
|
|
3280
3309
|
import { join as join12 } from "path";
|
|
3281
3310
|
var QODER_APP_SESSION_TOOLS = ["qoder_cn", "qoder"];
|
|
3282
3311
|
var KEEPER_FILE = "keeper";
|
|
@@ -3320,7 +3349,7 @@ function listQoderAppSessions(tool) {
|
|
|
3320
3349
|
for (const f of names) {
|
|
3321
3350
|
let t = "";
|
|
3322
3351
|
try {
|
|
3323
|
-
t = String(JSON.parse(
|
|
3352
|
+
t = String(JSON.parse(readFileSync15(join12(dir(), f), "utf8")).tool ?? "");
|
|
3324
3353
|
} catch {
|
|
3325
3354
|
t = "";
|
|
3326
3355
|
}
|
|
@@ -3334,7 +3363,7 @@ function qoderAppMarkedAt(sessionId) {
|
|
|
3334
3363
|
const f = file(sessionId);
|
|
3335
3364
|
if (!f) return 0;
|
|
3336
3365
|
try {
|
|
3337
|
-
const at = JSON.parse(
|
|
3366
|
+
const at = JSON.parse(readFileSync15(f, "utf8")).at;
|
|
3338
3367
|
return typeof at === "number" ? at : 0;
|
|
3339
3368
|
} catch {
|
|
3340
3369
|
return 0;
|
|
@@ -3407,7 +3436,7 @@ function statePath(sessionId) {
|
|
|
3407
3436
|
}
|
|
3408
3437
|
function readState(sessionId) {
|
|
3409
3438
|
try {
|
|
3410
|
-
return JSON.parse(
|
|
3439
|
+
return JSON.parse(readFileSync16(statePath(sessionId), "utf8"));
|
|
3411
3440
|
} catch {
|
|
3412
3441
|
return null;
|
|
3413
3442
|
}
|
|
@@ -3472,7 +3501,7 @@ var STALE_STATES = /* @__PURE__ */ new Set(["watch", "ask_approval"]);
|
|
|
3472
3501
|
var STALE_NO_PID_LOG = "\u65E0\u8FDB\u7A0B\u53F7\u4E14 2 \u5C0F\u65F6\u65E0\u4E8B\u4EF6\uFF0C\u6309\u5DF2\u7ED3\u675F\u5904\u7406";
|
|
3473
3502
|
function pendingApprovalSessions() {
|
|
3474
3503
|
try {
|
|
3475
|
-
const recs = JSON.parse(
|
|
3504
|
+
const recs = JSON.parse(readFileSync16(join14(deskbuddyHome(), "approvals.json"), "utf8"));
|
|
3476
3505
|
return new Set(Array.isArray(recs) ? recs.filter((r) => r && r.status === "pending" && typeof r.sessionId === "string").map((r) => r.sessionId) : []);
|
|
3477
3506
|
} catch {
|
|
3478
3507
|
return /* @__PURE__ */ new Set();
|
|
@@ -3499,7 +3528,7 @@ function readAliveStates(tool, opts = {}) {
|
|
|
3499
3528
|
if (!file3.endsWith(".json")) continue;
|
|
3500
3529
|
let s;
|
|
3501
3530
|
try {
|
|
3502
|
-
s = JSON.parse(
|
|
3531
|
+
s = JSON.parse(readFileSync16(join14(stateDir(), file3), "utf8"));
|
|
3503
3532
|
} catch {
|
|
3504
3533
|
rmSync8(join14(stateDir(), file3), { force: true });
|
|
3505
3534
|
continue;
|
|
@@ -3551,7 +3580,7 @@ var ALIAS_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
3551
3580
|
function resolveAlias(sessionId, now = Date.now()) {
|
|
3552
3581
|
let map = {};
|
|
3553
3582
|
try {
|
|
3554
|
-
map = JSON.parse(
|
|
3583
|
+
map = JSON.parse(readFileSync16(join14(deskbuddyHome(), "alias.json"), "utf8")) || {};
|
|
3555
3584
|
} catch {
|
|
3556
3585
|
return sessionId;
|
|
3557
3586
|
}
|
|
@@ -3566,7 +3595,7 @@ function resolveAlias(sessionId, now = Date.now()) {
|
|
|
3566
3595
|
|
|
3567
3596
|
// src/wrap/shim.ts
|
|
3568
3597
|
import { execFile as execFile3, execFileSync as execFileSync7 } from "child_process";
|
|
3569
|
-
import { chmodSync as chmodSync3, existsSync as existsSync14, mkdirSync as mkdirSync16, readdirSync as readdirSync6, readFileSync as
|
|
3598
|
+
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";
|
|
3570
3599
|
import { homedir as homedir3 } from "os";
|
|
3571
3600
|
import { delimiter, join as join15, resolve as resolve3 } from "path";
|
|
3572
3601
|
var SHIM_FALLBACK_EXIT = 213;
|
|
@@ -3722,7 +3751,7 @@ function removeRcBlock(content) {
|
|
|
3722
3751
|
return content.slice(0, start) + content.slice(end);
|
|
3723
3752
|
}
|
|
3724
3753
|
function readRc(p) {
|
|
3725
|
-
return
|
|
3754
|
+
return readFileSync17(p).toString("latin1");
|
|
3726
3755
|
}
|
|
3727
3756
|
function writeRc(p, latin1) {
|
|
3728
3757
|
writeFileSync16(p, Buffer.from(latin1, "latin1"));
|
|
@@ -3977,7 +4006,7 @@ function ourShims(binDir) {
|
|
|
3977
4006
|
}
|
|
3978
4007
|
return names.filter((n) => {
|
|
3979
4008
|
try {
|
|
3980
|
-
return
|
|
4009
|
+
return readFileSync17(join15(binDir, n), "utf8").includes(SHIM_MARKER);
|
|
3981
4010
|
} catch {
|
|
3982
4011
|
return false;
|
|
3983
4012
|
}
|
|
@@ -3989,7 +4018,7 @@ function uninstallShim(tool, e) {
|
|
|
3989
4018
|
let removed = false;
|
|
3990
4019
|
const file3 = shimFile(e.binDir, command, e.platform);
|
|
3991
4020
|
try {
|
|
3992
|
-
if (existsSync14(file3) &&
|
|
4021
|
+
if (existsSync14(file3) && readFileSync17(file3, "utf8").includes(SHIM_MARKER)) {
|
|
3993
4022
|
rmSync9(file3, { force: true });
|
|
3994
4023
|
removed = true;
|
|
3995
4024
|
}
|
|
@@ -4033,7 +4062,7 @@ function shimState(tool, binDir, pathEnv, platform = process.platform) {
|
|
|
4033
4062
|
const file3 = shimFile(binDir, command, platform);
|
|
4034
4063
|
let installed = false;
|
|
4035
4064
|
try {
|
|
4036
|
-
installed =
|
|
4065
|
+
installed = readFileSync17(file3, "utf8").includes(SHIM_MARKER);
|
|
4037
4066
|
} catch {
|
|
4038
4067
|
installed = false;
|
|
4039
4068
|
}
|
|
@@ -4045,18 +4074,18 @@ function shimState(tool, binDir, pathEnv, platform = process.platform) {
|
|
|
4045
4074
|
|
|
4046
4075
|
// src/daemon/workbuddyAppDb.ts
|
|
4047
4076
|
import { execFile as execFile5 } from "child_process";
|
|
4048
|
-
import { closeSync as closeSync5, existsSync as existsSync18, mkdirSync as mkdirSync20, openSync as openSync5, readdirSync as readdirSync9, readFileSync as
|
|
4077
|
+
import { closeSync as closeSync5, existsSync as existsSync18, mkdirSync as mkdirSync20, openSync as openSync5, readdirSync as readdirSync9, readFileSync as readFileSync23, readSync as readSync5, renameSync as renameSync14, rmSync as rmSync12, statSync as statSync9, writeFileSync as writeFileSync20 } from "fs";
|
|
4049
4078
|
import { createRequire as createRequire3 } from "module";
|
|
4050
4079
|
import { basename as basename4, dirname as dirname12, isAbsolute as isAbsolute2, join as join21 } from "path";
|
|
4051
4080
|
|
|
4052
4081
|
// src/core/launch.ts
|
|
4053
|
-
import { mkdirSync as mkdirSync18, readFileSync as
|
|
4082
|
+
import { mkdirSync as mkdirSync18, readFileSync as readFileSync19, renameSync as renameSync12, rmSync as rmSync11, writeFileSync as writeFileSync18 } from "fs";
|
|
4054
4083
|
import { join as join17 } from "path";
|
|
4055
4084
|
|
|
4056
4085
|
// src/core/wake.ts
|
|
4057
4086
|
import { execFileSync as execFileSync8 } from "child_process";
|
|
4058
4087
|
import { createHash as createHash2, createHmac, timingSafeEqual } from "crypto";
|
|
4059
|
-
import { chmodSync as chmodSync4, closeSync as closeSync2, mkdirSync as mkdirSync17, openSync as openSync2, readdirSync as readdirSync7, readFileSync as
|
|
4088
|
+
import { chmodSync as chmodSync4, closeSync as closeSync2, mkdirSync as mkdirSync17, openSync as openSync2, readdirSync as readdirSync7, readFileSync as readFileSync18, readSync as readSync2, renameSync as renameSync11, rmSync as rmSync10, statSync as statSync6, writeFileSync as writeFileSync17 } from "fs";
|
|
4060
4089
|
import { tmpdir } from "os";
|
|
4061
4090
|
import { join as join16 } from "path";
|
|
4062
4091
|
function wakeDir(home = deskbuddyHome()) {
|
|
@@ -4125,7 +4154,7 @@ function isWakeMarked(sessionId, alive = pidExists) {
|
|
|
4125
4154
|
const safe = safeSid(sessionId);
|
|
4126
4155
|
if (!safe) return false;
|
|
4127
4156
|
try {
|
|
4128
|
-
const m = JSON.parse(
|
|
4157
|
+
const m = JSON.parse(readFileSync18(join16(marksDir(), `${safe}.json`), "utf8"));
|
|
4129
4158
|
const daemonPid = Number(m?.daemonPid) || 0;
|
|
4130
4159
|
if (!daemonPid || !alive(daemonPid)) return false;
|
|
4131
4160
|
const pid = Number(m?.agentPid) || 0;
|
|
@@ -4195,10 +4224,11 @@ function macEqual(a, b) {
|
|
|
4195
4224
|
var WAKE_MARK_RE = /\[DeskBuddy#([0-9A-Za-z_-]{1,64})(?::[0-9a-f]{32})?\]/;
|
|
4196
4225
|
var INTERRUPT_RE = /^\[Request interrupted by user/;
|
|
4197
4226
|
var TRANSCRIPT_TAIL2 = 256 * 1024;
|
|
4227
|
+
var TEXT_PART_TYPES = /* @__PURE__ */ new Set(["text", "input_text", "output_text"]);
|
|
4198
4228
|
function userText(content) {
|
|
4199
4229
|
if (typeof content === "string") return content;
|
|
4200
4230
|
if (!Array.isArray(content)) return "";
|
|
4201
|
-
return content.filter((x) => x && x.type
|
|
4231
|
+
return content.filter((x) => x && TEXT_PART_TYPES.has(x.type)).map((x) => String(x.text ?? "")).join("\n");
|
|
4202
4232
|
}
|
|
4203
4233
|
function analyzeTranscript(file3) {
|
|
4204
4234
|
if (!file3) return null;
|
|
@@ -4223,7 +4253,9 @@ function analyzeTranscript(file3) {
|
|
|
4223
4253
|
} catch {
|
|
4224
4254
|
continue;
|
|
4225
4255
|
}
|
|
4226
|
-
if (!o
|
|
4256
|
+
if (!o) continue;
|
|
4257
|
+
if (o.type === "message" && (o.role === "user" || o.role === "assistant")) o = { type: o.role, message: { content: o.content } };
|
|
4258
|
+
if (!o.message) continue;
|
|
4227
4259
|
if (o.type === "assistant") {
|
|
4228
4260
|
const t = userText(o.message.content).trim();
|
|
4229
4261
|
if (t) {
|
|
@@ -4289,7 +4321,7 @@ function claimLaunch(runId) {
|
|
|
4289
4321
|
return null;
|
|
4290
4322
|
}
|
|
4291
4323
|
try {
|
|
4292
|
-
const p = JSON.parse(
|
|
4324
|
+
const p = JSON.parse(readFileSync19(claimed, "utf8"));
|
|
4293
4325
|
if (!p || typeof p.cwd !== "string" || typeof p.resume !== "string") return null;
|
|
4294
4326
|
if (p.tool === void 0) p.tool = "claude_code";
|
|
4295
4327
|
return validPlan(p) ? p : null;
|
|
@@ -4304,7 +4336,7 @@ function claimLaunch(runId) {
|
|
|
4304
4336
|
}
|
|
4305
4337
|
function launchPending(runId) {
|
|
4306
4338
|
try {
|
|
4307
|
-
|
|
4339
|
+
readFileSync19(planFile(runId));
|
|
4308
4340
|
return true;
|
|
4309
4341
|
} catch {
|
|
4310
4342
|
return false;
|
|
@@ -4312,7 +4344,7 @@ function launchPending(runId) {
|
|
|
4312
4344
|
}
|
|
4313
4345
|
|
|
4314
4346
|
// src/core/title.ts
|
|
4315
|
-
import { closeSync as closeSync3, existsSync as existsSync15, openSync as openSync3, readFileSync as
|
|
4347
|
+
import { closeSync as closeSync3, existsSync as existsSync15, openSync as openSync3, readFileSync as readFileSync20, readSync as readSync3, statSync as statSync7 } from "fs";
|
|
4316
4348
|
import { createRequire as createRequire2 } from "module";
|
|
4317
4349
|
import { homedir as homedir5 } from "os";
|
|
4318
4350
|
import { basename as basename3, dirname as dirname10, isAbsolute, join as join18 } from "path";
|
|
@@ -4374,7 +4406,7 @@ function qoderDbPaths(tool, platform = process.platform, home = homedir5(), env
|
|
|
4374
4406
|
|
|
4375
4407
|
// src/daemon/locate.ts
|
|
4376
4408
|
import { execFile as execFile4, execFileSync as execFileSync9 } from "child_process";
|
|
4377
|
-
import { accessSync, closeSync as closeSync4, constants, existsSync as existsSync17, lstatSync, openSync as openSync4, readFileSync as
|
|
4409
|
+
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";
|
|
4378
4410
|
import { homedir as homedir6 } from "os";
|
|
4379
4411
|
import { delimiter as delimiter2, dirname as dirname11, join as join20, win32 as win325 } from "path";
|
|
4380
4412
|
|
|
@@ -4394,7 +4426,7 @@ function scrubForCommand(cmd, env = process.env) {
|
|
|
4394
4426
|
}
|
|
4395
4427
|
|
|
4396
4428
|
// src/daemon/winAppLocator.ts
|
|
4397
|
-
import { existsSync as existsSync16, mkdirSync as mkdirSync19, readdirSync as readdirSync8, readFileSync as
|
|
4429
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync19, readdirSync as readdirSync8, readFileSync as readFileSync21, renameSync as renameSync13, writeFileSync as writeFileSync19 } from "fs";
|
|
4398
4430
|
import { join as join19, win32 as win324 } from "path";
|
|
4399
4431
|
var SOURCE_TEXT = {
|
|
4400
4432
|
process: "\u6B63\u5728\u8FD0\u884C\u7684\u8FDB\u7A0B",
|
|
@@ -4427,14 +4459,7 @@ var WIN_APP_SPECS = {
|
|
|
4427
4459
|
};
|
|
4428
4460
|
var defaultLocFs = {
|
|
4429
4461
|
exists: (p) => existsSync16(p),
|
|
4430
|
-
readText: (p) =>
|
|
4431
|
-
try {
|
|
4432
|
-
if (statSync8(p).size > 64 * 1024) return null;
|
|
4433
|
-
return readFileSync20(p, "utf8");
|
|
4434
|
-
} catch {
|
|
4435
|
-
return null;
|
|
4436
|
-
}
|
|
4437
|
-
},
|
|
4462
|
+
readText: (p) => readSmallText(p),
|
|
4438
4463
|
subdirs: (p) => {
|
|
4439
4464
|
try {
|
|
4440
4465
|
return readdirSync8(p, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
@@ -4530,7 +4555,7 @@ var LOCATE_EVERY_MS = 10 * 60 * 1e3;
|
|
|
4530
4555
|
var cacheFile = () => join19(deskbuddyHome(), WIN_APPS_FILE);
|
|
4531
4556
|
function loadCache(file3 = cacheFile()) {
|
|
4532
4557
|
try {
|
|
4533
|
-
const v = JSON.parse(
|
|
4558
|
+
const v = JSON.parse(readFileSync21(file3, "utf8"));
|
|
4534
4559
|
const out = {};
|
|
4535
4560
|
for (const [k, e] of Object.entries(v ?? {})) {
|
|
4536
4561
|
const x = e;
|
|
@@ -4685,7 +4710,7 @@ var defaultLocateDeps = () => ({
|
|
|
4685
4710
|
nodePath: process.execPath,
|
|
4686
4711
|
isExecutable: (p) => {
|
|
4687
4712
|
try {
|
|
4688
|
-
if (!
|
|
4713
|
+
if (!statSync8(p).isFile()) return false;
|
|
4689
4714
|
accessSync(p, constants.X_OK);
|
|
4690
4715
|
return true;
|
|
4691
4716
|
} catch {
|
|
@@ -4706,7 +4731,7 @@ var defaultLocateDeps = () => ({
|
|
|
4706
4731
|
localAppData: process.env.LOCALAPPDATA ?? "",
|
|
4707
4732
|
readText: (p) => {
|
|
4708
4733
|
try {
|
|
4709
|
-
return
|
|
4734
|
+
return readFileSync22(p, "utf8");
|
|
4710
4735
|
} catch {
|
|
4711
4736
|
return null;
|
|
4712
4737
|
}
|
|
@@ -4790,7 +4815,7 @@ function classifyAsyncError(e, stdout2, stderr) {
|
|
|
4790
4815
|
var defaultProbe = createVersionProbe({
|
|
4791
4816
|
stat: (p) => {
|
|
4792
4817
|
try {
|
|
4793
|
-
const st =
|
|
4818
|
+
const st = statSync8(p);
|
|
4794
4819
|
return { size: st.size, mtimeMs: st.mtimeMs };
|
|
4795
4820
|
} catch {
|
|
4796
4821
|
return null;
|
|
@@ -5303,7 +5328,7 @@ var SLICE = 64 * 1024;
|
|
|
5303
5328
|
function readSlice(p, from) {
|
|
5304
5329
|
const fd = openSync5(p, "r");
|
|
5305
5330
|
try {
|
|
5306
|
-
const size =
|
|
5331
|
+
const size = statSync9(p).size;
|
|
5307
5332
|
const len = Math.min(size, SLICE);
|
|
5308
5333
|
const buf = Buffer.alloc(len);
|
|
5309
5334
|
readSync5(fd, buf, 0, len, from === "head" ? 0 : size - len);
|
|
@@ -5347,7 +5372,7 @@ function userText2(o) {
|
|
|
5347
5372
|
function wbTranscriptInfo(p) {
|
|
5348
5373
|
const head = jsonLines(readSlice(p, "head"));
|
|
5349
5374
|
const tail = jsonLines(readSlice(p, "tail"));
|
|
5350
|
-
const mtime = Math.floor(
|
|
5375
|
+
const mtime = Math.floor(statSync9(p).mtimeMs);
|
|
5351
5376
|
const hs = head.map((o) => tsOf(o.timestamp)).filter((n) => n !== null);
|
|
5352
5377
|
const ts = tail.map((o) => tsOf(o.timestamp)).filter((n) => n !== null);
|
|
5353
5378
|
const createdAt = hs.length ? Math.min(...hs) : mtime;
|
|
@@ -5428,7 +5453,7 @@ function pendingPath() {
|
|
|
5428
5453
|
}
|
|
5429
5454
|
function loadPendingFile() {
|
|
5430
5455
|
try {
|
|
5431
|
-
const v = JSON.parse(
|
|
5456
|
+
const v = JSON.parse(readFileSync23(pendingPath(), "utf8"));
|
|
5432
5457
|
return Array.isArray(v) ? v.filter((j) => j && typeof j.sessionId === "string" && typeof j.cwd === "string") : [];
|
|
5433
5458
|
} catch {
|
|
5434
5459
|
return [];
|
|
@@ -5746,7 +5771,7 @@ var keeperThrottleFile = () => join22(deskbuddyHome(), "wbapp", "keeper.json");
|
|
|
5746
5771
|
var filePersist = {
|
|
5747
5772
|
load: () => {
|
|
5748
5773
|
try {
|
|
5749
|
-
return JSON.parse(
|
|
5774
|
+
return JSON.parse(readFileSync24(keeperThrottleFile(), "utf8"));
|
|
5750
5775
|
} catch {
|
|
5751
5776
|
return null;
|
|
5752
5777
|
}
|
|
@@ -5940,7 +5965,7 @@ function workbuddyBusy(now = Date.now(), dir2 = stateDir(), alive = isAlive) {
|
|
|
5940
5965
|
for (const f of readdirSync10(dir2)) {
|
|
5941
5966
|
if (!f.endsWith(".json")) continue;
|
|
5942
5967
|
try {
|
|
5943
|
-
const s = JSON.parse(
|
|
5968
|
+
const s = JSON.parse(readFileSync24(join22(dir2, f), "utf8"));
|
|
5944
5969
|
if (s.tool !== "workbuddy" || s.state !== "watch" && s.state !== "ask_approval") continue;
|
|
5945
5970
|
if (typeof s.pid === "number" && s.pid > 0) {
|
|
5946
5971
|
if (alive(s.pid, s.pidName)) return true;
|
|
@@ -7105,6 +7130,149 @@ var QoderAppTasks = class {
|
|
|
7105
7130
|
}
|
|
7106
7131
|
};
|
|
7107
7132
|
|
|
7133
|
+
// src/core/summaryTools.ts
|
|
7134
|
+
var SUMMARY_TOOLS = ["claude_code", "codex", "qoder", "qoder_cn", "opencode", "workbuddy", "qwenwork", "dumate", "deepseek_harness"];
|
|
7135
|
+
var SUMMARY_CAPS = SUMMARY_TOOLS.map((t) => `summary:${t}`);
|
|
7136
|
+
|
|
7137
|
+
// src/daemon/summary.ts
|
|
7138
|
+
var SUMMARY_TOOLS2 = SUMMARY_TOOLS;
|
|
7139
|
+
var SUMMARY_NO_OUTPUT = "no_output";
|
|
7140
|
+
var SUMMARY_TIMEOUT = "timeout";
|
|
7141
|
+
function isSummary(cmd) {
|
|
7142
|
+
return cmd.kind === "summary";
|
|
7143
|
+
}
|
|
7144
|
+
function summaryMark(instructionId) {
|
|
7145
|
+
return `[DeskBuddy#${instructionId}]`;
|
|
7146
|
+
}
|
|
7147
|
+
function withSummaryMark(text, instructionId) {
|
|
7148
|
+
if (text.includes(`[DeskBuddy#${instructionId}]`) || text.includes(`[DeskBuddy#${instructionId}:`)) return text;
|
|
7149
|
+
return `${text}
|
|
7150
|
+
${summaryMark(instructionId)}`;
|
|
7151
|
+
}
|
|
7152
|
+
function clipOutput(text) {
|
|
7153
|
+
return text.length > COMMAND_OUTPUT_MAX ? text.slice(0, COMMAND_OUTPUT_MAX) : text;
|
|
7154
|
+
}
|
|
7155
|
+
var BUSY = /* @__PURE__ */ new Set(["watch", "ask_approval"]);
|
|
7156
|
+
var PTY_SETTLE_MS = 1500;
|
|
7157
|
+
var SUMMARY_WAIT_MS = 4 * 60 * 1e3;
|
|
7158
|
+
var PTY_SUMMARY_WAIT_MS = SUMMARY_WAIT_MS;
|
|
7159
|
+
function ptyVerdict(job, st, tail, now) {
|
|
7160
|
+
if (now - job.startedAt > PTY_SUMMARY_WAIT_MS) return { kind: "fail", reason: SUMMARY_TIMEOUT };
|
|
7161
|
+
if (!st) return { kind: "fail", reason: "session_gone" };
|
|
7162
|
+
if (!tail || tail.id !== job.instructionId) return { kind: "wait" };
|
|
7163
|
+
if (tail.humanAfter || tail.interrupted) return { kind: "fail", reason: "exec_failed" };
|
|
7164
|
+
if (!tail.answered) return { kind: "wait" };
|
|
7165
|
+
if (BUSY.has(st.state) || now - st.updatedAt < PTY_SETTLE_MS) return { kind: "wait" };
|
|
7166
|
+
const text = (tail.reply ?? "").trim();
|
|
7167
|
+
return text ? { kind: "done", text } : { kind: "fail", reason: SUMMARY_NO_OUTPUT };
|
|
7168
|
+
}
|
|
7169
|
+
function hasSummaryMark(text, instructionId) {
|
|
7170
|
+
return text.includes(`[DeskBuddy#${instructionId}]`) || text.includes(`[DeskBuddy#${instructionId}:`);
|
|
7171
|
+
}
|
|
7172
|
+
function messagesVerdict(list, instructionId, idle) {
|
|
7173
|
+
if (!Array.isArray(list)) return { kind: "wait" };
|
|
7174
|
+
const msgs = list;
|
|
7175
|
+
const textOf = (m) => Array.isArray(m.parts) ? m.parts.filter((p) => p && p.type === "text" && typeof p.text === "string" && p.synthetic !== true).map((p) => p.text).join("\n").trim() : "";
|
|
7176
|
+
let at = -1;
|
|
7177
|
+
for (let i = msgs.length - 1; i >= 0; i--) {
|
|
7178
|
+
const m = msgs[i];
|
|
7179
|
+
if (m && m.info?.role === "user" && hasSummaryMark(textOf(m), instructionId)) {
|
|
7180
|
+
at = i;
|
|
7181
|
+
break;
|
|
7182
|
+
}
|
|
7183
|
+
}
|
|
7184
|
+
if (at < 0) return { kind: "wait" };
|
|
7185
|
+
const after = msgs.slice(at + 1).filter((m) => m && m.info);
|
|
7186
|
+
if (after.some((m) => m.info?.role === "user")) return { kind: "fail", reason: "exec_failed" };
|
|
7187
|
+
const markId = typeof msgs[at].info?.id === "string" ? msgs[at].info?.id : "";
|
|
7188
|
+
const replies = after.filter((m) => m.info?.role === "assistant" && (!markId || typeof m.info.parentID !== "string" || m.info.parentID === markId));
|
|
7189
|
+
if (!idle || replies.length === 0) return { kind: "wait" };
|
|
7190
|
+
const last = replies[replies.length - 1];
|
|
7191
|
+
if (!last.info?.time || last.info.time.completed == null) return { kind: "wait" };
|
|
7192
|
+
for (let i = replies.length - 1; i >= 0; i--) {
|
|
7193
|
+
const t = textOf(replies[i]);
|
|
7194
|
+
if (t) return { kind: "done", text: t };
|
|
7195
|
+
}
|
|
7196
|
+
return { kind: "fail", reason: SUMMARY_NO_OUTPUT };
|
|
7197
|
+
}
|
|
7198
|
+
function replyVerdict(r) {
|
|
7199
|
+
if (!r || typeof r !== "object") return { kind: "wait" };
|
|
7200
|
+
const v = r;
|
|
7201
|
+
if (v.ok === true) {
|
|
7202
|
+
const t = typeof v.text === "string" ? v.text.trim() : "";
|
|
7203
|
+
return t ? { kind: "done", text: t } : { kind: "fail", reason: SUMMARY_NO_OUTPUT };
|
|
7204
|
+
}
|
|
7205
|
+
const reason = typeof v.reason === "string" && /^[a-z_]{1,32}$/.test(v.reason) ? v.reason : "exec_failed";
|
|
7206
|
+
return { kind: "fail", reason };
|
|
7207
|
+
}
|
|
7208
|
+
var PtySummaryWatch = class {
|
|
7209
|
+
#d;
|
|
7210
|
+
#jobs = /* @__PURE__ */ new Map();
|
|
7211
|
+
constructor(deps) {
|
|
7212
|
+
this.#d = deps;
|
|
7213
|
+
}
|
|
7214
|
+
get size() {
|
|
7215
|
+
return this.#jobs.size;
|
|
7216
|
+
}
|
|
7217
|
+
has(instructionId) {
|
|
7218
|
+
return this.#jobs.has(instructionId);
|
|
7219
|
+
}
|
|
7220
|
+
/** 交出去(started / queued)时登记;handedAt = 交出去的时刻(缺省现在)。同一条重复登记保留最早的时刻 */
|
|
7221
|
+
begin(cmd, sessionId, handedAt, check) {
|
|
7222
|
+
const prev = this.#jobs.get(cmd.instructionId);
|
|
7223
|
+
this.#jobs.set(cmd.instructionId, { cmd, sessionId, startedAt: prev?.startedAt ?? handedAt ?? this.#d.now(), check: check ?? prev?.check });
|
|
7224
|
+
}
|
|
7225
|
+
drop(instructionId) {
|
|
7226
|
+
this.#jobs.delete(instructionId);
|
|
7227
|
+
}
|
|
7228
|
+
#settle(id, job, v) {
|
|
7229
|
+
if (v.kind === "wait" || this.#jobs.get(id) !== job) return;
|
|
7230
|
+
this.#jobs.delete(id);
|
|
7231
|
+
if (v.kind === "done") this.#d.done(job.cmd, job.sessionId, v.text);
|
|
7232
|
+
else this.#d.fail(job.cmd, job.sessionId, v.reason);
|
|
7233
|
+
}
|
|
7234
|
+
tick() {
|
|
7235
|
+
const now = this.#d.now();
|
|
7236
|
+
for (const [id, job] of [...this.#jobs]) {
|
|
7237
|
+
if (job.check) {
|
|
7238
|
+
if (now - job.startedAt > PTY_SUMMARY_WAIT_MS) {
|
|
7239
|
+
this.#settle(id, job, { kind: "fail", reason: SUMMARY_TIMEOUT });
|
|
7240
|
+
continue;
|
|
7241
|
+
}
|
|
7242
|
+
if (job.checking) continue;
|
|
7243
|
+
let r;
|
|
7244
|
+
try {
|
|
7245
|
+
r = job.check({ instructionId: id, sessionId: job.sessionId, startedAt: job.startedAt }, now);
|
|
7246
|
+
} catch {
|
|
7247
|
+
continue;
|
|
7248
|
+
}
|
|
7249
|
+
if (r && typeof r.then === "function") {
|
|
7250
|
+
job.checking = true;
|
|
7251
|
+
void r.then(
|
|
7252
|
+
(v) => {
|
|
7253
|
+
job.checking = false;
|
|
7254
|
+
this.#settle(id, job, v);
|
|
7255
|
+
},
|
|
7256
|
+
() => {
|
|
7257
|
+
job.checking = false;
|
|
7258
|
+
}
|
|
7259
|
+
);
|
|
7260
|
+
} else this.#settle(id, job, r);
|
|
7261
|
+
continue;
|
|
7262
|
+
}
|
|
7263
|
+
let st = null;
|
|
7264
|
+
let tail = null;
|
|
7265
|
+
try {
|
|
7266
|
+
st = this.#d.readState(job.sessionId);
|
|
7267
|
+
const path = st ? this.#d.transcriptOf(st) : null;
|
|
7268
|
+
tail = path ? this.#d.analyze(path) : null;
|
|
7269
|
+
} catch {
|
|
7270
|
+
}
|
|
7271
|
+
this.#settle(id, job, ptyVerdict({ instructionId: id, startedAt: job.startedAt }, st, tail, now));
|
|
7272
|
+
}
|
|
7273
|
+
}
|
|
7274
|
+
};
|
|
7275
|
+
|
|
7108
7276
|
// src/daemon/dumateWatch.ts
|
|
7109
7277
|
var APP_NOT_RUNNING = "app_not_running";
|
|
7110
7278
|
function unavailableMessage(reason) {
|
|
@@ -7158,6 +7326,7 @@ function isRefused(e) {
|
|
|
7158
7326
|
return code(e) === "ECONNREFUSED" || code(e?.cause) === "ECONNREFUSED";
|
|
7159
7327
|
}
|
|
7160
7328
|
var REPLY_HISTORY_LIMIT = 10;
|
|
7329
|
+
var SUMMARY_HISTORY_LIMIT = 100;
|
|
7161
7330
|
function pickOfInfo(info) {
|
|
7162
7331
|
const i = info && typeof info === "object" ? info : null;
|
|
7163
7332
|
if (!i || i.role !== "user") return null;
|
|
@@ -7331,7 +7500,7 @@ function scanSessionDirs(root, now, maxAgeMs = ACTIVE_DIR_MS) {
|
|
|
7331
7500
|
for (const day of list(u).sort().reverse().slice(0, 2))
|
|
7332
7501
|
for (const dir2 of list(day)) {
|
|
7333
7502
|
try {
|
|
7334
|
-
const at =
|
|
7503
|
+
const at = statSync10(dir2).mtimeMs;
|
|
7335
7504
|
if (now - at <= maxAgeMs) out.push({ dir: dir2, at });
|
|
7336
7505
|
} catch {
|
|
7337
7506
|
}
|
|
@@ -7530,6 +7699,25 @@ var DumateWatch = class {
|
|
|
7530
7699
|
if (r.status >= 400 && r.status < 500) return { status: "failed", reason: "window_failed", message: `\u5EFA\u4E86\u4F1A\u8BDD\u4F46\u7B2C\u4E00\u53E5\u88AB\u62D2\uFF08HTTP ${r.status}\uFF09`, sessionId: sid };
|
|
7531
7700
|
return { status: "failed", reason: "window_failed", message: r.status === 0 ? "\u5EFA\u4E86\u4F1A\u8BDD\u4F46\u53D1\u7B2C\u4E00\u53E5\u65F6\u8FDE\u63A5\u65AD\u5F00\u6216\u8D85\u65F6" : `\u5EFA\u4E86\u4F1A\u8BDD\u4F46\u767E\u5EA6\u642D\u5B50\u51FA\u9519\uFF08HTTP ${r.status}\uFF09`, sessionId: sid };
|
|
7532
7701
|
}
|
|
7702
|
+
/**
|
|
7703
|
+
* 任务总结的读回(spec 2026-10-11 summary-all-tools):GET /session/:id/message + /session/status,按标记认本轮(messagesVerdict)。
|
|
7704
|
+
* 连不上 / 读不出 → 等(总超时由调用方判);不唤起 App
|
|
7705
|
+
*/
|
|
7706
|
+
async summaryCheck(sessionId, instructionId) {
|
|
7707
|
+
const wait = { kind: "wait" };
|
|
7708
|
+
const t = this.#target ?? this.#discover(false);
|
|
7709
|
+
if (!t) return wait;
|
|
7710
|
+
const http = this.#http(t);
|
|
7711
|
+
const dir2 = this.#sessionDir.get(sessionId) ?? "";
|
|
7712
|
+
const sid = encodeURIComponent(sessionId);
|
|
7713
|
+
const msgs = await http(t, { method: "GET", path: `/session/${sid}/message?limit=${SUMMARY_HISTORY_LIMIT}`, ...dir2 ? { directory: dir2 } : {} });
|
|
7714
|
+
if (msgs.status === 404) return { kind: "fail", reason: "session_gone" };
|
|
7715
|
+
if (msgs.status !== 200) return wait;
|
|
7716
|
+
const st = await http(t, { method: "GET", path: "/session/status", ...dir2 ? { directory: dir2 } : {} });
|
|
7717
|
+
if (st.status !== 200 || !st.body || typeof st.body !== "object") return wait;
|
|
7718
|
+
const type = st.body[sessionId]?.type;
|
|
7719
|
+
return messagesVerdict(msgs.body, instructionId, type !== "busy" && type !== "preparing" && type !== "retry");
|
|
7720
|
+
}
|
|
7533
7721
|
/**
|
|
7534
7722
|
* 设备回复:往百度搭子里这个会话发一轮(spec 2026-10-08 dumate-qwenwork-reply §3.1)。界面订着同一个 serve 的事件流,实时显示(10-08 实测)。
|
|
7535
7723
|
* 请求体与界面自己发消息一致:带这个会话最后一条用户消息的 agent / model(没有就 build + /config 的 model)。
|
|
@@ -8065,7 +8253,7 @@ function runHook(node, input, agentPid, tool = "dumate") {
|
|
|
8065
8253
|
}
|
|
8066
8254
|
|
|
8067
8255
|
// src/daemon/qoderApp/keeper.ts
|
|
8068
|
-
import { existsSync as existsSync20, mkdirSync as mkdirSync22, readdirSync as readdirSync12, readFileSync as
|
|
8256
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync22, readdirSync as readdirSync12, readFileSync as readFileSync25, renameSync as renameSync16, writeFileSync as writeFileSync22 } from "fs";
|
|
8069
8257
|
import { homedir as homedir7 } from "os";
|
|
8070
8258
|
import { join as join24, win32 as win327 } from "path";
|
|
8071
8259
|
var WAKE_LAUNCH_GAP_MS2 = 60 * 1e3;
|
|
@@ -8130,7 +8318,7 @@ function toolBusy(tool, now = Date.now(), dir2 = stateDir(), alive = isAlive) {
|
|
|
8130
8318
|
for (const f of readdirSync12(dir2)) {
|
|
8131
8319
|
if (!f.endsWith(".json")) continue;
|
|
8132
8320
|
try {
|
|
8133
|
-
const s = JSON.parse(
|
|
8321
|
+
const s = JSON.parse(readFileSync25(join24(dir2, f), "utf8"));
|
|
8134
8322
|
if (s.tool !== tool || s.state !== "watch" && s.state !== "ask_approval") continue;
|
|
8135
8323
|
if (typeof s.pid === "number" && s.pid > 0) {
|
|
8136
8324
|
if (alive(s.pid, s.pidName)) return true;
|
|
@@ -8233,7 +8421,7 @@ var QoderCdpKeeper = class {
|
|
|
8233
8421
|
/** 节流状态(按品牌一份,落盘;读不出当没有) */
|
|
8234
8422
|
#loadThrottle() {
|
|
8235
8423
|
try {
|
|
8236
|
-
const all = JSON.parse(
|
|
8424
|
+
const all = JSON.parse(readFileSync25(this.#file(), "utf8"));
|
|
8237
8425
|
const t = all?.[this.#d.brand.tool] ?? {};
|
|
8238
8426
|
const out = { lastLaunch: Number(t.lastLaunch) || 0, lastRestart: Number(t.lastRestart) || 0, day: typeof t.day === "string" ? t.day : "", restarts: Number(t.restarts) || 0 };
|
|
8239
8427
|
if (this.#d.brand.win && isWinAppExe(t.appExe, this.#d.brand.win.exe)) out.appExe = t.appExe;
|
|
@@ -8247,7 +8435,7 @@ var QoderCdpKeeper = class {
|
|
|
8247
8435
|
try {
|
|
8248
8436
|
let all = {};
|
|
8249
8437
|
try {
|
|
8250
|
-
all = JSON.parse(
|
|
8438
|
+
all = JSON.parse(readFileSync25(f, "utf8"));
|
|
8251
8439
|
} catch {
|
|
8252
8440
|
all = {};
|
|
8253
8441
|
}
|
|
@@ -8623,12 +8811,12 @@ function dumateActivity(now = Date.now(), dataHome = dumateDataHome(), sessionsR
|
|
|
8623
8811
|
for (const u of users) {
|
|
8624
8812
|
const dir2 = join25(xdg, u, "data", "opencode");
|
|
8625
8813
|
try {
|
|
8626
|
-
latest = Math.max(latest,
|
|
8814
|
+
latest = Math.max(latest, statSync11(join25(dir2, "opencode.db")).mtimeMs);
|
|
8627
8815
|
found = true;
|
|
8628
8816
|
} catch {
|
|
8629
8817
|
}
|
|
8630
8818
|
try {
|
|
8631
|
-
const w =
|
|
8819
|
+
const w = statSync11(join25(dir2, "opencode.db-wal"));
|
|
8632
8820
|
if (w.size > 0) latest = Math.max(latest, w.mtimeMs);
|
|
8633
8821
|
} catch {
|
|
8634
8822
|
}
|
|
@@ -8836,7 +9024,7 @@ function restoreQoderShortcutsSync(tool, d, ps = defaultPsSync) {
|
|
|
8836
9024
|
}
|
|
8837
9025
|
|
|
8838
9026
|
// src/adapters/traeHook.ts
|
|
8839
|
-
import { chmodSync as chmodSync5, existsSync as existsSync21, mkdirSync as mkdirSync23, readFileSync as
|
|
9027
|
+
import { chmodSync as chmodSync5, existsSync as existsSync21, mkdirSync as mkdirSync23, readFileSync as readFileSync26, realpathSync as realpathSync5, renameSync as renameSync17, rmSync as rmSync13, statSync as statSync12, writeFileSync as writeFileSync23 } from "fs";
|
|
8840
9028
|
import { dirname as dirname13, join as join27 } from "path";
|
|
8841
9029
|
var TRAE_EVENTS = ["UserPromptSubmit", "PreToolUse", "PostToolUse", "Stop", "Notification"];
|
|
8842
9030
|
var TRAE_NOTICE_TYPES = ["permission_prompt", "ask_user_question", "document_review", "browser_interaction"];
|
|
@@ -8844,7 +9032,7 @@ var TRAE_NOTICE_MATCHER = `^(${TRAE_NOTICE_TYPES.join("|")})$`;
|
|
|
8844
9032
|
var TRAE_NOTICE_TIMEOUT_S = 7 * 24 * 60 * 60;
|
|
8845
9033
|
function readHooksFile(path) {
|
|
8846
9034
|
if (!existsSync21(path)) return {};
|
|
8847
|
-
const raw =
|
|
9035
|
+
const raw = readFileSync26(path, "utf8");
|
|
8848
9036
|
if (raw.trim() === "") return {};
|
|
8849
9037
|
let parsed;
|
|
8850
9038
|
try {
|
|
@@ -8870,7 +9058,7 @@ function writeHooksFile(linkPath, f) {
|
|
|
8870
9058
|
const path = writeTarget(linkPath);
|
|
8871
9059
|
let mode;
|
|
8872
9060
|
try {
|
|
8873
|
-
mode =
|
|
9061
|
+
mode = statSync12(path).mode & 511;
|
|
8874
9062
|
} catch {
|
|
8875
9063
|
mode = void 0;
|
|
8876
9064
|
}
|
|
@@ -8958,10 +9146,10 @@ function isTraeHookInstalled(path, hookPath) {
|
|
|
8958
9146
|
var TRAE_NOTICE = " TRAE\uFF1A\u8BF7\u5728 TRAE \u7684 \u8BBE\u7F6E > Hooks \u91CC\u786E\u8BA4\u300C\u5168\u5C40\u300DHooks \u5DF2\u542F\u7528\u3001\u8FD0\u884C\u65B9\u5F0F\u9009\u300C\u672C\u5730\u81EA\u52A8\u8FD0\u884C\u300D\uFF08\u6C99\u7BB1\u91CC hook \u8FDE\u4E0D\u4E0A\u5B88\u62A4\u8FDB\u7A0B\uFF09\uFF1B\u7535\u8111\u4E0A\u5F39\u6388\u6743\u6846\u65F6\u8BBE\u5907\u4E0A\u4F1A\u51FA\u73B0\u63D0\u793A\u5361\uFF0C\u9700\u56DE\u5230\u7535\u8111\u4E0A\u5904\u7406";
|
|
8959
9147
|
|
|
8960
9148
|
// src/commands/tools.ts
|
|
8961
|
-
import { existsSync as existsSync23, readFileSync as
|
|
9149
|
+
import { existsSync as existsSync23, readFileSync as readFileSync28 } from "fs";
|
|
8962
9150
|
|
|
8963
9151
|
// src/adapters/cbChannel.ts
|
|
8964
|
-
import { chmodSync as chmodSync6, existsSync as existsSync22, lstatSync as lstatSync2, mkdirSync as mkdirSync24, readFileSync as
|
|
9152
|
+
import { chmodSync as chmodSync6, existsSync as existsSync22, lstatSync as lstatSync2, mkdirSync as mkdirSync24, readFileSync as readFileSync27, realpathSync as realpathSync6, renameSync as renameSync18, statSync as statSync13, writeFileSync as writeFileSync24 } from "fs";
|
|
8965
9153
|
import { dirname as dirname14, join as join28 } from "path";
|
|
8966
9154
|
var CB_MCP_NAME = "deskbuddy";
|
|
8967
9155
|
var CB_CHANNEL_SCRIPT = "cbchannel.cjs";
|
|
@@ -8970,7 +9158,7 @@ function cbChannelScript(hookPath) {
|
|
|
8970
9158
|
}
|
|
8971
9159
|
function read(path) {
|
|
8972
9160
|
if (!existsSync22(path)) return {};
|
|
8973
|
-
const raw =
|
|
9161
|
+
const raw = readFileSync27(path, "utf8");
|
|
8974
9162
|
if (raw.trim() === "") return {};
|
|
8975
9163
|
let v;
|
|
8976
9164
|
try {
|
|
@@ -8991,7 +9179,7 @@ function write2(file3, v) {
|
|
|
8991
9179
|
mkdirSync24(dirname14(path), { recursive: true });
|
|
8992
9180
|
let mode;
|
|
8993
9181
|
try {
|
|
8994
|
-
mode =
|
|
9182
|
+
mode = statSync13(path).mode & 511;
|
|
8995
9183
|
} catch {
|
|
8996
9184
|
mode = void 0;
|
|
8997
9185
|
}
|
|
@@ -9039,7 +9227,7 @@ function codebuddyWanted(d = { standalone: () => standaloneProbe() }) {
|
|
|
9039
9227
|
function fileContains(path, needle) {
|
|
9040
9228
|
try {
|
|
9041
9229
|
if (!existsSync23(path)) return false;
|
|
9042
|
-
return
|
|
9230
|
+
return readFileSync28(path, "utf8").includes(needle);
|
|
9043
9231
|
} catch {
|
|
9044
9232
|
return false;
|
|
9045
9233
|
}
|
|
@@ -9086,6 +9274,7 @@ var ADAPTERS = {
|
|
|
9086
9274
|
if (tool === "workbuddy") return installCodebuddyTerminalApprovals(gate);
|
|
9087
9275
|
if (!WINDOW_GATE_TOOLS.has(tool)) return false;
|
|
9088
9276
|
installCcWindowGate(p, gate, tool);
|
|
9277
|
+
if (tool === "qoder_cn" || tool === "qoder") installCcPreToolQuestion(p, gate, tool);
|
|
9089
9278
|
return true;
|
|
9090
9279
|
},
|
|
9091
9280
|
// asyncRewake 只有 Claude Code 认(2.1.280 实测);别家当成同步 hook 会一直等
|
|
@@ -9140,7 +9329,7 @@ ADAPTERS["dumate-http"] = {
|
|
|
9140
9329
|
uninstall: () => restoreDumateShortcutsSync({ log: dmLnkLog }),
|
|
9141
9330
|
isInstalled: (p) => {
|
|
9142
9331
|
try {
|
|
9143
|
-
const enabled = JSON.parse(
|
|
9332
|
+
const enabled = JSON.parse(readFileSync28(p, "utf8")).enabledTools;
|
|
9144
9333
|
return Array.isArray(enabled) && enabled.includes("dumate");
|
|
9145
9334
|
} catch {
|
|
9146
9335
|
return false;
|
|
@@ -9173,7 +9362,7 @@ ADAPTERS["coze-cdp"] = {
|
|
|
9173
9362
|
},
|
|
9174
9363
|
isInstalled: (p) => {
|
|
9175
9364
|
try {
|
|
9176
|
-
const enabled = JSON.parse(
|
|
9365
|
+
const enabled = JSON.parse(readFileSync28(p, "utf8")).enabledTools;
|
|
9177
9366
|
return Array.isArray(enabled) && enabled.includes("coze");
|
|
9178
9367
|
} catch {
|
|
9179
9368
|
return false;
|
|
@@ -9204,7 +9393,7 @@ function subscribedEvents(registry, tool, fallback) {
|
|
|
9204
9393
|
}
|
|
9205
9394
|
|
|
9206
9395
|
// src/wrap/pty.ts
|
|
9207
|
-
import { chmodSync as chmodSync7, existsSync as existsSync24, statSync as
|
|
9396
|
+
import { chmodSync as chmodSync7, existsSync as existsSync24, statSync as statSync14 } from "fs";
|
|
9208
9397
|
import { createRequire as createRequire4 } from "module";
|
|
9209
9398
|
import { dirname as dirname15, join as join29 } from "path";
|
|
9210
9399
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
@@ -9228,7 +9417,7 @@ function fixSpawnHelper(ptyDir) {
|
|
|
9228
9417
|
if (process.platform !== "darwin") return;
|
|
9229
9418
|
try {
|
|
9230
9419
|
const helper = join29(ptyDir, "prebuilds", `darwin-${process.arch}`, "spawn-helper");
|
|
9231
|
-
if (existsSync24(helper) && (
|
|
9420
|
+
if (existsSync24(helper) && (statSync14(helper).mode & 73) === 0) chmodSync7(helper, 493);
|
|
9232
9421
|
} catch {
|
|
9233
9422
|
}
|
|
9234
9423
|
}
|
|
@@ -9465,7 +9654,7 @@ function migrateLegacyQoder(out, detect = () => detectTools()) {
|
|
|
9465
9654
|
|
|
9466
9655
|
// src/daemon/loginGuide.ts
|
|
9467
9656
|
import { execFile as execFile9, execFileSync as execFileSync13 } from "child_process";
|
|
9468
|
-
import { chmodSync as chmodSync9, existsSync as existsSync26, mkdirSync as mkdirSync26, readFileSync as
|
|
9657
|
+
import { chmodSync as chmodSync9, existsSync as existsSync26, mkdirSync as mkdirSync26, readFileSync as readFileSync29, writeFileSync as writeFileSync26 } from "fs";
|
|
9469
9658
|
import { homedir as homedir9 } from "os";
|
|
9470
9659
|
import { join as join34 } from "path";
|
|
9471
9660
|
|
|
@@ -10148,7 +10337,7 @@ var defaultCheckDeps = () => ({
|
|
|
10148
10337
|
home: homedir9(),
|
|
10149
10338
|
codexConfig: () => {
|
|
10150
10339
|
try {
|
|
10151
|
-
return
|
|
10340
|
+
return readFileSync29(join34(codexHome(), "config.toml"), "utf8");
|
|
10152
10341
|
} catch {
|
|
10153
10342
|
return null;
|
|
10154
10343
|
}
|
|
@@ -10306,7 +10495,7 @@ var defaultLoginOpenDeps = () => ({
|
|
|
10306
10495
|
});
|
|
10307
10496
|
async function installCodebuddyHooks(log) {
|
|
10308
10497
|
try {
|
|
10309
|
-
const { installTools: installTools2 } = await import("./enable-
|
|
10498
|
+
const { installTools: installTools2 } = await import("./enable-SIY4AEF7.js");
|
|
10310
10499
|
installTools2(["workbuddy"], () => {
|
|
10311
10500
|
}, null, { auto: true });
|
|
10312
10501
|
} catch (e) {
|
|
@@ -10820,7 +11009,7 @@ function defaultOfferDeps(log) {
|
|
|
10820
11009
|
}),
|
|
10821
11010
|
openLogin: () => defaultOpenLogin(platform),
|
|
10822
11011
|
installHooks: async () => {
|
|
10823
|
-
const { installTools: installTools2 } = await import("./enable-
|
|
11012
|
+
const { installTools: installTools2 } = await import("./enable-SIY4AEF7.js");
|
|
10824
11013
|
installTools2(["workbuddy"], (l) => log(`[WorkBuddy \u72EC\u7ACB\u7248] ${l}`), null, { auto: true });
|
|
10825
11014
|
},
|
|
10826
11015
|
log: (l) => log(`[WorkBuddy \u72EC\u7ACB\u7248] ${l}`),
|
|
@@ -11071,6 +11260,7 @@ export {
|
|
|
11071
11260
|
codebuddyConfigDir,
|
|
11072
11261
|
qoderCnSettingsPath,
|
|
11073
11262
|
qwenworkHome,
|
|
11263
|
+
qwenworkDataHome,
|
|
11074
11264
|
qoderSettingsPath,
|
|
11075
11265
|
opencodePluginPath,
|
|
11076
11266
|
installedHookPath,
|
|
@@ -11084,7 +11274,6 @@ export {
|
|
|
11084
11274
|
packageVersion,
|
|
11085
11275
|
installedHookVersion,
|
|
11086
11276
|
syncHookFile,
|
|
11087
|
-
COMMAND_OUTPUT_MAX,
|
|
11088
11277
|
APP_ID,
|
|
11089
11278
|
APP_SECRET,
|
|
11090
11279
|
sign,
|
|
@@ -11259,6 +11448,16 @@ export {
|
|
|
11259
11448
|
APP_IN_USE_REASON,
|
|
11260
11449
|
QODER_APP_POLL_MS,
|
|
11261
11450
|
QoderAppTasks,
|
|
11451
|
+
SUMMARY_CAPS,
|
|
11452
|
+
SUMMARY_TOOLS2 as SUMMARY_TOOLS,
|
|
11453
|
+
SUMMARY_NO_OUTPUT,
|
|
11454
|
+
isSummary,
|
|
11455
|
+
withSummaryMark,
|
|
11456
|
+
clipOutput,
|
|
11457
|
+
SUMMARY_WAIT_MS,
|
|
11458
|
+
ptyVerdict,
|
|
11459
|
+
replyVerdict,
|
|
11460
|
+
PtySummaryWatch,
|
|
11262
11461
|
APP_NOT_RUNNING,
|
|
11263
11462
|
DumateWatch,
|
|
11264
11463
|
runHook,
|