reasonix 0.51.0 → 0.52.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 (143) hide show
  1. package/dashboard/dist/app.css +1 -1
  2. package/dashboard/dist/app.js +3 -3
  3. package/dashboard/dist/app.js.map +1 -1
  4. package/dist/cli/{acp-XEUHGG7X.js → acp-NEUYWGUU.js} +26 -26
  5. package/dist/cli/chat-QA6IVFJD.js +49 -0
  6. package/dist/cli/{chunk-HGK57NBN.js → chunk-2W4F3RIZ.js} +2 -2
  7. package/dist/cli/{chunk-UO6E7FN3.js → chunk-3OXD5CBM.js} +32756 -31192
  8. package/dist/cli/chunk-3OXD5CBM.js.map +1 -0
  9. package/dist/cli/{chunk-UMZ6KHTS.js → chunk-5YLEKX2V.js} +2 -2
  10. package/dist/cli/{chunk-BA5R6BAE.js → chunk-6QBUXA73.js} +2 -2
  11. package/dist/cli/chunk-77JIQ7SL.js +40 -0
  12. package/dist/cli/chunk-77JIQ7SL.js.map +1 -0
  13. package/dist/cli/{chunk-6XWXIVQ3.js → chunk-AMSK3ZLB.js} +2 -2
  14. package/dist/cli/chunk-AMSK3ZLB.js.map +1 -0
  15. package/dist/cli/{chunk-A5PBEIJ7.js → chunk-AOYUW3HR.js} +37 -4
  16. package/dist/cli/chunk-AOYUW3HR.js.map +1 -0
  17. package/dist/cli/{chunk-3YRTIWFX.js → chunk-ARBGTNHM.js} +2 -2
  18. package/dist/cli/{chunk-3BTK5BHI.js → chunk-B4MOGWHW.js} +2 -2
  19. package/dist/cli/{chunk-5AIDYVH2.js → chunk-CFJY64UA.js} +2 -2
  20. package/dist/cli/{chunk-SBHF5NWD.js → chunk-CGVW5W7N.js} +14 -14
  21. package/dist/cli/{chunk-SBHF5NWD.js.map → chunk-CGVW5W7N.js.map} +1 -1
  22. package/dist/cli/{chunk-DVD67FXQ.js → chunk-CLHMV6OL.js} +568 -66
  23. package/dist/cli/chunk-CLHMV6OL.js.map +1 -0
  24. package/dist/cli/{chunk-2WUEAI2I.js → chunk-CPCUMMSR.js} +3 -3
  25. package/dist/cli/{chunk-JHWQDJZA.js → chunk-CTRM32BP.js} +2 -2
  26. package/dist/cli/{chunk-544J4PXD.js → chunk-D6WRFR6V.js} +5 -5
  27. package/dist/cli/{chunk-N4SEBLU4.js → chunk-DLTE4GBY.js} +3 -3
  28. package/dist/cli/{chunk-NRROJXXT.js → chunk-FY5UERSG.js} +9 -9
  29. package/dist/cli/{chunk-C2MRSJTV.js → chunk-GFJJEW3Z.js} +18 -10
  30. package/dist/cli/chunk-GFJJEW3Z.js.map +1 -0
  31. package/dist/cli/{chunk-R6KIHEF3.js → chunk-GNRKXRRE.js} +743 -660
  32. package/dist/cli/chunk-GNRKXRRE.js.map +1 -0
  33. package/dist/cli/{chunk-SXSAWOB7.js → chunk-HI6THNAZ.js} +19 -17
  34. package/dist/cli/chunk-HI6THNAZ.js.map +1 -0
  35. package/dist/cli/{chunk-K4YQFULP.js → chunk-HNZ4727T.js} +15 -15
  36. package/dist/cli/chunk-I3NE5S63.js +54 -0
  37. package/dist/cli/{chunk-EAMXOWUW.js.map → chunk-I3NE5S63.js.map} +1 -1
  38. package/dist/cli/{chunk-FEZK652I.js → chunk-MVLPXZAA.js} +834 -10
  39. package/dist/cli/chunk-MVLPXZAA.js.map +1 -0
  40. package/dist/cli/{chunk-36BM7INR.js → chunk-MW64SQUE.js} +2 -2
  41. package/dist/cli/{chunk-Z3MKG7MQ.js → chunk-OMNRXZNA.js} +2 -2
  42. package/dist/cli/{chunk-7YPMTE3U.js → chunk-RCC73DWQ.js} +5 -9
  43. package/dist/cli/chunk-RCC73DWQ.js.map +1 -0
  44. package/dist/cli/{chunk-2HVTBFCI.js → chunk-RHQOGG43.js} +5 -3
  45. package/dist/cli/chunk-RHQOGG43.js.map +1 -0
  46. package/dist/cli/{chunk-EWVFGYT6.js → chunk-VVPV5HU6.js} +2 -2
  47. package/dist/cli/{chunk-7YB26OQO.js → chunk-WPY7AFS6.js} +2 -2
  48. package/dist/cli/{chunk-BM6BBFAV.js → chunk-XBYHNZ5Z.js} +2 -2
  49. package/dist/cli/{chunk-WPOKBW5E.js → chunk-XNMXVL6C.js} +2 -2
  50. package/dist/cli/{chunk-SVD4UPRQ.js → chunk-XUZHBQSM.js} +2 -2
  51. package/dist/cli/{chunk-Q46B3Z7H.js → chunk-YMYX6QTC.js} +8 -5
  52. package/dist/cli/{chunk-Q46B3Z7H.js.map → chunk-YMYX6QTC.js.map} +1 -1
  53. package/dist/cli/{chunk-K3QJ3GKI.js → chunk-Z663GVUB.js} +3 -3
  54. package/dist/cli/{code-BMXLBC7D.js → code-WN6D4VZO.js} +35 -36
  55. package/dist/cli/{code-BMXLBC7D.js.map → code-WN6D4VZO.js.map} +1 -1
  56. package/dist/cli/{commands-E4RZXMF6.js → commands-DHETOY7O.js} +4 -4
  57. package/dist/cli/{commit-KSRQ64IL.js → commit-BBUYAKZV.js} +3 -3
  58. package/dist/cli/{config-QNDONOTU.js → config-KV7VV5LG.js} +4 -2
  59. package/dist/cli/{desktop-H3ZHIMDA.js → desktop-LJVXWXNF.js} +557 -70
  60. package/dist/cli/desktop-LJVXWXNF.js.map +1 -0
  61. package/dist/cli/diff-2JHMQAHI.js +165 -0
  62. package/dist/cli/{diff-I4PYI43W.js.map → diff-2JHMQAHI.js.map} +1 -1
  63. package/dist/cli/{doctor-Y2E4MY2F.js → doctor-GI5LOEZL.js} +11 -11
  64. package/dist/cli/{events-47HOT7ZA.js → events-LBKMLFM4.js} +5 -5
  65. package/dist/cli/index.js +40 -39
  66. package/dist/cli/index.js.map +1 -1
  67. package/dist/cli/{mcp-76DK63ZB.js → mcp-DKEJK5ND.js} +3 -3
  68. package/dist/cli/{mcp-browse-SDNUGO74.js → mcp-browse-V7KWDY32.js} +15 -15
  69. package/dist/cli/{mcp-browse-SDNUGO74.js.map → mcp-browse-V7KWDY32.js.map} +1 -1
  70. package/dist/cli/{mcp-inspect-BL5DEO5M.js → mcp-inspect-MTABNHVM.js} +5 -5
  71. package/dist/cli/{prompt-JLATI3P7.js → prompt-ATI7DKHF.js} +5 -5
  72. package/dist/cli/{prune-sessions-WHZDFUKD.js → prune-sessions-YQQSZTZS.js} +4 -4
  73. package/dist/cli/{replay-MHXS7C7Z.js → replay-ZJQ4I4CJ.js} +30 -30
  74. package/dist/cli/{replay-MHXS7C7Z.js.map → replay-ZJQ4I4CJ.js.map} +1 -1
  75. package/dist/cli/{run-SXNCPRJE.js → run-HFPRNWJY.js} +22 -22
  76. package/dist/cli/{server-GEHOE6CO.js → server-UHKO2VVM.js} +23 -23
  77. package/dist/cli/{sessions-EPBFYISL.js → sessions-IQEWWUH3.js} +16 -16
  78. package/dist/cli/setup-5BYKCL62.js +502 -0
  79. package/dist/cli/setup-5BYKCL62.js.map +1 -0
  80. package/dist/cli/{stats-4WB4XHBP.js → stats-OFCGOQMZ.js} +6 -6
  81. package/dist/cli/{version-4SP3DLLH.js → version-EODUFAAI.js} +16 -16
  82. package/dist/index.d.ts +12 -1
  83. package/dist/index.js +613 -78
  84. package/dist/index.js.map +1 -1
  85. package/package.json +21 -3
  86. package/dist/cli/chat-NJ2Q5KHG.js +0 -50
  87. package/dist/cli/chunk-2HVTBFCI.js.map +0 -1
  88. package/dist/cli/chunk-5BBC6YMV.js +0 -832
  89. package/dist/cli/chunk-5BBC6YMV.js.map +0 -1
  90. package/dist/cli/chunk-6XWXIVQ3.js.map +0 -1
  91. package/dist/cli/chunk-7YPMTE3U.js.map +0 -1
  92. package/dist/cli/chunk-A5PBEIJ7.js.map +0 -1
  93. package/dist/cli/chunk-C2MRSJTV.js.map +0 -1
  94. package/dist/cli/chunk-DVD67FXQ.js.map +0 -1
  95. package/dist/cli/chunk-EAMXOWUW.js +0 -54
  96. package/dist/cli/chunk-FEZK652I.js.map +0 -1
  97. package/dist/cli/chunk-R6KIHEF3.js.map +0 -1
  98. package/dist/cli/chunk-SXSAWOB7.js.map +0 -1
  99. package/dist/cli/chunk-UO6E7FN3.js.map +0 -1
  100. package/dist/cli/chunk-UPW544V3.js +0 -96
  101. package/dist/cli/chunk-UPW544V3.js.map +0 -1
  102. package/dist/cli/desktop-H3ZHIMDA.js.map +0 -1
  103. package/dist/cli/devtools-HW3WDT3Q.js +0 -91
  104. package/dist/cli/devtools-HW3WDT3Q.js.map +0 -1
  105. package/dist/cli/diff-I4PYI43W.js +0 -165
  106. package/dist/cli/setup-IW2XR5XI.js +0 -593
  107. package/dist/cli/setup-IW2XR5XI.js.map +0 -1
  108. /package/dist/cli/{acp-XEUHGG7X.js.map → acp-NEUYWGUU.js.map} +0 -0
  109. /package/dist/cli/{chat-NJ2Q5KHG.js.map → chat-QA6IVFJD.js.map} +0 -0
  110. /package/dist/cli/{chunk-HGK57NBN.js.map → chunk-2W4F3RIZ.js.map} +0 -0
  111. /package/dist/cli/{chunk-UMZ6KHTS.js.map → chunk-5YLEKX2V.js.map} +0 -0
  112. /package/dist/cli/{chunk-BA5R6BAE.js.map → chunk-6QBUXA73.js.map} +0 -0
  113. /package/dist/cli/{chunk-3YRTIWFX.js.map → chunk-ARBGTNHM.js.map} +0 -0
  114. /package/dist/cli/{chunk-3BTK5BHI.js.map → chunk-B4MOGWHW.js.map} +0 -0
  115. /package/dist/cli/{chunk-5AIDYVH2.js.map → chunk-CFJY64UA.js.map} +0 -0
  116. /package/dist/cli/{chunk-2WUEAI2I.js.map → chunk-CPCUMMSR.js.map} +0 -0
  117. /package/dist/cli/{chunk-JHWQDJZA.js.map → chunk-CTRM32BP.js.map} +0 -0
  118. /package/dist/cli/{chunk-544J4PXD.js.map → chunk-D6WRFR6V.js.map} +0 -0
  119. /package/dist/cli/{chunk-N4SEBLU4.js.map → chunk-DLTE4GBY.js.map} +0 -0
  120. /package/dist/cli/{chunk-NRROJXXT.js.map → chunk-FY5UERSG.js.map} +0 -0
  121. /package/dist/cli/{chunk-K4YQFULP.js.map → chunk-HNZ4727T.js.map} +0 -0
  122. /package/dist/cli/{chunk-36BM7INR.js.map → chunk-MW64SQUE.js.map} +0 -0
  123. /package/dist/cli/{chunk-Z3MKG7MQ.js.map → chunk-OMNRXZNA.js.map} +0 -0
  124. /package/dist/cli/{chunk-EWVFGYT6.js.map → chunk-VVPV5HU6.js.map} +0 -0
  125. /package/dist/cli/{chunk-7YB26OQO.js.map → chunk-WPY7AFS6.js.map} +0 -0
  126. /package/dist/cli/{chunk-BM6BBFAV.js.map → chunk-XBYHNZ5Z.js.map} +0 -0
  127. /package/dist/cli/{chunk-WPOKBW5E.js.map → chunk-XNMXVL6C.js.map} +0 -0
  128. /package/dist/cli/{chunk-SVD4UPRQ.js.map → chunk-XUZHBQSM.js.map} +0 -0
  129. /package/dist/cli/{chunk-K3QJ3GKI.js.map → chunk-Z663GVUB.js.map} +0 -0
  130. /package/dist/cli/{commands-E4RZXMF6.js.map → commands-DHETOY7O.js.map} +0 -0
  131. /package/dist/cli/{commit-KSRQ64IL.js.map → commit-BBUYAKZV.js.map} +0 -0
  132. /package/dist/cli/{config-QNDONOTU.js.map → config-KV7VV5LG.js.map} +0 -0
  133. /package/dist/cli/{doctor-Y2E4MY2F.js.map → doctor-GI5LOEZL.js.map} +0 -0
  134. /package/dist/cli/{events-47HOT7ZA.js.map → events-LBKMLFM4.js.map} +0 -0
  135. /package/dist/cli/{mcp-76DK63ZB.js.map → mcp-DKEJK5ND.js.map} +0 -0
  136. /package/dist/cli/{mcp-inspect-BL5DEO5M.js.map → mcp-inspect-MTABNHVM.js.map} +0 -0
  137. /package/dist/cli/{prompt-JLATI3P7.js.map → prompt-ATI7DKHF.js.map} +0 -0
  138. /package/dist/cli/{prune-sessions-WHZDFUKD.js.map → prune-sessions-YQQSZTZS.js.map} +0 -0
  139. /package/dist/cli/{run-SXNCPRJE.js.map → run-HFPRNWJY.js.map} +0 -0
  140. /package/dist/cli/{server-GEHOE6CO.js.map → server-UHKO2VVM.js.map} +0 -0
  141. /package/dist/cli/{sessions-EPBFYISL.js.map → sessions-IQEWWUH3.js.map} +0 -0
  142. /package/dist/cli/{stats-4WB4XHBP.js.map → stats-OFCGOQMZ.js.map} +0 -0
  143. /package/dist/cli/{version-4SP3DLLH.js.map → version-EODUFAAI.js.map} +0 -0
