@getpaseo/server 0.1.61 → 0.1.63

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 (464) hide show
  1. package/README.md +4 -0
  2. package/dist/server/client/daemon-client-runtime-metrics.d.ts +6 -6
  3. package/dist/server/client/daemon-client-runtime-metrics.d.ts.map +1 -1
  4. package/dist/server/client/daemon-client-transport-types.d.ts +13 -13
  5. package/dist/server/client/daemon-client-transport-types.d.ts.map +1 -1
  6. package/dist/server/client/daemon-client-websocket-transport.d.ts +1 -1
  7. package/dist/server/client/daemon-client-websocket-transport.d.ts.map +1 -1
  8. package/dist/server/client/daemon-client-websocket-transport.js +5 -4
  9. package/dist/server/client/daemon-client-websocket-transport.js.map +1 -1
  10. package/dist/server/client/daemon-client.d.ts +59 -37
  11. package/dist/server/client/daemon-client.d.ts.map +1 -1
  12. package/dist/server/client/daemon-client.js +62 -17
  13. package/dist/server/client/daemon-client.js.map +1 -1
  14. package/dist/server/server/agent/agent-loading.d.ts.map +1 -1
  15. package/dist/server/server/agent/agent-loading.js +5 -3
  16. package/dist/server/server/agent/agent-loading.js.map +1 -1
  17. package/dist/server/server/agent/agent-manager.d.ts +45 -19
  18. package/dist/server/server/agent/agent-manager.d.ts.map +1 -1
  19. package/dist/server/server/agent/agent-manager.js +393 -290
  20. package/dist/server/server/agent/agent-manager.js.map +1 -1
  21. package/dist/server/server/agent/agent-metadata-generator.d.ts +6 -6
  22. package/dist/server/server/agent/agent-metadata-generator.d.ts.map +1 -1
  23. package/dist/server/server/agent/agent-metadata-generator.js +46 -38
  24. package/dist/server/server/agent/agent-metadata-generator.js.map +1 -1
  25. package/dist/server/server/agent/agent-projections.d.ts +4 -6
  26. package/dist/server/server/agent/agent-projections.d.ts.map +1 -1
  27. package/dist/server/server/agent/agent-projections.js +59 -65
  28. package/dist/server/server/agent/agent-projections.js.map +1 -1
  29. package/dist/server/server/agent/agent-response-loop.d.ts +4 -4
  30. package/dist/server/server/agent/agent-response-loop.d.ts.map +1 -1
  31. package/dist/server/server/agent/agent-response-loop.js +58 -45
  32. package/dist/server/server/agent/agent-response-loop.js.map +1 -1
  33. package/dist/server/server/agent/agent-sdk-types.d.ts +43 -40
  34. package/dist/server/server/agent/agent-sdk-types.d.ts.map +1 -1
  35. package/dist/server/server/agent/agent-sdk-types.js.map +1 -1
  36. package/dist/server/server/agent/agent-storage.d.ts +2 -2
  37. package/dist/server/server/agent/agent-storage.d.ts.map +1 -1
  38. package/dist/server/server/agent/agent-storage.js +29 -36
  39. package/dist/server/server/agent/agent-storage.js.map +1 -1
  40. package/dist/server/server/agent/agent-stream-coalescer.d.ts +6 -6
  41. package/dist/server/server/agent/agent-stream-coalescer.d.ts.map +1 -1
  42. package/dist/server/server/agent/agent-timeline-store-types.d.ts +10 -10
  43. package/dist/server/server/agent/agent-timeline-store-types.d.ts.map +1 -1
  44. package/dist/server/server/agent/agent-timeline-store.d.ts +2 -2
  45. package/dist/server/server/agent/agent-timeline-store.d.ts.map +1 -1
  46. package/dist/server/server/agent/agent-timeline-store.js +85 -64
  47. package/dist/server/server/agent/agent-timeline-store.js.map +1 -1
  48. package/dist/server/server/agent/mcp-server.d.ts.map +1 -1
  49. package/dist/server/server/agent/mcp-server.js +185 -148
  50. package/dist/server/server/agent/mcp-server.js.map +1 -1
  51. package/dist/server/server/agent/mcp-shared.d.ts +9 -2
  52. package/dist/server/server/agent/mcp-shared.d.ts.map +1 -1
  53. package/dist/server/server/agent/mcp-shared.js +2 -0
  54. package/dist/server/server/agent/mcp-shared.js.map +1 -1
  55. package/dist/server/server/agent/model-resolver.d.ts +2 -2
  56. package/dist/server/server/agent/model-resolver.d.ts.map +1 -1
  57. package/dist/server/server/agent/model-resolver.js +9 -5
  58. package/dist/server/server/agent/model-resolver.js.map +1 -1
  59. package/dist/server/server/agent/provider-launch-config.d.ts +28 -17
  60. package/dist/server/server/agent/provider-launch-config.d.ts.map +1 -1
  61. package/dist/server/server/agent/provider-launch-config.js +20 -9
  62. package/dist/server/server/agent/provider-launch-config.js.map +1 -1
  63. package/dist/server/server/agent/provider-registry.d.ts +4 -2
  64. package/dist/server/server/agent/provider-registry.d.ts.map +1 -1
  65. package/dist/server/server/agent/provider-registry.js +24 -21
  66. package/dist/server/server/agent/provider-registry.js.map +1 -1
  67. package/dist/server/server/agent/provider-snapshot-manager.d.ts +6 -5
  68. package/dist/server/server/agent/provider-snapshot-manager.d.ts.map +1 -1
  69. package/dist/server/server/agent/provider-snapshot-manager.js +40 -31
  70. package/dist/server/server/agent/provider-snapshot-manager.js.map +1 -1
  71. package/dist/server/server/agent/providers/acp-agent.d.ts +11 -12
  72. package/dist/server/server/agent/providers/acp-agent.d.ts.map +1 -1
  73. package/dist/server/server/agent/providers/acp-agent.js +148 -122
  74. package/dist/server/server/agent/providers/acp-agent.js.map +1 -1
  75. package/dist/server/server/agent/providers/claude/sidechain-tracker.d.ts +2 -0
  76. package/dist/server/server/agent/providers/claude/sidechain-tracker.d.ts.map +1 -1
  77. package/dist/server/server/agent/providers/claude/sidechain-tracker.js +47 -45
  78. package/dist/server/server/agent/providers/claude/sidechain-tracker.js.map +1 -1
  79. package/dist/server/server/agent/providers/claude/task-notification-tool-call.d.ts +2 -2
  80. package/dist/server/server/agent/providers/claude/task-notification-tool-call.d.ts.map +1 -1
  81. package/dist/server/server/agent/providers/claude/task-notification-tool-call.js +10 -5
  82. package/dist/server/server/agent/providers/claude/task-notification-tool-call.js.map +1 -1
  83. package/dist/server/server/agent/providers/claude/tool-call-detail-parser.d.ts.map +1 -1
  84. package/dist/server/server/agent/providers/claude/tool-call-detail-parser.js +11 -2
  85. package/dist/server/server/agent/providers/claude/tool-call-detail-parser.js.map +1 -1
  86. package/dist/server/server/agent/providers/claude/tool-call-mapper.d.ts +2 -2
  87. package/dist/server/server/agent/providers/claude/tool-call-mapper.d.ts.map +1 -1
  88. package/dist/server/server/agent/providers/claude/tool-call-mapper.js +20 -13
  89. package/dist/server/server/agent/providers/claude/tool-call-mapper.js.map +1 -1
  90. package/dist/server/server/agent/providers/claude-agent.d.ts +20 -8
  91. package/dist/server/server/agent/providers/claude-agent.d.ts.map +1 -1
  92. package/dist/server/server/agent/providers/claude-agent.js +610 -460
  93. package/dist/server/server/agent/providers/claude-agent.js.map +1 -1
  94. package/dist/server/server/agent/providers/codex/tool-call-detail-parser.d.ts +2 -2
  95. package/dist/server/server/agent/providers/codex/tool-call-detail-parser.d.ts.map +1 -1
  96. package/dist/server/server/agent/providers/codex/tool-call-mapper.d.ts +2 -2
  97. package/dist/server/server/agent/providers/codex/tool-call-mapper.d.ts.map +1 -1
  98. package/dist/server/server/agent/providers/codex/tool-call-mapper.js +49 -44
  99. package/dist/server/server/agent/providers/codex/tool-call-mapper.js.map +1 -1
  100. package/dist/server/server/agent/providers/codex-app-server-agent.d.ts +27 -8
  101. package/dist/server/server/agent/providers/codex-app-server-agent.d.ts.map +1 -1
  102. package/dist/server/server/agent/providers/codex-app-server-agent.js +564 -492
  103. package/dist/server/server/agent/providers/codex-app-server-agent.js.map +1 -1
  104. package/dist/server/server/agent/providers/codex-rollout-timeline.d.ts +2 -2
  105. package/dist/server/server/agent/providers/codex-rollout-timeline.d.ts.map +1 -1
  106. package/dist/server/server/agent/providers/codex-rollout-timeline.js +58 -47
  107. package/dist/server/server/agent/providers/codex-rollout-timeline.js.map +1 -1
  108. package/dist/server/server/agent/providers/copilot-acp-agent.d.ts +2 -2
  109. package/dist/server/server/agent/providers/copilot-acp-agent.d.ts.map +1 -1
  110. package/dist/server/server/agent/providers/diagnostic-utils.d.ts +3 -3
  111. package/dist/server/server/agent/providers/diagnostic-utils.d.ts.map +1 -1
  112. package/dist/server/server/agent/providers/diagnostic-utils.js +82 -9
  113. package/dist/server/server/agent/providers/diagnostic-utils.js.map +1 -1
  114. package/dist/server/server/agent/providers/generic-acp-agent.d.ts +2 -2
  115. package/dist/server/server/agent/providers/generic-acp-agent.d.ts.map +1 -1
  116. package/dist/server/server/agent/providers/mock-load-test-agent.d.ts.map +1 -1
  117. package/dist/server/server/agent/providers/mock-load-test-agent.js.map +1 -1
  118. package/dist/server/server/agent/providers/opencode/tool-call-mapper.d.ts +2 -2
  119. package/dist/server/server/agent/providers/opencode/tool-call-mapper.d.ts.map +1 -1
  120. package/dist/server/server/agent/providers/opencode-agent.d.ts +2 -2
  121. package/dist/server/server/agent/providers/opencode-agent.d.ts.map +1 -1
  122. package/dist/server/server/agent/providers/opencode-agent.js +385 -360
  123. package/dist/server/server/agent/providers/opencode-agent.js.map +1 -1
  124. package/dist/server/server/agent/providers/pi-direct-agent.d.ts +1 -0
  125. package/dist/server/server/agent/providers/pi-direct-agent.d.ts.map +1 -1
  126. package/dist/server/server/agent/providers/pi-direct-agent.js +109 -140
  127. package/dist/server/server/agent/providers/pi-direct-agent.js.map +1 -1
  128. package/dist/server/server/agent/providers/test-utils/session-stream-adapter.d.ts.map +1 -1
  129. package/dist/server/server/agent/providers/test-utils/session-stream-adapter.js +3 -1
  130. package/dist/server/server/agent/providers/test-utils/session-stream-adapter.js.map +1 -1
  131. package/dist/server/server/agent/providers/tool-call-detail-primitives.d.ts +3 -3
  132. package/dist/server/server/agent/providers/tool-call-detail-primitives.d.ts.map +1 -1
  133. package/dist/server/server/agent/providers/tool-call-detail-primitives.js +102 -73
  134. package/dist/server/server/agent/providers/tool-call-detail-primitives.js.map +1 -1
  135. package/dist/server/server/agent/providers/tool-call-mapper-utils.d.ts +2 -2
  136. package/dist/server/server/agent/providers/tool-call-mapper-utils.d.ts.map +1 -1
  137. package/dist/server/server/agent/stt-manager.d.ts.map +1 -1
  138. package/dist/server/server/agent/stt-manager.js +63 -53
  139. package/dist/server/server/agent/stt-manager.js.map +1 -1
  140. package/dist/server/server/agent/timeline-projection.d.ts +6 -6
  141. package/dist/server/server/agent/timeline-projection.d.ts.map +1 -1
  142. package/dist/server/server/agent/timeline-projection.js +11 -6
  143. package/dist/server/server/agent/timeline-projection.js.map +1 -1
  144. package/dist/server/server/agent/tts-manager.d.ts.map +1 -1
  145. package/dist/server/server/agent/tts-manager.js +1 -0
  146. package/dist/server/server/agent/tts-manager.js.map +1 -1
  147. package/dist/server/server/agent-attention-policy.d.ts +2 -2
  148. package/dist/server/server/agent-attention-policy.d.ts.map +1 -1
  149. package/dist/server/server/bootstrap.d.ts +4 -4
  150. package/dist/server/server/bootstrap.d.ts.map +1 -1
  151. package/dist/server/server/bootstrap.js +493 -485
  152. package/dist/server/server/bootstrap.js.map +1 -1
  153. package/dist/server/server/chat/chat-service.d.ts +1 -1
  154. package/dist/server/server/chat/chat-service.d.ts.map +1 -1
  155. package/dist/server/server/chat/chat-service.js +3 -3
  156. package/dist/server/server/chat/chat-service.js.map +1 -1
  157. package/dist/server/server/checkout-diff-manager.d.ts +2 -2
  158. package/dist/server/server/checkout-diff-manager.d.ts.map +1 -1
  159. package/dist/server/server/checkout-git-utils.d.ts +5 -3
  160. package/dist/server/server/checkout-git-utils.d.ts.map +1 -1
  161. package/dist/server/server/checkout-git-utils.js +1 -2
  162. package/dist/server/server/checkout-git-utils.js.map +1 -1
  163. package/dist/server/server/config.d.ts.map +1 -1
  164. package/dist/server/server/config.js +68 -39
  165. package/dist/server/server/config.js.map +1 -1
  166. package/dist/server/server/connection-offer.d.ts +2 -2
  167. package/dist/server/server/connection-offer.d.ts.map +1 -1
  168. package/dist/server/server/daemon-config-store.d.ts +5 -3
  169. package/dist/server/server/daemon-config-store.d.ts.map +1 -1
  170. package/dist/server/server/daemon-config-store.js +26 -0
  171. package/dist/server/server/daemon-config-store.js.map +1 -1
  172. package/dist/server/server/daemon-keypair.d.ts +2 -2
  173. package/dist/server/server/daemon-keypair.d.ts.map +1 -1
  174. package/dist/server/server/editor-targets.d.ts +4 -4
  175. package/dist/server/server/editor-targets.d.ts.map +1 -1
  176. package/dist/server/server/editor-targets.js +11 -15
  177. package/dist/server/server/editor-targets.js.map +1 -1
  178. package/dist/server/server/exports.d.ts +3 -3
  179. package/dist/server/server/exports.d.ts.map +1 -1
  180. package/dist/server/server/exports.js +1 -3
  181. package/dist/server/server/exports.js.map +1 -1
  182. package/dist/server/server/file-download/token-store.d.ts +4 -4
  183. package/dist/server/server/file-download/token-store.d.ts.map +1 -1
  184. package/dist/server/server/index.js +16 -12
  185. package/dist/server/server/index.js.map +1 -1
  186. package/dist/server/server/logger.d.ts +4 -4
  187. package/dist/server/server/logger.d.ts.map +1 -1
  188. package/dist/server/server/logger.js +26 -20
  189. package/dist/server/server/logger.js.map +1 -1
  190. package/dist/server/server/loop/rpc-schemas.d.ts +52 -52
  191. package/dist/server/server/loop-service.d.ts +13 -12
  192. package/dist/server/server/loop-service.d.ts.map +1 -1
  193. package/dist/server/server/loop-service.js +22 -18
  194. package/dist/server/server/loop-service.js.map +1 -1
  195. package/dist/server/server/package-version.d.ts +2 -2
  196. package/dist/server/server/package-version.d.ts.map +1 -1
  197. package/dist/server/server/package-version.js +19 -17
  198. package/dist/server/server/package-version.js.map +1 -1
  199. package/dist/server/server/pairing-offer.d.ts +2 -2
  200. package/dist/server/server/pairing-offer.d.ts.map +1 -1
  201. package/dist/server/server/paseo-env.d.ts +9 -0
  202. package/dist/server/server/paseo-env.d.ts.map +1 -0
  203. package/dist/server/server/paseo-env.js +70 -0
  204. package/dist/server/server/paseo-env.js.map +1 -0
  205. package/dist/server/server/paseo-worktree-archive-service.d.ts +4 -4
  206. package/dist/server/server/paseo-worktree-archive-service.d.ts.map +1 -1
  207. package/dist/server/server/paseo-worktree-archive-service.js +11 -11
  208. package/dist/server/server/paseo-worktree-archive-service.js.map +1 -1
  209. package/dist/server/server/persisted-config.d.ts +62 -62
  210. package/dist/server/server/persisted-config.d.ts.map +1 -1
  211. package/dist/server/server/persisted-config.js +4 -4
  212. package/dist/server/server/persisted-config.js.map +1 -1
  213. package/dist/server/server/persistence-hooks.d.ts +8 -9
  214. package/dist/server/server/persistence-hooks.d.ts.map +1 -1
  215. package/dist/server/server/persistence-hooks.js +4 -12
  216. package/dist/server/server/persistence-hooks.js.map +1 -1
  217. package/dist/server/server/pid-lock.js.map +1 -1
  218. package/dist/server/server/push/push-service.d.ts.map +1 -1
  219. package/dist/server/server/push/push-service.js +1 -3
  220. package/dist/server/server/push/push-service.js.map +1 -1
  221. package/dist/server/server/relay-transport.d.ts +8 -8
  222. package/dist/server/server/relay-transport.d.ts.map +1 -1
  223. package/dist/server/server/relay-transport.js +27 -16
  224. package/dist/server/server/relay-transport.js.map +1 -1
  225. package/dist/server/server/schedule/service.d.ts.map +1 -1
  226. package/dist/server/server/schedule/service.js +2 -2
  227. package/dist/server/server/schedule/service.js.map +1 -1
  228. package/dist/server/server/script-health-monitor.d.ts.map +1 -1
  229. package/dist/server/server/script-health-monitor.js +7 -6
  230. package/dist/server/server/script-health-monitor.js.map +1 -1
  231. package/dist/server/server/script-proxy.js +1 -1
  232. package/dist/server/server/script-proxy.js.map +1 -1
  233. package/dist/server/server/script-status-projection.d.ts +4 -4
  234. package/dist/server/server/script-status-projection.d.ts.map +1 -1
  235. package/dist/server/server/script-status-projection.js +54 -44
  236. package/dist/server/server/script-status-projection.js.map +1 -1
  237. package/dist/server/server/server-id.d.ts +4 -4
  238. package/dist/server/server/server-id.d.ts.map +1 -1
  239. package/dist/server/server/session.d.ts +50 -19
  240. package/dist/server/server/session.d.ts.map +1 -1
  241. package/dist/server/server/session.js +1116 -783
  242. package/dist/server/server/session.js.map +1 -1
  243. package/dist/server/server/speech/audio.js +1 -1
  244. package/dist/server/server/speech/audio.js.map +1 -1
  245. package/dist/server/server/speech/providers/local/config.d.ts +6 -6
  246. package/dist/server/server/speech/providers/local/config.d.ts.map +1 -1
  247. package/dist/server/server/speech/providers/local/config.js +41 -16
  248. package/dist/server/server/speech/providers/local/config.js.map +1 -1
  249. package/dist/server/server/speech/providers/local/pocket/pocket-tts-onnx.d.ts +2 -2
  250. package/dist/server/server/speech/providers/local/pocket/pocket-tts-onnx.d.ts.map +1 -1
  251. package/dist/server/server/speech/providers/local/pocket/pocket-tts-onnx.js +42 -19
  252. package/dist/server/server/speech/providers/local/pocket/pocket-tts-onnx.js.map +1 -1
  253. package/dist/server/server/speech/providers/local/runtime.d.ts +4 -4
  254. package/dist/server/server/speech/providers/local/runtime.d.ts.map +1 -1
  255. package/dist/server/server/speech/providers/local/runtime.js +108 -77
  256. package/dist/server/server/speech/providers/local/runtime.js.map +1 -1
  257. package/dist/server/server/speech/providers/local/sherpa/model-catalog.d.ts +2 -2
  258. package/dist/server/server/speech/providers/local/sherpa/model-catalog.d.ts.map +1 -1
  259. package/dist/server/server/speech/providers/local/sherpa/model-catalog.js +1 -4
  260. package/dist/server/server/speech/providers/local/sherpa/model-catalog.js.map +1 -1
  261. package/dist/server/server/speech/providers/local/sherpa/model-downloader.d.ts +2 -2
  262. package/dist/server/server/speech/providers/local/sherpa/model-downloader.d.ts.map +1 -1
  263. package/dist/server/server/speech/providers/local/sherpa/model-downloader.js +19 -19
  264. package/dist/server/server/speech/providers/local/sherpa/model-downloader.js.map +1 -1
  265. package/dist/server/server/speech/providers/local/sherpa/sherpa-offline-recognizer.d.ts +28 -7
  266. package/dist/server/server/speech/providers/local/sherpa/sherpa-offline-recognizer.d.ts.map +1 -1
  267. package/dist/server/server/speech/providers/local/sherpa/sherpa-offline-recognizer.js.map +1 -1
  268. package/dist/server/server/speech/providers/local/sherpa/sherpa-online-recognizer.d.ts +23 -4
  269. package/dist/server/server/speech/providers/local/sherpa/sherpa-online-recognizer.d.ts.map +1 -1
  270. package/dist/server/server/speech/providers/local/sherpa/sherpa-online-recognizer.js +35 -28
  271. package/dist/server/server/speech/providers/local/sherpa/sherpa-online-recognizer.js.map +1 -1
  272. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-loader.d.ts +5 -5
  273. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-loader.d.ts.map +1 -1
  274. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.d.ts +7 -7
  275. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.d.ts.map +1 -1
  276. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.js +5 -0
  277. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.js.map +1 -1
  278. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.d.ts.map +1 -1
  279. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.js +3 -1
  280. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.js.map +1 -1
  281. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-stt.d.ts +2 -2
  282. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-stt.d.ts.map +1 -1
  283. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-stt.js +3 -1
  284. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-stt.js.map +1 -1
  285. package/dist/server/server/speech/providers/local/sherpa/sherpa-realtime-session.d.ts.map +1 -1
  286. package/dist/server/server/speech/providers/local/sherpa/sherpa-realtime-session.js +10 -4
  287. package/dist/server/server/speech/providers/local/sherpa/sherpa-realtime-session.js.map +1 -1
  288. package/dist/server/server/speech/providers/local/sherpa/sherpa-runtime-env.d.ts +2 -2
  289. package/dist/server/server/speech/providers/local/sherpa/sherpa-runtime-env.d.ts.map +1 -1
  290. package/dist/server/server/speech/providers/local/sherpa/sherpa-stt.d.ts +2 -2
  291. package/dist/server/server/speech/providers/local/sherpa/sherpa-stt.d.ts.map +1 -1
  292. package/dist/server/server/speech/providers/local/sherpa/sherpa-stt.js +4 -1
  293. package/dist/server/server/speech/providers/local/sherpa/sherpa-stt.js.map +1 -1
  294. package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.d.ts +2 -2
  295. package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.d.ts.map +1 -1
  296. package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.js +18 -11
  297. package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.js.map +1 -1
  298. package/dist/server/server/speech/providers/openai/config.d.ts +2 -2
  299. package/dist/server/server/speech/providers/openai/config.d.ts.map +1 -1
  300. package/dist/server/server/speech/providers/openai/config.js +58 -31
  301. package/dist/server/server/speech/providers/openai/config.js.map +1 -1
  302. package/dist/server/server/speech/providers/openai/realtime-transcription-session.d.ts.map +1 -1
  303. package/dist/server/server/speech/providers/openai/realtime-transcription-session.js +2 -2
  304. package/dist/server/server/speech/providers/openai/realtime-transcription-session.js.map +1 -1
  305. package/dist/server/server/speech/providers/openai/runtime.d.ts +4 -4
  306. package/dist/server/server/speech/providers/openai/runtime.d.ts.map +1 -1
  307. package/dist/server/server/speech/providers/openai/runtime.js +37 -32
  308. package/dist/server/server/speech/providers/openai/runtime.js.map +1 -1
  309. package/dist/server/server/speech/providers/openai/stt.d.ts.map +1 -1
  310. package/dist/server/server/speech/providers/openai/stt.js +4 -3
  311. package/dist/server/server/speech/providers/openai/stt.js.map +1 -1
  312. package/dist/server/server/speech/providers/openai/tts.d.ts.map +1 -1
  313. package/dist/server/server/speech/providers/openai/tts.js +3 -2
  314. package/dist/server/server/speech/providers/openai/tts.js.map +1 -1
  315. package/dist/server/server/speech/speech-config-resolver.d.ts.map +1 -1
  316. package/dist/server/server/speech/speech-config-resolver.js +46 -17
  317. package/dist/server/server/speech/speech-config-resolver.js.map +1 -1
  318. package/dist/server/server/speech/speech-provider.d.ts +2 -2
  319. package/dist/server/server/speech/speech-provider.d.ts.map +1 -1
  320. package/dist/server/server/speech/speech-runtime.d.ts +6 -6
  321. package/dist/server/server/speech/speech-runtime.d.ts.map +1 -1
  322. package/dist/server/server/speech/speech-runtime.js +17 -17
  323. package/dist/server/server/speech/speech-runtime.js.map +1 -1
  324. package/dist/server/server/speech/speech-types.d.ts +2 -2
  325. package/dist/server/server/speech/speech-types.d.ts.map +1 -1
  326. package/dist/server/server/speech/turn-detection-provider.d.ts +2 -2
  327. package/dist/server/server/speech/turn-detection-provider.d.ts.map +1 -1
  328. package/dist/server/server/utils/diff-highlighter.d.ts +0 -3
  329. package/dist/server/server/utils/diff-highlighter.d.ts.map +1 -1
  330. package/dist/server/server/utils/diff-highlighter.js +67 -66
  331. package/dist/server/server/utils/diff-highlighter.js.map +1 -1
  332. package/dist/server/server/voice/voice-turn-controller.d.ts.map +1 -1
  333. package/dist/server/server/voice/voice-turn-controller.js +1 -0
  334. package/dist/server/server/voice/voice-turn-controller.js.map +1 -1
  335. package/dist/server/server/voice-types.d.ts +2 -2
  336. package/dist/server/server/voice-types.d.ts.map +1 -1
  337. package/dist/server/server/websocket-server.d.ts +33 -23
  338. package/dist/server/server/websocket-server.d.ts.map +1 -1
  339. package/dist/server/server/websocket-server.js +349 -241
  340. package/dist/server/server/websocket-server.js.map +1 -1
  341. package/dist/server/server/workspace-git-metadata.d.ts +2 -2
  342. package/dist/server/server/workspace-git-metadata.d.ts.map +1 -1
  343. package/dist/server/server/workspace-git-metadata.js +2 -32
  344. package/dist/server/server/workspace-git-metadata.js.map +1 -1
  345. package/dist/server/server/workspace-git-service.d.ts +17 -13
  346. package/dist/server/server/workspace-git-service.d.ts.map +1 -1
  347. package/dist/server/server/workspace-git-service.js +232 -140
  348. package/dist/server/server/workspace-git-service.js.map +1 -1
  349. package/dist/server/server/workspace-reconciliation-service.d.ts +5 -4
  350. package/dist/server/server/workspace-reconciliation-service.d.ts.map +1 -1
  351. package/dist/server/server/workspace-reconciliation-service.js +82 -82
  352. package/dist/server/server/workspace-reconciliation-service.js.map +1 -1
  353. package/dist/server/server/workspace-registry-bootstrap.d.ts.map +1 -1
  354. package/dist/server/server/workspace-registry-bootstrap.js +40 -33
  355. package/dist/server/server/workspace-registry-bootstrap.js.map +1 -1
  356. package/dist/server/server/workspace-registry-model.d.ts +19 -6
  357. package/dist/server/server/workspace-registry-model.d.ts.map +1 -1
  358. package/dist/server/server/workspace-registry-model.js +35 -21
  359. package/dist/server/server/workspace-registry-model.js.map +1 -1
  360. package/dist/server/server/workspace-registry.d.ts +2 -2
  361. package/dist/server/server/workspace-script-runtime-store.d.ts +2 -2
  362. package/dist/server/server/workspace-script-runtime-store.d.ts.map +1 -1
  363. package/dist/server/server/workspace-service-env.js +3 -3
  364. package/dist/server/server/workspace-service-env.js.map +1 -1
  365. package/dist/server/server/worktree-bootstrap.d.ts +4 -4
  366. package/dist/server/server/worktree-bootstrap.d.ts.map +1 -1
  367. package/dist/server/server/worktree-bootstrap.js +95 -67
  368. package/dist/server/server/worktree-bootstrap.js.map +1 -1
  369. package/dist/server/server/worktree-session.d.ts +8 -8
  370. package/dist/server/server/worktree-session.d.ts.map +1 -1
  371. package/dist/server/server/worktree-session.js +27 -19
  372. package/dist/server/server/worktree-session.js.map +1 -1
  373. package/dist/server/services/github-service.d.ts +2 -7
  374. package/dist/server/services/github-service.d.ts.map +1 -1
  375. package/dist/server/services/github-service.js +156 -157
  376. package/dist/server/services/github-service.js.map +1 -1
  377. package/dist/server/shared/agent-attention-notification.d.ts +9 -8
  378. package/dist/server/shared/agent-attention-notification.d.ts.map +1 -1
  379. package/dist/server/shared/agent-attention-notification.js +27 -17
  380. package/dist/server/shared/agent-attention-notification.js.map +1 -1
  381. package/dist/server/shared/daemon-endpoints.d.ts +2 -2
  382. package/dist/server/shared/daemon-endpoints.d.ts.map +1 -1
  383. package/dist/server/shared/daemon-endpoints.js +17 -2
  384. package/dist/server/shared/daemon-endpoints.js.map +1 -1
  385. package/dist/server/shared/messages.d.ts +21962 -3049
  386. package/dist/server/shared/messages.d.ts.map +1 -1
  387. package/dist/server/shared/messages.js +79 -2
  388. package/dist/server/shared/messages.js.map +1 -1
  389. package/dist/server/shared/terminal-stream-protocol.d.ts +2 -2
  390. package/dist/server/shared/terminal-stream-protocol.d.ts.map +1 -1
  391. package/dist/server/shared/tool-call-display.d.ts +2 -2
  392. package/dist/server/shared/tool-call-display.d.ts.map +1 -1
  393. package/dist/server/terminal/terminal-manager.d.ts.map +1 -1
  394. package/dist/server/terminal/terminal-manager.js +1 -3
  395. package/dist/server/terminal/terminal-manager.js.map +1 -1
  396. package/dist/server/terminal/terminal-output-coalescer.d.ts +6 -6
  397. package/dist/server/terminal/terminal-output-coalescer.d.ts.map +1 -1
  398. package/dist/server/terminal/terminal.d.ts +3 -2
  399. package/dist/server/terminal/terminal.d.ts.map +1 -1
  400. package/dist/server/terminal/terminal.js +57 -19
  401. package/dist/server/terminal/terminal.js.map +1 -1
  402. package/dist/server/utils/checkout-git.d.ts +13 -12
  403. package/dist/server/utils/checkout-git.d.ts.map +1 -1
  404. package/dist/server/utils/checkout-git.js +416 -282
  405. package/dist/server/utils/checkout-git.js.map +1 -1
  406. package/dist/server/utils/directory-suggestions.js +12 -33
  407. package/dist/server/utils/directory-suggestions.js.map +1 -1
  408. package/dist/server/utils/executable.d.ts +1 -14
  409. package/dist/server/utils/executable.d.ts.map +1 -1
  410. package/dist/server/utils/executable.js +13 -49
  411. package/dist/server/utils/executable.js.map +1 -1
  412. package/dist/server/utils/github-remote.d.ts +13 -0
  413. package/dist/server/utils/github-remote.d.ts.map +1 -0
  414. package/dist/server/utils/github-remote.js +128 -0
  415. package/dist/server/utils/github-remote.js.map +1 -0
  416. package/dist/server/utils/paseo-config-file.d.ts +30 -0
  417. package/dist/server/utils/paseo-config-file.d.ts.map +1 -0
  418. package/dist/server/utils/paseo-config-file.js +90 -0
  419. package/dist/server/utils/paseo-config-file.js.map +1 -0
  420. package/dist/server/utils/paseo-config-schema.d.ts +290 -0
  421. package/dist/server/utils/paseo-config-schema.d.ts.map +1 -0
  422. package/dist/server/utils/paseo-config-schema.js +60 -0
  423. package/dist/server/utils/paseo-config-schema.js.map +1 -0
  424. package/dist/server/utils/project-icon.d.ts.map +1 -1
  425. package/dist/server/utils/project-icon.js +84 -109
  426. package/dist/server/utils/project-icon.js.map +1 -1
  427. package/dist/server/utils/promise-timeout.d.ts +2 -2
  428. package/dist/server/utils/promise-timeout.d.ts.map +1 -1
  429. package/dist/server/utils/run-git-command.d.ts +3 -1
  430. package/dist/server/utils/run-git-command.d.ts.map +1 -1
  431. package/dist/server/utils/run-git-command.js +10 -1
  432. package/dist/server/utils/run-git-command.js.map +1 -1
  433. package/dist/server/utils/script-hostname.d.ts +2 -2
  434. package/dist/server/utils/script-hostname.d.ts.map +1 -1
  435. package/dist/server/utils/spawn.d.ts +10 -3
  436. package/dist/server/utils/spawn.d.ts.map +1 -1
  437. package/dist/server/utils/spawn.js +30 -5
  438. package/dist/server/utils/spawn.js.map +1 -1
  439. package/dist/server/utils/windows-command.d.ts +15 -0
  440. package/dist/server/utils/windows-command.d.ts.map +1 -0
  441. package/dist/server/utils/windows-command.js +37 -0
  442. package/dist/server/utils/windows-command.js.map +1 -0
  443. package/dist/server/utils/worktree.d.ts +10 -7
  444. package/dist/server/utils/worktree.d.ts.map +1 -1
  445. package/dist/server/utils/worktree.js +64 -55
  446. package/dist/server/utils/worktree.js.map +1 -1
  447. package/dist/src/server/pid-lock.js.map +1 -1
  448. package/package.json +15 -20
  449. package/dist/server/server/agent/llm-openai.d.ts +0 -7
  450. package/dist/server/server/agent/llm-openai.d.ts.map +0 -1
  451. package/dist/server/server/agent/llm-openai.js +0 -8
  452. package/dist/server/server/agent/llm-openai.js.map +0 -1
  453. package/dist/server/server/agent/orchestrator.d.ts +0 -12
  454. package/dist/server/server/agent/orchestrator.d.ts.map +0 -1
  455. package/dist/server/server/agent/orchestrator.js +0 -12
  456. package/dist/server/server/agent/orchestrator.js.map +0 -1
  457. package/dist/server/server/types.d.ts +0 -5
  458. package/dist/server/server/types.d.ts.map +0 -1
  459. package/dist/server/server/types.js +0 -3
  460. package/dist/server/server/types.js.map +0 -1
  461. package/dist/server/server/workspace-registry.test-helpers.d.ts +0 -37
  462. package/dist/server/server/workspace-registry.test-helpers.d.ts.map +0 -1
  463. package/dist/server/server/workspace-registry.test-helpers.js +0 -121
  464. package/dist/server/server/workspace-registry.test-helpers.js.map +0 -1
