reasonix 0.46.1 → 0.47.0

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.
Files changed (131) hide show
  1. package/README.md +62 -13
  2. package/README.zh-CN.md +52 -10
  3. package/dashboard/dist/app.js +217 -60
  4. package/dashboard/dist/app.js.map +1 -1
  5. package/dist/cli/{acp-LKJU5DZX.js → acp-QK3DMC53.js} +22 -22
  6. package/dist/cli/chat-VV5UWY4V.js +51 -0
  7. package/dist/cli/{chunk-DGA5QYFM.js → chunk-24A7FHGJ.js} +42 -13
  8. package/dist/cli/chunk-24A7FHGJ.js.map +1 -0
  9. package/dist/cli/{chunk-K3AIFMI6.js → chunk-6J6BSUCR.js} +2 -2
  10. package/dist/cli/{chunk-C72TNHDE.js → chunk-BWYVFFKR.js} +2 -2
  11. package/dist/cli/{chunk-EAOL43HB.js → chunk-BYYVYJDX.js} +3 -3
  12. package/dist/cli/{chunk-HNXDZGC6.js → chunk-CI2PF5QX.js} +2 -2
  13. package/dist/cli/{chunk-JVQT5IYP.js → chunk-COWPEX54.js} +19 -9
  14. package/dist/cli/chunk-COWPEX54.js.map +1 -0
  15. package/dist/cli/{chunk-IYQ325V7.js → chunk-E5WCLUIU.js} +2 -2
  16. package/dist/cli/{chunk-YRLC2EDF.js → chunk-EQATK2L2.js} +2 -2
  17. package/dist/cli/{chunk-R2ASNSEO.js → chunk-FDKOUJKZ.js} +8 -8
  18. package/dist/cli/{chunk-TEUDEGX2.js → chunk-FY4S7TJZ.js} +19 -5
  19. package/dist/cli/chunk-FY4S7TJZ.js.map +1 -0
  20. package/dist/cli/{chunk-JVFEJAJX.js → chunk-GDKB2PPK.js} +2 -2
  21. package/dist/cli/{chunk-WQ6ZRDQM.js → chunk-HIYTRCSW.js} +16 -12
  22. package/dist/cli/chunk-HIYTRCSW.js.map +1 -0
  23. package/dist/cli/{chunk-ZOQHVQON.js → chunk-ICAFSZHS.js} +307 -30
  24. package/dist/cli/chunk-ICAFSZHS.js.map +1 -0
  25. package/dist/cli/{chunk-SPXN5JIT.js → chunk-ICSYGIPN.js} +1386 -1021
  26. package/dist/cli/chunk-ICSYGIPN.js.map +1 -0
  27. package/dist/cli/{chunk-XPAUNFOL.js → chunk-K6GUKSXH.js} +3 -2
  28. package/dist/cli/chunk-K6GUKSXH.js.map +1 -0
  29. package/dist/cli/{chunk-6VANO7KB.js → chunk-KDRUEXII.js} +147 -20
  30. package/dist/cli/chunk-KDRUEXII.js.map +1 -0
  31. package/dist/cli/{chunk-NCBP5D6E.js → chunk-LBLR4CUZ.js} +2 -2
  32. package/dist/cli/{chunk-2425HK6U.js → chunk-LGEKVMMV.js} +7 -2
  33. package/dist/cli/{chunk-2425HK6U.js.map → chunk-LGEKVMMV.js.map} +1 -1
  34. package/dist/cli/{chunk-7SGGXNB2.js → chunk-OJVITDGB.js} +2 -2
  35. package/dist/cli/{chunk-SE7C5ZSI.js → chunk-QVDWH2A2.js} +3 -3
  36. package/dist/cli/{chunk-WRONKNIH.js → chunk-QVUFWDD2.js} +2 -2
  37. package/dist/cli/{chunk-3AAG2CUT.js → chunk-R6GQKKBW.js} +2 -2
  38. package/dist/cli/{chunk-E7TAHQ4A.js → chunk-RRXUIPWG.js} +19 -18
  39. package/dist/cli/chunk-RRXUIPWG.js.map +1 -0
  40. package/dist/cli/{chunk-CXVWUPA3.js → chunk-TKVXTQ3T.js} +26 -26
  41. package/dist/cli/chunk-TKVXTQ3T.js.map +1 -0
  42. package/dist/cli/{chunk-DHRVZJ2D.js → chunk-UDVFBEXC.js} +3 -3
  43. package/dist/cli/{chunk-7YW6TPXK.js → chunk-VC2CQA5D.js} +9 -9
  44. package/dist/cli/{chunk-M4E5JK6S.js → chunk-VJMBISEI.js} +2 -2
  45. package/dist/cli/{chunk-TDSBASOF.js → chunk-VKYSZKH2.js} +2 -2
  46. package/dist/cli/{chunk-7LOJS3LV.js → chunk-VMUUFWFF.js} +2 -2
  47. package/dist/cli/{chunk-MIIZJD5O.js → chunk-VNQGCA3Q.js} +2 -2
  48. package/dist/cli/{chunk-2AASOSD5.js → chunk-WF7TPVZM.js} +2 -2
  49. package/dist/cli/{chunk-JLQDNLZF.js → chunk-YDPLF7XR.js} +26 -14
  50. package/dist/cli/chunk-YDPLF7XR.js.map +1 -0
  51. package/dist/cli/{code-2JIHL5M2.js → code-C24TUAE5.js} +39 -34
  52. package/dist/cli/code-C24TUAE5.js.map +1 -0
  53. package/dist/cli/{commands-OPT5AJNH.js → commands-RR3GIYOK.js} +4 -4
  54. package/dist/cli/{commit-KA37H6GM.js → commit-FSHPIINM.js} +3 -3
  55. package/dist/cli/{desktop-5ONTRU3C.js → desktop-7NCHPEFB.js} +263 -36
  56. package/dist/cli/desktop-7NCHPEFB.js.map +1 -0
  57. package/dist/cli/{diff-SOIA7AKH.js → diff-RAAHHLHV.js} +8 -8
  58. package/dist/cli/{doctor-RCUP4XRV.js → doctor-PKVQIXRT.js} +9 -9
  59. package/dist/cli/{events-6KHITNX4.js → events-VRYXOSKI.js} +3 -3
  60. package/dist/cli/index.js +81 -40
  61. package/dist/cli/index.js.map +1 -1
  62. package/dist/cli/{mcp-JP5OWD6R.js → mcp-CRJ26PP4.js} +2 -2
  63. package/dist/cli/{mcp-browse-ONCJJPJN.js → mcp-browse-QPAOWZOP.js} +2 -2
  64. package/dist/cli/{mcp-inspect-TPLHW5JA.js → mcp-inspect-CVCLABRS.js} +4 -4
  65. package/dist/cli/{prompt-RJDNCQAP.js → prompt-SKYXERSI.js} +4 -4
  66. package/dist/cli/{prune-sessions-MKEATRVL.js → prune-sessions-SEWX7GP6.js} +2 -2
  67. package/dist/cli/{replay-4NILJG4U.js → replay-KPDW2ZMJ.js} +9 -9
  68. package/dist/cli/{run-WFGXB4SB.js → run-WIKDIXTG.js} +17 -17
  69. package/dist/cli/{server-5VFQP3PV.js → server-P6V2G3P6.js} +82 -34
  70. package/dist/cli/server-P6V2G3P6.js.map +1 -0
  71. package/dist/cli/{sessions-5XDJDALO.js → sessions-2NULRMSA.js} +15 -15
  72. package/dist/cli/{setup-F6XSWLRA.js → setup-Y5WDBQFL.js} +6 -6
  73. package/dist/cli/{stats-ALHBZICE.js → stats-T7BL2YOR.js} +6 -6
  74. package/dist/cli/{version-JVRAHBMM.js → version-3KWDNWLN.js} +15 -15
  75. package/dist/index.d.ts +31 -10
  76. package/dist/index.js +505 -66
  77. package/dist/index.js.map +1 -1
  78. package/package.json +1 -1
  79. package/dist/cli/chat-W7LAWEN6.js +0 -51
  80. package/dist/cli/chunk-6VANO7KB.js.map +0 -1
  81. package/dist/cli/chunk-CXVWUPA3.js.map +0 -1
  82. package/dist/cli/chunk-DGA5QYFM.js.map +0 -1
  83. package/dist/cli/chunk-E7TAHQ4A.js.map +0 -1
  84. package/dist/cli/chunk-JLQDNLZF.js.map +0 -1
  85. package/dist/cli/chunk-JVQT5IYP.js.map +0 -1
  86. package/dist/cli/chunk-SPXN5JIT.js.map +0 -1
  87. package/dist/cli/chunk-TEUDEGX2.js.map +0 -1
  88. package/dist/cli/chunk-WQ6ZRDQM.js.map +0 -1
  89. package/dist/cli/chunk-XPAUNFOL.js.map +0 -1
  90. package/dist/cli/chunk-ZOQHVQON.js.map +0 -1
  91. package/dist/cli/code-2JIHL5M2.js.map +0 -1
  92. package/dist/cli/desktop-5ONTRU3C.js.map +0 -1
  93. package/dist/cli/server-5VFQP3PV.js.map +0 -1
  94. /package/dist/cli/{acp-LKJU5DZX.js.map → acp-QK3DMC53.js.map} +0 -0
  95. /package/dist/cli/{chat-W7LAWEN6.js.map → chat-VV5UWY4V.js.map} +0 -0
  96. /package/dist/cli/{chunk-K3AIFMI6.js.map → chunk-6J6BSUCR.js.map} +0 -0
  97. /package/dist/cli/{chunk-C72TNHDE.js.map → chunk-BWYVFFKR.js.map} +0 -0
  98. /package/dist/cli/{chunk-EAOL43HB.js.map → chunk-BYYVYJDX.js.map} +0 -0
  99. /package/dist/cli/{chunk-HNXDZGC6.js.map → chunk-CI2PF5QX.js.map} +0 -0
  100. /package/dist/cli/{chunk-IYQ325V7.js.map → chunk-E5WCLUIU.js.map} +0 -0
  101. /package/dist/cli/{chunk-YRLC2EDF.js.map → chunk-EQATK2L2.js.map} +0 -0
  102. /package/dist/cli/{chunk-R2ASNSEO.js.map → chunk-FDKOUJKZ.js.map} +0 -0
  103. /package/dist/cli/{chunk-JVFEJAJX.js.map → chunk-GDKB2PPK.js.map} +0 -0
  104. /package/dist/cli/{chunk-NCBP5D6E.js.map → chunk-LBLR4CUZ.js.map} +0 -0
  105. /package/dist/cli/{chunk-7SGGXNB2.js.map → chunk-OJVITDGB.js.map} +0 -0
  106. /package/dist/cli/{chunk-SE7C5ZSI.js.map → chunk-QVDWH2A2.js.map} +0 -0
  107. /package/dist/cli/{chunk-WRONKNIH.js.map → chunk-QVUFWDD2.js.map} +0 -0
  108. /package/dist/cli/{chunk-3AAG2CUT.js.map → chunk-R6GQKKBW.js.map} +0 -0
  109. /package/dist/cli/{chunk-DHRVZJ2D.js.map → chunk-UDVFBEXC.js.map} +0 -0
  110. /package/dist/cli/{chunk-7YW6TPXK.js.map → chunk-VC2CQA5D.js.map} +0 -0
  111. /package/dist/cli/{chunk-M4E5JK6S.js.map → chunk-VJMBISEI.js.map} +0 -0
  112. /package/dist/cli/{chunk-TDSBASOF.js.map → chunk-VKYSZKH2.js.map} +0 -0
  113. /package/dist/cli/{chunk-7LOJS3LV.js.map → chunk-VMUUFWFF.js.map} +0 -0
  114. /package/dist/cli/{chunk-MIIZJD5O.js.map → chunk-VNQGCA3Q.js.map} +0 -0
  115. /package/dist/cli/{chunk-2AASOSD5.js.map → chunk-WF7TPVZM.js.map} +0 -0
  116. /package/dist/cli/{commands-OPT5AJNH.js.map → commands-RR3GIYOK.js.map} +0 -0
  117. /package/dist/cli/{commit-KA37H6GM.js.map → commit-FSHPIINM.js.map} +0 -0
  118. /package/dist/cli/{diff-SOIA7AKH.js.map → diff-RAAHHLHV.js.map} +0 -0
  119. /package/dist/cli/{doctor-RCUP4XRV.js.map → doctor-PKVQIXRT.js.map} +0 -0
  120. /package/dist/cli/{events-6KHITNX4.js.map → events-VRYXOSKI.js.map} +0 -0
  121. /package/dist/cli/{mcp-JP5OWD6R.js.map → mcp-CRJ26PP4.js.map} +0 -0
  122. /package/dist/cli/{mcp-browse-ONCJJPJN.js.map → mcp-browse-QPAOWZOP.js.map} +0 -0
  123. /package/dist/cli/{mcp-inspect-TPLHW5JA.js.map → mcp-inspect-CVCLABRS.js.map} +0 -0
  124. /package/dist/cli/{prompt-RJDNCQAP.js.map → prompt-SKYXERSI.js.map} +0 -0
  125. /package/dist/cli/{prune-sessions-MKEATRVL.js.map → prune-sessions-SEWX7GP6.js.map} +0 -0
  126. /package/dist/cli/{replay-4NILJG4U.js.map → replay-KPDW2ZMJ.js.map} +0 -0
  127. /package/dist/cli/{run-WFGXB4SB.js.map → run-WIKDIXTG.js.map} +0 -0
  128. /package/dist/cli/{sessions-5XDJDALO.js.map → sessions-2NULRMSA.js.map} +0 -0
  129. /package/dist/cli/{setup-F6XSWLRA.js.map → setup-Y5WDBQFL.js.map} +0 -0
  130. /package/dist/cli/{stats-ALHBZICE.js.map → stats-T7BL2YOR.js.map} +0 -0
  131. /package/dist/cli/{version-JVRAHBMM.js.map → version-3KWDNWLN.js.map} +0 -0