@@ -3,22 +3,22 @@ import { createRequire as __cr } from 'node:module'; if (typeof globalThis.requi
3
3
  import {
4
4
  collectMemoryEntriesForWorkspace,
5
5
  readMemoryEntryDetail
6
- } from "./chunk-JHWQDJZA.js";
6
+ } from "./chunk-CTRM32BP.js";
7
7
  import {
8
8
  QQChannel,
9
9
  createMcpRuntime
10
- } from "./chunk-5BBC6YMV.js";
10
+ } from "./chunk-MVLPXZAA.js";
11
11
  import {
12
12
  applyPlanMode,
13
13
  buildCodeToolset
14
- } from "./chunk-NRROJXXT.js";
15
- import "./chunk-Z3MKG7MQ.js";
14
+ } from "./chunk-FY5UERSG.js";
15
+ import "./chunk-OMNRXZNA.js";
16
16
  import {
17
17
  Eventizer,
18
18
  autoResolveVerdict
19
- } from "./chunk-BM6BBFAV.js";
20
- import "./chunk-5AIDYVH2.js";
21
- import "./chunk-SVD4UPRQ.js";
19
+ } from "./chunk-XBYHNZ5Z.js";
20
+ import "./chunk-CFJY64UA.js";
21
+ import "./chunk-XUZHBQSM.js";
22
22
  import {
23
23
  CacheFirstLoop,
24
24
  ImmutablePrefix,
@@ -26,53 +26,55 @@ import {
26
26
  listFilesWithStatsAsync,
27
27
  parseAtQuery,
28
28
  rankPickerCandidates
29
- } from "./chunk-K4YQFULP.js";
30
- import "./chunk-7YPMTE3U.js";
31
- import "./chunk-36BM7INR.js";
32
- import "./chunk-544J4PXD.js";
29
+ } from "./chunk-HNZ4727T.js";
30
+ import "./chunk-MW64SQUE.js";
31
+ import "./chunk-D6WRFR6V.js";
32
+ import "./chunk-RCC73DWQ.js";
33
33
  import {
34
34
  pauseGate,
35
35
  toApprovalPrompt
36
- } from "./chunk-UMZ6KHTS.js";
37
- import "./chunk-3YRTIWFX.js";
38
- import "./chunk-BA5R6BAE.js";
36
+ } from "./chunk-5YLEKX2V.js";
39
37
  import {
40
38
  codeSystemPrompt
41
- } from "./chunk-HGK57NBN.js";
39
+ } from "./chunk-2W4F3RIZ.js";
42
40
  import {
43
41
  SkillStore
44
- } from "./chunk-N4SEBLU4.js";
45
- import "./chunk-FEZK652I.js";
42
+ } from "./chunk-DLTE4GBY.js";
46
43
  import "./chunk-PLHAZOLZ.js";
