dsh-config-manager 0.1.69 → 0.1.71

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 (719) hide show
  1. package/README.md +59 -18
  2. package/README.zh-CN.md +29 -9
  3. package/lib/adapters/credentials.js +6 -3
  4. package/lib/adapters/file-collection.d.ts +21 -1
  5. package/lib/adapters/file-collection.js +32 -8
  6. package/lib/adapters/mcp.d.ts +12 -2
  7. package/lib/adapters/mcp.js +30 -13
  8. package/lib/adapters/plugin-files.d.ts +8 -0
  9. package/lib/adapters/plugin-files.js +36 -4
  10. package/lib/adapters/plugins.d.ts +28 -2
  11. package/lib/adapters/plugins.js +204 -55
  12. package/lib/adapters/prompts.d.ts +12 -2
  13. package/lib/adapters/prompts.js +34 -19
  14. package/lib/adapters/providers.js +5 -4
  15. package/lib/adapters/self.d.ts +20 -0
  16. package/lib/adapters/self.js +73 -0
  17. package/lib/adapters/sessions.d.ts +8 -0
  18. package/lib/adapters/sessions.js +47 -1
  19. package/lib/adapters/settings.d.ts +21 -3
  20. package/lib/adapters/settings.js +44 -7
  21. package/lib/adapters/skills.d.ts +36 -4
  22. package/lib/adapters/skills.js +222 -3
  23. package/lib/adapters/test-helpers.d.ts +31 -2
  24. package/lib/adapters/test-helpers.js +42 -5
  25. package/lib/adapters/workspaces.js +97 -5
  26. package/lib/cli/actions.d.ts +50 -3
  27. package/lib/cli/actions.js +103 -11
  28. package/lib/cli/help.d.ts +65 -0
  29. package/lib/cli/help.js +517 -0
  30. package/lib/cli/import-source.d.ts +32 -0
  31. package/lib/cli/import-source.js +178 -0
  32. package/lib/cli/index.d.ts +18 -2
  33. package/lib/cli/index.js +118 -90
  34. package/lib/cli/web/client-script.d.ts +8 -0
  35. package/lib/cli/web/client-script.js +11 -0
  36. package/lib/cli/web/http.d.ts +5 -0
  37. package/lib/cli/web/http.js +2 -1
  38. package/lib/cli/web/page.d.ts +16 -6
  39. package/lib/cli/web/page.js +102 -25
  40. package/lib/cli/web/routes.js +24 -5
  41. package/lib/cli/web/server.js +23 -2
  42. package/lib/client.d.ts +1019 -36
  43. package/lib/client.js +5522 -1564
  44. package/lib/core/analyzer.d.ts +15 -1
  45. package/lib/core/analyzer.js +114 -13
  46. package/lib/core/backup-plan.js +17 -1
  47. package/lib/core/backup.d.ts +8 -0
  48. package/lib/core/backup.js +28 -6
  49. package/lib/core/cache-cleaner.d.ts +10 -0
  50. package/lib/core/cache-cleaner.js +63 -22
  51. package/lib/core/checkpoint.d.ts +362 -0
  52. package/lib/core/checkpoint.js +1309 -0
  53. package/lib/core/journal.d.ts +37 -0
  54. package/lib/core/journal.js +69 -0
  55. package/lib/core/messages.d.ts +13 -0
  56. package/lib/core/messages.js +26 -0
  57. package/lib/core/model-tools.js +3 -0
  58. package/lib/core/patch-layers.d.ts +83 -0
  59. package/lib/core/patch-layers.js +110 -0
  60. package/lib/core/restore.d.ts +21 -0
  61. package/lib/core/restore.js +37 -3
  62. package/lib/core/rollback.js +6 -3
  63. package/lib/core/self-update.d.ts +52 -0
  64. package/lib/core/self-update.js +70 -0
  65. package/lib/core/session-health.d.ts +29 -5
  66. package/lib/core/session-health.js +28 -3
  67. package/lib/core/types.d.ts +126 -0
  68. package/lib/foreign/antigravity.d.ts +28 -0
  69. package/lib/foreign/antigravity.js +157 -0
  70. package/lib/foreign/bundle.d.ts +25 -0
  71. package/lib/foreign/bundle.js +79 -0
  72. package/lib/foreign/chatgpt.d.ts +6 -0
  73. package/lib/foreign/chatgpt.js +25 -0
  74. package/lib/foreign/claude-code.d.ts +3 -0
  75. package/lib/foreign/claude-code.js +85 -0
  76. package/lib/foreign/claude-sessions.d.ts +108 -0
  77. package/lib/foreign/claude-sessions.js +299 -0
  78. package/lib/foreign/cline.d.ts +6 -0
  79. package/lib/foreign/cline.js +27 -0
  80. package/lib/foreign/codex.d.ts +83 -0
  81. package/lib/foreign/codex.js +348 -0
  82. package/lib/foreign/continue.d.ts +9 -0
  83. package/lib/foreign/continue.js +65 -0
  84. package/lib/foreign/copilot.d.ts +39 -0
  85. package/lib/foreign/copilot.js +95 -0
  86. package/lib/foreign/crush.d.ts +11 -0
  87. package/lib/foreign/crush.js +57 -0
  88. package/lib/foreign/cursor.d.ts +87 -0
  89. package/lib/foreign/cursor.js +171 -0
  90. package/lib/foreign/dsh.d.ts +30 -0
  91. package/lib/foreign/dsh.js +101 -0
  92. package/lib/foreign/dsh4.d.ts +3 -0
  93. package/lib/foreign/dsh4.js +13 -0
  94. package/lib/foreign/gemini.d.ts +7 -0
  95. package/lib/foreign/gemini.js +44 -0
  96. package/lib/foreign/goose.d.ts +11 -0
  97. package/lib/foreign/goose.js +53 -0
  98. package/lib/foreign/grokbuild.d.ts +8 -0
  99. package/lib/foreign/grokbuild.js +25 -0
  100. package/lib/foreign/hermes.d.ts +2 -0
  101. package/lib/foreign/hermes.js +78 -0
  102. package/lib/foreign/kernel.d.ts +132 -0
  103. package/lib/foreign/kernel.js +569 -0
  104. package/lib/foreign/kilocode.d.ts +11 -0
  105. package/lib/foreign/kilocode.js +51 -0
  106. package/lib/foreign/kimi.d.ts +7 -0
  107. package/lib/foreign/kimi.js +47 -0
  108. package/lib/foreign/mimocode.d.ts +11 -0
  109. package/lib/foreign/mimocode.js +51 -0
  110. package/lib/foreign/openclaw.d.ts +7 -0
  111. package/lib/foreign/openclaw.js +46 -0
  112. package/lib/foreign/opencode.d.ts +11 -0
  113. package/lib/foreign/opencode.js +52 -0
  114. package/lib/foreign/pi.d.ts +7 -0
  115. package/lib/foreign/pi.js +48 -0
  116. package/lib/foreign/platform-paths.d.ts +66 -0
  117. package/lib/foreign/platform-paths.js +141 -0
  118. package/lib/foreign/qoder.d.ts +10 -0
  119. package/lib/foreign/qoder.js +49 -0
  120. package/lib/foreign/qwen.d.ts +7 -0
  121. package/lib/foreign/qwen.js +45 -0
  122. package/lib/foreign/read-antigravity.d.ts +57 -0
  123. package/lib/foreign/read-antigravity.js +504 -0
  124. package/lib/foreign/read-chatgpt.d.ts +20 -0
  125. package/lib/foreign/read-chatgpt.js +509 -0
  126. package/lib/foreign/read-claude-code.d.ts +24 -0
  127. package/lib/foreign/read-claude-code.js +234 -0
  128. package/lib/foreign/read-cline.d.ts +53 -0
  129. package/lib/foreign/read-cline.js +479 -0
  130. package/lib/foreign/read-codex.d.ts +75 -0
  131. package/lib/foreign/read-codex.js +842 -0
  132. package/lib/foreign/read-continue.d.ts +87 -0
  133. package/lib/foreign/read-continue.js +489 -0
  134. package/lib/foreign/read-copilot.d.ts +42 -0
  135. package/lib/foreign/read-copilot.js +267 -0
  136. package/lib/foreign/read-crush.d.ts +54 -0
  137. package/lib/foreign/read-crush.js +478 -0
  138. package/lib/foreign/read-cursor.d.ts +141 -0
  139. package/lib/foreign/read-cursor.js +705 -0
  140. package/lib/foreign/read-dsh.d.ts +43 -0
  141. package/lib/foreign/read-dsh.js +205 -0
  142. package/lib/foreign/read-dsh4.d.ts +14 -0
  143. package/lib/foreign/read-dsh4.js +27 -0
  144. package/lib/foreign/read-gemini.d.ts +55 -0
  145. package/lib/foreign/read-gemini.js +273 -0
  146. package/lib/foreign/read-goose.d.ts +25 -0
  147. package/lib/foreign/read-goose.js +322 -0
  148. package/lib/foreign/read-grokbuild.d.ts +34 -0
  149. package/lib/foreign/read-grokbuild.js +455 -0
  150. package/lib/foreign/read-hermes.d.ts +74 -0
  151. package/lib/foreign/read-hermes.js +690 -0
  152. package/lib/foreign/read-kilocode.d.ts +17 -0
  153. package/lib/foreign/read-kilocode.js +46 -0
  154. package/lib/foreign/read-kimi.d.ts +63 -0
  155. package/lib/foreign/read-kimi.js +719 -0
  156. package/lib/foreign/read-mimocode.d.ts +12 -0
  157. package/lib/foreign/read-mimocode.js +56 -0
  158. package/lib/foreign/read-openclaw.d.ts +51 -0
  159. package/lib/foreign/read-openclaw.js +445 -0
  160. package/lib/foreign/read-opencode.d.ts +150 -0
  161. package/lib/foreign/read-opencode.js +896 -0
  162. package/lib/foreign/read-pi.d.ts +56 -0
  163. package/lib/foreign/read-pi.js +411 -0
  164. package/lib/foreign/read-qoder.d.ts +54 -0
  165. package/lib/foreign/read-qoder.js +317 -0
  166. package/lib/foreign/read-qwen.d.ts +40 -0
  167. package/lib/foreign/read-qwen.js +326 -0
  168. package/lib/foreign/read-reasonix.d.ts +66 -0
  169. package/lib/foreign/read-reasonix.js +537 -0
  170. package/lib/foreign/read-teleagent.d.ts +15 -0
  171. package/lib/foreign/read-teleagent.js +68 -0
  172. package/lib/foreign/read-trae.d.ts +67 -0
  173. package/lib/foreign/read-trae.js +492 -0
  174. package/lib/foreign/read-vibe.d.ts +28 -0
  175. package/lib/foreign/read-vibe.js +364 -0
  176. package/lib/foreign/read-workbuddy.d.ts +49 -0
  177. package/lib/foreign/read-workbuddy.js +346 -0
  178. package/lib/foreign/read-zcode.d.ts +12 -0
  179. package/lib/foreign/read-zcode.js +38 -0
  180. package/lib/foreign/read-zed.d.ts +30 -0
  181. package/lib/foreign/read-zed.js +473 -0
  182. package/lib/foreign/reasonix.d.ts +6 -0
  183. package/lib/foreign/reasonix.js +20 -0
  184. package/lib/foreign/registry.d.ts +196 -0
  185. package/lib/foreign/registry.js +573 -0
  186. package/lib/foreign/session-ir.d.ts +186 -0
  187. package/lib/foreign/session-ir.js +427 -0
  188. package/lib/foreign/session-read.d.ts +102 -0
  189. package/lib/foreign/session-read.js +254 -0
  190. package/lib/foreign/session-source.d.ts +216 -0
  191. package/lib/foreign/session-source.js +453 -0
  192. package/lib/foreign/source-modules.d.ts +45 -0
  193. package/lib/foreign/source-modules.js +52 -0
  194. package/lib/foreign/sqlite.d.ts +61 -0
  195. package/lib/foreign/sqlite.js +404 -0
  196. package/lib/foreign/teleagent.d.ts +11 -0
  197. package/lib/foreign/teleagent.js +53 -0
  198. package/lib/foreign/trae.d.ts +6 -0
  199. package/lib/foreign/trae.js +20 -0
  200. package/lib/foreign/truth-table.d.ts +62 -0
  201. package/lib/foreign/truth-table.js +333 -0
  202. package/lib/foreign/types.d.ts +272 -0
  203. package/lib/foreign/types.js +2 -0
  204. package/lib/foreign/vibe.d.ts +6 -0
  205. package/lib/foreign/vibe.js +23 -0
  206. package/lib/foreign/workbuddy.d.ts +7 -0
  207. package/lib/foreign/workbuddy.js +45 -0
  208. package/lib/foreign/zcode.d.ts +11 -0
  209. package/lib/foreign/zcode.js +51 -0
  210. package/lib/foreign/zed.d.ts +11 -0
  211. package/lib/foreign/zed.js +53 -0
  212. package/lib/index.d.ts +154 -13
  213. package/lib/index.js +661 -84
  214. package/lib/market/github-repos.d.ts +28 -0
  215. package/lib/market/github-repos.js +43 -1
  216. package/lib/market/types.d.ts +1 -3
  217. package/lib/profiles/dsh-profile-manager.d.ts +54 -2
  218. package/lib/profiles/dsh-profile-manager.js +182 -11
  219. package/lib/profiles/dsh-profile-shared.d.ts +47 -0
  220. package/lib/profiles/dsh-profile-shared.js +15 -1
  221. package/lib/profiles/index.d.ts +1 -1
  222. package/lib/profiles/index.js +1 -1
  223. package/lib/routes/consult.js +51 -5
  224. package/lib/routes/foreign-context.d.ts +43 -0
  225. package/lib/routes/foreign-context.js +65 -0
  226. package/lib/routes/foreign.d.ts +11 -0
  227. package/lib/routes/foreign.js +208 -0
  228. package/lib/routes/import.d.ts +8 -0
  229. package/lib/routes/import.js +22 -1
  230. package/lib/routes/index.d.ts +2 -2
  231. package/lib/routes/index.js +4 -0
  232. package/lib/routes/kit.d.ts +4 -3
  233. package/lib/routes/market.js +0 -1
  234. package/lib/routes/prefs.d.ts +2 -1
  235. package/lib/routes/prefs.js +14 -2
  236. package/lib/routes/recovery.js +363 -3
  237. package/lib/routes/session-export.d.ts +117 -0
  238. package/lib/routes/session-export.js +270 -0
  239. package/lib/routes/snapshots.js +12 -2
  240. package/lib/routes/sync.js +82 -10
  241. package/lib/security/redaction.d.ts +14 -0
  242. package/lib/security/redaction.js +24 -9
  243. package/lib/security/secret-scanner.d.ts +27 -0
  244. package/lib/security/secret-scanner.js +54 -1
  245. package/lib/sync/autosync-scheduler.d.ts +13 -1
  246. package/lib/sync/autosync-scheduler.js +49 -26
  247. package/lib/sync/backup-files.js +6 -0
  248. package/lib/sync/gist/gist-transport.d.ts +91 -0
  249. package/lib/sync/gist/gist-transport.js +406 -0
  250. package/lib/sync/gist/messages.d.ts +22 -0
  251. package/lib/sync/gist/messages.js +46 -0
  252. package/lib/sync/s3/messages.d.ts +53 -0
  253. package/lib/sync/s3/messages.js +83 -0
  254. package/lib/sync/s3/s3-providers.d.ts +78 -0
  255. package/lib/sync/s3/s3-providers.js +156 -0
  256. package/lib/sync/s3/s3-transport.d.ts +126 -0
  257. package/lib/sync/s3/s3-transport.js +551 -0
  258. package/lib/sync/s3/sigv4.d.ts +107 -0
  259. package/lib/sync/s3/sigv4.js +196 -0
  260. package/lib/sync/sync-config.d.ts +250 -4
  261. package/lib/sync/sync-config.js +658 -57
  262. package/lib/sync/sync-engine.d.ts +1 -0
  263. package/lib/sync/sync-engine.js +4 -2
  264. package/lib/sync/sync-history.d.ts +1 -1
  265. package/lib/sync/webdav/webdav-transport.d.ts +31 -3
  266. package/lib/sync/webdav/webdav-transport.js +102 -18
  267. package/lib/ui/commands.d.ts +4 -3
  268. package/lib/ui/commands.js +41 -9
  269. package/lib/ui/disk-usage-view.d.ts +44 -0
  270. package/lib/ui/disk-usage-view.js +55 -1
  271. package/lib/ui/dsh-profiles-view.d.ts +53 -0
  272. package/lib/ui/dsh-profiles-view.js +56 -0
  273. package/lib/ui/foreign-view.d.ts +162 -0
  274. package/lib/ui/foreign-view.js +225 -0
  275. package/lib/ui/i18n.d.ts +77 -0
  276. package/lib/ui/i18n.js +164 -0
  277. package/lib/ui/session-inventory-view.d.ts +106 -0
  278. package/lib/ui/session-inventory-view.js +58 -0
  279. package/lib/ui/session-layout-view.d.ts +265 -0
  280. package/lib/ui/session-layout-view.js +271 -0
  281. package/lib/ui/sync-repository-picker.d.ts +98 -0
  282. package/lib/ui/sync-repository-picker.js +145 -0
  283. package/lib/ui/sync-settings-view.d.ts +143 -4
  284. package/lib/ui/sync-settings-view.js +231 -7
  285. package/lib/ui/types.d.ts +47 -0
  286. package/lib/utils/asar-read.d.ts +113 -0
  287. package/lib/utils/asar-read.js +523 -0
  288. package/lib/utils/env-lock.js +7 -2
  289. package/lib/utils/patch-yaml.d.ts +25 -0
  290. package/lib/utils/patch-yaml.js +62 -0
  291. package/lib/utils/paths.d.ts +10 -1
  292. package/lib/utils/paths.js +24 -3
  293. package/lib/utils/recursive-walk.js +12 -13
  294. package/lib/utils/session-format.d.ts +35 -2
  295. package/lib/utils/session-format.js +131 -5
  296. package/lib/utils/session-health-scan.d.ts +7 -1
  297. package/lib/utils/session-health-scan.js +369 -12
  298. package/lib/utils/session-layout-repair-service.d.ts +98 -0
  299. package/lib/utils/session-layout-repair-service.js +457 -0
  300. package/lib/utils/session-log-repair.d.ts +27 -0
  301. package/lib/utils/session-log-repair.js +233 -62
  302. package/lib/utils/session-repair-service.d.ts +32 -3
  303. package/lib/utils/session-repair-service.js +148 -9
  304. package/lib/utils/session-row-facts.d.ts +73 -0
  305. package/lib/utils/session-row-facts.js +182 -0
  306. package/lib/utils/session-verify.d.ts +118 -0
  307. package/lib/utils/session-verify.js +705 -0
  308. package/lib/utils/shared-constants.d.ts +59 -0
  309. package/lib/utils/shared-constants.js +71 -0
  310. package/package.json +1 -1
  311. package/src/adapters/credentials.test.ts +27 -0
  312. package/src/adapters/credentials.ts +6 -3
  313. package/src/adapters/file-collection.ts +33 -8
  314. package/src/adapters/files.test.ts +222 -0
  315. package/src/adapters/mcp.test.ts +43 -0
  316. package/src/adapters/mcp.ts +37 -14
  317. package/src/adapters/plugin-files.ts +34 -4
  318. package/src/adapters/plugins.test.ts +241 -0
  319. package/src/adapters/plugins.ts +201 -53
  320. package/src/adapters/prompts.test.ts +49 -0
  321. package/src/adapters/prompts.ts +41 -20
  322. package/src/adapters/providers.test.ts +16 -0
  323. package/src/adapters/providers.ts +4 -3
  324. package/src/adapters/self.test.ts +77 -0
  325. package/src/adapters/self.ts +75 -0
  326. package/src/adapters/sessions.test.ts +77 -0
  327. package/src/adapters/sessions.ts +47 -1
  328. package/src/adapters/settings.test.ts +78 -0
  329. package/src/adapters/settings.ts +42 -6
  330. package/src/adapters/skills.ts +221 -3
  331. package/src/adapters/test-helpers.ts +43 -5
  332. package/src/adapters/workspaces-dup-id.test.ts +144 -0
  333. package/src/adapters/workspaces.test.ts +10 -0
  334. package/src/adapters/workspaces.ts +97 -5
  335. package/src/cli/actions.test.ts +117 -2
  336. package/src/cli/actions.ts +132 -12
  337. package/src/cli/help.ts +570 -0
  338. package/src/cli/import-source.test.ts +193 -0
  339. package/src/cli/import-source.ts +229 -0
  340. package/src/cli/index.ts +129 -94
  341. package/src/cli/web/client-script.ts +12 -0
  342. package/src/cli/web/console-fixes.test.ts +36 -0
  343. package/src/cli/web/http.ts +7 -1
  344. package/src/cli/web/page.ts +108 -25
  345. package/src/cli/web/routes.ts +23 -4
  346. package/src/cli/web/script-anchor.test.ts +33 -0
  347. package/src/cli/web/server.ts +28 -2
  348. package/src/cli/web/web.test.ts +447 -4
  349. package/src/client/ConfigManagerSection.tsx +118 -63
  350. package/src/client/about/AboutPanel.tsx +42 -3
  351. package/src/client/about/PluginUpdateDialog.tsx +185 -0
  352. package/src/client/about/ReleaseBody.tsx +144 -0
  353. package/src/client/about/ReleaseNotesDialog.tsx +3 -130
  354. package/src/client/about/about-view.ts +7 -5
  355. package/src/client/about/plugin-update-view.test.ts +25 -0
  356. package/src/client/about/plugin-update-view.ts +26 -0
  357. package/src/client/about/release-notes-view.test.ts +33 -0
  358. package/src/client/about/release-notes-view.ts +34 -0
  359. package/src/client/api.ts +145 -1
  360. package/src/client/common/Icon.tsx +3 -0
  361. package/src/client/common/RunsCenter.tsx +8 -2
  362. package/src/client/common/Select.tsx +9 -2
  363. package/src/client/common/info-hint-guard.test.ts +63 -18
  364. package/src/client/common/plan-text-redaction.test.ts +193 -8
  365. package/src/client/common/routes.ts +15 -0
  366. package/src/client/config-manager.module.css +506 -354
  367. package/src/client/css-scale-guard.test.ts +122 -0
  368. package/src/client/css-token-guard.test.ts +82 -0
  369. package/src/client/environment/EnvironmentPanel.tsx +45 -16
  370. package/src/client/{snapshots → environment/maintenance}/DiskUsageCard.tsx +21 -17
  371. package/src/client/environment/profiles-incomplete-ui.test.ts +103 -0
  372. package/src/client/export/ExportView.tsx +9 -2
  373. package/src/client/{snapshots → home}/BackupScheduleCard.tsx +13 -4
  374. package/src/client/home/HomePanel.tsx +69 -157
  375. package/src/client/icon-layer-guard.test.ts +1 -1
  376. package/src/client/import/ForeignImportView.tsx +318 -0
  377. package/src/client/import/ImportWizardView.tsx +3 -1
  378. package/src/client/import/foreign-import-view-guard.test.ts +195 -0
  379. package/src/client/import/import-file-select.test.ts +6 -6
  380. package/src/client/import/import-wizard-steps.tsx +17 -1
  381. package/src/client/import/use-import-wizard-controller.ts +3 -3
  382. package/src/client/index.ts +1 -1
  383. package/src/client/library/LibraryActions.tsx +31 -34
  384. package/src/client/library/LibraryPanel.tsx +4 -1
  385. package/src/client/{snapshots → library}/RestorePlanView.tsx +1 -1
  386. package/src/client/{snapshots → library}/files-layout.test.ts +2 -2
  387. package/src/client/{snapshots → library}/report-dismiss.test.ts +26 -3
  388. package/src/client/library/task-panel-visibility.test.ts +25 -17
  389. package/src/client/locales.ts +278 -36
  390. package/src/client/lucide-icons.d.ts +1 -0
  391. package/src/client/market/MarketPanel.tsx +11 -2
  392. package/src/client/recovery/IncompleteCopiesSection.tsx +132 -0
  393. package/src/client/recovery/RecoveryPanel.tsx +486 -59
  394. package/src/client/recovery/recovery-api.ts +30 -0
  395. package/src/client/recovery/recovery-incomplete-copies.test.ts +151 -0
  396. package/src/client/recovery/recovery-locales.test.ts +88 -0
  397. package/src/client/recovery/recovery-locales.ts +321 -6
  398. package/src/client/recovery/recovery-panel-layout.test.ts +52 -0
  399. package/src/client/recovery/recovery-view.ts +92 -2
  400. package/src/client/run-store.test.ts +201 -89
  401. package/src/client/run-store.ts +114 -143
  402. package/src/client/session-export/session-export-view.test.ts +103 -0
  403. package/src/client/session-export/session-export-view.ts +118 -0
  404. package/src/client/sync/ChannelConfigDialog.tsx +219 -14
  405. package/src/client/sync/SyncChannelEntryCard.tsx +52 -4
  406. package/src/client/sync/SyncLogList.tsx +1 -1
  407. package/src/client/sync/SyncPanel.tsx +166 -102
  408. package/src/client/sync/SyncRepositoryPicker.tsx +216 -0
  409. package/src/client/sync/SyncSettingsView.test.ts +6 -1
  410. package/src/client/sync/history-model.test.ts +94 -57
  411. package/src/client/sync/history-model.ts +44 -25
  412. package/src/client/sync/sync-api.test.ts +56 -0
  413. package/src/client/sync/sync-api.ts +92 -0
  414. package/src/client/sync/sync-locales.ts +162 -2
  415. package/src/client/sync/sync-view.test.ts +3 -8
  416. package/src/client/sync/sync-view.ts +111 -21
  417. package/src/core/analyzer-cache.test.ts +47 -0
  418. package/src/core/analyzer.ts +115 -14
  419. package/src/core/backup-plan.test.ts +35 -0
  420. package/src/core/backup-plan.ts +19 -1
  421. package/src/core/backup.test.ts +37 -1
  422. package/src/core/backup.ts +27 -6
  423. package/src/core/cache-cleaner.test.ts +120 -1
  424. package/src/core/cache-cleaner.ts +59 -22
  425. package/src/core/checkpoint.test.ts +665 -0
  426. package/src/core/checkpoint.ts +1614 -0
  427. package/src/core/credential-plan-consistency.test.ts +93 -0
  428. package/src/core/incident-wiring.test.ts +6 -2
  429. package/src/core/journal.test.ts +70 -0
  430. package/src/core/journal.ts +68 -0
  431. package/src/core/messages.ts +26 -0
  432. package/src/core/model-tools.ts +3 -0
  433. package/src/core/patch-layers.test.ts +94 -0
  434. package/src/core/patch-layers.ts +150 -0
  435. package/src/core/restore.ts +59 -3
  436. package/src/core/rollback.ts +6 -3
  437. package/src/core/section-content-consistency.test.ts +185 -0
  438. package/src/core/self-update.test.ts +110 -0
  439. package/src/core/self-update.ts +118 -0
  440. package/src/core/session-health.test.ts +91 -1
  441. package/src/core/session-health.ts +56 -9
  442. package/src/core/types.ts +127 -1
  443. package/src/foreign/antigravity.test.ts +271 -0
  444. package/src/foreign/antigravity.ts +188 -0
  445. package/src/foreign/bundle.ts +108 -0
  446. package/src/foreign/chatgpt.test.ts +279 -0
  447. package/src/foreign/chatgpt.ts +30 -0
  448. package/src/foreign/claude-code.test.ts +234 -0
  449. package/src/foreign/claude-code.ts +106 -0
  450. package/src/foreign/claude-sessions-bytes.test.ts +227 -0
  451. package/src/foreign/claude-sessions.test.ts +180 -0
  452. package/src/foreign/claude-sessions.ts +461 -0
  453. package/src/foreign/cline.test.ts +274 -0
  454. package/src/foreign/cline.ts +32 -0
  455. package/src/foreign/codex.test.ts +585 -0
  456. package/src/foreign/codex.ts +409 -0
  457. package/src/foreign/continue.test.ts +365 -0
  458. package/src/foreign/continue.ts +73 -0
  459. package/src/foreign/copilot.test.ts +273 -0
  460. package/src/foreign/copilot.ts +133 -0
  461. package/src/foreign/crush.test.ts +234 -0
  462. package/src/foreign/crush.ts +66 -0
  463. package/src/foreign/cursor.test.ts +509 -0
  464. package/src/foreign/cursor.ts +259 -0
  465. package/src/foreign/dsh.test.ts +198 -0
  466. package/src/foreign/dsh.ts +117 -0
  467. package/src/foreign/dsh4.test.ts +127 -0
  468. package/src/foreign/dsh4.ts +15 -0
  469. package/src/foreign/file-budget.test.ts +256 -0
  470. package/src/foreign/fixtures/antigravity/README.md +18 -0
  471. package/src/foreign/fixtures/antigravity/basic/gemini/antigravity/mcp_config.json +13 -0
  472. package/src/foreign/fixtures/antigravity/basic/gemini/config/mcp_config.json +24 -0
  473. package/src/foreign/fixtures/antigravity/empty/gemini/antigravity/mcp_config.json +0 -0
  474. package/src/foreign/fixtures/antigravity/empty/gemini/antigravity/mcp_oauth_tokens.json +0 -0
  475. package/src/foreign/fixtures/antigravity/empty/gemini/config/mcp_config.json +0 -0
  476. package/src/foreign/fixtures/codex/README.md +31 -0
  477. package/src/foreign/fixtures/codex/basic/.agents/skills/hello/SKILL.md +6 -0
  478. package/src/foreign/fixtures/codex/basic/.agents/skills/wrapper/nested/SKILL.md +6 -0
  479. package/src/foreign/fixtures/codex/basic/.codex/AGENTS.md +4 -0
  480. package/src/foreign/fixtures/codex/basic/.codex/config.toml +28 -0
  481. package/src/foreign/fixtures/codex/malformed/.codex/config.toml +3 -0
  482. package/src/foreign/fixtures/codex/override/.codex/AGENTS.md +1 -0
  483. package/src/foreign/fixtures/codex/override/.codex/AGENTS.override.md +3 -0
  484. package/src/foreign/fixtures/codex/sessions/.codex/archived_sessions/rollout-2026-10-05T09-00-00-22222222-2222-4222-8222-222222222222.jsonl +2 -0
  485. package/src/foreign/fixtures/codex/sessions/.codex/sessions/2026/10/06/rollout-2026-10-06T10-00-00-11111111-1111-4111-8111-111111111111.jsonl +15 -0
  486. package/src/foreign/fixtures/codex/sessions/.codex/sessions/2026/10/06/rollout-2026-10-06T11-00-00-33333333-3333-4333-8333-333333333333.jsonl +2 -0
  487. package/src/foreign/fixtures/codex/sessions/.codex/sessions/2026/10/06/rollout-2026-10-06T11-30-00-55555555-5555-4555-8555-555555555555.jsonl +2 -0
  488. package/src/foreign/fixtures/codex/sessions/.codex/sessions/2026/10/06/rollout-2026-10-06T12-00-00-44444444-4444-4444-8444-444444444444.jsonl +2 -0
  489. package/src/foreign/fixtures/codex/sessions/.codex/sessions/notes.jsonl +1 -0
  490. package/src/foreign/fixtures/copilot/README.md +22 -0
  491. package/src/foreign/fixtures/copilot/basic/copilot-instructions.md +3 -0
  492. package/src/foreign/fixtures/copilot/basic/instructions/empty.instructions.md +1 -0
  493. package/src/foreign/fixtures/copilot/basic/instructions/repo.instructions.md +5 -0
  494. package/src/foreign/fixtures/copilot/basic/mcp-config.json +24 -0
  495. package/src/foreign/fixtures/copilot/basic/skills/hello/SKILL.md +6 -0
  496. package/src/foreign/fixtures/copilot/overridden/mcp-config.json +10 -0
  497. package/src/foreign/fixtures/cursor/README.md +17 -0
  498. package/src/foreign/fixtures/cursor/alt/.cursor/mcp.json +5 -0
  499. package/src/foreign/fixtures/cursor/basic/.cursor/mcp.json +18 -0
  500. package/src/foreign/fixtures/cursor/basic/.cursor/rules/agent.mdc +5 -0
  501. package/src/foreign/fixtures/cursor/basic/.cursor/rules/always.mdc +6 -0
  502. package/src/foreign/fixtures/cursor/basic/.cursor/rules/auto.mdc +7 -0
  503. package/src/foreign/fixtures/cursor/basic/.cursor/rules/manual.mdc +3 -0
  504. package/src/foreign/fixtures/cursor/basic/.cursor/skills/.hidden/SKILL.md +6 -0
  505. package/src/foreign/fixtures/cursor/basic/.cursor/skills/hello/SKILL.md +6 -0
  506. package/src/foreign/fixtures/cursor/basic/.cursor/skills/wrapper/nested/SKILL.md +6 -0
  507. package/src/foreign/fixtures/cursor/basic/.cursor/skills/wrapper/nested/notes.md +1 -0
  508. package/src/foreign/fixtures/cursor/basic/.cursorrules +1 -0
  509. package/src/foreign/fixtures/cursor/basic/project/.cursor/mcp.json +9 -0
  510. package/src/foreign/fixtures/cursor/basic/project/.cursor/rules/project-always.mdc +5 -0
  511. package/src/foreign/fixtures/cursor/basic/project/.cursor/skills/hello/SKILL.md +6 -0
  512. package/src/foreign/fixtures/cursor/basic/project/.cursorrules +1 -0
  513. package/src/foreign/fixtures/cursor/empty/.cursor/mcp.json +0 -0
  514. package/src/foreign/fixtures/cursor/malformed/.cursor/mcp.json +3 -0
  515. package/src/foreign/fixtures/cursor/malformed/.cursor/rules/broken.mdc +6 -0
  516. package/src/foreign/fixtures/cursor/shape/.cursor/mcp.json +3 -0
  517. package/src/foreign/fixtures/hermes/README.md +14 -0
  518. package/src/foreign/fixtures/hermes/basic/SOUL.md +3 -0
  519. package/src/foreign/fixtures/hermes/basic/config.yaml +48 -0
  520. package/src/foreign/fixtures/hermes/basic/dotenv.fixture +1 -0
  521. package/src/foreign/fixtures/hermes/basic/memories/MEMORY.md +1 -0
  522. package/src/foreign/fixtures/hermes/basic/memories/USER.md +1 -0
  523. package/src/foreign/fixtures/hermes/basic/skills/se-team-design/SKILL.md +6 -0
  524. package/src/foreign/fixtures/hermes/basic/skills/se-team-design/examples/usage.md +1 -0
  525. package/src/foreign/fixtures/hermes/basic/skills/software-development/dogfood/SKILL.md +6 -0
  526. package/src/foreign/fixtures/hermes/basic/skills/software-development/dogfood/notes.md +1 -0
  527. package/src/foreign/fixtures/hermes/basic/state.db +1 -0
  528. package/src/foreign/fixtures/hermes/empty/config.yaml +0 -0
  529. package/src/foreign/gemini.test.ts +291 -0
  530. package/src/foreign/gemini.ts +52 -0
  531. package/src/foreign/goose.test.ts +196 -0
  532. package/src/foreign/goose.ts +62 -0
  533. package/src/foreign/grokbuild.test.ts +246 -0
  534. package/src/foreign/grokbuild.ts +30 -0
  535. package/src/foreign/hermes.test.ts +545 -0
  536. package/src/foreign/hermes.ts +86 -0
  537. package/src/foreign/kernel-credentials.test.ts +88 -0
  538. package/src/foreign/kernel-workspaces.test.ts +88 -0
  539. package/src/foreign/kernel.ts +584 -0
  540. package/src/foreign/kilocode.test.ts +186 -0
  541. package/src/foreign/kilocode.ts +60 -0
  542. package/src/foreign/kimi.test.ts +259 -0
  543. package/src/foreign/kimi.ts +55 -0
  544. package/src/foreign/mcp-value-shape.test.ts +286 -0
  545. package/src/foreign/mimocode.test.ts +178 -0
  546. package/src/foreign/mimocode.ts +60 -0
  547. package/src/foreign/openclaw.test.ts +248 -0
  548. package/src/foreign/openclaw.ts +54 -0
  549. package/src/foreign/opencode.test.ts +376 -0
  550. package/src/foreign/opencode.ts +61 -0
  551. package/src/foreign/pi.test.ts +275 -0
  552. package/src/foreign/pi.ts +56 -0
  553. package/src/foreign/platform-paths.ts +156 -0
  554. package/src/foreign/qoder.test.ts +266 -0
  555. package/src/foreign/qoder.ts +57 -0
  556. package/src/foreign/qwen.test.ts +203 -0
  557. package/src/foreign/qwen.ts +53 -0
  558. package/src/foreign/read-antigravity.ts +569 -0
  559. package/src/foreign/read-chatgpt.ts +506 -0
  560. package/src/foreign/read-claude-code.ts +264 -0
  561. package/src/foreign/read-cline.ts +517 -0
  562. package/src/foreign/read-codex.ts +823 -0
  563. package/src/foreign/read-continue.ts +557 -0
  564. package/src/foreign/read-copilot.ts +304 -0
  565. package/src/foreign/read-crush.ts +503 -0
  566. package/src/foreign/read-cursor.ts +778 -0
  567. package/src/foreign/read-dsh.ts +215 -0
  568. package/src/foreign/read-dsh4.ts +35 -0
  569. package/src/foreign/read-gemini.ts +306 -0
  570. package/src/foreign/read-goose.ts +333 -0
  571. package/src/foreign/read-grokbuild.ts +475 -0
  572. package/src/foreign/read-hermes.ts +724 -0
  573. package/src/foreign/read-kilocode.ts +55 -0
  574. package/src/foreign/read-kimi.ts +768 -0
  575. package/src/foreign/read-mimocode.ts +66 -0
  576. package/src/foreign/read-openclaw.ts +505 -0
  577. package/src/foreign/read-opencode.ts +994 -0
  578. package/src/foreign/read-pi.ts +459 -0
  579. package/src/foreign/read-qoder.ts +351 -0
  580. package/src/foreign/read-qwen.ts +342 -0
  581. package/src/foreign/read-reasonix.ts +590 -0
  582. package/src/foreign/read-teleagent.ts +82 -0
  583. package/src/foreign/read-trae.ts +488 -0
  584. package/src/foreign/read-vibe.ts +353 -0
  585. package/src/foreign/read-workbuddy.ts +374 -0
  586. package/src/foreign/read-zcode.ts +48 -0
  587. package/src/foreign/read-zed.ts +479 -0
  588. package/src/foreign/reasonix.test.ts +336 -0
  589. package/src/foreign/reasonix.ts +25 -0
  590. package/src/foreign/registry.test.ts +377 -0
  591. package/src/foreign/registry.ts +750 -0
  592. package/src/foreign/session-ir.test.ts +189 -0
  593. package/src/foreign/session-ir.ts +614 -0
  594. package/src/foreign/session-read.ts +295 -0
  595. package/src/foreign/session-source.ts +625 -0
  596. package/src/foreign/skill-file-caps.test.ts +171 -0
  597. package/src/foreign/source-modules.ts +86 -0
  598. package/src/foreign/source-registry.test.ts +190 -0
  599. package/src/foreign/sqlite.test.ts +313 -0
  600. package/src/foreign/sqlite.ts +446 -0
  601. package/src/foreign/teleagent.test.ts +147 -0
  602. package/src/foreign/teleagent.ts +62 -0
  603. package/src/foreign/trae.test.ts +316 -0
  604. package/src/foreign/trae.ts +25 -0
  605. package/src/foreign/truncation-report.test.ts +238 -0
  606. package/src/foreign/truth-table.ts +453 -0
  607. package/src/foreign/types.ts +312 -0
  608. package/src/foreign/vibe.test.ts +209 -0
  609. package/src/foreign/vibe.ts +28 -0
  610. package/src/foreign/workbuddy.test.ts +207 -0
  611. package/src/foreign/workbuddy.ts +53 -0
  612. package/src/foreign/zcode.test.ts +224 -0
  613. package/src/foreign/zcode.ts +60 -0
  614. package/src/foreign/zed.test.ts +240 -0
  615. package/src/foreign/zed.ts +62 -0
  616. package/src/index.facade.test.ts +254 -16
  617. package/src/index.ts +704 -82
  618. package/src/market/github-repos.test.ts +98 -1
  619. package/src/market/github-repos.ts +63 -1
  620. package/src/market/types.ts +3 -3
  621. package/src/profiles/dsh-profile-incomplete-copy.test.ts +177 -0
  622. package/src/profiles/dsh-profile-manager.test.ts +37 -0
  623. package/src/profiles/dsh-profile-manager.ts +188 -13
  624. package/src/profiles/dsh-profile-shared.ts +55 -1
  625. package/src/profiles/index.ts +2 -1
  626. package/src/routes/consult.ts +53 -4
  627. package/src/routes/foreign-context.ts +89 -0
  628. package/src/routes/foreign.test.ts +443 -0
  629. package/src/routes/foreign.ts +226 -0
  630. package/src/routes/import.ts +23 -1
  631. package/src/routes/index.ts +6 -2
  632. package/src/routes/kit.ts +4 -3
  633. package/src/routes/market.ts +0 -1
  634. package/src/routes/prefs.ts +15 -1
  635. package/src/routes/recovery.test.ts +167 -0
  636. package/src/routes/recovery.ts +331 -1
  637. package/src/routes/session-export.ts +308 -0
  638. package/src/routes/snapshots.ts +12 -2
  639. package/src/routes/sync.ts +91 -7
  640. package/src/security/redaction.test.ts +149 -0
  641. package/src/security/redaction.ts +25 -9
  642. package/src/security/secret-scanner.test.ts +186 -0
  643. package/src/security/secret-scanner.ts +57 -1
  644. package/src/sync/autosync-risk-tier.test.ts +61 -0
  645. package/src/sync/autosync-scheduler.test.ts +48 -1
  646. package/src/sync/autosync-scheduler.ts +50 -26
  647. package/src/sync/backup-files.ts +5 -0
  648. package/src/sync/gist/gist-msgkeys-catalog.test.ts +33 -0
  649. package/src/sync/gist/gist-msgkeys.test.ts +71 -0
  650. package/src/sync/gist/gist-transport.test.ts +308 -0
  651. package/src/sync/gist/gist-transport.ts +550 -0
  652. package/src/sync/gist/messages.ts +49 -0
  653. package/src/sync/retention-prune-all-off.test.ts +50 -0
  654. package/src/sync/s3/cloud-config.test.ts +283 -0
  655. package/src/sync/s3/messages.ts +102 -0
  656. package/src/sync/s3/s3-delete-index-404.test.ts +170 -0
  657. package/src/sync/s3/s3-delete-index-unreadable.test.ts +141 -0
  658. package/src/sync/s3/s3-msgkeys.test.ts +101 -0
  659. package/src/sync/s3/s3-providers.ts +213 -0
  660. package/src/sync/s3/s3-transport.test.ts +394 -0
  661. package/src/sync/s3/s3-transport.ts +651 -0
  662. package/src/sync/s3/s3-upload-index-404.test.ts +171 -0
  663. package/src/sync/s3/sigv4.test.ts +219 -0
  664. package/src/sync/s3/sigv4.ts +283 -0
  665. package/src/sync/sync-config.test.ts +237 -5
  666. package/src/sync/sync-config.ts +841 -52
  667. package/src/sync/sync-engine-download-tombstone.test.ts +73 -0
  668. package/src/sync/sync-engine.ts +5 -3
  669. package/src/sync/sync-history.ts +1 -1
  670. package/src/sync/webdav/webdav-delete-index-404.test.ts +178 -0
  671. package/src/sync/webdav/webdav-delete-index-unreadable.test.ts +143 -0
  672. package/src/sync/webdav/webdav-msgkeys.test.ts +53 -0
  673. package/src/sync/webdav/webdav-transport.test.ts +9 -5
  674. package/src/sync/webdav/webdav-transport.ts +99 -17
  675. package/src/sync/webdav/webdav-upload-index-404.test.ts +177 -0
  676. package/src/ui/commands.test.ts +4 -1
  677. package/src/ui/commands.ts +46 -12
  678. package/src/ui/disk-usage-view.test.ts +63 -1
  679. package/src/ui/disk-usage-view.ts +93 -1
  680. package/src/ui/dsh-profiles-incomplete-view.test.ts +102 -0
  681. package/src/ui/dsh-profiles-view.ts +94 -0
  682. package/src/ui/foreign-view.test.ts +241 -0
  683. package/src/ui/foreign-view.ts +362 -0
  684. package/src/ui/i18n.ts +164 -0
  685. package/src/ui/mid-ellipsis.test.ts +5 -10
  686. package/src/ui/session-inventory-view.test.ts +142 -2
  687. package/src/ui/session-inventory-view.ts +127 -0
  688. package/src/ui/session-layout-view.test.ts +361 -0
  689. package/src/ui/session-layout-view.ts +444 -0
  690. package/src/ui/sync-repository-picker.test.ts +130 -0
  691. package/src/ui/sync-repository-picker.ts +180 -0
  692. package/src/ui/sync-settings-view.test.ts +166 -0
  693. package/src/ui/sync-settings-view.ts +319 -9
  694. package/src/ui/types.ts +42 -0
  695. package/src/utils/asar-read.test.ts +330 -0
  696. package/src/utils/asar-read.ts +606 -0
  697. package/src/utils/env-lock.test.ts +55 -0
  698. package/src/utils/env-lock.ts +6 -1
  699. package/src/utils/patch-yaml.test.ts +112 -0
  700. package/src/utils/patch-yaml.ts +72 -0
  701. package/src/utils/paths.test.ts +63 -0
  702. package/src/utils/paths.ts +25 -3
  703. package/src/utils/recursive-walk.test.ts +20 -0
  704. package/src/utils/recursive-walk.ts +12 -13
  705. package/src/utils/session-format.test.ts +113 -2
  706. package/src/utils/session-format.ts +127 -5
  707. package/src/utils/session-health-scan.test.ts +364 -1
  708. package/src/utils/session-health-scan.ts +434 -15
  709. package/src/utils/session-layout-repair-service.test.ts +362 -0
  710. package/src/utils/session-layout-repair-service.ts +568 -0
  711. package/src/utils/session-log-repair.test.ts +260 -1
  712. package/src/utils/session-log-repair.ts +294 -55
  713. package/src/utils/session-repair-service.test.ts +148 -1
  714. package/src/utils/session-repair-service.ts +165 -10
  715. package/src/utils/session-row-facts.test.ts +159 -0
  716. package/src/utils/session-row-facts.ts +187 -0
  717. package/src/utils/session-verify.test.ts +762 -0
  718. package/src/utils/session-verify.ts +784 -0
  719. package/src/utils/shared-constants.ts +82 -0