@@ -2,16 +2,16 @@
2
2
  import { createRequire as __cr } from 'node:module'; if (typeof globalThis.require === 'undefined') { globalThis.require = __cr(import.meta.url); }
3
3
  import {
4
4
  createMcpRuntime
5
- } from "./chunk-JVQT5IYP.js";
5
+ } from "./chunk-COWPEX54.js";
6
6
  import {
7
7
  buildCodeToolset
8
- } from "./chunk-7YW6TPXK.js";
8
+ } from "./chunk-VC2CQA5D.js";
9
9
  import {
10
10
  Eventizer,
11
11
  autoResolveVerdict
12
- } from "./chunk-HNXDZGC6.js";
13
- import "./chunk-NCBP5D6E.js";
14
- import "./chunk-YRLC2EDF.js";
12
+ } from "./chunk-CI2PF5QX.js";
13
+ import "./chunk-LBLR4CUZ.js";
14
+ import "./chunk-EQATK2L2.js";
15
15
  import {
16
16
  CacheFirstLoop,
17
17
  ImmutablePrefix,
@@ -19,39 +19,39 @@ import {
19
19
  listFilesWithStatsAsync,
20
20
  parseAtQuery,
21
21
  rankPickerCandidates
22
- } from "./chunk-ZOQHVQON.js";
23
- import "./chunk-TDSBASOF.js";
24
- import "./chunk-EAOL43HB.js";
25
- import "./chunk-WQ6ZRDQM.js";
22
+ } from "./chunk-ICAFSZHS.js";
23
+ import "./chunk-VKYSZKH2.js";
24
+ import "./chunk-BYYVYJDX.js";
25
+ import "./chunk-HIYTRCSW.js";
26
26
  import {
27
27
  MemoryStore,
28
28
  codeSystemPrompt
29
- } from "./chunk-DHRVZJ2D.js";
29
+ } from "./chunk-UDVFBEXC.js";
30
30
  import {
31
31
  canonicalPresetName,
32
32
  resolvePreset
33
- } from "./chunk-2425HK6U.js";
33
+ } from "./chunk-LGEKVMMV.js";
34
34
  import {
35
35
  countTokensBounded
36
36
  } from "./chunk-6OWJV3YW.js";
