@prestyj/cli 5.10.0 → 5.12.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 (703) hide show
  1. package/README.md +3 -4
  2. package/assets/skills/compliance-guard/SKILL.md +251 -0
  3. package/assets/skills/compliance-guard/references/artifacts.md +186 -0
  4. package/assets/skills/compliance-guard/references/eu-uk.md +151 -0
  5. package/assets/skills/compliance-guard/references/exposure-triage.md +161 -0
  6. package/assets/skills/compliance-guard/references/lawsuit-vectors.md +141 -0
  7. package/assets/skills/compliance-guard/references/provenance.md +42 -0
  8. package/assets/skills/compliance-guard/references/sector-gates.md +173 -0
  9. package/assets/skills/compliance-guard/references/security-baseline.md +130 -0
  10. package/assets/skills/compliance-guard/references/trigger-map.md +163 -0
  11. package/assets/skills/compliance-guard/references/us.md +164 -0
  12. package/dist/app-sidecar-auth-broadcast.test.d.ts +2 -0
  13. package/dist/app-sidecar-auth-broadcast.test.d.ts.map +1 -0
  14. package/dist/app-sidecar-auth-broadcast.test.js +348 -0
  15. package/dist/app-sidecar-auth-broadcast.test.js.map +1 -0
  16. package/dist/app-sidecar-sessions.d.ts +5 -2
  17. package/dist/app-sidecar-sessions.d.ts.map +1 -1
  18. package/dist/app-sidecar-sessions.js +34 -8
  19. package/dist/app-sidecar-sessions.js.map +1 -1
  20. package/dist/app-sidecar-sessions.test.js +96 -1
  21. package/dist/app-sidecar-sessions.test.js.map +1 -1
  22. package/dist/app-sidecar.js +616 -173
  23. package/dist/app-sidecar.js.map +1 -1
  24. package/dist/chat-agents/jiwa.test.js +1 -1
  25. package/dist/cli/auth.d.ts.map +1 -1
  26. package/dist/cli/auth.js +33 -36
  27. package/dist/cli/auth.js.map +1 -1
  28. package/dist/cli/command-routing.d.ts +1 -1
  29. package/dist/cli/command-routing.d.ts.map +1 -1
  30. package/dist/cli/command-routing.js +1 -0
  31. package/dist/cli/command-routing.js.map +1 -1
  32. package/dist/cli/command-routing.test.js +1 -0
  33. package/dist/cli/command-routing.test.js.map +1 -1
  34. package/dist/cli.d.ts.map +1 -1
  35. package/dist/cli.js +179 -48
  36. package/dist/cli.js.map +1 -1
  37. package/dist/config.d.ts +18 -5
  38. package/dist/config.d.ts.map +1 -1
  39. package/dist/config.js +45 -76
  40. package/dist/config.js.map +1 -1
  41. package/dist/config.test.js +30 -13
  42. package/dist/config.test.js.map +1 -1
  43. package/dist/core/agent-notifications.d.ts +62 -0
  44. package/dist/core/agent-notifications.d.ts.map +1 -0
  45. package/dist/core/agent-notifications.js +92 -0
  46. package/dist/core/agent-notifications.js.map +1 -0
  47. package/dist/core/agent-notifications.test.d.ts +2 -0
  48. package/dist/core/agent-notifications.test.d.ts.map +1 -0
  49. package/dist/core/agent-notifications.test.js +97 -0
  50. package/dist/core/agent-notifications.test.js.map +1 -0
  51. package/dist/core/agent-session-checkpoint-flush.test.d.ts +2 -0
  52. package/dist/core/agent-session-checkpoint-flush.test.d.ts.map +1 -0
  53. package/dist/core/agent-session-checkpoint-flush.test.js +201 -0
  54. package/dist/core/agent-session-checkpoint-flush.test.js.map +1 -0
  55. package/dist/core/agent-session-compaction.test.js +323 -6
  56. package/dist/core/agent-session-compaction.test.js.map +1 -1
  57. package/dist/core/agent-session-crash-durability.test.d.ts +2 -0
  58. package/dist/core/agent-session-crash-durability.test.d.ts.map +1 -0
  59. package/dist/core/agent-session-crash-durability.test.js +102 -0
  60. package/dist/core/agent-session-crash-durability.test.js.map +1 -0
  61. package/dist/core/agent-session-marker-anchors.test.js +181 -2
  62. package/dist/core/agent-session-marker-anchors.test.js.map +1 -1
  63. package/dist/core/agent-session-model-switch.test.d.ts +2 -0
  64. package/dist/core/agent-session-model-switch.test.d.ts.map +1 -0
  65. package/dist/core/agent-session-model-switch.test.js +161 -0
  66. package/dist/core/agent-session-model-switch.test.js.map +1 -0
  67. package/dist/core/agent-session-notifications.test.d.ts +2 -0
  68. package/dist/core/agent-session-notifications.test.d.ts.map +1 -0
  69. package/dist/core/agent-session-notifications.test.js +114 -0
  70. package/dist/core/agent-session-notifications.test.js.map +1 -0
  71. package/dist/core/agent-session-process-gate.test.d.ts +2 -0
  72. package/dist/core/agent-session-process-gate.test.d.ts.map +1 -0
  73. package/dist/core/agent-session-process-gate.test.js +98 -0
  74. package/dist/core/agent-session-process-gate.test.js.map +1 -0
  75. package/dist/core/agent-session-queue.test.js +65 -0
  76. package/dist/core/agent-session-queue.test.js.map +1 -1
  77. package/dist/core/agent-session-review-coverage.test.js +80 -23
  78. package/dist/core/agent-session-review-coverage.test.js.map +1 -1
  79. package/dist/core/agent-session-slash-restore.test.d.ts +2 -0
  80. package/dist/core/agent-session-slash-restore.test.d.ts.map +1 -0
  81. package/dist/core/agent-session-slash-restore.test.js +121 -0
  82. package/dist/core/agent-session-slash-restore.test.js.map +1 -0
  83. package/dist/core/agent-session-tool-tiers.test.d.ts +2 -0
  84. package/dist/core/agent-session-tool-tiers.test.d.ts.map +1 -0
  85. package/dist/core/agent-session-tool-tiers.test.js +138 -0
  86. package/dist/core/agent-session-tool-tiers.test.js.map +1 -0
  87. package/dist/core/agent-session.d.ts +257 -13
  88. package/dist/core/agent-session.d.ts.map +1 -1
  89. package/dist/core/agent-session.js +1118 -241
  90. package/dist/core/agent-session.js.map +1 -1
  91. package/dist/core/agents.d.ts +29 -1
  92. package/dist/core/agents.d.ts.map +1 -1
  93. package/dist/core/agents.js +47 -97
  94. package/dist/core/agents.js.map +1 -1
  95. package/dist/core/agents.test.js +87 -7
  96. package/dist/core/agents.test.js.map +1 -1
  97. package/dist/core/api-benchmark.d.ts +3 -3
  98. package/dist/core/api-benchmark.js +7 -7
  99. package/dist/core/auth-providers.d.ts +37 -1
  100. package/dist/core/auth-providers.d.ts.map +1 -1
  101. package/dist/core/auth-providers.js +83 -3
  102. package/dist/core/auth-providers.js.map +1 -1
  103. package/dist/core/auto-update.test.js +1 -1
  104. package/dist/core/autopilot-gate.d.ts +2 -2
  105. package/dist/core/autopilot-gate.js +1 -1
  106. package/dist/core/bash-spawn-benchmark.js +6 -6
  107. package/dist/core/bundled-agents.d.ts +3 -0
  108. package/dist/core/bundled-agents.d.ts.map +1 -0
  109. package/dist/core/bundled-agents.js +252 -0
  110. package/dist/core/bundled-agents.js.map +1 -0
  111. package/dist/core/cache-warm-benchmark.d.ts +2 -2
  112. package/dist/core/cache-warm-benchmark.js +5 -5
  113. package/dist/core/code-retrieval-chunkers.d.ts +27 -0
  114. package/dist/core/code-retrieval-chunkers.d.ts.map +1 -0
  115. package/dist/core/code-retrieval-chunkers.js +264 -0
  116. package/dist/core/code-retrieval-chunkers.js.map +1 -0
  117. package/dist/core/code-retrieval-chunkers.test.d.ts +2 -0
  118. package/dist/core/code-retrieval-chunkers.test.d.ts.map +1 -0
  119. package/dist/core/code-retrieval-chunkers.test.js +203 -0
  120. package/dist/core/code-retrieval-chunkers.test.js.map +1 -0
  121. package/dist/core/code-retrieval.d.ts +6 -0
  122. package/dist/core/code-retrieval.d.ts.map +1 -1
  123. package/dist/core/code-retrieval.js +38 -1
  124. package/dist/core/code-retrieval.js.map +1 -1
  125. package/dist/core/compaction/active-context.test.js +21 -0
  126. package/dist/core/compaction/active-context.test.js.map +1 -1
  127. package/dist/core/compaction/compactor.d.ts +108 -8
  128. package/dist/core/compaction/compactor.d.ts.map +1 -1
  129. package/dist/core/compaction/compactor.js +423 -119
  130. package/dist/core/compaction/compactor.js.map +1 -1
  131. package/dist/core/compaction/compactor.test.js +360 -8
  132. package/dist/core/compaction/compactor.test.js.map +1 -1
  133. package/dist/core/compaction/policy.d.ts +17 -0
  134. package/dist/core/compaction/policy.d.ts.map +1 -0
  135. package/dist/core/compaction/policy.js +22 -0
  136. package/dist/core/compaction/policy.js.map +1 -0
  137. package/dist/core/compaction/policy.test.d.ts +2 -0
  138. package/dist/core/compaction/policy.test.d.ts.map +1 -0
  139. package/dist/core/compaction/policy.test.js +35 -0
  140. package/dist/core/compaction/policy.test.js.map +1 -0
  141. package/dist/core/compaction/query-aware-selector.d.ts +33 -0
  142. package/dist/core/compaction/query-aware-selector.d.ts.map +1 -0
  143. package/dist/core/compaction/query-aware-selector.js +202 -0
  144. package/dist/core/compaction/query-aware-selector.js.map +1 -0
  145. package/dist/core/compaction/query-aware-selector.test.d.ts +2 -0
  146. package/dist/core/compaction/query-aware-selector.test.d.ts.map +1 -0
  147. package/dist/core/compaction/query-aware-selector.test.js +96 -0
  148. package/dist/core/compaction/query-aware-selector.test.js.map +1 -0
  149. package/dist/core/compaction/tool-result-pruner.d.ts +24 -11
  150. package/dist/core/compaction/tool-result-pruner.d.ts.map +1 -1
  151. package/dist/core/compaction/tool-result-pruner.js +98 -26
  152. package/dist/core/compaction/tool-result-pruner.js.map +1 -1
  153. package/dist/core/compaction/tool-result-pruner.test.js +178 -6
  154. package/dist/core/compaction/tool-result-pruner.test.js.map +1 -1
  155. package/dist/core/encode-cwd.test.js +1 -1
  156. package/dist/core/event-bus.d.ts +23 -0
  157. package/dist/core/event-bus.d.ts.map +1 -1
  158. package/dist/core/event-bus.js +10 -0
  159. package/dist/core/event-bus.js.map +1 -1
  160. package/dist/core/extensions/loader.d.ts.map +1 -1
  161. package/dist/core/extensions/loader.js +28 -8
  162. package/dist/core/extensions/loader.js.map +1 -1
  163. package/dist/core/extensions/plugin-bundles.d.ts +23 -0
  164. package/dist/core/extensions/plugin-bundles.d.ts.map +1 -0
  165. package/dist/core/extensions/plugin-bundles.js +228 -0
  166. package/dist/core/extensions/plugin-bundles.js.map +1 -0
  167. package/dist/core/extensions/plugin-bundles.test.d.ts +2 -0
  168. package/dist/core/extensions/plugin-bundles.test.d.ts.map +1 -0
  169. package/dist/core/extensions/plugin-bundles.test.js +110 -0
  170. package/dist/core/extensions/plugin-bundles.test.js.map +1 -0
  171. package/dist/core/fast-apply-benchmark.d.ts +2 -2
  172. package/dist/core/fast-apply-benchmark.js +6 -6
  173. package/dist/core/foreign-session-import.d.ts +120 -0
  174. package/dist/core/foreign-session-import.d.ts.map +1 -0
  175. package/dist/core/foreign-session-import.js +598 -0
  176. package/dist/core/foreign-session-import.js.map +1 -0
  177. package/dist/core/foreign-session-import.test.d.ts +2 -0
  178. package/dist/core/foreign-session-import.test.d.ts.map +1 -0
  179. package/dist/core/foreign-session-import.test.js +220 -0
  180. package/dist/core/foreign-session-import.test.js.map +1 -0
  181. package/dist/core/foreign-transcript-blocks.d.ts +51 -0
  182. package/dist/core/foreign-transcript-blocks.d.ts.map +1 -0
  183. package/dist/core/foreign-transcript-blocks.js +151 -0
  184. package/dist/core/foreign-transcript-blocks.js.map +1 -0
  185. package/dist/core/goal-lifecycle-smoke.test.js +2 -2
  186. package/dist/core/goal-store.js +1 -1
  187. package/dist/core/goal-store.test.js +2 -2
  188. package/dist/core/goal-verifier.test.js +2 -2
  189. package/dist/core/goal-worker-dev-server-lifecycle.test.js +1 -1
  190. package/dist/core/goal-worker.test.js +2 -2
  191. package/dist/core/hashline-edit-benchmark.d.ts +2 -2
  192. package/dist/core/hashline-edit-benchmark.js +7 -7
  193. package/dist/core/ideal-review.d.ts +20 -1
  194. package/dist/core/ideal-review.d.ts.map +1 -1
  195. package/dist/core/ideal-review.js +37 -2
  196. package/dist/core/ideal-review.js.map +1 -1
  197. package/dist/core/ideal-review.test.js +99 -3
  198. package/dist/core/ideal-review.test.js.map +1 -1
  199. package/dist/core/local-endpoint-store.test.js +1 -1
  200. package/dist/core/logger.d.ts +1 -1
  201. package/dist/core/logger.js +2 -2
  202. package/dist/core/logger.js.map +1 -1
  203. package/dist/core/loop-breaker.d.ts.map +1 -1
  204. package/dist/core/loop-breaker.js +1 -0
  205. package/dist/core/loop-breaker.js.map +1 -1
  206. package/dist/core/lsp/client-navigation.test.d.ts +2 -0
  207. package/dist/core/lsp/client-navigation.test.d.ts.map +1 -0
  208. package/dist/core/lsp/client-navigation.test.js +135 -0
  209. package/dist/core/lsp/client-navigation.test.js.map +1 -0
  210. package/dist/core/lsp/client.d.ts +84 -0
  211. package/dist/core/lsp/client.d.ts.map +1 -1
  212. package/dist/core/lsp/client.js +190 -3
  213. package/dist/core/lsp/client.js.map +1 -1
  214. package/dist/core/lsp/integration.test.js +2 -2
  215. package/dist/core/lsp/manager-navigation.test.d.ts +2 -0
  216. package/dist/core/lsp/manager-navigation.test.d.ts.map +1 -0
  217. package/dist/core/lsp/manager-navigation.test.js +121 -0
  218. package/dist/core/lsp/manager-navigation.test.js.map +1 -0
  219. package/dist/core/lsp/manager.d.ts +81 -9
  220. package/dist/core/lsp/manager.d.ts.map +1 -1
  221. package/dist/core/lsp/manager.js +183 -64
  222. package/dist/core/lsp/manager.js.map +1 -1
  223. package/dist/core/lsp/manager.test.js +18 -0
  224. package/dist/core/lsp/manager.test.js.map +1 -1
  225. package/dist/core/lsp/pool.d.ts +113 -0
  226. package/dist/core/lsp/pool.d.ts.map +1 -0
  227. package/dist/core/lsp/pool.js +255 -0
  228. package/dist/core/lsp/pool.js.map +1 -0
  229. package/dist/core/lsp/pool.test.d.ts +2 -0
  230. package/dist/core/lsp/pool.test.d.ts.map +1 -0
  231. package/dist/core/lsp/pool.test.js +286 -0
  232. package/dist/core/lsp/pool.test.js.map +1 -0
  233. package/dist/core/lsp/servers.d.ts.map +1 -1
  234. package/dist/core/lsp/servers.js +43 -3
  235. package/dist/core/lsp/servers.js.map +1 -1
  236. package/dist/core/lsp/servers.test.d.ts +2 -0
  237. package/dist/core/lsp/servers.test.d.ts.map +1 -0
  238. package/dist/core/lsp/servers.test.js +67 -0
  239. package/dist/core/lsp/servers.test.js.map +1 -0
  240. package/dist/core/lsp/windows.test.js +6 -18
  241. package/dist/core/lsp/windows.test.js.map +1 -1
  242. package/dist/core/mcp/catalog-cache.d.ts +63 -0
  243. package/dist/core/mcp/catalog-cache.d.ts.map +1 -0
  244. package/dist/core/mcp/catalog-cache.js +163 -0
  245. package/dist/core/mcp/catalog-cache.js.map +1 -0
  246. package/dist/core/mcp/catalog-cache.test.d.ts +2 -0
  247. package/dist/core/mcp/catalog-cache.test.d.ts.map +1 -0
  248. package/dist/core/mcp/catalog-cache.test.js +99 -0
  249. package/dist/core/mcp/catalog-cache.test.js.map +1 -0
  250. package/dist/core/mcp/client-session-recovery.test.d.ts +2 -0
  251. package/dist/core/mcp/client-session-recovery.test.d.ts.map +1 -0
  252. package/dist/core/mcp/client-session-recovery.test.js +231 -0
  253. package/dist/core/mcp/client-session-recovery.test.js.map +1 -0
  254. package/dist/core/mcp/client.d.ts +158 -0
  255. package/dist/core/mcp/client.d.ts.map +1 -1
  256. package/dist/core/mcp/client.js +478 -45
  257. package/dist/core/mcp/client.js.map +1 -1
  258. package/dist/core/mcp/content.d.ts +19 -0
  259. package/dist/core/mcp/content.d.ts.map +1 -0
  260. package/dist/core/mcp/content.js +172 -0
  261. package/dist/core/mcp/content.js.map +1 -0
  262. package/dist/core/mcp/content.test.d.ts +2 -0
  263. package/dist/core/mcp/content.test.d.ts.map +1 -0
  264. package/dist/core/mcp/content.test.js +135 -0
  265. package/dist/core/mcp/content.test.js.map +1 -0
  266. package/dist/core/mcp/deferred-catalog.d.ts +1 -1
  267. package/dist/core/mcp/deferred-catalog.js +1 -1
  268. package/dist/core/mcp/elicitation-bridge.d.ts +41 -0
  269. package/dist/core/mcp/elicitation-bridge.d.ts.map +1 -0
  270. package/dist/core/mcp/elicitation-bridge.js +52 -0
  271. package/dist/core/mcp/elicitation-bridge.js.map +1 -0
  272. package/dist/core/mcp/elicitation.test.d.ts +2 -0
  273. package/dist/core/mcp/elicitation.test.d.ts.map +1 -0
  274. package/dist/core/mcp/elicitation.test.js +158 -0
  275. package/dist/core/mcp/elicitation.test.js.map +1 -0
  276. package/dist/core/mcp/index.d.ts +5 -1
  277. package/dist/core/mcp/index.d.ts.map +1 -1
  278. package/dist/core/mcp/index.js +2 -0
  279. package/dist/core/mcp/index.js.map +1 -1
  280. package/dist/core/mcp/legacy-negotiation.test.d.ts +2 -0
  281. package/dist/core/mcp/legacy-negotiation.test.d.ts.map +1 -0
  282. package/dist/core/mcp/legacy-negotiation.test.js +80 -0
  283. package/dist/core/mcp/legacy-negotiation.test.js.map +1 -0
  284. package/dist/core/mcp/oauth-provider.d.ts +1 -2
  285. package/dist/core/mcp/oauth-provider.d.ts.map +1 -1
  286. package/dist/core/mcp/oauth-provider.js +6 -2
  287. package/dist/core/mcp/oauth-provider.js.map +1 -1
  288. package/dist/core/mcp/oauth-store.d.ts +1 -1
  289. package/dist/core/mcp/oauth-store.d.ts.map +1 -1
  290. package/dist/core/mcp/oauth-store.js.map +1 -1
  291. package/dist/core/mcp/oauth-store.test.js +2 -2
  292. package/dist/core/mcp/resolve-stdio.test.js +5 -5
  293. package/dist/core/mcp/session-elicitation-wiring.test.d.ts +2 -0
  294. package/dist/core/mcp/session-elicitation-wiring.test.d.ts.map +1 -0
  295. package/dist/core/mcp/session-elicitation-wiring.test.js +138 -0
  296. package/dist/core/mcp/session-elicitation-wiring.test.js.map +1 -0
  297. package/dist/core/mcp/shared-pool.d.ts +158 -0
  298. package/dist/core/mcp/shared-pool.d.ts.map +1 -0
  299. package/dist/core/mcp/shared-pool.js +235 -0
  300. package/dist/core/mcp/shared-pool.js.map +1 -0
  301. package/dist/core/mcp/shared-pool.test.d.ts +2 -0
  302. package/dist/core/mcp/shared-pool.test.d.ts.map +1 -0
  303. package/dist/core/mcp/shared-pool.test.js +425 -0
  304. package/dist/core/mcp/shared-pool.test.js.map +1 -0
  305. package/dist/core/mcp/store.test.js +5 -5
  306. package/dist/core/mcp/types.d.ts +12 -0
  307. package/dist/core/mcp/types.d.ts.map +1 -1
  308. package/dist/core/mcp/when-connected.test.d.ts +2 -0
  309. package/dist/core/mcp/when-connected.test.d.ts.map +1 -0
  310. package/dist/core/mcp/when-connected.test.js +46 -0
  311. package/dist/core/mcp/when-connected.test.js.map +1 -0
  312. package/dist/core/nolan-context.d.ts.map +1 -1
  313. package/dist/core/nolan-context.js +8 -0
  314. package/dist/core/nolan-context.js.map +1 -1
  315. package/dist/core/nolan-context.test.js +40 -0
  316. package/dist/core/nolan-context.test.js.map +1 -1
  317. package/dist/core/nolan-model.test.js +1 -1
  318. package/dist/core/nolan-prompt.js +8 -5
  319. package/dist/core/nolan-prompt.js.map +1 -1
  320. package/dist/core/nolan-prompt.test.js +5 -0
  321. package/dist/core/nolan-prompt.test.js.map +1 -1
  322. package/dist/core/oauth/xai.d.ts +2 -0
  323. package/dist/core/oauth/xai.d.ts.map +1 -0
  324. package/dist/core/oauth/xai.js +4 -0
  325. package/dist/core/oauth/xai.js.map +1 -0
  326. package/dist/core/persistent-shell.d.ts +3 -2
  327. package/dist/core/persistent-shell.d.ts.map +1 -1
  328. package/dist/core/persistent-shell.js +11 -4
  329. package/dist/core/persistent-shell.js.map +1 -1
  330. package/dist/core/persistent-shell.test.js +6 -6
  331. package/dist/core/process-gate.d.ts +45 -0
  332. package/dist/core/process-gate.d.ts.map +1 -0
  333. package/dist/core/process-gate.js +79 -0
  334. package/dist/core/process-gate.js.map +1 -0
  335. package/dist/core/process-gate.test.d.ts +2 -0
  336. package/dist/core/process-gate.test.d.ts.map +1 -0
  337. package/dist/core/process-gate.test.js +87 -0
  338. package/dist/core/process-gate.test.js.map +1 -0
  339. package/dist/core/process-manager-dev-server-repro.test.js +51 -12
  340. package/dist/core/process-manager-dev-server-repro.test.js.map +1 -1
  341. package/dist/core/process-manager-notifications.test.d.ts +2 -0
  342. package/dist/core/process-manager-notifications.test.d.ts.map +1 -0
  343. package/dist/core/process-manager-notifications.test.js +227 -0
  344. package/dist/core/process-manager-notifications.test.js.map +1 -0
  345. package/dist/core/process-manager.d.ts +72 -1
  346. package/dist/core/process-manager.d.ts.map +1 -1
  347. package/dist/core/process-manager.js +247 -4
  348. package/dist/core/process-manager.js.map +1 -1
  349. package/dist/core/progress/git-xp.test.js +2 -2
  350. package/dist/core/progress/ranks.d.ts +14 -3
  351. package/dist/core/progress/ranks.d.ts.map +1 -1
  352. package/dist/core/progress/ranks.js +181 -12
  353. package/dist/core/progress/ranks.js.map +1 -1
  354. package/dist/core/progress/ranks.test.js +48 -7
  355. package/dist/core/progress/ranks.test.js.map +1 -1
  356. package/dist/core/progress/rebuild.test.js +1 -1
  357. package/dist/core/progress/store.test.js +1 -1
  358. package/dist/core/progress/types.d.ts +2 -1
  359. package/dist/core/progress/types.d.ts.map +1 -1
  360. package/dist/core/project-discovery.d.ts +31 -6
  361. package/dist/core/project-discovery.d.ts.map +1 -1
  362. package/dist/core/project-discovery.js +349 -79
  363. package/dist/core/project-discovery.js.map +1 -1
  364. package/dist/core/project-discovery.test.js +128 -4
  365. package/dist/core/project-discovery.test.js.map +1 -1
  366. package/dist/core/prompt-commands.js +3 -3
  367. package/dist/core/radio.d.ts +1 -1
  368. package/dist/core/radio.d.ts.map +1 -1
  369. package/dist/core/radio.js +90 -6
  370. package/dist/core/radio.js.map +1 -1
  371. package/dist/core/radio.test.js +15 -2
  372. package/dist/core/radio.test.js.map +1 -1
  373. package/dist/core/regrounding.d.ts.map +1 -1
  374. package/dist/core/regrounding.js +1 -0
  375. package/dist/core/regrounding.js.map +1 -1
  376. package/dist/core/run-claim.d.ts +37 -0
  377. package/dist/core/run-claim.d.ts.map +1 -0
  378. package/dist/core/run-claim.js +46 -0
  379. package/dist/core/run-claim.js.map +1 -0
  380. package/dist/core/run-claim.test.d.ts +2 -0
  381. package/dist/core/run-claim.test.d.ts.map +1 -0
  382. package/dist/core/run-claim.test.js +107 -0
  383. package/dist/core/run-claim.test.js.map +1 -0
  384. package/dist/core/run-journal.test.d.ts +2 -0
  385. package/dist/core/run-journal.test.d.ts.map +1 -0
  386. package/dist/core/run-journal.test.js +195 -0
  387. package/dist/core/run-journal.test.js.map +1 -0
  388. package/dist/core/run-lifecycle.d.ts +22 -3
  389. package/dist/core/run-lifecycle.d.ts.map +1 -1
  390. package/dist/core/run-lifecycle.js +12 -3
  391. package/dist/core/run-lifecycle.js.map +1 -1
  392. package/dist/core/sandbox-domains.d.ts +14 -0
  393. package/dist/core/sandbox-domains.d.ts.map +1 -0
  394. package/dist/core/sandbox-domains.js +76 -0
  395. package/dist/core/sandbox-domains.js.map +1 -0
  396. package/dist/core/sandbox-feedback.d.ts +22 -0
  397. package/dist/core/sandbox-feedback.d.ts.map +1 -0
  398. package/dist/core/sandbox-feedback.js +69 -0
  399. package/dist/core/sandbox-feedback.js.map +1 -0
  400. package/dist/core/sandbox-feedback.test.d.ts +2 -0
  401. package/dist/core/sandbox-feedback.test.d.ts.map +1 -0
  402. package/dist/core/sandbox-feedback.test.js +32 -0
  403. package/dist/core/sandbox-feedback.test.js.map +1 -0
  404. package/dist/core/sandbox.d.ts +91 -0
  405. package/dist/core/sandbox.d.ts.map +1 -0
  406. package/dist/core/sandbox.js +254 -0
  407. package/dist/core/sandbox.js.map +1 -0
  408. package/dist/core/sandbox.test.d.ts +2 -0
  409. package/dist/core/sandbox.test.d.ts.map +1 -0
  410. package/dist/core/sandbox.test.js +157 -0
  411. package/dist/core/sandbox.test.js.map +1 -0
  412. package/dist/core/semantic-search-benchmark.d.ts +2 -2
  413. package/dist/core/semantic-search-benchmark.js +5 -5
  414. package/dist/core/session-compaction.d.ts +6 -0
  415. package/dist/core/session-compaction.d.ts.map +1 -1
  416. package/dist/core/session-compaction.js +11 -1
  417. package/dist/core/session-compaction.js.map +1 -1
  418. package/dist/core/session-compaction.test.js +19 -2
  419. package/dist/core/session-compaction.test.js.map +1 -1
  420. package/dist/core/session-export.d.ts.map +1 -1
  421. package/dist/core/session-export.js +12 -4
  422. package/dist/core/session-export.js.map +1 -1
  423. package/dist/core/session-history.d.ts +95 -6
  424. package/dist/core/session-history.d.ts.map +1 -1
  425. package/dist/core/session-history.js +261 -17
  426. package/dist/core/session-history.js.map +1 -1
  427. package/dist/core/session-history.test.js +173 -2
  428. package/dist/core/session-history.test.js.map +1 -1
  429. package/dist/core/session-manager.d.ts +223 -6
  430. package/dist/core/session-manager.d.ts.map +1 -1
  431. package/dist/core/session-manager.js +579 -74
  432. package/dist/core/session-manager.js.map +1 -1
  433. package/dist/core/session-manager.test.js +154 -10
  434. package/dist/core/session-manager.test.js.map +1 -1
  435. package/dist/core/session-notification-visibility.test.d.ts +2 -0
  436. package/dist/core/session-notification-visibility.test.d.ts.map +1 -0
  437. package/dist/core/session-notification-visibility.test.js +113 -0
  438. package/dist/core/session-notification-visibility.test.js.map +1 -0
  439. package/dist/core/session-preview.d.ts +5 -4
  440. package/dist/core/session-preview.d.ts.map +1 -1
  441. package/dist/core/session-preview.js +12 -5
  442. package/dist/core/session-preview.js.map +1 -1
  443. package/dist/core/session-restore-display.test.js +25 -0
  444. package/dist/core/session-restore-display.test.js.map +1 -1
  445. package/dist/core/session-storage-fd-leak.test.d.ts +2 -0
  446. package/dist/core/session-storage-fd-leak.test.d.ts.map +1 -0
  447. package/dist/core/session-storage-fd-leak.test.js +116 -0
  448. package/dist/core/session-storage-fd-leak.test.js.map +1 -0
  449. package/dist/core/session-storage.d.ts +22 -2
  450. package/dist/core/session-storage.d.ts.map +1 -1
  451. package/dist/core/session-storage.js +72 -9
  452. package/dist/core/session-storage.js.map +1 -1
  453. package/dist/core/session-storage.test.js +8 -3
  454. package/dist/core/session-storage.test.js.map +1 -1
  455. package/dist/core/settings-manager.d.ts +10 -2
  456. package/dist/core/settings-manager.d.ts.map +1 -1
  457. package/dist/core/settings-manager.js +36 -1
  458. package/dist/core/settings-manager.js.map +1 -1
  459. package/dist/core/shell-path.js +1 -1
  460. package/dist/core/shell.d.ts +1 -1
  461. package/dist/core/shell.js +2 -2
  462. package/dist/core/shell.test.js +2 -2
  463. package/dist/core/shutdown.d.ts +71 -0
  464. package/dist/core/shutdown.d.ts.map +1 -0
  465. package/dist/core/shutdown.js +144 -0
  466. package/dist/core/shutdown.js.map +1 -0
  467. package/dist/core/shutdown.test.d.ts +2 -0
  468. package/dist/core/shutdown.test.d.ts.map +1 -0
  469. package/dist/core/shutdown.test.js +160 -0
  470. package/dist/core/shutdown.test.js.map +1 -0
  471. package/dist/core/sidecar-error-reporter.js +1 -1
  472. package/dist/core/sidecar-error-reporter.test.js +2 -2
  473. package/dist/core/skills-routing.test.js +96 -0
  474. package/dist/core/skills-routing.test.js.map +1 -1
  475. package/dist/core/skills.d.ts.map +1 -1
  476. package/dist/core/skills.js +3 -0
  477. package/dist/core/skills.js.map +1 -1
  478. package/dist/core/steering.d.ts +12 -0
  479. package/dist/core/steering.d.ts.map +1 -1
  480. package/dist/core/steering.js +16 -0
  481. package/dist/core/steering.js.map +1 -1
  482. package/dist/core/subagent-manager.d.ts +22 -0
  483. package/dist/core/subagent-manager.d.ts.map +1 -1
  484. package/dist/core/subagent-manager.js +84 -13
  485. package/dist/core/subagent-manager.js.map +1 -1
  486. package/dist/core/subagent-manager.test.js +57 -15
  487. package/dist/core/subagent-manager.test.js.map +1 -1
  488. package/dist/core/subagent-store.test.js +3 -3
  489. package/dist/core/task-store.js +1 -1
  490. package/dist/core/verification-evidence.d.ts +17 -0
  491. package/dist/core/verification-evidence.d.ts.map +1 -0
  492. package/dist/core/verification-evidence.js +283 -0
  493. package/dist/core/verification-evidence.js.map +1 -0
  494. package/dist/core/verification-evidence.test.d.ts +2 -0
  495. package/dist/core/verification-evidence.test.d.ts.map +1 -0
  496. package/dist/core/verification-evidence.test.js +103 -0
  497. package/dist/core/verification-evidence.test.js.map +1 -0
  498. package/dist/index.js +1 -1
  499. package/dist/index.js.map +1 -1
  500. package/dist/interactive.d.ts.map +1 -1
  501. package/dist/interactive.js +17 -3
  502. package/dist/interactive.js.map +1 -1
  503. package/dist/modes/acp-mode.d.ts +122 -0
  504. package/dist/modes/acp-mode.d.ts.map +1 -0
  505. package/dist/modes/acp-mode.js +1366 -0
  506. package/dist/modes/acp-mode.js.map +1 -0
  507. package/dist/modes/acp-mode.test.d.ts +2 -0
  508. package/dist/modes/acp-mode.test.d.ts.map +1 -0
  509. package/dist/modes/acp-mode.test.js +1065 -0
  510. package/dist/modes/acp-mode.test.js.map +1 -0
  511. package/dist/modes/agent-home-mode.d.ts.map +1 -1
  512. package/dist/modes/agent-home-mode.js +15 -11
  513. package/dist/modes/agent-home-mode.js.map +1 -1
  514. package/dist/modes/index.d.ts +1 -0
  515. package/dist/modes/index.d.ts.map +1 -1
  516. package/dist/modes/index.js +1 -0
  517. package/dist/modes/index.js.map +1 -1
  518. package/dist/modes/json-mode.d.ts +36 -0
  519. package/dist/modes/json-mode.d.ts.map +1 -1
  520. package/dist/modes/json-mode.js +39 -0
  521. package/dist/modes/json-mode.js.map +1 -1
  522. package/dist/modes/json-mode.test.d.ts +2 -0
  523. package/dist/modes/json-mode.test.d.ts.map +1 -0
  524. package/dist/modes/json-mode.test.js +84 -0
  525. package/dist/modes/json-mode.test.js.map +1 -0
  526. package/dist/modes/serve-mode.d.ts +1 -1
  527. package/dist/modes/serve-mode.d.ts.map +1 -1
  528. package/dist/modes/serve-mode.js +14 -9
  529. package/dist/modes/serve-mode.js.map +1 -1
  530. package/dist/modes/subagent-worker-mode.d.ts +8 -0
  531. package/dist/modes/subagent-worker-mode.d.ts.map +1 -1
  532. package/dist/modes/subagent-worker-mode.js +91 -11
  533. package/dist/modes/subagent-worker-mode.js.map +1 -1
  534. package/dist/modes/subagent-worker-mode.test.d.ts +2 -0
  535. package/dist/modes/subagent-worker-mode.test.d.ts.map +1 -0
  536. package/dist/modes/subagent-worker-mode.test.js +52 -0
  537. package/dist/modes/subagent-worker-mode.test.js.map +1 -0
  538. package/dist/session.d.ts +29 -0
  539. package/dist/session.d.ts.map +1 -1
  540. package/dist/session.js +41 -0
  541. package/dist/session.js.map +1 -1
  542. package/dist/session.test.js +1 -1
  543. package/dist/system-prompt.d.ts +37 -1
  544. package/dist/system-prompt.d.ts.map +1 -1
  545. package/dist/system-prompt.js +123 -11
  546. package/dist/system-prompt.js.map +1 -1
  547. package/dist/system-prompt.test.js +90 -11
  548. package/dist/system-prompt.test.js.map +1 -1
  549. package/dist/system-prompt.tiering.test.d.ts +2 -0
  550. package/dist/system-prompt.tiering.test.d.ts.map +1 -0
  551. package/dist/system-prompt.tiering.test.js +105 -0
  552. package/dist/system-prompt.tiering.test.js.map +1 -0
  553. package/dist/tools/bash.d.ts +2 -1
  554. package/dist/tools/bash.d.ts.map +1 -1
  555. package/dist/tools/bash.js +55 -16
  556. package/dist/tools/bash.js.map +1 -1
  557. package/dist/tools/code-nav.d.ts +30 -0
  558. package/dist/tools/code-nav.d.ts.map +1 -0
  559. package/dist/tools/code-nav.js +320 -0
  560. package/dist/tools/code-nav.js.map +1 -0
  561. package/dist/tools/code-nav.test.d.ts +2 -0
  562. package/dist/tools/code-nav.test.d.ts.map +1 -0
  563. package/dist/tools/code-nav.test.js +136 -0
  564. package/dist/tools/code-nav.test.js.map +1 -0
  565. package/dist/tools/edit.test.js +1 -1
  566. package/dist/tools/generate-image.d.ts +1 -1
  567. package/dist/tools/goals.d.ts +4 -4
  568. package/dist/tools/goals.test.js +2 -2
  569. package/dist/tools/grep-parity.test.d.ts +2 -0
  570. package/dist/tools/grep-parity.test.d.ts.map +1 -0
  571. package/dist/tools/grep-parity.test.js +92 -0
  572. package/dist/tools/grep-parity.test.js.map +1 -0
  573. package/dist/tools/grep-recall.test.d.ts +2 -0
  574. package/dist/tools/grep-recall.test.d.ts.map +1 -0
  575. package/dist/tools/grep-recall.test.js +114 -0
  576. package/dist/tools/grep-recall.test.js.map +1 -0
  577. package/dist/tools/grep-spawn.test.d.ts +2 -0
  578. package/dist/tools/grep-spawn.test.d.ts.map +1 -0
  579. package/dist/tools/grep-spawn.test.js +66 -0
  580. package/dist/tools/grep-spawn.test.js.map +1 -0
  581. package/dist/tools/grep.d.ts +13 -3
  582. package/dist/tools/grep.d.ts.map +1 -1
  583. package/dist/tools/grep.js +342 -41
  584. package/dist/tools/grep.js.map +1 -1
  585. package/dist/tools/grep.test.js +17 -14
  586. package/dist/tools/grep.test.js.map +1 -1
  587. package/dist/tools/index.d.ts +20 -2
  588. package/dist/tools/index.d.ts.map +1 -1
  589. package/dist/tools/index.js +28 -18
  590. package/dist/tools/index.js.map +1 -1
  591. package/dist/tools/index.test.d.ts +2 -0
  592. package/dist/tools/index.test.d.ts.map +1 -0
  593. package/dist/tools/index.test.js +55 -0
  594. package/dist/tools/index.test.js.map +1 -0
  595. package/dist/tools/plan-mode.test.js +1 -1
  596. package/dist/tools/prompt-hints.d.ts +9 -0
  597. package/dist/tools/prompt-hints.d.ts.map +1 -1
  598. package/dist/tools/prompt-hints.js +61 -8
  599. package/dist/tools/prompt-hints.js.map +1 -1
  600. package/dist/tools/read-only-bash.d.ts +3 -0
  601. package/dist/tools/read-only-bash.d.ts.map +1 -1
  602. package/dist/tools/read-only-bash.js +7 -9
  603. package/dist/tools/read-only-bash.js.map +1 -1
  604. package/dist/tools/safe-env.js +1 -1
  605. package/dist/tools/search-code.d.ts.map +1 -1
  606. package/dist/tools/search-code.js +7 -6
  607. package/dist/tools/search-code.js.map +1 -1
  608. package/dist/tools/search-code.test.js +8 -2
  609. package/dist/tools/search-code.test.js.map +1 -1
  610. package/dist/tools/skill.js +2 -1
  611. package/dist/tools/skill.js.map +1 -1
  612. package/dist/tools/subagent-control.d.ts.map +1 -1
  613. package/dist/tools/subagent-control.js +25 -6
  614. package/dist/tools/subagent-control.js.map +1 -1
  615. package/dist/tools/subagent-control.test.js +34 -1
  616. package/dist/tools/subagent-control.test.js.map +1 -1
  617. package/dist/tools/subagent-shared.d.ts +26 -1
  618. package/dist/tools/subagent-shared.d.ts.map +1 -1
  619. package/dist/tools/subagent-shared.js +40 -7
  620. package/dist/tools/subagent-shared.js.map +1 -1
  621. package/dist/tools/subagent-shared.test.js +43 -9
  622. package/dist/tools/subagent-shared.test.js.map +1 -1
  623. package/dist/tools/subagent.d.ts.map +1 -1
  624. package/dist/tools/subagent.js +54 -16
  625. package/dist/tools/subagent.js.map +1 -1
  626. package/dist/tools/subagent.test.js +68 -3
  627. package/dist/tools/subagent.test.js.map +1 -1
  628. package/dist/tools/task-output.d.ts.map +1 -1
  629. package/dist/tools/task-output.js +3 -1
  630. package/dist/tools/task-output.js.map +1 -1
  631. package/dist/tools/task-send.test.js +19 -10
  632. package/dist/tools/task-send.test.js.map +1 -1
  633. package/dist/tools/tool-search.d.ts +12 -1
  634. package/dist/tools/tool-search.d.ts.map +1 -1
  635. package/dist/tools/tool-search.js +24 -4
  636. package/dist/tools/tool-search.js.map +1 -1
  637. package/dist/tools/tool-search.test.d.ts +2 -0
  638. package/dist/tools/tool-search.test.d.ts.map +1 -0
  639. package/dist/tools/tool-search.test.js +69 -0
  640. package/dist/tools/tool-search.test.js.map +1 -0
  641. package/dist/tools/tool-tiers.d.ts +42 -0
  642. package/dist/tools/tool-tiers.d.ts.map +1 -0
  643. package/dist/tools/tool-tiers.js +78 -0
  644. package/dist/tools/tool-tiers.js.map +1 -0
  645. package/dist/tools/tool-tiers.test.d.ts +2 -0
  646. package/dist/tools/tool-tiers.test.d.ts.map +1 -0
  647. package/dist/tools/tool-tiers.test.js +48 -0
  648. package/dist/tools/tool-tiers.test.js.map +1 -0
  649. package/dist/tools/web-fetch.d.ts +1 -1
  650. package/dist/tools/web-fetch.d.ts.map +1 -1
  651. package/dist/tools/web-fetch.js +5 -2
  652. package/dist/tools/web-fetch.js.map +1 -1
  653. package/dist/tools/write.test.js +1 -1
  654. package/dist/types.d.ts +7 -0
  655. package/dist/types.d.ts.map +1 -1
  656. package/dist/ui/App.d.ts.map +1 -1
  657. package/dist/ui/App.js +27 -1
  658. package/dist/ui/App.js.map +1 -1
  659. package/dist/ui/components/Banner.d.ts.map +1 -1
  660. package/dist/ui/components/Banner.js +24 -16
  661. package/dist/ui/components/Banner.js.map +1 -1
  662. package/dist/ui/components/ToolExecution.js +42 -34
  663. package/dist/ui/components/ToolExecution.js.map +1 -1
  664. package/dist/ui/components/force-color.d.ts +2 -0
  665. package/dist/ui/components/force-color.d.ts.map +1 -0
  666. package/dist/ui/components/force-color.js +11 -0
  667. package/dist/ui/components/force-color.js.map +1 -0
  668. package/dist/ui/components/themed-output.test.d.ts +2 -0
  669. package/dist/ui/components/themed-output.test.d.ts.map +1 -0
  670. package/dist/ui/components/themed-output.test.js +111 -0
  671. package/dist/ui/components/themed-output.test.js.map +1 -0
  672. package/dist/ui/error-item.d.ts +1 -1
  673. package/dist/ui/error-item.js +3 -3
  674. package/dist/ui/error-item.js.map +1 -1
  675. package/dist/ui/hooks/useAgentLoop.d.ts +3 -0
  676. package/dist/ui/hooks/useAgentLoop.d.ts.map +1 -1
  677. package/dist/ui/hooks/useAgentLoop.js +45 -6
  678. package/dist/ui/hooks/useAgentLoop.js.map +1 -1
  679. package/dist/ui/login.js +1 -1
  680. package/dist/ui/login.js.map +1 -1
  681. package/dist/ui/render.d.ts +1 -1
  682. package/dist/ui/render.js +6 -6
  683. package/dist/ui/theme/dark-ansi.json +6 -0
  684. package/dist/ui/theme/dark-daltonized.json +6 -0
  685. package/dist/ui/theme/dark.json +6 -0
  686. package/dist/ui/theme/light-ansi.json +6 -0
  687. package/dist/ui/theme/light-daltonized.json +6 -0
  688. package/dist/ui/theme/light.json +6 -0
  689. package/dist/ui/theme/theme.d.ts +6 -0
  690. package/dist/ui/theme/theme.d.ts.map +1 -1
  691. package/dist/ui/tui-terminal-recorder.test.js +1 -1
  692. package/dist/utils/git.test.js +3 -3
  693. package/dist/utils/github.test.js +3 -3
  694. package/dist/utils/github.test.js.map +1 -1
  695. package/dist/utils/image.d.ts +26 -3
  696. package/dist/utils/image.d.ts.map +1 -1
  697. package/dist/utils/image.js +83 -14
  698. package/dist/utils/image.js.map +1 -1
  699. package/dist/utils/image.test.d.ts +2 -0
  700. package/dist/utils/image.test.d.ts.map +1 -0
  701. package/dist/utils/image.test.js +139 -0
  702. package/dist/utils/image.test.js.map +1 -0
  703. package/package.json +7 -6
