deskbuddy 0.2.0-beta.34 → 0.2.0-beta.36
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.
|
@@ -5608,10 +5608,13 @@ var defaultFetchJson = async (url, timeoutMs) => {
|
|
|
5608
5608
|
clearTimeout(t);
|
|
5609
5609
|
}
|
|
5610
5610
|
};
|
|
5611
|
-
function
|
|
5612
|
-
if (!Array.isArray(list)) return
|
|
5611
|
+
function mainTargets(list) {
|
|
5612
|
+
if (!Array.isArray(list)) return [];
|
|
5613
5613
|
const pages = list.filter((t) => t && t.type === "page" && typeof t.webSocketDebuggerUrl === "string" && !/^devtools:/.test(t.url ?? ""));
|
|
5614
|
-
return pages.
|
|
5614
|
+
return pages.filter((t) => /renderer\/index\.html/.test(t.url ?? ""));
|
|
5615
|
+
}
|
|
5616
|
+
function pickMainTarget(list) {
|
|
5617
|
+
return mainTargets(list)[0] ?? null;
|
|
5615
5618
|
}
|
|
5616
5619
|
function loopbackWsUrl(wsUrl, port) {
|
|
5617
5620
|
try {
|
|
@@ -5624,16 +5627,18 @@ function loopbackWsUrl(wsUrl, port) {
|
|
|
5624
5627
|
return null;
|
|
5625
5628
|
}
|
|
5626
5629
|
}
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5630
|
+
var HAS_SDK_EXPR = "!!(globalThis.wb && globalThis.wb.conversations)";
|
|
5631
|
+
function pageName(url) {
|
|
5632
|
+
return String(url || "").split(/[?#]/)[0].split(/[\\/]/).slice(-2).join("/");
|
|
5633
|
+
}
|
|
5634
|
+
function openWs(target, port, d, info) {
|
|
5635
|
+
if (!target.webSocketDebuggerUrl) return Promise.reject(new Error("\u627E\u4E0D\u5230 App \u4E3B\u7A97\u53E3"));
|
|
5631
5636
|
const url = loopbackWsUrl(target.webSocketDebuggerUrl, port);
|
|
5632
|
-
if (!url)
|
|
5637
|
+
if (!url) return Promise.reject(new Error("\u4E3B\u7A97\u53E3\u7684\u8C03\u8BD5\u5730\u5740\u4E0D\u5BF9"));
|
|
5633
5638
|
const ws = (d.ws ?? ((u) => new WebSocket(u, { handshakeTimeout: 5e3 })))(url);
|
|
5634
|
-
return
|
|
5639
|
+
return new Promise((resolve6, reject) => {
|
|
5635
5640
|
let opened = false;
|
|
5636
|
-
const client = new WsCdpClient(ws);
|
|
5641
|
+
const client = new WsCdpClient(ws, info);
|
|
5637
5642
|
ws.on("open", () => {
|
|
5638
5643
|
opened = true;
|
|
5639
5644
|
resolve6(client);
|
|
@@ -5648,13 +5653,53 @@ async function connectCdp(port, d = {}) {
|
|
|
5648
5653
|
ws.on("message", (data) => client.onMessage(data));
|
|
5649
5654
|
});
|
|
5650
5655
|
}
|
|
5656
|
+
async function connectCdp(port, d = {}) {
|
|
5657
|
+
const fetchJson = d.fetchJson ?? defaultFetchJson;
|
|
5658
|
+
const list = await fetchJson(`http://127.0.0.1:${port}/json/list`, 3e3);
|
|
5659
|
+
if (!d.pickSdk) {
|
|
5660
|
+
const target = (d.pick ?? pickMainTarget)(list);
|
|
5661
|
+
if (!target?.webSocketDebuggerUrl) throw new Error("\u627E\u4E0D\u5230 App \u4E3B\u7A97\u53E3");
|
|
5662
|
+
return openWs(target, port, d);
|
|
5663
|
+
}
|
|
5664
|
+
const all = mainTargets(list);
|
|
5665
|
+
if (all.length === 0) throw new Error("\u627E\u4E0D\u5230 App \u4E3B\u7A97\u53E3");
|
|
5666
|
+
let ua = "";
|
|
5667
|
+
try {
|
|
5668
|
+
const v = await fetchJson(`http://127.0.0.1:${port}/json/version`, 2e3);
|
|
5669
|
+
const m = typeof v?.["User-Agent"] === "string" ? /\bWorkBuddy\/[\w.-]+/.exec(v["User-Agent"]) : null;
|
|
5670
|
+
ua = [m?.[0], typeof v?.Browser === "string" ? v.Browser : ""].filter(Boolean).join(" ");
|
|
5671
|
+
} catch {
|
|
5672
|
+
ua = "";
|
|
5673
|
+
}
|
|
5674
|
+
const infoOf = (i, sdk) => ({ url: pageName(String(all[i].url ?? "")), title: "", candidates: all.length, index: i, sdk, ...ua ? { ua } : {} });
|
|
5675
|
+
if (all.length === 1) return openWs(all[0], port, d, infoOf(0, null));
|
|
5676
|
+
for (let i = 0; i < all.length; i++) {
|
|
5677
|
+
let c;
|
|
5678
|
+
try {
|
|
5679
|
+
c = await openWs(all[i], port, d, infoOf(i, true));
|
|
5680
|
+
} catch {
|
|
5681
|
+
continue;
|
|
5682
|
+
}
|
|
5683
|
+
let has = false;
|
|
5684
|
+
try {
|
|
5685
|
+
has = await c.evaluate(HAS_SDK_EXPR, 2e3) === true;
|
|
5686
|
+
} catch {
|
|
5687
|
+
has = false;
|
|
5688
|
+
}
|
|
5689
|
+
if (has) return c;
|
|
5690
|
+
c.close();
|
|
5691
|
+
}
|
|
5692
|
+
return openWs(all[0], port, d, infoOf(0, false));
|
|
5693
|
+
}
|
|
5651
5694
|
var WsCdpClient = class {
|
|
5652
5695
|
#ws;
|
|
5696
|
+
target;
|
|
5653
5697
|
#id = 0;
|
|
5654
5698
|
#closed = false;
|
|
5655
5699
|
#waiting = /* @__PURE__ */ new Map();
|
|
5656
|
-
constructor(ws) {
|
|
5700
|
+
constructor(ws, target) {
|
|
5657
5701
|
this.#ws = ws;
|
|
5702
|
+
if (target) this.target = target;
|
|
5658
5703
|
}
|
|
5659
5704
|
get closed() {
|
|
5660
5705
|
return this.#closed;
|
|
@@ -5858,6 +5903,7 @@ var HungTracker = class {
|
|
|
5858
5903
|
}
|
|
5859
5904
|
};
|
|
5860
5905
|
var APP_PORT_HUNG_REASON = "app_port_unresponsive";
|
|
5906
|
+
var STARTUP_GRACE_MS = 90 * 1e3;
|
|
5861
5907
|
var FORCE_QUIT_WAIT_MS = 10 * 1e3;
|
|
5862
5908
|
function isTimeoutError(e) {
|
|
5863
5909
|
const err = e;
|
|
@@ -6005,6 +6051,12 @@ var CdpKeeper = class {
|
|
|
6005
6051
|
#hung = new HungTracker();
|
|
6006
6052
|
/** 这一段卡死里「暂不重启」的原因记过哪条(同一条只记一次) */
|
|
6007
6053
|
#hungNote = "";
|
|
6054
|
+
/** 启动宽限期到什么时候(0 = 不在宽限期) */
|
|
6055
|
+
#graceUntil = 0;
|
|
6056
|
+
/** 宽限期内超时记过一行没有(每段宽限只记一次) */
|
|
6057
|
+
#graceNoted = false;
|
|
6058
|
+
/** 上一轮端口检查的结果(判「刚从不通变成通」) */
|
|
6059
|
+
#lastPort = null;
|
|
6008
6060
|
/** 这一段端口不通里「不重启」的原因记过哪条(同一条只记一次;端口通了 / 转成卡死时清掉。258:原先这些分支一行不记) */
|
|
6009
6061
|
#downNote = "";
|
|
6010
6062
|
/** 最近一轮端口不通的细分(日志 / 设备任务的等待原因用):fail = 没在监听或回包不是 WorkBuddy;timeout = 超时且监听者不是本机回环的 WorkBuddy */
|
|
@@ -6149,6 +6201,20 @@ var CdpKeeper = class {
|
|
|
6149
6201
|
this.#hung.clear();
|
|
6150
6202
|
this.#hungNote = "";
|
|
6151
6203
|
}
|
|
6204
|
+
/** 进入启动宽限期(拉起 / 重启 / 端口刚从不通变成通) */
|
|
6205
|
+
#startGrace(now) {
|
|
6206
|
+
this.#graceUntil = now + STARTUP_GRACE_MS;
|
|
6207
|
+
this.#graceNoted = false;
|
|
6208
|
+
}
|
|
6209
|
+
#inGrace(now) {
|
|
6210
|
+
return this.#graceUntil > 0 && now < this.#graceUntil;
|
|
6211
|
+
}
|
|
6212
|
+
/** 宽限期内超时:记一行(每段一次) */
|
|
6213
|
+
#noteGrace() {
|
|
6214
|
+
if (this.#graceNoted) return;
|
|
6215
|
+
this.#graceNoted = true;
|
|
6216
|
+
this.#d.log(`WorkBuddy \u8C03\u8BD5\u7AEF\u53E3 ${this.#d.port()} \u8D85\u65F6\uFF0C\u4F46 App \u521A\u542F\u52A8 / \u521A\u6062\u590D\uFF08${STARTUP_GRACE_MS / 1e3} \u79D2\u5BBD\u9650\u671F\u5185\uFF09\uFF0C\u5148\u4E0D\u5224\u65E0\u54CD\u5E94`);
|
|
6217
|
+
}
|
|
6152
6218
|
/** 最近一轮端口不通的细分(没不通过返回 '') */
|
|
6153
6219
|
get downWhy() {
|
|
6154
6220
|
return this.#downWhy;
|
|
@@ -6200,7 +6266,13 @@ var CdpKeeper = class {
|
|
|
6200
6266
|
await this.ensureEnv().catch(() => {
|
|
6201
6267
|
});
|
|
6202
6268
|
const pr = await this.#probe();
|
|
6269
|
+
const st = await this.#tickInner(pr);
|
|
6270
|
+
this.#lastPort = st;
|
|
6271
|
+
return st;
|
|
6272
|
+
}
|
|
6273
|
+
async #tickInner(pr) {
|
|
6203
6274
|
if (pr === "ok") {
|
|
6275
|
+
if (this.#lastPort === "down") this.#startGrace(this.#now());
|
|
6204
6276
|
if (this.#hung.since) this.#d.log(`WorkBuddy \u8C03\u8BD5\u7AEF\u53E3 ${this.#d.port()} \u6062\u590D\u54CD\u5E94`);
|
|
6205
6277
|
this.#markHung(false, 0);
|
|
6206
6278
|
this.#downRounds = 0;
|
|
@@ -6211,6 +6283,11 @@ var CdpKeeper = class {
|
|
|
6211
6283
|
});
|
|
6212
6284
|
return ok ? "up" : "untrusted";
|
|
6213
6285
|
}
|
|
6286
|
+
if (pr === "timeout" && this.#inGrace(this.#now()) && await this.ownerOk().catch(() => false)) {
|
|
6287
|
+
this.#noteGrace();
|
|
6288
|
+
this.#downRounds = 0;
|
|
6289
|
+
return this.#lastPort === "up" ? "up" : "down";
|
|
6290
|
+
}
|
|
6214
6291
|
if (await this.#isHung(pr)) {
|
|
6215
6292
|
const now = this.#now();
|
|
6216
6293
|
this.#markHung(true, now);
|
|
@@ -6277,6 +6354,7 @@ var CdpKeeper = class {
|
|
|
6277
6354
|
async #doRestart(verify, hung = false) {
|
|
6278
6355
|
this.#restarting = true;
|
|
6279
6356
|
this.#lastRestart = this.#now();
|
|
6357
|
+
this.#startGrace(this.#lastRestart);
|
|
6280
6358
|
this.#restarts++;
|
|
6281
6359
|
this.#saveThrottle();
|
|
6282
6360
|
try {
|
|
@@ -6368,6 +6446,10 @@ var CdpKeeper = class {
|
|
|
6368
6446
|
this.#d.log(`\u5524\u8D77 WorkBuddy\uFF1A${Math.round((now - this.#lastWakeLaunch) / 1e3)} \u79D2\u524D\u521A\u62C9\u8D77\u8FC7\uFF08\u8282\u6D41 60 \u79D2\uFF09\uFF0C\u4E0D\u518D\u62C9\u8D77\uFF0C\u7B49\u5B83\u8D77\u6765`);
|
|
6369
6447
|
return "launched";
|
|
6370
6448
|
}
|
|
6449
|
+
if (pr === "timeout" && this.#inGrace(now) && await this.ownerOk().catch(() => false)) {
|
|
6450
|
+
this.#noteGrace();
|
|
6451
|
+
return "running";
|
|
6452
|
+
}
|
|
6371
6453
|
if (await this.#isHung(pr)) return this.#wakeHung(now);
|
|
6372
6454
|
if (this.#lastRestart && now - this.#lastRestart < RESTART_GAP_MS) {
|
|
6373
6455
|
this.#d.log(`\u5524\u8D77 WorkBuddy\uFF1A${Math.round((now - this.#lastRestart) / 6e4)} \u5206\u949F\u524D\u521A\u91CD\u542F\u8FC7\uFF08\u8282\u6D41 30 \u5206\u949F\uFF09\uFF0C\u4E0D\u518D\u91CD\u542F\uFF0C\u7B49\u7AEF\u53E3\u8D77\u6765`);
|
|
@@ -6384,6 +6466,7 @@ var CdpKeeper = class {
|
|
|
6384
6466
|
return "not_installed";
|
|
6385
6467
|
}
|
|
6386
6468
|
this.#lastWakeLaunch = now;
|
|
6469
|
+
this.#startGrace(now);
|
|
6387
6470
|
this.#saveThrottle();
|
|
6388
6471
|
await this.ensureEnv().catch(() => {
|
|
6389
6472
|
});
|
|
@@ -10648,7 +10731,7 @@ var defaultLoginOpenDeps = () => ({
|
|
|
10648
10731
|
});
|
|
10649
10732
|
async function installCodebuddyHooks(log) {
|
|
10650
10733
|
try {
|
|
10651
|
-
const { installTools: installTools2 } = await import("./enable-
|
|
10734
|
+
const { installTools: installTools2 } = await import("./enable-UNMUBPWP.js");
|
|
10652
10735
|
installTools2(["workbuddy"], () => {
|
|
10653
10736
|
}, null, { auto: true });
|
|
10654
10737
|
} catch (e) {
|
|
@@ -11162,7 +11245,7 @@ function defaultOfferDeps(log) {
|
|
|
11162
11245
|
}),
|
|
11163
11246
|
openLogin: () => defaultOpenLogin(platform),
|
|
11164
11247
|
installHooks: async () => {
|
|
11165
|
-
const { installTools: installTools2 } = await import("./enable-
|
|
11248
|
+
const { installTools: installTools2 } = await import("./enable-UNMUBPWP.js");
|
|
11166
11249
|
installTools2(["workbuddy"], (l) => log(`[WorkBuddy \u72EC\u7ACB\u7248] ${l}`), null, { auto: true });
|
|
11167
11250
|
},
|
|
11168
11251
|
log: (l) => log(`[WorkBuddy \u72EC\u7ACB\u7248] ${l}`),
|
package/dist/cli.js
CHANGED
|
@@ -262,7 +262,7 @@ import {
|
|
|
262
262
|
writeState,
|
|
263
263
|
writeWakeMark,
|
|
264
264
|
writeWakeSecret
|
|
265
|
-
} from "./chunk-
|
|
265
|
+
} from "./chunk-37YGRQ4H.js";
|
|
266
266
|
|
|
267
267
|
// src/commands/config.ts
|
|
268
268
|
function runConfig(args, out = (s2) => process.stdout.write(s2 + "\n")) {
|
|
@@ -795,9 +795,9 @@ var AutoEnabler = class {
|
|
|
795
795
|
|
|
796
796
|
// src/daemon/index.ts
|
|
797
797
|
import { randomBytes as randomBytes7 } from "crypto";
|
|
798
|
-
import { existsSync as existsSync7, readdirSync as readdirSync11, readFileSync as
|
|
798
|
+
import { existsSync as existsSync7, readdirSync as readdirSync11, readFileSync as readFileSync14, statSync as statSync13 } from "fs";
|
|
799
799
|
import { homedir as homedir8 } from "os";
|
|
800
|
-
import { basename as basename9, dirname as
|
|
800
|
+
import { basename as basename9, dirname as dirname9, join as join27 } from "path";
|
|
801
801
|
import WebSocket2 from "ws";
|
|
802
802
|
|
|
803
803
|
// src/core/transcript/locate.ts
|
|
@@ -2735,6 +2735,23 @@ function basename5(p) {
|
|
|
2735
2735
|
const parts = p.split(/[\\/]+/).filter(Boolean);
|
|
2736
2736
|
return parts[parts.length - 1] ?? "";
|
|
2737
2737
|
}
|
|
2738
|
+
function addedTail(toolName, a) {
|
|
2739
|
+
const str6 = (v) => typeof v === "string" ? v : "";
|
|
2740
|
+
let oldS = "";
|
|
2741
|
+
let newS = "";
|
|
2742
|
+
if (toolName === "MultiEdit" && Array.isArray(a.edits) && a.edits.length > 0) {
|
|
2743
|
+
const last = a.edits[a.edits.length - 1];
|
|
2744
|
+
oldS = str6(last?.old_string);
|
|
2745
|
+
newS = str6(last?.new_string);
|
|
2746
|
+
} else if (toolName === "NotebookEdit") newS = str6(a.new_source);
|
|
2747
|
+
else {
|
|
2748
|
+
oldS = str6(a.old_string);
|
|
2749
|
+
newS = str6(a.new_string);
|
|
2750
|
+
}
|
|
2751
|
+
const old = new Set(oldS.split(/\r?\n/).map((l) => squash(l)));
|
|
2752
|
+
const added = newS.split(/\r?\n/).map((l) => squash(l)).filter((l) => l && !old.has(l));
|
|
2753
|
+
return (added[added.length - 1] ?? "").slice(0, 20);
|
|
2754
|
+
}
|
|
2738
2755
|
function displayFingerprint(toolName, input) {
|
|
2739
2756
|
const a = input && typeof input === "object" ? input : {};
|
|
2740
2757
|
const s2 = (v) => typeof v === "string" ? v : "";
|
|
@@ -2748,7 +2765,14 @@ function displayFingerprint(toolName, input) {
|
|
|
2748
2765
|
const body = squash(s2(a.content)).slice(0, 20);
|
|
2749
2766
|
return name ? body ? name + FP_SEP + body : name : "";
|
|
2750
2767
|
}
|
|
2751
|
-
if (["Edit", "MultiEdit", "
|
|
2768
|
+
if (["Edit", "MultiEdit", "NotebookEdit"].includes(toolName)) {
|
|
2769
|
+
const name = squash(basename5(s2(a.file_path) || s2(a.notebook_path)));
|
|
2770
|
+
if (!name) return "";
|
|
2771
|
+
if (toolName === "NotebookEdit") return name;
|
|
2772
|
+
const tail4 = addedTail(toolName, a);
|
|
2773
|
+
return tail4 ? name + FP_SEP + tail4 : name;
|
|
2774
|
+
}
|
|
2775
|
+
if (toolName === "Read") return squash(basename5(s2(a.file_path)));
|
|
2752
2776
|
return headTail(Object.values(a).find((v) => typeof v === "string" && v.trim() !== "") ?? "").slice(0, 200);
|
|
2753
2777
|
}
|
|
2754
2778
|
var SETTLE_MS = 800;
|
|
@@ -2792,10 +2816,33 @@ function permissionRegion(lines3, toolName) {
|
|
|
2792
2816
|
function isPermissionDialog(lines3, toolName, fingerprint2) {
|
|
2793
2817
|
if (!fingerprint2) return false;
|
|
2794
2818
|
const region = permissionRegion(lines3, toolName);
|
|
2795
|
-
if (!region) return
|
|
2819
|
+
if (!region) return scrolledFileDialog(lines3, toolName, fingerprint2);
|
|
2796
2820
|
const text = squash(joined(region));
|
|
2797
2821
|
return fingerprint2.split(FP_SEP).every((part) => !!part && text.includes(squash(part)));
|
|
2798
2822
|
}
|
|
2823
|
+
var SCROLL_TOOLS = /* @__PURE__ */ new Set(["Edit", "MultiEdit", "NotebookEdit"]);
|
|
2824
|
+
var EDIT_QUESTION_RE = /^\s*Do you want to make this edit to (.+)\?\s*$/;
|
|
2825
|
+
function scrolledFileDialog(lines3, toolName, fingerprint2) {
|
|
2826
|
+
if (!SCROLL_TOOLS.has(toolName)) return false;
|
|
2827
|
+
const [name, ...content] = fingerprint2.split(FP_SEP);
|
|
2828
|
+
if (!name || content.length === 0 || content.some((c) => !c)) return false;
|
|
2829
|
+
let q = -1;
|
|
2830
|
+
for (let i = lines3.length - 1; i >= 0; i--) {
|
|
2831
|
+
if (/^\s*Do you want to .+\?\s*$/.test(lines3[i])) {
|
|
2832
|
+
q = i;
|
|
2833
|
+
break;
|
|
2834
|
+
}
|
|
2835
|
+
}
|
|
2836
|
+
if (q < 0) return false;
|
|
2837
|
+
const m = EDIT_QUESTION_RE.exec(lines3[q]);
|
|
2838
|
+
if (!m || squash(basename5(m[1].trim())) !== name) return false;
|
|
2839
|
+
if (lines3.slice(0, q).some((l) => /^\s*●/.test(l))) return false;
|
|
2840
|
+
const after = joined(lines3.slice(q + 1, q + 6));
|
|
2841
|
+
if (!new RegExp(`^\\s*(?:${CURSOR}\\s*)?1\\.\\s+Yes\\s*$`, "m").test(after)) return false;
|
|
2842
|
+
if (!/^\s*(?:[❯>›]\s*)?3\.\s+No\b/m.test(after)) return false;
|
|
2843
|
+
const body = squash(joined(lines3.slice(0, q)));
|
|
2844
|
+
return content.every((c) => body.includes(c));
|
|
2845
|
+
}
|
|
2799
2846
|
async function answerPermission(io, toolName, fingerprint2, decision) {
|
|
2800
2847
|
const ok = (l) => isPermissionDialog(l, toolName, fingerprint2);
|
|
2801
2848
|
if (!await settled(io, ok)) return "not_waiting";
|
|
@@ -2843,13 +2890,40 @@ function singleCursor(lines3, q) {
|
|
|
2843
2890
|
if (m) {
|
|
2844
2891
|
const k = Number(m[1]) - 1;
|
|
2845
2892
|
if (k >= 0 && k < n) return squash(m[2]).startsWith(squash(q.options[k].label).slice(0, 6)) ? k : -1;
|
|
2846
|
-
if (k === n) return /^Typesomething
|
|
2893
|
+
if (k === n) return /^(Typesomething)?$/.test(squash(m[2])) ? n : -1;
|
|
2847
2894
|
return -1;
|
|
2848
2895
|
}
|
|
2849
2896
|
if (new RegExp(`^\\s*${CURSOR}\\s*(Next|Submit)\\s*$`).test(l)) return n + 1;
|
|
2850
2897
|
}
|
|
2851
2898
|
return -1;
|
|
2852
2899
|
}
|
|
2900
|
+
function typeLine(lines3, n) {
|
|
2901
|
+
const start = questionStart(lines3);
|
|
2902
|
+
if (start < 0) return -1;
|
|
2903
|
+
for (let i = start; i < lines3.length; i++) {
|
|
2904
|
+
const m = lines3[i].match(/^\s*(?:[❯>›]\s*)?[☐☒]?\s*(\d+)\.(?:\s|$)/);
|
|
2905
|
+
if (m && Number(m[1]) === n + 1) return i;
|
|
2906
|
+
}
|
|
2907
|
+
return -1;
|
|
2908
|
+
}
|
|
2909
|
+
function typedText(lines3, n) {
|
|
2910
|
+
const ln = typeLine(lines3, n);
|
|
2911
|
+
if (ln < 0) return null;
|
|
2912
|
+
const parts = [lines3[ln].replace(/^\s*(?:[❯>›]\s*)?[☐☒]?\s*\d+\./, "")];
|
|
2913
|
+
for (let i = ln + 1; i < lines3.length; i++) {
|
|
2914
|
+
if (new RegExp(`^\\s*(?:${CURSOR}\\s*)?(Submit|Next)\\s*$`).test(lines3[i]) || /^\s*(?:[❯>›]\s*)?[☐☒]?\s*\d+\./.test(lines3[i])) break;
|
|
2915
|
+
parts.push(lines3[i]);
|
|
2916
|
+
}
|
|
2917
|
+
return squash(parts.join(""));
|
|
2918
|
+
}
|
|
2919
|
+
async function typeOther(io, q, text) {
|
|
2920
|
+
const n = q.options.length;
|
|
2921
|
+
const want = squash(text);
|
|
2922
|
+
if (!want) return "no_focus";
|
|
2923
|
+
if (!await waitUntil(io, (l) => onQuestion(l, q) && typedText(l, n) === "")) return "no_focus";
|
|
2924
|
+
io.write(text);
|
|
2925
|
+
return await waitUntil(io, (l) => typedText(l, n) === want) ? "typed" : "mismatch";
|
|
2926
|
+
}
|
|
2853
2927
|
async function move(io, delta) {
|
|
2854
2928
|
const key = delta > 0 ? KEY_DOWN : KEY_UP;
|
|
2855
2929
|
for (let i = 0; i < Math.abs(delta); i++) {
|
|
@@ -2857,12 +2931,16 @@ async function move(io, delta) {
|
|
|
2857
2931
|
await io.sleep(ARROW_GAP_MS);
|
|
2858
2932
|
}
|
|
2859
2933
|
}
|
|
2860
|
-
async function answerQuestions(io, questions, selections) {
|
|
2934
|
+
async function answerQuestions(io, questions, selections, others) {
|
|
2861
2935
|
if (questions.length === 0 || selections.length !== questions.length) return "not_waiting";
|
|
2936
|
+
if (others !== void 0 && others.length !== questions.length) return "not_waiting";
|
|
2862
2937
|
for (let qi = 0; qi < questions.length; qi++) {
|
|
2863
2938
|
const sel = selections[qi];
|
|
2864
2939
|
const q = questions[qi];
|
|
2865
|
-
|
|
2940
|
+
const n = q.options.length;
|
|
2941
|
+
const other = others?.[qi] ?? "";
|
|
2942
|
+
if (sel.length === 0 || sel.some((i) => !Number.isInteger(i) || i < 0 || i > n)) return "not_waiting";
|
|
2943
|
+
if (sel.includes(n) !== (squash(other) !== "")) return "not_waiting";
|
|
2866
2944
|
if (q.multiSelect !== true && sel.length !== 1) return "not_waiting";
|
|
2867
2945
|
}
|
|
2868
2946
|
if (!await settled(io, (l) => onQuestion(l, questions[0]))) return "not_waiting";
|
|
@@ -2883,6 +2961,14 @@ async function answerQuestions(io, questions, selections) {
|
|
|
2883
2961
|
for (const t of sel) {
|
|
2884
2962
|
await move(io, t - cur);
|
|
2885
2963
|
cur = t;
|
|
2964
|
+
if (t === n) {
|
|
2965
|
+
const ty = await typeOther(io, q, others?.[qi] ?? "");
|
|
2966
|
+
if (ty !== "no_focus") wrote = true;
|
|
2967
|
+
if (ty !== "typed") return fail();
|
|
2968
|
+
io.write(KEY_ENTER);
|
|
2969
|
+
if (!await waitUntil(io, (l) => checked(l, typeLine(l, n)))) return fail();
|
|
2970
|
+
continue;
|
|
2971
|
+
}
|
|
2886
2972
|
const onTarget = await waitUntil(io, (l) => {
|
|
2887
2973
|
const ln = optionLine(l, t + 1, q.options[t].label);
|
|
2888
2974
|
return ln >= 0 && io.cursorLine?.() === ln;
|
|
@@ -2901,7 +2987,11 @@ async function answerQuestions(io, questions, selections) {
|
|
|
2901
2987
|
const cur = singleCursor(io.screen(), q);
|
|
2902
2988
|
if (cur < 0) return fail();
|
|
2903
2989
|
await move(io, t - cur);
|
|
2904
|
-
if (
|
|
2990
|
+
if (t === n) {
|
|
2991
|
+
const ty = await typeOther(io, q, others?.[qi] ?? "");
|
|
2992
|
+
if (ty !== "no_focus") wrote = true;
|
|
2993
|
+
if (ty !== "typed") return fail();
|
|
2994
|
+
} else if (!await waitUntil(io, (l) => singleCursor(l, q) === t && optionLine(l, t + 1, q.options[t].label) >= 0)) return fail();
|
|
2905
2995
|
io.write(KEY_ENTER);
|
|
2906
2996
|
wrote = true;
|
|
2907
2997
|
}
|
|
@@ -7759,7 +7849,14 @@ ${PRELUDE3}
|
|
|
7759
7849
|
}
|
|
7760
7850
|
}
|
|
7761
7851
|
if (C && typeof C.currentId === 'string') return { mode: 'dom', locale: localeOf(), why };
|
|
7762
|
-
|
|
7852
|
+
// 没有 SDK 时列出页面上像接口的全局名(258 退回:WorkBuddy 5.1.7 没有 wb,日志里据此判断老版本把接口放在哪)
|
|
7853
|
+
let globals;
|
|
7854
|
+
if (why === 'no_wb') {
|
|
7855
|
+
try {
|
|
7856
|
+
globals = Object.getOwnPropertyNames(globalThis).filter((k) => /wb|work|buddy|genie|sdk|electron|bridge|ipc|conv|agent|app/i.test(k) && !/^on/.test(k) && k.length <= 40).sort().slice(0, 30);
|
|
7857
|
+
} catch (e) { globals = undefined; }
|
|
7858
|
+
}
|
|
7859
|
+
return { mode: 'none', locale: localeOf(), why, ...(globals ? { globals } : {}) };
|
|
7763
7860
|
})()`;
|
|
7764
7861
|
var IDLE_STATES = "['idle','completed','cancelled','canceled','done','failed','error','terminated','archived','deleted','']";
|
|
7765
7862
|
var SNAPSHOT2 = String.raw`(async () => {
|
|
@@ -7909,6 +8006,8 @@ ${PRELUDE3}
|
|
|
7909
8006
|
|
|
7910
8007
|
// src/daemon/workbuddyApp/watch.ts
|
|
7911
8008
|
var KEEPER_EVERY_MS3 = 15 * 1e3;
|
|
8009
|
+
var NON_SDK_KEEP_MS = 60 * 1e3;
|
|
8010
|
+
var NO_SDK_REPROBE_MS = 90 * 1e3;
|
|
7912
8011
|
var PROBE_EVERY_MS3 = 60 * 1e3;
|
|
7913
8012
|
var SEEN_TTL_MS4 = 60 * 60 * 1e3;
|
|
7914
8013
|
var CONNECT_BACKOFF_MIN_MS3 = 15 * 1e3;
|
|
@@ -7956,6 +8055,10 @@ var WorkbuddyAppWatch = class {
|
|
|
7956
8055
|
#modeProbed = false;
|
|
7957
8056
|
#connectedAt = 0;
|
|
7958
8057
|
#nonSdkSince = 0;
|
|
8058
|
+
/** 断开时还是非 sdk:记下原起点和断开时刻,短暂断线(< NON_SDK_KEEP_MS)重连后仍非 sdk 就沿用(258 退回:断线清零让快速回落永远攒不够) */
|
|
8059
|
+
#nonSdkKept = null;
|
|
8060
|
+
/** 上次因为「页面里没有 SDK」重连重探候选页的时刻 */
|
|
8061
|
+
#reprobeAt = 0;
|
|
7959
8062
|
#connectError = "";
|
|
7960
8063
|
/** 端口检查过没有(第一轮不通也记一行) */
|
|
7961
8064
|
#portChecked = false;
|
|
@@ -8146,7 +8249,7 @@ var WorkbuddyAppWatch = class {
|
|
|
8146
8249
|
}
|
|
8147
8250
|
if (now < this.#connectRetryAt) return;
|
|
8148
8251
|
try {
|
|
8149
|
-
const client = await (this.#d.connect ?? ((p) => connectCdp(p)))(this.#d.port());
|
|
8252
|
+
const client = await (this.#d.connect ?? ((p) => connectCdp(p, { pickSdk: true })))(this.#d.port());
|
|
8150
8253
|
if (this.#stopped) {
|
|
8151
8254
|
try {
|
|
8152
8255
|
client.close();
|
|
@@ -8163,7 +8266,8 @@ var WorkbuddyAppWatch = class {
|
|
|
8163
8266
|
this.#connectBackoffMs = CONNECT_BACKOFF_MIN_MS3;
|
|
8164
8267
|
this.#connectRetryAt = 0;
|
|
8165
8268
|
this.#connectFailLogged = false;
|
|
8166
|
-
|
|
8269
|
+
const ti = client.target;
|
|
8270
|
+
this.#d.log(`WorkBuddy App \u6388\u6743\u6865\u5DF2\u8FDE\u4E0A${ti ? `\uFF08\u9875\u9762 ${ti.url}\uFF0C\u5019\u9009 ${ti.index + 1}/${ti.candidates}${ti.sdk === false ? "\uFF0C\u5404\u5019\u9009\u9875\u90FD\u6CA1\u6709 SDK" : ""}${ti.ua ? `\uFF0C${ti.ua}` : ""}\uFF09` : ""}`);
|
|
8167
8271
|
} catch (e) {
|
|
8168
8272
|
this.#client = null;
|
|
8169
8273
|
this.#connectError = String(e?.message ?? e).slice(0, 120);
|
|
@@ -8187,9 +8291,26 @@ var WorkbuddyAppWatch = class {
|
|
|
8187
8291
|
this.#mode = r?.mode === "sdk" ? "sdk" : r?.mode === "dom" ? "dom" : "none";
|
|
8188
8292
|
this.#modeWhy = this.#mode === "sdk" ? "" : !r ? "no_result" : typeof r.why === "string" ? r.why.slice(0, 120) : "";
|
|
8189
8293
|
this.#modeProbed = true;
|
|
8190
|
-
if (this.#mode === "sdk")
|
|
8191
|
-
|
|
8192
|
-
|
|
8294
|
+
if (this.#mode === "sdk") {
|
|
8295
|
+
this.#nonSdkSince = 0;
|
|
8296
|
+
this.#nonSdkKept = null;
|
|
8297
|
+
} else if (first || prev === "sdk" || !this.#nonSdkSince) {
|
|
8298
|
+
const kept = this.#nonSdkKept;
|
|
8299
|
+
this.#nonSdkSince = first && kept && now - kept.at < NON_SDK_KEEP_MS ? kept.since : now;
|
|
8300
|
+
this.#nonSdkKept = null;
|
|
8301
|
+
}
|
|
8302
|
+
if (first || prev !== this.#mode || prevWhy !== this.#modeWhy) {
|
|
8303
|
+
const g = Array.isArray(r?.globals) ? r.globals.filter((x) => typeof x === "string").map((x) => x.slice(0, 40)).slice(0, 30) : null;
|
|
8304
|
+
this.#d.log(`WorkBuddy App \u6388\u6743\u6865\u6A21\u5F0F\uFF1A${this.#mode}${this.#modeWhy ? `\uFF08${modeWhyText(this.#modeWhy)}\uFF09` : ""}${g ? `\uFF1B\u9875\u9762\u5168\u5C40\u540D\uFF1A${g.join(",") || "\u65E0"}` : ""}`);
|
|
8305
|
+
}
|
|
8306
|
+
const cands = this.#client?.target?.candidates ?? 1;
|
|
8307
|
+
if (this.#mode !== "sdk" && this.#modeWhy === "no_wb" && cands > 1 && this.#nonSdkSince && now - this.#nonSdkSince >= NO_SDK_REPROBE_MS && now - this.#reprobeAt >= NO_SDK_REPROBE_MS) {
|
|
8308
|
+
this.#reprobeAt = now;
|
|
8309
|
+
this.#d.log(`WorkBuddy App \u5404\u5019\u9009\u9875\u90FD\u6CA1\u6709 SDK \u5DF2\u8D85\u8FC7 ${NO_SDK_REPROBE_MS / 1e3} \u79D2\uFF0C\u91CD\u8FDE\u518D\u9010\u9875\u63A2\u4E00\u6B21`);
|
|
8310
|
+
this.#disconnect(REASON_APP_EXITED);
|
|
8311
|
+
this.#connectRetryAt = 0;
|
|
8312
|
+
return;
|
|
8313
|
+
}
|
|
8193
8314
|
}
|
|
8194
8315
|
if (!this.#client) return;
|
|
8195
8316
|
if (this.#mode === "sdk") await this.#sdkRound();
|
|
@@ -8208,6 +8329,7 @@ var WorkbuddyAppWatch = class {
|
|
|
8208
8329
|
}
|
|
8209
8330
|
}
|
|
8210
8331
|
#disconnect(reason) {
|
|
8332
|
+
if (this.#nonSdkSince) this.#nonSdkKept = { since: this.#nonSdkSince, at: this.#now() };
|
|
8211
8333
|
this.#mode = "none";
|
|
8212
8334
|
this.#modeWhy = "";
|
|
8213
8335
|
this.#modeProbed = false;
|
|
@@ -8449,7 +8571,7 @@ function modeWhyText(why) {
|
|
|
8449
8571
|
const msg = rest.join(":");
|
|
8450
8572
|
switch (k) {
|
|
8451
8573
|
case "no_wb":
|
|
8452
|
-
return "\u9875\u9762\u91CC\u6CA1\u6709 WorkBuddy SDK\uFF08globalThis.wb\uFF09";
|
|
8574
|
+
return "\u9875\u9762\u91CC\u6CA1\u6709 WorkBuddy SDK\uFF08globalThis.wb\uFF09\uFF0CWorkBuddy \u7248\u672C\u53EF\u80FD\u592A\u65E7\uFF0C\u5347\u7EA7\u5230\u6700\u65B0\u7248\u540E\u4EFB\u52A1\u624D\u80FD\u76F4\u63A5\u8FDB App";
|
|
8453
8575
|
case "no_conversations":
|
|
8454
8576
|
return "\u9875\u9762\u91CC\u6CA1\u6709\u4F1A\u8BDD\u63A5\u53E3\uFF08wb.conversations\uFF09";
|
|
8455
8577
|
case "no_list_get":
|
|
@@ -8810,6 +8932,7 @@ var REASON_TAKEOVER = "\u5DF2\u6539\u63A8\u9009\u62E9\u9898\u5361";
|
|
|
8810
8932
|
var FALLBACK_GRACE_MS = 3e3;
|
|
8811
8933
|
var FALLBACK_GRACE_APP_MS = 8e3;
|
|
8812
8934
|
var FALLBACK_BUTTON = "\u53BB\u7535\u8111\u4E0A\u4F5C\u7B54";
|
|
8935
|
+
var NOPORT_STAT = "[stat:qoder_noport_question]";
|
|
8813
8936
|
var REASON_APP_GONE = REASON_APP_EXITED;
|
|
8814
8937
|
var REASON_STOPPED = "Qoder App \u5DF2\u65AD\u5F00";
|
|
8815
8938
|
var RECOMMENDED_RE2 = /\s*\(Recommended\)\s*$/i;
|
|
@@ -9025,7 +9148,7 @@ var QoderAppQuestions = class {
|
|
|
9025
9148
|
card.markedAt = this.#mark(sid);
|
|
9026
9149
|
if (noPort && !this.#noPortLogged.has(sid)) {
|
|
9027
9150
|
this.#noPortLogged.add(sid);
|
|
9028
|
-
this.#d.log(`${this.#d.label} App \u6CA1\u5E26\u8C03\u8BD5\u7AEF\u53E3\uFF0CApp \u91CC\u7684\u9009\u62E9\u9898\u63A8\u4E0D\u5230\u8BBE\u5907\uFF0C\u5DF2\u63A8\u63D0\u793A\u5361\uFF08\u4F1A\u8BDD ${sid.slice(0, 8)}\uFF09`);
|
|
9151
|
+
this.#d.log(`${this.#d.label} App \u6CA1\u5E26\u8C03\u8BD5\u7AEF\u53E3\uFF0CApp \u91CC\u7684\u9009\u62E9\u9898\u63A8\u4E0D\u5230\u8BBE\u5907\uFF0C\u5DF2\u63A8\u63D0\u793A\u5361\uFF08\u4F1A\u8BDD ${sid.slice(0, 8)}\uFF09 ${NOPORT_STAT} tool=${this.#d.tool} scene=notice`);
|
|
9029
9152
|
}
|
|
9030
9153
|
const req = {
|
|
9031
9154
|
window: true,
|
|
@@ -9307,7 +9430,7 @@ var QoderHookQuestionGate = class {
|
|
|
9307
9430
|
const questions = hookQuestions(hook.tool_input);
|
|
9308
9431
|
if (!questions || hasDuplicateQuestion(questions)) return none;
|
|
9309
9432
|
if (!await this.#d.userAway(tool)) {
|
|
9310
|
-
this.#d.log(`${tag}\uFF1AApp \u6CA1\u8FDE\u4E0A\u8C03\u8BD5\u7AEF\u53E3\uFF0C\u7528\u6237\u5728\u7535\u8111\u524D\uFF0C\u9009\u62E9\u9898\u7167\u5E38\u5728\u7535\u8111\u4E0A\u51FA`);
|
|
9433
|
+
this.#d.log(`${tag}\uFF1AApp \u6CA1\u8FDE\u4E0A\u8C03\u8BD5\u7AEF\u53E3\uFF0C\u7528\u6237\u5728\u7535\u8111\u524D\uFF0C\u9009\u62E9\u9898\u7167\u5E38\u5728\u7535\u8111\u4E0A\u51FA ${NOPORT_STAT} tool=${tool} scene=present`);
|
|
9311
9434
|
return none;
|
|
9312
9435
|
}
|
|
9313
9436
|
if (signal.aborted) return none;
|
|
@@ -9319,7 +9442,7 @@ var QoderHookQuestionGate = class {
|
|
|
9319
9442
|
const onAbort = () => ac.abort(typeof signal.reason === "string" && signal.reason ? signal.reason : REASON_PC_CANCELLED);
|
|
9320
9443
|
if (signal.aborted) onAbort();
|
|
9321
9444
|
else signal.addEventListener("abort", onAbort, { once: true });
|
|
9322
|
-
this.#d.log(`${tag}\uFF1AApp \u6CA1\u8FDE\u4E0A\u8C03\u8BD5\u7AEF\u53E3\u3001\u7528\u6237\u4E0D\u5728\u7535\u8111\u524D\uFF0C\u9009\u62E9\u9898\u6302\u8D77\u5E76\u63A8\u8BBE\u5907`);
|
|
9445
|
+
this.#d.log(`${tag}\uFF1AApp \u6CA1\u8FDE\u4E0A\u8C03\u8BD5\u7AEF\u53E3\u3001\u7528\u6237\u4E0D\u5728\u7535\u8111\u524D\uFF0C\u9009\u62E9\u9898\u6302\u8D77\u5E76\u63A8\u8BBE\u5907 ${NOPORT_STAT} tool=${tool} scene=away`);
|
|
9323
9446
|
const cwd = typeof hook.cwd === "string" ? hook.cwd : "";
|
|
9324
9447
|
const card = this.#d.gate(
|
|
9325
9448
|
{
|
|
@@ -9601,6 +9724,7 @@ import { resolve as resolve4 } from "path";
|
|
|
9601
9724
|
var WB_APP_WAKE_WAIT_MS = 60 * 1e3;
|
|
9602
9725
|
var WB_APP_WAKE_WAIT_WIN_MS = 120 * 1e3;
|
|
9603
9726
|
var WB_APP_STUCK_MS = 120 * 1e3;
|
|
9727
|
+
var WB_APP_NO_SDK_MS = 15 * 1e3;
|
|
9604
9728
|
var WB_APP_CONFIRM_MS = 60 * 1e3;
|
|
9605
9729
|
var WB_APP_CONFIRM_POLL_MS = 5 * 1e3;
|
|
9606
9730
|
var WB_APP_LOCATE_WAIT_MS = 20 * 1e3;
|
|
@@ -9715,7 +9839,7 @@ var WbAppTasks = class {
|
|
|
9715
9839
|
* 计时起点是「模式最近一次变成非 sdk 的时刻」(长期 sdk 时偶尔掉一下不算);页面脚本没结果(no_result,多半是一次超时)
|
|
9716
9840
|
* 不算:催一次重探,照常等。返回原因;不是这种情况返回 ''
|
|
9717
9841
|
*/
|
|
9718
|
-
#stuckWhy(max) {
|
|
9842
|
+
#stuckWhy(max, justWoke = false) {
|
|
9719
9843
|
const r = this.#readiness();
|
|
9720
9844
|
if (!r || !r.connected || !r.probed || r.mode === "sdk" || !r.nonSdkSince) return "";
|
|
9721
9845
|
if (r.modeWhy === "no_result") {
|
|
@@ -9723,7 +9847,7 @@ var WbAppTasks = class {
|
|
|
9723
9847
|
return "";
|
|
9724
9848
|
}
|
|
9725
9849
|
const secs = Math.round((this.#d.now() - r.nonSdkSince) / 1e3);
|
|
9726
|
-
if (this.#d.now() - r.nonSdkSince < max) return "";
|
|
9850
|
+
if (this.#d.now() - r.nonSdkSince < (r.modeWhy === "no_wb" && !justWoke ? Math.min(max, WB_APP_NO_SDK_MS) : max)) return "";
|
|
9727
9851
|
return `\u6388\u6743\u6865\u6A21\u5F0F\u662F ${r.mode} \u5DF2 ${secs} \u79D2${r.modeWhy ? `\uFF08${modeWhyText(r.modeWhy)}\uFF09` : ""}\uFF0CApp \u4E0D\u662F\u521A\u6253\u5F00\uFF0C\u518D\u7B49\u4E5F\u4E0D\u4F1A\u597D`;
|
|
9728
9852
|
}
|
|
9729
9853
|
async #ensureReady(cmd, sid, q, report, mayWake) {
|
|
@@ -9780,6 +9904,11 @@ var WbAppTasks = class {
|
|
|
9780
9904
|
await this.#sleep(Math.max(1, Math.min(this.#d.pollMs ?? WB_APP_POLL_MS, deadline - this.#d.now())));
|
|
9781
9905
|
const now = await this.#notReady();
|
|
9782
9906
|
if (!now) return true;
|
|
9907
|
+
const stuckNow = sid ? "" : this.#stuckWhy(WB_APP_STUCK_MS, w === "launched" || w === "restarted");
|
|
9908
|
+
if (stuckNow) {
|
|
9909
|
+
this.#d.log(`\u6307\u4EE4 ${cmd.instructionId} WorkBuddy App \u7528\u4E0D\u4E86\uFF1A${stuckNow}\uFF0C\u8D70\u547D\u4EE4\u884C`);
|
|
9910
|
+
return false;
|
|
9911
|
+
}
|
|
9783
9912
|
if (now !== why) this.#d.log(`\u6307\u4EE4 ${cmd.instructionId} \u7B49 WorkBuddy App\uFF1A${now}`);
|
|
9784
9913
|
why = now;
|
|
9785
9914
|
}
|
|
@@ -10379,14 +10508,28 @@ function parseAnswer(m) {
|
|
|
10379
10508
|
const questions = parseQuestions(a.questions);
|
|
10380
10509
|
const sel = a.selections;
|
|
10381
10510
|
if (!questions || sel.length !== questions.length) return null;
|
|
10511
|
+
let others;
|
|
10512
|
+
if (a.others !== void 0) {
|
|
10513
|
+
if (!Array.isArray(a.others) || a.others.length !== questions.length) return null;
|
|
10514
|
+
others = [];
|
|
10515
|
+
for (const o of a.others) {
|
|
10516
|
+
if (typeof o !== "string" || o.length > OTHER_MAX_CHARS || /[\u0000-\u001f\u007f-\u009f\u200b-\u200f\u202a-\u202e\u2066-\u2069\ufeff]/.test(o)) return null;
|
|
10517
|
+
others.push(o);
|
|
10518
|
+
}
|
|
10519
|
+
}
|
|
10382
10520
|
const selections = [];
|
|
10383
10521
|
for (let i = 0; i < questions.length; i++) {
|
|
10384
10522
|
const s2 = sel[i];
|
|
10385
|
-
|
|
10523
|
+
const n = questions[i].options.length;
|
|
10524
|
+
const other = others?.[i] ?? "";
|
|
10525
|
+
if (!Array.isArray(s2) || s2.length === 0 || !s2.every((x) => Number.isInteger(x) && x >= 0 && x <= n)) return null;
|
|
10526
|
+
if (s2.includes(n) !== (other.trim() !== "")) return null;
|
|
10527
|
+
if (new Set(s2).size !== s2.length) return null;
|
|
10386
10528
|
selections.push(s2);
|
|
10387
10529
|
}
|
|
10388
|
-
return { instructionId, sessionId, expireAt, answer: { kind: "question", questions, selections } };
|
|
10530
|
+
return { instructionId, sessionId, expireAt, answer: { kind: "question", questions, selections, ...others ? { others } : {} } };
|
|
10389
10531
|
}
|
|
10532
|
+
var OTHER_MAX_CHARS = 500;
|
|
10390
10533
|
function parseQuestions(v) {
|
|
10391
10534
|
if (!Array.isArray(v)) return null;
|
|
10392
10535
|
const qs = v;
|
|
@@ -10752,20 +10895,31 @@ function pendingCall(text, toolName) {
|
|
|
10752
10895
|
function selectionsOf(input, lists) {
|
|
10753
10896
|
const qs = Array.isArray(input.questions) ? input.questions : null;
|
|
10754
10897
|
if (!qs || !Array.isArray(lists) || lists.length !== qs.length) return null;
|
|
10755
|
-
const
|
|
10898
|
+
const selections = [];
|
|
10899
|
+
const others = [];
|
|
10756
10900
|
for (let i = 0; i < qs.length; i++) {
|
|
10757
10901
|
const opts = Array.isArray(qs[i]?.options) ? qs[i].options : [];
|
|
10758
10902
|
const items = lists[i];
|
|
10759
10903
|
if (!Array.isArray(items) || items.length === 0) return null;
|
|
10760
10904
|
const idx = [];
|
|
10761
|
-
|
|
10905
|
+
let other = "";
|
|
10906
|
+
for (let j = 0; j < items.length; j++) {
|
|
10907
|
+
const label = items[j];
|
|
10762
10908
|
const k = opts.findIndex((o) => o?.label === label);
|
|
10763
|
-
if (k
|
|
10764
|
-
|
|
10909
|
+
if (k >= 0) {
|
|
10910
|
+
if (!idx.includes(k)) idx.push(k);
|
|
10911
|
+
continue;
|
|
10912
|
+
}
|
|
10913
|
+
if (j !== items.length - 1 || typeof label !== "string") return null;
|
|
10914
|
+
other = label.replace(/[\u0000-\u001f\u007f-\u009f\u200b-\u200f\u202a-\u202e\u2066-\u2069\ufeff]+/g, " ").replace(/\s+/g, " ").trim();
|
|
10915
|
+
if (!other) return null;
|
|
10765
10916
|
}
|
|
10766
|
-
|
|
10917
|
+
if (other) idx.push(opts.length);
|
|
10918
|
+
if (qs[i]?.multiSelect !== true && idx.length !== 1) return null;
|
|
10919
|
+
selections.push(idx);
|
|
10920
|
+
others.push(other);
|
|
10767
10921
|
}
|
|
10768
|
-
return
|
|
10922
|
+
return { selections, others };
|
|
10769
10923
|
}
|
|
10770
10924
|
var WorkbuddyBridge = class {
|
|
10771
10925
|
#d;
|
|
@@ -10903,10 +11057,16 @@ var WorkbuddyBridge = class {
|
|
|
10903
11057
|
if (reply.decision !== "allow") return;
|
|
10904
11058
|
const sel = selectionsOf(card.input, reply.answerLists);
|
|
10905
11059
|
if (!sel) {
|
|
10906
|
-
this.#d.log(`WorkBuddy\uFF1A\u4F1A\u8BDD ${card.sessionId.slice(0, 8)} \u7684\u8BBE\u5907\u7B54\u6848\u5BF9\u4E0D\u4E0A\u9009\u9879\
|
|
11060
|
+
this.#d.log(`WorkBuddy\uFF1A\u4F1A\u8BDD ${card.sessionId.slice(0, 8)} \u7684\u8BBE\u5907\u7B54\u6848\u5BF9\u4E0D\u4E0A\u9009\u9879\uFF0C\u6846\u7559\u7ED9\u7535\u8111`);
|
|
10907
11061
|
return;
|
|
10908
11062
|
}
|
|
10909
|
-
|
|
11063
|
+
const withOther = sel.others.some((o) => o !== "");
|
|
11064
|
+
spec = {
|
|
11065
|
+
kind: "question",
|
|
11066
|
+
questions: card.input.questions,
|
|
11067
|
+
selections: sel.selections,
|
|
11068
|
+
...withOther ? { others: sel.others } : {}
|
|
11069
|
+
};
|
|
10910
11070
|
} else if (reply.decision === "allow" || reply.decision === "deny") {
|
|
10911
11071
|
spec = { kind: "permission", toolName: card.toolName, fingerprint: card.fingerprint, decision: reply.decision };
|
|
10912
11072
|
} else return;
|
|
@@ -12665,10 +12825,50 @@ function unwrapShell(command) {
|
|
|
12665
12825
|
const w = command.match(/^"?(?:[^"]*[\\/])?(?:powershell|pwsh)(?:\.exe)?"?(?: -NoLogo| -NoProfile| -NonInteractive)* -Command ([\s\S]+)$/i);
|
|
12666
12826
|
if (!w) return command;
|
|
12667
12827
|
const body = w[1].trim();
|
|
12828
|
+
const posix4 = posixWord(body);
|
|
12829
|
+
if (posix4 !== null && /^'[^']*'["']/.test(body)) return posix4;
|
|
12668
12830
|
if (body.length >= 2 && body.startsWith('"') && body.endsWith('"')) return body.slice(1, -1).replace(/\\"/g, '"');
|
|
12669
12831
|
if (body.length >= 2 && body.startsWith("'") && body.endsWith("'")) return body.slice(1, -1).replace(/''/g, "'");
|
|
12670
12832
|
return body;
|
|
12671
12833
|
}
|
|
12834
|
+
function posixWord(s2) {
|
|
12835
|
+
let out = "";
|
|
12836
|
+
let i = 0;
|
|
12837
|
+
while (i < s2.length) {
|
|
12838
|
+
const c = s2[i];
|
|
12839
|
+
if (c === "'") {
|
|
12840
|
+
const j = s2.indexOf("'", i + 1);
|
|
12841
|
+
if (j < 0) return null;
|
|
12842
|
+
out += s2.slice(i + 1, j);
|
|
12843
|
+
i = j + 1;
|
|
12844
|
+
} else if (c === '"') {
|
|
12845
|
+
i++;
|
|
12846
|
+
let closed = false;
|
|
12847
|
+
while (i < s2.length) {
|
|
12848
|
+
const d = s2[i];
|
|
12849
|
+
if (d === '"') {
|
|
12850
|
+
closed = true;
|
|
12851
|
+
i++;
|
|
12852
|
+
break;
|
|
12853
|
+
}
|
|
12854
|
+
if (d === "\\" && i + 1 < s2.length && '\\"$`\n'.includes(s2[i + 1])) {
|
|
12855
|
+
out += s2[i + 1];
|
|
12856
|
+
i += 2;
|
|
12857
|
+
continue;
|
|
12858
|
+
}
|
|
12859
|
+
out += d;
|
|
12860
|
+
i++;
|
|
12861
|
+
}
|
|
12862
|
+
if (!closed) return null;
|
|
12863
|
+
} else if (/\s/.test(c)) {
|
|
12864
|
+
return null;
|
|
12865
|
+
} else {
|
|
12866
|
+
out += c;
|
|
12867
|
+
i++;
|
|
12868
|
+
}
|
|
12869
|
+
}
|
|
12870
|
+
return out;
|
|
12871
|
+
}
|
|
12672
12872
|
var CodexWatch = class {
|
|
12673
12873
|
#d;
|
|
12674
12874
|
#ws = null;
|
|
@@ -14046,6 +14246,68 @@ function describe2(r) {
|
|
|
14046
14246
|
return [r.status, r.n !== void 0 ? `n=${r.n}` : "", r.detail ?? ""].filter(Boolean).join(" ");
|
|
14047
14247
|
}
|
|
14048
14248
|
|
|
14249
|
+
// src/daemon/dshVersion.ts
|
|
14250
|
+
import { readFileSync as readFileSync11, realpathSync as realpathSync5 } from "fs";
|
|
14251
|
+
import { dirname as dirname8, join as join24 } from "path";
|
|
14252
|
+
var DSH_HEADLESS_MIN_VERSION = "0.0.1-rc.1";
|
|
14253
|
+
var DSH_PKG = "@deepseek-ai/dsh";
|
|
14254
|
+
var DSH_VERSION_UNSUPPORTED = "tool_version_unsupported";
|
|
14255
|
+
var defaultDeps2 = {
|
|
14256
|
+
locate: () => locate("deepseek_harness"),
|
|
14257
|
+
realpath: (p) => realpathSync5.native(p),
|
|
14258
|
+
readFile: (p) => {
|
|
14259
|
+
try {
|
|
14260
|
+
return readFileSync11(p, "utf8");
|
|
14261
|
+
} catch {
|
|
14262
|
+
return null;
|
|
14263
|
+
}
|
|
14264
|
+
}
|
|
14265
|
+
};
|
|
14266
|
+
function dshSupport(d = defaultDeps2) {
|
|
14267
|
+
let loc = null;
|
|
14268
|
+
try {
|
|
14269
|
+
loc = d.locate();
|
|
14270
|
+
} catch {
|
|
14271
|
+
loc = null;
|
|
14272
|
+
}
|
|
14273
|
+
if (!loc) return { ok: true };
|
|
14274
|
+
const script = loc.prefixArgs.find((a) => /\.(?:c|m)?js$/i.test(a)) ?? loc.file;
|
|
14275
|
+
let real2 = script;
|
|
14276
|
+
try {
|
|
14277
|
+
real2 = d.realpath(script);
|
|
14278
|
+
} catch {
|
|
14279
|
+
real2 = script;
|
|
14280
|
+
}
|
|
14281
|
+
let dir2 = dirname8(real2);
|
|
14282
|
+
for (let i = 0; i < 4; i++) {
|
|
14283
|
+
const raw = d.readFile(join24(dir2, "package.json"));
|
|
14284
|
+
if (raw !== null) {
|
|
14285
|
+
let pkg = {};
|
|
14286
|
+
try {
|
|
14287
|
+
pkg = JSON.parse(raw);
|
|
14288
|
+
} catch {
|
|
14289
|
+
pkg = {};
|
|
14290
|
+
}
|
|
14291
|
+
const name = typeof pkg.name === "string" ? pkg.name : "";
|
|
14292
|
+
const version = typeof pkg.version === "string" ? pkg.version : "";
|
|
14293
|
+
if (!name) {
|
|
14294
|
+
dir2 = dirname8(dir2);
|
|
14295
|
+
continue;
|
|
14296
|
+
}
|
|
14297
|
+
if (name !== DSH_PKG) return { ok: true };
|
|
14298
|
+
if (!isValidVersion(version) || semverLt(version, DSH_HEADLESS_MIN_VERSION)) return { ok: false, why: `${DSH_PKG} ${version || "\u7248\u672C\u8BFB\u4E0D\u51FA"} \u4F4E\u4E8E ${DSH_HEADLESS_MIN_VERSION}` };
|
|
14299
|
+
return { ok: true, version };
|
|
14300
|
+
}
|
|
14301
|
+
const up = dirname8(dir2);
|
|
14302
|
+
if (up === dir2) break;
|
|
14303
|
+
dir2 = up;
|
|
14304
|
+
}
|
|
14305
|
+
return { ok: true };
|
|
14306
|
+
}
|
|
14307
|
+
function dshOutputUnsupported(out) {
|
|
14308
|
+
return /unknown (?:command|option|argument)[^\n]*(?:headless|profile)|(?:invalid|no such) (?:command|choice)[^\n]*(?:headless|profile)|unrecognized arguments?:[^\n]*(?:--profile|headless)/i.test(out);
|
|
14309
|
+
}
|
|
14310
|
+
|
|
14049
14311
|
// src/daemon/opencodeVersion.ts
|
|
14050
14312
|
import { execFile as execFile5 } from "child_process";
|
|
14051
14313
|
import { statSync as statSync12 } from "fs";
|
|
@@ -14535,24 +14797,24 @@ function startWakeServer(path, hub, secret, platform = process.platform) {
|
|
|
14535
14797
|
}
|
|
14536
14798
|
|
|
14537
14799
|
// src/core/appended.ts
|
|
14538
|
-
import { chmodSync as chmodSync4, mkdirSync as mkdirSync11, readFileSync as
|
|
14539
|
-
import { join as
|
|
14800
|
+
import { chmodSync as chmodSync4, mkdirSync as mkdirSync11, readFileSync as readFileSync12, renameSync as renameSync8, rmSync as rmSync9, writeFileSync as writeFileSync10 } from "fs";
|
|
14801
|
+
import { join as join25 } from "path";
|
|
14540
14802
|
var APPENDED_MAX_ITEMS = 5;
|
|
14541
14803
|
var APPENDED_TEXT_MAX = 500;
|
|
14542
14804
|
var APPENDED_RESULT_MAX = 800;
|
|
14543
14805
|
var APPENDED_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
14544
14806
|
function appendedDir() {
|
|
14545
|
-
return
|
|
14807
|
+
return join25(deskbuddyHome(), "appended");
|
|
14546
14808
|
}
|
|
14547
14809
|
function appendedPath(sessionId) {
|
|
14548
14810
|
const safe2 = sessionId.replace(/[^A-Za-z0-9_-]/g, "");
|
|
14549
|
-
return safe2 ?
|
|
14811
|
+
return safe2 ? join25(appendedDir(), `${safe2}.json`) : null;
|
|
14550
14812
|
}
|
|
14551
14813
|
function readAppended(sessionId) {
|
|
14552
14814
|
const file = appendedPath(sessionId);
|
|
14553
14815
|
if (!file) return [];
|
|
14554
14816
|
try {
|
|
14555
|
-
const d = JSON.parse(
|
|
14817
|
+
const d = JSON.parse(readFileSync12(file, "utf8"));
|
|
14556
14818
|
return Array.isArray(d.items) ? d.items : [];
|
|
14557
14819
|
} catch {
|
|
14558
14820
|
return [];
|
|
@@ -14576,13 +14838,13 @@ function writeAppended(sessionId, item) {
|
|
|
14576
14838
|
var RUNNING_TTL_MS = 60 * 60 * 1e3;
|
|
14577
14839
|
function runningPath(sessionId) {
|
|
14578
14840
|
const safe2 = sessionId.replace(/[^A-Za-z0-9_-]/g, "");
|
|
14579
|
-
return safe2 ?
|
|
14841
|
+
return safe2 ? join25(deskbuddyHome(), "running", `${safe2}.json`) : null;
|
|
14580
14842
|
}
|
|
14581
14843
|
function writeRunning(sessionId, now = Date.now()) {
|
|
14582
14844
|
const file = runningPath(sessionId);
|
|
14583
14845
|
if (!file) return;
|
|
14584
14846
|
try {
|
|
14585
|
-
mkdirSync11(
|
|
14847
|
+
mkdirSync11(join25(deskbuddyHome(), "running"), { recursive: true, mode: 448 });
|
|
14586
14848
|
writeFileSync10(`${file}.tmp`, JSON.stringify({ at: now, pid: process.pid }), { encoding: "utf8", mode: 384 });
|
|
14587
14849
|
renameSync8(`${file}.tmp`, file);
|
|
14588
14850
|
} catch {
|
|
@@ -14629,8 +14891,8 @@ function resultSummary(tool, stdout6) {
|
|
|
14629
14891
|
}
|
|
14630
14892
|
|
|
14631
14893
|
// src/core/dshMailbox.ts
|
|
14632
|
-
import { chmodSync as chmodSync5, existsSync as existsSync6, mkdirSync as mkdirSync12, readdirSync as readdirSync10, readFileSync as
|
|
14633
|
-
import { join as
|
|
14894
|
+
import { chmodSync as chmodSync5, existsSync as existsSync6, mkdirSync as mkdirSync12, readdirSync as readdirSync10, readFileSync as readFileSync13, renameSync as renameSync9, rmSync as rmSync10, writeFileSync as writeFileSync11 } from "fs";
|
|
14895
|
+
import { join as join26 } from "path";
|
|
14634
14896
|
var DSH_HEARTBEAT_FRESH_MS = 5 * 1e3;
|
|
14635
14897
|
var DSH_ACK_TIMEOUT_MS = 8 * 1e3;
|
|
14636
14898
|
var ACK_POLL_MS = 200;
|
|
@@ -14641,10 +14903,10 @@ var REVOKE_RETRY_MS = 50;
|
|
|
14641
14903
|
var SID_RE2 = /^[A-Za-z0-9_-]{1,128}$/;
|
|
14642
14904
|
var IID_RE = /^[A-Za-z0-9_-]{1,128}$/;
|
|
14643
14905
|
function dshMailboxDir(home = deskbuddyHome(), channel = "dsh") {
|
|
14644
|
-
return
|
|
14906
|
+
return join26(home, channel);
|
|
14645
14907
|
}
|
|
14646
14908
|
function sub(home, name, channel = "dsh") {
|
|
14647
|
-
return
|
|
14909
|
+
return join26(dshMailboxDir(home, channel), name);
|
|
14648
14910
|
}
|
|
14649
14911
|
function ensureDir2(p) {
|
|
14650
14912
|
mkdirSync12(p, { recursive: true, mode: 448 });
|
|
@@ -14684,7 +14946,7 @@ function liveHeartbeats(sessionId, d0 = {}) {
|
|
|
14684
14946
|
if (!/^\d+\.json$/.test(n)) continue;
|
|
14685
14947
|
let hb;
|
|
14686
14948
|
try {
|
|
14687
|
-
hb = JSON.parse(
|
|
14949
|
+
hb = JSON.parse(readFileSync13(join26(dir2, n), "utf8"));
|
|
14688
14950
|
} catch {
|
|
14689
14951
|
continue;
|
|
14690
14952
|
}
|
|
@@ -14708,8 +14970,8 @@ async function dshDeliver(sessionId, msg, d0 = {}) {
|
|
|
14708
14970
|
const ackDir = sub(d.home, "ack", d.channel);
|
|
14709
14971
|
ensureDir2(inbox);
|
|
14710
14972
|
ensureDir2(ackDir);
|
|
14711
|
-
const letter =
|
|
14712
|
-
const ackPath =
|
|
14973
|
+
const letter = join26(inbox, `${sessionId}.${msg.instructionId}.json`);
|
|
14974
|
+
const ackPath = join26(ackDir, `${msg.instructionId}.json`);
|
|
14713
14975
|
if (existsSync6(letter)) return { ok: false, reason: "inbox_busy" };
|
|
14714
14976
|
const writtenAt = d.now();
|
|
14715
14977
|
writeJson(letter, {
|
|
@@ -14727,7 +14989,7 @@ async function dshDeliver(sessionId, msg, d0 = {}) {
|
|
|
14727
14989
|
if (existsSync6(ackPath)) {
|
|
14728
14990
|
let ack = { ok: false, reason: "bad_ack" };
|
|
14729
14991
|
try {
|
|
14730
|
-
const v = JSON.parse(
|
|
14992
|
+
const v = JSON.parse(readFileSync13(ackPath, "utf8"));
|
|
14731
14993
|
if (v && typeof v.ok === "boolean") ack = v;
|
|
14732
14994
|
} catch {
|
|
14733
14995
|
}
|
|
@@ -14778,10 +15040,10 @@ function dshClearInbox(home = deskbuddyHome(), channel = "dsh") {
|
|
|
14778
15040
|
var DSH_REPLY_WAIT_MS = 4 * 60 * 1e3;
|
|
14779
15041
|
function takeMailboxReply(instructionId, home = deskbuddyHome(), channel = "dsh") {
|
|
14780
15042
|
if (!IID_RE.test(instructionId)) return null;
|
|
14781
|
-
const p =
|
|
15043
|
+
const p = join26(sub(home, "reply", channel), `${instructionId}.json`);
|
|
14782
15044
|
let v = null;
|
|
14783
15045
|
try {
|
|
14784
|
-
v = JSON.parse(
|
|
15046
|
+
v = JSON.parse(readFileSync13(p, "utf8"));
|
|
14785
15047
|
} catch {
|
|
14786
15048
|
return null;
|
|
14787
15049
|
}
|
|
@@ -14807,7 +15069,7 @@ function clearDir(inbox) {
|
|
|
14807
15069
|
let n = 0;
|
|
14808
15070
|
for (const f of names) {
|
|
14809
15071
|
try {
|
|
14810
|
-
rmSync10(
|
|
15072
|
+
rmSync10(join26(inbox, f), { force: true });
|
|
14811
15073
|
n++;
|
|
14812
15074
|
} catch {
|
|
14813
15075
|
}
|
|
@@ -14882,7 +15144,7 @@ function defaultCodexAppServers() {
|
|
|
14882
15144
|
}
|
|
14883
15145
|
function opencodeReady() {
|
|
14884
15146
|
const mod = ocPluginModule(installedHookPath());
|
|
14885
|
-
return isOcPluginInstalled(opencodePluginPath()) && existsSync7(mod) && existsSync7(
|
|
15147
|
+
return isOcPluginInstalled(opencodePluginPath()) && existsSync7(mod) && existsSync7(join27(dirname9(mod), "ocTranslate.mjs"));
|
|
14886
15148
|
}
|
|
14887
15149
|
var INTERNAL_PROMPT_MARK = "[DeskBuddy]";
|
|
14888
15150
|
function orphanResumeText(summary2) {
|
|
@@ -15039,6 +15301,7 @@ var Daemon = class {
|
|
|
15039
15301
|
materialize: deps2.materialize ?? ((plan, tool) => materialize(plan, tool)),
|
|
15040
15302
|
opencodeReady: deps2.opencodeReady ?? opencodeReady,
|
|
15041
15303
|
opencodeVersion: deps2.opencodeVersion ?? defaultOpencodeVersion,
|
|
15304
|
+
dshSupport: deps2.dshSupport ?? (() => dshSupport()),
|
|
15042
15305
|
codexAppServers: deps2.codexAppServers ?? defaultCodexAppServers,
|
|
15043
15306
|
codexRoute: deps2.codexRoute ?? ((tid) => this.#codexRouteFor(tid)),
|
|
15044
15307
|
report: deps2.report ?? ((p, t) => api.commandResult(p, t)),
|
|
@@ -16741,7 +17004,7 @@ var Daemon = class {
|
|
|
16741
17004
|
for (const n of names) {
|
|
16742
17005
|
if (!n.endsWith(".json")) continue;
|
|
16743
17006
|
try {
|
|
16744
|
-
const s2 = JSON.parse(
|
|
17007
|
+
const s2 = JSON.parse(readFileSync14(join27(stateDir(), n), "utf8"));
|
|
16745
17008
|
if (typeof s2.sessionId === "string" && typeof s2.tool === "string" && enabled.has(s2.tool)) out.push({ tool: s2.tool, sessionId: s2.sessionId, state: typeof s2.state === "string" ? s2.state : "", cwd: typeof s2.cwd === "string" ? s2.cwd : "" });
|
|
16746
17009
|
} catch {
|
|
16747
17010
|
}
|
|
@@ -16775,12 +17038,12 @@ var Daemon = class {
|
|
|
16775
17038
|
}
|
|
16776
17039
|
case "deepseek_harness": {
|
|
16777
17040
|
if (!TRANSCRIPT_SID_RE.test(s2.sessionId)) return null;
|
|
16778
|
-
const p =
|
|
17041
|
+
const p = join27(deskbuddyHome(), "dsh", "transcript", `${s2.sessionId}.jsonl`);
|
|
16779
17042
|
return existsSync7(p) ? { kind: "file", path: p, format: "dsh" } : null;
|
|
16780
17043
|
}
|
|
16781
17044
|
case "opencode": {
|
|
16782
17045
|
if (!TRANSCRIPT_SID_RE.test(s2.sessionId)) return null;
|
|
16783
|
-
return snapshotSource(`opencode-snap:${s2.sessionId}`,
|
|
17046
|
+
return snapshotSource(`opencode-snap:${s2.sessionId}`, join27(deskbuddyHome(), "opencode", "transcript", `${s2.sessionId}.json`));
|
|
16784
17047
|
}
|
|
16785
17048
|
case "dumate":
|
|
16786
17049
|
return { kind: "http", key: "dumate", fetch: () => this.#dumate.transcriptMessages(s2.sessionId) };
|
|
@@ -16811,7 +17074,7 @@ var Daemon = class {
|
|
|
16811
17074
|
#summaryTranscriptOf(st) {
|
|
16812
17075
|
const f = this.#transcriptOf(st, this.#deps.now());
|
|
16813
17076
|
if (f) return f;
|
|
16814
|
-
const homes = st.tool === "workbuddy" ? [st.configDir,
|
|
17077
|
+
const homes = st.tool === "workbuddy" ? [st.configDir, dirname9(workbuddySettingsPath()), codebuddyConfigDir()] : st.tool === "qwenwork" ? [qwenworkDataHome()] : [];
|
|
16815
17078
|
for (const h of homes) {
|
|
16816
17079
|
if (!h) continue;
|
|
16817
17080
|
const p = claudeTranscriptFile(st.sessionId, st.cwd, h);
|
|
@@ -17131,6 +17394,19 @@ var Daemon = class {
|
|
|
17131
17394
|
return;
|
|
17132
17395
|
}
|
|
17133
17396
|
}
|
|
17397
|
+
if (cmd.tool === "deepseek_harness" && !sessionId) {
|
|
17398
|
+
let sup = { ok: true };
|
|
17399
|
+
try {
|
|
17400
|
+
sup = this.#deps.dshSupport();
|
|
17401
|
+
} catch {
|
|
17402
|
+
sup = { ok: true };
|
|
17403
|
+
}
|
|
17404
|
+
if (!sup.ok) {
|
|
17405
|
+
log(`\u6307\u4EE4 ${cmd.instructionId} \u4E0D\u6267\u884C\uFF1A\u7535\u8111\u4E0A\u7684 DeepSeek Harness \u7248\u672C\u592A\u65E7\uFF0C\u4E0D\u652F\u6301\u8BBE\u5907\u65B0\u5EFA\u4EFB\u52A1\uFF08${sup.why}\uFF1B\u9700\u8981 ${DSH_PKG} \u2265 ${DSH_HEADLESS_MIN_VERSION}\uFF09`);
|
|
17406
|
+
this.#report(cmd, "", "rejected", "", DSH_VERSION_UNSUPPORTED);
|
|
17407
|
+
return;
|
|
17408
|
+
}
|
|
17409
|
+
}
|
|
17134
17410
|
const runId = newRunId();
|
|
17135
17411
|
const text = isSummary(cmd) ? withSummaryMark(cmd.text, cmd.instructionId) : cmd.text;
|
|
17136
17412
|
const plan = buildSpawnPlan({ ...cmd, sessionId, text }, cwd, this.#gateTarget(runId), void 0, sessionId ? readState(sessionId)?.configDir : void 0);
|
|
@@ -17167,12 +17443,15 @@ var Daemon = class {
|
|
|
17167
17443
|
);
|
|
17168
17444
|
const writerBusy = cmd.tool === "codex" && isCodexWriterBusy(result, cmd.text);
|
|
17169
17445
|
if (writerBusy) log(`\u6307\u4EE4 ${cmd.instructionId} Codex \u4F1A\u8BDD\u6B63\u5F00\u5728\u7535\u8111\u7A97\u53E3\u91CC\uFF08\u5360\u7740\u5199\uFF09\uFF0C\u540E\u53F0\u7EED\u4E0D\u4E86`);
|
|
17446
|
+
const dshOld = cmd.tool === "deepseek_harness" && !sessionId && dshOutputUnsupported(`${result.stderr ?? ""}
|
|
17447
|
+
${result.stdout}`);
|
|
17448
|
+
if (dshOld) log(`\u6307\u4EE4 ${cmd.instructionId} \u7535\u8111\u4E0A\u7684 DeepSeek Harness \u7248\u672C\u592A\u65E7\uFF0C\u4E0D\u652F\u6301\u8BBE\u5907\u65B0\u5EFA\u4EFB\u52A1\uFF08\u4E0D\u8BA4 --profile headless\uFF09`);
|
|
17170
17449
|
this.#report(
|
|
17171
17450
|
cmd,
|
|
17172
17451
|
sessionId || result.sessionId || "",
|
|
17173
17452
|
"failed",
|
|
17174
17453
|
"headless",
|
|
17175
|
-
notLoggedIn ? AGENT_NOT_LOGGED_IN : writerBusy ? "window_open" : "exec_failed"
|
|
17454
|
+
notLoggedIn ? AGENT_NOT_LOGGED_IN : writerBusy ? "window_open" : dshOld ? DSH_VERSION_UNSUPPORTED : "exec_failed"
|
|
17176
17455
|
);
|
|
17177
17456
|
if (notLoggedIn) this.#guideLogin(cmd.tool);
|
|
17178
17457
|
}
|
|
@@ -17407,7 +17686,7 @@ async function runDaemon(deps2 = {}) {
|
|
|
17407
17686
|
}
|
|
17408
17687
|
|
|
17409
17688
|
// src/daemon/shimCheck.ts
|
|
17410
|
-
import { readFileSync as
|
|
17689
|
+
import { readFileSync as readFileSync15 } from "fs";
|
|
17411
17690
|
var SHIM_CHECK_FIRST_DELAY_MS = 60 * 1e3;
|
|
17412
17691
|
var SHIM_CHECK_INTERVAL_MS = 60 * 60 * 1e3;
|
|
17413
17692
|
var TOOL = "claude_code";
|
|
@@ -17503,7 +17782,7 @@ function defaultShimCheckDeps(log2, idle, inj = {}) {
|
|
|
17503
17782
|
idle,
|
|
17504
17783
|
shimInstalled: () => {
|
|
17505
17784
|
try {
|
|
17506
|
-
return
|
|
17785
|
+
return readFileSync15(shimFile(probe.binDir, command, "win32"), "utf8").includes(SHIM_MARKER);
|
|
17507
17786
|
} catch {
|
|
17508
17787
|
return false;
|
|
17509
17788
|
}
|
|
@@ -17712,7 +17991,7 @@ async function runDisable(tools, opts = {}) {
|
|
|
17712
17991
|
|
|
17713
17992
|
// src/commands/install.ts
|
|
17714
17993
|
import { mkdirSync as mkdirSync13, rmSync as rmSync12, writeFileSync as writeFileSync13 } from "fs";
|
|
17715
|
-
import { join as
|
|
17994
|
+
import { join as join28 } from "path";
|
|
17716
17995
|
|
|
17717
17996
|
// src/commands/setup.ts
|
|
17718
17997
|
import qrcode from "qrcode-terminal";
|
|
@@ -17929,7 +18208,7 @@ function inSandbox(env) {
|
|
|
17929
18208
|
}
|
|
17930
18209
|
function precheckWritable(dirs) {
|
|
17931
18210
|
for (const dir2 of dirs) {
|
|
17932
|
-
const probe =
|
|
18211
|
+
const probe = join28(dir2, `.deskbuddy-probe-${process.pid}`);
|
|
17933
18212
|
try {
|
|
17934
18213
|
mkdirSync13(dir2, { recursive: true });
|
|
17935
18214
|
writeFileSync13(probe, "");
|
|
@@ -18339,11 +18618,12 @@ async function runAutoSwitch(opts) {
|
|
|
18339
18618
|
// src/wrap/run.ts
|
|
18340
18619
|
import { randomBytes as randomBytes10 } from "crypto";
|
|
18341
18620
|
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync15, statSync as statSync16, truncateSync as truncateSync3 } from "fs";
|
|
18342
|
-
import { join as
|
|
18621
|
+
import { join as join31 } from "path";
|
|
18343
18622
|
import { StringDecoder as StringDecoder2 } from "string_decoder";
|
|
18344
18623
|
|
|
18345
18624
|
// src/wrap/injector.ts
|
|
18346
18625
|
var SEEN_MAX = 200;
|
|
18626
|
+
var PERMISSION_PENDING = "permission_pending";
|
|
18347
18627
|
var WINDOW_UNRECOGNIZED = "window_unrecognized";
|
|
18348
18628
|
var QUIET_MS = 1500;
|
|
18349
18629
|
var STARTUP_QUIET_MS = 3e3;
|
|
@@ -18509,7 +18789,8 @@ var Injector = class {
|
|
|
18509
18789
|
return;
|
|
18510
18790
|
}
|
|
18511
18791
|
if (job.expireAt > 0 && this.#d.now() > job.expireAt) {
|
|
18512
|
-
this.#
|
|
18792
|
+
const perm = this.#lastWhy.split(",").includes("permission");
|
|
18793
|
+
this.#final(job, { status: "rejected", mode: "window", reason: perm ? PERMISSION_PENDING : "expired" });
|
|
18513
18794
|
return;
|
|
18514
18795
|
}
|
|
18515
18796
|
if (!this.#owns(job.sessionId)) {
|
|
@@ -18684,9 +18965,9 @@ var WithdrawWatch = class {
|
|
|
18684
18965
|
|
|
18685
18966
|
// src/wrap/passthrough.ts
|
|
18686
18967
|
import { spawn as spawn3 } from "child_process";
|
|
18687
|
-
import { realpathSync as
|
|
18968
|
+
import { realpathSync as realpathSync6 } from "fs";
|
|
18688
18969
|
import { constants } from "os";
|
|
18689
|
-
import { dirname as
|
|
18970
|
+
import { dirname as dirname10, resolve as resolve7 } from "path";
|
|
18690
18971
|
var CLAUDE_SUBCOMMANDS = /* @__PURE__ */ new Set([
|
|
18691
18972
|
"agents",
|
|
18692
18973
|
"attach",
|
|
@@ -18742,7 +19023,7 @@ function norm(p, win) {
|
|
|
18742
19023
|
}
|
|
18743
19024
|
function real(p) {
|
|
18744
19025
|
try {
|
|
18745
|
-
return
|
|
19026
|
+
return realpathSync6(p);
|
|
18746
19027
|
} catch {
|
|
18747
19028
|
return p;
|
|
18748
19029
|
}
|
|
@@ -18750,7 +19031,7 @@ function real(p) {
|
|
|
18750
19031
|
function findReal(tool, d = defaultLocateDeps(), skip = shimDir()) {
|
|
18751
19032
|
const win = (d.platform ?? process.platform) === "win32";
|
|
18752
19033
|
const skipKeys = /* @__PURE__ */ new Set([norm(skip, win), norm(real(skip), win)]);
|
|
18753
|
-
const inSkip = (file) => skipKeys.has(norm(
|
|
19034
|
+
const inSkip = (file) => skipKeys.has(norm(dirname10(file), win)) || skipKeys.has(norm(dirname10(real(file)), win));
|
|
18754
19035
|
const dd = { ...d, skipDirs: [...d.skipDirs ?? [], skip] };
|
|
18755
19036
|
const name = SHIM_COMMANDS[tool];
|
|
18756
19037
|
if (!name) {
|
|
@@ -18834,10 +19115,10 @@ function runDirect(real2, args, env = process.env) {
|
|
|
18834
19115
|
|
|
18835
19116
|
// src/wrap/codexLaunch.ts
|
|
18836
19117
|
import { execFileSync as execFileSync4, spawn as spawn4 } from "child_process";
|
|
18837
|
-
import { closeSync as closeSync9, mkdirSync as mkdirSync14, openSync as openSync9, readdirSync as readdirSync12, readFileSync as
|
|
19118
|
+
import { closeSync as closeSync9, mkdirSync as mkdirSync14, openSync as openSync9, readdirSync as readdirSync12, readFileSync as readFileSync16, rmSync as rmSync14, statSync as statSync15, truncateSync as truncateSync2, writeFileSync as writeFileSync14, renameSync as renameSync10 } from "fs";
|
|
18838
19119
|
import { request as request2 } from "http";
|
|
18839
19120
|
import { createServer as createServer5 } from "net";
|
|
18840
|
-
import { join as
|
|
19121
|
+
import { join as join29 } from "path";
|
|
18841
19122
|
var TAKEOVER_VALUE_OPTS = /* @__PURE__ */ new Set(["-c", "--config", "-m", "--model", "-s", "--sandbox", "-a", "--ask-for-approval", "-C", "--cd", "--enable", "--disable"]);
|
|
18842
19123
|
var SHORT_VALUE_OPTS = /* @__PURE__ */ new Set(["-c", "-m", "-s", "-a", "-C"]);
|
|
18843
19124
|
var TAKEOVER_FLAGS = /* @__PURE__ */ new Set(["--search", "--no-alt-screen", "--dangerously-bypass-approvals-and-sandbox"]);
|
|
@@ -19006,10 +19287,10 @@ async function runCodexWindow(real2, args, d) {
|
|
|
19006
19287
|
}
|
|
19007
19288
|
var MAX_LOG_BYTES2 = 1024 * 1024;
|
|
19008
19289
|
function appServerLogPath() {
|
|
19009
|
-
return
|
|
19290
|
+
return join29(deskbuddyHome(), "codex-app-server.log");
|
|
19010
19291
|
}
|
|
19011
19292
|
function windowsDir2() {
|
|
19012
|
-
return
|
|
19293
|
+
return join29(deskbuddyHome(), "codex-windows");
|
|
19013
19294
|
}
|
|
19014
19295
|
function pidAlive5(pid) {
|
|
19015
19296
|
try {
|
|
@@ -19022,7 +19303,7 @@ function pidAlive5(pid) {
|
|
|
19022
19303
|
function daemonAlive(pidFile = pidFilePath(), args = processArgs) {
|
|
19023
19304
|
let pid = 0;
|
|
19024
19305
|
try {
|
|
19025
|
-
pid = Number(
|
|
19306
|
+
pid = Number(readFileSync16(pidFile, "utf8").trim());
|
|
19026
19307
|
} catch {
|
|
19027
19308
|
return false;
|
|
19028
19309
|
}
|
|
@@ -19099,7 +19380,7 @@ function killOwnServer(pid, url, args = freshArgs, kill = (p) => killServer(p))
|
|
|
19099
19380
|
if (a && isAppServerArgs(a, url)) kill(pid);
|
|
19100
19381
|
}
|
|
19101
19382
|
function recordPath(rec) {
|
|
19102
|
-
return
|
|
19383
|
+
return join29(windowsDir2(), `${rec.server}.json`);
|
|
19103
19384
|
}
|
|
19104
19385
|
function writeRecord(rec) {
|
|
19105
19386
|
try {
|
|
@@ -19124,10 +19405,10 @@ function reapWindows(dir2 = windowsDir2(), alive = pidAlive5, args = freshArgs,
|
|
|
19124
19405
|
return;
|
|
19125
19406
|
}
|
|
19126
19407
|
for (const n of names) {
|
|
19127
|
-
const p =
|
|
19408
|
+
const p = join29(dir2, n);
|
|
19128
19409
|
let rec;
|
|
19129
19410
|
try {
|
|
19130
|
-
rec = JSON.parse(
|
|
19411
|
+
rec = JSON.parse(readFileSync16(p, "utf8"));
|
|
19131
19412
|
} catch {
|
|
19132
19413
|
rmSync14(p, { force: true });
|
|
19133
19414
|
continue;
|
|
@@ -19147,7 +19428,7 @@ function reapWindows(dir2 = windowsDir2(), alive = pidAlive5, args = freshArgs,
|
|
|
19147
19428
|
function launchLog(line) {
|
|
19148
19429
|
try {
|
|
19149
19430
|
mkdirSync14(deskbuddyHome(), { recursive: true });
|
|
19150
|
-
writeFileSync14(
|
|
19431
|
+
writeFileSync14(join29(deskbuddyHome(), "wrap.log"), `${(/* @__PURE__ */ new Date()).toISOString()} [codex ${process.pid}] ${line}
|
|
19151
19432
|
`, { flag: "a" });
|
|
19152
19433
|
} catch {
|
|
19153
19434
|
}
|
|
@@ -19172,7 +19453,7 @@ function defaultCodexWindowDeps(base) {
|
|
|
19172
19453
|
// src/wrap/promptLaunch.ts
|
|
19173
19454
|
import { randomBytes as randomBytes8, randomUUID as randomUUID3 } from "crypto";
|
|
19174
19455
|
import { homedir as homedir10 } from "os";
|
|
19175
|
-
import { join as
|
|
19456
|
+
import { join as join30 } from "path";
|
|
19176
19457
|
var FIRST_LINE_WAIT_MS2 = 2 * 60 * 1e3;
|
|
19177
19458
|
function promptArgs(text, tool = "") {
|
|
19178
19459
|
if (!text) return [];
|
|
@@ -19182,7 +19463,7 @@ function promptArgs(text, tool = "") {
|
|
|
19182
19463
|
function promptEnv(tool, env, launcherPid = process.pid, answerWindowId = "") {
|
|
19183
19464
|
const out = { ...env };
|
|
19184
19465
|
if (tool === "workbuddy") {
|
|
19185
|
-
if (!out.CODEBUDDY_CONFIG_DIR) out.CODEBUDDY_CONFIG_DIR =
|
|
19466
|
+
if (!out.CODEBUDDY_CONFIG_DIR) out.CODEBUDDY_CONFIG_DIR = join30(homedir10(), ".workbuddy");
|
|
19186
19467
|
out.DESKBUDDY_LAUNCHER_PID = String(launcherPid);
|
|
19187
19468
|
out.DESKBUDDY_LAUNCHED_TOOL = tool;
|
|
19188
19469
|
if (answerWindowId) out.DESKBUDDY_LAUNCHED_WINDOW = answerWindowId;
|
|
@@ -19470,7 +19751,7 @@ async function applyAnswer(req, io, trust) {
|
|
|
19470
19751
|
} else if (a.kind === "trust" && a.prompt !== "hooks" && trust?.widens) r = "not_waiting";
|
|
19471
19752
|
else if (a.kind === "trust") r = await answerTrust(keys, trust?.tool ?? "", a.decision, trust?.forms ?? [], a.prompt ?? "trust");
|
|
19472
19753
|
else if (a.kind === "permission") r = await answerPermission(keys, a.toolName, a.fingerprint, a.decision);
|
|
19473
|
-
else r = await answerQuestions(keys, a.questions, a.selections);
|
|
19754
|
+
else r = await answerQuestions(keys, a.questions, a.selections, a.others);
|
|
19474
19755
|
} catch {
|
|
19475
19756
|
r = "partial";
|
|
19476
19757
|
}
|
|
@@ -19721,7 +20002,7 @@ async function runAnswerWindow(tool, real2, args, env, windowId, d) {
|
|
|
19721
20002
|
}
|
|
19722
20003
|
|
|
19723
20004
|
// src/wrap/launchRegister.ts
|
|
19724
|
-
import { dirname as
|
|
20005
|
+
import { dirname as dirname11 } from "path";
|
|
19725
20006
|
async function launchTranscriptReady(tool, sessionId) {
|
|
19726
20007
|
try {
|
|
19727
20008
|
if (tool === "qoder_cn") {
|
|
@@ -19729,7 +20010,7 @@ async function launchTranscriptReady(tool, sessionId) {
|
|
|
19729
20010
|
return !!p && (await transcriptInfo(p)).title !== "";
|
|
19730
20011
|
}
|
|
19731
20012
|
if (tool === "workbuddy") {
|
|
19732
|
-
const p = findWbTranscript(
|
|
20013
|
+
const p = findWbTranscript(dirname11(workbuddySettingsPath()), sessionId);
|
|
19733
20014
|
return !!p && wbTranscriptInfo(p).title !== "";
|
|
19734
20015
|
}
|
|
19735
20016
|
return false;
|
|
@@ -19737,8 +20018,8 @@ async function launchTranscriptReady(tool, sessionId) {
|
|
|
19737
20018
|
return false;
|
|
19738
20019
|
}
|
|
19739
20020
|
}
|
|
19740
|
-
var
|
|
19741
|
-
async function launchRegister(tool, sessionId, cwd, firstLine, final, d =
|
|
20021
|
+
var defaultDeps3 = { qoder: (j) => syncQoderApp(j), workbuddy: (j) => registerWorkbuddySession(j) };
|
|
20022
|
+
async function launchRegister(tool, sessionId, cwd, firstLine, final, d = defaultDeps3) {
|
|
19742
20023
|
if (tool === "workbuddy") return d.workbuddy({ sessionId, cwd, fallbackTitle: firstLine ?? "" });
|
|
19743
20024
|
if (tool !== "qoder_cn") return "skip tool";
|
|
19744
20025
|
const r = await d.qoder({ tool, kind: "register", sessionId, cwd, fallbackTitle: firstLine ?? "" });
|
|
@@ -19766,7 +20047,7 @@ function childEnv(src, windowId, takeover = true) {
|
|
|
19766
20047
|
}
|
|
19767
20048
|
function wrapLog(line) {
|
|
19768
20049
|
try {
|
|
19769
|
-
const p =
|
|
20050
|
+
const p = join31(deskbuddyHome(), "wrap.log");
|
|
19770
20051
|
mkdirSync15(deskbuddyHome(), { recursive: true });
|
|
19771
20052
|
try {
|
|
19772
20053
|
if (statSync16(p).size > MAX_LOG_BYTES3) truncateSync3(p, 0);
|
package/hook/hook-debug.log
CHANGED
|
@@ -308,3 +308,57 @@
|
|
|
308
308
|
2026-10-12T06:14:16.558Z [opencode] opencode 版本 读不出:带说明的拒绝不走新路由
|
|
309
309
|
2026-10-12T06:14:16.558Z [opencode] opencode 版本不确定支持带说明的拒绝,设备上的反馈没有带给模型
|
|
310
310
|
2026-10-12T06:14:19.410Z [opencode] 后台任务里的提问 que_r2 没法在设备上回答(后台任务不能提问,请在电脑上继续),已拒绝
|
|
311
|
+
2026-10-12T07:00:56.655Z [opencode] 回填选择题失败:/question/{requestID}/reply status=404
|
|
312
|
+
2026-10-12T07:01:01.581Z [opencode] opencode 版本 1.4.3:带说明的拒绝不走新路由
|
|
313
|
+
2026-10-12T07:01:01.581Z [opencode] opencode 版本不确定支持带说明的拒绝,设备上的反馈没有带给模型
|
|
314
|
+
2026-10-12T07:01:01.681Z [opencode] opencode 版本 读不出:带说明的拒绝不走新路由
|
|
315
|
+
2026-10-12T07:01:01.681Z [opencode] opencode 版本不确定支持带说明的拒绝,设备上的反馈没有带给模型
|
|
316
|
+
2026-10-12T07:01:04.078Z [opencode] 后台任务里的提问 que_r2 没法在设备上回答(后台任务不能提问,请在电脑上继续),已拒绝
|
|
317
|
+
2026-10-12T07:36:12.685Z [opencode] 回填选择题失败:/question/{requestID}/reply status=404
|
|
318
|
+
2026-10-12T07:36:17.637Z [opencode] opencode 版本 1.4.3:带说明的拒绝不走新路由
|
|
319
|
+
2026-10-12T07:36:17.637Z [opencode] opencode 版本不确定支持带说明的拒绝,设备上的反馈没有带给模型
|
|
320
|
+
2026-10-12T07:36:17.734Z [opencode] opencode 版本 读不出:带说明的拒绝不走新路由
|
|
321
|
+
2026-10-12T07:36:17.734Z [opencode] opencode 版本不确定支持带说明的拒绝,设备上的反馈没有带给模型
|
|
322
|
+
2026-10-12T07:36:20.164Z [opencode] 后台任务里的提问 que_r2 没法在设备上回答(后台任务不能提问,请在电脑上继续),已拒绝
|
|
323
|
+
2026-10-12T07:38:26.140Z [opencode] 回填选择题失败:/question/{requestID}/reply status=404
|
|
324
|
+
2026-10-12T07:38:31.306Z [opencode] opencode 版本 1.4.3:带说明的拒绝不走新路由
|
|
325
|
+
2026-10-12T07:38:31.306Z [opencode] opencode 版本不确定支持带说明的拒绝,设备上的反馈没有带给模型
|
|
326
|
+
2026-10-12T07:38:31.422Z [opencode] opencode 版本 读不出:带说明的拒绝不走新路由
|
|
327
|
+
2026-10-12T07:38:31.422Z [opencode] opencode 版本不确定支持带说明的拒绝,设备上的反馈没有带给模型
|
|
328
|
+
2026-10-12T07:38:34.204Z [opencode] 后台任务里的提问 que_r2 没法在设备上回答(后台任务不能提问,请在电脑上继续),已拒绝
|
|
329
|
+
2026-10-12T07:45:21.768Z [opencode] 回填选择题失败:/question/{requestID}/reply status=404
|
|
330
|
+
2026-10-12T07:45:26.698Z [opencode] opencode 版本 1.4.3:带说明的拒绝不走新路由
|
|
331
|
+
2026-10-12T07:45:26.699Z [opencode] opencode 版本不确定支持带说明的拒绝,设备上的反馈没有带给模型
|
|
332
|
+
2026-10-12T07:45:26.806Z [opencode] opencode 版本 读不出:带说明的拒绝不走新路由
|
|
333
|
+
2026-10-12T07:45:26.806Z [opencode] opencode 版本不确定支持带说明的拒绝,设备上的反馈没有带给模型
|
|
334
|
+
2026-10-12T07:45:29.059Z [opencode] 后台任务里的提问 que_r2 没法在设备上回答(后台任务不能提问,请在电脑上继续),已拒绝
|
|
335
|
+
2026-10-12T07:48:52.563Z [opencode] 回填选择题失败:/question/{requestID}/reply status=404
|
|
336
|
+
2026-10-12T07:48:57.566Z [opencode] opencode 版本 1.4.3:带说明的拒绝不走新路由
|
|
337
|
+
2026-10-12T07:48:57.566Z [opencode] opencode 版本不确定支持带说明的拒绝,设备上的反馈没有带给模型
|
|
338
|
+
2026-10-12T07:48:57.673Z [opencode] opencode 版本 读不出:带说明的拒绝不走新路由
|
|
339
|
+
2026-10-12T07:48:57.673Z [opencode] opencode 版本不确定支持带说明的拒绝,设备上的反馈没有带给模型
|
|
340
|
+
2026-10-12T07:49:00.208Z [opencode] 后台任务里的提问 que_r2 没法在设备上回答(后台任务不能提问,请在电脑上继续),已拒绝
|
|
341
|
+
2026-10-12T08:43:33.911Z [opencode] 回填选择题失败:/question/{requestID}/reply status=404
|
|
342
|
+
2026-10-12T08:43:38.975Z [opencode] opencode 版本 1.4.3:带说明的拒绝不走新路由
|
|
343
|
+
2026-10-12T08:43:38.975Z [opencode] opencode 版本不确定支持带说明的拒绝,设备上的反馈没有带给模型
|
|
344
|
+
2026-10-12T08:43:39.078Z [opencode] opencode 版本 读不出:带说明的拒绝不走新路由
|
|
345
|
+
2026-10-12T08:43:39.078Z [opencode] opencode 版本不确定支持带说明的拒绝,设备上的反馈没有带给模型
|
|
346
|
+
2026-10-12T08:43:41.400Z [opencode] 后台任务里的提问 que_r2 没法在设备上回答(后台任务不能提问,请在电脑上继续),已拒绝
|
|
347
|
+
2026-10-12T08:45:36.004Z [opencode] 回填选择题失败:/question/{requestID}/reply status=404
|
|
348
|
+
2026-10-12T08:45:40.986Z [opencode] opencode 版本 1.4.3:带说明的拒绝不走新路由
|
|
349
|
+
2026-10-12T08:45:40.986Z [opencode] opencode 版本不确定支持带说明的拒绝,设备上的反馈没有带给模型
|
|
350
|
+
2026-10-12T08:45:41.084Z [opencode] opencode 版本 读不出:带说明的拒绝不走新路由
|
|
351
|
+
2026-10-12T08:45:41.084Z [opencode] opencode 版本不确定支持带说明的拒绝,设备上的反馈没有带给模型
|
|
352
|
+
2026-10-12T08:45:43.292Z [opencode] 后台任务里的提问 que_r2 没法在设备上回答(后台任务不能提问,请在电脑上继续),已拒绝
|
|
353
|
+
2026-10-12T08:51:55.878Z [opencode] 回填选择题失败:/question/{requestID}/reply status=404
|
|
354
|
+
2026-10-12T08:52:01.359Z [opencode] opencode 版本 1.4.3:带说明的拒绝不走新路由
|
|
355
|
+
2026-10-12T08:52:01.360Z [opencode] opencode 版本不确定支持带说明的拒绝,设备上的反馈没有带给模型
|
|
356
|
+
2026-10-12T08:52:01.517Z [opencode] opencode 版本 读不出:带说明的拒绝不走新路由
|
|
357
|
+
2026-10-12T08:52:01.517Z [opencode] opencode 版本不确定支持带说明的拒绝,设备上的反馈没有带给模型
|
|
358
|
+
2026-10-12T08:52:04.661Z [opencode] 后台任务里的提问 que_r2 没法在设备上回答(后台任务不能提问,请在电脑上继续),已拒绝
|
|
359
|
+
2026-10-12T09:01:07.164Z [opencode] 回填选择题失败:/question/{requestID}/reply status=404
|
|
360
|
+
2026-10-12T09:01:12.193Z [opencode] opencode 版本 1.4.3:带说明的拒绝不走新路由
|
|
361
|
+
2026-10-12T09:01:12.194Z [opencode] opencode 版本不确定支持带说明的拒绝,设备上的反馈没有带给模型
|
|
362
|
+
2026-10-12T09:01:12.293Z [opencode] opencode 版本 读不出:带说明的拒绝不走新路由
|
|
363
|
+
2026-10-12T09:01:12.293Z [opencode] opencode 版本不确定支持带说明的拒绝,设备上的反馈没有带给模型
|
|
364
|
+
2026-10-12T09:01:14.613Z [opencode] 后台任务里的提问 que_r2 没法在设备上回答(后台任务不能提问,请在电脑上继续),已拒绝
|