37
37
  import {
38
38
  DeepSeekClient,
39
39
  pickPrimaryBalance
40
- } from "./chunk-MIIZJD5O.js";
40
+ } from "./chunk-VNQGCA3Q.js";
41
41
  import "./chunk-25T6CVUP.js";
42
42
  import {
43
43
  loadDotenv
44
44
  } from "./chunk-2UQP6H6T.js";
45
- import "./chunk-XPAUNFOL.js";
45
+ import "./chunk-K6GUKSXH.js";
46
46
  import {
47
47
  pauseGate
48
- } from "./chunk-JVFEJAJX.js";
48
+ } from "./chunk-GDKB2PPK.js";
49
49
  import {
50
50
  SkillStore
51
- } from "./chunk-TEUDEGX2.js";
51
+ } from "./chunk-FY4S7TJZ.js";
52
52
  import "./chunk-PLHAZOLZ.js";
53
- import "./chunk-JLQDNLZF.js";
54
- import "./chunk-C72TNHDE.js";
53
+ import "./chunk-YDPLF7XR.js";
54
+ import "./chunk-BWYVFFKR.js";
55
55
  import "./chunk-S4XVGLRW.js";
56
56
  import {
57
57
  deleteSession,
@@ -59,12 +59,14 @@ import {
59
59
  loadSessionMessages,
60
60
  loadSessionMeta,
61
61
  patchSessionMeta,
62
+ sessionPath,
62
63
  timestampSuffix
63
- } from "./chunk-E7TAHQ4A.js";
64
- import "./chunk-WRONKNIH.js";
65
- import "./chunk-M4E5JK6S.js";
66
- import "./chunk-6VANO7KB.js";
64
+ } from "./chunk-RRXUIPWG.js";
65
+ import "./chunk-QVUFWDD2.js";
66
+ import "./chunk-VJMBISEI.js";
67
+ import "./chunk-KDRUEXII.js";
67
68
  import {
69
+ describeQQAccess,
68
70
  isPlausibleKey,
69
71
  loadApiKey,
70
72
  loadBaseUrl,
@@ -72,6 +74,7 @@ import {
72
74
  loadEditMode,
73
75
  loadEditor,
74
76
  loadPreset,
77
+ loadQQConfig,
75
78
  loadReasoningEffort,
76
79
  loadRecentWorkspaces,
77
80
  loadResolvedSkillPaths,
@@ -85,10 +88,11 @@ import {
85
88
  saveEditMode,
86
89
  saveEditor,
87
90
  savePreset,
91
+ saveQQConfig,
88
92
  saveReasoningEffort,
89
93
  saveWorkspaceDir,
90
94
  writeConfig
91
- } from "./chunk-DGA5QYFM.js";
95
+ } from "./chunk-24A7FHGJ.js";
92
96
  import {
93
97
  VERSION
94
98
  } from "./chunk-XXC2BYTV.js";
@@ -101,6 +105,58 @@ import { readFile } from "fs/promises";
101
105
  import { isAbsolute, join, resolve } from "path";
102
106
  import { stdin } from "process";
103
107
  import { createInterface } from "readline";
108
+
109
+ // src/desktop/qq-settings.ts
110
+ function trimOptional(value) {
111
+ const trimmed = value?.trim();
112
+ return trimmed ? trimmed : void 0;
113
+ }
114
+ function toPreview(appId) {
115
+ if (!appId) return void 0;
116
+ return appId.length > 6 ? `${appId.slice(0, 6)}...` : appId;
117
+ }
118
+ function toAccess(config) {
119
+ return describeQQAccess({
120
+ ownerOpenId: config.ownerOpenId,
121
+ allowlist: config.allowlist
122
+ });
123
+ }
124
+ function loadDesktopQQState(path) {
125
+ const config = loadQQConfig(path);
126
+ const configured = Boolean(config.appId && config.appSecret);
127
+ return {
128
+ ...config,
129
+ sandbox: config.sandbox ?? false,
130
+ enabled: config.enabled === true,
131
+ configured,
132
+ connected: configured && config.enabled === true,
133
+ appIdPreview: toPreview(config.appId),
134
+ access: toAccess(config)
135
+ };
136
+ }
137
+ function saveDesktopQQSettings(patch, path) {
138
+ const existing = loadQQConfig(path);
139
+ saveQQConfig(
140
+ {
141
+ ...existing,
142
+ appId: trimOptional(patch.appId),
143
+ appSecret: trimOptional(patch.appSecret),
144
+ sandbox: patch.sandbox
145
+ },
146
+ path
147
+ );
148
+ return loadDesktopQQState(path);
149
+ }
150
+ function setDesktopQQEnabled(enabled, path) {
151
+ const existing = loadQQConfig(path);
152
+ if (enabled && !(existing.appId && existing.appSecret)) {
153
+ throw new Error("QQ App ID and App Secret are required.");
154
+ }
155
+ saveQQConfig({ ...existing, enabled }, path);
156
+ return loadDesktopQQState(path);
157
+ }
158
+
159
+ // src/cli/commands/desktop.ts
104
160
  function emit(ev, tabId) {
105
161
  const payload = tabId ? { ...ev, tabId } : ev;
106
162
  writeSync(1, Buffer.from(`${JSON.stringify(payload)}
@@ -179,6 +235,9 @@ function emitSettings(tab) {
179
235
  tab.id
180
236
  );
181
237
  }
238
+ function emitQQSettings(tab) {
239
+ emit({ type: "$qq_settings", ...loadDesktopQQState() }, tab.id);
240
+ }
182
241
  async function emitBalance(tab) {
183
242
  if (!tab.runtime) return;
184
243
  const bal = await tab.runtime.loop.client.getBalance().catch(() => null);
@@ -418,6 +477,7 @@ async function desktopCommand(opts) {
418
477
  installDesktopCrashGuards();
419
478
  const tabs = /* @__PURE__ */ new Map();
420
479
  const tabContext = new AsyncLocalStorage();
480
+ let lastActiveTabId = "";
421
481
  function activeRunningTab() {
422
482
  const id = tabContext.getStore();
423
483
  return id ? tabs.get(id) : void 0;
@@ -519,7 +579,13 @@ async function desktopCommand(opts) {
519
579
  }
520
580
  function persistOpenTabs() {
521
581
  try {
522
- saveDesktopOpenTabs(Array.from(tabs.values()).map((t) => t.rootDir));
582
+ saveDesktopOpenTabs(
583
+ Array.from(tabs.values()).map((t) => ({
584
+ dir: t.rootDir,
585
+ session: t.currentSession || void 0,
586
+ active: t.id === lastActiveTabId
587
+ }))
588
+ );
523
589
  } catch {
524
590
  }
525
591
  }
@@ -622,6 +688,7 @@ async function desktopCommand(opts) {
622
688
  emitSessions(tab);
623
689
  emitSettings(tab);
624
690
  emitSkills(tab);
691
+ persistOpenTabs();
625
692
  }
626
693
  function forgetGate(id) {
627
694
  for (const t of tabs.values()) {
@@ -849,14 +916,44 @@ async function desktopCommand(opts) {
849
916
  if (tab) tab.pendingGateIds.delete(req.id);
850
917
  pauseGate.cancel(req.id);
851
918
  });
852
- function bootstrapTab(initialDir) {
919
+ function bootstrapTab(initialDir, restore) {
853
920
  const tab = createTabSkeleton(initialDir);
854
- emit({ type: "$tab_opened", workspaceDir: tab.rootDir }, tab.id);
921
+ let restoredMessages;
922
+ if (restore?.session) {
923
+ try {
924
+ if (existsSync(sessionPath(restore.session))) {
925
+ const msgs = buildLoadedMessages(loadSessionMessages(restore.session));
926
+ if (msgs.length > 0) {
927
+ tab.currentSession = restore.session;
928
+ restoredMessages = msgs;
929
+ }
930
+ }
931
+ } catch {
932
+ }
933
+ }
934
+ emit({ type: "$tab_opened", workspaceDir: tab.rootDir, active: restore?.active }, tab.id);
855
935
  emitSessions(tab);
856
936
  emitSettings(tab);
857
937
  emitMcpSpecs(tab);
858
938
  emitSkills(tab);
859
939
  emitMemory(tab);
940
+ emitQQSettings(tab);
941
+ if (restoredMessages) {
942
+ const meta = loadSessionMeta(tab.currentSession);
943
+ emit(
944
+ {
945
+ type: "$session_loaded",
946
+ name: tab.currentSession,
947
+ messages: restoredMessages,
948
+ carryover: {
949
+ totalCostUsd: meta.totalCostUsd ?? 0,
950
+ cacheHitTokens: meta.cacheHitTokens ?? 0,
951
+ cacheMissTokens: meta.cacheMissTokens ?? 0
952
+ }
953
+ },
954
+ tab.id
955
+ );
956
+ }
860
957
  if (!loadApiKey()) emit({ type: "$needs_setup", reason: "no_api_key" }, tab.id);
861
958
  void emitBalance(tab);
862
959
  void initTabToolset(tab).then(() => {
@@ -867,18 +964,18 @@ async function desktopCommand(opts) {
867
964
  });
868
965
  return tab;
869
966
  }
870
- const savedTabDirs = opts.dir ? [] : loadDesktopOpenTabs().filter((d) => {
967
+ const savedTabs = opts.dir ? [] : loadDesktopOpenTabs().filter((t) => {
871
968
  try {
872
- return existsSync(d) && statSync(d).isDirectory();
969
+ return existsSync(t.dir) && statSync(t.dir).isDirectory();
873
970
  } catch {
874
971
  return false;
875
972
  }
876
973
  });
877
- first = bootstrapTab(savedTabDirs[0]);
878
- for (const d of savedTabDirs.slice(1)) {
879
- if (resolve(d) === first.rootDir) continue;
880
- bootstrapTab(d);
881
- }
974
+ first = bootstrapTab(savedTabs[0]?.dir, savedTabs[0]);
975
+ const restored = [first];
976
+ for (const t of savedTabs.slice(1)) restored.push(bootstrapTab(t.dir, t));
977
+ const activeIdx = savedTabs.findIndex((t) => t.active);
978
+ lastActiveTabId = ((activeIdx >= 0 ? restored[activeIdx] : first) ?? first).id;
882
979
  persistOpenTabs();
883
980
  const rl = createInterface({ input: stdin });
884
981
  rl.on("line", (line) => {
@@ -893,13 +990,21 @@ async function desktopCommand(opts) {
893
990
  }
894
991
  if (msg.cmd === "tab_open") {
895
992
  try {
896
- bootstrapTab(msg.workspaceDir);
993
+ const opened = bootstrapTab(msg.workspaceDir, { active: true });
994
+ lastActiveTabId = opened.id;
897
995
  persistOpenTabs();
898
996
  } catch (err) {
899
997
  emit({ type: "$error", message: `tab_open failed: ${err.message}` });
900
998
  }
901
999
  return;
902
1000
  }
1001
+ if (msg.cmd === "tab_activate") {
1002
+ if (tabs.has(msg.tabId)) {
1003
+ lastActiveTabId = msg.tabId;
1004
+ persistOpenTabs();
1005
+ }
1006
+ return;
1007
+ }
903
1008
  if (msg.cmd === "confirm_response") {
904
1009
  forgetGate(msg.id);
905
1010
  pauseGate.resolve(msg.id, msg.response);
@@ -977,7 +1082,10 @@ async function desktopCommand(opts) {
977
1082
  }
978
1083
  const tab = msg.tabId ? tabs.get(msg.tabId) : first;
979
1084
  if (!tab) {
980
- emit({ type: "$error", message: `unknown tab: ${msg.tabId}` });
1085
+ process.stderr.write(
1086
+ `rpc dispatch: unknown tabId=${msg.tabId} for cmd=${msg.cmd} \u2014 dropping
1087
+ `
1088
+ );
981
1089
  return;
982
1090
  }
983
1091
  if (msg.cmd === "abort") {
@@ -1088,12 +1196,26 @@ ${found.body}${argsLine}`;
1088
1196
  abortTurn(tab);
1089
1197
  cancelPendingGates(tab);
1090
1198
  tab.currentSession = msg.name;
1199
+ persistOpenTabs();
1091
1200
  if (tab.runtime) tab.runtime = buildRuntimeFor(tab);
1201
+ const loadedMessages = buildLoadedMessages(records);
1202
+ if (loadedMessages.length === 0) {
1203
+ let sizeBytes = 0;
1204
+ try {
1205
+ sizeBytes = statSync(sessionPath(msg.name)).size;
1206
+ } catch {
1207
+ }
1208
+ process.stderr.write(
1209
+ `session_load: "${msg.name}" returned 0 messages (file size=${sizeBytes}B) \u2014 empty or unreadable jsonl
1210
+ `
1211
+ );
1212
+ emit({ type: "$session_empty", name: msg.name, sizeBytes }, tab.id);
1213
+ }
1092
1214
  emit(
1093
1215
  {
1094
1216
  type: "$session_loaded",
1095
1217
  name: msg.name,
1096
- messages: buildLoadedMessages(records),
1218
+ messages: loadedMessages,
1097
1219
  carryover: {
1098
1220
  totalCostUsd: meta.totalCostUsd ?? 0,
1099
1221
  cacheHitTokens: meta.cacheHitTokens ?? 0,
@@ -1103,6 +1225,8 @@ ${found.body}${argsLine}`;
1103
1225
  tab.id
1104
1226
  );
1105
1227
  } catch (err) {
1228
+ process.stderr.write(`session_load: "${msg.name}" threw \u2014 ${err.message}
1229
+ `);
1106
1230
  emit({ type: "$error", message: `session_load failed: ${err.message}` }, tab.id);
1107
1231
  }
1108
1232
  return;
@@ -1111,6 +1235,7 @@ ${found.body}${argsLine}`;
1111
1235
  abortTurn(tab);
1112
1236
  cancelPendingGates(tab);
1113
1237
  tab.currentSession = mintSessionFor(tab.rootDir);
1238
+ persistOpenTabs();
1114
1239
  if (tab.runtime) tab.runtime = buildRuntimeFor(tab);
1115
1240
  emitSessions(tab);
1116
1241
  return;
@@ -1119,6 +1244,10 @@ ${found.body}${argsLine}`;
1119
1244
  emitSettings(tab);
1120
1245
  return;
1121
1246
  }
1247
+ if (msg.cmd === "qq_status_get") {
1248
+ emitQQSettings(tab);
1249
+ return;
1250
+ }
1122
1251
  if (msg.cmd === "settings_save") {
1123
1252
  try {
1124
1253
  if (msg.reasoningEffort !== void 0) {
@@ -1158,6 +1287,68 @@ ${found.body}${argsLine}`;
1158
1287
  }
1159
1288
  return;
1160
1289
  }
1290
+ if (msg.cmd === "qq_config_save") {
1291
+ try {
1292
+ saveDesktopQQSettings(
1293
+ {
1294
+ appId: msg.appId,
1295
+ appSecret: msg.appSecret,
1296
+ sandbox: msg.sandbox
1297
+ },
1298
+ void 0
1299
+ );
1300
+ emitQQSettings(tab);
1301
+ } catch (err) {
1302
+ emit(
1303
+ { type: "$error", message: `qq_config_save failed: ${err.message}` },
1304
+ tab.id
1305
+ );
1306
+ }
1307
+ return;
1308
+ }
1309
+ if (msg.cmd === "qq_connect") {
1310
+ try {
1311
+ const current = loadQQConfig();
1312
+ setDesktopQQEnabled(true);
1313
+ emit(
1314
+ {
1315
+ type: "status",
1316
+ id: Date.now(),
1317
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
1318
+ turn: 0,
1319
+ text: `QQ enabled (${current.sandbox ? "sandbox" : "production"})`
1320
+ },
1321
+ tab.id
1322
+ );
1323
+ emitQQSettings(tab);
1324
+ } catch (err) {
1325
+ emit({ type: "$error", message: `qq_connect failed: ${err.message}` }, tab.id);
1326
+ emitQQSettings(tab);
1327
+ }
1328
+ return;
1329
+ }
1330
+ if (msg.cmd === "qq_disconnect") {
1331
+ try {
1332
+ setDesktopQQEnabled(false);
1333
+ emit(
1334
+ {
1335
+ type: "status",
1336
+ id: Date.now(),
1337
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
1338
+ turn: 0,
1339
+ text: "QQ disabled"
1340
+ },
1341
+ tab.id
1342
+ );
1343
+ emitQQSettings(tab);
1344
+ } catch (err) {
1345
+ emit(
1346
+ { type: "$error", message: `qq_disconnect failed: ${err.message}` },
1347
+ tab.id
1348
+ );
1349
+ }
1350
+ return;
1351
+ }
1161
1352
  if (msg.cmd === "mention_query") {
1162
1353
  const nonce = msg.nonce;
1163
1354
  const query = msg.query;
@@ -1230,6 +1421,42 @@ ${found.body}${argsLine}`;
1230
1421
  });
1231
1422
  return;
1232
1423
  }
1424
+ if (msg.cmd === "compact_history") {
1425
+ if (!tab.runtime) return;
1426
+ void tab.runtime.loop.compactHistory().catch((err) => {
1427
+ emit({ type: "$error", message: `/compact failed: ${err.message}` }, tab.id);
1428
+ });
1429
+ return;
1430
+ }
1431
+ if (msg.cmd === "retry") {
1432
+ if (!tab.runtime) return;
1433
+ const prev = tab.runtime.loop.retryLastUser();
1434
+ if (prev) {
1435
+ emit({ type: "$retry_result", text: prev }, tab.id);
1436
+ }
1437
+ return;
1438
+ }
1439
+ if (msg.cmd === "btw") {
1440
+ if (!tab.runtime) return;
1441
+ const question = msg.text.trim();
1442
+ if (!question) return;
1443
+ void (async () => {
1444
+ try {
1445
+ const reply = await tab.runtime.loop.client.chat({
1446
+ model: tab.currentModel,
1447
+ messages: [
1448
+ { role: "system", content: tab.system },
1449
+ { role: "user", content: question }
1450
+ ]
1451
+ });
1452
+ const answer = (typeof reply.content === "string" ? reply.content.trim() : "") || "(no answer)";
1453
+ emit({ type: "$btw_result", question, answer }, tab.id);
1454
+ } catch (err) {
1455
+ emit({ type: "$error", message: `/btw failed: ${err.message}` }, tab.id);
1456
+ }
1457
+ })();
1458
+ return;
1459
+ }
1233
1460
  if (msg.cmd === "user_input") {
1234
1461
  if (!tab.runtime) {
1235
1462
  emit(
@@ -1252,4 +1479,4 @@ export {
1252
1479
  desktopCommand,
1253
1480
  installDesktopCrashGuards
1254
1481
  };
1255
- //# sourceMappingURL=desktop-5ONTRU3C.js.map
1482
+ //# sourceMappingURL=desktop-7NCHPEFB.js.map