@@ -1,5 +1,5 @@
1
1
  import fs from "node:fs/promises";
2
- import { createReadStream } from "node:fs";
2
+ import { createReadStream, realpathSync } from "node:fs";
3
3
  import readline from "node:readline";
4
4
  import os from "node:os";
5
5
  import path from "node:path";
@@ -7,34 +7,45 @@ import { getAppPaths } from "../config.js";
7
7
  import { encodeCwd, stripExtendedLengthPrefix } from "./encode-cwd.js";
8
8
  import { getUserSessionPrompt } from "./session-preview.js";
9
9
  import { isSessionPath, openSessionReadStream, resolveSessionPath } from "./session-storage.js";
10
+ import { parseForeignTranscript } from "./foreign-session-import.js";
10
11
  /**
11
- * Scan ezcoder + Claude Code + Codex session stores and return one row per
12
- * project, sorted most-recent first. Duplicates (same cwd) are collapsed; the
13
- * `sources` field lists every store the project appeared in so the picker can
14
- * show a combined badge.
12
+ * Scan EZ Coder + Claude Code + Codex session stores and the user's project
13
+ * folders, returning one deduplicated row per project, most-recent first.
15
14
  */
16
- export async function discoverProjects() {
15
+ export async function discoverProjects(options = {}) {
17
16
  const [ez, cc, cx] = await Promise.all([
18
17
  discoverEzcoderProjects(),
19
18
  discoverClaudeProjects(),
20
19
  discoverCodexProjects(),
21
20
  ]);
21
+ const fromSessions = [...ez, ...cc, ...cx];
22
+ const folders = await discoverFolderProjects(resolveProjectRoots(options.projectsRoot, options.extraRoots, fromSessions));
22
23
  const byPath = new Map();
23
- for (const p of [...ez, ...cc, ...cx]) {
24
+ for (const p of [...fromSessions, ...folders]) {
24
25
  const existing = byPath.get(p.path);
25
26
  if (!existing) {
26
27
  byPath.set(p.path, p);
27
28
  continue;
28
29
  }
30
+ // A folder's mtime is not activity: a checkout or a build touching the
31
+ // directory must not reorder a project above one you actually worked in.
32
+ // Session recency wins whenever any session store knows this project.
33
+ const merged = mergeSources(existing.sources, p.sources);
34
+ const sessionOnly = [existing, p].filter((row) => !isFolderOnly(row.sources));
29
35
  byPath.set(p.path, {
30
36
  name: existing.name,
31
37
  path: existing.path,
32
- lastActiveMs: Math.max(existing.lastActiveMs, p.lastActiveMs),
38
+ lastActiveMs: Math.max(...(sessionOnly.length > 0 ? sessionOnly : [existing, p]).map((r) => r.lastActiveMs)),
33
39
  lastActiveDisplay: "", // recomputed below
34
- sources: mergeSources(existing.sources, p.sources),
40
+ sources: merged,
35
41
  });
36
42
  }
37
- const merged = Array.from(byPath.values()).map((p) => ({
43
+ // Hiding is by resolved path so a row dismissed once stays gone regardless of
44
+ // which store re-surfaces it later.
45
+ const hidden = new Set((options.hiddenPaths ?? []).map((p) => path.resolve(p)));
46
+ const merged = Array.from(byPath.values())
47
+ .filter((p) => !hidden.has(p.path))
48
+ .map((p) => ({
38
49
  ...p,
39
50
  lastActiveDisplay: formatRelativeTime(p.lastActiveMs),
40
51
  }));
@@ -45,7 +56,11 @@ const SOURCE_ORDER = {
45
56
  ezcoder: 0,
46
57
  "claude-code": 1,
47
58
  codex: 2,
59
+ folder: 3,
48
60
  };
61
+ function isFolderOnly(sources) {
62
+ return sources.length === 1 && sources[0] === "folder";
63
+ }
49
64
  function mergeSources(a, b) {
50
65
  const set = new Set([...a, ...b]);
51
66
  return Array.from(set).sort((x, y) => SOURCE_ORDER[x] - SOURCE_ORDER[y]);
@@ -68,15 +83,17 @@ async function discoverEzcoderProjects() {
68
83
  catch {
69
84
  return [];
70
85
  }
71
- const results = [];
72
- for (const entry of entries) {
86
+ // Per-entry work is independent I/O (readdir + stat + a header read), so it
87
+ // runs concurrently; sequentially this dominated picker load time once a user
88
+ // had dozens of session stores.
89
+ const results = await mapConcurrent(entries, async (entry) => {
73
90
  const dir = path.join(sessionsDir, entry);
74
- const mtime = await maxGgcoderSessionMtime(dir);
91
+ const mtime = await maxEzcoderSessionMtime(dir);
75
92
  if (mtime === null)
76
- continue;
77
- const rawCwd = (await readFirstFromGgcoderDir(dir, ezcoderCwdExtractor)) ?? fallbackUnderscoreDecode(entry);
93
+ return null;
94
+ const rawCwd = (await readFirstFromEzcoderDir(dir, ezcoderCwdExtractor)) ?? fallbackUnderscoreDecode(entry);
78
95
  if (!rawCwd)
79
- continue;
96
+ return null;
80
97
  // Normalize traversal segments (e.g. an agent launched with cwd
81
98
  // `.../src-tauri/../..`) so the basename isn't a stray "..", and drop any
82
99
  // Windows extended-length prefix so a session recorded as `\\?\C:\proj`
@@ -84,16 +101,29 @@ async function discoverEzcoderProjects() {
84
101
  // project as a plain `C:\proj` instead of listing a prefixed duplicate.
85
102
  const cwd = path.resolve(stripExtendedLengthPrefix(rawCwd));
86
103
  if (!(await isDirectory(cwd)))
87
- continue;
88
- results.push({
104
+ return null;
105
+ return {
89
106
  name: path.basename(cwd),
90
107
  path: cwd,
91
108
  lastActiveMs: mtime,
92
109
  lastActiveDisplay: formatRelativeTime(mtime),
93
110
  sources: ["ezcoder"],
94
- });
95
- }
96
- return results;
111
+ };
112
+ });
113
+ return results.filter((p) => p !== null);
114
+ }
115
+ /** Bounded-concurrency Promise.all for large session stores. */
116
+ const IO_CONCURRENCY = 32;
117
+ async function mapConcurrent(items, fn) {
118
+ const out = new Array(items.length);
119
+ let next = 0;
120
+ const workers = Array.from({ length: Math.min(IO_CONCURRENCY, items.length) }, async () => {
121
+ for (let i = next++; i < items.length; i = next++) {
122
+ out[i] = await fn(items[i]);
123
+ }
124
+ });
125
+ await Promise.all(workers);
126
+ return out;
97
127
  }
98
128
  /**
99
129
  * Is `value` an absolute path on any platform?
@@ -140,7 +170,7 @@ async function discoverClaudeProjects() {
140
170
  catch {
141
171
  return [];
142
172
  }
143
- const results = await Promise.all(entries.map(async (entry) => {
173
+ const results = await mapConcurrent(entries, async (entry) => {
144
174
  const dir = path.join(projectsDir, entry);
145
175
  const mtime = await maxJsonlMtime(dir);
146
176
  if (mtime === null)
@@ -157,7 +187,7 @@ async function discoverClaudeProjects() {
157
187
  lastActiveDisplay: formatRelativeTime(mtime),
158
188
  sources: ["claude-code"],
159
189
  };
160
- }));
190
+ });
161
191
  return results.filter((p) => p !== null);
162
192
  }
163
193
  /**
@@ -176,28 +206,155 @@ async function discoverCodexProjects() {
176
206
  return [];
177
207
  // Process newest first so per-cwd we always start with the latest mtime.
178
208
  files.sort((a, b) => b.mtime - a.mtime);
209
+ const cwds = await mapConcurrent(files, (f) => readFirstFromFile(f.path, codexCwdExtractor));
179
210
  const byCwd = new Map();
180
- for (const f of files) {
181
- const cwd = await readFirstFromFile(f.path, codexCwdExtractor);
211
+ files.forEach((f, i) => {
212
+ const cwd = cwds[i];
182
213
  if (!cwd)
183
- continue;
214
+ return;
184
215
  const prev = byCwd.get(cwd);
185
216
  if (prev === undefined || f.mtime > prev)
186
217
  byCwd.set(cwd, f.mtime);
187
- }
188
- const results = [];
189
- for (const [cwd, mtime] of byCwd) {
218
+ });
219
+ const results = await mapConcurrent(Array.from(byCwd), async ([cwd, mtime]) => {
190
220
  if (!(await isDirectory(cwd)))
191
- continue;
192
- results.push({
221
+ return null;
222
+ return {
193
223
  name: path.basename(cwd),
194
224
  path: cwd,
195
225
  lastActiveMs: mtime,
196
226
  lastActiveDisplay: formatRelativeTime(mtime),
197
227
  sources: ["codex"],
198
- });
228
+ };
229
+ });
230
+ return results.filter((p) => p !== null);
231
+ }
232
+ /**
233
+ * How many already-known projects must share a parent directory before that
234
+ * parent is treated as a project root in its own right. Users keep more than
235
+ * one "projects folder" (the configured root plus wherever the rest actually
236
+ * live), but only one is configurable — so a directory that has repeatedly
237
+ * acted like a root is inferred from evidence rather than guessed.
238
+ */
239
+ const INFERRED_ROOT_MIN_PROJECTS = 3;
240
+ /** Directory names that are never a project of their own. */
241
+ const FOLDER_SCAN_IGNORED = new Set([
242
+ "node_modules",
243
+ "dist",
244
+ "build",
245
+ "out",
246
+ "target",
247
+ "vendor",
248
+ "coverage",
249
+ "tmp",
250
+ "temp",
251
+ "Library",
252
+ "Applications",
253
+ ]);
254
+ /**
255
+ * Which directories should be scanned for project folders: the configured root,
256
+ * plus any parent that already holds several known projects.
257
+ *
258
+ * Scanning the home directory or a filesystem/temp root would list mail, music
259
+ * and scratch dirs as "projects", so those are never roots no matter how many
260
+ * sessions point inside them.
261
+ */
262
+ function resolveProjectRoots(projectsRoot, extraRoots, discovered) {
263
+ const roots = new Set();
264
+ const configured = projectsRoot?.trim();
265
+ if (configured)
266
+ roots.add(path.resolve(configured));
267
+ for (const extra of extraRoots ?? []) {
268
+ const trimmed = extra.trim();
269
+ if (trimmed)
270
+ roots.add(path.resolve(trimmed));
199
271
  }
200
- return results;
272
+ const counts = new Map();
273
+ const seen = new Set();
274
+ for (const project of discovered) {
275
+ if (seen.has(project.path))
276
+ continue;
277
+ seen.add(project.path);
278
+ const parent = path.dirname(project.path);
279
+ if (parent === project.path)
280
+ continue;
281
+ counts.set(parent, (counts.get(parent) ?? 0) + 1);
282
+ }
283
+ for (const [parent, count] of counts) {
284
+ if (count >= INFERRED_ROOT_MIN_PROJECTS && !isUnscannableRoot(parent))
285
+ roots.add(parent);
286
+ }
287
+ return Array.from(roots);
288
+ }
289
+ function isUnscannableRoot(dir) {
290
+ const resolved = resolveExistingPath(dir);
291
+ if (resolved === resolveExistingPath(path.parse(resolved).root))
292
+ return true;
293
+ if (resolved === resolveExistingPath(os.homedir()))
294
+ return true;
295
+ // Scratch checkouts and test fixtures cluster as direct children of the temp
296
+ // dir, which would otherwise infer it as a root and list every stale
297
+ // `tmp.XXXX` as a project. Resolve symlinks before comparing because macOS
298
+ // reports the same temp directory through both `/var` and `/private/var`.
299
+ // Only the temp dir itself is barred — a real projects folder below it is
300
+ // still scannable.
301
+ return resolved === resolveExistingPath(os.tmpdir());
302
+ }
303
+ function resolveExistingPath(dir) {
304
+ const resolved = path.resolve(dir);
305
+ try {
306
+ return realpathSync(resolved);
307
+ }
308
+ catch {
309
+ return resolved;
310
+ }
311
+ }
312
+ /**
313
+ * List the direct children of each project root as projects. Directory mtime
314
+ * stands in for "last active" — imprecise, but these rows are session-less by
315
+ * definition and merging keeps real session recency where it exists.
316
+ */
317
+ async function discoverFolderProjects(roots) {
318
+ const candidates = [];
319
+ for (const root of roots) {
320
+ let entries;
321
+ try {
322
+ entries = await fs.readdir(root, { withFileTypes: true });
323
+ }
324
+ catch {
325
+ continue;
326
+ }
327
+ for (const entry of entries) {
328
+ if (!entry.isDirectory() && !entry.isSymbolicLink())
329
+ continue;
330
+ if (entry.name.startsWith("."))
331
+ continue;
332
+ if (FOLDER_SCAN_IGNORED.has(entry.name))
333
+ continue;
334
+ candidates.push({ name: entry.name, path: path.join(root, entry.name) });
335
+ }
336
+ }
337
+ // `stat` (not `lstat`) so a symlinked project folder resolves to its target:
338
+ // `readdir` reports a symlink as neither file nor directory, so checking the
339
+ // dirent alone would silently drop linked-in projects.
340
+ const rows = await mapConcurrent(candidates, async (c) => {
341
+ try {
342
+ const stats = await fs.stat(c.path);
343
+ if (!stats.isDirectory())
344
+ return null;
345
+ return {
346
+ name: c.name,
347
+ path: c.path,
348
+ lastActiveMs: stats.mtimeMs,
349
+ lastActiveDisplay: formatRelativeTime(stats.mtimeMs),
350
+ sources: ["folder"],
351
+ };
352
+ }
353
+ catch {
354
+ return null;
355
+ }
356
+ });
357
+ return rows.filter((r) => r !== null);
201
358
  }
202
359
  async function isDirectory(p) {
203
360
  try {
@@ -220,10 +377,10 @@ async function maxJsonlMtime(dir) {
220
377
  max = f.mtime;
221
378
  return max > 0 ? max : null;
222
379
  }
223
- async function maxGgcoderSessionMtime(dir) {
380
+ async function maxEzcoderSessionMtime(dir) {
224
381
  if (!(await isDirectory(dir)))
225
382
  return null;
226
- const files = await collectGgcoderSessionFiles(dir, 2);
383
+ const files = await collectEzcoderSessionFiles(dir, 2);
227
384
  if (files.length === 0)
228
385
  return null;
229
386
  return Math.max(...files.map((file) => file.mtime));
@@ -262,7 +419,7 @@ async function collectJsonlFiles(dir, maxDepth) {
262
419
  }
263
420
  }
264
421
  }
265
- async function collectGgcoderSessionFiles(dir, maxDepth) {
422
+ async function collectEzcoderSessionFiles(dir, maxDepth) {
266
423
  const byResolvedPath = new Map();
267
424
  await walk(dir, 0);
268
425
  return [...byResolvedPath.values()];
@@ -356,20 +513,27 @@ async function readFirstFromJsonlDir(dir, extractor) {
356
513
  }
357
514
  return null;
358
515
  }
359
- async function readFirstFromGgcoderDir(dir, extractor) {
360
- const files = await collectGgcoderSessionFiles(dir, 2);
516
+ async function readFirstFromEzcoderDir(dir, extractor) {
517
+ const files = await collectEzcoderSessionFiles(dir, 2);
361
518
  files.sort((a, b) => b.mtime - a.mtime);
362
519
  for (const file of files) {
363
520
  try {
364
- const { stream } = await openSessionReadStream(file.path);
521
+ const { stream, close } = await openSessionReadStream(file.path);
365
522
  const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });
366
- let lines = 0;
367
- for await (const line of rl) {
368
- if (++lines > 200)
369
- break;
370
- const value = extractor(line);
371
- if (value)
372
- return value;
523
+ try {
524
+ let lines = 0;
525
+ for await (const line of rl) {
526
+ if (++lines > 200)
527
+ break;
528
+ const value = extractor(line);
529
+ if (value)
530
+ return value;
531
+ }
532
+ }
533
+ finally {
534
+ // Always via close(): destroying the gunzip alone strands the source fd.
535
+ rl.close();
536
+ close();
373
537
  }
374
538
  }
375
539
  catch {
@@ -464,7 +628,7 @@ function formatRelativeTime(ms) {
464
628
  */
465
629
  export async function listRecentSessions(cwd, limit = 5, sessionsDir = getAppPaths().sessionsDir) {
466
630
  const dir = path.join(sessionsDir, encodeCwd(cwd));
467
- const files = await collectGgcoderSessionFiles(dir, 1);
631
+ const files = await collectEzcoderSessionFiles(dir, 1);
468
632
  if (files.length === 0)
469
633
  return [];
470
634
  files.sort((a, b) => b.mtime - a.mtime);
@@ -484,10 +648,109 @@ export async function listRecentSessions(cwd, limit = 5, sessionsDir = getAppPat
484
648
  }
485
649
  return out;
486
650
  }
651
+ /**
652
+ * List the most recent Claude Code and Codex conversations for a project cwd.
653
+ *
654
+ * The project picker has always surfaced these stores (`discoverProjects`), so a
655
+ * project can appear *because* it has Claude Code history — and then show an
656
+ * empty session list, because that only read EZ Coder's own directory. These
657
+ * rows close that gap: each one points at the foreign transcript, tagged with
658
+ * its `source`, and the host imports it on click.
659
+ *
660
+ * Cheap by construction: a transcript is only opened if its cwd matches, and
661
+ * both the per-store file walk and the preview read are line-capped.
662
+ */
663
+ export async function listForeignSessions(cwd, limit = 5, homeDir = os.homedir()) {
664
+ const [claude, codex] = await Promise.all([
665
+ listClaudeSessions(cwd, limit, homeDir),
666
+ listCodexSessions(cwd, limit, homeDir),
667
+ ]);
668
+ return [...claude, ...codex]
669
+ .sort((left, right) => right.lastActiveMs - left.lastActiveMs)
670
+ .slice(0, limit)
671
+ .map(({ lastActiveMs: _lastActiveMs, ...session }) => session);
672
+ }
673
+ async function listClaudeSessions(cwd, limit, homeDir) {
674
+ const projectsDir = path.join(homeDir, ".claude", "projects");
675
+ if (!(await isDirectory(projectsDir)))
676
+ return [];
677
+ // Claude's directory encoding is ambiguous (every "/" becomes "-", colliding
678
+ // with real dashes), so we cannot map cwd → directory. Instead walk the files
679
+ // newest-first and keep the ones whose recorded cwd matches.
680
+ const files = await collectJsonlFiles(projectsDir, 3);
681
+ return collectMatchingForeignSessions(files, cwd, limit, "claude-code", claudeCwdExtractor);
682
+ }
683
+ async function listCodexSessions(cwd, limit, homeDir) {
684
+ const sessionsDir = path.join(homeDir, ".codex", "sessions");
685
+ if (!(await isDirectory(sessionsDir)))
686
+ return [];
687
+ // Layout is YYYY/MM/DD/*.jsonl — depth 4 covers it.
688
+ const files = await collectJsonlFiles(sessionsDir, 4);
689
+ return collectMatchingForeignSessions(files, cwd, limit, "codex", codexCwdExtractor);
690
+ }
691
+ /**
692
+ * Newest-first scan for transcripts belonging to `cwd`. Stops as soon as
693
+ * `limit` matches are found so a large history costs only the files it reads.
694
+ */
695
+ async function collectMatchingForeignSessions(files, cwd, limit, source, extractor) {
696
+ if (files.length === 0)
697
+ return [];
698
+ files.sort((left, right) => right.mtime - left.mtime);
699
+ const target = path.resolve(stripExtendedLengthPrefix(cwd));
700
+ const out = [];
701
+ for (const file of files) {
702
+ if (out.length >= limit)
703
+ break;
704
+ const recorded = await readFirstFromFile(file.path, extractor);
705
+ if (!recorded)
706
+ continue;
707
+ if (path.resolve(stripExtendedLengthPrefix(recorded)) !== target)
708
+ continue;
709
+ const summary = await readForeignSessionSummary(file.path, source);
710
+ if (!summary)
711
+ continue;
712
+ out.push({
713
+ ...summary,
714
+ lastActiveDisplay: formatRelativeTime(file.mtime),
715
+ lastActiveMs: file.mtime,
716
+ });
717
+ }
718
+ return out;
719
+ }
720
+ /**
721
+ * Preview + message count for a foreign transcript, using the same parsers the
722
+ * importer uses — so the row's title is exactly the title the imported session
723
+ * ends up with (notably Cursor's `<user_query>` unwrapping).
724
+ */
725
+ async function readForeignSessionSummary(file, source) {
726
+ let text;
727
+ try {
728
+ text = await fs.readFile(file, "utf-8");
729
+ }
730
+ catch {
731
+ return null;
732
+ }
733
+ try {
734
+ const parsed = parseForeignTranscript(text, source === "codex" ? "codex" : "claude");
735
+ if (parsed.messages.length === 0)
736
+ return null;
737
+ return {
738
+ id: path.basename(file).replace(/\.jsonl$/, ""),
739
+ path: file,
740
+ preview: parsed.preview ?? "(no prompt)",
741
+ messageCount: parsed.messages.length,
742
+ source,
743
+ };
744
+ }
745
+ catch {
746
+ // An unreadable transcript is skipped, never surfaced as a broken row.
747
+ return null;
748
+ }
749
+ }
487
750
  /** Single-pass parse of one session file: identity + count + activity + preview. */
488
751
  async function readSessionSummary(file) {
489
752
  try {
490
- const { path: resolvedPath, stream } = await openSessionReadStream(file);
753
+ const { path: resolvedPath, stream, close } = await openSessionReadStream(file);
491
754
  const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });
492
755
  let id = "";
493
756
  let conversationId = "";
@@ -497,41 +760,48 @@ async function readSessionSummary(file) {
497
760
  let preview = "";
498
761
  let label = "";
499
762
  let valid = false;
500
- for await (const line of rl) {
501
- if (!line)
502
- continue;
503
- try {
504
- const entry = JSON.parse(line);
505
- if (!valid) {
506
- if (entry.type !== "session")
507
- return null;
508
- valid = true;
509
- id = entry.id ?? "";
510
- conversationId = entry.conversationId ?? id;
511
- if (typeof entry.preview === "string") {
512
- headerPreview = entry.preview.replace(/\s+/g, " ").trim().slice(0, 80);
513
- }
514
- if (entry.timestamp)
515
- lastActivity = entry.timestamp;
763
+ try {
764
+ for await (const line of rl) {
765
+ if (!line)
516
766
  continue;
517
- }
518
- if (entry.type === "label" && typeof entry.label === "string" && entry.label.trim()) {
519
- label = entry.label.replace(/\s+/g, " ").trim().slice(0, 80);
520
- }
521
- else if (entry.type === "message") {
522
- messageCount += 1;
523
- if (entry.timestamp)
524
- lastActivity = entry.timestamp;
525
- if (!preview && entry.message?.role === "user") {
526
- const text = getUserSessionPrompt(entry.message.content);
527
- if (text)
528
- preview = text.replace(/\s+/g, " ").trim().slice(0, 80);
767
+ try {
768
+ const entry = JSON.parse(line);
769
+ if (!valid) {
770
+ if (entry.type !== "session")
771
+ return null;
772
+ valid = true;
773
+ id = entry.id ?? "";
774
+ conversationId = entry.conversationId ?? id;
775
+ if (typeof entry.preview === "string") {
776
+ headerPreview = entry.preview.replace(/\s+/g, " ").trim().slice(0, 80);
777
+ }
778
+ if (entry.timestamp)
779
+ lastActivity = entry.timestamp;
780
+ continue;
781
+ }
782
+ if (entry.type === "label" && typeof entry.label === "string" && entry.label.trim()) {
783
+ label = entry.label.replace(/\s+/g, " ").trim().slice(0, 80);
784
+ }
785
+ else if (entry.type === "message") {
786
+ messageCount += 1;
787
+ if (entry.timestamp)
788
+ lastActivity = entry.timestamp;
789
+ if (!preview && entry.message?.role === "user") {
790
+ const text = getUserSessionPrompt(entry.message.content);
791
+ if (text)
792
+ preview = text.replace(/\s+/g, " ").trim().slice(0, 80);
793
+ }
529
794
  }
530
795
  }
796
+ catch {
797
+ // Skip malformed lines; archive migration preserves them byte-for-byte.
798
+ }
531
799
  }
532
- catch {
533
- // Skip malformed lines; archive migration preserves them byte-for-byte.
534
- }
800
+ }
801
+ finally {
802
+ // `return null` above exits mid-stream; close() destroys gunzip + source.
803
+ rl.close();
804
+ close();
535
805
  }
536
806
  return valid
537
807
  ? {