@@ -3,13 +3,13 @@ import { existsSync, realpathSync } from "fs";
3
3
  import { open as openFile, readFile, stat as statFile } from "fs/promises";
4
4
  import { TTLCache } from "@isaacs/ttlcache";
5
5
  import { parseAndHighlightDiff } from "../server/utils/diff-highlighter.js";
6
- import { GitHubAuthenticationError, GitHubCliMissingError, createGitHubService, resolveGitHubRepo, } from "../services/github-service.js";
6
+ import { parseGitHubRepoFromRemote } from "../server/workspace-git-metadata.js";
7
+ import { GitHubAuthenticationError, GitHubCliMissingError, GitHubCommandError, createGitHubService, resolveGitHubRepo, } from "../services/github-service.js";
7
8
  import { parseGitRevParsePath, resolveGitRevParsePath } from "./git-rev-parse-path.js";
8
9
  import { runGitCommand } from "./run-git-command.js";
9
10
  import { isPaseoOwnedWorktreeCwd } from "./worktree.js";
10
- import { requirePaseoWorktreeBaseRefName } from "./worktree-metadata.js";
11
+ import { readPaseoWorktreeMetadata } from "./worktree-metadata.js";
11
12
  const READ_ONLY_GIT_ENV = {
12
- ...process.env,
13
13
  GIT_OPTIONAL_LOCKS: "0",
14
14
  };
