deskbuddy 0.2.0-beta.32 → 0.2.0-beta.34

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.
@@ -148,6 +148,7 @@ function loadConfig() {
148
148
  approvalPolicy: parsed.approvalPolicy === "all" ? "all" : parsed.approvalPolicy === "commands" ? "commands" : void 0,
149
149
  codexAppServer: typeof parsed.codexAppServer === "string" ? parsed.codexAppServer : void 0,
150
150
  autoUpdate: typeof parsed.autoUpdate === "boolean" ? parsed.autoUpdate : void 0,
151
+ transcript: parsed.transcript === false ? false : void 0,
151
152
  disabledTools: Array.isArray(parsed.disabledTools) ? parsed.disabledTools.filter((t) => typeof t === "string") : void 0,
152
153
  workbuddySetup: parseWorkbuddySetup(parsed.workbuddySetup),
153
154
  workbuddyAppApproval: typeof parsed.workbuddyAppApproval === "boolean" ? parsed.workbuddyAppApproval : void 0,
@@ -161,6 +162,7 @@ function loadConfig() {
161
162
  dumateCdpPort: portOrUndefined(parsed.dumateCdpPort),
162
163
  dumateShortcuts: typeof parsed.dumateShortcuts === "boolean" ? parsed.dumateShortcuts : void 0,
163
164
  qoderShortcuts: typeof parsed.qoderShortcuts === "boolean" ? parsed.qoderShortcuts : void 0,
165
+ qoderLaunchPort: typeof parsed.qoderLaunchPort === "boolean" ? parsed.qoderLaunchPort : void 0,
164
166
  cozeApp: typeof parsed.cozeApp === "boolean" ? parsed.cozeApp : void 0,
165
167
  cozeCdpPort: portOrUndefined(parsed.cozeCdpPort)
166
168
  };
@@ -1022,6 +1024,8 @@ var SERVICES = {
1022
1024
  var DIRS_SERVICE = "com.shifeng.api.service.api.v2.deskbuddy.deskbuddyclientdirsreportapi";
1023
1025
  var INSTALL_REDEEM_SERVICE = "com.shifeng.api.service.api.v2.deskbuddy.deskbuddyinstallredeemapi";
1024
1026
  var CMD_RESULT_SERVICE = "com.shifeng.api.service.api.v2.deskbuddy.deskbuddycommandresultapi";
1027
+ var TRANSCRIPT_SERVICE = "com.shifeng.api.service.api.v2.deskbuddy.deskbuddytranscriptappendapi";
1028
+ var CODE_NOT_SUPPORT = "5001";
1025
1029
  var COMMAND_OUTPUT_MAX = 8e3;
1026
1030
  var APPROVAL_SERVICES = {
1027
1031
  create: "com.shifeng.api.service.api.v2.deskbuddy.deskbuddyapprovalcreateapi",
@@ -1167,7 +1171,8 @@ var api = {
1167
1171
  dirsReport: (payload) => call(DIRS_SERVICE, payload),
1168
1172
  installRedeem: (installCode, clientId, hostName) => call(INSTALL_REDEEM_SERVICE, { installCode, clientId, hostName, ...machineInfo() }),
1169
1173
  // 2 秒超时、失败不重试(spec §4.1):回报丢了只是设备少一句提示,任务状态仍由会话快照负责
1170
- commandResult: (payload, timeoutMs = 2e3) => call(CMD_RESULT_SERVICE, payload, timeoutMs)
1174
+ commandResult: (payload, timeoutMs = 2e3) => call(CMD_RESULT_SERVICE, payload, timeoutMs),
1175
+ transcriptAppend: (payload, timeoutMs = 15e3) => call(TRANSCRIPT_SERVICE, payload, timeoutMs)
1171
1176
  };
1172
1177
 
1173
1178
  // src/core/registry.ts
@@ -2566,8 +2571,11 @@ function renderAmendmentQuoted(v) {
2566
2571
  if (!Array.isArray(v) || v.length === 0 || v.some((x) => typeof x !== "string" || x === "")) return null;
2567
2572
  const out = [];
2568
2573
  for (const x of v) {
2569
- if (/["\u0000-\u001f\u007f-\u009f​-‏‪-‮⁦-⁩]/.test(x)) return null;
2570
- out.push(/^[A-Za-z0-9_@%+=,./-]+$/.test(x) ? x : `"${x}"`);
2574
+ if (/[\u0000-\u001f\u007f-\u009f​-‏‪-‮⁦-⁩]/.test(x)) return null;
2575
+ if (/^[A-Za-z0-9_@%+=,./-]+$/.test(x)) out.push(x);
2576
+ else if (!x.includes('"')) out.push(`"${x}"`);
2577
+ else if (!x.includes("'")) out.push(`'${x}'`);
2578
+ else out.push(`"${x.replace(/"/g, '\\"')}"`);
2571
2579
  }
2572
2580
  return out.join(" ");
2573
2581
  }
@@ -5997,6 +6005,10 @@ var CdpKeeper = class {
5997
6005
  #hung = new HungTracker();
5998
6006
  /** 这一段卡死里「暂不重启」的原因记过哪条(同一条只记一次) */
5999
6007
  #hungNote = "";
6008
+ /** 这一段端口不通里「不重启」的原因记过哪条(同一条只记一次;端口通了 / 转成卡死时清掉。258:原先这些分支一行不记) */
6009
+ #downNote = "";
6010
+ /** 最近一轮端口不通的细分(日志 / 设备任务的等待原因用):fail = 没在监听或回包不是 WorkBuddy;timeout = 超时且监听者不是本机回环的 WorkBuddy */
6011
+ #downWhy = "";
6000
6012
  constructor(deps) {
6001
6013
  this.#d = deps;
6002
6014
  }
@@ -6137,6 +6149,16 @@ var CdpKeeper = class {
6137
6149
  this.#hung.clear();
6138
6150
  this.#hungNote = "";
6139
6151
  }
6152
+ /** 最近一轮端口不通的细分(没不通过返回 '') */
6153
+ get downWhy() {
6154
+ return this.#downWhy;
6155
+ }
6156
+ /** 端口不通期间不重启的原因:同一段里同一条只记一次 */
6157
+ #noteDown(why) {
6158
+ if (this.#downNote === why) return;
6159
+ this.#downNote = why;
6160
+ this.#d.log(`WorkBuddy \u8C03\u8BD5\u7AEF\u53E3 ${this.#d.port()} \u4E0D\u901A\uFF0C${why}`);
6161
+ }
6140
6162
  /** 卡死期间暂不重启的原因:同一段卡死里同一条只记一次 */
6141
6163
  #noteHung(why) {
6142
6164
  if (this.#hungNote === why) return;
@@ -6182,6 +6204,8 @@ var CdpKeeper = class {
6182
6204
  if (this.#hung.since) this.#d.log(`WorkBuddy \u8C03\u8BD5\u7AEF\u53E3 ${this.#d.port()} \u6062\u590D\u54CD\u5E94`);
6183
6205
  this.#markHung(false, 0);
6184
6206
  this.#downRounds = 0;
6207
+ this.#downNote = "";
6208
+ this.#downWhy = "";
6185
6209
  const ok = await this.ownerOk().catch(() => false);
6186
6210
  if (ok) await this.#rememberExe().catch(() => {
6187
6211
  });
@@ -6191,6 +6215,8 @@ var CdpKeeper = class {
6191
6215
  const now = this.#now();
6192
6216
  this.#markHung(true, now);
6193
6217
  this.#downRounds = 0;
6218
+ this.#downNote = "";
6219
+ this.#downWhy = "";
6194
6220
  if (this.#hung.confirmed(now)) {
6195
6221
  await this.#maybeRestart(true).catch((e) => this.#d.log(`WorkBuddy \u8C03\u8BD5\u7AEF\u53E3\uFF1A\u91CD\u542F\u51FA\u9519 ${e?.message ?? e}`));
6196
6222
  }
@@ -6198,6 +6224,7 @@ var CdpKeeper = class {
6198
6224
  }
6199
6225
  this.#markHung(false, 0);
6200
6226
  this.#downRounds++;
6227
+ this.#downWhy = pr === "timeout" ? "timeout" : "fail";
6201
6228
  await this.#maybeRestart().catch((e) => this.#d.log(`WorkBuddy \u8C03\u8BD5\u7AEF\u53E3\uFF1A\u91CD\u542F\u51FA\u9519 ${e?.message ?? e}`));
6202
6229
  return "down";
6203
6230
  }
@@ -6218,18 +6245,27 @@ var CdpKeeper = class {
6218
6245
  }
6219
6246
  if (this.#restarts >= RESTART_DAILY_MAX) {
6220
6247
  if (hung) this.#noteHung(`\u4ECA\u5929\u5DF2\u91CD\u542F ${RESTART_DAILY_MAX} \u6B21\uFF0C\u4E0D\u518D\u91CD\u542F\uFF1B\u8BF7\u5728\u7535\u8111\u4E0A\u91CD\u5F00 WorkBuddy`);
6248
+ else this.#noteDown(`\u4ECA\u5929\u5DF2\u91CD\u542F ${RESTART_DAILY_MAX} \u6B21\uFF0C\u4E0D\u518D\u5E26\u7AEF\u53E3\u91CD\u542F`);
6249
+ return;
6250
+ }
6251
+ if (this.#lastRestart && now - this.#lastRestart < RESTART_GAP_MS) {
6252
+ if (!hung) this.#noteDown("30 \u5206\u949F\u5185\u521A\u91CD\u542F\u8FC7\uFF0C\u5148\u4E0D\u518D\u91CD\u542F");
6221
6253
  return;
6222
6254
  }
6223
- if (this.#lastRestart && now - this.#lastRestart < RESTART_GAP_MS) return;
6224
6255
  if (this.#lastWakeLaunch && now - this.#lastWakeLaunch < WAKE_LAUNCH_GAP_MS) return;
6225
6256
  const running = await (this.#d.appRunning ?? defaultAppRunning)();
6226
- if (!running) return;
6257
+ if (!running) {
6258
+ if (!hung) this.#noteDown("WorkBuddy App \u6CA1\u5728\u8FD0\u884C");
6259
+ return;
6260
+ }
6227
6261
  if (this.#isBusy(now)) {
6228
6262
  if (hung) this.#noteHung("\u4E14\u6709\u4EFB\u52A1\u5728\u8DD1 / \u6709\u7B49\u8BBE\u5907\u7684\u5361\uFF0C\u4E0D\u91CD\u542F\uFF1B\u8BF7\u5728\u7535\u8111\u4E0A\u91CD\u5F00 WorkBuddy");
6263
+ else this.#noteDown("App \u5728\u8FD0\u884C\u4F46\u6CA1\u5E26\u8C03\u8BD5\u7AEF\u53E3\uFF08\u53EF\u80FD\u662F\u8BBE\u7F6E\u73AF\u5883\u53D8\u91CF\u4E4B\u524D\u6253\u5F00\u7684\uFF09\uFF0C\u4E14\u6709\u4EFB\u52A1\u5728\u8DD1 / \u6709\u7B49\u8BBE\u5907\u7684\u5361\uFF0C\u4E0D\u91CD\u542F");
6229
6264
  return;
6230
6265
  }
6231
6266
  if (!await this.#userAway()) {
6232
6267
  if (hung) this.#noteHung("\u7528\u6237\u5728\u7535\u8111\u524D\uFF0C\u4E0D\u6253\u65AD\uFF1B\u8BF7\u5728\u7535\u8111\u4E0A\u91CD\u5F00 WorkBuddy");
6268
+ else this.#noteDown("App \u5728\u8FD0\u884C\u4F46\u6CA1\u5E26\u8C03\u8BD5\u7AEF\u53E3\uFF08\u53EF\u80FD\u662F\u8BBE\u7F6E\u73AF\u5883\u53D8\u91CF\u4E4B\u524D\u6253\u5F00\u7684\uFF09\uFF0C\u7528\u6237\u5728\u7535\u8111\u524D\uFF0C\u4E0D\u91CD\u542F");
6233
6269
  return;
6234
6270
  }
6235
6271
  await this.#doRestart(true, hung);
@@ -7703,6 +7739,17 @@ var DumateWatch = class {
7703
7739
  * 任务总结的读回(spec 2026-10-11 summary-all-tools):GET /session/:id/message + /session/status,按标记认本轮(messagesVerdict)。
7704
7740
  * 连不上 / 读不出 → 等(总超时由调用方判);不唤起 App
7705
7741
  */
7742
+ /**
7743
+ * 会话完整对话(spec 2026-10-11 transcript-sync §3):GET /session/:id/message 全量(消息只追加,序号稳定)。
7744
+ * 连不上 / 读不出 → null(游标不动,下次可读再补);不唤起 App
7745
+ */
7746
+ async transcriptMessages(sessionId) {
7747
+ const t = this.#target ?? this.#discover(false);
7748
+ if (!t) return null;
7749
+ const dir2 = this.#sessionDir.get(sessionId) ?? "";
7750
+ const r = await this.#http(t)(t, { method: "GET", path: `/session/${encodeURIComponent(sessionId)}/message`, ...dir2 ? { directory: dir2 } : {} });
7751
+ return r.status === 200 && Array.isArray(r.body) ? r.body : null;
7752
+ }
7706
7753
  async summaryCheck(sessionId, instructionId) {
7707
7754
  const wait = { kind: "wait" };
7708
7755
  const t = this.#target ?? this.#discover(false);
@@ -8262,6 +8309,10 @@ var RESTART_DAILY_MAX2 = 3;
8262
8309
  var BUSY_WINDOW_MS2 = 30 * 60 * 1e3;
8263
8310
  var QUIT_WAIT_MS2 = 20 * 1e3;
8264
8311
  var USER_IDLE_MS = 5 * 60 * 1e3;
8312
+ var LAUNCH_FRESH_MS = 10 * 1e3;
8313
+ var LAUNCH_PORT_WINDOW_MS = 10 * 60 * 1e3;
8314
+ var LAUNCH_PORT_MAX = 2;
8315
+ var LAUNCH_SEEN_MAX = 32;
8265
8316
  function winBrandMainProc(procs, exe) {
8266
8317
  const want = exe.toLowerCase();
8267
8318
  for (const p of procs) {
@@ -8313,6 +8364,24 @@ function parseLsappBundle(out) {
8313
8364
  const m = /"CFBundleIdentifier"\s*=\s*"([^"]+)"/.exec(out);
8314
8365
  return m ? m[1] : null;
8315
8366
  }
8367
+ function parseEtime(s) {
8368
+ const m = /^(?:(?:(\d+)-)?(\d+):)?(\d+):(\d+)$/.exec(s.trim());
8369
+ if (!m) return null;
8370
+ const [d, h, mi, se] = [m[1], m[2], m[3], m[4]].map((x) => Number(x ?? 0));
8371
+ return (((d * 24 + h) * 60 + mi) * 60 + se) * 1e3;
8372
+ }
8373
+ function hasPortArg(args) {
8374
+ return /(^|\s|")--remote-debugging-port(=|\s|"|$)/.test(args);
8375
+ }
8376
+ function macBrandMains(psOut, macExe) {
8377
+ const out = [];
8378
+ for (const line of psOut.split(/\r?\n/)) {
8379
+ const m = /^\s*(\d+)\s+(\S+)\s+(.*)$/.exec(line);
8380
+ if (!m || !isMainArgs(m[3], macExe)) continue;
8381
+ out.push({ pid: Number(m[1]), ageMs: parseEtime(m[2]), hasPort: hasPortArg(m[3].slice(macExe.length)) });
8382
+ }
8383
+ return out;
8384
+ }
8316
8385
  function toolBusy(tool, now = Date.now(), dir2 = stateDir(), alive = isAlive) {
8317
8386
  if (!existsSync20(dir2)) return false;
8318
8387
  for (const f of readdirSync12(dir2)) {
@@ -8343,6 +8412,8 @@ var QoderCdpKeeper = class {
8343
8412
  #hung = new HungTracker();
8344
8413
  /** 这一段卡死里「暂不重启」的原因记过哪条(同一条只记一次) */
8345
8414
  #hungNote = "";
8415
+ /** 启动瞬间补端口处理过的主进程号(每个启动只做一次) */
8416
+ #launchSeen = [];
8346
8417
  constructor(deps) {
8347
8418
  this.#d = deps;
8348
8419
  }
@@ -8425,6 +8496,7 @@ var QoderCdpKeeper = class {
8425
8496
  const t = all?.[this.#d.brand.tool] ?? {};
8426
8497
  const out = { lastLaunch: Number(t.lastLaunch) || 0, lastRestart: Number(t.lastRestart) || 0, day: typeof t.day === "string" ? t.day : "", restarts: Number(t.restarts) || 0 };
8427
8498
  if (this.#d.brand.win && isWinAppExe(t.appExe, this.#d.brand.win.exe)) out.appExe = t.appExe;
8499
+ if (Array.isArray(t.launchPorts)) out.launchPorts = t.launchPorts.map(Number).filter((x) => Number.isFinite(x) && x > 0);
8428
8500
  return out;
8429
8501
  } catch {
8430
8502
  return { lastLaunch: 0, lastRestart: 0, day: "", restarts: 0 };
@@ -8594,6 +8666,87 @@ var QoderCdpKeeper = class {
8594
8666
  const r = await this.#exec()("ioreg", ["-c", "IOHIDSystem", "-d", "4"]);
8595
8667
  return r.code === 0 ? parseHidIdleMs2(r.stdout) : null;
8596
8668
  }
8669
+ /** 主进程(macOS;只认唯一一个;没有 / 认不出 / 多个 → null) */
8670
+ async #brandMain() {
8671
+ const r = await this.#exec()("ps", ["-axww", "-o", "pid=,etime=,args="]);
8672
+ if (r.code !== 0) return null;
8673
+ const mains = macBrandMains(r.stdout, this.#d.brand.macExe);
8674
+ return mains.length === 1 ? mains[0] : null;
8675
+ }
8676
+ /**
8677
+ * 启动瞬间补端口(spec 2026-10-12 qoder-launch-port):主进程刚起(不到 LAUNCH_FRESH_MS)、命令行没带调试端口、没有会话在跑 / 待答题 →
8678
+ * 不管用户在不在,正常退出并带端口拉起。每个启动(主进程号)只看一次:带了端口 / 已超过 10 秒 / 处理过(成败都算)都不再动;
8679
+ * 单独限流 LAUNCH_PORT_MAX 次 / LAUNCH_PORT_WINDOW_MS(落盘),不占每天 3 次的重启额度。
8680
+ * 🔴 macOS 只正常退出(osascript quit),20 秒没退就放弃、绝不强杀;Windows 关闭按钮只会缩到托盘,按原有规则结束这一个主进程树(刚起、没会话)
8681
+ */
8682
+ async fixFreshLaunch() {
8683
+ if (this.#platform() !== "darwin" || this.#skip() || this.#d.noRestart) return "skipped";
8684
+ if (this.#restarting || this.#waking || this.#launchChecking) return "skipped";
8685
+ this.#launchChecking = true;
8686
+ try {
8687
+ return await this.#fixFresh();
8688
+ } finally {
8689
+ this.#launchChecking = false;
8690
+ if (this.#launchRestarting) {
8691
+ this.#launchRestarting = false;
8692
+ this.#restarting = false;
8693
+ }
8694
+ }
8695
+ }
8696
+ /** 补端口检测进行中(只看进程表,不挡唤起) */
8697
+ #launchChecking = false;
8698
+ /** 这次 #restarting 是补端口占的(finally 里释放) */
8699
+ #launchRestarting = false;
8700
+ /** 正在启动补端口 / 重启(常开据此跳过) */
8701
+ get restarting() {
8702
+ return this.#restarting;
8703
+ }
8704
+ async #fixFresh() {
8705
+ const main = await this.#brandMain();
8706
+ if (!main) return "none";
8707
+ if (this.#launchSeen.includes(main.pid)) return "seen";
8708
+ this.#launchSeen.push(main.pid);
8709
+ if (this.#launchSeen.length > LAUNCH_SEEN_MAX) this.#launchSeen.shift();
8710
+ if (main.hasPort) return "has_port";
8711
+ if (main.ageMs === null || main.ageMs < 0 || main.ageMs >= LAUNCH_FRESH_MS) return "old";
8712
+ const b = this.#d.brand;
8713
+ const now = this.#now();
8714
+ if ((this.#d.busy ?? (() => toolBusy(b.tool, now)))()) {
8715
+ this.#d.log(`${b.label} \u521A\u542F\u52A8\u6CA1\u5E26\u8C03\u8BD5\u7AEF\u53E3\uFF0C\u4F46\u6709\u4F1A\u8BDD\u5728\u8DD1\u6216\u6709\u5F85\u7B54\u9898\uFF0C\u4E0D\u91CD\u5F00`);
8716
+ return "busy";
8717
+ }
8718
+ const t = this.#loadThrottle();
8719
+ const recent = (t.launchPorts ?? []).filter((x) => now - x < LAUNCH_PORT_WINDOW_MS && x <= now);
8720
+ if (recent.length >= LAUNCH_PORT_MAX) {
8721
+ this.#d.log(`${b.label} \u521A\u542F\u52A8\u6CA1\u5E26\u8C03\u8BD5\u7AEF\u53E3\uFF0C\u4F46 ${LAUNCH_PORT_WINDOW_MS / 6e4} \u5206\u949F\u5185\u5DF2\u91CD\u5F00 ${recent.length} \u6B21\uFF0C\u8FD9\u6B21\u4E0D\u91CD\u5F00`);
8722
+ return "limited";
8723
+ }
8724
+ const app = this.appPath();
8725
+ if (!app) return "failed";
8726
+ if (this.#restarting || this.#waking) return "skipped";
8727
+ this.#restarting = true;
8728
+ this.#launchRestarting = true;
8729
+ this.#saveThrottle({ ...t, launchPorts: [...recent, now], lastLaunch: now });
8730
+ await this.#exec()("osascript", ["-e", `quit app ${JSON.stringify(b.appName)}`], 15e3);
8731
+ let gone = false;
8732
+ for (let waited = 0; waited < QUIT_WAIT_MS2; waited += 1e3) {
8733
+ if (!await this.appRunning()) {
8734
+ gone = true;
8735
+ break;
8736
+ }
8737
+ await this.#sleep(1e3);
8738
+ }
8739
+ if (!gone) {
8740
+ this.#d.log(`${b.label} \u521A\u542F\u52A8\u6CA1\u5E26\u8C03\u8BD5\u7AEF\u53E3\uFF0C${QUIT_WAIT_MS2 / 1e3} \u79D2\u5185\u6CA1\u6709\u9000\u51FA\uFF0C\u653E\u5F03\u91CD\u5F00\uFF08\u4E0D\u5F3A\u5236\u7ED3\u675F\uFF09`);
8741
+ return "failed";
8742
+ }
8743
+ const port = this.#d.port();
8744
+ const launch = this.#d.launch ?? defaultLaunch;
8745
+ const env = (this.#d.launchEnv ?? cleanLaunchEnv)();
8746
+ const ok = await launch("open", ["-a", app, "--args", `--remote-debugging-port=${port}`], env);
8747
+ this.#d.log(ok ? `${b.label} \u521A\u542F\u52A8\u6CA1\u5E26\u8C03\u8BD5\u7AEF\u53E3\uFF0C\u5DF2\u5E26\u7AEF\u53E3\u91CD\u5F00\uFF08\u7AEF\u53E3 ${port}\uFF09` : `${b.label} \u521A\u542F\u52A8\u6CA1\u5E26\u8C03\u8BD5\u7AEF\u53E3\uFF0C\u5DF2\u9000\u51FA\u4F46\u5E26\u7AEF\u53E3\u62C9\u8D77\u5931\u8D25\uFF08\u4E0D\u518D\u91CD\u8BD5\uFF09`);
8748
+ return ok ? "reopened" : "failed";
8749
+ }
8597
8750
  /**
8598
8751
  * 设备任务到达、App 不可用时唤起(spec §3.1)。不等端口起来(调用方等连上):
8599
8752
  * - 端口已活 → running;
@@ -8601,9 +8754,9 @@ var QoderCdpKeeper = class {
8601
8754
  * - App 开着没带端口:用户在场 → present、正在跑任务 → busy(都不动 App);用户不在场且空闲 → 退出重启 → restarted;
8602
8755
  * - 没装 → not_installed;当天重启次数用完 / 拉不起来 → failed;非 macOS / 测试兜底 → skipped
8603
8756
  */
8604
- async wakeForTask() {
8757
+ async wakeForTask(source = "task") {
8605
8758
  if (this.#waking) return this.#waking;
8606
- const p = this.#wake();
8759
+ const p = this.#wake(source);
8607
8760
  this.#waking = p;
8608
8761
  try {
8609
8762
  return await p;
@@ -8611,7 +8764,7 @@ var QoderCdpKeeper = class {
8611
8764
  if (this.#waking === p) this.#waking = null;
8612
8765
  }
8613
8766
  }
8614
- async #wake() {
8767
+ async #wake(source) {
8615
8768
  if (this.#skip() || !this.#canManage() || this.#d.noRestart) return "skipped";
8616
8769
  if (this.#restarting) return "restarted";
8617
8770
  const pr = await this.#probe();
@@ -8642,7 +8795,7 @@ var QoderCdpKeeper = class {
8642
8795
  if (restarts >= RESTART_DAILY_MAX2) return "failed";
8643
8796
  const app = this.appPath();
8644
8797
  if (!app) return "not_installed";
8645
- return await this.#restart(app, t, now, restarts, false) ? "restarted" : "failed";
8798
+ return await this.#restart(app, t, now, restarts, false, source) ? "restarted" : "failed";
8646
8799
  }
8647
8800
  /**
8648
8801
  * 设备任务到达、端口在监听但无响应:空闲、用户不在场、已连续无响应满 HUNG_RESTART_MS、没超节流 → 结束并带端口重启(restarted);
@@ -8678,7 +8831,7 @@ var QoderCdpKeeper = class {
8678
8831
  * hung=false(没带端口):正常退出 20 秒没反应就放弃——🔴 可能有确认弹窗,不强杀;
8679
8832
  * hung=true(端口无响应、App 卡死):正常退出没反应时结束端口监听者(确认是这个 App 的主进程才动)
8680
8833
  */
8681
- async #restart(app, t, now, restarts, hung) {
8834
+ async #restart(app, t, now, restarts, hung, source = "task") {
8682
8835
  if (this.#restarting) return false;
8683
8836
  this.#restarting = true;
8684
8837
  const b = this.#d.brand;
@@ -8686,7 +8839,7 @@ var QoderCdpKeeper = class {
8686
8839
  try {
8687
8840
  this.#saveThrottle({ ...this.#loadThrottle(), lastRestart: now, day: localDay2(now), restarts: restarts + 1 });
8688
8841
  this.#d.log(
8689
- hung ? `${b.label} \u8C03\u8BD5\u7AEF\u53E3 ${port} \u65E0\u54CD\u5E94 ${this.#hung.minutes(now)} \u5206\u949F\u3001App \u7A7A\u95F2\u3001\u7528\u6237\u4E0D\u5728\u573A\uFF1A\u9000\u51FA\u5E76\u5E26\u7AEF\u53E3\u91CD\u542F\uFF08\u4ECA\u5929\u7B2C ${restarts + 1}/${RESTART_DAILY_MAX2} \u6B21\uFF09` : `\u8BBE\u5907\u4EFB\u52A1\u5230\u8FBE\uFF1A${b.label} \u5F00\u7740\u4F46\u6CA1\u5E26\u8C03\u8BD5\u7AEF\u53E3\u3001\u7528\u6237\u4E0D\u5728\u573A\uFF1A\u9000\u51FA\u5E76\u5E26\u7AEF\u53E3\u91CD\u542F\uFF08\u4ECA\u5929\u7B2C ${restarts + 1}/${RESTART_DAILY_MAX2} \u6B21\uFF09`
8842
+ hung ? `${b.label} \u8C03\u8BD5\u7AEF\u53E3 ${port} \u65E0\u54CD\u5E94 ${this.#hung.minutes(now)} \u5206\u949F\u3001App \u7A7A\u95F2\u3001\u7528\u6237\u4E0D\u5728\u573A\uFF1A\u9000\u51FA\u5E76\u5E26\u7AEF\u53E3\u91CD\u542F\uFF08\u4ECA\u5929\u7B2C ${restarts + 1}/${RESTART_DAILY_MAX2} \u6B21\uFF09` : source === "keep_open" ? `${b.label} \u7AEF\u53E3\u4E0D\u5728\u3001\u7528\u6237\u4E0D\u5728\u4E14\u7A7A\u95F2\uFF0C\u5E26\u7AEF\u53E3\u91CD\u5F00\uFF08\u5E38\u5F00\uFF0C\u4ECA\u5929\u7B2C ${restarts + 1}/${RESTART_DAILY_MAX2} \u6B21\uFF09` : `\u8BBE\u5907\u4EFB\u52A1\u5230\u8FBE\uFF1A${b.label} \u5F00\u7740\u4F46\u6CA1\u5E26\u8C03\u8BD5\u7AEF\u53E3\u3001\u7528\u6237\u4E0D\u5728\u573A\uFF1A\u9000\u51FA\u5E76\u5E26\u7AEF\u53E3\u91CD\u542F\uFF08\u4ECA\u5929\u7B2C ${restarts + 1}/${RESTART_DAILY_MAX2} \u6B21\uFF09`
8690
8843
  );
8691
8844
  const exec = this.#exec();
8692
8845
  if (this.#isWin()) return await this.#restartWin(app, hung);
@@ -10495,7 +10648,7 @@ var defaultLoginOpenDeps = () => ({
10495
10648
  });
10496
10649
  async function installCodebuddyHooks(log) {
10497
10650
  try {
10498
- const { installTools: installTools2 } = await import("./enable-SIY4AEF7.js");
10651
+ const { installTools: installTools2 } = await import("./enable-OC46BDQD.js");
10499
10652
  installTools2(["workbuddy"], () => {
10500
10653
  }, null, { auto: true });
10501
10654
  } catch (e) {
@@ -11009,7 +11162,7 @@ function defaultOfferDeps(log) {
11009
11162
  }),
11010
11163
  openLogin: () => defaultOpenLogin(platform),
11011
11164
  installHooks: async () => {
11012
- const { installTools: installTools2 } = await import("./enable-SIY4AEF7.js");
11165
+ const { installTools: installTools2 } = await import("./enable-OC46BDQD.js");
11013
11166
  installTools2(["workbuddy"], (l) => log(`[WorkBuddy \u72EC\u7ACB\u7248] ${l}`), null, { auto: true });
11014
11167
  },
11015
11168
  log: (l) => log(`[WorkBuddy \u72EC\u7ACB\u7248] ${l}`),
@@ -11263,6 +11416,7 @@ export {
11263
11416
  qwenworkDataHome,
11264
11417
  qoderSettingsPath,
11265
11418
  opencodePluginPath,
11419
+ codexHome,
11266
11420
  installedHookPath,
11267
11421
  loadConfig,
11268
11422
  saveConfig,
@@ -11274,6 +11428,7 @@ export {
11274
11428
  packageVersion,
11275
11429
  installedHookVersion,
11276
11430
  syncHookFile,
11431
+ CODE_NOT_SUPPORT,
11277
11432
  APP_ID,
11278
11433
  APP_SECRET,
11279
11434
  sign,