@@ -0,0 +1,66 @@
1
+ import type { ForeignPlatform } from './platform-paths.ts';
2
+ import type { ParsedTranscript, RootProbeOptions, SessionReadOutcome } from './session-source.ts';
3
+ export declare const REASONIX_DIR = ".reasonix";
4
+ export declare const REASONIX_SESSIONS_SUBDIR = "sessions";
5
+ export declare const REASONIX_DESKTOP_DIR = "reasonix";
6
+ /**
7
+ * 静态探测位置(**多根**):`<home>/.reasonix/sessions` +(win32)`%APPDATA%/reasonix`。
8
+ *
9
+ * 为什么 win32 的第二根无条件加入(而不是「仅 $APPDATA 存在时」):真值表把这两条都写进了
10
+ * `defaults.win32`,而 `roamingAppDataDir` 在缺 %APPDATA% 时会回落到 `<home>/AppData/Roaming`
11
+ * —— 条件加入会让 probePaths 与真值表在「空环境」下逐项不等(t6 按合成真值交叉核对时必红)。
12
+ */
13
+ export declare function reasonixSessionRoots(opts: RootProbeOptions): string[];
14
+ /**
15
+ * 一条已归一的会话文件(`ParsedTranscript` + 源侧 id,draftOf 直接透传)。
16
+ *
17
+ * `walMerged` / `walRecords` 是 WAL 合并的可见性报告(绝不静默)。
18
+ */
19
+ export interface ReasonixSessionFile extends ParsedTranscript {
20
+ readonly id: string;
21
+ readonly walMerged: boolean;
22
+ readonly walRecords: number;
23
+ }
24
+ /** 伴生元数据路径(**旧版**):`<stem>.jsonl` → `<stem>.meta.json` */
25
+ export declare function reasonixMetaPath(jsonlPath: string): string;
26
+ /** 伴生元数据路径(**新版**):`<file>.jsonl` → `<file>.jsonl.meta`(chat-import source-derive.mjs:118) */
27
+ export declare function reasonixModernMetaPath(jsonlPath: string): string;
28
+ /** V2 事件日志(WAL)路径:`<stem>.jsonl` → `<stem>.events.jsonl` */
29
+ export declare function reasonixWalPath(jsonlPath: string): string;
30
+ /**
31
+ * stem 内嵌的会话创建时刻(`YYYYMMDDHHMM`,本地时间;chat-import convert/reasonix.mjs:31-41)。
32
+ * 转录行与 meta 都没有时间戳时回退到它 —— 否则会话创建时间会落成**导入时刻**。
33
+ */
34
+ export declare function reasonixStemTime(stem: string): number | undefined;
35
+ /**
36
+ * 桌面版布局 `…/projects/<slug>/sessions/<file>.jsonl`(chat-import source-derive.mjs:210-218):
37
+ * 返回 slug 与 sessions 目录;不是该布局返回 undefined。
38
+ */
39
+ export declare function reasonixDesktopLayout(path: string): {
40
+ readonly slug: string;
41
+ readonly sessionsDir: string;
42
+ } | undefined;
43
+ /**
44
+ * Reasonix 项目 slug 贪心逆解码(chat-import cwd-map.mjs:86-134):磁盘存在性逐段匹配,
45
+ * `c--users--name--proj` → `C:\users\name\proj`,兼容含 `-` 的目录名(合并 ≤3 段)。
46
+ * 只接受**绝对路径**(相对候选会随进程 cwd 漂移,宁可返回 undefined)。
47
+ */
48
+ export declare function greedyDecodeSlugPath(slug: string, platform: ForeignPlatform): Promise<string | undefined>;
49
+ /** 一次解析的结果(含 WAL 合并报告,与参考的 `{walMerged, walRecords}` 同口径) */
50
+ export interface ReasonixParseResult extends ParsedTranscript {
51
+ readonly walMerged: boolean;
52
+ readonly walRecords: number;
53
+ }
54
+ /**
55
+ * checkpoint JSONL(+ 可选 V2 WAL)→ 归一记录。
56
+ *
57
+ * WAL 合并(chat-import convert/reasonix.mjs:58-74):
58
+ * · `{type:'replace', messages:[…]}` = 权威快照,**整表替换** checkpoint;
59
+ * · 其余行按出现顺序追加到 checkpoint 之后(晚到者胜);
60
+ * · 无 WAL / 空 WAL → 纯 checkpoint(旧行为)。
61
+ */
62
+ export declare function parseReasonixTranscript(checkpointText: string, walText?: string | null): ReasonixParseResult;
63
+ /** 读全部 reasonix 会话(多根;同 id 先到先得,不覆盖 —— 与全局「同 id 只允许一条」同口径) */
64
+ export declare function readReasonix(opts: RootProbeOptions & {
65
+ readonly maxFiles?: number;
66
+ }): Promise<SessionReadOutcome<ReasonixSessionFile>>;
@@ -0,0 +1,537 @@
1
+ /**
2
+ * Reasonix 会话读盘层 —— 档 B 文件类来源(真值表见 truth-table.ts 的 reasonix 行)。
3
+ *
4
+ * 布局(chat-import discovery/jsonl.mjs:178-234、tools/source-derive.mjs:102-287;read-vault §10.2):
5
+ * CLI :<home>/.reasonix/sessions/<stem>.jsonl + 伴生 <stem>.meta.json(旧版)
6
+ * + 伴生 <file>.jsonl.meta(新版)
7
+ * + WAL <stem>.events.jsonl(V2)
8
+ * 桌面:<appdata>/reasonix/projects/<slug>/sessions/<file>.jsonl(.titles.json 权威标题)
9
+ * <appdata>/reasonix 仅在 win32 平台加入(**Windows 桌面端第二根**)。
10
+ *
11
+ * 四条归一(都在本层做实,翻译层只做草稿装配):
12
+ * ① 两代消息形状都接受:assistant 的 `tool_calls`(v1 嵌套 `function{name,arguments}`,
13
+ * v2 扁平 `{id,name,arguments}`)与 `role:"tool"` 的结果记录**必须**配对成
14
+ * assistant(tool_call) + user(tool_result) 两条归一记录(DSH 合成器硬校验工具生命周期闭合);
15
+ * ② `<stem>.events.jsonl`(V2 WAL)合并进 checkpoint:`{type:'replace',messages:[…]}` 整表接管,
16
+ * 其余行按顺序追加(chat-import convert/reasonix.mjs:49-74);
17
+ * ③ `.events/.conflicts/.guardian.jsonl` 是**旁路日志不是会话** → 绝不扫描(否则幻影会话 +
18
+ * 幻影 session-empty);`subagent-sub-*` 子代理会话只计数报码,不当独立对话;
19
+ * ④ usage 的 snake_case 桶名(input_tokens…)归一到 IR 的 camelCase 口径,
20
+ * stem 内嵌时刻(YYYYMMDDHHMM)作 createdAt 的最后兜底(否则会话时间落成导入时刻)。
21
+ *
22
+ * 纪律:路径函数显式收 platform;cwd 只有「记录字段 / sidecar / slug 逆解码」三种来源,
23
+ * 都没有就留空由下游按 session-missing-cwd 跳过(**绝不猜**);单文件 8 MiB 上限、
24
+ * 目录树深度上限、根不存在 = 正常(未安装),读不到才报码。
25
+ */
26
+ import { isAbsoluteFor, joinFor, normalizePlatform, roamingAppDataDir } from './platform-paths.js';
27
+ import { isDirectory, parseJsonlText, readJsonSafe, readTextSafe, statOrNull, stemOf, walkFiles, } from './session-read.js';
28
+ import { firstUserText } from './session-source.js';
29
+ import { irBump, irEarlier, irSafeTime, irStr, irToolCallBlock, irToolResultBlock, irTextBlock } from './session-ir.js';
30
+ import { isRecord } from '../utils/guards.js';
31
+ export const REASONIX_DIR = '.reasonix';
32
+ export const REASONIX_SESSIONS_SUBDIR = 'sessions';
33
+ export const REASONIX_DESKTOP_DIR = 'reasonix';
34
+ const MAX_FILE_BYTES = 8 * 1024 * 1024;
35
+ const MAX_FILES = 5000;
36
+ const MAX_DEPTH = 6;
37
+ /** 子代理会话(chat-import convert/reasonix.mjs:46):不是独立主会话,只计数报码 */
38
+ const REASONIX_SUBAGENT_RE = /^subagent-/;
39
+ /**
40
+ * 伴生文件(chat-import discovery/jsonl.mjs:183-189 的 isReasonixSidecar):
41
+ * `.events.jsonl` 是 V2 的 WAL、`.conflicts/.guardian.jsonl` 是守护日志 —— 都不是会话。
42
+ * 早期实现按「一切 .jsonl」扫描,于是每个会话都多出 1~3 条幻影会话(stem 变成
43
+ * `desktop-1.events`,且因无 meta 而 session-missing-cwd 或 session-empty)。
44
+ */
45
+ const REASONIX_SIDECAR_RE = /\.(events|conflicts|guardian)\.jsonl$/i;
46
+ const LEGACY_CWD_KEYS = [
47
+ 'workspace', 'cwd', 'workdir', 'workingDirectory', 'working_directory', 'projectPath', 'directory', 'path',
48
+ ];
49
+ const LEGACY_TITLE_KEYS = ['summary', 'title', 'name', 'topic'];
50
+ const TIME_KEYS = ['createdAt', 'created_at', 'startTime', 'startedAt', 'timestamp', 'time', 'updatedAt'];
51
+ const RECORD_TIME_KEYS = ['createdAt', 'created_at', 'timestamp', 'time'];
52
+ /**
53
+ * 静态探测位置(**多根**):`<home>/.reasonix/sessions` +(win32)`%APPDATA%/reasonix`。
54
+ *
55
+ * 为什么 win32 的第二根无条件加入(而不是「仅 $APPDATA 存在时」):真值表把这两条都写进了
56
+ * `defaults.win32`,而 `roamingAppDataDir` 在缺 %APPDATA% 时会回落到 `<home>/AppData/Roaming`
57
+ * —— 条件加入会让 probePaths 与真值表在「空环境」下逐项不等(t6 按合成真值交叉核对时必红)。
58
+ */
59
+ export function reasonixSessionRoots(opts) {
60
+ const platform = normalizePlatform(opts.platform);
61
+ const roots = [joinFor(platform, opts.homeDir, REASONIX_DIR, REASONIX_SESSIONS_SUBDIR)];
62
+ if (platform === 'win32') {
63
+ roots.push(joinFor(platform, roamingAppDataDir(platform, opts.homeDir, opts.env), REASONIX_DESKTOP_DIR));
64
+ }
65
+ return roots;
66
+ }
67
+ function firstStringIn(rec, keys) {
68
+ for (const key of keys) {
69
+ const v = rec[key];
70
+ if (typeof v === 'string' && v !== '')
71
+ return v;
72
+ }
73
+ return undefined;
74
+ }
75
+ function firstTimeIn(rec, keys) {
76
+ for (const key of keys) {
77
+ const t = irSafeTime(rec[key]);
78
+ if (t !== undefined)
79
+ return t;
80
+ }
81
+ return undefined;
82
+ }
83
+ /** 伴生元数据路径(**旧版**):`<stem>.jsonl` → `<stem>.meta.json` */
84
+ export function reasonixMetaPath(jsonlPath) {
85
+ return jsonlPath.slice(0, jsonlPath.length - '.jsonl'.length) + '.meta.json';
86
+ }
87
+ /** 伴生元数据路径(**新版**):`<file>.jsonl` → `<file>.jsonl.meta`(chat-import source-derive.mjs:118) */
88
+ export function reasonixModernMetaPath(jsonlPath) {
89
+ return jsonlPath + '.meta';
90
+ }
91
+ /** V2 事件日志(WAL)路径:`<stem>.jsonl` → `<stem>.events.jsonl` */
92
+ export function reasonixWalPath(jsonlPath) {
93
+ return jsonlPath.slice(0, jsonlPath.length - '.jsonl'.length) + '.events.jsonl';
94
+ }
95
+ /**
96
+ * stem 内嵌的会话创建时刻(`YYYYMMDDHHMM`,本地时间;chat-import convert/reasonix.mjs:31-41)。
97
+ * 转录行与 meta 都没有时间戳时回退到它 —— 否则会话创建时间会落成**导入时刻**。
98
+ */
99
+ export function reasonixStemTime(stem) {
100
+ const m = /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})/.exec(stem);
101
+ if (m === null)
102
+ return undefined;
103
+ const month = Number(m[2]);
104
+ const day = Number(m[3]);
105
+ const hour = Number(m[4]);
106
+ const minute = Number(m[5]);
107
+ if (month < 1 || month > 12 || day < 1 || day > 31 || hour > 23 || minute > 59)
108
+ return undefined;
109
+ const t = new Date(Number(m[1]), month - 1, day, hour, minute).getTime();
110
+ return Number.isNaN(t) ? undefined : t;
111
+ }
112
+ /**
113
+ * 桌面版布局 `…/projects/<slug>/sessions/<file>.jsonl`(chat-import source-derive.mjs:210-218):
114
+ * 返回 slug 与 sessions 目录;不是该布局返回 undefined。
115
+ */
116
+ export function reasonixDesktopLayout(path) {
117
+ const value = path.replace(/[\\/]+$/, '');
118
+ const segs = value.split(/[\\/]/);
119
+ const sessionsIdx = segs.lastIndexOf('sessions');
120
+ if (sessionsIdx < 2 || segs[sessionsIdx - 2] !== 'projects')
121
+ return undefined;
122
+ const slug = segs[sessionsIdx - 1];
123
+ if (slug === undefined || slug === '')
124
+ return undefined;
125
+ // 前 sessionsIdx+1 段在原串里的长度 = 各段长度 + 段间分隔符(保留输入的分隔符风格)
126
+ const end = segs.slice(0, sessionsIdx + 1).reduce((n, seg) => n + seg.length, 0) + sessionsIdx;
127
+ return { slug, sessionsDir: value.slice(0, end) };
128
+ }
129
+ /**
130
+ * Reasonix 项目 slug 贪心逆解码(chat-import cwd-map.mjs:86-134):磁盘存在性逐段匹配,
131
+ * `c--users--name--proj` → `C:\users\name\proj`,兼容含 `-` 的目录名(合并 ≤3 段)。
132
+ * 只接受**绝对路径**(相对候选会随进程 cwd 漂移,宁可返回 undefined)。
133
+ */
134
+ export async function greedyDecodeSlugPath(slug, platform) {
135
+ const segments = slug.split('-').filter((s) => s !== '');
136
+ if (segments.length === 0)
137
+ return undefined;
138
+ let base;
139
+ let rest = segments;
140
+ const head = segments[0] ?? '';
141
+ if (platform === 'win32' && /^[a-z]$/.test(head)) {
142
+ base = head.toUpperCase() + ':';
143
+ rest = segments.slice(1);
144
+ }
145
+ else if (slug.startsWith('-')) {
146
+ base = '/';
147
+ }
148
+ const build = (parts) => base === undefined ? joinFor(platform, ...parts) : joinFor(platform, base, ...parts);
149
+ const exists = async (p) => isAbsoluteFor(platform, p) && (await isDirectory(p));
150
+ const matched = [];
151
+ let i = 0;
152
+ while (i < rest.length) {
153
+ if (await exists(build([...matched, ...rest.slice(i)])))
154
+ return build([...matched, ...rest.slice(i)]);
155
+ const single = rest[i] ?? '';
156
+ if (await exists(build([...matched, single]))) {
157
+ matched.push(single);
158
+ i += 1;
159
+ continue;
160
+ }
161
+ let consumed = 0;
162
+ for (let n = 2; n <= 3 && i + n <= rest.length; n += 1) {
163
+ const merged = rest.slice(i, i + n).join('-');
164
+ if (await exists(build([...matched, merged]))) {
165
+ consumed = n;
166
+ break;
167
+ }
168
+ }
169
+ if (consumed === 0)
170
+ return undefined;
171
+ matched.push(rest.slice(i, i + consumed).join('-'));
172
+ i += consumed;
173
+ }
174
+ return matched.length > 0 ? build(matched) : undefined;
175
+ }
176
+ /* ---------------- 归一解析(两代消息形状 + 工具配对) ---------------- */
177
+ /** usage 桶名两代并存:V2 是 snake_case,IR 只认 camelCase → 在这里归一(否则整份记 0) */
178
+ const USAGE_KEY_MAP = [
179
+ ['input_tokens', 'inputTokens'],
180
+ ['inputTokens', 'inputTokens'],
181
+ ['output_tokens', 'outputTokens'],
182
+ ['outputTokens', 'outputTokens'],
183
+ ['cache_read_tokens', 'cacheReadTokens'],
184
+ ['cacheReadTokens', 'cacheReadTokens'],
185
+ ['reasoning_tokens', 'reasoningTokens'],
186
+ ['reasoningTokens', 'reasoningTokens'],
187
+ ];
188
+ function reasonixUsageOf(raw) {
189
+ if (!isRecord(raw))
190
+ return undefined;
191
+ const out = {};
192
+ for (const [source, target] of USAGE_KEY_MAP) {
193
+ const v = raw[source];
194
+ if (typeof v === 'number' && Number.isSafeInteger(v) && v >= 0 && out[target] === undefined)
195
+ out[target] = v;
196
+ }
197
+ return Object.keys(out).length > 0 ? out : undefined;
198
+ }
199
+ /** 工具入参:字符串是 JSON 就解析(与 session-source.ts 的 toolInputOf 同口径;合成器会再 JSON.stringify) */
200
+ function reasonixToolInput(raw) {
201
+ if (typeof raw === 'string') {
202
+ const trimmed = raw.trim();
203
+ if (trimmed.startsWith('{') || trimmed.startsWith('[')) {
204
+ try {
205
+ return JSON.parse(trimmed);
206
+ }
207
+ catch {
208
+ return raw;
209
+ }
210
+ }
211
+ }
212
+ return raw;
213
+ }
214
+ function recordTimeOf(rec, keys) {
215
+ for (const key of keys) {
216
+ const t = irSafeTime(rec[key]);
217
+ if (t !== undefined)
218
+ return t;
219
+ }
220
+ return undefined;
221
+ }
222
+ /**
223
+ * 归一记录(不含 WAL 合并):user / assistant(两代 tool_calls) / tool(结果配对)。
224
+ *
225
+ * 结果按 callId 挂回**声明它的那条 assistant 记录**,随后者之后补一条 user(tool_result):
226
+ * DSH 合成器要求 tool/result 与 tool/call 同 step 且紧随其后(session-ir.ts:296)。
227
+ */
228
+ function buildReasonixRecords(objects, ignored) {
229
+ const records = [];
230
+ const callOwner = new Map();
231
+ const openCallIds = [];
232
+ const resultsByCall = new Map();
233
+ let assistantCount = 0;
234
+ const attach = (callId, text) => {
235
+ const declared = callId !== undefined && callOwner.has(callId) ? callId : undefined;
236
+ // 对不上 callId 时挂到「最近一个尚无结果的调用」(参考 convert/reasonix.mjs:142 的 lastStep 口径)
237
+ const target = declared ?? openCallIds[openCallIds.length - 1];
238
+ if (target === undefined) {
239
+ irBump(ignored, 'orphan-tool-result');
240
+ return;
241
+ }
242
+ const block = irToolResultBlock(target, text, false);
243
+ const list = resultsByCall.get(target);
244
+ if (list === undefined)
245
+ resultsByCall.set(target, [block]);
246
+ else
247
+ list.push(block);
248
+ const i = openCallIds.indexOf(target);
249
+ if (i >= 0)
250
+ openCallIds.splice(i, 1);
251
+ };
252
+ for (const rec of objects) {
253
+ const role = irStr(rec['role']);
254
+ const time = recordTimeOf(rec, RECORD_TIME_KEYS);
255
+ if (role === 'user') {
256
+ const content = rec['content'];
257
+ if (typeof content !== 'string') {
258
+ irBump(ignored, content === undefined || content === null ? 'user-empty' : 'user:non-string-content');
259
+ continue;
260
+ }
261
+ const prompt = content.trim();
262
+ if (prompt === '') {
263
+ irBump(ignored, 'user-empty');
264
+ continue;
265
+ }
266
+ records.push({ role: 'user', blocks: [irTextBlock(content)], time });
267
+ continue;
268
+ }
269
+ if (role === 'assistant') {
270
+ assistantCount += 1;
271
+ const blocks = [];
272
+ const content = rec['content'];
273
+ if (typeof content === 'string' && content.trim() !== '')
274
+ blocks.push(irTextBlock(content));
275
+ // reasoning_content:IR 没有 reasoning 承载块 → 逐类计数(绝不塞进正文)
276
+ if (rec['reasoning_content'] !== undefined || rec['reasoningContent'] !== undefined)
277
+ irBump(ignored, 'reasoning_content');
278
+ const rawCalls = rec['tool_calls'] ?? rec['toolCalls'];
279
+ let callIndex = 0;
280
+ if (rawCalls !== undefined) {
281
+ if (!Array.isArray(rawCalls)) {
282
+ irBump(ignored, 'tool_calls:not-an-array');
283
+ }
284
+ else {
285
+ for (const tc of rawCalls) {
286
+ if (!isRecord(tc)) {
287
+ irBump(ignored, 'toolCall:not-an-object');
288
+ continue;
289
+ }
290
+ callIndex += 1;
291
+ // v1:{id,type:'function',function:{name,arguments}};v2:{id,name,arguments}(扁平)
292
+ const fn = isRecord(tc['function']) ? tc['function'] : tc;
293
+ const id = irStr(tc['id']) ?? 'reasonix-' + String(assistantCount) + '-' + String(callIndex);
294
+ const name = irStr(fn['name']) ?? 'unknown';
295
+ const args = fn['arguments'] ?? tc['arguments'] ?? fn['args'] ?? tc['args'];
296
+ blocks.push(irToolCallBlock(id, name, reasonixToolInput(args)));
297
+ callOwner.set(id, records.length);
298
+ openCallIds.push(id);
299
+ }
300
+ }
301
+ }
302
+ if (blocks.length === 0) {
303
+ irBump(ignored, 'assistant-empty');
304
+ continue;
305
+ }
306
+ const model = irStr(rec['model']);
307
+ const usage = reasonixUsageOf(rec['usage']);
308
+ records.push({
309
+ role: 'assistant',
310
+ blocks,
311
+ time,
312
+ ...(model === undefined ? {} : { model }),
313
+ ...(usage === undefined ? {} : { usage }),
314
+ });
315
+ continue;
316
+ }
317
+ if (role === 'tool') {
318
+ const content = rec['content'];
319
+ const text = typeof content === 'string' ? content : content === undefined ? '' : JSON.stringify(content);
320
+ attach(irStr(rec['tool_call_id']) ?? irStr(rec['call_id']), text);
321
+ continue;
322
+ }
323
+ irBump(ignored, role ?? irStr(rec['type']) ?? 'unknown');
324
+ }
325
+ // 结果插到「声明它的 assistant 记录」之后(保持源顺序内的相对位置)
326
+ const out = [];
327
+ for (const rec of records) {
328
+ out.push(rec);
329
+ if (rec.role !== 'assistant')
330
+ continue;
331
+ const collected = [];
332
+ for (const block of rec.blocks) {
333
+ if (block.type !== 'tool_call')
334
+ continue;
335
+ const got = resultsByCall.get(block.id);
336
+ if (got !== undefined) {
337
+ collected.push(...got);
338
+ resultsByCall.delete(block.id);
339
+ }
340
+ }
341
+ if (collected.length > 0)
342
+ out.push({ role: 'user', blocks: collected });
343
+ }
344
+ let orphaned = 0;
345
+ for (const leftover of resultsByCall.values())
346
+ orphaned += leftover.length;
347
+ if (orphaned > 0)
348
+ irBump(ignored, 'orphan-tool-result', orphaned);
349
+ return out;
350
+ }
351
+ /**
352
+ * checkpoint JSONL(+ 可选 V2 WAL)→ 归一记录。
353
+ *
354
+ * WAL 合并(chat-import convert/reasonix.mjs:58-74):
355
+ * · `{type:'replace', messages:[…]}` = 权威快照,**整表替换** checkpoint;
356
+ * · 其余行按出现顺序追加到 checkpoint 之后(晚到者胜);
357
+ * · 无 WAL / 空 WAL → 纯 checkpoint(旧行为)。
358
+ */
359
+ export function parseReasonixTranscript(checkpointText, walText) {
360
+ const checkpoint = parseJsonlText(checkpointText);
361
+ let objects = checkpoint.objects;
362
+ let bad = checkpoint.bad;
363
+ let walMerged = false;
364
+ let walRecords = 0;
365
+ if (typeof walText === 'string' && walText.trim() !== '') {
366
+ const wal = parseJsonlText(walText);
367
+ bad += wal.bad;
368
+ const replace = wal.objects.find((r) => r['type'] === 'replace' && Array.isArray(r['messages']));
369
+ if (replace !== undefined) {
370
+ const messages = replace['messages'].filter(isRecord);
371
+ walMerged = true;
372
+ walRecords = messages.length;
373
+ objects = messages;
374
+ }
375
+ else if (wal.objects.length > 0) {
376
+ walMerged = true;
377
+ walRecords = wal.objects.length;
378
+ objects = [...objects, ...wal.objects];
379
+ }
380
+ }
381
+ const ignored = {};
382
+ const records = buildReasonixRecords(objects, ignored);
383
+ let createdAt;
384
+ for (const rec of objects)
385
+ createdAt = irEarlier(createdAt, recordTimeOf(rec, RECORD_TIME_KEYS));
386
+ return {
387
+ records,
388
+ createdAt,
389
+ title: firstUserText(records),
390
+ raw: objects.length,
391
+ bad,
392
+ ignored,
393
+ walMerged,
394
+ walRecords,
395
+ };
396
+ }
397
+ async function readMetaAt(path, label, findings, detail) {
398
+ const read = await readJsonSafe(path, MAX_FILE_BYTES);
399
+ if (!read.ok) {
400
+ if (read.problem !== 'missing') {
401
+ findings.push({ code: 'source-unreadable', origin: label, detail: detail + '-' + read.problem });
402
+ }
403
+ return undefined;
404
+ }
405
+ if (!isRecord(read.value)) {
406
+ findings.push({ code: 'source-unreadable', origin: label, detail: detail + '-not-object' });
407
+ return undefined;
408
+ }
409
+ return read.value;
410
+ }
411
+ /** 两代 sidecar:新版 `<file>.jsonl.meta` 优先,旧版 `<stem>.meta.json` 回退 */
412
+ async function readReasonixMeta(file, label, findings) {
413
+ const modern = await readMetaAt(reasonixModernMetaPath(file.abs), label, findings, 'meta');
414
+ if (modern !== undefined)
415
+ return { record: modern, modern: true };
416
+ const legacy = await readMetaAt(reasonixMetaPath(file.abs), label, findings, 'meta');
417
+ return legacy === undefined ? undefined : { record: legacy, modern: false };
418
+ }
419
+ /** 桌面版 sessions 目录级的 `.titles.json`(basename → 标题);缺失是常态,读不出才报码 */
420
+ async function readReasonixTitles(platform, sessionsDir, label, findings) {
421
+ return await readMetaAt(joinFor(platform, sessionsDir, '.titles.json'), label, findings, 'titles');
422
+ }
423
+ /* ---------------- 单文件读取 ---------------- */
424
+ async function readReasonixSession(file, platform, findings) {
425
+ const id = stemOf(file.name);
426
+ const label = id;
427
+ const st = await statOrNull(file.abs);
428
+ if (st === null || !st.isFile()) {
429
+ findings.push({ code: 'source-unreadable', origin: label, detail: 'missing' });
430
+ return undefined;
431
+ }
432
+ const text = await readTextSafe(file.abs, MAX_FILE_BYTES);
433
+ if (text === null) {
434
+ findings.push({
435
+ code: 'source-unreadable',
436
+ origin: label,
437
+ detail: st.size > MAX_FILE_BYTES ? 'too-large' : 'read-error',
438
+ });
439
+ return undefined;
440
+ }
441
+ const walText = await readTextSafe(reasonixWalPath(file.abs), MAX_FILE_BYTES);
442
+ const parsed = parseReasonixTranscript(text, walText);
443
+ const meta = await readReasonixMeta(file, label, findings);
444
+ const desktop = reasonixDesktopLayout(file.abs);
445
+ // cwd:新版 workspace_root(scope='global' 的会话不属于任何工作区)→ 旧版 workspace →
446
+ // 桌面版 slug 逆解码;都没有 = 留空(下游 session-missing-cwd,绝不猜)
447
+ let cwd;
448
+ if (meta !== undefined) {
449
+ if (meta.modern) {
450
+ if (meta.record['scope'] !== 'global')
451
+ cwd = irStr(meta.record['workspace_root']);
452
+ }
453
+ else {
454
+ cwd = firstStringIn(meta.record, LEGACY_CWD_KEYS);
455
+ }
456
+ }
457
+ if (cwd === undefined && desktop !== undefined)
458
+ cwd = await greedyDecodeSlugPath(desktop.slug, platform);
459
+ // 标题:新版 topic_title → 旧版 summary → 桌面版 .titles.json → 首问兜底
460
+ let title;
461
+ if (meta !== undefined) {
462
+ title = meta.modern ? irStr(meta.record['topic_title']) : firstStringIn(meta.record, LEGACY_TITLE_KEYS);
463
+ }
464
+ if (title === undefined && desktop !== undefined) {
465
+ const titles = await readReasonixTitles(platform, desktop.sessionsDir, label, findings);
466
+ const t = titles?.[id];
467
+ if (typeof t === 'string' && t.trim() !== '')
468
+ title = t.trim();
469
+ }
470
+ const metaTime = meta === undefined ? undefined : firstTimeIn(meta.record, TIME_KEYS);
471
+ const createdAt = irEarlier(irEarlier(metaTime, parsed.createdAt), reasonixStemTime(id));
472
+ return {
473
+ id,
474
+ cwd,
475
+ createdAt,
476
+ title: title === undefined ? parsed.title : title.slice(0, 200),
477
+ records: parsed.records,
478
+ raw: parsed.raw,
479
+ bad: parsed.bad,
480
+ ignored: parsed.ignored,
481
+ walMerged: parsed.walMerged,
482
+ walRecords: parsed.walRecords,
483
+ };
484
+ }
485
+ /** 读全部 reasonix 会话(多根;同 id 先到先得,不覆盖 —— 与全局「同 id 只允许一条」同口径) */
486
+ export async function readReasonix(opts) {
487
+ const platform = normalizePlatform(opts.platform);
488
+ const findings = [];
489
+ const files = [];
490
+ const seen = new Set();
491
+ const maxFiles = opts.maxFiles ?? MAX_FILES;
492
+ // walkFiles 只回数组、不报是否触顶 → 每个根多要一条:拿到 maxFiles+1 条即**证明**触顶(audit-foreign F4)。
493
+ let truncated = false;
494
+ let walked = 0;
495
+ let subagents = 0;
496
+ let walRecords = 0;
497
+ for (const root of reasonixSessionRoots(opts)) {
498
+ const foundAll = await walkFiles(root, {
499
+ match: (name) => name.endsWith('.jsonl') && !REASONIX_SIDECAR_RE.test(name),
500
+ maxDepth: MAX_DEPTH,
501
+ maxFiles: maxFiles + 1,
502
+ });
503
+ if (foundAll.length > maxFiles)
504
+ truncated = true;
505
+ const found = foundAll.length > maxFiles ? foundAll.slice(0, maxFiles) : foundAll;
506
+ for (const entry of found) {
507
+ const stem = stemOf(entry.name);
508
+ // 子代理会话不是独立主会话:只计数报码,绝不产出碎片对话(chat-import convert/reasonix.mjs:46)
509
+ if (REASONIX_SUBAGENT_RE.test(stem)) {
510
+ subagents += 1;
511
+ continue;
512
+ }
513
+ walked += 1;
514
+ if (seen.has(stem))
515
+ continue;
516
+ const file = await readReasonixSession(entry, platform, findings);
517
+ if (file === undefined)
518
+ continue;
519
+ seen.add(file.id);
520
+ walRecords += file.walRecords;
521
+ files.push(file);
522
+ }
523
+ }
524
+ files.sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
525
+ if (truncated)
526
+ findings.push({ code: 'source-unreadable', origin: 'reasonix', detail: 'max-sessions-reached', count: maxFiles });
527
+ const extraSkips = subagents > 0
528
+ ? [{ code: 'unsupported-session-record', origin: 'subagents', detail: 'subagent-session', count: subagents }]
529
+ : [];
530
+ const extraCounts = { 'reasonix.files': walked };
531
+ if (subagents > 0)
532
+ extraCounts['reasonix.subagentSessions'] = subagents;
533
+ if (walRecords > 0)
534
+ extraCounts['reasonix.walRecords'] = walRecords;
535
+ return { files, readFindings: findings, extraSkips, extraCounts };
536
+ }
537
+ //# sourceMappingURL=read-reasonix.js.map
@@ -0,0 +1,15 @@
1
+ import type { SqliteDeps, SqliteSessionFile } from './read-opencode.ts';
2
+ import type { SessionReadOutcome } from './session-source.ts';
3
+ export interface TeleagentPathInput {
4
+ readonly homeDir: string;
5
+ readonly platform: string;
6
+ readonly env: Readonly<Record<string, string | undefined>>;
7
+ }
8
+ /** `$TELEAGENT_HOME`(**仅绝对路径**生效)替换基座 → `<base>/users`;否则 `~/.local/share/TeleAgent/users` */
9
+ export declare function teleagentUsersDir(opts: TeleagentPathInput): string;
10
+ export interface TeleagentReadOptions extends TeleagentPathInput {
11
+ /** 仅测试注入 */
12
+ readonly sqliteDeps?: SqliteDeps | undefined;
13
+ }
14
+ /** 读盘入口(wiring 的 `read`:枚举账户 → 每库一次家族读) */
15
+ export declare function readTeleagent(opts: TeleagentReadOptions): Promise<SessionReadOutcome<SqliteSessionFile>>;