deskbuddy 0.2.0-beta.35 → 0.2.0-beta.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -2890,13 +2890,40 @@ function singleCursor(lines3, q) {
2890
2890
  if (m) {
2891
2891
  const k = Number(m[1]) - 1;
2892
2892
  if (k >= 0 && k < n) return squash(m[2]).startsWith(squash(q.options[k].label).slice(0, 6)) ? k : -1;
2893
- if (k === n) return /^Typesomething/.test(squash(m[2])) ? n : -1;
2893
+ if (k === n) return /^(Typesomething)?$/.test(squash(m[2])) ? n : -1;
2894
2894
  return -1;
2895
2895
  }
2896
2896
  if (new RegExp(`^\\s*${CURSOR}\\s*(Next|Submit)\\s*$`).test(l)) return n + 1;
2897
2897
  }
2898
2898
  return -1;
2899
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
+ }
2900
2927
  async function move(io, delta) {
2901
2928
  const key = delta > 0 ? KEY_DOWN : KEY_UP;
2902
2929
  for (let i = 0; i < Math.abs(delta); i++) {
@@ -2904,12 +2931,16 @@ async function move(io, delta) {
2904
2931
  await io.sleep(ARROW_GAP_MS);
2905
2932
  }
2906
2933
  }
2907
- async function answerQuestions(io, questions, selections) {
2934
+ async function answerQuestions(io, questions, selections, others) {
2908
2935
  if (questions.length === 0 || selections.length !== questions.length) return "not_waiting";
2936
+ if (others !== void 0 && others.length !== questions.length) return "not_waiting";
2909
2937
  for (let qi = 0; qi < questions.length; qi++) {
2910
2938
  const sel = selections[qi];
2911
2939
  const q = questions[qi];
2912
- if (sel.length === 0 || sel.some((i) => !Number.isInteger(i) || i < 0 || i >= q.options.length)) return "not_waiting";
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";
2913
2944
  if (q.multiSelect !== true && sel.length !== 1) return "not_waiting";
2914
2945
  }
2915
2946
  if (!await settled(io, (l) => onQuestion(l, questions[0]))) return "not_waiting";
@@ -2930,6 +2961,14 @@ async function answerQuestions(io, questions, selections) {
2930
2961
  for (const t of sel) {
2931
2962
  await move(io, t - cur);
2932
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
+ }
2933
2972
  const onTarget = await waitUntil(io, (l) => {
2934
2973
  const ln = optionLine(l, t + 1, q.options[t].label);
2935
2974
  return ln >= 0 && io.cursorLine?.() === ln;
@@ -2948,7 +2987,11 @@ async function answerQuestions(io, questions, selections) {
2948
2987
  const cur = singleCursor(io.screen(), q);
2949
2988
  if (cur < 0) return fail();
2950
2989
  await move(io, t - cur);
2951
- if (!await waitUntil(io, (l) => singleCursor(l, q) === t && optionLine(l, t + 1, q.options[t].label) >= 0)) return fail();
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();
2952
2995
  io.write(KEY_ENTER);
2953
2996
  wrote = true;
2954
2997
  }
@@ -7806,7 +7849,14 @@ ${PRELUDE3}
7806
7849
  }
7807
7850
  }
7808
7851
  if (C && typeof C.currentId === 'string') return { mode: 'dom', locale: localeOf(), why };
7809
- return { mode: 'none', locale: localeOf(), why };
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 } : {}) };
7810
7860
  })()`;
7811
7861
  var IDLE_STATES = "['idle','completed','cancelled','canceled','done','failed','error','terminated','archived','deleted','']";
7812
7862
  var SNAPSHOT2 = String.raw`(async () => {
@@ -8249,7 +8299,10 @@ var WorkbuddyAppWatch = class {
8249
8299
  this.#nonSdkSince = first && kept && now - kept.at < NON_SDK_KEEP_MS ? kept.since : now;
8250
8300
  this.#nonSdkKept = null;
8251
8301
  }
8252
- if (first || prev !== this.#mode || prevWhy !== this.#modeWhy) this.#d.log(`WorkBuddy App \u6388\u6743\u6865\u6A21\u5F0F\uFF1A${this.#mode}${this.#modeWhy ? `\uFF08${modeWhyText(this.#modeWhy)}\uFF09` : ""}`);
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
+ }
8253
8306
  const cands = this.#client?.target?.candidates ?? 1;
8254
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) {
8255
8308
  this.#reprobeAt = now;
@@ -8518,7 +8571,7 @@ function modeWhyText(why) {
8518
8571
  const msg = rest.join(":");
8519
8572
  switch (k) {
8520
8573
  case "no_wb":
8521
- 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";
8522
8575
  case "no_conversations":
8523
8576
  return "\u9875\u9762\u91CC\u6CA1\u6709\u4F1A\u8BDD\u63A5\u53E3\uFF08wb.conversations\uFF09";
8524
8577
  case "no_list_get":
@@ -10455,14 +10508,28 @@ function parseAnswer(m) {
10455
10508
  const questions = parseQuestions(a.questions);
10456
10509
  const sel = a.selections;
10457
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
+ }
10458
10520
  const selections = [];
10459
10521
  for (let i = 0; i < questions.length; i++) {
10460
10522
  const s2 = sel[i];
10461
- if (!Array.isArray(s2) || s2.length === 0 || !s2.every((x) => Number.isInteger(x) && x >= 0 && x < questions[i].options.length)) return null;
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;
10462
10528
  selections.push(s2);
10463
10529
  }
10464
- return { instructionId, sessionId, expireAt, answer: { kind: "question", questions, selections } };
10530
+ return { instructionId, sessionId, expireAt, answer: { kind: "question", questions, selections, ...others ? { others } : {} } };
10465
10531
  }
10532
+ var OTHER_MAX_CHARS = 500;
10466
10533
  function parseQuestions(v) {
10467
10534
  if (!Array.isArray(v)) return null;
10468
10535
  const qs = v;
@@ -10828,20 +10895,31 @@ function pendingCall(text, toolName) {
10828
10895
  function selectionsOf(input, lists) {
10829
10896
  const qs = Array.isArray(input.questions) ? input.questions : null;
10830
10897
  if (!qs || !Array.isArray(lists) || lists.length !== qs.length) return null;
10831
- const out = [];
10898
+ const selections = [];
10899
+ const others = [];
10832
10900
  for (let i = 0; i < qs.length; i++) {
10833
10901
  const opts = Array.isArray(qs[i]?.options) ? qs[i].options : [];
10834
10902
  const items = lists[i];
10835
10903
  if (!Array.isArray(items) || items.length === 0) return null;
10836
10904
  const idx = [];
10837
- for (const label of items) {
10905
+ let other = "";
10906
+ for (let j = 0; j < items.length; j++) {
10907
+ const label = items[j];
10838
10908
  const k = opts.findIndex((o) => o?.label === label);
10839
- if (k < 0) return null;
10840
- idx.push(k);
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;
10841
10916
  }
10842
- out.push(idx);
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);
10843
10921
  }
10844
- return out;
10922
+ return { selections, others };
10845
10923
  }
10846
10924
  var WorkbuddyBridge = class {
10847
10925
  #d;
@@ -10979,10 +11057,16 @@ var WorkbuddyBridge = class {
10979
11057
  if (reply.decision !== "allow") return;
10980
11058
  const sel = selectionsOf(card.input, reply.answerLists);
10981
11059
  if (!sel) {
10982
- this.#d.log(`WorkBuddy\uFF1A\u4F1A\u8BDD ${card.sessionId.slice(0, 8)} \u7684\u8BBE\u5907\u7B54\u6848\u5BF9\u4E0D\u4E0A\u9009\u9879\uFF08\u542B\u81EA\u5DF1\u586B\u5199\u7684\u7B54\u6848\uFF09\uFF0C\u6846\u7559\u7ED9\u7535\u8111`);
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`);
10983
11061
  return;
10984
11062
  }
10985
- spec = { kind: "question", questions: card.input.questions, selections: sel };
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
+ };
10986
11070
  } else if (reply.decision === "allow" || reply.decision === "deny") {
10987
11071
  spec = { kind: "permission", toolName: card.toolName, fingerprint: card.fingerprint, decision: reply.decision };
10988
11072
  } else return;
@@ -13768,6 +13852,7 @@ function removeCodexRemote() {
13768
13852
  import { closeSync as closeSync8, openSync as openSync8, readdirSync as readdirSync9, readSync as readSync7, statSync as statSync11 } from "fs";
13769
13853
  import { dirname as dirname6, join as join22 } from "path";
13770
13854
  var INTERRUPT_TOOLS = ["claude_code", "qoder_cn", "qoder"];
13855
+ var CODEX_INTERRUPT_TOOL = "codex";
13771
13856
  function transcriptHome(tool) {
13772
13857
  if (tool === "claude_code") return claudeHome();
13773
13858
  if (tool === "qoder_cn") return dirname6(qoderCnSettingsPath());
@@ -13890,14 +13975,53 @@ function claudeTranscriptFile(sessionId, cwd, home = claudeHome()) {
13890
13975
  var INTERRUPT_SETTLE_MS = 2e3;
13891
13976
  var INTERRUPT_TOLERANCE_MS = 5e3;
13892
13977
  function shouldSettleInterrupt(st, markerAt, now) {
13893
- if (markerAt === null || !INTERRUPT_TOOLS.includes(st.tool)) return false;
13978
+ const codex = st.tool === CODEX_INTERRUPT_TOOL;
13979
+ if (markerAt === null || !INTERRUPT_TOOLS.includes(st.tool) && !codex) return false;
13894
13980
  if (st.state !== "watch" && st.state !== "ask_approval") return false;
13895
- if (st.interactive !== true && st.embedded !== true) return false;
13981
+ if (!codex && st.interactive !== true && st.embedded !== true) return false;
13896
13982
  if (now - markerAt < INTERRUPT_SETTLE_MS) return false;
13897
13983
  if (st.updatedAt > markerAt + INTERRUPT_TOLERANCE_MS) return false;
13898
13984
  if ((st.recent ?? []).some((r) => r.e === "UserPromptSubmit" && r.at > markerAt)) return false;
13899
13985
  return true;
13900
13986
  }
13987
+ function codexInterruptedAt(file) {
13988
+ let fd;
13989
+ try {
13990
+ const st = statSync11(file);
13991
+ const len = Math.min(st.size, TAIL);
13992
+ const buf = Buffer.alloc(len);
13993
+ fd = openSync8(file, "r");
13994
+ readSync7(fd, buf, 0, len, st.size - len);
13995
+ const lines3 = buf.toString("utf8").split("\n");
13996
+ for (let i = lines3.length - 1; i >= 0; i--) {
13997
+ const line = lines3[i];
13998
+ if (line.indexOf('"event_msg"') === -1) continue;
13999
+ let o;
14000
+ try {
14001
+ o = JSON.parse(line);
14002
+ } catch {
14003
+ continue;
14004
+ }
14005
+ if (!o || o.type !== "event_msg" || !o.payload) continue;
14006
+ const t = o.payload.type;
14007
+ if (t === "turn_aborted") {
14008
+ const at = typeof o.timestamp === "string" ? Date.parse(o.timestamp) : NaN;
14009
+ return Number.isFinite(at) ? at : st.mtimeMs;
14010
+ }
14011
+ if (t === "task_complete" || t === "turn_complete" || t === "task_started" || t === "turn_started" || t === "user_message") return null;
14012
+ }
14013
+ return null;
14014
+ } catch {
14015
+ return null;
14016
+ } finally {
14017
+ if (fd !== void 0) {
14018
+ try {
14019
+ closeSync8(fd);
14020
+ } catch {
14021
+ }
14022
+ }
14023
+ }
14024
+ }
13901
14025
 
13902
14026
  // src/daemon/qoderAppDb.ts
13903
14027
  import { execFile as execFile4 } from "child_process";
@@ -15668,7 +15792,7 @@ var Daemon = class {
15668
15792
  #settleInterrupted() {
15669
15793
  if (this.#stopped) return;
15670
15794
  const enabled = loadConfig().enabledTools;
15671
- const tools = INTERRUPT_TOOLS.filter((t) => enabled.includes(t));
15795
+ const tools = [...INTERRUPT_TOOLS, CODEX_INTERRUPT_TOOL].filter((t) => enabled.includes(t));
15672
15796
  if (tools.length === 0) return;
15673
15797
  const now = this.#deps.now();
15674
15798
  const alive = /* @__PURE__ */ new Set();
@@ -15676,7 +15800,7 @@ var Daemon = class {
15676
15800
  let changed = false;
15677
15801
  for (const st of this.#aliveStates(tool)) {
15678
15802
  alive.add(st.sessionId);
15679
- if (!BUSY_STATES3.has(st.state) || st.interactive !== true && st.embedded !== true) {
15803
+ if (!BUSY_STATES3.has(st.state) || tool !== CODEX_INTERRUPT_TOOL && st.interactive !== true && st.embedded !== true) {
15680
15804
  this.#transcriptSeen.delete(st.sessionId);
15681
15805
  continue;
15682
15806
  }
@@ -15688,16 +15812,16 @@ var Daemon = class {
15688
15812
  if (!file) continue;
15689
15813
  const sig = transcriptSig(file);
15690
15814
  if (sig && this.#transcriptSeen.get(st.sessionId) === sig) continue;
15691
- const at = interruptedAt(file);
15815
+ const at = tool === CODEX_INTERRUPT_TOOL ? codexInterruptedAt(file) : interruptedAt(file);
15692
15816
  if (sig && (at === null || now - at >= INTERRUPT_SETTLE_MS)) this.#transcriptSeen.set(st.sessionId, sig);
15693
15817
  if (at === null || !shouldSettleInterrupt(st, at, now)) continue;
15694
- if (this.#settleBusy(st.sessionId, tool, st.updatedAt, `\u5728\u7A97\u53E3\u91CC\u88AB\u6253\u65AD\uFF08${tool} \u4E0D\u53D1 Stop\uFF09`)) {
15818
+ if (this.#settleBusy(st.sessionId, tool, st.updatedAt, `${tool === CODEX_INTERRUPT_TOOL ? "\u88AB\u7528\u6237\u505C\u6B62" : "\u5728\u7A97\u53E3\u91CC\u88AB\u6253\u65AD"}\uFF08${tool} \u4E0D\u53D1 Stop\uFF09`)) {
15695
15819
  changed = true;
15696
15820
  this.#idleWindowAfterInterrupt(st.sessionId, tool, at);
15697
15821
  this.#coord.settleInterruptedWindows(st.sessionId, at);
15698
15822
  }
15699
15823
  }
15700
- if (changed) void this.#reportTool(tool);
15824
+ if (changed) void (tool === CODEX_INTERRUPT_TOOL ? this.#reportCodex() : this.#reportTool(tool));
15701
15825
  }
15702
15826
  for (const m of [this.#transcripts, this.#transcriptMiss, this.#transcriptSeen]) for (const k of [...m.keys()]) if (!alive.has(k)) m.delete(k);
15703
15827
  }
@@ -15718,7 +15842,7 @@ var Daemon = class {
15718
15842
  const missAt = this.#transcriptMiss.get(st.sessionId);
15719
15843
  if (missAt !== void 0 && now - missAt < TRANSCRIPT_MISS_TTL_MS) return null;
15720
15844
  const home = transcriptHome(st.tool);
15721
- const f = home ? claudeTranscriptFile(st.sessionId, st.cwd, home) : null;
15845
+ const f = st.tool === CODEX_INTERRUPT_TOOL ? findCodexRollout(codexHome(), st.sessionId, 7) : home ? claudeTranscriptFile(st.sessionId, st.cwd, home) : null;
15722
15846
  if (f) {
15723
15847
  this.#transcripts.set(st.sessionId, f);
15724
15848
  this.#transcriptMiss.delete(st.sessionId);
@@ -19667,7 +19791,7 @@ async function applyAnswer(req, io, trust) {
19667
19791
  } else if (a.kind === "trust" && a.prompt !== "hooks" && trust?.widens) r = "not_waiting";
19668
19792
  else if (a.kind === "trust") r = await answerTrust(keys, trust?.tool ?? "", a.decision, trust?.forms ?? [], a.prompt ?? "trust");
19669
19793
  else if (a.kind === "permission") r = await answerPermission(keys, a.toolName, a.fingerprint, a.decision);
19670
- else r = await answerQuestions(keys, a.questions, a.selections);
19794
+ else r = await answerQuestions(keys, a.questions, a.selections, a.others);
19671
19795
  } catch {
19672
19796
  r = "partial";
19673
19797
  }
@@ -338,3 +338,45 @@
338
338
  2026-10-12T07:48:57.673Z [opencode] opencode 版本 读不出:带说明的拒绝不走新路由
339
339
  2026-10-12T07:48:57.673Z [opencode] opencode 版本不确定支持带说明的拒绝,设备上的反馈没有带给模型
340
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 没法在设备上回答(后台任务不能提问,请在电脑上继续),已拒绝
365
+ 2026-10-12T10:52:32.632Z [opencode] 回填选择题失败:/question/{requestID}/reply status=404
366
+ 2026-10-12T10:52:37.625Z [opencode] opencode 版本 1.4.3:带说明的拒绝不走新路由
367
+ 2026-10-12T10:52:37.625Z [opencode] opencode 版本不确定支持带说明的拒绝,设备上的反馈没有带给模型
368
+ 2026-10-12T10:52:37.718Z [opencode] opencode 版本 读不出:带说明的拒绝不走新路由
369
+ 2026-10-12T10:52:37.719Z [opencode] opencode 版本不确定支持带说明的拒绝,设备上的反馈没有带给模型
370
+ 2026-10-12T10:52:40.546Z [opencode] 后台任务里的提问 que_r2 没法在设备上回答(后台任务不能提问,请在电脑上继续),已拒绝
371
+ 2026-10-12T10:56:52.376Z [opencode] 回填选择题失败:/question/{requestID}/reply status=404
372
+ 2026-10-12T10:56:57.350Z [opencode] opencode 版本 1.4.3:带说明的拒绝不走新路由
373
+ 2026-10-12T10:56:57.350Z [opencode] opencode 版本不确定支持带说明的拒绝,设备上的反馈没有带给模型
374
+ 2026-10-12T10:56:57.454Z [opencode] opencode 版本 读不出:带说明的拒绝不走新路由
375
+ 2026-10-12T10:56:57.454Z [opencode] opencode 版本不确定支持带说明的拒绝,设备上的反馈没有带给模型
376
+ 2026-10-12T10:56:59.731Z [opencode] 后台任务里的提问 que_r2 没法在设备上回答(后台任务不能提问,请在电脑上继续),已拒绝
377
+ 2026-10-12T11:00:08.567Z [opencode] 回填选择题失败:/question/{requestID}/reply status=404
378
+ 2026-10-12T11:00:13.510Z [opencode] opencode 版本 1.4.3:带说明的拒绝不走新路由
379
+ 2026-10-12T11:00:13.510Z [opencode] opencode 版本不确定支持带说明的拒绝,设备上的反馈没有带给模型
380
+ 2026-10-12T11:00:13.614Z [opencode] opencode 版本 读不出:带说明的拒绝不走新路由
381
+ 2026-10-12T11:00:13.614Z [opencode] opencode 版本不确定支持带说明的拒绝,设备上的反馈没有带给模型
382
+ 2026-10-12T11:00:15.993Z [opencode] 后台任务里的提问 que_r2 没法在设备上回答(后台任务不能提问,请在电脑上继续),已拒绝
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deskbuddy",
3
- "version": "0.2.0-beta.35",
3
+ "version": "0.2.0-beta.37",
4
4
  "description": "把 Claude Code、Codex 等 AI 编码智能体每个会话窗口的状态,实时同步到桌面硬件屏幕",
5
5
  "keywords": [
6
6
  "ai",