47
44
  import "./chunk-L3VPEESB.js";
48
- import "./chunk-7YB26OQO.js";
45
+ import "./chunk-WPY7AFS6.js";
49
46
  import {
50
47
  countTokensBounded
51
48
  } from "./chunk-BOWSNGQC.js";
52
- import {
53
- DeepSeekClient,
54
- pickPrimaryBalance
55
- } from "./chunk-C2MRSJTV.js";
56
- import "./chunk-25T6CVUP.js";
57
- import "./chunk-2WUEAI2I.js";
49
+ import "./chunk-CPCUMMSR.js";
58
50
  import "./chunk-6UNHNVJR.js";
59
51
  import {
60
52
  deleteSession,
53
+ detectGitBranch,
61
54
  listSessionsForWorkspace,
62
55
  loadSessionMessages,
63
56
  loadSessionMeta,
64
57
  patchSessionMeta,
65
58
  patchSessionWorkspaceIfMissing,
59
+ rewriteSession,
66
60
  sessionPath,
61
+ sessionsDir,
67
62
  timestampSuffix
68
- } from "./chunk-6XWXIVQ3.js";
63
+ } from "./chunk-AMSK3ZLB.js";
69
64
  import {
70
65
  VERSION
71
66
  } from "./chunk-XXC2BYTV.js";