15
15
  const DEFAULT_PULL_REQUEST_STATUS_CACHE_TTL_MS = 30000;
@@ -19,6 +19,7 @@ const SHORTSTAT_CACHE_MAX = 1000;
19
19
  let pullRequestStatusCacheTtlMs = DEFAULT_PULL_REQUEST_STATUS_CACHE_TTL_MS;
20
20
  let pullRequestStatusCache = createPullRequestStatusCache(pullRequestStatusCacheTtlMs);
21
21
  const pullRequestStatusInFlight = new Map();
22
+ const lastSuccessfulPullRequestStatus = new Map();
22
23
  let shortstatCacheTtlMs = DEFAULT_SHORTSTAT_CACHE_TTL_MS;
23
24
  let shortstatCache = createShortstatCache(shortstatCacheTtlMs);
24
25
  const shortstatInFlight = new Map();
@@ -39,6 +40,16 @@ function createShortstatCache(ttlMs) {
39
40
  function getPullRequestStatusCacheKey(cwd) {
40
41
  return resolve(cwd);
41
42
  }
43
+ function rememberPullRequestStatus(cacheKey, status) {
44
+ lastSuccessfulPullRequestStatus.set(cacheKey, status);
45
+ if (lastSuccessfulPullRequestStatus.size <= PULL_REQUEST_STATUS_CACHE_MAX) {
46
+ return;
47
+ }
48
+ const oldest = lastSuccessfulPullRequestStatus.keys().next();
49
+ if (!oldest.done) {
50
+ lastSuccessfulPullRequestStatus.delete(oldest.value);
51
+ }
52
+ }
42
53
  function getShortstatCacheKey(cwd) {
43
54
  return resolve(cwd);
44
55
  }
@@ -48,6 +59,7 @@ export function __resetPullRequestStatusCacheForTests() {
48
59
  pullRequestStatusCacheTtlMs = DEFAULT_PULL_REQUEST_STATUS_CACHE_TTL_MS;
49
60
  pullRequestStatusCache = createPullRequestStatusCache(pullRequestStatusCacheTtlMs);
50
61
  pullRequestStatusInFlight.clear();
62
+ lastSuccessfulPullRequestStatus.clear();
51
63
  }
52
64
  export function __setPullRequestStatusCacheTtlForTests(ttlMs) {
53
65
  pullRequestStatusCache.clear();
@@ -55,6 +67,7 @@ export function __setPullRequestStatusCacheTtlForTests(ttlMs) {
55
67
  pullRequestStatusCacheTtlMs = ttlMs;
56
68
  pullRequestStatusCache = createPullRequestStatusCache(ttlMs);
57
69
  pullRequestStatusInFlight.clear();
70
+ lastSuccessfulPullRequestStatus.clear();
58
71
  }
59
72
  export function __resetCheckoutShortstatCacheForTests() {
60
73
  shortstatCache.clear();
@@ -99,7 +112,7 @@ async function listGitRefs(cwd, refPrefix) {
99
112
  "--sort=-committerdate",
100
113
  "--format=%(refname)%09%(committerdate:unix)",
101
114
  refPrefix,
102
- ], { cwd, env: READ_ONLY_GIT_ENV });
115
+ ], { cwd, envOverlay: READ_ONLY_GIT_ENV });
103
116
  return stdout