67
+ import {
68
+ DeepSeekClient,
69
+ pickPrimaryBalance
70
+ } from "./chunk-GFJJEW3Z.js";
71
+ import "./chunk-25T6CVUP.js";
72
72
  import {
73
73
  loadDotenv
74
74
  } from "./chunk-2UQP6H6T.js";
75
- import "./chunk-DVD67FXQ.js";
75
+ import "./chunk-ARBGTNHM.js";
76
+ import "./chunk-6QBUXA73.js";
77
+ import "./chunk-CLHMV6OL.js";
76
78
  import {
77
79
  DEFAULT_MODEL,
78
80
  bridgeEndpointEnv,
@@ -84,13 +86,17 @@ import {
84
86
  loadEditMode,
85
87
  loadEditor,
86
88
  loadEndpoint,
89
+ loadExaApiKey,
90
+ loadMetasoApiKey,
87
91
  loadModel,
92
+ loadPerplexityApiKey,
88
93
  loadQQConfig,
89
94
  loadReasoningEffort,
90
95
  loadRecentWorkspaces,
91
96
  loadResolvedSkillPaths,
92
97
  loadShowSystemEvents,
93
98
  loadSubagentModels,
99
+ loadTavilyApiKey,
94
100
  loadWorkspaceDir,
95
101
  parseMcpSpec,
96
102
  pushRecentWorkspace,
@@ -108,14 +114,14 @@ import {
108
114
  saveWorkspaceDir,
109
115
  webSearchEngine,
110
116
  writeConfig
111
- } from "./chunk-A5PBEIJ7.js";
117
+ } from "./chunk-AOYUW3HR.js";
112
118
  import "./chunk-TUK7OWJA.js";
113
119
 
114
120
  // src/cli/commands/desktop.ts
115
121
  import { AsyncLocalStorage } from "async_hooks";
116
- import { existsSync, statSync, writeSync } from "fs";
122
+ import { existsSync as existsSync2, statSync as statSync2, writeSync } from "fs";
117
123
  import { readFile } from "fs/promises";
118
- import { isAbsolute, join, resolve } from "path";
124
+ import { isAbsolute, join as join2, resolve } from "path";
119
125
  import { stdin } from "process";
120
126
  import { createInterface } from "readline";
121
127
 
@@ -249,6 +255,386 @@ function clearQQTurnRouting(state) {
249
255
  state.pendingByTab.clear();
250
256
  }
251
257
 
258
+ // src/session-import.ts
259
+ import { existsSync, readFileSync, readdirSync, statSync } from "fs";
260
+ import { homedir } from "os";
261
+ import { basename, extname, join } from "path";
262
+ function parseExternalSessionFile(source, path) {
263
+ if (!existsSync(path)) {
264
+ throw new Error(`source file not found: ${path}`);
265
+ }
266
+ return source === "claude" ? parseClaudeSessionFile(path) : parseCodexSessionFile(path);
267
+ }
268
+ function buildImportedSessionName(source, path, imported) {
269
+ const stem = basename(path, extname(path));
270
+ const hint = oneLine(imported.nameHint || imported.summary || stem, 48);
271
+ return `${source}-${hint || stem || "session"}`;
272
+ }
273
+ function importExternalSession(opts) {
274
+ const imported = parseExternalSessionFile(opts.source, opts.path);
275
+ if (imported.messages.length === 0) {
276
+ throw new Error(`no importable chat messages found in ${opts.path}`);
277
+ }
278
+ const name = opts.name?.trim() || buildImportedSessionName(opts.source, opts.path, imported);
279
+ const outputPath = sessionPath(name);
280
+ if (existsSync(outputPath) && !opts.force) {
281
+ throw new Error(`target session already exists: ${name}`);
282
+ }
283
+ rewriteSession(name, imported.messages);
284
+ const workspace = opts.workspace?.trim() || imported.workspace;
285
+ const summary = opts.summary?.trim() || imported.summary;
286
+ const branch = workspace ? detectGitBranch(workspace) : void 0;
287
+ patchSessionMeta(name, {
288
+ workspace,
289
+ summary,
290
+ branch,
291
+ importedSource: opts.source,
292
+ importedPath: opts.path
293
+ });
294
+ return {
295
+ source: opts.source,
296
+ path: opts.path,
297
+ name,
298
+ messageCount: imported.messages.length,
299
+ workspace,
300
+ summary,
301
+ branch
302
+ };
303
+ }
304
+ function discoverExternalSessionApps() {
305
+ return ["claude", "codex"].map((source) => {
306
+ const root = defaultSessionRoot(source);
307
+ const files = scanExternalSessionFiles(source);
308
+ const latest = files[0];
309
+ return {
310
+ source,
311
+ label: source === "claude" ? "Claude Code" : "Codex",
312
+ root,
313
+ available: files.length > 0,
314
+ sessionCount: files.length,
315
+ latestMtime: latest ? new Date(latest.mtimeMs).toISOString() : void 0
316
+ };
317
+ });
318
+ }
319
+ function importExternalSessions(opts) {
320
+ let imported = 0;
321
+ let skipped = 0;
322
+ let failed = 0;
323
+ let latestName;
324
+ const existing = importedPathKeys();
325
+ for (const source of opts.sources) {
326
+ const files = scanExternalSessionFiles(source);
327
+ for (const file of files) {
328
+ const key = importKey(source, file.path);
329
+ if (existing.has(key)) {
330
+ skipped++;
331
+ continue;
332
+ }
333
+ try {
334
+ const result = importExternalSession({
335
+ source,
336
+ path: file.path,
337
+ workspace: opts.workspace
338
+ });
339
+ existing.add(key);
340
+ imported++;
341
+ latestName ||= result.name;
342
+ } catch {
343
+ failed++;
344
+ }
345
+ }
346
+ }
347
+ return { imported, skipped, failed, latestName };
348
+ }
349
+ function defaultSessionRoot(source) {
350
+ return source === "claude" ? join(homedir(), ".claude", "projects") : join(homedir(), ".codex", "sessions");
351
+ }
352
+ function scanExternalSessionFiles(source) {
353
+ const root = defaultSessionRoot(source);
354
+ const out = [];
355
+ collectJsonl(root, source, out);
356
+ out.sort((a, b) => b.mtimeMs - a.mtimeMs);
357
+ return out;
358
+ }
359
+ function collectJsonl(dir, source, out) {
360
+ if (!existsSync(dir)) return;
361
+ let entries;
362
+ try {
363
+ entries = readdirSync(dir);
364
+ } catch {
365
+ return;
366
+ }
367
+ for (const entry of entries) {
368
+ const path = join(dir, entry);
369
+ let stat;
370
+ try {
371
+ stat = statSync(path);
372
+ } catch {
373
+ continue;
374
+ }
375
+ if (stat.isDirectory()) {
376
+ collectJsonl(path, source, out);
377
+ } else if (stat.isFile() && entry.endsWith(".jsonl")) {
378
+ out.push({ source, path, mtimeMs: stat.mtimeMs });
379
+ }
380
+ }
381
+ }
382
+ function importedPathKeys() {
383
+ const out = /* @__PURE__ */ new Set();
384
+ const dir = sessionsDir();
385
+ if (!existsSync(dir)) return out;
386
+ let files;
387
+ try {
388
+ files = readdirSync(dir);
389
+ } catch {
390
+ return out;
391
+ }
392
+ for (const file of files) {
393
+ if (!file.endsWith(".jsonl") || file.endsWith(".events.jsonl")) continue;
394
+ const name = file.replace(/\.jsonl$/, "");
395
+ const meta = loadSessionMeta(name);
396
+ if (meta.importedSource && meta.importedPath) {
397
+ out.add(importKey(meta.importedSource, meta.importedPath));
398
+ }
399
+ }
400
+ return out;
401
+ }
402
+ function importKey(source, path) {
403
+ return `${source}:${path}`;
404
+ }
405
+ function parseClaudeSessionFile(path) {
406
+ const records = readJsonl(path);
407
+ const messages = [];
408
+ const toolNames = /* @__PURE__ */ new Map();
409
+ let workspace;
410
+ let firstUserText;
411
+ for (const record of records) {
412
+ if (!workspace) workspace = firstString(record.cwd) || firstString(record.project);
413
+ if (record.isMeta === true) continue;
414
+ if (!record.message || typeof record.message !== "object") continue;
415
+ const role = normalizeRole(record.message.role);
416
+ if (!role) continue;
417
+ if (role === "assistant") {
418
+ const assistant = normalizeClaudeAssistant(record.message.content);
419
+ for (const call of assistant.toolCalls) {
420
+ if (call.id && call.function?.name) toolNames.set(call.id, call.function.name);
421
+ }
422
+ if (assistant.content || assistant.toolCalls.length > 0) {
423
+ messages.push({
424
+ role: "assistant",
425
+ content: assistant.content || null,
426
+ tool_calls: assistant.toolCalls.length > 0 ? assistant.toolCalls : void 0,
427
+ reasoning_content: assistant.reasoning || void 0
428
+ });
429
+ }
430
+ continue;
431
+ }
432
+ const user = normalizeClaudeUser(record.message.content, toolNames);
433
+ if (user.content) {
434
+ messages.push({ role: "user", content: user.content });
435
+ if (!firstUserText) firstUserText = user.content;
436
+ }
437
+ messages.push(...user.toolMessages);
438
+ }
439
+ return {
440
+ messages,
441
+ workspace,
442
+ nameHint: firstUserText,
443
+ summary: summarize(firstUserText)
444
+ };
445
+ }
446
+ function parseCodexSessionFile(path) {
447
+ const records = readJsonl(path);
448
+ const messages = [];
449
+ const fallback = [];
450
+ let workspace;
451
+ let firstUserText;
452
+ for (const record of records) {
453
+ if (record.type === "session_meta" || record.type === "turn_context") {
454
+ workspace ||= firstString(record.payload?.cwd);
455
+ }
456
+ if (record.type === "response_item" && record.payload?.type === "message") {
457
+ const role = normalizeRole(record.payload.role);
458
+ if (!role) continue;
459
+ const content = normalizeCodexMessageContent(role, record.payload.content);
460
+ if (!content) continue;
461
+ messages.push({ role, content });
462
+ if (role === "user" && !firstUserText) firstUserText = content;
463
+ continue;
464
+ }
465
+ if (record.type === "event_msg") {
466
+ const eventType = firstString(record.payload?.type);
467
+ const content = firstString(record.payload?.message);
468
+ if (!content) continue;
469
+ if (eventType === "user_message") {
470
+ fallback.push({ role: "user", content });
471
+ if (!firstUserText) firstUserText = content;
472
+ } else if (eventType === "agent_message") {
473
+ fallback.push({ role: "assistant", content });
474
+ }
475
+ }
476
+ }
477
+ const importedMessages = messages.length > 0 ? messages : dedupeAdjacentMessages(fallback);
478
+ return {
479
+ messages: importedMessages,
480
+ workspace,
481
+ nameHint: firstUserText,
482
+ summary: summarize(firstUserText)
483
+ };
484
+ }
485
+ function normalizeClaudeAssistant(content) {
486
+ if (typeof content === "string") {
487
+ return { content: content.trim(), toolCalls: [] };
488
+ }
489
+ if (!Array.isArray(content)) {
490
+ return { content: "", toolCalls: [] };
491
+ }
492
+ const textParts = [];
493
+ const toolCalls = [];
494
+ const reasoningParts = [];
495
+ for (const item of content) {
496
+ if (!item || typeof item !== "object") continue;
497
+ const type = firstString(item.type);
498
+ if (type === "text") {
499
+ const text = firstString(item.text);
500
+ if (text) textParts.push(text);
501
+ continue;
502
+ }
503
+ if (type === "thinking") {
504
+ const text = firstString(item.thinking);
505
+ if (text) reasoningParts.push(text);
506
+ continue;
507
+ }
508
+ if (type === "tool_use") {
509
+ const name = firstString(item.name);
510
+ if (!name) continue;
511
+ toolCalls.push({
512
+ id: firstString(item.id),
513
+ type: "function",
514
+ function: {
515
+ name,
516
+ arguments: safeJson(item.input ?? {})
517
+ }
518
+ });
519
+ }
520
+ }
521
+ return {
522
+ content: joinParts(textParts),
523
+ toolCalls,
524
+ reasoning: joinParts(reasoningParts) || void 0
525
+ };
526
+ }
527
+ function normalizeClaudeUser(content, toolNames) {
528
+ if (typeof content === "string") {
529
+ return { content: content.trim(), toolMessages: [] };
530
+ }
531
+ if (!Array.isArray(content)) {
532
+ return { content: "", toolMessages: [] };
533
+ }
534
+ const userText = [];
535
+ const toolMessages = [];
536
+ for (const item of content) {
537
+ if (!item || typeof item !== "object") continue;
538
+ const type = firstString(item.type);
539
+ if (type === "text") {
540
+ const text = firstString(item.text);
541
+ if (text) userText.push(text);
542
+ continue;
543
+ }
544
+ if (type === "image") {
545
+ userText.push("[image omitted]");
546
+ continue;
547
+ }
548
+ if (type === "tool_result") {
549
+ const callId = firstString(item.tool_use_id);
550
+ toolMessages.push({
551
+ role: "tool",
552
+ content: normalizeArbitraryContent(item.content),
553
+ tool_call_id: callId,
554
+ name: callId ? toolNames.get(callId) : void 0
555
+ });
556
+ }
557
+ }
558
+ return { content: joinParts(userText), toolMessages };
559
+ }
560
+ function normalizeCodexMessageContent(role, content) {
561
+ if (typeof content === "string") return content.trim();
562
+ if (!Array.isArray(content)) return "";
563
+ const textParts = [];
564
+ for (const item of content) {
565
+ if (!item || typeof item !== "object") continue;
566
+ const type = firstString(item.type);
567
+ if (type === "input_text" || type === "output_text" || type === "text") {
568
+ const text = firstString(item.text);
569
+ if (!text) continue;
570
+ if (role === "user" && looksLikeCodexBootstrapBlock(text)) continue;
571
+ textParts.push(text);
572
+ }
573
+ }
574
+ return joinParts(textParts);
575
+ }
576
+ function looksLikeCodexBootstrapBlock(text) {
577
+ const trimmed = text.trimStart();
578
+ return trimmed.startsWith("# AGENTS.md instructions for ") || trimmed.startsWith("<environment_context>");
579
+ }
580
+ function dedupeAdjacentMessages(messages) {
581
+ const out = [];
582
+ for (const msg of messages) {
583
+ const prev = out[out.length - 1];
584
+ if (prev && prev.role === msg.role && prev.content === msg.content) continue;
585
+ out.push(msg);
586
+ }
587
+ return out;
588
+ }
589
+ function normalizeArbitraryContent(value) {
590
+ if (typeof value === "string") return value;
591
+ if (Array.isArray(value)) {
592
+ const textParts = value.map((item) => {
593
+ if (typeof item === "string") return item;
594
+ if (item && typeof item === "object") {
595
+ return firstString(item.text);
596
+ }
597
+ return "";
598
+ }).filter(Boolean);
599
+ if (textParts.length > 0) return joinParts(textParts);
600
+ }
601
+ return safeJson(value);
602
+ }
603
+ function readJsonl(path) {
604
+ const raw = readFileSync(path, "utf8");
605
+ return raw.split(/\r?\n/).map((line) => line.trim()).filter(Boolean).flatMap((line) => {
606
+ try {
607
+ return [JSON.parse(line)];
608
+ } catch {
609
+ return [];
610
+ }
611
+ });
612
+ }
613
+ function normalizeRole(value) {
614
+ return value === "user" || value === "assistant" ? value : void 0;
615
+ }
616
+ function firstString(value) {
617
+ return typeof value === "string" && value.trim().length > 0 ? value : void 0;
618
+ }
619
+ function safeJson(value) {
620
+ try {
621
+ return JSON.stringify(value ?? null);
622
+ } catch {
623
+ return JSON.stringify(String(value));
624
+ }
625
+ }
626
+ function joinParts(parts) {
627
+ return parts.map((part) => part.trim()).filter(Boolean).join("\n\n");
628
+ }
629
+ function summarize(text) {
630
+ const flat = oneLine(text || "", 120);
631
+ return flat || void 0;
632
+ }
633
+ function oneLine(text, max) {
634
+ const flat = text.replace(/\s+/g, " ").trim();
635
+ return flat.length > max ? `${flat.slice(0, max)}...` : flat;
636
+ }
637
+
252
638
  // src/cli/commands/desktop.ts
253
639
  var desktopQqRuntimeSnapshot = {
254
640
  runtimeState: "disconnected"
@@ -367,6 +753,19 @@ function buildLoadedMessages(records) {
367
753
  }
368
754
  return elideLoadedMessages(out);
369
755
  }
756
+ function maskApiKey(key) {
757
+ if (!key) return void 0;
758
+ if (key.length <= 7) return `${key.slice(0, 2)}\u2026`;
759
+ return `${key.slice(0, 6)}\u2026${key.slice(-3)}`;
760
+ }
761
+ function collectWebSearchApiKeyPrefixes() {
762
+ return {
763
+ metaso: maskApiKey(loadMetasoApiKey()),
764
+ tavily: maskApiKey(loadTavilyApiKey()),
765
+ perplexity: maskApiKey(loadPerplexityApiKey()),
766
+ exa: maskApiKey(loadExaApiKey())
767
+ };
768
+ }
370
769
  function emitSettings(tab) {
371
770
  const ep = loadEndpoint();
372
771
  const editMode = loadEditMode();
@@ -385,6 +784,8 @@ function emitSettings(tab) {
385
784
  model: tab.currentModel,
386
785
  editor: loadEditor(),
387
786
  webSearchEngine: webSearchEngine(),
787
+ webSearchEndpoint: readConfig().webSearchEndpoint,
788
+ webSearchApiKeys: collectWebSearchApiKeyPrefixes(),
388
789
  subagentModels: loadSubagentModels(),
389
790
  showSystemEvents: loadShowSystemEvents(),
390
791
  version: VERSION
@@ -434,6 +835,45 @@ function emitSessions(tab) {
434
835
  emit({ type: "$error", message: `session_list failed: ${err.message}` }, tab.id);
435
836
  }
436
837
  }
838
+ function loadSessionIntoTab(tab, name, actions) {
839
+ const records = loadSessionMessages(name);
840
+ const backfilledWorkspace = patchSessionWorkspaceIfMissing(name, tab.rootDir);
841
+ const meta = loadSessionMeta(name);
842
+ if (tab.aborter) tab.switching = true;
843
+ actions.abortTurn(tab);
844
+ actions.cancelPendingGates(tab);
845
+ tab.currentSession = name;
846
+ actions.persistOpenTabs();
847
+ if (tab.runtime) tab.runtime = buildRuntimeFor(tab);
848
+ const loadedMessages = buildLoadedMessages(records);
849
+ if (loadedMessages.length === 0) {
850
+ let sizeBytes = 0;
851
+ try {
852
+ sizeBytes = statSync2(sessionPath(name)).size;
853
+ } catch {
854
+ }
855
+ process.stderr.write(
856
+ `session_load: "${name}" returned 0 messages (file size=${sizeBytes}B) \u2014 empty or unreadable jsonl
857
+ `
858
+ );
859
+ emit({ type: "$session_empty", name, sizeBytes }, tab.id);
860
+ }
861
+ emit(
862
+ {
863
+ type: "$session_loaded",
864
+ name,
865
+ messages: loadedMessages,
866
+ carryover: {
867
+ totalCostUsd: meta.totalCostUsd ?? 0,
868
+ cacheHitTokens: meta.cacheHitTokens ?? 0,
869
+ cacheMissTokens: meta.cacheMissTokens ?? 0,
870
+ totalCompletionTokens: meta.totalCompletionTokens ?? 0
871
+ }
872
+ },
873
+ tab.id
874
+ );
875
+ if (backfilledWorkspace) emitSessions(tab);
876
+ }
437
877
  function summarizeMcpSpec(raw) {
438
878
  try {
439
879
  const parsed = parseMcpSpec(raw);
@@ -579,7 +1019,7 @@ async function getSymbolIndexFor(tab) {
579
1019
  const batch = candidates.slice(i, i + PARALLEL);
580
1020
  await Promise.all(
581
1021
  batch.map(async (entry) => {
582
- const abs = isAbsolute(entry.path) ? entry.path : join(tab.rootDir, entry.path);
1022
+ const abs = isAbsolute(entry.path) ? entry.path : join2(tab.rootDir, entry.path);
583
1023
  try {
584
1024
  const text = await readFile(abs, "utf8");
585
1025
  const lines = text.split(/\r?\n/);
@@ -1147,7 +1587,7 @@ ${optionsList}${p.allowCustom ? "\n\n(You can also reply with custom text.)" : "
1147
1587
  emitSettings(tab);
1148
1588
  return;
1149
1589
  }
1150
- if (!existsSync(target) || !statSync(target).isDirectory()) {
1590
+ if (!existsSync2(target) || !statSync2(target).isDirectory()) {
1151
1591
  emit({ type: "$error", message: `Workspace not found: ${target}` }, tab.id);
1152
1592
  emitSettings(tab);
1153
1593
  return;
@@ -1442,7 +1882,7 @@ ${optionsList}${p.allowCustom ? "\n\n(You can also reply with custom text.)" : "
1442
1882
  let restoredMessages;
1443
1883
  if (restore?.session) {
1444
1884
  try {
1445
- if (existsSync(sessionPath(restore.session))) {
1885
+ if (existsSync2(sessionPath(restore.session))) {
1446
1886
  const msgs = buildLoadedMessages(loadSessionMessages(restore.session));
1447
1887
  if (msgs.length > 0) {
1448
1888
  tab.currentSession = restore.session;
@@ -1488,7 +1928,7 @@ ${optionsList}${p.allowCustom ? "\n\n(You can also reply with custom text.)" : "
1488
1928
  }
1489
1929
  const savedTabs = loadDesktopOpenTabs().filter((t) => {
1490
1930
  try {
1491
- return existsSync(t.dir) && statSync(t.dir).isDirectory();
1931
+ return existsSync2(t.dir) && statSync2(t.dir).isDirectory();
1492
1932
  } catch {
1493
1933
  return false;
1494
1934
  }
@@ -1772,45 +2212,77 @@ ${found.body}${argsLine}`;
1772
2212
  }
1773
2213
  return;
1774
2214
  }
1775
- if (msg.cmd === "session_load") {
2215
+ if (msg.cmd === "session_import") {
1776
2216
  try {
1777
- const records = loadSessionMessages(msg.name);
1778
- const backfilledWorkspace = patchSessionWorkspaceIfMissing(msg.name, tab.rootDir);
1779
- const meta = loadSessionMeta(msg.name);
1780
- if (tab.aborter) tab.switching = true;
1781
- abortTurn(tab);
1782
- cancelPendingGates(tab);
1783
- tab.currentSession = msg.name;
1784
- persistOpenTabs();
1785
- if (tab.runtime) tab.runtime = buildRuntimeFor(tab);
1786
- const loadedMessages = buildLoadedMessages(records);
1787
- if (loadedMessages.length === 0) {
1788
- let sizeBytes = 0;
1789
- try {
1790
- sizeBytes = statSync(sessionPath(msg.name)).size;
1791
- } catch {
1792
- }
1793
- process.stderr.write(
1794
- `session_load: "${msg.name}" returned 0 messages (file size=${sizeBytes}B) \u2014 empty or unreadable jsonl
1795
- `
1796
- );
1797
- emit({ type: "$session_empty", name: msg.name, sizeBytes }, tab.id);
1798
- }
2217
+ const result = importExternalSession({
2218
+ source: msg.source,
2219
+ path: msg.path,
2220
+ name: msg.name,
2221
+ workspace: tab.rootDir
2222
+ });
2223
+ emitSessions(tab);
2224
+ loadSessionIntoTab(tab, result.name, {
2225
+ abortTurn,
2226
+ cancelPendingGates,
2227
+ persistOpenTabs
2228
+ });
2229
+ } catch (err) {
2230
+ emit(
2231
+ { type: "$error", message: `session_import failed: ${err.message}` },
2232
+ tab.id
2233
+ );
2234
+ }
2235
+ return;
2236
+ }
2237
+ if (msg.cmd === "session_import_scan") {
2238
+ try {
2239
+ emit({ type: "$session_import_sources", apps: discoverExternalSessionApps() }, tab.id);
2240
+ } catch (err) {
2241
+ emit(
2242
+ { type: "$error", message: `session_import_scan failed: ${err.message}` },
2243
+ tab.id
2244
+ );
2245
+ }
2246
+ return;
2247
+ }
2248
+ if (msg.cmd === "session_import_bulk") {
2249
+ try {
2250
+ const result = importExternalSessions({
2251
+ sources: msg.sources,
2252
+ workspace: tab.rootDir
2253
+ });
2254
+ emitSessions(tab);
1799
2255
  emit(
1800
2256
  {
1801
- type: "$session_loaded",
1802
- name: msg.name,
1803
- messages: loadedMessages,
1804
- carryover: {
1805
- totalCostUsd: meta.totalCostUsd ?? 0,
1806
- cacheHitTokens: meta.cacheHitTokens ?? 0,
1807
- cacheMissTokens: meta.cacheMissTokens ?? 0,
1808
- totalCompletionTokens: meta.totalCompletionTokens ?? 0
1809
- }
2257
+ type: "$session_import_result",
2258
+ imported: result.imported,
2259
+ skipped: result.skipped,
2260
+ failed: result.failed
1810
2261
  },
1811
2262
  tab.id
1812
2263
  );
1813
- if (backfilledWorkspace) emitSessions(tab);
2264
+ if (result.latestName) {
2265
+ loadSessionIntoTab(tab, result.latestName, {
2266
+ abortTurn,
2267
+ cancelPendingGates,
2268
+ persistOpenTabs
2269
+ });
2270
+ }
2271
+ } catch (err) {
2272
+ emit(
2273
+ { type: "$error", message: `session_import_bulk failed: ${err.message}` },
2274
+ tab.id
2275
+ );
2276
+ }
2277
+ return;
2278
+ }
2279
+ if (msg.cmd === "session_load") {
2280
+ try {
2281
+ loadSessionIntoTab(tab, msg.name, {
2282
+ abortTurn,
2283
+ cancelPendingGates,
2284
+ persistOpenTabs
2285
+ });
1814
2286
  } catch (err) {
1815
2287
  process.stderr.write(`session_load: "${msg.name}" threw \u2014 ${err.message}
1816
2288
  `);
@@ -1866,9 +2338,24 @@ ${found.body}${argsLine}`;
1866
2338
  }
1867
2339
  if (msg.editor !== void 0) saveEditor(msg.editor);
1868
2340
  if (msg.showSystemEvents !== void 0) saveShowSystemEvents(msg.showSystemEvents);
1869
- if (msg.webSearchEngine !== void 0) {
2341
+ if (msg.webSearchEngine !== void 0 || msg.webSearchEndpoint !== void 0 || msg.metasoApiKey !== void 0 || msg.tavilyApiKey !== void 0 || msg.perplexityApiKey !== void 0 || msg.exaApiKey !== void 0) {
1870
2342
  const cfg = readConfig();
1871
- cfg.webSearchEngine = msg.webSearchEngine;
2343
+ if (msg.webSearchEngine !== void 0) cfg.webSearchEngine = msg.webSearchEngine;
2344
+ if (msg.webSearchEndpoint !== void 0) {
2345
+ cfg.webSearchEndpoint = msg.webSearchEndpoint?.trim() || void 0;
2346
+ }
2347
+ if (msg.metasoApiKey !== void 0) {
2348
+ cfg.metasoApiKey = msg.metasoApiKey?.trim() || void 0;
2349
+ }
2350
+ if (msg.tavilyApiKey !== void 0) {
2351
+ cfg.tavilyApiKey = msg.tavilyApiKey?.trim() || void 0;
2352
+ }
2353
+ if (msg.perplexityApiKey !== void 0) {
2354
+ cfg.perplexityApiKey = msg.perplexityApiKey?.trim() || void 0;
2355
+ }
2356
+ if (msg.exaApiKey !== void 0) {
2357
+ cfg.exaApiKey = msg.exaApiKey?.trim() || void 0;
2358
+ }
1872
2359
  writeConfig(cfg);
1873
2360
  }
1874
2361
  if (msg.subagentModels !== void 0) {
@@ -2041,7 +2528,7 @@ ${found.body}${argsLine}`;
2041
2528
  if (msg.cmd === "mention_preview") {
2042
2529
  const nonce = msg.nonce;
2043
2530
  const rel = msg.path;
2044
- const abs = isAbsolute(rel) ? rel : join(tab.rootDir, rel);
2531
+ const abs = isAbsolute(rel) ? rel : join2(tab.rootDir, rel);
2045
2532
  const safeAbs = resolve(abs);
2046
2533
  const safeRoot = resolve(tab.rootDir);
2047
2534
  if (!safeAbs.startsWith(safeRoot)) {
@@ -2125,4 +2612,4 @@ export {
2125
2612
  normalizeSessionTitle,
2126
2613
  writeAllSync
2127
2614
  };
2128
- //# sourceMappingURL=desktop-H3ZHIMDA.js.map
2615
+ //# sourceMappingURL=desktop-LJVXWXNF.js.map