104
117
  .split("\n")
105
118
  .map((line) => {
@@ -199,7 +212,7 @@ export async function resolveBranchCheckout(cwd, name) {
199
212
  const localRef = `refs/heads/${normalized}`;
200
213
  const localResult = await runGitCommand(["rev-parse", "--verify", "--quiet", localRef], {
201
214
  cwd,
202
- env: READ_ONLY_GIT_ENV,
215
+ envOverlay: READ_ONLY_GIT_ENV,
203
216
  acceptExitCodes: [0, 1],
204
217
  });
205
218
  const hasLocal = localResult.exitCode === 0;
@@ -210,7 +223,7 @@ export async function resolveBranchCheckout(cwd, name) {
210
223
  const remoteRefPath = `refs/remotes/${remoteRef}`;
211
224
  const remoteResult = await runGitCommand(["rev-parse", "--verify", "--quiet", remoteRefPath], {
212
225
  cwd,
213
- env: READ_ONLY_GIT_ENV,
226
+ envOverlay: READ_ONLY_GIT_ENV,
214
227
  acceptExitCodes: [0, 1],
215
228
  });
216
229
  const hasRemote = remoteResult.exitCode === 0;
@@ -245,7 +258,7 @@ async function listCheckoutFileChanges(cwd, refs, ignoreWhitespace = false) {
245
258
  const { stdout: nameStatusOut } = await runGitCommand(buildGitDiffArgs({
246
259
  ignoreWhitespace,
247
260
  extra: ["--name-status", ...getCheckoutDiffRefArgs(refs)],
248
- }), { cwd, env: READ_ONLY_GIT_ENV });
261
+ }), { cwd, envOverlay: READ_ONLY_GIT_ENV });
249
262
  for (const line of nameStatusOut
250
263
  .split("\n")
251
264
  .map((l) => l.trim())
@@ -283,7 +296,7 @@ async function listCheckoutFileChanges(cwd, refs, ignoreWhitespace = false) {
283
296
  if (refs.includeUntracked) {
284
297
  const { stdout: untrackedOut } = await runGitCommand(["ls-files", "--others", "--exclude-standard"], {
285
298
  cwd,
286
- env: READ_ONLY_GIT_ENV,
299
+ envOverlay: READ_ONLY_GIT_ENV,
287
300
  });
288
301
  for (const file of untrackedOut
289
302
  .split("\n")
@@ -316,7 +329,7 @@ async function readGitFileContentAtRef(cwd, ref, path) {
316
329
  try {
317
330
  const { stdout } = await runGitCommand(["show", `${ref}:${path}`], {
318
331
  cwd,
319
- env: READ_ONLY_GIT_ENV,
332
+ envOverlay: READ_ONLY_GIT_ENV,
320
333
  });
321
334
  return stdout;
322
335
  }
@@ -328,7 +341,7 @@ async function tryResolveMergeBase(cwd, baseRef) {
328
341
  try {
329
342
  const { stdout } = await runGitCommand(["merge-base", baseRef, "HEAD"], {
330
343
  cwd,
331
- env: READ_ONLY_GIT_ENV,
344
+ envOverlay: READ_ONLY_GIT_ENV,
332
345
  });
333
346
  const sha = stdout.trim();
334
347
  return sha.length > 0 ? sha : null;
@@ -360,7 +373,7 @@ async function getTrackedNumstatByPath(cwd, refs, ignoreWhitespace = false) {
360
373
  extra: ["--numstat", ...getCheckoutDiffRefArgs(refs)],
361
374
  }), {
362
375
  cwd,
363
- env: READ_ONLY_GIT_ENV,
376
+ envOverlay: READ_ONLY_GIT_ENV,
364
377
  maxOutputBytes: TRACKED_DIFF_NUMSTAT_MAX_BYTES,
365
378
  acceptExitCodes: [0],
366
379
  });
@@ -435,9 +448,9 @@ function isGitError(error) {
435
448
  }
436
449
  async function requireGitRepo(cwd) {
437
450
  try {
438
- await runGitCommand(["rev-parse", "--git-dir"], { cwd, env: READ_ONLY_GIT_ENV });
451
+ await runGitCommand(["rev-parse", "--git-dir"], { cwd, envOverlay: READ_ONLY_GIT_ENV });
439
452
  }
440
- catch (error) {
453
+ catch {
441
454
  throw new NotGitRepoError(cwd);
442
455
  }
443
456
  }
@@ -445,7 +458,7 @@ export async function getCurrentBranch(cwd) {
445
458
  try {
446
459
  const { stdout } = await runGitCommand(["rev-parse", "--abbrev-ref", "HEAD"], {
447
460
  cwd,
448
- env: READ_ONLY_GIT_ENV,
461
+ envOverlay: READ_ONLY_GIT_ENV,
449
462
  });
450
463
  const branch = stdout.trim();
451
464
  if (branch === "HEAD") {
@@ -458,11 +471,12 @@ export async function getCurrentBranch(cwd) {
458
471
  }
459
472
  }
460
473
  async function getRebaseHeadBranch(cwd) {
461
- for (const path of ["rebase-merge/head-name", "rebase-apply/head-name"]) {
474
+ const paths = ["rebase-merge/head-name", "rebase-apply/head-name"];
475
+ const results = await Promise.all(paths.map(async (path) => {
462
476
  try {
463
477
  const { stdout } = await runGitCommand(["rev-parse", "--git-path", path], {
464
478
  cwd,
465
- env: READ_ONLY_GIT_ENV,
479
+ envOverlay: READ_ONLY_GIT_ENV,
466
480
  });
467
481
  const headName = (await readFile(resolve(cwd, stdout.trim()), "utf8")).trim();
468
482
  if (headName.startsWith("refs/heads/")) {
@@ -471,16 +485,16 @@ async function getRebaseHeadBranch(cwd) {
471
485
  return headName || null;
472
486
  }
473
487
  catch {
474
- // Try the other rebase backend.
488
+ return null;
475
489
  }
476
- }
477
- return null;
490
+ }));
491
+ return results.find((result) => result !== null) ?? null;
478
492
  }
479
493
  async function getWorktreeRoot(cwd) {
480
494
  try {
481
495
  const { stdout } = await runGitCommand(["rev-parse", "--show-toplevel"], {
482
496
  cwd,
483
- env: READ_ONLY_GIT_ENV,
497
+ envOverlay: READ_ONLY_GIT_ENV,
484
498
  });
485
499
  return parseGitRevParsePath(stdout);
486
500
  }
@@ -491,7 +505,7 @@ async function getWorktreeRoot(cwd) {
491
505
  export async function getMainRepoRoot(cwd) {
492
506
  const { stdout: commonDirOut } = await runGitCommand(["rev-parse", "--git-common-dir"], {
493
507
  cwd,
494
- env: READ_ONLY_GIT_ENV,
508
+ envOverlay: READ_ONLY_GIT_ENV,
495
509
  });
496
510
  const commonDir = resolveGitRevParsePath(cwd, commonDirOut);
497
511
  if (!commonDir) {
@@ -503,7 +517,7 @@ export async function getMainRepoRoot(cwd) {
503
517
  }
504
518
  const { stdout: worktreeOut } = await runGitCommand(["worktree", "list", "--porcelain"], {
505
519
  cwd,
506
- env: READ_ONLY_GIT_ENV,
520
+ envOverlay: READ_ONLY_GIT_ENV,
507
521
  });
508
522
  const worktrees = parseWorktreeList(worktreeOut);
509
523
  const nonBareNonPaseo = worktrees.filter((wt) => !wt.isBare && !isPaseoWorktreePath(wt.path));
@@ -561,7 +575,7 @@ async function getWorktreePathForBranch(cwd, branchName) {
561
575
  try {
562
576
  const { stdout } = await runGitCommand(["worktree", "list", "--porcelain"], {
563
577
  cwd,
564
- env: READ_ONLY_GIT_ENV,
578
+ envOverlay: READ_ONLY_GIT_ENV,
565
579
  });
566
580
  const entries = parseWorktreeList(stdout);
567
581
  const ref = branchName.startsWith("refs/heads/") ? branchName : `refs/heads/${branchName}`;
@@ -584,25 +598,45 @@ export async function renameCurrentBranch(cwd, newName) {
584
598
  const currentBranch = await getCurrentBranch(cwd);
585
599
  return { previousBranch, currentBranch };
586
600
  }
587
- async function getConfiguredBaseRefForCwd(cwd, context) {
601
+ async function getPaseoWorktreeForCwd(cwd, context) {
588
602
  // Fast-path reject: non-worktree paths do not need expensive ownership checks.
589
603
  if (!/[\\/]worktrees[\\/]/.test(cwd)) {
590
- return { baseRef: null, isPaseoOwnedWorktree: false };
604
+ return { isPaseoOwnedWorktree: false };
591
605
  }
592
606
  const ownership = await isPaseoOwnedWorktreeCwd(cwd, { paseoHome: context?.paseoHome });
593
607
  if (!ownership.allowed) {
594
- return { baseRef: null, isPaseoOwnedWorktree: false };
608
+ return { isPaseoOwnedWorktree: false };
595
609
  }
596
- const worktreeRoot = (await getWorktreeRoot(cwd)) ?? cwd;
597
610
  return {
598
- baseRef: requirePaseoWorktreeBaseRefName(worktreeRoot),
599
611
  isPaseoOwnedWorktree: true,
612
+ worktreeRoot: (await getWorktreeRoot(cwd)) ?? cwd,
613
+ };
614
+ }
615
+ function readPaseoWorktreeBaseRef(worktreeRoot) {
616
+ return readPaseoWorktreeMetadata(worktreeRoot)?.baseRefName ?? null;
617
+ }
618
+ async function getStoredBaseRefForCwd(cwd, context) {
619
+ const paseoWorktree = await getPaseoWorktreeForCwd(cwd, context);
620
+ if (!paseoWorktree.isPaseoOwnedWorktree) {
621
+ return null;
622
+ }
623
+ return readPaseoWorktreeBaseRef(paseoWorktree.worktreeRoot);
624
+ }
625
+ async function getResolvedBaseRefForCwd(cwd, context) {
626
+ const { resolvedBaseRef } = await resolveBaseRefForCwd(cwd, context);
627
+ return resolvedBaseRef;
628
+ }
629
+ async function resolveBaseRefForCwd(cwd, context) {
630
+ const storedBaseRef = await getStoredBaseRefForCwd(cwd, context);
631
+ return {
632
+ storedBaseRef,
633
+ resolvedBaseRef: storedBaseRef ?? (await resolveBaseRef(cwd)),
600
634
  };
601
635
  }
602
636
  async function isWorkingTreeDirty(cwd) {
603
637
  const { stdout } = await runGitCommand(["status", "--porcelain"], {
604
638
  cwd,
605
- env: READ_ONLY_GIT_ENV,
639
+ envOverlay: READ_ONLY_GIT_ENV,
606
640
  });
607
641
  return stdout.trim().length > 0;
608
642
  }
@@ -610,7 +644,7 @@ export async function getOriginRemoteUrl(cwd) {
610
644
  try {
611
645
  const { stdout } = await runGitCommand(["config", "--get", "remote.origin.url"], {
612
646
  cwd,
613
- env: READ_ONLY_GIT_ENV,
647
+ envOverlay: READ_ONLY_GIT_ENV,
614
648
  });
615
649
  const url = stdout.trim();
616
650
  return url.length > 0 ? url : null;
@@ -623,11 +657,50 @@ export async function hasOriginRemote(cwd) {
623
657
  const url = await getOriginRemoteUrl(cwd);
624
658
  return url !== null;
625
659
  }
660
+ async function getGitConfigValue(cwd, key) {
661
+ try {
662
+ const { stdout } = await runGitCommand(["config", "--get", key], {
663
+ cwd,
664
+ envOverlay: READ_ONLY_GIT_ENV,
665
+ });
666
+ const value = stdout.trim();
667
+ return value.length > 0 ? value : null;
668
+ }
669
+ catch {
670
+ return null;
671
+ }
672
+ }
673
+ function parseBranchMergeHeadRef(mergeRef) {
674
+ const prefix = "refs/heads/";
675
+ if (!mergeRef?.startsWith(prefix)) {
676
+ return null;
677
+ }
678
+ const headRef = mergeRef.slice(prefix.length).trim();
679
+ return headRef.length > 0 ? headRef : null;
680
+ }
681
+ async function resolvePullRequestStatusLookupTarget(cwd, currentBranch) {
682
+ const remoteName = await getGitConfigValue(cwd, `branch.${currentBranch}.remote`);
683
+ if (!remoteName?.startsWith("paseo-pr-")) {
684
+ return { headRef: currentBranch };
685
+ }
686
+ const mergeRef = await getGitConfigValue(cwd, `branch.${currentBranch}.merge`);
687
+ const trackedHeadRef = parseBranchMergeHeadRef(mergeRef);
688
+ if (!trackedHeadRef) {
689
+ return { headRef: currentBranch };
690
+ }
691
+ const remoteUrl = await getGitConfigValue(cwd, `remote.${remoteName}.url`);
692
+ const remoteRepo = remoteUrl ? parseGitHubRepoFromRemote(remoteUrl) : null;
693
+ const headRepositoryOwner = remoteRepo?.split("/")[0];
694
+ return {
695
+ headRef: trackedHeadRef,
696
+ ...(headRepositoryOwner ? { headRepositoryOwner } : {}),
697
+ };
698
+ }
626
699
  export async function resolveAbsoluteGitDir(cwd) {
627
700
  try {
628
701
  const { stdout } = await runGitCommand(["rev-parse", "--absolute-git-dir"], {
629
702
  cwd,
630
- env: READ_ONLY_GIT_ENV,
703
+ envOverlay: READ_ONLY_GIT_ENV,
631
704
  });
632
705
  const gitDir = stdout.trim();
633
706
  return gitDir.length > 0 ? gitDir : null;
@@ -665,7 +738,7 @@ export async function resolveRepositoryDefaultBranch(repoRoot) {
665
738
  try {
666
739
  const { stdout } = await runGitCommand(["symbolic-ref", "--quiet", "refs/remotes/origin/HEAD"], {
667
740
  cwd: repoRoot,
668
- env: READ_ONLY_GIT_ENV,
741
+ envOverlay: READ_ONLY_GIT_ENV,
669
742
  });
670
743
  const ref = stdout.trim();
671
744
  if (ref) {
@@ -678,7 +751,7 @@ export async function resolveRepositoryDefaultBranch(repoRoot) {
678
751
  try {
679
752
  await runGitCommand(["show-ref", "--verify", "--quiet", `refs/heads/${localName}`], {
680
753
  cwd: repoRoot,
681
- env: READ_ONLY_GIT_ENV,
754
+ envOverlay: READ_ONLY_GIT_ENV,
682
755
  });
683
756
  return localName;
684
757
  }
@@ -692,16 +765,16 @@ export async function resolveRepositoryDefaultBranch(repoRoot) {
692
765
  }
693
766
  const { stdout } = await runGitCommand(["branch", "--format=%(refname:short)"], {
694
767
  cwd: repoRoot,
695
- env: READ_ONLY_GIT_ENV,
768
+ envOverlay: READ_ONLY_GIT_ENV,
696
769
  });
697
- const branches = stdout
770
+ const branches = new Set(stdout
698
771
  .split("\n")
699
772
  .map((line) => line.trim())
700
- .filter((line) => line.length > 0);
701
- if (branches.includes("main")) {
773
+ .filter((line) => line.length > 0));
774
+ if (branches.has("main")) {
702
775
  return "main";
703
776
  }
704
- if (branches.includes("master")) {
777
+ if (branches.has("master")) {
705
778
  return "master";
706
779
  }
707
780
  return null;
@@ -728,7 +801,7 @@ function normalizeComparisonBaseRefName(input) {
728
801
  async function doesGitRefExist(cwd, fullRef) {
729
802
  const result = await runGitCommand(["show-ref", "--verify", "--quiet", fullRef], {
730
803
  cwd,
731
- env: READ_ONLY_GIT_ENV,
804
+ envOverlay: READ_ONLY_GIT_ENV,
732
805
  acceptExitCodes: [0, 1],
733
806
  });
734
807
  return result.exitCode === 0;
@@ -764,7 +837,7 @@ async function resolveMostAheadBaseRef(cwd, normalizedBaseRef) {
764
837
  if (!hasLocal && !hasOrigin) {
765
838
  throw new Error(`Base branch not found locally or on origin: ${normalizedBaseRef}`);
766
839
  }
767
- const { stdout } = await runGitCommand(["rev-list", "--left-right", "--count", `${normalizedBaseRef}...origin/${normalizedBaseRef}`], { cwd, env: READ_ONLY_GIT_ENV });
840
+ const { stdout } = await runGitCommand(["rev-list", "--left-right", "--count", `${normalizedBaseRef}...origin/${normalizedBaseRef}`], { cwd, envOverlay: READ_ONLY_GIT_ENV });
768
841
  const [localOnlyRaw, originOnlyRaw] = stdout.trim().split(/\s+/);
769
842
  const localOnly = Number.parseInt(localOnlyRaw ?? "0", 10);
770
843
  const originOnly = Number.parseInt(originOnlyRaw ?? "0", 10);
@@ -782,7 +855,7 @@ async function getAheadBehind(cwd, baseRef, currentBranch) {
782
855
  return null;
783
856
  }
784
857
  const comparisonBaseRef = await resolveBestComparisonBaseRef(cwd, baseRef);
785
- const { stdout } = await runGitCommand(["rev-list", "--left-right", "--count", `${comparisonBaseRef}...${currentBranch}`], { cwd, env: READ_ONLY_GIT_ENV });
858
+ const { stdout } = await runGitCommand(["rev-list", "--left-right", "--count", `${comparisonBaseRef}...${currentBranch}`], { cwd, envOverlay: READ_ONLY_GIT_ENV });
786
859
  const [behindRaw, aheadRaw] = stdout.trim().split(/\s+/);
787
860
  const behind = Number.parseInt(behindRaw ?? "0", 10);
788
861
  const ahead = Number.parseInt(aheadRaw ?? "0", 10);
@@ -796,7 +869,7 @@ async function getAheadOfOrigin(cwd, currentBranch) {
796
869
  return null;
797
870
  }
798
871
  try {
799
- const { stdout } = await runGitCommand(["rev-list", "--count", `origin/${currentBranch}..${currentBranch}`], { cwd, env: READ_ONLY_GIT_ENV });
872
+ const { stdout } = await runGitCommand(["rev-list", "--count", `origin/${currentBranch}..${currentBranch}`], { cwd, envOverlay: READ_ONLY_GIT_ENV });
800
873
  const count = Number.parseInt(stdout.trim(), 10);
801
874
  return Number.isNaN(count) ? null : count;
802
875
  }
@@ -804,7 +877,7 @@ async function getAheadOfOrigin(cwd, currentBranch) {
804
877
  try {
805
878
  const { stdout } = await runGitCommand(["rev-list", "--count", currentBranch], {
806
879
  cwd,
807
- env: READ_ONLY_GIT_ENV,
880
+ envOverlay: READ_ONLY_GIT_ENV,
808
881
  });
809
882
  const count = Number.parseInt(stdout.trim(), 10);
810
883
  return Number.isNaN(count) ? null : count;
@@ -819,7 +892,7 @@ async function getBehindOfOrigin(cwd, currentBranch) {
819
892
  return null;
820
893
  }
821
894
  try {
822
- const { stdout } = await runGitCommand(["rev-list", "--count", `${currentBranch}..origin/${currentBranch}`], { cwd, env: READ_ONLY_GIT_ENV });
895
+ const { stdout } = await runGitCommand(["rev-list", "--count", `${currentBranch}..origin/${currentBranch}`], { cwd, envOverlay: READ_ONLY_GIT_ENV });
823
896
  const count = Number.parseInt(stdout.trim(), 10);
824
897
  return Number.isNaN(count) ? null : count;
825
898
  }
@@ -833,16 +906,16 @@ async function inspectCheckoutContext(cwd, context) {
833
906
  if (!root) {
834
907
  return null;
835
908
  }
836
- const [currentBranch, remoteUrl, configured] = await Promise.all([
909
+ const [currentBranch, remoteUrl, paseoWorktree] = await Promise.all([
837
910
  getCurrentBranch(cwd),
838
911
  getOriginRemoteUrl(cwd),
839
- getConfiguredBaseRefForCwd(cwd, context),
912
+ getPaseoWorktreeForCwd(cwd, context),
840
913
  ]);
841
914
  return {
842
915
  worktreeRoot: root,
843
916
  currentBranch,
844
917
  remoteUrl,
845
- configured,
918
+ paseoWorktree,
846
919
  };
847
920
  }
848
921
  catch (error) {
@@ -929,7 +1002,7 @@ async function getUntrackedDiffText(cwd, change, ignoreWhitespace = false) {
929
1002
  extra: ["--no-index", "/dev/null", "--", change.path],
930
1003
  }), {
931
1004
  cwd,
932
- env: READ_ONLY_GIT_ENV,
1005
+ envOverlay: READ_ONLY_GIT_ENV,
933
1006
  maxOutputBytes: PER_FILE_DIFF_MAX_BYTES,
934
1007
  acceptExitCodes: [0, 1],
935
1008
  });
@@ -947,24 +1020,24 @@ export async function getCheckoutStatus(cwd, context) {
947
1020
  const worktreeRoot = inspected.worktreeRoot;
948
1021
  const currentBranch = inspected.currentBranch;
949
1022
  const remoteUrl = inspected.remoteUrl;
950
- const configured = inspected.configured;
1023
+ const paseoWorktree = inspected.paseoWorktree;
951
1024
  const isDirty = await isWorkingTreeDirty(cwd);
952
1025
  const hasRemote = remoteUrl !== null;
953
- const baseRef = configured.baseRef ?? (await resolveBaseRef(cwd));
1026
+ const { resolvedBaseRef: baseRef } = await resolveBaseRefForCwd(cwd, context);
1027
+ const mainRepoRoot = await getMainRepoRoot(cwd).catch(() => null);
954
1028
  const [aheadBehind, aheadOfOrigin, behindOfOrigin] = await Promise.all([
955
1029
  baseRef && currentBranch ? getAheadBehind(cwd, baseRef, currentBranch) : Promise.resolve(null),
956
1030
  hasRemote && currentBranch ? getAheadOfOrigin(cwd, currentBranch) : Promise.resolve(null),
957
1031
  hasRemote && currentBranch ? getBehindOfOrigin(cwd, currentBranch) : Promise.resolve(null),
958
1032
  ]);
959
- if (configured.isPaseoOwnedWorktree) {
960
- const mainRepoRoot = await getMainRepoRoot(cwd);
1033
+ if (paseoWorktree.isPaseoOwnedWorktree && baseRef) {
961
1034
  return {
962
1035
  isGit: true,
963
1036
  repoRoot: worktreeRoot,
964
- mainRepoRoot,
1037
+ mainRepoRoot: mainRepoRoot ?? worktreeRoot,
965
1038
  currentBranch,
966
1039
  isDirty,
967
- baseRef: configured.baseRef,
1040
+ baseRef,
968
1041
  aheadBehind,
969
1042
  aheadOfOrigin,
970
1043
  behindOfOrigin,
@@ -976,6 +1049,7 @@ export async function getCheckoutStatus(cwd, context) {
976
1049
  return {
977
1050
  isGit: true,
978
1051
  repoRoot: worktreeRoot,
1052
+ mainRepoRoot: mainRepoRoot && resolve(mainRepoRoot) !== resolve(worktreeRoot) ? mainRepoRoot : null,
979
1053
  currentBranch,
980
1054
  isDirty,
981
1055
  baseRef,
@@ -1014,8 +1088,7 @@ async function getCheckoutShortstatUncached(cwd, context) {
1014
1088
  catch {
1015
1089
  return null;
1016
1090
  }
1017
- const configured = await getConfiguredBaseRefForCwd(cwd, context);
1018
- const localBaseRef = configured.baseRef ?? (await resolveBaseRef(cwd));
1091
+ const localBaseRef = await getResolvedBaseRefForCwd(cwd, context);
1019
1092
  const currentBranch = await getCurrentBranch(cwd);
1020
1093
  let comparisonRef;
1021
1094
  if (currentBranch && localBaseRef && currentBranch !== localBaseRef) {
@@ -1039,7 +1112,7 @@ async function getCheckoutShortstatUncached(cwd, context) {
1039
1112
  try {
1040
1113
  const { stdout: mergeBaseOut } = await runGitCommand(["merge-base", "HEAD", comparisonRef], {
1041
1114
  cwd,
1042
- env: READ_ONLY_GIT_ENV,
1115
+ envOverlay: READ_ONLY_GIT_ENV,
1043
1116
  });
1044
1117
  const mergeBase = mergeBaseOut.trim();
1045
1118
  if (!mergeBase) {
@@ -1047,7 +1120,7 @@ async function getCheckoutShortstatUncached(cwd, context) {
1047
1120
  }
1048
1121
  const { stdout } = await runGitCommand(["diff", "--shortstat", mergeBase], {
1049
1122
  cwd,
1050
- env: READ_ONLY_GIT_ENV,
1123
+ envOverlay: READ_ONLY_GIT_ENV,
1051
1124
  });
1052
1125
  return parseCheckoutShortstat(stdout);
1053
1126
  }
@@ -1092,32 +1165,143 @@ export function warmCheckoutShortstatInBackground(cwd, context, onComplete) {
1092
1165
  void getOrLoadCheckoutShortstat(cwd, context)
1093
1166
  .then(() => {
1094
1167
  onComplete?.();
1168
+ return;
1095
1169
  })
1096
1170
  .catch(() => {
1097
1171
  // Non-critical: keep listing path resilient even if git commands fail.
1098
1172
  });
1099
1173
  }
1100
- export async function getCheckoutDiff(cwd, compare, context) {
1101
- await requireGitRepo(cwd);
1102
- let refsForDiff;
1103
- if (compare.mode === "uncommitted") {
1104
- refsForDiff = { baseRef: "HEAD", includeUntracked: true };
1174
+ async function appendStructuredTrackedDiffs(input) {
1175
+ const { cwd, trackedChanges, trackedChangeByPath, trackedNumstatByPath, trackedPlaceholderByPath, trackedDiffText, trackedDiffTruncated, refsForDiff, ignoreWhitespace, structured, appendTrackedPlaceholderComment, } = input;
1176
+ const parsedTrackedFiles = trackedDiffText.length > 0
1177
+ ? await parseAndHighlightDiff(trackedDiffText, cwd, {
1178
+ getOldFileContent: async (file) => {
1179
+ const change = trackedChangeByPath.get(file.path);
1180
+ if (!change || change.isNew) {
1181
+ return null;
1182
+ }
1183
+ const refPath = change.oldPath ?? change.path;
1184
+ return readGitFileContentAtRef(cwd, refsForDiff.baseRef, refPath);
1185
+ },
1186
+ getNewFileContent: async (file) => {
1187
+ if (!refsForDiff.targetRef) {
1188
+ return null;
1189
+ }
1190
+ return readGitFileContentAtRef(cwd, refsForDiff.targetRef, file.path);
1191
+ },
1192
+ })
1193
+ : [];
1194
+ const parsedTrackedByPath = new Map(parsedTrackedFiles.map((file) => [file.path, file]));
1195
+ for (const change of trackedChanges) {
1196
+ const placeholder = trackedPlaceholderByPath.get(change.path);
1197
+ if (placeholder) {
1198
+ structured.push(buildPlaceholderParsedDiffFile(change, {
1199
+ status: placeholder.status,
1200
+ stat: placeholder.stat,
1201
+ }));
1202
+ appendTrackedPlaceholderComment(change, placeholder.status);
1203
+ continue;
1204
+ }
1205
+ const stat = trackedNumstatByPath.get(change.path) ?? null;
1206
+ const parsedFile = parsedTrackedByPath.get(change.path);
1207
+ if (parsedFile) {
1208
+ structured.push({
1209
+ ...parsedFile,
1210
+ path: change.path,
1211
+ isNew: change.isNew,
1212
+ isDeleted: change.isDeleted,
1213
+ status: "ok",
1214
+ });
1215
+ continue;
1216
+ }
1217
+ // `git diff -w --name-status` can still report a modified path even when the
1218
+ // whitespace-filtered patch and numstat are both empty. Skip emitting a
1219
+ // structured placeholder in that case so whitespace-only edits truly disappear.
1220
+ if (ignoreWhitespace &&
1221
+ !trackedDiffTruncated &&
1222
+ change.status.startsWith("M") &&
1223
+ (!stat || (!stat.isBinary && stat.additions === 0 && stat.deletions === 0))) {
1224
+ continue;
1225
+ }
1226
+ structured.push({
1227
+ path: change.path,
1228
+ isNew: change.isNew,
1229
+ isDeleted: change.isDeleted,
1230
+ additions: stat?.additions ?? 0,
1231
+ deletions: stat?.deletions ?? 0,
1232
+ hunks: [],
1233
+ status: trackedDiffTruncated ? "too_large" : "ok",
1234
+ });
1105
1235
  }
1106
- else {
1107
- const configured = await getConfiguredBaseRefForCwd(cwd, context);
1108
- const baseRef = configured.baseRef ?? compare.baseRef ?? (await resolveBaseRef(cwd));
1109
- if (!baseRef) {
1110
- return { diff: "" };
1111
- }
1112
- if (configured.isPaseoOwnedWorktree && compare.baseRef && compare.baseRef !== baseRef) {
1113
- throw new Error(`Base ref mismatch: expected ${baseRef}, got ${compare.baseRef}`);
1114
- }
1115
- const bestBaseRef = await resolveBestComparisonBaseRef(cwd, baseRef);
1116
- refsForDiff = {
1117
- baseRef: (await tryResolveMergeBase(cwd, bestBaseRef)) ?? bestBaseRef,
1118
- targetRef: "HEAD",
1119
- includeUntracked: false,
1236
+ }
1237
+ async function processUntrackedChange(input) {
1238
+ const { cwd, change, ignoreWhitespace, includeStructured, structured, appendDiff } = input;
1239
+ const { text, truncated, stat } = await getUntrackedDiffText(cwd, change, ignoreWhitespace);
1240
+ if (!includeStructured) {
1241
+ if (stat?.isBinary) {
1242
+ appendDiff(`# ${change.path}: binary diff omitted\n`);
1243
+ }
1244
+ else if (truncated) {
1245
+ appendDiff(`# ${change.path}: diff too large omitted\n`);
1246
+ }
1247
+ else {
1248
+ appendDiff(text);
1249
+ }
1250
+ return;
1251
+ }
1252
+ if (stat?.isBinary) {
1253
+ structured.push(buildPlaceholderParsedDiffFile(change, { status: "binary", stat }));
1254
+ appendDiff(`# ${change.path}: binary diff omitted\n`);
1255
+ return;
1256
+ }
1257
+ if (truncated) {
1258
+ structured.push(buildPlaceholderParsedDiffFile(change, { status: "too_large", stat }));
1259
+ appendDiff(`# ${change.path}: diff too large omitted\n`);
1260
+ return;
1261
+ }
1262
+ appendDiff(text);
1263
+ const parsed = await parseAndHighlightDiff(text, cwd);
1264
+ const parsedFile = parsed[0] ??
1265
+ {
1266
+ path: change.path,
1267
+ isNew: change.isNew,
1268
+ isDeleted: change.isDeleted,
1269
+ additions: stat?.additions ?? 0,
1270
+ deletions: stat?.deletions ?? 0,
1271
+ hunks: [],
1120
1272
  };
1273
+ structured.push({
1274
+ ...parsedFile,
1275
+ path: change.path,
1276
+ isNew: change.isNew,
1277
+ isDeleted: change.isDeleted,
1278
+ status: "ok",
1279
+ });
1280
+ }
1281
+ async function resolveCheckoutDiffRefs(cwd, compare, context) {
1282
+ if (compare.mode === "uncommitted") {
1283
+ return { baseRef: "HEAD", includeUntracked: true };
1284
+ }
1285
+ const { storedBaseRef, resolvedBaseRef } = await resolveBaseRefForCwd(cwd, context);
1286
+ const baseRef = compare.baseRef ?? resolvedBaseRef;
1287
+ if (!baseRef) {
1288
+ return null;
1289
+ }
1290
+ if (storedBaseRef && compare.baseRef && compare.baseRef !== storedBaseRef) {
1291
+ throw new Error(`Base ref mismatch: expected ${baseRef}, got ${compare.baseRef}`);
1292
+ }
1293
+ const bestBaseRef = await resolveBestComparisonBaseRef(cwd, baseRef);
1294
+ return {
1295
+ baseRef: (await tryResolveMergeBase(cwd, bestBaseRef)) ?? bestBaseRef,
1296
+ targetRef: "HEAD",
1297
+ includeUntracked: false,
1298
+ };
1299
+ }
1300
+ export async function getCheckoutDiff(cwd, compare, context) {
1301
+ await requireGitRepo(cwd);
1302
+ const refsForDiff = await resolveCheckoutDiffRefs(cwd, compare, context);
1303
+ if (!refsForDiff) {
1304
+ return { diff: "" };
1121
1305
  }
1122
1306
  const ignoreWhitespace = compare.ignoreWhitespace === true;
1123
1307
  const changes = await listCheckoutFileChanges(cwd, refsForDiff, ignoreWhitespace);
@@ -1174,7 +1358,7 @@ export async function getCheckoutDiff(cwd, compare, context) {
1174
1358
  extra: [...getCheckoutDiffRefArgs(refsForDiff), "--", ...trackedDiffPaths],
1175
1359
  }), {
1176
1360
  cwd,
1177
- env: READ_ONLY_GIT_ENV,
1361
+ envOverlay: READ_ONLY_GIT_ENV,
1178
1362
  maxOutputBytes: TOTAL_DIFF_MAX_BYTES,
1179
1363
  });
1180
1364
  trackedDiffText = trackedDiffResult.stdout;
@@ -1192,66 +1376,20 @@ export async function getCheckoutDiff(cwd, compare, context) {
1192
1376
  appendDiff(`# ${change.path}: diff too large omitted\n`);
1193
1377
  };
1194
1378
  if (compare.includeStructured) {
1195
- const parsedTrackedFiles = trackedDiffText.length > 0
1196
- ? await parseAndHighlightDiff(trackedDiffText, cwd, {
1197
- getOldFileContent: async (file) => {
1198
- const change = trackedChangeByPath.get(file.path);
1199
- if (!change || change.isNew) {
1200
- return null;
1201
- }
1202
- const refPath = change.oldPath ?? change.path;
1203
- return readGitFileContentAtRef(cwd, refsForDiff.baseRef, refPath);
1204
- },
1205
- getNewFileContent: async (file) => {
1206
- if (!refsForDiff.targetRef) {
1207
- return null;
1208
- }
1209
- return readGitFileContentAtRef(cwd, refsForDiff.targetRef, file.path);
1210
- },
1211
- })
1212
- : [];
1213
- const parsedTrackedByPath = new Map(parsedTrackedFiles.map((file) => [file.path, file]));
1214
- for (const change of trackedChanges) {
1215
- const placeholder = trackedPlaceholderByPath.get(change.path);
1216
- if (placeholder) {
1217
- structured.push(buildPlaceholderParsedDiffFile(change, {
1218
- status: placeholder.status,
1219
- stat: placeholder.stat,
1220
- }));
1221
- appendTrackedPlaceholderComment(change, placeholder.status);
1222
- continue;
1223
- }
1224
- const stat = trackedNumstatByPath.get(change.path) ?? null;
1225
- const parsedFile = parsedTrackedByPath.get(change.path);
1226
- if (parsedFile) {
1227
- structured.push({
1228
- ...parsedFile,
1229
- path: change.path,
1230
- isNew: change.isNew,
1231
- isDeleted: change.isDeleted,
1232
- status: "ok",
1233
- });
1234
- continue;
1235
- }
1236
- // `git diff -w --name-status` can still report a modified path even when the
1237
- // whitespace-filtered patch and numstat are both empty. Skip emitting a
1238
- // structured placeholder in that case so whitespace-only edits truly disappear.
1239
- if (ignoreWhitespace &&
1240
- !trackedDiffTruncated &&
1241
- change.status.startsWith("M") &&
1242
- (!stat || (!stat.isBinary && stat.additions === 0 && stat.deletions === 0))) {
1243
- continue;
1244
- }
1245
- structured.push({
1246
- path: change.path,
1247
- isNew: change.isNew,
1248
- isDeleted: change.isDeleted,
1249
- additions: stat?.additions ?? 0,
1250
- deletions: stat?.deletions ?? 0,
1251
- hunks: [],
1252
- status: trackedDiffTruncated ? "too_large" : "ok",
1253
- });
1254
- }
1379
+ await appendStructuredTrackedDiffs({
1380
+ cwd,
1381
+ trackedChanges,
1382
+ trackedChangeByPath,
1383
+ trackedNumstatByPath,
1384
+ trackedPlaceholderByPath,
1385
+ trackedDiffText,
1386
+ trackedDiffTruncated,
1387
+ refsForDiff,
1388
+ ignoreWhitespace,
1389
+ structured,
1390
+ appendDiff,
1391
+ appendTrackedPlaceholderComment,
1392
+ });
1255
1393
  }
1256
1394
  else {
1257
1395
  for (const change of trackedChanges) {
@@ -1265,46 +1403,13 @@ export async function getCheckoutDiff(cwd, compare, context) {
1265
1403
  if (diffBytes >= TOTAL_DIFF_MAX_BYTES) {
1266
1404
  break;
1267
1405
  }
1268
- const { text, truncated, stat } = await getUntrackedDiffText(cwd, change, ignoreWhitespace);
1269
- if (!compare.includeStructured) {
1270
- if (stat?.isBinary) {
1271
- appendDiff(`# ${change.path}: binary diff omitted\n`);
1272
- }
1273
- else if (truncated) {
1274
- appendDiff(`# ${change.path}: diff too large omitted\n`);
1275
- }
1276
- else {
1277
- appendDiff(text);
1278
- }
1279
- continue;
1280
- }
1281
- if (stat?.isBinary) {
1282
- structured.push(buildPlaceholderParsedDiffFile(change, { status: "binary", stat }));
1283
- appendDiff(`# ${change.path}: binary diff omitted\n`);
1284
- continue;
1285
- }
1286
- if (truncated) {
1287
- structured.push(buildPlaceholderParsedDiffFile(change, { status: "too_large", stat }));
1288
- appendDiff(`# ${change.path}: diff too large omitted\n`);
1289
- continue;
1290
- }
1291
- appendDiff(text);
1292
- const parsed = await parseAndHighlightDiff(text, cwd);
1293
- const parsedFile = parsed[0] ??
1294
- {
1295
- path: change.path,
1296
- isNew: change.isNew,
1297
- isDeleted: change.isDeleted,
1298
- additions: stat?.additions ?? 0,
1299
- deletions: stat?.deletions ?? 0,
1300
- hunks: [],
1301
- };
1302
- structured.push({
1303
- ...parsedFile,
1304
- path: change.path,
1305
- isNew: change.isNew,
1306
- isDeleted: change.isDeleted,
1307
- status: "ok",
1406
+ await processUntrackedChange({
1407
+ cwd,
1408
+ change,
1409
+ ignoreWhitespace,
1410
+ includeStructured: compare.includeStructured === true,
1411
+ structured,
1412
+ appendDiff,
1308
1413
  });
1309
1414
  }
1310
1415
  if (compare.includeStructured) {
@@ -1325,15 +1430,66 @@ export async function commitChanges(cwd, options) {
1325
1430
  export async function commitAll(cwd, message) {
1326
1431
  await commitChanges(cwd, { message, addAll: true });
1327
1432
  }
1433
+ async function detectAndThrowMergeToBaseConflict(input) {
1434
+ const { operationCwd, error, baseRef, currentBranch } = input;
1435
+ const errorDetails = error instanceof Error
1436
+ ? `${error.message}\n${error.stderr ?? ""}\n${error.stdout ?? ""}`
1437
+ : String(error);
1438
+ try {
1439
+ const [unmergedOutput, lsFilesOutput, statusOutput] = await Promise.all([
1440
+ runGitCommand(["diff", "--name-only", "--diff-filter=U"], { cwd: operationCwd }),
1441
+ runGitCommand(["ls-files", "-u"], { cwd: operationCwd }),
1442
+ runGitCommand(["status", "--porcelain"], { cwd: operationCwd }),
1443
+ ]);
1444
+ const statusConflicts = statusOutput.stdout
1445
+ .split("\n")
1446
+ .map((line) => line.trim())
1447
+ .filter(Boolean)
1448
+ .filter((line) => /^(UU|AA|DD|AU|UA|UD|DU)\s/.test(line))
1449
+ .map((line) => line.slice(3).trim());
1450
+ const conflicts = [
1451
+ ...unmergedOutput.stdout
1452
+ .split("\n")
1453
+ .map((line) => line.trim())
1454
+ .filter(Boolean),
1455
+ ...lsFilesOutput.stdout
1456
+ .split("\n")
1457
+ .map((line) => line.trim())
1458
+ .filter(Boolean)
1459
+ .map((line) => line.split("\t").pop()),
1460
+ ...statusConflicts,
1461
+ ].filter(Boolean);
1462
+ const conflictDetected = conflicts.length > 0 || /CONFLICT|Automatic merge failed/i.test(errorDetails);
1463
+ if (conflictDetected) {
1464
+ try {
1465
+ await runGitCommand(["merge", "--abort"], { cwd: operationCwd, timeout: 120000 });
1466
+ }
1467
+ catch {
1468
+ // ignore
1469
+ }
1470
+ throw new MergeConflictError({
1471
+ baseRef,
1472
+ currentBranch,
1473
+ conflictFiles: conflicts.length > 0 ? conflicts : [],
1474
+ });
1475
+ }
1476
+ }
1477
+ catch (innerError) {
1478
+ if (innerError instanceof MergeConflictError) {
1479
+ throw innerError;
1480
+ }
1481
+ // ignore detection failures
1482
+ }
1483
+ }
1328
1484
  export async function mergeToBase(cwd, options = {}, context) {
1329
1485
  await requireGitRepo(cwd);
1330
1486
  const currentBranch = await getCurrentBranch(cwd);
1331
- const configured = await getConfiguredBaseRefForCwd(cwd, context);
1332
- const baseRef = configured.baseRef ?? options.baseRef ?? (await resolveBaseRef(cwd));
1487
+ const { storedBaseRef, resolvedBaseRef } = await resolveBaseRefForCwd(cwd, context);
1488
+ const baseRef = options.baseRef ?? resolvedBaseRef;
1333
1489
  if (!baseRef) {
1334
1490
  throw new Error("Unable to determine base branch for merge");
1335
1491
  }
1336
- if (configured.isPaseoOwnedWorktree && options.baseRef && options.baseRef !== baseRef) {
1492
+ if (storedBaseRef && options.baseRef && options.baseRef !== storedBaseRef) {
1337
1493
  throw new Error(`Base ref mismatch: expected ${baseRef}, got ${options.baseRef}`);
1338
1494
  }
1339
1495
  if (!currentBranch) {
@@ -1371,54 +1527,12 @@ export async function mergeToBase(cwd, options = {}, context) {
1371
1527
  }
1372
1528
  }
1373
1529
  catch (error) {
1374
- const errorDetails = error instanceof Error
1375
- ? `${error.message}\n${error.stderr ?? ""}\n${error.stdout ?? ""}`
1376
- : String(error);
1377
- try {
1378
- const [unmergedOutput, lsFilesOutput, statusOutput] = await Promise.all([
1379
- runGitCommand(["diff", "--name-only", "--diff-filter=U"], { cwd: operationCwd }),
1380
- runGitCommand(["ls-files", "-u"], { cwd: operationCwd }),
1381
- runGitCommand(["status", "--porcelain"], { cwd: operationCwd }),
1382
- ]);
1383
- const statusConflicts = statusOutput.stdout
1384
- .split("\n")
1385
- .map((line) => line.trim())
1386
- .filter(Boolean)
1387
- .filter((line) => /^(UU|AA|DD|AU|UA|UD|DU)\s/.test(line))
1388
- .map((line) => line.slice(3).trim());
1389
- const conflicts = [
1390
- ...unmergedOutput.stdout
1391
- .split("\n")
1392
- .map((line) => line.trim())
1393
- .filter(Boolean),
1394
- ...lsFilesOutput.stdout
1395
- .split("\n")
1396
- .map((line) => line.trim())
1397
- .filter(Boolean)
1398
- .map((line) => line.split("\t").pop()),
1399
- ...statusConflicts,
1400
- ].filter(Boolean);
1401
- const conflictDetected = conflicts.length > 0 || /CONFLICT|Automatic merge failed/i.test(errorDetails);
1402
- if (conflictDetected) {
1403
- try {
1404
- await runGitCommand(["merge", "--abort"], { cwd: operationCwd, timeout: 120000 });
1405
- }
1406
- catch {
1407
- // ignore
1408
- }
1409
- throw new MergeConflictError({
1410
- baseRef: normalizedBaseRef,
1411
- currentBranch,
1412
- conflictFiles: conflicts.length > 0 ? conflicts : [],
1413
- });
1414
- }
1415
- }
1416
- catch (innerError) {
1417
- if (innerError instanceof MergeConflictError) {
1418
- throw innerError;
1419
- }
1420
- // ignore detection failures
1421
- }
1530
+ await detectAndThrowMergeToBaseConflict({
1531
+ operationCwd,
1532
+ error,
1533
+ baseRef: normalizedBaseRef,
1534
+ currentBranch,
1535
+ });
1422
1536
  throw error;
1423
1537
  }
1424
1538
  finally {
@@ -1442,19 +1556,19 @@ export async function mergeFromBase(cwd, options = {}, context) {
1442
1556
  if (!currentBranch || currentBranch === "HEAD") {
1443
1557
  throw new Error("Unable to determine current branch for merge");
1444
1558
  }
1445
- const configured = await getConfiguredBaseRefForCwd(cwd, context);
1446
- const baseRef = configured.baseRef ?? options.baseRef ?? (await resolveBaseRef(cwd));
1559
+ const { storedBaseRef, resolvedBaseRef } = await resolveBaseRefForCwd(cwd, context);
1560
+ const baseRef = options.baseRef ?? resolvedBaseRef;
1447
1561
  if (!baseRef) {
1448
1562
  throw new Error("Unable to determine base branch for merge");
1449
1563
  }
1450
- if (configured.isPaseoOwnedWorktree && options.baseRef && options.baseRef !== baseRef) {
1564
+ if (storedBaseRef && options.baseRef && options.baseRef !== storedBaseRef) {
1451
1565
  throw new Error(`Base ref mismatch: expected ${baseRef}, got ${options.baseRef}`);
1452
1566
  }
1453
1567
  const requireCleanTarget = options.requireCleanTarget ?? true;
1454
1568
  if (requireCleanTarget) {
1455
1569
  const { stdout } = await runGitCommand(["status", "--porcelain"], {
1456
1570
  cwd,
1457
- env: READ_ONLY_GIT_ENV,
1571
+ envOverlay: READ_ONLY_GIT_ENV,
1458
1572
  });
1459
1573
  if (stdout.trim().length > 0) {
1460
1574
  throw new Error("Working directory has uncommitted changes.");
@@ -1469,55 +1583,64 @@ export async function mergeFromBase(cwd, options = {}, context) {
1469
1583
  await runGitCommand(["merge", bestBaseRef], { cwd, timeout: 120000 });
1470
1584
  }
1471
1585
  catch (error) {
1472
- const errorDetails = error instanceof Error
1473
- ? `${error.message}\n${error.stderr ?? ""}\n${error.stdout ?? ""}`
1474
- : String(error);
1475
- try {
1476
- const [unmergedOutput, lsFilesOutput, statusOutput] = await Promise.all([
1477
- runGitCommand(["diff", "--name-only", "--diff-filter=U"], { cwd }),
1478
- runGitCommand(["ls-files", "-u"], { cwd }),
1479
- runGitCommand(["status", "--porcelain"], { cwd }),
1480
- ]);
1481
- const statusConflicts = statusOutput.stdout
1586
+ await detectAndThrowMergeFromBaseConflict({
1587
+ cwd,
1588
+ error,
1589
+ baseRef: bestBaseRef,
1590
+ currentBranch,
1591
+ });
1592
+ throw error;
1593
+ }
1594
+ }
1595
+ async function detectAndThrowMergeFromBaseConflict(input) {
1596
+ const { cwd, error, baseRef, currentBranch } = input;
1597
+ const errorDetails = error instanceof Error
1598
+ ? `${error.message}\n${error.stderr ?? ""}\n${error.stdout ?? ""}`
1599
+ : String(error);
1600
+ try {
1601
+ const [unmergedOutput, lsFilesOutput, statusOutput] = await Promise.all([
1602
+ runGitCommand(["diff", "--name-only", "--diff-filter=U"], { cwd }),
1603
+ runGitCommand(["ls-files", "-u"], { cwd }),
1604
+ runGitCommand(["status", "--porcelain"], { cwd }),
1605
+ ]);
1606
+ const statusConflicts = statusOutput.stdout
1607
+ .split("\n")
1608
+ .map((line) => line.trim())
1609
+ .filter(Boolean)
1610
+ .filter((line) => /^(UU|AA|DD|AU|UA|UD|DU)\s/.test(line))
1611
+ .map((line) => line.slice(3).trim());
1612
+ const conflicts = [
1613
+ ...unmergedOutput.stdout
1614
+ .split("\n")
1615
+ .map((line) => line.trim())
1616
+ .filter(Boolean),
1617
+ ...lsFilesOutput.stdout
1482
1618
  .split("\n")
1483
1619
  .map((line) => line.trim())
1484
1620
  .filter(Boolean)
1485
- .filter((line) => /^(UU|AA|DD|AU|UA|UD|DU)\s/.test(line))
1486
- .map((line) => line.slice(3).trim());
1487
- const conflicts = [
1488
- ...unmergedOutput.stdout
1489
- .split("\n")
1490
- .map((line) => line.trim())
1491
- .filter(Boolean),
1492
- ...lsFilesOutput.stdout
1493
- .split("\n")
1494
- .map((line) => line.trim())
1495
- .filter(Boolean)
1496
- .map((line) => line.split("\t").pop()),
1497
- ...statusConflicts,
1498
- ].filter(Boolean);
1499
- const conflictDetected = conflicts.length > 0 || /CONFLICT|Automatic merge failed/i.test(errorDetails);
1500
- if (conflictDetected) {
1501
- try {
1502
- await runGitCommand(["merge", "--abort"], { cwd, timeout: 120000 });
1503
- }
1504
- catch {
1505
- // ignore
1506
- }
1507
- throw new MergeFromBaseConflictError({
1508
- baseRef: bestBaseRef,
1509
- currentBranch,
1510
- conflictFiles: conflicts.length > 0 ? conflicts : [],
1511
- });
1621
+ .map((line) => line.split("\t").pop()),
1622
+ ...statusConflicts,
1623
+ ].filter(Boolean);
1624
+ const conflictDetected = conflicts.length > 0 || /CONFLICT|Automatic merge failed/i.test(errorDetails);
1625
+ if (conflictDetected) {
1626
+ try {
1627
+ await runGitCommand(["merge", "--abort"], { cwd, timeout: 120000 });
1512
1628
  }
1513
- }
1514
- catch (innerError) {
1515
- if (innerError instanceof MergeFromBaseConflictError) {
1516
- throw innerError;
1629
+ catch {
1630
+ // ignore
1517
1631
  }
1518
- // ignore detection failures
1632
+ throw new MergeFromBaseConflictError({
1633
+ baseRef,
1634
+ currentBranch,
1635
+ conflictFiles: conflicts.length > 0 ? conflicts : [],
1636
+ });
1519
1637
  }
1520
- throw error;
1638
+ }
1639
+ catch (innerError) {
1640
+ if (innerError instanceof MergeFromBaseConflictError) {
1641
+ throw innerError;
1642
+ }
1643
+ // ignore detection failures
1521
1644
  }
1522
1645
  }
1523
1646
  export async function pullCurrentBranch(cwd, github) {
@@ -1552,15 +1675,15 @@ export async function pushCurrentBranch(cwd, github) {
1552
1675
  await runGitCommand(["push", "-u", "origin", currentBranch], { cwd, timeout: 120000 });
1553
1676
  github?.invalidate({ cwd });
1554
1677
  }
1555
- export async function createPullRequest(cwd, options, github = createGitHubService(), workspaceGitService) {
1678
+ export async function createPullRequest(cwd, options, github = createGitHubService(), context) {
1556
1679
  await requireGitRepo(cwd);
1557
- const repo = await resolveGitHubRepo(cwd, { workspaceGitService });
1680
+ const repo = await resolveGitHubRepo(cwd);
1558
1681
  if (!repo) {
1559
1682
  throw new Error("Unable to determine GitHub repo from git remote");
1560
1683
  }
1561
1684
  const head = options.head ?? (await getCurrentBranch(cwd));
1562
- const configured = await getConfiguredBaseRefForCwd(cwd);
1563
- const base = configured.baseRef ?? options.base ?? (await resolveBaseRef(cwd));
1685
+ const { storedBaseRef, resolvedBaseRef } = await resolveBaseRefForCwd(cwd, context);
1686
+ const base = options.base ?? resolvedBaseRef;
1564
1687
  if (!head) {
1565
1688
  throw new Error("Unable to determine head branch for PR");
1566
1689
  }
@@ -1568,7 +1691,7 @@ export async function createPullRequest(cwd, options, github = createGitHubServi
1568
1691
  throw new Error("Unable to determine base branch for PR");
1569
1692
  }
1570
1693
  const normalizedBase = normalizeLocalBranchRefName(base);
1571
- if (configured.isPaseoOwnedWorktree && options.base && options.base !== base) {
1694
+ if (storedBaseRef && options.base && options.base !== storedBaseRef) {
1572
1695
  throw new Error(`Base ref mismatch: expected ${base}, got ${options.base}`);
1573
1696
  }
1574
1697
  await runGitCommand(["push", "-u", "origin", head], { cwd, timeout: 120000 });
@@ -1598,7 +1721,17 @@ export async function getPullRequestStatus(cwd, github = createGitHubService(),
1598
1721
  const lookup = getPullRequestStatusUncached(cwd, github, options)
1599
1722
  .then((status) => {
1600
1723
  pullRequestStatusCache.set(cacheKey, status);
1724
+ rememberPullRequestStatus(cacheKey, status);
1601
1725
  return status;
1726
+ })
1727
+ .catch((error) => {
1728
+ if (error instanceof GitHubCommandError) {
1729
+ const stale = lastSuccessfulPullRequestStatus.get(cacheKey);
1730
+ if (stale) {
1731
+ return stale;
1732
+ }
1733
+ }
1734
+ throw error;
1602
1735
  })
1603
1736
  .finally(() => {
1604
1737
  pullRequestStatusInFlight.delete(cacheKey);
@@ -1616,9 +1749,10 @@ async function getPullRequestStatusUncached(cwd, github, options) {
1616
1749
  };
1617
1750
  }
1618
1751
  try {
1752
+ const lookupTarget = await resolvePullRequestStatusLookupTarget(cwd, head);
1619
1753
  const status = await github.getCurrentPullRequestStatus({
1620
1754
  cwd,
1621
- headRef: head,
1755
+ ...lookupTarget,
1622
1756
  reason: options?.reason,
1623
1757
  });
1624
1758
  return {