@camerontaylor/paseo-server 0.8.0-fork.1

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 (928) hide show
  1. package/.env.example +31 -0
  2. package/README.md +111 -0
  3. package/dist/scripts/dev-runner.js +37 -0
  4. package/dist/scripts/mcp-stdio-socket-bridge-cli.mjs +62 -0
  5. package/dist/scripts/supervisor-entrypoint.js +160 -0
  6. package/dist/scripts/supervisor-log-config.js +31 -0
  7. package/dist/scripts/supervisor.js +313 -0
  8. package/dist/server/executable-resolution/executable-resolution.d.ts +10 -0
  9. package/dist/server/executable-resolution/executable-resolution.js +121 -0
  10. package/dist/server/executable-resolution/windows.d.ts +18 -0
  11. package/dist/server/executable-resolution/windows.js +65 -0
  12. package/dist/server/server/agent/activity-curator.d.ts +40 -0
  13. package/dist/server/server/agent/activity-curator.js +243 -0
  14. package/dist/server/server/agent/agent-archive.d.ts +11 -0
  15. package/dist/server/server/agent/agent-archive.js +16 -0
  16. package/dist/server/server/agent/agent-configuration-validator.d.ts +18 -0
  17. package/dist/server/server/agent/agent-configuration-validator.js +42 -0
  18. package/dist/server/server/agent/agent-loading.d.ts +17 -0
  19. package/dist/server/server/agent/agent-loading.js +88 -0
  20. package/dist/server/server/agent/agent-manager.d.ts +555 -0
  21. package/dist/server/server/agent/agent-manager.js +3930 -0
  22. package/dist/server/server/agent/agent-owner.d.ts +12 -0
  23. package/dist/server/server/agent/agent-owner.js +12 -0
  24. package/dist/server/server/agent/agent-projections.d.ts +26 -0
  25. package/dist/server/server/agent/agent-projections.js +414 -0
  26. package/dist/server/server/agent/agent-prompt.d.ts +91 -0
  27. package/dist/server/server/agent/agent-prompt.js +359 -0
  28. package/dist/server/server/agent/agent-response-loop.d.ts +72 -0
  29. package/dist/server/server/agent/agent-response-loop.js +336 -0
  30. package/dist/server/server/agent/agent-run-state.d.ts +76 -0
  31. package/dist/server/server/agent/agent-run-state.js +212 -0
  32. package/dist/server/server/agent/agent-sdk-types.d.ts +742 -0
  33. package/dist/server/server/agent/agent-sdk-types.js +25 -0
  34. package/dist/server/server/agent/agent-storage.d.ts +148 -0
  35. package/dist/server/server/agent/agent-storage.js +401 -0
  36. package/dist/server/server/agent/agent-stream-coalescer.d.ts +43 -0
  37. package/dist/server/server/agent/agent-stream-coalescer.js +187 -0
  38. package/dist/server/server/agent/agent-timeline-content.d.ts +6 -0
  39. package/dist/server/server/agent/agent-timeline-content.js +62 -0
  40. package/dist/server/server/agent/agent-timeline-store-types.d.ts +54 -0
  41. package/dist/server/server/agent/agent-timeline-store-types.js +2 -0
  42. package/dist/server/server/agent/agent-timeline-store.d.ts +31 -0
  43. package/dist/server/server/agent/agent-timeline-store.js +249 -0
  44. package/dist/server/server/agent/audio-utils.d.ts +3 -0
  45. package/dist/server/server/agent/audio-utils.js +19 -0
  46. package/dist/server/server/agent/create-agent/create.d.ts +102 -0
  47. package/dist/server/server/agent/create-agent/create.js +362 -0
  48. package/dist/server/server/agent/create-agent/intent.d.ts +25 -0
  49. package/dist/server/server/agent/create-agent/intent.js +30 -0
  50. package/dist/server/server/agent/create-agent-lifecycle-dispatch.d.ts +65 -0
  51. package/dist/server/server/agent/create-agent-lifecycle-dispatch.js +166 -0
  52. package/dist/server/server/agent/create-agent-mode.d.ts +13 -0
  53. package/dist/server/server/agent/create-agent-mode.js +65 -0
  54. package/dist/server/server/agent/create-agent-title.d.ts +10 -0
  55. package/dist/server/server/agent/create-agent-title.js +34 -0
  56. package/dist/server/server/agent/dictation-debug.d.ts +13 -0
  57. package/dist/server/server/agent/dictation-debug.js +50 -0
  58. package/dist/server/server/agent/import-sessions.d.ts +57 -0
  59. package/dist/server/server/agent/import-sessions.js +240 -0
  60. package/dist/server/server/agent/lifecycle-command.d.ts +73 -0
  61. package/dist/server/server/agent/lifecycle-command.js +99 -0
  62. package/dist/server/server/agent/mcp-server.d.ts +5 -0
  63. package/dist/server/server/agent/mcp-server.js +31 -0
  64. package/dist/server/server/agent/mcp-shared.d.ts +181 -0
  65. package/dist/server/server/agent/mcp-shared.js +199 -0
  66. package/dist/server/server/agent/mutable-provider-config-owner.d.ts +8 -0
  67. package/dist/server/server/agent/mutable-provider-config-owner.js +35 -0
  68. package/dist/server/server/agent/paseo-tool-policy.d.ts +9 -0
  69. package/dist/server/server/agent/paseo-tool-policy.js +16 -0
  70. package/dist/server/server/agent/pcm16-resampler.d.ts +14 -0
  71. package/dist/server/server/agent/pcm16-resampler.js +63 -0
  72. package/dist/server/server/agent/permission-response.d.ts +15 -0
  73. package/dist/server/server/agent/permission-response.js +14 -0
  74. package/dist/server/server/agent/plugin-provider.d.ts +16 -0
  75. package/dist/server/server/agent/plugin-provider.js +1356 -0
  76. package/dist/server/server/agent/prompt-attachments.d.ts +12 -0
  77. package/dist/server/server/agent/prompt-attachments.js +182 -0
  78. package/dist/server/server/agent/provider-history-timestamps.d.ts +2 -0
  79. package/dist/server/server/agent/provider-history-timestamps.js +16 -0
  80. package/dist/server/server/agent/provider-launch-config.d.ts +43 -0
  81. package/dist/server/server/agent/provider-launch-config.js +167 -0
  82. package/dist/server/server/agent/provider-notices.d.ts +4 -0
  83. package/dist/server/server/agent/provider-notices.js +9 -0
  84. package/dist/server/server/agent/provider-options.d.ts +19 -0
  85. package/dist/server/server/agent/provider-options.js +53 -0
  86. package/dist/server/server/agent/provider-refresh-deadline.d.ts +11 -0
  87. package/dist/server/server/agent/provider-refresh-deadline.js +65 -0
  88. package/dist/server/server/agent/provider-registry.d.ts +72 -0
  89. package/dist/server/server/agent/provider-registry.js +604 -0
  90. package/dist/server/server/agent/provider-runtime.d.ts +16 -0
  91. package/dist/server/server/agent/provider-runtime.js +35 -0
  92. package/dist/server/server/agent/provider-session-import.d.ts +10 -0
  93. package/dist/server/server/agent/provider-session-import.js +55 -0
  94. package/dist/server/server/agent/provider-snapshot-manager.d.ts +166 -0
  95. package/dist/server/server/agent/provider-snapshot-manager.js +843 -0
  96. package/dist/server/server/agent/provider-subagents/store.d.ts +68 -0
  97. package/dist/server/server/agent/provider-subagents/store.js +111 -0
  98. package/dist/server/server/agent/providers/acp-agent.d.ts +703 -0
  99. package/dist/server/server/agent/providers/acp-agent.js +3412 -0
  100. package/dist/server/server/agent/providers/claude/agent.d.ts +74 -0
  101. package/dist/server/server/agent/providers/claude/agent.js +5236 -0
  102. package/dist/server/server/agent/providers/claude/feature-definitions.d.ts +8 -0
  103. package/dist/server/server/agent/providers/claude/feature-definitions.js +24 -0
  104. package/dist/server/server/agent/providers/claude/hooks.d.ts +12 -0
  105. package/dist/server/server/agent/providers/claude/hooks.js +20 -0
  106. package/dist/server/server/agent/providers/claude/model-manifest.d.ts +147 -0
  107. package/dist/server/server/agent/providers/claude/model-manifest.js +342 -0
  108. package/dist/server/server/agent/providers/claude/models.d.ts +28 -0
  109. package/dist/server/server/agent/providers/claude/models.js +141 -0
  110. package/dist/server/server/agent/providers/claude/options.d.ts +85 -0
  111. package/dist/server/server/agent/providers/claude/options.js +93 -0
  112. package/dist/server/server/agent/providers/claude/partial-json.d.ts +5 -0
  113. package/dist/server/server/agent/providers/claude/partial-json.js +306 -0
  114. package/dist/server/server/agent/providers/claude/project-dir.d.ts +6 -0
  115. package/dist/server/server/agent/providers/claude/project-dir.js +57 -0
  116. package/dist/server/server/agent/providers/claude/query.d.ts +17 -0
  117. package/dist/server/server/agent/providers/claude/query.js +86 -0
  118. package/dist/server/server/agent/providers/claude/rewind.d.ts +30 -0
  119. package/dist/server/server/agent/providers/claude/rewind.js +30 -0
  120. package/dist/server/server/agent/providers/claude/side-question.d.ts +16 -0
  121. package/dist/server/server/agent/providers/claude/side-question.js +57 -0
  122. package/dist/server/server/agent/providers/claude/sidechain-tracker.d.ts +35 -0
  123. package/dist/server/server/agent/providers/claude/sidechain-tracker.js +392 -0
  124. package/dist/server/server/agent/providers/claude/subagents/live-source.d.ts +161 -0
  125. package/dist/server/server/agent/providers/claude/subagents/live-source.js +415 -0
  126. package/dist/server/server/agent/providers/claude/subagents/observation.d.ts +53 -0
  127. package/dist/server/server/agent/providers/claude/subagents/observation.js +57 -0
  128. package/dist/server/server/agent/providers/claude/subagents/presentation.d.ts +12 -0
  129. package/dist/server/server/agent/providers/claude/subagents/presentation.js +41 -0
  130. package/dist/server/server/agent/providers/claude/subagents/replay-source.d.ts +70 -0
  131. package/dist/server/server/agent/providers/claude/subagents/replay-source.js +305 -0
  132. package/dist/server/server/agent/providers/claude/subagents/workflow-output.d.ts +4 -0
  133. package/dist/server/server/agent/providers/claude/subagents/workflow-output.js +86 -0
  134. package/dist/server/server/agent/providers/claude/subagents/workflow-replay-source.d.ts +38 -0
  135. package/dist/server/server/agent/providers/claude/subagents/workflow-replay-source.js +225 -0
  136. package/dist/server/server/agent/providers/claude/task-notification-tool-call.d.ts +37 -0
  137. package/dist/server/server/agent/providers/claude/task-notification-tool-call.js +296 -0
  138. package/dist/server/server/agent/providers/claude/task-state.d.ts +18 -0
  139. package/dist/server/server/agent/providers/claude/task-state.js +185 -0
  140. package/dist/server/server/agent/providers/claude/test-rewind-claude-sdk.d.ts +24 -0
  141. package/dist/server/server/agent/providers/claude/test-rewind-claude-sdk.js +23 -0
  142. package/dist/server/server/agent/providers/claude/tool-call-detail-parser.d.ts +3 -0
  143. package/dist/server/server/agent/providers/claude/tool-call-detail-parser.js +130 -0
  144. package/dist/server/server/agent/providers/claude/tool-call-mapper.d.ts +16 -0
  145. package/dist/server/server/agent/providers/claude/tool-call-mapper.js +129 -0
  146. package/dist/server/server/agent/providers/codex/app-server-transport.d.ts +101 -0
  147. package/dist/server/server/agent/providers/codex/app-server-transport.js +290 -0
  148. package/dist/server/server/agent/providers/codex/async-questions.d.ts +18 -0
  149. package/dist/server/server/agent/providers/codex/async-questions.js +135 -0
  150. package/dist/server/server/agent/providers/codex/options.d.ts +59 -0
  151. package/dist/server/server/agent/providers/codex/options.js +82 -0
  152. package/dist/server/server/agent/providers/codex/rewind.d.ts +24 -0
  153. package/dist/server/server/agent/providers/codex/rewind.js +77 -0
  154. package/dist/server/server/agent/providers/codex/tool-call-detail-parser.d.ts +12 -0
  155. package/dist/server/server/agent/providers/codex/tool-call-detail-parser.js +104 -0
  156. package/dist/server/server/agent/providers/codex/tool-call-mapper.d.ts +24 -0
  157. package/dist/server/server/agent/providers/codex/tool-call-mapper.js +909 -0
  158. package/dist/server/server/agent/providers/codex-app-server-agent.d.ts +384 -0
  159. package/dist/server/server/agent/providers/codex-app-server-agent.js +5877 -0
  160. package/dist/server/server/agent/providers/codex-feature-definitions.d.ts +11 -0
  161. package/dist/server/server/agent/providers/codex-feature-definitions.js +55 -0
  162. package/dist/server/server/agent/providers/copilot-acp-agent.d.ts +26 -0
  163. package/dist/server/server/agent/providers/copilot-acp-agent.js +187 -0
  164. package/dist/server/server/agent/providers/cursor-acp-agent.d.ts +17 -0
  165. package/dist/server/server/agent/providers/cursor-acp-agent.js +31 -0
  166. package/dist/server/server/agent/providers/diagnostic-utils.d.ts +36 -0
  167. package/dist/server/server/agent/providers/diagnostic-utils.js +356 -0
  168. package/dist/server/server/agent/providers/generic-acp-agent.d.ts +55 -0
  169. package/dist/server/server/agent/providers/generic-acp-agent.js +178 -0
  170. package/dist/server/server/agent/providers/gjc-acp-agent.d.ts +155 -0
  171. package/dist/server/server/agent/providers/gjc-acp-agent.js +588 -0
  172. package/dist/server/server/agent/providers/jsonl-frame-decoder.d.ts +17 -0
  173. package/dist/server/server/agent/providers/jsonl-frame-decoder.js +149 -0
  174. package/dist/server/server/agent/providers/jsonl-rpc-process.d.ts +63 -0
  175. package/dist/server/server/agent/providers/jsonl-rpc-process.js +207 -0
  176. package/dist/server/server/agent/providers/kimi-acp-agent.d.ts +35 -0
  177. package/dist/server/server/agent/providers/kimi-acp-agent.js +65 -0
  178. package/dist/server/server/agent/providers/kiro-acp-agent.d.ts +17 -0
  179. package/dist/server/server/agent/providers/kiro-acp-agent.js +78 -0
  180. package/dist/server/server/agent/providers/mock-load-test-agent.d.ts +111 -0
  181. package/dist/server/server/agent/providers/mock-load-test-agent.js +1340 -0
  182. package/dist/server/server/agent/providers/mock-slow-provider.d.ts +14 -0
  183. package/dist/server/server/agent/providers/mock-slow-provider.js +40 -0
  184. package/dist/server/server/agent/providers/omp/advisor-message.d.ts +11 -0
  185. package/dist/server/server/agent/providers/omp/advisor-message.js +80 -0
  186. package/dist/server/server/agent/providers/omp/agent.d.ts +178 -0
  187. package/dist/server/server/agent/providers/omp/agent.js +1952 -0
  188. package/dist/server/server/agent/providers/omp/cli-runtime.d.ts +22 -0
  189. package/dist/server/server/agent/providers/omp/cli-runtime.js +208 -0
  190. package/dist/server/server/agent/providers/omp/commands.d.ts +8 -0
  191. package/dist/server/server/agent/providers/omp/commands.js +62 -0
  192. package/dist/server/server/agent/providers/omp/custom-message.d.ts +7 -0
  193. package/dist/server/server/agent/providers/omp/custom-message.js +4 -0
  194. package/dist/server/server/agent/providers/omp/event-mapper.d.ts +13 -0
  195. package/dist/server/server/agent/providers/omp/event-mapper.js +267 -0
  196. package/dist/server/server/agent/providers/omp/history-hooks.d.ts +3 -0
  197. package/dist/server/server/agent/providers/omp/history-hooks.js +13 -0
  198. package/dist/server/server/agent/providers/omp/history.d.ts +19 -0
  199. package/dist/server/server/agent/providers/omp/history.js +306 -0
  200. package/dist/server/server/agent/providers/omp/host-tools.d.ts +14 -0
  201. package/dist/server/server/agent/providers/omp/host-tools.js +196 -0
  202. package/dist/server/server/agent/providers/omp/map-omp-model.d.ts +11 -0
  203. package/dist/server/server/agent/providers/omp/map-omp-model.js +67 -0
  204. package/dist/server/server/agent/providers/omp/message-history.d.ts +38 -0
  205. package/dist/server/server/agent/providers/omp/message-history.js +216 -0
  206. package/dist/server/server/agent/providers/omp/protocol-session.d.ts +13 -0
  207. package/dist/server/server/agent/providers/omp/protocol-session.js +39 -0
  208. package/dist/server/server/agent/providers/omp/provider-config.d.ts +43 -0
  209. package/dist/server/server/agent/providers/omp/provider-config.js +120 -0
  210. package/dist/server/server/agent/providers/omp/rpc-types.d.ts +2040 -0
  211. package/dist/server/server/agent/providers/omp/rpc-types.js +551 -0
  212. package/dist/server/server/agent/providers/omp/rpc-ui-permission-mapper.d.ts +24 -0
  213. package/dist/server/server/agent/providers/omp/rpc-ui-permission-mapper.js +156 -0
  214. package/dist/server/server/agent/providers/omp/runtime.d.ts +85 -0
  215. package/dist/server/server/agent/providers/omp/runtime.js +62 -0
  216. package/dist/server/server/agent/providers/omp/session-descriptor.d.ts +16 -0
  217. package/dist/server/server/agent/providers/omp/session-descriptor.js +389 -0
  218. package/dist/server/server/agent/providers/omp/subagent-card-tracker.d.ts +33 -0
  219. package/dist/server/server/agent/providers/omp/subagent-card-tracker.js +264 -0
  220. package/dist/server/server/agent/providers/omp/subagent-index.d.ts +13 -0
  221. package/dist/server/server/agent/providers/omp/subagent-index.js +111 -0
  222. package/dist/server/server/agent/providers/omp/subagent-title.d.ts +2 -0
  223. package/dist/server/server/agent/providers/omp/subagent-title.js +14 -0
  224. package/dist/server/server/agent/providers/omp/system-notice.d.ts +8 -0
  225. package/dist/server/server/agent/providers/omp/system-notice.js +68 -0
  226. package/dist/server/server/agent/providers/omp/todo-mapper.d.ts +9 -0
  227. package/dist/server/server/agent/providers/omp/todo-mapper.js +52 -0
  228. package/dist/server/server/agent/providers/omp/tool-call-detail.d.ts +110 -0
  229. package/dist/server/server/agent/providers/omp/tool-call-detail.js +288 -0
  230. package/dist/server/server/agent/providers/omp/tool-call-id.d.ts +4 -0
  231. package/dist/server/server/agent/providers/omp/tool-call-id.js +34 -0
  232. package/dist/server/server/agent/providers/omp/tool-call-mapper.d.ts +7 -0
  233. package/dist/server/server/agent/providers/omp/tool-call-mapper.js +98 -0
  234. package/dist/server/server/agent/providers/omp/usage-poller.d.ts +32 -0
  235. package/dist/server/server/agent/providers/omp/usage-poller.js +141 -0
  236. package/dist/server/server/agent/providers/opencode/bridge-plugin.bundle.mjs +14678 -0
  237. package/dist/server/server/agent/providers/opencode/bridge.d.ts +39 -0
  238. package/dist/server/server/agent/providers/opencode/bridge.js +249 -0
  239. package/dist/server/server/agent/providers/opencode/event-consumer.d.ts +60 -0
  240. package/dist/server/server/agent/providers/opencode/event-consumer.js +221 -0
  241. package/dist/server/server/agent/providers/opencode/options.d.ts +156 -0
  242. package/dist/server/server/agent/providers/opencode/options.js +62 -0
  243. package/dist/server/server/agent/providers/opencode/paths.d.ts +2 -0
  244. package/dist/server/server/agent/providers/opencode/paths.js +7 -0
  245. package/dist/server/server/agent/providers/opencode/rewind.d.ts +18 -0
  246. package/dist/server/server/agent/providers/opencode/rewind.js +14 -0
  247. package/dist/server/server/agent/providers/opencode/server-manager.d.ts +101 -0
  248. package/dist/server/server/agent/providers/opencode/server-manager.js +513 -0
  249. package/dist/server/server/agent/providers/opencode/side-question.d.ts +78 -0
  250. package/dist/server/server/agent/providers/opencode/side-question.js +172 -0
  251. package/dist/server/server/agent/providers/opencode/subagent-presentation.d.ts +36 -0
  252. package/dist/server/server/agent/providers/opencode/subagent-presentation.js +62 -0
  253. package/dist/server/server/agent/providers/opencode/test-server-manager.d.ts +22 -0
  254. package/dist/server/server/agent/providers/opencode/test-server-manager.js +43 -0
  255. package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.d.ts +3 -0
  256. package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.js +256 -0
  257. package/dist/server/server/agent/providers/opencode/tool-call-mapper.d.ts +13 -0
  258. package/dist/server/server/agent/providers/opencode/tool-call-mapper.js +53 -0
  259. package/dist/server/server/agent/providers/opencode-agent.d.ts +393 -0
  260. package/dist/server/server/agent/providers/opencode-agent.js +4106 -0
  261. package/dist/server/server/agent/providers/pi/agent.d.ts +164 -0
  262. package/dist/server/server/agent/providers/pi/agent.js +2236 -0
  263. package/dist/server/server/agent/providers/pi/cli-runtime.d.ts +21 -0
  264. package/dist/server/server/agent/providers/pi/cli-runtime.js +177 -0
  265. package/dist/server/server/agent/providers/pi/history-mapper.d.ts +36 -0
  266. package/dist/server/server/agent/providers/pi/history-mapper.js +212 -0
  267. package/dist/server/server/agent/providers/pi/rewind.d.ts +8 -0
  268. package/dist/server/server/agent/providers/pi/rewind.js +8 -0
  269. package/dist/server/server/agent/providers/pi/rpc-types.d.ts +252 -0
  270. package/dist/server/server/agent/providers/pi/rpc-types.js +2 -0
  271. package/dist/server/server/agent/providers/pi/runtime.d.ts +77 -0
  272. package/dist/server/server/agent/providers/pi/runtime.js +65 -0
  273. package/dist/server/server/agent/providers/pi/session-descriptor.d.ts +16 -0
  274. package/dist/server/server/agent/providers/pi/session-descriptor.js +355 -0
  275. package/dist/server/server/agent/providers/pi/tool-call-mapper.d.ts +113 -0
  276. package/dist/server/server/agent/providers/pi/tool-call-mapper.js +340 -0
  277. package/dist/server/server/agent/providers/pi/usage-poller.d.ts +32 -0
  278. package/dist/server/server/agent/providers/pi/usage-poller.js +141 -0
  279. package/dist/server/server/agent/providers/provider-image-output.d.ts +25 -0
  280. package/dist/server/server/agent/providers/provider-image-output.js +165 -0
  281. package/dist/server/server/agent/providers/provider-runner.d.ts +27 -0
  282. package/dist/server/server/agent/providers/provider-runner.js +81 -0
  283. package/dist/server/server/agent/providers/tool-call-detail-primitives.d.ts +884 -0
  284. package/dist/server/server/agent/providers/tool-call-detail-primitives.js +778 -0
  285. package/dist/server/server/agent/providers/tool-call-mapper-utils.d.ts +25 -0
  286. package/dist/server/server/agent/providers/tool-call-mapper-utils.js +208 -0
  287. package/dist/server/server/agent/providers/trae-acp-agent.d.ts +15 -0
  288. package/dist/server/server/agent/providers/trae-acp-agent.js +18 -0
  289. package/dist/server/server/agent/recordings-debug.d.ts +3 -0
  290. package/dist/server/server/agent/recordings-debug.js +19 -0
  291. package/dist/server/server/agent/rewind/rewind.d.ts +10 -0
  292. package/dist/server/server/agent/rewind/rewind.js +29 -0
  293. package/dist/server/server/agent/rewind/test-rewind-session.d.ts +48 -0
  294. package/dist/server/server/agent/rewind/test-rewind-session.js +88 -0
  295. package/dist/server/server/agent/runtime-mcp-config.d.ts +14 -0
  296. package/dist/server/server/agent/runtime-mcp-config.js +53 -0
  297. package/dist/server/server/agent/side-conversations/store.d.ts +33 -0
  298. package/dist/server/server/agent/side-conversations/store.js +62 -0
  299. package/dist/server/server/agent/stale-provider-session-error.d.ts +6 -0
  300. package/dist/server/server/agent/stale-provider-session-error.js +11 -0
  301. package/dist/server/server/agent/structured-generation-providers.d.ts +29 -0
  302. package/dist/server/server/agent/structured-generation-providers.js +193 -0
  303. package/dist/server/server/agent/stt-debug.d.ts +10 -0
  304. package/dist/server/server/agent/stt-debug.js +33 -0
  305. package/dist/server/server/agent/stt-manager.d.ts +38 -0
  306. package/dist/server/server/agent/stt-manager.js +246 -0
  307. package/dist/server/server/agent/system-prompt.d.ts +2 -0
  308. package/dist/server/server/agent/system-prompt.js +8 -0
  309. package/dist/server/server/agent/timeline-append.d.ts +10 -0
  310. package/dist/server/server/agent/timeline-append.js +27 -0
  311. package/dist/server/server/agent/timeline-page-bounds.d.ts +19 -0
  312. package/dist/server/server/agent/timeline-page-bounds.js +37 -0
  313. package/dist/server/server/agent/timeline-projection.d.ts +74 -0
  314. package/dist/server/server/agent/timeline-projection.js +467 -0
  315. package/dist/server/server/agent/timeline-prompt-index.d.ts +12 -0
  316. package/dist/server/server/agent/timeline-prompt-index.js +23 -0
  317. package/dist/server/server/agent/tools/paseo-tool-serialization.d.ts +4 -0
  318. package/dist/server/server/agent/tools/paseo-tool-serialization.js +58 -0
  319. package/dist/server/server/agent/tools/paseo-tools.d.ts +62 -0
  320. package/dist/server/server/agent/tools/paseo-tools.js +2445 -0
  321. package/dist/server/server/agent/tools/types.d.ts +39 -0
  322. package/dist/server/server/agent/tools/types.js +2 -0
  323. package/dist/server/server/agent/tts-debug.d.ts +8 -0
  324. package/dist/server/server/agent/tts-debug.js +24 -0
  325. package/dist/server/server/agent/tts-manager.d.ts +41 -0
  326. package/dist/server/server/agent/tts-manager.js +375 -0
  327. package/dist/server/server/agent-attention-policy.d.ts +29 -0
  328. package/dist/server/server/agent-attention-policy.js +36 -0
  329. package/dist/server/server/agent-history-search.d.ts +48 -0
  330. package/dist/server/server/agent-history-search.js +129 -0
  331. package/dist/server/server/atomic-file.d.ts +3 -0
  332. package/dist/server/server/atomic-file.js +19 -0
  333. package/dist/server/server/auth.d.ts +38 -0
  334. package/dist/server/server/auth.js +122 -0
  335. package/dist/server/server/authorization/index.d.ts +18 -0
  336. package/dist/server/server/authorization/index.js +47 -0
  337. package/dist/server/server/authorization/operation-permissions.d.ts +8 -0
  338. package/dist/server/server/authorization/operation-permissions.js +438 -0
  339. package/dist/server/server/auto-archive-on-merge/archive-if-safe.d.ts +40 -0
  340. package/dist/server/server/auto-archive-on-merge/archive-if-safe.js +64 -0
  341. package/dist/server/server/auto-archive-on-merge/index.d.ts +13 -0
  342. package/dist/server/server/auto-archive-on-merge/index.js +77 -0
  343. package/dist/server/server/bootstrap.d.ts +166 -0
  344. package/dist/server/server/bootstrap.js +1388 -0
  345. package/dist/server/server/browser-tools/broker.d.ts +45 -0
  346. package/dist/server/server/browser-tools/broker.js +390 -0
  347. package/dist/server/server/browser-tools/errors.d.ts +22 -0
  348. package/dist/server/server/browser-tools/errors.js +27 -0
  349. package/dist/server/server/browser-tools/policy.d.ts +10 -0
  350. package/dist/server/server/browser-tools/policy.js +16 -0
  351. package/dist/server/server/browser-tools/tools.d.ts +16 -0
  352. package/dist/server/server/browser-tools/tools.js +796 -0
  353. package/dist/server/server/checkout/status-projection.d.ts +19 -0
  354. package/dist/server/server/checkout/status-projection.js +127 -0
  355. package/dist/server/server/checkout-diff-manager.d.ts +48 -0
  356. package/dist/server/server/checkout-diff-manager.js +284 -0
  357. package/dist/server/server/checkout-git-utils.d.ts +11 -0
  358. package/dist/server/server/checkout-git-utils.js +34 -0
  359. package/dist/server/server/client-message-id.d.ts +3 -0
  360. package/dist/server/server/client-message-id.js +12 -0
  361. package/dist/server/server/config.d.ts +26 -0
  362. package/dist/server/server/config.js +594 -0
  363. package/dist/server/server/connection-offer.d.ts +20 -0
  364. package/dist/server/server/connection-offer.js +59 -0
  365. package/dist/server/server/creation/index.d.ts +41 -0
  366. package/dist/server/server/creation/index.js +250 -0
  367. package/dist/server/server/daemon-config-store.d.ts +63 -0
  368. package/dist/server/server/daemon-config-store.js +524 -0
  369. package/dist/server/server/daemon-keypair.d.ts +8 -0
  370. package/dist/server/server/daemon-keypair.js +42 -0
  371. package/dist/server/server/daemon-version.d.ts +5 -0
  372. package/dist/server/server/daemon-version.js +22 -0
  373. package/dist/server/server/daemon-worker.d.ts +2 -0
  374. package/dist/server/server/daemon-worker.js +287 -0
  375. package/dist/server/server/dictation/dictation-stream-manager.d.ts +88 -0
  376. package/dist/server/server/dictation/dictation-stream-manager.js +578 -0
  377. package/dist/server/server/directory-sync/index.d.ts +45 -0
  378. package/dist/server/server/directory-sync/index.js +98 -0
  379. package/dist/server/server/directory-sync/internal/versioned-collection.d.ts +56 -0
  380. package/dist/server/server/directory-sync/internal/versioned-collection.js +94 -0
  381. package/dist/server/server/exports.d.ts +24 -0
  382. package/dist/server/server/exports.js +24 -0
  383. package/dist/server/server/file-download/token-store.d.ts +24 -0
  384. package/dist/server/server/file-download/token-store.js +40 -0
  385. package/dist/server/server/file-explorer/observer.d.ts +32 -0
  386. package/dist/server/server/file-explorer/observer.js +130 -0
  387. package/dist/server/server/file-explorer/service.d.ts +125 -0
  388. package/dist/server/server/file-explorer/service.js +663 -0
  389. package/dist/server/server/file-observer/index.d.ts +43 -0
  390. package/dist/server/server/file-observer/index.js +114 -0
  391. package/dist/server/server/file-observer/internal/contracts.d.ts +26 -0
  392. package/dist/server/server/file-observer/internal/contracts.js +2 -0
  393. package/dist/server/server/file-observer/internal/linux.d.ts +4 -0
  394. package/dist/server/server/file-observer/internal/linux.js +260 -0
  395. package/dist/server/server/file-observer/internal/native-recursive.d.ts +9 -0
  396. package/dist/server/server/file-observer/internal/native-recursive.js +577 -0
  397. package/dist/server/server/file-observer/internal/observation.d.ts +21 -0
  398. package/dist/server/server/file-observer/internal/observation.js +129 -0
  399. package/dist/server/server/file-observer/internal/paths.d.ts +10 -0
  400. package/dist/server/server/file-observer/internal/paths.js +43 -0
  401. package/dist/server/server/file-upload/index.d.ts +27 -0
  402. package/dist/server/server/file-upload/index.js +158 -0
  403. package/dist/server/server/git-metadata-event-rules.d.ts +123 -0
  404. package/dist/server/server/git-metadata-event-rules.js +152 -0
  405. package/dist/server/server/hostnames.d.ts +13 -0
  406. package/dist/server/server/hostnames.js +94 -0
  407. package/dist/server/server/hub/daemon-executions.d.ts +89 -0
  408. package/dist/server/server/hub/daemon-executions.js +287 -0
  409. package/dist/server/server/hub/execution-controller.d.ts +30 -0
  410. package/dist/server/server/hub/execution-controller.js +220 -0
  411. package/dist/server/server/hub/relationship-controller.d.ts +116 -0
  412. package/dist/server/server/hub/relationship-controller.js +534 -0
  413. package/dist/server/server/hub/relationship-remote.d.ts +68 -0
  414. package/dist/server/server/hub/relationship-remote.js +159 -0
  415. package/dist/server/server/hub/relationship-retry.d.ts +7 -0
  416. package/dist/server/server/hub/relationship-retry.js +15 -0
  417. package/dist/server/server/json-utils.d.ts +11 -0
  418. package/dist/server/server/json-utils.js +45 -0
  419. package/dist/server/server/lifecycle-reasons.d.ts +4 -0
  420. package/dist/server/server/lifecycle-reasons.js +6 -0
  421. package/dist/server/server/logger.d.ts +29 -0
  422. package/dist/server/server/logger.js +127 -0
  423. package/dist/server/server/managed-processes/managed-processes.d.ts +76 -0
  424. package/dist/server/server/managed-processes/managed-processes.js +326 -0
  425. package/dist/server/server/messages.d.ts +9 -0
  426. package/dist/server/server/messages.js +29 -0
  427. package/dist/server/server/migrations/backfill-workspace-id.migration.d.ts +9 -0
  428. package/dist/server/server/migrations/backfill-workspace-id.migration.js +64 -0
  429. package/dist/server/server/orchestration-skills/index.d.ts +18 -0
  430. package/dist/server/server/orchestration-skills/index.js +18 -0
  431. package/dist/server/server/orchestration-skills/internal/controller.d.ts +39 -0
  432. package/dist/server/server/orchestration-skills/internal/controller.js +108 -0
  433. package/dist/server/server/orchestration-skills/internal/operations.d.ts +43 -0
  434. package/dist/server/server/orchestration-skills/internal/operations.js +178 -0
  435. package/dist/server/server/orchestration-skills/internal/paths.d.ts +4 -0
  436. package/dist/server/server/orchestration-skills/internal/paths.js +21 -0
  437. package/dist/server/server/orchestration-skills/internal/selection-store.d.ts +12 -0
  438. package/dist/server/server/orchestration-skills/internal/selection-store.js +39 -0
  439. package/dist/server/server/orchestration-skills/internal/sync.d.ts +21 -0
  440. package/dist/server/server/orchestration-skills/internal/sync.js +177 -0
  441. package/dist/server/server/orchestration-skills/internal/transaction.d.ts +22 -0
  442. package/dist/server/server/orchestration-skills/internal/transaction.js +483 -0
  443. package/dist/server/server/package-version.d.ts +19 -0
  444. package/dist/server/server/package-version.js +60 -0
  445. package/dist/server/server/pagination/cursor.d.ts +16 -0
  446. package/dist/server/server/pagination/cursor.js +62 -0
  447. package/dist/server/server/pagination/sortable-pager.d.ts +24 -0
  448. package/dist/server/server/pagination/sortable-pager.js +68 -0
  449. package/dist/server/server/pairing-offer.d.ts +18 -0
  450. package/dist/server/server/pairing-offer.js +47 -0
  451. package/dist/server/server/pairing-qr.d.ts +2 -0
  452. package/dist/server/server/pairing-qr.js +15 -0
  453. package/dist/server/server/paseo-env.d.ts +13 -0
  454. package/dist/server/server/paseo-env.js +54 -0
  455. package/dist/server/server/paseo-home.d.ts +2 -0
  456. package/dist/server/server/paseo-home.js +19 -0
  457. package/dist/server/server/paseo-worktree-service.d.ts +45 -0
  458. package/dist/server/server/paseo-worktree-service.js +191 -0
  459. package/dist/server/server/path-utils.d.ts +5 -0
  460. package/dist/server/server/path-utils.js +34 -0
  461. package/dist/server/server/persisted-config.d.ts +397 -0
  462. package/dist/server/server/persisted-config.js +411 -0
  463. package/dist/server/server/persistence-hooks.d.ts +32 -0
  464. package/dist/server/server/persistence-hooks.js +96 -0
  465. package/dist/server/server/pid-lock.d.ts +44 -0
  466. package/dist/server/server/pid-lock.js +285 -0
  467. package/dist/server/server/plugins/compiler-imports.d.ts +13 -0
  468. package/dist/server/server/plugins/compiler-imports.js +90 -0
  469. package/dist/server/server/plugins/compiler.d.ts +10 -0
  470. package/dist/server/server/plugins/compiler.js +354 -0
  471. package/dist/server/server/plugins/daemon-transport.d.ts +9 -0
  472. package/dist/server/server/plugins/daemon-transport.js +68 -0
  473. package/dist/server/server/plugins/index.d.ts +102 -0
  474. package/dist/server/server/plugins/index.js +575 -0
  475. package/dist/server/server/plugins/lifecycle/index.d.ts +40 -0
  476. package/dist/server/server/plugins/lifecycle/index.js +200 -0
  477. package/dist/server/server/plugins/managed-source.d.ts +50 -0
  478. package/dist/server/server/plugins/managed-source.js +327 -0
  479. package/dist/server/server/plugins/manifest.d.ts +12 -0
  480. package/dist/server/server/plugins/manifest.js +26 -0
  481. package/dist/server/server/plugins/plugin-process-protocol.d.ts +120 -0
  482. package/dist/server/server/plugins/plugin-process-protocol.js +154 -0
  483. package/dist/server/server/plugins/plugin-process.d.ts +2 -0
  484. package/dist/server/server/plugins/plugin-process.js +419 -0
  485. package/dist/server/server/plugins/plugin-sdk-specifiers.d.ts +5 -0
  486. package/dist/server/server/plugins/plugin-sdk-specifiers.js +23 -0
  487. package/dist/server/server/plugins/plugin-session-identity.d.ts +4 -0
  488. package/dist/server/server/plugins/plugin-session-identity.js +11 -0
  489. package/dist/server/server/plugins/preparation.d.ts +4 -0
  490. package/dist/server/server/plugins/preparation.js +49 -0
  491. package/dist/server/server/plugins/provider-icon.d.ts +2 -0
  492. package/dist/server/server/plugins/provider-icon.js +55 -0
  493. package/dist/server/server/plugins/runtime.d.ts +83 -0
  494. package/dist/server/server/plugins/runtime.js +836 -0
  495. package/dist/server/server/plugins/session-socket.d.ts +23 -0
  496. package/dist/server/server/plugins/session-socket.js +82 -0
  497. package/dist/server/server/plugins/settings/index.d.ts +96 -0
  498. package/dist/server/server/plugins/settings/index.js +115 -0
  499. package/dist/server/server/private-files.d.ts +6 -0
  500. package/dist/server/server/private-files.js +37 -0
  501. package/dist/server/server/process-diagnostics.d.ts +17 -0
  502. package/dist/server/server/process-diagnostics.js +22 -0
  503. package/dist/server/server/project-directory-service.d.ts +30 -0
  504. package/dist/server/server/project-directory-service.js +120 -0
  505. package/dist/server/server/project-key.d.ts +14 -0
  506. package/dist/server/server/project-key.js +44 -0
  507. package/dist/server/server/push/index.d.ts +16 -0
  508. package/dist/server/server/push/index.js +26 -0
  509. package/dist/server/server/push/push-service.d.ts +19 -0
  510. package/dist/server/server/push/push-service.js +66 -0
  511. package/dist/server/server/push/token-store.d.ts +22 -0
  512. package/dist/server/server/push/token-store.js +125 -0
  513. package/dist/server/server/relay-runtime.d.ts +27 -0
  514. package/dist/server/server/relay-runtime.js +46 -0
  515. package/dist/server/server/relay-transport.d.ts +33 -0
  516. package/dist/server/server/relay-transport.js +481 -0
  517. package/dist/server/server/request-receipts/index.d.ts +33 -0
  518. package/dist/server/server/request-receipts/index.js +131 -0
  519. package/dist/server/server/resolve-workspace-id-for-path.d.ts +3 -0
  520. package/dist/server/server/resolve-workspace-id-for-path.js +41 -0
  521. package/dist/server/server/resolve-worktree-creation-intent.d.ts +44 -0
  522. package/dist/server/server/resolve-worktree-creation-intent.js +186 -0
  523. package/dist/server/server/schedule/cron.d.ts +4 -0
  524. package/dist/server/server/schedule/cron.js +83 -0
  525. package/dist/server/server/schedule/service.d.ts +75 -0
  526. package/dist/server/server/schedule/service.js +810 -0
  527. package/dist/server/server/schedule/store.d.ts +27 -0
  528. package/dist/server/server/schedule/store.js +190 -0
  529. package/dist/server/server/script-health-monitor.d.ts +39 -0
  530. package/dist/server/server/script-health-monitor.js +159 -0
  531. package/dist/server/server/script-proxy.d.ts +3 -0
  532. package/dist/server/server/script-proxy.js +2 -0
  533. package/dist/server/server/script-route-branch-handler.d.ts +10 -0
  534. package/dist/server/server/script-route-branch-handler.js +11 -0
  535. package/dist/server/server/script-status-projection.d.ts +36 -0
  536. package/dist/server/server/script-status-projection.js +200 -0
  537. package/dist/server/server/server-id.d.ts +17 -0
  538. package/dist/server/server/server-id.js +68 -0
  539. package/dist/server/server/service-proxy.d.ts +237 -0
  540. package/dist/server/server/service-proxy.js +679 -0
  541. package/dist/server/server/session/agent-config/agent-config-session.d.ts +75 -0
  542. package/dist/server/server/session/agent-config/agent-config-session.js +151 -0
  543. package/dist/server/server/session/agent-updates/agent-updates-service.d.ts +65 -0
  544. package/dist/server/server/session/agent-updates/agent-updates-service.js +266 -0
  545. package/dist/server/server/session/checkout/checkout-session.d.ts +150 -0
  546. package/dist/server/server/session/checkout/checkout-session.js +1187 -0
  547. package/dist/server/server/session/checkout/git-metadata-generator.d.ts +53 -0
  548. package/dist/server/server/session/checkout/git-metadata-generator.js +159 -0
  549. package/dist/server/server/session/daemon/daemon-self-update-session-controller.d.ts +34 -0
  550. package/dist/server/server/session/daemon/daemon-self-update-session-controller.js +90 -0
  551. package/dist/server/server/session/daemon/daemon-self-updater.d.ts +33 -0
  552. package/dist/server/server/session/daemon/daemon-self-updater.js +60 -0
  553. package/dist/server/server/session/daemon/daemon-session.d.ts +90 -0
  554. package/dist/server/server/session/daemon/daemon-session.js +224 -0
  555. package/dist/server/server/session/daemon/diagnostics.d.ts +41 -0
  556. package/dist/server/server/session/daemon/diagnostics.js +431 -0
  557. package/dist/server/server/session/daemon/install-origin.d.ts +7 -0
  558. package/dist/server/server/session/daemon/install-origin.js +64 -0
  559. package/dist/server/server/session/daemon/npm-global-cli.d.ts +29 -0
  560. package/dist/server/server/session/daemon/npm-global-cli.js +98 -0
  561. package/dist/server/server/session/files/workspace-files-session.d.ts +55 -0
  562. package/dist/server/server/session/files/workspace-files-session.js +359 -0
  563. package/dist/server/server/session/git-mutation/git-mutation-service.d.ts +32 -0
  564. package/dist/server/server/session/git-mutation/git-mutation-service.js +74 -0
  565. package/dist/server/server/session/project-config/project-config-session.d.ts +35 -0
  566. package/dist/server/server/session/project-config/project-config-session.js +143 -0
  567. package/dist/server/server/session/project-config/worktree-setup-commit-status.d.ts +6 -0
  568. package/dist/server/server/session/project-config/worktree-setup-commit-status.js +38 -0
  569. package/dist/server/server/session/provider/provider-catalog-session.d.ts +78 -0
  570. package/dist/server/server/session/provider/provider-catalog-session.js +388 -0
  571. package/dist/server/server/session/schedule/schedule-session.d.ts +47 -0
  572. package/dist/server/server/session/schedule/schedule-session.js +188 -0
  573. package/dist/server/server/session/voice/voice-session.d.ts +166 -0
  574. package/dist/server/server/session/voice/voice-session.js +904 -0
  575. package/dist/server/server/session/voice/voice-turn-controller.d.ts +38 -0
  576. package/dist/server/server/session/voice/voice-turn-controller.js +393 -0
  577. package/dist/server/server/session/workspace-git-observer/workspace-git-observer-service.d.ts +42 -0
  578. package/dist/server/server/session/workspace-git-observer/workspace-git-observer-service.js +170 -0
  579. package/dist/server/server/session/workspace-provisioning/workspace-provisioning-service.d.ts +59 -0
  580. package/dist/server/server/session/workspace-provisioning/workspace-provisioning-service.js +326 -0
  581. package/dist/server/server/session/workspace-recovery/workspace-recovery-service.d.ts +30 -0
  582. package/dist/server/server/session/workspace-recovery/workspace-recovery-service.js +178 -0
  583. package/dist/server/server/session/workspace-scripts/workspace-scripts-service.d.ts +54 -0
  584. package/dist/server/server/session/workspace-scripts/workspace-scripts-service.js +156 -0
  585. package/dist/server/server/session.d.ts +555 -0
  586. package/dist/server/server/session.js +6540 -0
  587. package/dist/server/server/speech/audio.d.ts +10 -0
  588. package/dist/server/server/speech/audio.js +101 -0
  589. package/dist/server/server/speech/provider-resolver.d.ts +3 -0
  590. package/dist/server/server/speech/provider-resolver.js +7 -0
  591. package/dist/server/server/speech/providers/local/config.d.ts +30 -0
  592. package/dist/server/server/speech/providers/local/config.js +134 -0
  593. package/dist/server/server/speech/providers/local/models.d.ts +12 -0
  594. package/dist/server/server/speech/providers/local/models.js +18 -0
  595. package/dist/server/server/speech/providers/local/runtime.d.ts +31 -0
  596. package/dist/server/server/speech/providers/local/runtime.js +135 -0
  597. package/dist/server/server/speech/providers/local/sherpa/assets/silero_vad.onnx +0 -0
  598. package/dist/server/server/speech/providers/local/sherpa/model-catalog.d.ts +56 -0
  599. package/dist/server/server/speech/providers/local/sherpa/model-catalog.js +74 -0
  600. package/dist/server/server/speech/providers/local/sherpa/model-downloader.d.ts +17 -0
  601. package/dist/server/server/speech/providers/local/sherpa/model-downloader.js +145 -0
  602. package/dist/server/server/speech/providers/local/sherpa/sherpa-offline-recognizer.d.ts +49 -0
  603. package/dist/server/server/speech/providers/local/sherpa/sherpa-offline-recognizer.js +73 -0
  604. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.d.ts +9 -0
  605. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.js +107 -0
  606. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.d.ts +28 -0
  607. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.js +137 -0
  608. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-stt.d.ts +21 -0
  609. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-stt.js +133 -0
  610. package/dist/server/server/speech/providers/local/sherpa/sherpa-runtime-env.d.ts +18 -0
  611. package/dist/server/server/speech/providers/local/sherpa/sherpa-runtime-env.js +84 -0
  612. package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.d.ts +21 -0
  613. package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.js +101 -0
  614. package/dist/server/server/speech/providers/local/sherpa/silero-vad-provider.d.ts +19 -0
  615. package/dist/server/server/speech/providers/local/sherpa/silero-vad-provider.js +49 -0
  616. package/dist/server/server/speech/providers/local/sherpa/silero-vad-session.d.ts +38 -0
  617. package/dist/server/server/speech/providers/local/sherpa/silero-vad-session.js +176 -0
  618. package/dist/server/server/speech/providers/local/worker-bytes.d.ts +4 -0
  619. package/dist/server/server/speech/providers/local/worker-bytes.js +9 -0
  620. package/dist/server/server/speech/providers/local/worker-client.d.ts +93 -0
  621. package/dist/server/server/speech/providers/local/worker-client.js +590 -0
  622. package/dist/server/server/speech/providers/local/worker-process.d.ts +2 -0
  623. package/dist/server/server/speech/providers/local/worker-process.js +270 -0
  624. package/dist/server/server/speech/providers/local/worker-protocol.d.ts +95 -0
  625. package/dist/server/server/speech/providers/local/worker-protocol.js +2 -0
  626. package/dist/server/server/speech/providers/openai/config.d.ts +19 -0
  627. package/dist/server/server/speech/providers/openai/config.js +148 -0
  628. package/dist/server/server/speech/providers/openai/runtime.d.ts +29 -0
  629. package/dist/server/server/speech/providers/openai/runtime.js +102 -0
  630. package/dist/server/server/speech/providers/openai/stt.d.ts +23 -0
  631. package/dist/server/server/speech/providers/openai/stt.js +209 -0
  632. package/dist/server/server/speech/providers/openai/tts.d.ts +19 -0
  633. package/dist/server/server/speech/providers/openai/tts.js +48 -0
  634. package/dist/server/server/speech/speech-config-resolver.d.ts +11 -0
  635. package/dist/server/server/speech/speech-config-resolver.js +132 -0
  636. package/dist/server/server/speech/speech-provider.d.ts +59 -0
  637. package/dist/server/server/speech/speech-provider.js +2 -0
  638. package/dist/server/server/speech/speech-runtime.d.ts +45 -0
  639. package/dist/server/server/speech/speech-runtime.js +571 -0
  640. package/dist/server/server/speech/speech-types.d.ts +22 -0
  641. package/dist/server/server/speech/speech-types.js +8 -0
  642. package/dist/server/server/speech/turn-detection-provider.d.ts +23 -0
  643. package/dist/server/server/speech/turn-detection-provider.js +2 -0
  644. package/dist/server/server/utils/diff-highlighter.d.ts +57 -0
  645. package/dist/server/server/utils/diff-highlighter.js +304 -0
  646. package/dist/server/server/voice-config.d.ts +15 -0
  647. package/dist/server/server/voice-config.js +54 -0
  648. package/dist/server/server/voice-permission-policy.d.ts +4 -0
  649. package/dist/server/server/voice-permission-policy.js +13 -0
  650. package/dist/server/server/voice-types.d.ts +12 -0
  651. package/dist/server/server/voice-types.js +2 -0
  652. package/dist/server/server/watcher-liveness-canary.d.ts +11 -0
  653. package/dist/server/server/watcher-liveness-canary.js +53 -0
  654. package/dist/server/server/web-ui.d.ts +10 -0
  655. package/dist/server/server/web-ui.js +205 -0
  656. package/dist/server/server/websocket/encrypted-relay-socket.d.ts +23 -0
  657. package/dist/server/server/websocket/encrypted-relay-socket.js +64 -0
  658. package/dist/server/server/websocket/physical-socket.d.ts +36 -0
  659. package/dist/server/server/websocket/physical-socket.js +95 -0
  660. package/dist/server/server/websocket/runtime-metrics.d.ts +95 -0
  661. package/dist/server/server/websocket/runtime-metrics.js +148 -0
  662. package/dist/server/server/websocket-server.d.ts +214 -0
  663. package/dist/server/server/websocket-server.js +2258 -0
  664. package/dist/server/server/workspace-archive-service.d.ts +63 -0
  665. package/dist/server/server/workspace-archive-service.js +355 -0
  666. package/dist/server/server/workspace-auto-name.d.ts +55 -0
  667. package/dist/server/server/workspace-auto-name.js +127 -0
  668. package/dist/server/server/workspace-automation-gate.d.ts +16 -0
  669. package/dist/server/server/workspace-automation-gate.js +35 -0
  670. package/dist/server/server/workspace-bootstrap-dedupe.d.ts +34 -0
  671. package/dist/server/server/workspace-bootstrap-dedupe.js +23 -0
  672. package/dist/server/server/workspace-directory.d.ts +99 -0
  673. package/dist/server/server/workspace-directory.js +467 -0
  674. package/dist/server/server/workspace-git-fetch.d.ts +33 -0
  675. package/dist/server/server/workspace-git-fetch.js +108 -0
  676. package/dist/server/server/workspace-git-metadata.d.ts +8 -0
  677. package/dist/server/server/workspace-git-metadata.js +24 -0
  678. package/dist/server/server/workspace-git-service.d.ts +348 -0
  679. package/dist/server/server/workspace-git-service.js +2534 -0
  680. package/dist/server/server/workspace-labels/index.d.ts +14 -0
  681. package/dist/server/server/workspace-labels/index.js +10 -0
  682. package/dist/server/server/workspace-labels/internal/catalog-store.d.ts +50 -0
  683. package/dist/server/server/workspace-labels/internal/catalog-store.js +203 -0
  684. package/dist/server/server/workspace-labels/internal/sequence.d.ts +43 -0
  685. package/dist/server/server/workspace-labels/internal/sequence.js +80 -0
  686. package/dist/server/server/workspace-labels/internal/service.d.ts +57 -0
  687. package/dist/server/server/workspace-labels/internal/service.js +224 -0
  688. package/dist/server/server/workspace-reconciliation-service.d.ts +103 -0
  689. package/dist/server/server/workspace-reconciliation-service.js +379 -0
  690. package/dist/server/server/workspace-registry-bootstrap-legacy.d.ts +21 -0
  691. package/dist/server/server/workspace-registry-bootstrap-legacy.js +57 -0
  692. package/dist/server/server/workspace-registry-bootstrap.d.ts +14 -0
  693. package/dist/server/server/workspace-registry-bootstrap.js +155 -0
  694. package/dist/server/server/workspace-registry-model.d.ts +56 -0
  695. package/dist/server/server/workspace-registry-model.js +150 -0
  696. package/dist/server/server/workspace-registry.d.ts +228 -0
  697. package/dist/server/server/workspace-registry.js +468 -0
  698. package/dist/server/server/workspace-script-runtime-store.d.ts +28 -0
  699. package/dist/server/server/workspace-script-runtime-store.js +78 -0
  700. package/dist/server/server/workspace-service-env.d.ts +18 -0
  701. package/dist/server/server/workspace-service-env.js +85 -0
  702. package/dist/server/server/workspace-service-port-allocator.d.ts +11 -0
  703. package/dist/server/server/workspace-service-port-allocator.js +89 -0
  704. package/dist/server/server/workspace-service-port-registry.d.ts +24 -0
  705. package/dist/server/server/workspace-service-port-registry.js +172 -0
  706. package/dist/server/server/workspace-setup-runtime.d.ts +7 -0
  707. package/dist/server/server/workspace-setup-runtime.js +30 -0
  708. package/dist/server/server/workspace-source.d.ts +7 -0
  709. package/dist/server/server/workspace-source.js +15 -0
  710. package/dist/server/server/worktree/commands.d.ts +55 -0
  711. package/dist/server/server/worktree/commands.js +99 -0
  712. package/dist/server/server/worktree-bootstrap.d.ts +86 -0
  713. package/dist/server/server/worktree-bootstrap.js +753 -0
  714. package/dist/server/server/worktree-branch-name-generator.d.ts +35 -0
  715. package/dist/server/server/worktree-branch-name-generator.js +89 -0
  716. package/dist/server/server/worktree-core.d.ts +32 -0
  717. package/dist/server/server/worktree-core.js +114 -0
  718. package/dist/server/server/worktree-errors.d.ts +12 -0
  719. package/dist/server/server/worktree-errors.js +28 -0
  720. package/dist/server/server/worktree-session.d.ts +165 -0
  721. package/dist/server/server/worktree-session.js +594 -0
  722. package/dist/server/services/forge-cli-command.d.ts +128 -0
  723. package/dist/server/services/forge-cli-command.js +212 -0
  724. package/dist/server/services/forge-registry.d.ts +25 -0
  725. package/dist/server/services/forge-registry.js +155 -0
  726. package/dist/server/services/forge-resolver.d.ts +38 -0
  727. package/dist/server/services/forge-resolver.js +191 -0
  728. package/dist/server/services/forge-service.d.ts +430 -0
  729. package/dist/server/services/forge-service.js +50 -0
  730. package/dist/server/services/gitea-facts.d.ts +11 -0
  731. package/dist/server/services/gitea-facts.js +4 -0
  732. package/dist/server/services/gitea-service.d.ts +62 -0
  733. package/dist/server/services/gitea-service.js +1844 -0
  734. package/dist/server/services/github-facts.d.ts +27 -0
  735. package/dist/server/services/github-facts.js +4 -0
  736. package/dist/server/services/github-service.d.ts +76 -0
  737. package/dist/server/services/github-service.js +3297 -0
  738. package/dist/server/services/gitlab-facts.d.ts +26 -0
  739. package/dist/server/services/gitlab-facts.js +4 -0
  740. package/dist/server/services/gitlab-service.d.ts +43 -0
  741. package/dist/server/services/gitlab-service.js +1092 -0
  742. package/dist/server/services/quota-fetcher/manifest.d.ts +5 -0
  743. package/dist/server/services/quota-fetcher/manifest.js +118 -0
  744. package/dist/server/services/quota-fetcher/provider.d.ts +18 -0
  745. package/dist/server/services/quota-fetcher/provider.js +2 -0
  746. package/dist/server/services/quota-fetcher/providers/claude.d.ts +40 -0
  747. package/dist/server/services/quota-fetcher/providers/claude.js +389 -0
  748. package/dist/server/services/quota-fetcher/providers/codex.d.ts +23 -0
  749. package/dist/server/services/quota-fetcher/providers/codex.js +167 -0
  750. package/dist/server/services/quota-fetcher/providers/copilot.d.ts +21 -0
  751. package/dist/server/services/quota-fetcher/providers/copilot.js +77 -0
  752. package/dist/server/services/quota-fetcher/providers/cursor.d.ts +19 -0
  753. package/dist/server/services/quota-fetcher/providers/cursor.js +185 -0
  754. package/dist/server/services/quota-fetcher/providers/grok.d.ts +23 -0
  755. package/dist/server/services/quota-fetcher/providers/grok.js +137 -0
  756. package/dist/server/services/quota-fetcher/providers/kimi.d.ts +23 -0
  757. package/dist/server/services/quota-fetcher/providers/kimi.js +260 -0
  758. package/dist/server/services/quota-fetcher/providers/minimax.d.ts +29 -0
  759. package/dist/server/services/quota-fetcher/providers/minimax.js +227 -0
  760. package/dist/server/services/quota-fetcher/providers/zai.d.ts +17 -0
  761. package/dist/server/services/quota-fetcher/providers/zai.js +58 -0
  762. package/dist/server/services/quota-fetcher/service.d.ts +34 -0
  763. package/dist/server/services/quota-fetcher/service.js +74 -0
  764. package/dist/server/services/quota-fetcher/usage.d.ts +39 -0
  765. package/dist/server/services/quota-fetcher/usage.js +78 -0
  766. package/dist/server/skills/paseo/SKILL.md +129 -0
  767. package/dist/server/skills/paseo-advisor/SKILL.md +63 -0
  768. package/dist/server/skills/paseo-committee/SKILL.md +46 -0
  769. package/dist/server/skills/paseo-handoff/SKILL.md +65 -0
  770. package/dist/server/skills/paseo-help/SKILL.md +92 -0
  771. package/dist/server/skills/paseo-plugin/SKILL.md +639 -0
  772. package/dist/server/terminal/activity/terminal-activity-tracker.d.ts +21 -0
  773. package/dist/server/terminal/activity/terminal-activity-tracker.js +65 -0
  774. package/dist/server/terminal/agent-hooks/agent-hook-installer.d.ts +62 -0
  775. package/dist/server/terminal/agent-hooks/agent-hook-installer.js +117 -0
  776. package/dist/server/terminal/agent-hooks/claude/claude-settings.d.ts +7 -0
  777. package/dist/server/terminal/agent-hooks/claude/claude-settings.js +88 -0
  778. package/dist/server/terminal/agent-hooks/claude/claude.d.ts +4 -0
  779. package/dist/server/terminal/agent-hooks/claude/claude.js +47 -0
  780. package/dist/server/terminal/agent-hooks/codex/codex-settings.d.ts +7 -0
  781. package/dist/server/terminal/agent-hooks/codex/codex-settings.js +99 -0
  782. package/dist/server/terminal/agent-hooks/codex/codex.d.ts +4 -0
  783. package/dist/server/terminal/agent-hooks/codex/codex.js +30 -0
  784. package/dist/server/terminal/agent-hooks/opencode/opencode-plugin.d.ts +4 -0
  785. package/dist/server/terminal/agent-hooks/opencode/opencode-plugin.js +81 -0
  786. package/dist/server/terminal/agent-hooks/opencode/opencode.d.ts +3 -0
  787. package/dist/server/terminal/agent-hooks/opencode/opencode.js +23 -0
  788. package/dist/server/terminal/agent-hooks/provider-registry.d.ts +24 -0
  789. package/dist/server/terminal/agent-hooks/provider-registry.js +36 -0
  790. package/dist/server/terminal/agent-hooks/terminal-agent-hook-setting.d.ts +10 -0
  791. package/dist/server/terminal/agent-hooks/terminal-agent-hook-setting.js +26 -0
  792. package/dist/server/terminal/shell-integration/zsh/.zshenv +17 -0
  793. package/dist/server/terminal/shell-integration/zsh/paseo-integration.zsh +32 -0
  794. package/dist/server/terminal/terminal-capture.d.ts +12 -0
  795. package/dist/server/terminal/terminal-capture.js +43 -0
  796. package/dist/server/terminal/terminal-manager-factory.d.ts +6 -0
  797. package/dist/server/terminal/terminal-manager-factory.js +5 -0
  798. package/dist/server/terminal/terminal-manager.d.ts +80 -0
  799. package/dist/server/terminal/terminal-manager.js +321 -0
  800. package/dist/server/terminal/terminal-output-coalescer.d.ts +34 -0
  801. package/dist/server/terminal/terminal-output-coalescer.js +73 -0
  802. package/dist/server/terminal/terminal-restore.d.ts +18 -0
  803. package/dist/server/terminal/terminal-restore.js +52 -0
  804. package/dist/server/terminal/terminal-session-controller.d.ts +90 -0
  805. package/dist/server/terminal/terminal-session-controller.js +849 -0
  806. package/dist/server/terminal/terminal-size-ownership.d.ts +9 -0
  807. package/dist/server/terminal/terminal-size-ownership.js +23 -0
  808. package/dist/server/terminal/terminal-ts-loader.mjs +20 -0
  809. package/dist/server/terminal/terminal-worker-process.d.ts +2 -0
  810. package/dist/server/terminal/terminal-worker-process.js +308 -0
  811. package/dist/server/terminal/terminal-worker-protocol.d.ts +121 -0
  812. package/dist/server/terminal/terminal-worker-protocol.js +2 -0
  813. package/dist/server/terminal/terminal.d.ts +151 -0
  814. package/dist/server/terminal/terminal.js +1234 -0
  815. package/dist/server/terminal/worker-terminal-manager.d.ts +20 -0
  816. package/dist/server/terminal/worker-terminal-manager.js +688 -0
  817. package/dist/server/utils/build-metadata-prompt.d.ts +19 -0
  818. package/dist/server/utils/build-metadata-prompt.js +29 -0
  819. package/dist/server/utils/checkout-git.d.ts +317 -0
  820. package/dist/server/utils/checkout-git.js +2886 -0
  821. package/dist/server/utils/directory-suggestions.d.ts +29 -0
  822. package/dist/server/utils/directory-suggestions.js +596 -0
  823. package/dist/server/utils/git-command-runtime-metrics.d.ts +67 -0
  824. package/dist/server/utils/git-command-runtime-metrics.js +126 -0
  825. package/dist/server/utils/git-command-trace.d.ts +29 -0
  826. package/dist/server/utils/git-command-trace.js +74 -0
  827. package/dist/server/utils/git-process-scheduler.d.ts +34 -0
  828. package/dist/server/utils/git-process-scheduler.js +112 -0
  829. package/dist/server/utils/git-rev-parse-path.d.ts +3 -0
  830. package/dist/server/utils/git-rev-parse-path.js +21 -0
  831. package/dist/server/utils/paseo-config-file.d.ts +30 -0
  832. package/dist/server/utils/paseo-config-file.js +90 -0
  833. package/dist/server/utils/path.d.ts +27 -0
  834. package/dist/server/utils/path.js +156 -0
  835. package/dist/server/utils/project-custom-icon.d.ts +40 -0
  836. package/dist/server/utils/project-custom-icon.js +144 -0
  837. package/dist/server/utils/project-icon.d.ts +54 -0
  838. package/dist/server/utils/project-icon.js +445 -0
  839. package/dist/server/utils/promise-timeout.d.ts +9 -0
  840. package/dist/server/utils/promise-timeout.js +25 -0
  841. package/dist/server/utils/run-git-command.d.ts +59 -0
  842. package/dist/server/utils/run-git-command.js +393 -0
  843. package/dist/server/utils/spawn.d.ts +26 -0
  844. package/dist/server/utils/spawn.js +60 -0
  845. package/dist/server/utils/ssh-hostname.d.ts +8 -0
  846. package/dist/server/utils/ssh-hostname.js +60 -0
  847. package/dist/server/utils/string-command-shell.d.ts +13 -0
  848. package/dist/server/utils/string-command-shell.js +37 -0
  849. package/dist/server/utils/tree-kill.d.ts +19 -0
  850. package/dist/server/utils/tree-kill.js +77 -0
  851. package/dist/server/utils/windows-command.d.ts +15 -0
  852. package/dist/server/utils/windows-command.js +41 -0
  853. package/dist/server/utils/worktree-metadata.d.ts +77 -0
  854. package/dist/server/utils/worktree-metadata.js +280 -0
  855. package/dist/server/utils/worktree.d.ts +232 -0
  856. package/dist/server/utils/worktree.js +1193 -0
  857. package/dist/server/web-ui/_expo/static/css/xterm-3bb1704bf6cb0876640973dc0244b4cb.css +1 -0
  858. package/dist/server/web-ui/_expo/static/css/xterm-3bb1704bf6cb0876640973dc0244b4cb.css.br +0 -0
  859. package/dist/server/web-ui/_expo/static/css/xterm-3bb1704bf6cb0876640973dc0244b4cb.css.gz +0 -0
  860. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-29f33408b1a3c5b435c5202d62a36719.js +1 -0
  861. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-29f33408b1a3c5b435c5202d62a36719.js.br +0 -0
  862. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-29f33408b1a3c5b435c5202d62a36719.js.gz +0 -0
  863. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-41547ee520dfff946caa727824742a5c.js +1 -0
  864. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-41547ee520dfff946caa727824742a5c.js.br +0 -0
  865. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-41547ee520dfff946caa727824742a5c.js.gz +0 -0
  866. package/dist/server/web-ui/_expo/static/js/web/index-03b99be4265ac4a2bc5a6d602fd59cc4.js +16819 -0
  867. package/dist/server/web-ui/_expo/static/js/web/index-03b99be4265ac4a2bc5a6d602fd59cc4.js.br +0 -0
  868. package/dist/server/web-ui/_expo/static/js/web/index-03b99be4265ac4a2bc5a6d602fd59cc4.js.gz +0 -0
  869. package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-5444610146b0794f1e7d9edad4522d41.js +1 -0
  870. package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-5444610146b0794f1e7d9edad4522d41.js.br +0 -0
  871. package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-5444610146b0794f1e7d9edad4522d41.js.gz +0 -0
  872. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-88b083190031a44788be59103814f511.js +3 -0
  873. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-88b083190031a44788be59103814f511.js.br +0 -0
  874. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-88b083190031a44788be59103814f511.js.gz +0 -0
  875. package/dist/server/web-ui/apple-touch-icon.png +0 -0
  876. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/back-icon-mask.0a328cd9c1afd0afe8e3b1ec5165b1b4.png +0 -0
  877. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/back-icon.35ba0eaec5a4f5ed12ca16fabeae451d.png +0 -0
  878. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55.png +0 -0
  879. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@2x.png +0 -0
  880. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@3x.png +0 -0
  881. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@4x.png +0 -0
  882. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7.png +0 -0
  883. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@2x.png +0 -0
  884. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@3x.png +0 -0
  885. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@4x.png +0 -0
  886. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/search-icon.286d67d3f74808a60a78d3ebf1a5fb57.png +0 -0
  887. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/arrow_down.017bc6ba3fc25503e5eb5e53826d48a8.png +0 -0
  888. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/error.d1ea1496f9057eb392d5bbf3732a61b7.png +0 -0
  889. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/file.19eeb73b9593a38f8e9f418337fc7d10.png +0 -0
  890. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/forward.d8b800c443b8972542883e0b9de2bdc6.png +0 -0
  891. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/pkg.ab19f4cbc543357183a20571f68380a3.png +0 -0
  892. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/sitemap.412dd9275b6b48ad28f5e3d81bb1f626.png +0 -0
  893. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/unmatched.20e71bdf79e3a97bf55fd9e164041578.png +0 -0
  894. package/dist/server/web-ui/assets/assets/images/favicon-dark-attention.882b3a27dcb2073e9e31b334f9ed9728.png +0 -0
  895. package/dist/server/web-ui/assets/assets/images/favicon-dark-running.8112342ff0d39e047a7f8d4fad9402f3.png +0 -0
  896. package/dist/server/web-ui/assets/assets/images/favicon-dark.8005ed36ac07a5a7c60de25780897bd4.png +0 -0
  897. package/dist/server/web-ui/assets/assets/images/favicon-light-attention.882b3a27dcb2073e9e31b334f9ed9728.png +0 -0
  898. package/dist/server/web-ui/assets/assets/images/favicon-light-running.8112342ff0d39e047a7f8d4fad9402f3.png +0 -0
  899. package/dist/server/web-ui/assets/assets/images/favicon-light.8005ed36ac07a5a7c60de25780897bd4.png +0 -0
  900. package/dist/server/web-ui/assets/assets/images/notification-icon.3bf81d33ddbf380606bdd248ba83e158.png +0 -0
  901. package/dist/server/web-ui/favicon.ico +0 -0
  902. package/dist/server/web-ui/index.html +90 -0
  903. package/dist/server/web-ui/index.html.br +0 -0
  904. package/dist/server/web-ui/index.html.gz +0 -0
  905. package/dist/server/web-ui/manifest.json +27 -0
  906. package/dist/server/web-ui/manifest.json.br +0 -0
  907. package/dist/server/web-ui/manifest.json.gz +0 -0
  908. package/dist/server/web-ui/metadata.json +1 -0
  909. package/dist/server/web-ui/metadata.json.br +1 -0
  910. package/dist/server/web-ui/metadata.json.gz +0 -0
  911. package/dist/server/web-ui/pwa-icon-192.png +0 -0
  912. package/dist/server/web-ui/pwa-icon-512.png +0 -0
  913. package/dist/server/web-ui/robots.txt +2 -0
  914. package/dist/src/executable-resolution/executable-resolution.js +121 -0
  915. package/dist/src/executable-resolution/windows.js +65 -0
  916. package/dist/src/server/agent/provider-launch-config.js +167 -0
  917. package/dist/src/server/paseo-env.js +54 -0
  918. package/dist/src/server/paseo-home.js +19 -0
  919. package/dist/src/server/persisted-config.js +411 -0
  920. package/dist/src/server/pid-lock.js +285 -0
  921. package/dist/src/server/private-files.js +37 -0
  922. package/dist/src/server/speech/providers/local/sherpa/sherpa-runtime-env.js +84 -0
  923. package/dist/src/terminal/shell-integration/zsh/.zshenv +17 -0
  924. package/dist/src/terminal/shell-integration/zsh/paseo-integration.zsh +32 -0
  925. package/dist/src/utils/spawn.js +60 -0
  926. package/dist/src/utils/tree-kill.js +77 -0
  927. package/dist/src/utils/windows-command.js +41 -0
  928. package/package.json +125 -0
@@ -0,0 +1,2534 @@
1
+ import { createHash } from "node:crypto";
2
+ import { readFile } from "node:fs/promises";
3
+ import { basename, join, resolve } from "node:path";
4
+ import { LRUCache } from "lru-cache";
5
+ import pLimit from "p-limit";
6
+ import { parseGitRemoteLocation } from "@camerontaylor/paseo-protocol/git-remote";
7
+ import { getCheckoutDiff, getCheckoutRefDerivedState, getCheckoutSnapshotFacts, getCheckoutShortstat, getCheckoutStatus, getCheckoutWorktreeState, getPullRequestStatus, forgeAuthStateFromError, hasOriginRemote, listBranchSuggestions, resolveRepositoryDefaultBranch, resolveBranchCheckout, resolveAbsoluteGitDir, } from "../utils/checkout-git.js";
8
+ import { createForgeService } from "../services/forge-registry.js";
9
+ import { createForgeResolver, } from "../services/forge-resolver.js";
10
+ import { parseGitRevParsePath } from "../utils/git-rev-parse-path.js";
11
+ import { createRealpathAwarePathMatcher, getRealpathAwareRelativePath, isRealpathInsideRoot, } from "../utils/path.js";
12
+ import { createRunGitCommand, runGitCommand, } from "../utils/run-git-command.js";
13
+ import { branchNameFromRef } from "../utils/worktree-metadata.js";
14
+ import { listPaseoWorktrees } from "../utils/worktree.js";
15
+ import { READ_ONLY_GIT_ENV } from "./checkout-git-utils.js";
16
+ import { classifyGitMetadataPath, getPrunedGitMetadataPaths } from "./git-metadata-event-rules.js";
17
+ import { fetchWorkspaceGitRemote, } from "./workspace-git-fetch.js";
18
+ import { deriveProjectSlug } from "./workspace-git-metadata.js";
19
+ import { createFileObserver, } from "./file-observer/index.js";
20
+ import { checkoutLiteFromGitSnapshot } from "./workspace-registry-model.js";
21
+ import { createWatcherLivenessCanary } from "./watcher-liveness-canary.js";
22
+ const WORKSPACE_GIT_WATCH_DEBOUNCE_MS = 1000;
23
+ const BACKGROUND_GIT_FETCH_INTERVAL_MS = 180000;
24
+ const FETCH_METADATA_ECHO_TTL_MS = 5000;
25
+ export const WORKSPACE_GIT_OBSERVATION_REENSURE_INTERVAL_MS = 60000;
26
+ const FORGE_PR_STATUS_POLL_FAST_INTERVAL_MS = 20000;
27
+ const FORGE_PR_STATUS_POLL_SLOW_INTERVAL_MS = 120000;
28
+ const FORGE_PR_STATUS_POLL_ERROR_BACKOFF_CAP_MS = 300000;
29
+ const DEGRADED_GIT_POLL_INTERVAL_MS = 5000;
30
+ // Keep whole workspace pipelines below the lower-level Git process pool so daemon control work
31
+ // retains subprocess and event-loop headroom during large workspace reconciliation bursts.
32
+ export const WORKSPACE_GIT_REFRESH_CONCURRENCY = 4;
33
+ export const WORKSPACE_GIT_OBSERVATION_SETUP_CONCURRENCY = 2;
34
+ export const WORKSPACE_GIT_WATCHER_SUBSCRIBE_TIMEOUT_MS = 10000;
35
+ const WATCH_RECOVERY_BASE_DELAY_MS = 30000;
36
+ const WATCH_RECOVERY_MAX_ATTEMPTS = 3;
37
+ // Auxiliary reads may reuse cached values within this window; snapshots do not expire on read.
38
+ const WORKSPACE_GIT_AUXILIARY_READ_TTL_MS = 15000;
39
+ // Non-forced refresh triggers share this minimum gap to absorb watcher/self-heal bursts; force bypasses it.
40
+ const WORKSPACE_GIT_INTERNAL_MIN_GAP_MS = 2000;
41
+ // Heavy values (multi-MB highlighted diffs); cap aggressively. Ephemeral worktree cwds would otherwise pile up forever.
42
+ const WORKSPACE_GIT_CHECKOUT_DIFF_CACHE_MAX = 64;
43
+ // Small values (booleans, short strings, small arrays); generous cap.
44
+ const WORKSPACE_GIT_AUXILIARY_CACHE_MAX = 256;
45
+ function mergeSets(left, right) {
46
+ const merged = new Set(left);
47
+ let added = false;
48
+ for (const value of right) {
49
+ if (!merged.has(value)) {
50
+ merged.add(value);
51
+ added = true;
52
+ }
53
+ }
54
+ return { merged, added };
55
+ }
56
+ export function getWorkspaceGitObservationReensurePhaseMs(cwd) {
57
+ return (createHash("sha256").update(cwd).digest().readUInt32BE(0) %
58
+ WORKSPACE_GIT_OBSERVATION_REENSURE_INTERVAL_MS);
59
+ }
60
+ // Kept for local diagnostic fixtures that only use the stable phase calculation.
61
+ export const getWorkspaceGitSelfHealPhaseMs = getWorkspaceGitObservationReensurePhaseMs;
62
+ class WorkspaceGitServiceDisposedError extends Error {
63
+ constructor() {
64
+ super("WorkspaceGitService is disposed");
65
+ this.name = "WorkspaceGitServiceDisposedError";
66
+ }
67
+ }
68
+ class WorkspaceGitWatcherSubscriptionTimeoutError extends Error {
69
+ constructor(watchPath) {
70
+ super(`Watcher subscription for ${watchPath} timed out after ${WORKSPACE_GIT_WATCHER_SUBSCRIBE_TIMEOUT_MS}ms`);
71
+ this.name = "WorkspaceGitWatcherSubscriptionTimeoutError";
72
+ }
73
+ }
74
+ function setsEqual(left, right) {
75
+ return left.size === right.size && [...left].every((value) => right.has(value));
76
+ }
77
+ function buildDefaultWorkspaceGitServiceDeps(subscribe) {
78
+ return {
79
+ subscribe,
80
+ getCheckoutSnapshotFacts,
81
+ getCheckoutRefDerivedState,
82
+ getCheckoutStatus,
83
+ getCheckoutShortstat,
84
+ getCheckoutWorktreeState,
85
+ getCheckoutDiff,
86
+ getPullRequestStatus,
87
+ resolveBranchCheckout,
88
+ resolveRepositoryDefaultBranch,
89
+ listBranchSuggestions,
90
+ listPaseoWorktrees,
91
+ resolveAbsoluteGitDir,
92
+ hasOriginRemote,
93
+ runGitFetch: fetchWorkspaceGitRemote,
94
+ runGitCommand,
95
+ getWorkspaceGitSelfHealPhaseMs: getWorkspaceGitObservationReensurePhaseMs,
96
+ createWatcherLivenessCanary,
97
+ now: () => new Date(),
98
+ };
99
+ }
100
+ function resolveWorkspaceGitServiceDeps(subscribe, deps) {
101
+ return { ...buildDefaultWorkspaceGitServiceDeps(subscribe), ...deps };
102
+ }
103
+ export class WorkspaceGitServiceImpl {
104
+ constructor(options) {
105
+ this.workspaceRefreshLimit = pLimit({
106
+ concurrency: WORKSPACE_GIT_REFRESH_CONCURRENCY,
107
+ rejectOnClear: true,
108
+ });
109
+ this.workspaceObservationSetupLimit = pLimit({
110
+ concurrency: WORKSPACE_GIT_OBSERVATION_SETUP_CONCURRENCY,
111
+ rejectOnClear: true,
112
+ });
113
+ this.disposeController = new AbortController();
114
+ this.disposed = false;
115
+ this.disposePromise = null;
116
+ this.snapshotUpdatedListeners = new Set();
117
+ this.workspaceTargets = new Map();
118
+ this.repoTargets = new Map();
119
+ this.workingTreeWatchTargets = new Map();
120
+ this.workingTreeWatchSetups = new Map();
121
+ this.workingTreeWatchResolutions = new Map();
122
+ this.workingTreeWatchAliases = new Map();
123
+ this.branchValidationCache = new LRUCache({ max: WORKSPACE_GIT_AUXILIARY_CACHE_MAX });
124
+ this.localBranchCache = new LRUCache({ max: WORKSPACE_GIT_AUXILIARY_CACHE_MAX });
125
+ this.branchSuggestionsCache = new LRUCache({ max: WORKSPACE_GIT_AUXILIARY_CACHE_MAX });
126
+ this.stashListCache = new LRUCache({ max: WORKSPACE_GIT_AUXILIARY_CACHE_MAX });
127
+ this.worktreeListCache = new LRUCache({ max: WORKSPACE_GIT_AUXILIARY_CACHE_MAX });
128
+ this.defaultBranchCache = new LRUCache({ max: WORKSPACE_GIT_AUXILIARY_CACHE_MAX });
129
+ this.checkoutDiffCache = new LRUCache({ max: WORKSPACE_GIT_CHECKOUT_DIFF_CACHE_MAX });
130
+ this.watcherErrorCallbackCount = 0;
131
+ this.logger = options.logger.child({ module: "workspace-git-service" });
132
+ this.paseoHome = options.paseoHome;
133
+ this.worktreesRoot = options.worktreesRoot;
134
+ this.fileObserver = options.fileObserver ?? createFileObserver();
135
+ this.deps = resolveWorkspaceGitServiceDeps(this.fileObserver.subscribe.bind(this.fileObserver), options.deps);
136
+ this.forgeResolver = createForgeResolver({
137
+ createService: (forge) => this.deps.forgeOverrides?.[forge] ?? createForgeService(forge),
138
+ });
139
+ }
140
+ resolveForge(cwd) {
141
+ this.assertNotDisposed();
142
+ return this.forgeResolver.resolve(resolve(cwd));
143
+ }
144
+ registerWorkspace(params, listener) {
145
+ this.assertNotDisposed();
146
+ const cwd = resolve(params.cwd);
147
+ const target = this.ensureWorkspaceTarget(cwd);
148
+ target.listeners.add(listener);
149
+ if (target.listeners.size === 1) {
150
+ this.startWorkspaceSubscriptionTimers(target);
151
+ }
152
+ if (!target.latestSnapshot) {
153
+ this.scheduleInitialWorkspaceRefresh(target);
154
+ }
155
+ this.scheduleWorkspaceObservationSetup(target);
156
+ return {
157
+ unsubscribe: () => {
158
+ this.removeWorkspaceListener(cwd, listener);
159
+ },
160
+ };
161
+ }
162
+ onSnapshotUpdated(listener) {
163
+ this.assertNotDisposed();
164
+ this.snapshotUpdatedListeners.add(listener);
165
+ return {
166
+ unsubscribe: () => {
167
+ this.snapshotUpdatedListeners.delete(listener);
168
+ },
169
+ };
170
+ }
171
+ getMetrics() {
172
+ let workspaceListenerCount = 0;
173
+ let repositoryWorkspaceLinkCount = 0;
174
+ let workingTreeWatchListenerCount = 0;
175
+ let workspaceRefreshInFlightCount = 0;
176
+ let workspaceRefreshQueuedCount = 0;
177
+ let workspaceObservationSetupInFlightCount = 0;
178
+ let fetchInFlightCount = 0;
179
+ for (const target of this.workspaceTargets.values()) {
180
+ workspaceListenerCount += target.listeners.size;
181
+ if (target.observationSetupPromise) {
182
+ workspaceObservationSetupInFlightCount += 1;
183
+ }
184
+ if (target.refreshState.status === "in-flight") {
185
+ workspaceRefreshInFlightCount += 1;
186
+ if (target.refreshState.queued) {
187
+ workspaceRefreshQueuedCount += 1;
188
+ }
189
+ }
190
+ }
191
+ for (const target of this.repoTargets.values()) {
192
+ repositoryWorkspaceLinkCount += target.workspaceKeys.size;
193
+ if (target.fetchInFlight) {
194
+ fetchInFlightCount += 1;
195
+ }
196
+ }
197
+ for (const target of this.workingTreeWatchTargets.values()) {
198
+ workingTreeWatchListenerCount += target.listeners.size;
199
+ }
200
+ return {
201
+ workspaceTargetCount: this.workspaceTargets.size,
202
+ workspaceListenerCount,
203
+ repositoryTargetCount: this.repoTargets.size,
204
+ repositoryWorkspaceLinkCount,
205
+ workingTreeWatchTargetCount: this.workingTreeWatchTargets.size,
206
+ workingTreeWatchListenerCount,
207
+ workspaceObservationSetupInFlightCount,
208
+ workingTreeWatchSetupInFlightCount: this.workingTreeWatchSetups.size,
209
+ workspaceRefreshInFlightCount,
210
+ workspaceRefreshQueuedCount,
211
+ workspaceRefreshAdmissionActiveCount: this.workspaceRefreshLimit.activeCount,
212
+ workspaceRefreshAdmissionPendingCount: this.workspaceRefreshLimit.pendingCount,
213
+ workspaceObservationSetupAdmissionActiveCount: this.workspaceObservationSetupLimit.activeCount,
214
+ workspaceObservationSetupAdmissionPendingCount: this.workspaceObservationSetupLimit.pendingCount,
215
+ fetchInFlightCount,
216
+ snapshotUpdatedListenerCount: this.snapshotUpdatedListeners.size,
217
+ watcherErrorCallbackCount: this.watcherErrorCallbackCount,
218
+ fileObserver: this.fileObserver.getDiagnostics(),
219
+ };
220
+ }
221
+ async getSnapshot(cwd, options) {
222
+ this.assertNotDisposed();
223
+ cwd = resolve(cwd);
224
+ const request = this.normalizeRefreshRequest(options, "getSnapshot", true);
225
+ const target = this.ensureWorkspaceTarget(cwd);
226
+ if (!request.force && target.latestSnapshot) {
227
+ return target.latestSnapshot;
228
+ }
229
+ return this.requestWorkspaceSnapshot(target, request);
230
+ }
231
+ async getCheckout(cwd) {
232
+ this.assertNotDisposed();
233
+ const normalizedCwd = resolve(cwd);
234
+ const status = await this.deps.getCheckoutStatus(normalizedCwd, {
235
+ paseoHome: this.paseoHome,
236
+ worktreesRoot: this.worktreesRoot,
237
+ logger: this.logger,
238
+ });
239
+ if (!status.isGit) {
240
+ return checkoutLiteFromGitSnapshot(normalizedCwd, {
241
+ isGit: false,
242
+ currentBranch: null,
243
+ remoteUrl: null,
244
+ repoRoot: null,
245
+ isPaseoOwnedWorktree: false,
246
+ mainRepoRoot: null,
247
+ });
248
+ }
249
+ return checkoutLiteFromGitSnapshot(normalizedCwd, {
250
+ isGit: true,
251
+ currentBranch: status.currentBranch,
252
+ remoteUrl: status.remoteUrl,
253
+ repoRoot: status.repoRoot,
254
+ isPaseoOwnedWorktree: status.isPaseoOwnedWorktree,
255
+ mainRepoRoot: status.mainRepoRoot,
256
+ });
257
+ }
258
+ peekSnapshot(cwd) {
259
+ cwd = resolve(cwd);
260
+ return this.workspaceTargets.get(cwd)?.latestSnapshot ?? null;
261
+ }
262
+ getCheckoutDiff(cwd, options, readOptions) {
263
+ this.assertNotDisposed();
264
+ const normalizedCwd = resolve(cwd);
265
+ const normalizedOptions = this.normalizeCheckoutDiffOptions(options);
266
+ const key = this.buildCheckoutDiffCacheKey(normalizedCwd, normalizedOptions);
267
+ return this.readAuxiliaryCache(this.checkoutDiffCache, key, readOptions, () => this.deps.getCheckoutDiff(normalizedCwd, normalizedOptions, {
268
+ paseoHome: this.paseoHome,
269
+ worktreesRoot: this.worktreesRoot,
270
+ }));
271
+ }
272
+ normalizeCheckoutDiffOptions(options) {
273
+ return {
274
+ mode: options.mode,
275
+ ...(options.mode === "base" && options.baseRef !== undefined
276
+ ? { baseRef: options.baseRef }
277
+ : {}),
278
+ ...(options.ignoreWhitespace === true ? { ignoreWhitespace: true } : {}),
279
+ ...(options.includeStructured === true ? { includeStructured: true } : {}),
280
+ };
281
+ }
282
+ buildCheckoutDiffCacheKey(cwd, options) {
283
+ // Diff content varies by compare signature. Keep the cache per exact diff read shape so
284
+ // hot diff panes coalesce while base refs and rendering options never share stale patches.
285
+ return JSON.stringify([
286
+ "checkout-diff",
287
+ cwd,
288
+ options.mode,
289
+ options.mode === "base" ? (options.baseRef ?? null) : null,
290
+ options.ignoreWhitespace === true,
291
+ options.includeStructured === true,
292
+ ]);
293
+ }
294
+ invalidateCheckoutDiffCache(cwd, mode) {
295
+ for (const key of this.checkoutDiffCache.keys()) {
296
+ const [kind, cachedCwd, cachedMode] = JSON.parse(key);
297
+ if (kind === "checkout-diff" && cachedCwd === cwd && cachedMode === mode) {
298
+ this.checkoutDiffCache.delete(key);
299
+ }
300
+ }
301
+ }
302
+ validateBranchRef(cwd, ref, options) {
303
+ this.assertNotDisposed();
304
+ const normalizedCwd = resolve(cwd);
305
+ const normalizedRef = ref.trim();
306
+ const key = JSON.stringify(["branch-validation", normalizedCwd, normalizedRef]);
307
+ return this.readAuxiliaryCache(this.branchValidationCache, key, options, () => this.deps.resolveBranchCheckout(normalizedCwd, normalizedRef));
308
+ }
309
+ hasLocalBranch(cwd, branch, options) {
310
+ this.assertNotDisposed();
311
+ const normalizedCwd = resolve(cwd);
312
+ const normalizedBranch = branch.trim();
313
+ const ref = `refs/heads/${normalizedBranch}`;
314
+ const key = JSON.stringify(["local-branch", normalizedCwd, ref]);
315
+ return this.readAuxiliaryCache(this.localBranchCache, key, options, async () => {
316
+ const result = await this.deps.runGitCommand(["rev-parse", "--verify", "--quiet", ref], {
317
+ cwd: normalizedCwd,
318
+ envOverlay: READ_ONLY_GIT_ENV,
319
+ acceptExitCodes: [0, 1],
320
+ });
321
+ return result.exitCode === 0;
322
+ });
323
+ }
324
+ suggestBranchesForCwd(cwd, options, readOptions) {
325
+ this.assertNotDisposed();
326
+ const normalizedCwd = resolve(cwd);
327
+ const query = options?.query ?? "";
328
+ const limit = options?.limit;
329
+ const key = JSON.stringify(["branch-suggestions", normalizedCwd, query, limit ?? null]);
330
+ return this.readAuxiliaryCache(this.branchSuggestionsCache, key, readOptions, () => this.deps.listBranchSuggestions(normalizedCwd, options));
331
+ }
332
+ listStashes(cwd, options, readOptions) {
333
+ this.assertNotDisposed();
334
+ const normalizedCwd = resolve(cwd);
335
+ const paseoOnly = options?.paseoOnly !== false;
336
+ const key = JSON.stringify(["stashes", normalizedCwd, paseoOnly]);
337
+ return this.readAuxiliaryCache(this.stashListCache, key, readOptions, async () => {
338
+ const { stdout } = await this.deps.runGitCommand(["stash", "list", "--format=%gd%x00%s"], {
339
+ cwd: normalizedCwd,
340
+ envOverlay: READ_ONLY_GIT_ENV,
341
+ });
342
+ return parseWorkspaceGitStashList(stdout, { paseoOnly });
343
+ });
344
+ }
345
+ async listWorktrees(cwdOrRepoRoot, options) {
346
+ this.assertNotDisposed();
347
+ const repoRoot = await this.resolveRepoRoot(cwdOrRepoRoot, options);
348
+ const key = JSON.stringify(["worktrees", repoRoot]);
349
+ return this.readAuxiliaryCache(this.worktreeListCache, key, options, () => this.deps.listPaseoWorktrees({
350
+ cwd: repoRoot,
351
+ paseoHome: this.paseoHome,
352
+ worktreesRoot: this.worktreesRoot,
353
+ }));
354
+ }
355
+ async resolveRepoRoot(cwd, options) {
356
+ const snapshot = await this.getSnapshot(cwd, options);
357
+ if (!snapshot.git.isGit) {
358
+ throw new Error("Create worktree requires a git repository");
359
+ }
360
+ return snapshot.git.isPaseoOwnedWorktree
361
+ ? (snapshot.git.mainRepoRoot ?? snapshot.git.repoRoot ?? resolve(cwd))
362
+ : (snapshot.git.repoRoot ?? resolve(cwd));
363
+ }
364
+ async resolveDefaultBranch(cwdOrRepoRoot, options) {
365
+ this.assertNotDisposed();
366
+ const cwd = resolve(cwdOrRepoRoot);
367
+ const key = JSON.stringify(["default-branch", cwd]);
368
+ return this.readAuxiliaryCache(this.defaultBranchCache, key, options, async () => {
369
+ const defaultBranch = await this.deps.resolveRepositoryDefaultBranch(cwd);
370
+ if (!defaultBranch) {
371
+ throw new Error("Unable to resolve repository default branch");
372
+ }
373
+ return defaultBranch;
374
+ });
375
+ }
376
+ async getProjectSlug(cwd, options) {
377
+ const snapshot = await this.getSnapshot(cwd, options);
378
+ return deriveProjectSlug(resolve(cwd), snapshot.git.isGit ? snapshot.git.remoteUrl : null);
379
+ }
380
+ async resolveRepoRemoteUrl(cwd, options) {
381
+ const snapshot = await this.getSnapshot(cwd, options);
382
+ return snapshot.git.remoteUrl;
383
+ }
384
+ async refresh(cwd, _options) {
385
+ this.assertNotDisposed();
386
+ cwd = resolve(cwd);
387
+ const target = this.ensureWorkspaceTarget(cwd);
388
+ await this.refreshWorkspaceTarget(target, {
389
+ force: false,
390
+ refreshStructure: true,
391
+ refreshWorktree: true,
392
+ includeForge: false,
393
+ reason: "refresh",
394
+ notify: true,
395
+ queueIfBusy: false,
396
+ movedRemoteRefs: new Set(),
397
+ });
398
+ this.scheduleWorkspaceObservationSetup(target);
399
+ }
400
+ async requestWorkingTreeWatch(cwd, onChange) {
401
+ this.assertNotDisposed();
402
+ cwd = resolve(cwd);
403
+ const target = await this.ensureWorkingTreeWatchTarget(cwd);
404
+ target.listeners.add(onChange);
405
+ return {
406
+ repoRoot: target.repoRoot,
407
+ unsubscribe: () => {
408
+ this.removeWorkingTreeWatchListener(target.cwd, onChange);
409
+ },
410
+ };
411
+ }
412
+ scheduleRefreshForCwd(cwd) {
413
+ this.assertNotDisposed();
414
+ cwd = resolve(cwd);
415
+ const target = this.workspaceTargets.get(cwd);
416
+ if (target) {
417
+ this.scheduleWorkspaceRefresh(target, { queueIfBusy: false });
418
+ }
419
+ }
420
+ onWorkspaceStateMayHaveChanged(cwd) {
421
+ this.assertNotDisposed();
422
+ const normalizedCwd = resolve(cwd);
423
+ const target = this.workspaceTargets.get(normalizedCwd);
424
+ if (!target || target.closed) {
425
+ return;
426
+ }
427
+ this.invalidateForge(normalizedCwd);
428
+ this.scheduleWorkspaceRefresh(target, {
429
+ force: true,
430
+ includeForge: true,
431
+ reason: "external-state-change",
432
+ });
433
+ }
434
+ /**
435
+ * Drop the resolved forge adapter's cached state for a cwd. Goes through the
436
+ * resolver so it targets the same adapter instance the poller reads — used by
437
+ * git mutations to force a fresh forge status on the next refresh.
438
+ */
439
+ invalidateForge(cwd) {
440
+ this.assertNotDisposed();
441
+ this.forgeResolver.invalidate(resolve(cwd));
442
+ }
443
+ dispose() {
444
+ if (this.disposePromise)
445
+ return this.disposePromise;
446
+ this.disposed = true;
447
+ this.disposeController.abort(new WorkspaceGitServiceDisposedError());
448
+ this.workspaceRefreshLimit.clearQueue();
449
+ this.workspaceObservationSetupLimit.clearQueue();
450
+ for (const target of this.workspaceTargets.values()) {
451
+ this.closeWorkspaceTarget(target);
452
+ }
453
+ this.workspaceTargets.clear();
454
+ for (const target of this.repoTargets.values()) {
455
+ this.closeRepoTarget(target);
456
+ }
457
+ this.repoTargets.clear();
458
+ for (const target of this.workingTreeWatchTargets.values()) {
459
+ this.closeWorkingTreeWatchTarget(target);
460
+ }
461
+ this.workingTreeWatchTargets.clear();
462
+ this.workingTreeWatchSetups.clear();
463
+ this.workingTreeWatchResolutions.clear();
464
+ this.workingTreeWatchAliases.clear();
465
+ this.snapshotUpdatedListeners.clear();
466
+ this.disposePromise = this.fileObserver.close();
467
+ return this.disposePromise;
468
+ }
469
+ assertNotDisposed() {
470
+ if (this.disposed) {
471
+ throw new WorkspaceGitServiceDisposedError();
472
+ }
473
+ }
474
+ ensureWorkspaceTarget(cwd) {
475
+ this.assertNotDisposed();
476
+ const existingTarget = this.workspaceTargets.get(cwd);
477
+ if (existingTarget) {
478
+ return existingTarget;
479
+ }
480
+ return this.createWorkspaceTarget(cwd);
481
+ }
482
+ readAuxiliaryCache(cache, key, options, load) {
483
+ this.assertNotDisposed();
484
+ if (options?.force && !options.reason) {
485
+ throw new Error("WorkspaceGitService forced read requires a reason");
486
+ }
487
+ const entry = this.ensureAuxiliaryCacheEntry(cache, key);
488
+ const nowMs = this.deps.now().getTime();
489
+ if (!options?.force && entry.value !== null && entry.loadedAtMs !== null) {
490
+ const ageMs = nowMs - entry.loadedAtMs;
491
+ if (ageMs <= WORKSPACE_GIT_AUXILIARY_READ_TTL_MS) {
492
+ return Promise.resolve(entry.value);
493
+ }
494
+ if (entry.lastShellOutAtMs !== null &&
495
+ nowMs - entry.lastShellOutAtMs < WORKSPACE_GIT_INTERNAL_MIN_GAP_MS) {
496
+ return Promise.resolve(entry.value);
497
+ }
498
+ }
499
+ if (entry.inFlight) {
500
+ return entry.inFlight;
501
+ }
502
+ entry.lastShellOutAtMs = nowMs;
503
+ entry.inFlight = load()
504
+ .then((value) => {
505
+ entry.value = value;
506
+ entry.loadedAtMs = this.deps.now().getTime();
507
+ return value;
508
+ })
509
+ .finally(() => {
510
+ entry.inFlight = null;
511
+ });
512
+ return entry.inFlight;
513
+ }
514
+ ensureAuxiliaryCacheEntry(cache, key) {
515
+ const existing = cache.get(key);
516
+ if (existing) {
517
+ return existing;
518
+ }
519
+ const entry = {
520
+ value: null,
521
+ loadedAtMs: null,
522
+ lastShellOutAtMs: null,
523
+ inFlight: null,
524
+ };
525
+ cache.set(key, entry);
526
+ return entry;
527
+ }
528
+ ensureWorkingTreeWatchTarget(cwd) {
529
+ this.assertNotDisposed();
530
+ const targetCwd = this.workingTreeWatchAliases.get(cwd);
531
+ if (targetCwd) {
532
+ const existingTarget = this.workingTreeWatchTargets.get(targetCwd);
533
+ if (existingTarget) {
534
+ return Promise.resolve(existingTarget);
535
+ }
536
+ this.workingTreeWatchAliases.delete(cwd);
537
+ }
538
+ const existingResolution = this.workingTreeWatchResolutions.get(cwd);
539
+ if (existingResolution) {
540
+ return existingResolution;
541
+ }
542
+ const resolution = this.resolveWorkingTreeWatchTarget(cwd).finally(() => {
543
+ if (this.workingTreeWatchResolutions.get(cwd) === resolution) {
544
+ this.workingTreeWatchResolutions.delete(cwd);
545
+ }
546
+ });
547
+ this.workingTreeWatchResolutions.set(cwd, resolution);
548
+ return resolution;
549
+ }
550
+ async resolveWorkingTreeWatchTarget(cwd) {
551
+ const repoRoot = await this.resolveCheckoutWatchRoot(cwd);
552
+ const targetCwd = repoRoot ?? cwd;
553
+ const existingTarget = this.workingTreeWatchTargets.get(targetCwd);
554
+ if (existingTarget) {
555
+ this.rememberWorkingTreeWatchAlias(existingTarget, cwd);
556
+ return existingTarget;
557
+ }
558
+ const existingSetup = this.workingTreeWatchSetups.get(targetCwd);
559
+ if (existingSetup) {
560
+ const target = await existingSetup;
561
+ this.rememberWorkingTreeWatchAlias(target, cwd);
562
+ return target;
563
+ }
564
+ const watchPath = repoRoot && createRealpathAwarePathMatcher(repoRoot)(cwd) ? cwd : targetCwd;
565
+ const setup = this.createWorkingTreeWatchTarget(targetCwd, watchPath, repoRoot).finally(() => {
566
+ if (this.workingTreeWatchSetups.get(targetCwd) === setup) {
567
+ this.workingTreeWatchSetups.delete(targetCwd);
568
+ }
569
+ });
570
+ this.workingTreeWatchSetups.set(targetCwd, setup);
571
+ const target = await setup;
572
+ this.rememberWorkingTreeWatchAlias(target, cwd);
573
+ return target;
574
+ }
575
+ rememberWorkingTreeWatchAlias(target, cwd) {
576
+ target.aliases.add(cwd);
577
+ this.workingTreeWatchAliases.set(cwd, target.cwd);
578
+ }
579
+ createWorkspaceTarget(cwd) {
580
+ const target = {
581
+ cwd,
582
+ listeners: new Set(),
583
+ workingTreeWatchTarget: null,
584
+ debounceTimer: null,
585
+ pendingDebounceRequest: null,
586
+ observationReensureTimer: null,
587
+ forgePrStatusPollSubscription: null,
588
+ forgePrStatusPollKey: null,
589
+ refreshState: { status: "idle" },
590
+ latestGit: null,
591
+ latestGitLoadedAtMs: null,
592
+ latestForge: null,
593
+ latestForgeLoadedAtMs: null,
594
+ latestSnapshot: null,
595
+ latestSnapshotLoadedAtMs: null,
596
+ latestFacts: null,
597
+ factsPromise: null,
598
+ latestFingerprint: null,
599
+ lastShellOutAtMs: null,
600
+ repoGitRoot: null,
601
+ observationSetupPromise: null,
602
+ observationSetupComplete: false,
603
+ closed: false,
604
+ };
605
+ this.workspaceTargets.set(cwd, target);
606
+ return target;
607
+ }
608
+ scheduleInitialWorkspaceRefresh(target) {
609
+ queueMicrotask(() => {
610
+ if (!this.isActiveObservedWorkspaceTarget(target) || target.latestSnapshot) {
611
+ return;
612
+ }
613
+ void this.refreshWorkspaceTarget(target, {
614
+ force: false,
615
+ refreshStructure: true,
616
+ refreshWorktree: true,
617
+ includeForge: true,
618
+ reason: "initial",
619
+ notify: true,
620
+ queueIfBusy: false,
621
+ movedRemoteRefs: new Set(),
622
+ });
623
+ });
624
+ }
625
+ scheduleWorkspaceObservationSetup(target) {
626
+ if (target.observationSetupComplete ||
627
+ target.observationSetupPromise ||
628
+ !this.isActiveObservedWorkspaceTarget(target)) {
629
+ return;
630
+ }
631
+ target.observationSetupPromise = this.workspaceObservationSetupLimit(async () => {
632
+ if (!this.isActiveObservedWorkspaceTarget(target)) {
633
+ return;
634
+ }
635
+ await this.setupWorkspaceObservation(target);
636
+ })
637
+ .catch((error) => {
638
+ if (this.disposed || !this.isActiveObservedWorkspaceTarget(target)) {
639
+ return;
640
+ }
641
+ this.logger.warn({ err: error, cwd: target.cwd }, "Failed to set up workspace git observation");
642
+ })
643
+ .finally(() => {
644
+ target.observationSetupPromise = null;
645
+ });
646
+ }
647
+ async setupWorkspaceObservation(target) {
648
+ const facts = await this.getFactsForObservation(target);
649
+ if (!this.isActiveObservedWorkspaceTarget(target)) {
650
+ return;
651
+ }
652
+ const watchCwd = facts.isGit ? facts.worktreeRoot : target.cwd;
653
+ const workingTreeTargetPromise = this.ensureWorkingTreeWatchTarget(watchCwd);
654
+ const workingTreeTarget = await workingTreeTargetPromise;
655
+ if (!this.isActiveObservedWorkspaceTarget(target)) {
656
+ queueMicrotask(() => this.closeWorkingTreeWatchTargetIfUnused(workingTreeTarget));
657
+ return;
658
+ }
659
+ if (target.workingTreeWatchTarget !== workingTreeTarget) {
660
+ if (target.workingTreeWatchTarget) {
661
+ this.removeWorkspaceWorkingTreeLink(target.workingTreeWatchTarget, target.cwd);
662
+ }
663
+ target.workingTreeWatchTarget = workingTreeTarget;
664
+ }
665
+ workingTreeTarget.workspaceKeys.add(target.cwd);
666
+ if (!facts.isGit || !facts.absoluteGitDir) {
667
+ target.observationSetupComplete = true;
668
+ return;
669
+ }
670
+ await this.promoteWorkingTreeWatchTarget(workingTreeTarget, facts.worktreeRoot);
671
+ const gitDir = facts.absoluteGitDir;
672
+ const repoGitRoot = facts.gitCommonDir ?? (await this.resolveWorkspaceGitRefsRoot(gitDir));
673
+ if (!this.isActiveObservedWorkspaceTarget(target)) {
674
+ return;
675
+ }
676
+ target.repoGitRoot = repoGitRoot;
677
+ await this.ensureRepoTarget(target);
678
+ if (this.isActiveObservedWorkspaceTarget(target)) {
679
+ target.observationSetupComplete = true;
680
+ }
681
+ }
682
+ async getFactsForObservation(target) {
683
+ if (target.latestFacts) {
684
+ return target.latestFacts;
685
+ }
686
+ return this.loadCheckoutFacts(target, {
687
+ paseoHome: this.paseoHome,
688
+ logger: this.logger,
689
+ });
690
+ }
691
+ loadCheckoutFacts(target, context) {
692
+ if (target.factsPromise) {
693
+ return target.factsPromise;
694
+ }
695
+ const promise = this.deps
696
+ .getCheckoutSnapshotFacts(target.cwd, context)
697
+ .then((facts) => {
698
+ target.latestFacts = facts;
699
+ return facts;
700
+ })
701
+ .finally(() => {
702
+ if (target.factsPromise === promise) {
703
+ target.factsPromise = null;
704
+ }
705
+ });
706
+ target.factsPromise = promise;
707
+ return promise;
708
+ }
709
+ isActiveObservedWorkspaceTarget(target) {
710
+ return (!target.closed &&
711
+ target.listeners.size > 0 &&
712
+ this.workspaceTargets.get(target.cwd) === target);
713
+ }
714
+ async createWorkingTreeWatchTarget(cwd, watchPath, repoRoot) {
715
+ const ignoredDirectories = repoRoot ? await this.loadIgnoredDirs(watchPath) : new Set();
716
+ const target = {
717
+ cwd,
718
+ watchPath,
719
+ repoRoot,
720
+ subscription: null,
721
+ ignoredDirectories,
722
+ ignoredDirectoriesRefreshPromise: null,
723
+ ignoredDirectoriesRefreshRequested: false,
724
+ aliases: new Set([cwd]),
725
+ workspaceKeys: new Set(),
726
+ fallbackPolling: false,
727
+ fallbackPollTimer: null,
728
+ recovery: { attemptCount: 0, timer: null },
729
+ listeners: new Set(),
730
+ closed: false,
731
+ };
732
+ this.workingTreeWatchTargets.set(cwd, target);
733
+ this.workingTreeWatchAliases.set(cwd, cwd);
734
+ await this.startWorkingTreeSubscription(target);
735
+ this.assertNotDisposed();
736
+ if (repoRoot === null) {
737
+ this.startWorkingTreeWatchFallback(target, "not_a_git_checkout");
738
+ }
739
+ return target;
740
+ }
741
+ async subscribeWithDeadline(watchPath, callback, options, onSubscribeSettled) {
742
+ this.assertNotDisposed();
743
+ const signal = this.disposeController.signal;
744
+ let outcome = "pending";
745
+ let timeout = null;
746
+ let removeAbortListener = () => { };
747
+ let unsubscribePromise = null;
748
+ let subscriptionPromise;
749
+ try {
750
+ subscriptionPromise = this.deps
751
+ .subscribe(watchPath, callback, options)
752
+ .finally(onSubscribeSettled);
753
+ }
754
+ catch (error) {
755
+ onSubscribeSettled();
756
+ throw error;
757
+ }
758
+ void subscriptionPromise.then((subscription) => {
759
+ if (outcome === "expired" || signal.aborted) {
760
+ unsubscribePromise ?? (unsubscribePromise = this.unsubscribeWatcherSubscription(subscription, watchPath));
761
+ return unsubscribePromise;
762
+ }
763
+ return undefined;
764
+ }, () => undefined);
765
+ const timeoutPromise = new Promise((_resolve, reject) => {
766
+ timeout = setTimeout(() => {
767
+ outcome = "expired";
768
+ reject(new WorkspaceGitWatcherSubscriptionTimeoutError(watchPath));
769
+ }, WORKSPACE_GIT_WATCHER_SUBSCRIBE_TIMEOUT_MS);
770
+ });
771
+ const disposalPromise = new Promise((_resolve, reject) => {
772
+ const rejectForDisposal = () => {
773
+ outcome = "expired";
774
+ reject(signal.reason);
775
+ };
776
+ if (signal.aborted) {
777
+ rejectForDisposal();
778
+ return;
779
+ }
780
+ signal.addEventListener("abort", rejectForDisposal, { once: true });
781
+ removeAbortListener = () => signal.removeEventListener("abort", rejectForDisposal);
782
+ });
783
+ try {
784
+ const subscription = await Promise.race([
785
+ subscriptionPromise,
786
+ timeoutPromise,
787
+ disposalPromise,
788
+ ]);
789
+ if (signal.aborted) {
790
+ outcome = "expired";
791
+ unsubscribePromise ?? (unsubscribePromise = this.unsubscribeWatcherSubscription(subscription, watchPath));
792
+ await unsubscribePromise;
793
+ throw signal.reason;
794
+ }
795
+ outcome = "accepted";
796
+ return subscription;
797
+ }
798
+ finally {
799
+ if (outcome === "pending") {
800
+ outcome = "expired";
801
+ }
802
+ if (timeout) {
803
+ clearTimeout(timeout);
804
+ }
805
+ removeAbortListener();
806
+ }
807
+ }
808
+ async unsubscribeWatcherSubscription(subscription, watchPath) {
809
+ try {
810
+ await subscription.unsubscribe();
811
+ }
812
+ catch (error) {
813
+ this.logger.warn({ err: error, watchPath }, "Failed to stop watcher subscription");
814
+ }
815
+ }
816
+ async startWorkingTreeSubscription(target, options) {
817
+ const ignore = [join(target.watchPath, ".git"), ...target.ignoredDirectories];
818
+ let watcherErrored = false;
819
+ let subscribeSettled = false;
820
+ const markSubscribeSettled = () => {
821
+ subscribeSettled = true;
822
+ if (watcherErrored) {
823
+ this.scheduleWorkingTreeWatchRecovery(target);
824
+ }
825
+ };
826
+ try {
827
+ const subscription = await this.subscribeWithDeadline(target.watchPath, (error, events) => {
828
+ if (error) {
829
+ if (watcherErrored) {
830
+ return;
831
+ }
832
+ watcherErrored = true;
833
+ this.watcherErrorCallbackCount += 1;
834
+ this.logger.warn({ err: error, cwd: target.cwd }, "Working tree watcher error; using degraded polling");
835
+ this.degradeWorkingTreeWatch(target, "watcher_error");
836
+ if (subscribeSettled) {
837
+ this.scheduleWorkingTreeWatchRecovery(target);
838
+ }
839
+ return;
840
+ }
841
+ if (watcherErrored) {
842
+ return;
843
+ }
844
+ if (events.some((event) => basename(event.path) === ".gitignore")) {
845
+ void this.refreshWorkingTreeIgnoredDirectories(target);
846
+ }
847
+ if (!this.hasRelevantWorkingTreeEvent(target, events)) {
848
+ return;
849
+ }
850
+ this.notifyWorkingTreeChanged(target, "working-tree-watch");
851
+ }, { ignore }, markSubscribeSettled);
852
+ if (watcherErrored) {
853
+ await this.unsubscribeWatcherSubscription(subscription, target.watchPath);
854
+ return false;
855
+ }
856
+ if (target.closed ||
857
+ (target.fallbackPolling && !options?.replaceFallback) ||
858
+ target.subscription) {
859
+ await this.unsubscribeWatcherSubscription(subscription, target.watchPath);
860
+ return false;
861
+ }
862
+ target.subscription = subscription;
863
+ if (options?.replaceFallback && target.repoRoot !== null) {
864
+ target.fallbackPolling = false;
865
+ if (target.fallbackPollTimer) {
866
+ clearTimeout(target.fallbackPollTimer);
867
+ target.fallbackPollTimer = null;
868
+ }
869
+ }
870
+ return true;
871
+ }
872
+ catch (error) {
873
+ if (watcherErrored) {
874
+ return false;
875
+ }
876
+ if (this.disposed || target.closed) {
877
+ throw error;
878
+ }
879
+ this.logger.warn({ err: error, cwd: target.cwd }, "Failed to start working tree watcher; using degraded polling");
880
+ if (!options?.replaceFallback) {
881
+ this.startWorkingTreeWatchFallback(target, "watcher_setup_failed");
882
+ }
883
+ return false;
884
+ }
885
+ }
886
+ startWorkingTreeWatchFallback(target, reason) {
887
+ if (this.disposed || target.closed || target.fallbackPolling) {
888
+ return;
889
+ }
890
+ target.fallbackPolling = true;
891
+ const { cwd } = target;
892
+ const poll = async () => {
893
+ target.fallbackPollTimer = null;
894
+ if (target.closed || this.workingTreeWatchTargets.get(target.cwd) !== target) {
895
+ return;
896
+ }
897
+ await Promise.all(Array.from(target.workspaceKeys, async (workspaceKey) => {
898
+ const workspaceTarget = this.workspaceTargets.get(workspaceKey);
899
+ if (!workspaceTarget) {
900
+ return;
901
+ }
902
+ await this.refreshWorkspaceTarget(workspaceTarget, {
903
+ force: false,
904
+ refreshStructure: target.repoRoot === null,
905
+ refreshWorktree: true,
906
+ includeForge: false,
907
+ reason: "working-tree-watch-fallback",
908
+ notify: true,
909
+ queueIfBusy: true,
910
+ movedRemoteRefs: new Set(),
911
+ });
912
+ if (target.repoRoot === null && workspaceTarget.latestGit?.isGit === true) {
913
+ workspaceTarget.observationSetupComplete = false;
914
+ this.scheduleWorkspaceObservationSetup(workspaceTarget);
915
+ }
916
+ }));
917
+ this.notifyWorkingTreeConsumers(target);
918
+ if (!target.closed && (target.subscription === null || target.repoRoot === null)) {
919
+ target.fallbackPollTimer = setTimeout(poll, DEGRADED_GIT_POLL_INTERVAL_MS);
920
+ }
921
+ else {
922
+ target.fallbackPolling = false;
923
+ }
924
+ };
925
+ target.fallbackPollTimer = setTimeout(poll, DEGRADED_GIT_POLL_INTERVAL_MS);
926
+ this.logger.warn({
927
+ cwd,
928
+ intervalMs: DEGRADED_GIT_POLL_INTERVAL_MS,
929
+ reason,
930
+ }, "Working tree watcher unavailable; using bounded polling fallback");
931
+ }
932
+ degradeWorkingTreeWatch(target, reason) {
933
+ const subscription = target.subscription;
934
+ target.subscription = null;
935
+ if (subscription) {
936
+ void this.unsubscribeWatcherSubscription(subscription, target.watchPath);
937
+ }
938
+ this.notifyWorkingTreeChanged(target, "working-tree-watch-error");
939
+ this.startWorkingTreeWatchFallback(target, reason);
940
+ }
941
+ scheduleWorkingTreeWatchRecovery(target) {
942
+ if (target.closed ||
943
+ target.subscription ||
944
+ target.recovery.timer ||
945
+ target.recovery.attemptCount >= WATCH_RECOVERY_MAX_ATTEMPTS) {
946
+ return;
947
+ }
948
+ target.recovery.attemptCount += 1;
949
+ const delayMs = WATCH_RECOVERY_BASE_DELAY_MS * 2 ** (target.recovery.attemptCount - 1);
950
+ target.recovery.timer = setTimeout(() => {
951
+ target.recovery.timer = null;
952
+ void this.recoverWorkingTreeWatch(target);
953
+ }, delayMs);
954
+ }
955
+ async recoverWorkingTreeWatch(target) {
956
+ if (target.closed || target.subscription) {
957
+ return;
958
+ }
959
+ await this.refreshWorkingTreeIgnoredDirectories(target);
960
+ if (target.closed || target.subscription) {
961
+ return;
962
+ }
963
+ const recovered = await this.startWorkingTreeSubscription(target, { replaceFallback: true });
964
+ if (!recovered) {
965
+ this.scheduleWorkingTreeWatchRecovery(target);
966
+ return;
967
+ }
968
+ this.logger.info({ cwd: target.cwd }, "Working tree watcher recovered");
969
+ this.notifyWorkingTreeChanged(target, "working-tree-watch-recovered");
970
+ }
971
+ async promoteWorkingTreeWatchTarget(target, repoRoot) {
972
+ if (target.repoRoot !== null) {
973
+ return;
974
+ }
975
+ target.repoRoot = repoRoot;
976
+ if (target.subscription && target.fallbackPolling) {
977
+ target.fallbackPolling = false;
978
+ if (target.fallbackPollTimer) {
979
+ clearTimeout(target.fallbackPollTimer);
980
+ target.fallbackPollTimer = null;
981
+ }
982
+ }
983
+ await this.refreshWorkingTreeIgnoredDirectories(target);
984
+ }
985
+ hasRelevantWorkingTreeEvent(target, events) {
986
+ const gitDir = join(target.watchPath, ".git");
987
+ const matchesWatchPath = createRealpathAwarePathMatcher(target.watchPath);
988
+ return events.some((event) => {
989
+ // Directory metadata changes at the watch root do not change Git state.
990
+ // FSEvents may emit these when every changed descendant was ignored.
991
+ if (matchesWatchPath(event.path)) {
992
+ return false;
993
+ }
994
+ if (isRealpathInsideRoot(gitDir, event.path)) {
995
+ return false;
996
+ }
997
+ for (const ignoredDirectory of target.ignoredDirectories) {
998
+ if (isRealpathInsideRoot(ignoredDirectory, event.path)) {
999
+ return false;
1000
+ }
1001
+ }
1002
+ return true;
1003
+ });
1004
+ }
1005
+ refreshWorkingTreeIgnoredDirectories(target) {
1006
+ if (target.closed || target.repoRoot === null) {
1007
+ return Promise.resolve();
1008
+ }
1009
+ target.ignoredDirectoriesRefreshRequested = true;
1010
+ if (target.ignoredDirectoriesRefreshPromise) {
1011
+ return target.ignoredDirectoriesRefreshPromise;
1012
+ }
1013
+ const refreshPromise = (async () => {
1014
+ while (!target.closed && target.ignoredDirectoriesRefreshRequested) {
1015
+ target.ignoredDirectoriesRefreshRequested = false;
1016
+ try {
1017
+ await this.replaceWorkingTreeIgnoredDirectories(target);
1018
+ }
1019
+ catch (error) {
1020
+ this.logger.warn({ err: error, cwd: target.cwd }, "Failed to refresh working tree watcher ignore paths");
1021
+ }
1022
+ }
1023
+ })().finally(() => {
1024
+ if (target.ignoredDirectoriesRefreshPromise === refreshPromise) {
1025
+ target.ignoredDirectoriesRefreshPromise = null;
1026
+ }
1027
+ });
1028
+ target.ignoredDirectoriesRefreshPromise = refreshPromise;
1029
+ return refreshPromise;
1030
+ }
1031
+ async replaceWorkingTreeIgnoredDirectories(target) {
1032
+ const ignoredDirectories = await this.loadIgnoredDirs(target.watchPath);
1033
+ if (target.closed || this.haveSamePaths(target.ignoredDirectories, ignoredDirectories)) {
1034
+ return;
1035
+ }
1036
+ target.ignoredDirectories = ignoredDirectories;
1037
+ if (target.fallbackPolling) {
1038
+ return;
1039
+ }
1040
+ const subscription = target.subscription;
1041
+ if (subscription) {
1042
+ try {
1043
+ await subscription.updateIgnore([join(target.watchPath, ".git"), ...ignoredDirectories]);
1044
+ }
1045
+ catch (error) {
1046
+ target.subscription = null;
1047
+ if (!target.closed && !target.fallbackPolling) {
1048
+ this.startWorkingTreeWatchFallback(target, "watcher_update_failed");
1049
+ this.scheduleWorkingTreeWatchRecovery(target);
1050
+ }
1051
+ this.logger.warn({ err: error, cwd: target.cwd }, "Failed to update working tree watcher ignore paths");
1052
+ return;
1053
+ }
1054
+ }
1055
+ if (target.closed || target.fallbackPolling) {
1056
+ return;
1057
+ }
1058
+ this.notifyWorkingTreeChanged(target, "working-tree-watch-reconfigured");
1059
+ }
1060
+ haveSamePaths(first, second) {
1061
+ if (first.size !== second.size) {
1062
+ return false;
1063
+ }
1064
+ for (const path of first) {
1065
+ if (!second.has(path)) {
1066
+ return false;
1067
+ }
1068
+ }
1069
+ return true;
1070
+ }
1071
+ notifyWorkingTreeChanged(target, reason) {
1072
+ if (target.closed) {
1073
+ return;
1074
+ }
1075
+ this.notifyWorkingTreeConsumers(target);
1076
+ this.scheduleWorkingTreeRefreshes(target, reason);
1077
+ }
1078
+ notifyWorkingTreeConsumers(target) {
1079
+ for (const alias of target.aliases) {
1080
+ this.invalidateCheckoutDiffCache(alias, "uncommitted");
1081
+ }
1082
+ for (const listener of target.listeners) {
1083
+ listener();
1084
+ }
1085
+ }
1086
+ scheduleWorkingTreeRefreshes(target, reason) {
1087
+ for (const workspaceKey of target.workspaceKeys) {
1088
+ const workspaceTarget = this.workspaceTargets.get(workspaceKey);
1089
+ if (workspaceTarget) {
1090
+ this.scheduleWorkspaceRefresh(workspaceTarget, { scope: "worktree", reason });
1091
+ }
1092
+ }
1093
+ }
1094
+ getWorkingTreeWatchTargetForWorkspace(workspaceTarget) {
1095
+ const target = workspaceTarget.workingTreeWatchTarget;
1096
+ return target && !target.closed ? target : null;
1097
+ }
1098
+ async resolveCheckoutWatchRoot(cwd) {
1099
+ try {
1100
+ const { stdout } = await this.deps.runGitCommand(["rev-parse", "--show-toplevel"], {
1101
+ cwd,
1102
+ envOverlay: READ_ONLY_GIT_ENV,
1103
+ });
1104
+ return parseGitRevParsePath(stdout);
1105
+ }
1106
+ catch {
1107
+ return null;
1108
+ }
1109
+ }
1110
+ async resolveWorkspaceGitRefsRoot(gitDir) {
1111
+ try {
1112
+ const commonDir = (await readFile(join(gitDir, "commondir"), "utf8")).trim();
1113
+ if (commonDir.length > 0) {
1114
+ return resolve(gitDir, commonDir);
1115
+ }
1116
+ }
1117
+ catch {
1118
+ return gitDir;
1119
+ }
1120
+ return gitDir;
1121
+ }
1122
+ async ensureRepoTarget(workspaceTarget) {
1123
+ const repoGitRoot = workspaceTarget.repoGitRoot;
1124
+ if (!repoGitRoot || !this.isActiveObservedWorkspaceTarget(workspaceTarget)) {
1125
+ return;
1126
+ }
1127
+ const existingTarget = this.repoTargets.get(repoGitRoot);
1128
+ if (existingTarget) {
1129
+ existingTarget.workspaceKeys.add(workspaceTarget.cwd);
1130
+ return;
1131
+ }
1132
+ const repoTarget = {
1133
+ repoGitRoot,
1134
+ cwd: workspaceTarget.cwd,
1135
+ workspaceKeys: new Set([workspaceTarget.cwd]),
1136
+ subscription: null,
1137
+ fallbackPolling: false,
1138
+ fallbackPollTimer: null,
1139
+ recovery: { attemptCount: 0, timer: null },
1140
+ intervalId: null,
1141
+ fetchInFlight: false,
1142
+ bufferedFetchMetadataEvents: [],
1143
+ recentFetchRemoteRefChanges: new Map(),
1144
+ knownRemoteRefs: null,
1145
+ closed: false,
1146
+ };
1147
+ this.repoTargets.set(repoGitRoot, repoTarget);
1148
+ await this.startRepoMetadataObservation(repoTarget);
1149
+ if (repoTarget.closed || this.repoTargets.get(repoGitRoot) !== repoTarget) {
1150
+ return;
1151
+ }
1152
+ const fetchWorkspaceTarget = Array.from(repoTarget.workspaceKeys)
1153
+ .map((workspaceKey) => this.workspaceTargets.get(workspaceKey))
1154
+ .find((candidate) => candidate !== undefined && this.isActiveObservedWorkspaceTarget(candidate));
1155
+ if (!fetchWorkspaceTarget) {
1156
+ return;
1157
+ }
1158
+ repoTarget.cwd = fetchWorkspaceTarget.cwd;
1159
+ const facts = fetchWorkspaceTarget.latestFacts;
1160
+ const hasOrigin = facts?.isGit === true
1161
+ ? facts.remoteUrl !== null
1162
+ : await this.deps.hasOriginRemote(fetchWorkspaceTarget.cwd);
1163
+ if (repoTarget.closed || this.repoTargets.get(repoGitRoot) !== repoTarget) {
1164
+ return;
1165
+ }
1166
+ if (!hasOrigin) {
1167
+ return;
1168
+ }
1169
+ repoTarget.intervalId = setInterval(() => {
1170
+ void this.runRepoFetch(repoTarget);
1171
+ }, BACKGROUND_GIT_FETCH_INTERVAL_MS);
1172
+ void this.runRepoFetch(repoTarget);
1173
+ }
1174
+ async startRepoMetadataObservation(target, options) {
1175
+ const ignore = getPrunedGitMetadataPaths("common").map((path) => join(target.repoGitRoot, path));
1176
+ const matchesRepoGitRoot = createRealpathAwarePathMatcher(target.repoGitRoot);
1177
+ const canary = this.deps.createWatcherLivenessCanary(target.repoGitRoot);
1178
+ let openedSubscription = null;
1179
+ let watcherErrored = false;
1180
+ let subscribeSettled = false;
1181
+ const markSubscribeSettled = () => {
1182
+ subscribeSettled = true;
1183
+ if (watcherErrored) {
1184
+ this.scheduleRepoMetadataWatchRecovery(target);
1185
+ }
1186
+ };
1187
+ try {
1188
+ const subscription = await this.subscribeWithDeadline(target.repoGitRoot, (error, events) => {
1189
+ const liveEvents = canary.filterEvents(events);
1190
+ if (error) {
1191
+ if (watcherErrored) {
1192
+ return;
1193
+ }
1194
+ watcherErrored = true;
1195
+ this.watcherErrorCallbackCount += 1;
1196
+ this.logger.warn({ err: error, repoGitRoot: target.repoGitRoot }, "Repository metadata watcher error; using degraded polling");
1197
+ this.degradeRepoMetadataWatch(target);
1198
+ if (subscribeSettled) {
1199
+ this.scheduleRepoMetadataWatchRecovery(target);
1200
+ }
1201
+ return;
1202
+ }
1203
+ if (watcherErrored) {
1204
+ return;
1205
+ }
1206
+ if (liveEvents.length === 0) {
1207
+ return;
1208
+ }
1209
+ const relevantEvents = liveEvents.filter((event) => !matchesRepoGitRoot(event.path) &&
1210
+ ignore.every((ignoredPath) => !isRealpathInsideRoot(ignoredPath, event.path)));
1211
+ if (relevantEvents.length > 0) {
1212
+ const immediateEvents = target.fetchInFlight
1213
+ ? relevantEvents.filter((event) => {
1214
+ if (this.isFetchRemoteMetadataEvent(target, event)) {
1215
+ target.bufferedFetchMetadataEvents.push(event);
1216
+ return false;
1217
+ }
1218
+ return true;
1219
+ })
1220
+ : relevantEvents;
1221
+ if (immediateEvents.length > 0) {
1222
+ this.refreshWorkingTreeIgnoresFromRepoMetadataEvents(target, immediateEvents);
1223
+ const routedRefreshes = this.routeRepoMetadataEvents(target, immediateEvents);
1224
+ this.scheduleRepoMetadataRefresh(target, "git-metadata-watch", routedRefreshes === null || [...routedRefreshes.values()].some((r) => r.structural), routedRefreshes);
1225
+ }
1226
+ }
1227
+ }, { ignore }, markSubscribeSettled);
1228
+ openedSubscription = subscription;
1229
+ await canary.verify(this.disposeController.signal);
1230
+ if (watcherErrored) {
1231
+ await this.unsubscribeWatcherSubscription(subscription, target.repoGitRoot);
1232
+ return false;
1233
+ }
1234
+ if (target.closed ||
1235
+ (target.fallbackPolling && !options?.replaceFallback) ||
1236
+ this.repoTargets.get(target.repoGitRoot) !== target) {
1237
+ await this.unsubscribeWatcherSubscription(subscription, target.repoGitRoot);
1238
+ return false;
1239
+ }
1240
+ target.subscription = subscription;
1241
+ if (options?.replaceFallback) {
1242
+ target.fallbackPolling = false;
1243
+ if (target.fallbackPollTimer) {
1244
+ clearTimeout(target.fallbackPollTimer);
1245
+ target.fallbackPollTimer = null;
1246
+ }
1247
+ }
1248
+ return true;
1249
+ }
1250
+ catch (error) {
1251
+ if (openedSubscription) {
1252
+ await this.unsubscribeWatcherSubscription(openedSubscription, target.repoGitRoot);
1253
+ }
1254
+ if (watcherErrored) {
1255
+ return false;
1256
+ }
1257
+ if (this.disposed || target.closed) {
1258
+ throw error;
1259
+ }
1260
+ this.logger.warn({ err: error, repoGitRoot: target.repoGitRoot }, "Failed to start repository metadata watcher; using degraded polling");
1261
+ if (!options?.replaceFallback) {
1262
+ this.startRepoMetadataFallback(target);
1263
+ }
1264
+ return false;
1265
+ }
1266
+ }
1267
+ degradeRepoMetadataWatch(target) {
1268
+ const subscription = target.subscription;
1269
+ target.subscription = null;
1270
+ if (subscription) {
1271
+ void this.unsubscribeWatcherSubscription(subscription, target.repoGitRoot);
1272
+ }
1273
+ this.scheduleRepoMetadataRefresh(target, "git-metadata-watch-error", true);
1274
+ this.startRepoMetadataFallback(target);
1275
+ }
1276
+ scheduleRepoMetadataWatchRecovery(target) {
1277
+ if (target.closed ||
1278
+ target.subscription ||
1279
+ target.recovery.timer ||
1280
+ target.recovery.attemptCount >= WATCH_RECOVERY_MAX_ATTEMPTS) {
1281
+ return;
1282
+ }
1283
+ target.recovery.attemptCount += 1;
1284
+ const delayMs = WATCH_RECOVERY_BASE_DELAY_MS * 2 ** (target.recovery.attemptCount - 1);
1285
+ target.recovery.timer = setTimeout(() => {
1286
+ target.recovery.timer = null;
1287
+ void this.recoverRepoMetadataWatch(target);
1288
+ }, delayMs);
1289
+ }
1290
+ async recoverRepoMetadataWatch(target) {
1291
+ if (target.closed || target.subscription) {
1292
+ return;
1293
+ }
1294
+ const recovered = await this.startRepoMetadataObservation(target, { replaceFallback: true });
1295
+ if (!recovered) {
1296
+ this.scheduleRepoMetadataWatchRecovery(target);
1297
+ return;
1298
+ }
1299
+ this.logger.info({ repoGitRoot: target.repoGitRoot }, "Repository metadata watcher recovered");
1300
+ }
1301
+ routeRepoMetadataEvents(target, events) {
1302
+ const refreshes = new Map();
1303
+ const matchesRepoGitRoot = createRealpathAwarePathMatcher(target.repoGitRoot);
1304
+ for (const event of events) {
1305
+ if (!this.routeRepoMetadataEvent(target, event, matchesRepoGitRoot, refreshes))
1306
+ return null;
1307
+ }
1308
+ return refreshes;
1309
+ }
1310
+ refreshWorkingTreeIgnoresFromRepoMetadataEvents(target, events) {
1311
+ const workspaceKeys = new Set();
1312
+ for (const event of events) {
1313
+ const commonRelativePath = getRealpathAwareRelativePath(target.repoGitRoot, event.path)?.replaceAll("\\", "/");
1314
+ if (commonRelativePath === "config" || commonRelativePath === "info/exclude") {
1315
+ for (const workspaceKey of target.workspaceKeys)
1316
+ workspaceKeys.add(workspaceKey);
1317
+ continue;
1318
+ }
1319
+ for (const workspaceKey of target.workspaceKeys) {
1320
+ const facts = this.workspaceTargets.get(workspaceKey)?.latestFacts;
1321
+ if (facts?.isGit &&
1322
+ facts.absoluteGitDir &&
1323
+ getRealpathAwareRelativePath(facts.absoluteGitDir, event.path)?.replaceAll("\\", "/") ===
1324
+ "config.worktree") {
1325
+ workspaceKeys.add(workspaceKey);
1326
+ }
1327
+ }
1328
+ }
1329
+ for (const workspaceKey of workspaceKeys) {
1330
+ const workspaceTarget = this.workspaceTargets.get(workspaceKey);
1331
+ const workingTreeTarget = workspaceTarget
1332
+ ? this.getWorkingTreeWatchTargetForWorkspace(workspaceTarget)
1333
+ : null;
1334
+ if (workingTreeTarget)
1335
+ void this.refreshWorkingTreeIgnoredDirectories(workingTreeTarget);
1336
+ }
1337
+ }
1338
+ isFetchRemoteMetadataEvent(target, event) {
1339
+ const relativePath = getRealpathAwareRelativePath(target.repoGitRoot, event.path);
1340
+ const effect = classifyGitMetadataPath("common", relativePath ?? "");
1341
+ return ((effect.kind === "ref" && effect.namespace === "remote") ||
1342
+ (effect.kind === "all" &&
1343
+ (relativePath === "packed-refs" || relativePath?.startsWith("reftable/") === true)));
1344
+ }
1345
+ routeRepoMetadataEvent(target, event, matchesRepoGitRoot, refreshes) {
1346
+ if (this.routePrivateGitDirEvent(target, event, matchesRepoGitRoot, refreshes))
1347
+ return true;
1348
+ const commonRelativePath = getRealpathAwareRelativePath(target.repoGitRoot, event.path);
1349
+ const effect = classifyGitMetadataPath("common", commonRelativePath ?? "");
1350
+ switch (effect.kind) {
1351
+ case "ignore":
1352
+ return true;
1353
+ case "owner":
1354
+ this.routeMainCheckoutMetadata(target, matchesRepoGitRoot, effect.refreshBase, refreshes);
1355
+ return true;
1356
+ case "ref":
1357
+ if (effect.namespace === "local") {
1358
+ this.routeLocalBranchRef(target, effect.ref, refreshes);
1359
+ }
1360
+ else {
1361
+ if (event.type === "delete") {
1362
+ target.recentFetchRemoteRefChanges.delete(effect.ref);
1363
+ target.knownRemoteRefs = null;
1364
+ return false;
1365
+ }
1366
+ const recent = target.recentFetchRemoteRefChanges.get(effect.ref);
1367
+ if (recent && recent.expiresAtMs >= this.deps.now().getTime()) {
1368
+ this.routeRemoteBranchRef(target, effect.ref, refreshes, {
1369
+ narrow: recent.change.kind === "moved",
1370
+ });
1371
+ }
1372
+ else {
1373
+ target.recentFetchRemoteRefChanges.delete(effect.ref);
1374
+ if (target.knownRemoteRefs?.has(effect.ref)) {
1375
+ this.routeRemoteBranchRef(target, effect.ref, refreshes, { narrow: true });
1376
+ }
1377
+ else if (event.type === "create" &&
1378
+ target.knownRemoteRefs &&
1379
+ [...target.knownRemoteRefs].some((ref) => ref.startsWith(`${effect.ref}/`))) {
1380
+ return true;
1381
+ }
1382
+ else {
1383
+ return false;
1384
+ }
1385
+ }
1386
+ }
1387
+ return true;
1388
+ case "all":
1389
+ if (commonRelativePath === "packed-refs" ||
1390
+ commonRelativePath?.startsWith("reftable/") === true) {
1391
+ target.knownRemoteRefs = null;
1392
+ }
1393
+ return false;
1394
+ }
1395
+ }
1396
+ routePrivateGitDirEvent(target, event, matchesRepoGitRoot, refreshes) {
1397
+ let matched = false;
1398
+ for (const workspaceKey of target.workspaceKeys) {
1399
+ const facts = this.workspaceTargets.get(workspaceKey)?.latestFacts;
1400
+ if (!facts?.isGit || !facts.absoluteGitDir || matchesRepoGitRoot(facts.absoluteGitDir)) {
1401
+ continue;
1402
+ }
1403
+ const relativePath = getRealpathAwareRelativePath(facts.absoluteGitDir, event.path);
1404
+ if (relativePath === null)
1405
+ continue;
1406
+ matched = true;
1407
+ const effect = classifyGitMetadataPath("worktree", relativePath);
1408
+ if (effect.kind === "owner") {
1409
+ this.addWorkspaceMetadataRefresh(refreshes, workspaceKey, effect.refreshBase);
1410
+ }
1411
+ else if (effect.kind !== "ignore") {
1412
+ throw new Error(`Invalid ${effect.kind} effect for worktree metadata`);
1413
+ }
1414
+ }
1415
+ return matched;
1416
+ }
1417
+ routeMainCheckoutMetadata(target, matchesRepoGitRoot, refreshBase, refreshes) {
1418
+ for (const workspaceKey of target.workspaceKeys) {
1419
+ const facts = this.workspaceTargets.get(workspaceKey)?.latestFacts;
1420
+ if (facts?.isGit && facts.absoluteGitDir && matchesRepoGitRoot(facts.absoluteGitDir)) {
1421
+ this.addWorkspaceMetadataRefresh(refreshes, workspaceKey, refreshBase);
1422
+ }
1423
+ }
1424
+ }
1425
+ routeLocalBranchRef(target, branch, refreshes) {
1426
+ for (const workspaceKey of target.workspaceKeys) {
1427
+ const facts = this.workspaceTargets.get(workspaceKey)?.latestFacts;
1428
+ if (!facts?.isGit)
1429
+ continue;
1430
+ const dependentRefs = [
1431
+ facts.storedBaseRef,
1432
+ facts.resolvedBaseRef,
1433
+ facts.comparisonBaseRef,
1434
+ facts.upstreamStatus?.ref,
1435
+ ];
1436
+ const usesBranch = dependentRefs.some((ref) => ref === branch || ref === `refs/heads/${branch}`);
1437
+ if (facts.currentBranch === branch || usesBranch) {
1438
+ this.addWorkspaceMetadataRefresh(refreshes, workspaceKey, true);
1439
+ }
1440
+ }
1441
+ }
1442
+ routeRemoteBranchRef(target, remoteRef, refreshes, options) {
1443
+ const qualifiedRemoteRef = `refs/remotes/${remoteRef}`;
1444
+ for (const workspaceKey of target.workspaceKeys) {
1445
+ const facts = this.workspaceTargets.get(workspaceKey)?.latestFacts;
1446
+ if (!facts?.isGit)
1447
+ continue;
1448
+ const trackedBranch = facts.branchMergeRef?.startsWith("refs/heads/")
1449
+ ? facts.branchMergeRef.slice("refs/heads/".length)
1450
+ : null;
1451
+ const configuredRemoteRef = facts.branchRemoteName && facts.branchRemoteName !== "." && trackedBranch
1452
+ ? `${facts.branchRemoteName}/${trackedBranch}`
1453
+ : null;
1454
+ const shortstatRemoteRef = facts.currentBranch &&
1455
+ (!facts.resolvedBaseRef || branchNameFromRef(facts.resolvedBaseRef) === facts.currentBranch)
1456
+ ? `origin/${facts.currentBranch}`
1457
+ : null;
1458
+ const refs = [
1459
+ facts.storedBaseRef,
1460
+ facts.resolvedBaseRef,
1461
+ facts.comparisonBaseRef,
1462
+ facts.upstreamStatus?.ref,
1463
+ configuredRemoteRef,
1464
+ shortstatRemoteRef,
1465
+ ];
1466
+ const usesRemoteRef = refs.some((ref) => ref === remoteRef || ref === qualifiedRemoteRef);
1467
+ if (usesRemoteRef) {
1468
+ this.addWorkspaceMetadataRefresh(refreshes, workspaceKey, true, {
1469
+ structural: options?.narrow !== true,
1470
+ movedRemoteRef: options?.narrow === true ? remoteRef : undefined,
1471
+ queueIfBusy: options?.queueIfBusy,
1472
+ });
1473
+ }
1474
+ }
1475
+ }
1476
+ addWorkspaceMetadataRefresh(refreshes, workspaceKey, refreshBase, options) {
1477
+ const previous = refreshes.get(workspaceKey);
1478
+ const movedRemoteRefs = new Set(previous?.movedRemoteRefs);
1479
+ if (options?.movedRemoteRef) {
1480
+ movedRemoteRefs.add(options.movedRemoteRef);
1481
+ }
1482
+ refreshes.set(workspaceKey, {
1483
+ refreshBase: previous?.refreshBase === true || refreshBase,
1484
+ structural: previous?.structural === true || options?.structural !== false,
1485
+ movedRemoteRefs,
1486
+ queueIfBusy: (previous?.queueIfBusy ?? false) || (options?.queueIfBusy ?? true),
1487
+ });
1488
+ }
1489
+ scheduleRepoMetadataRefresh(target, reason, refreshWorktree, routedRefreshes = null) {
1490
+ if (target.closed || this.repoTargets.get(target.repoGitRoot) !== target) {
1491
+ return;
1492
+ }
1493
+ const workingTreeTargets = new Set();
1494
+ const refreshes = routedRefreshes ??
1495
+ new Map(Array.from(target.workspaceKeys, (workspaceKey) => [
1496
+ workspaceKey,
1497
+ {
1498
+ refreshBase: true,
1499
+ structural: true,
1500
+ movedRemoteRefs: new Set(),
1501
+ queueIfBusy: true,
1502
+ },
1503
+ ]));
1504
+ for (const [workspaceKey, refresh] of refreshes) {
1505
+ const workspaceTarget = this.workspaceTargets.get(workspaceKey);
1506
+ if (workspaceTarget) {
1507
+ let scope;
1508
+ if (!refreshWorktree) {
1509
+ scope = refresh.structural ? "structure" : "refs";
1510
+ }
1511
+ if (refresh.refreshBase) {
1512
+ this.invalidateCheckoutDiffCache(workspaceTarget.cwd, "base");
1513
+ if (workspaceTarget.latestFacts?.isGit) {
1514
+ this.invalidateCheckoutDiffCache(workspaceTarget.latestFacts.worktreeRoot, "base");
1515
+ }
1516
+ }
1517
+ if (refreshWorktree) {
1518
+ const workingTreeTarget = this.getWorkingTreeWatchTargetForWorkspace(workspaceTarget);
1519
+ if (workingTreeTarget) {
1520
+ workingTreeTargets.add(workingTreeTarget);
1521
+ }
1522
+ }
1523
+ this.scheduleWorkspaceRefresh(workspaceTarget, {
1524
+ scope,
1525
+ emitUnchanged: refresh.refreshBase,
1526
+ reason,
1527
+ queueIfBusy: refresh.queueIfBusy,
1528
+ movedRemoteRefs: refresh.movedRemoteRefs,
1529
+ });
1530
+ }
1531
+ }
1532
+ for (const workingTreeTarget of workingTreeTargets) {
1533
+ this.notifyWorkingTreeConsumers(workingTreeTarget);
1534
+ }
1535
+ }
1536
+ startRepoMetadataFallback(target) {
1537
+ if (target.fallbackPolling || target.closed) {
1538
+ return;
1539
+ }
1540
+ target.fallbackPolling = true;
1541
+ const poll = async () => {
1542
+ target.fallbackPollTimer = null;
1543
+ if (target.closed || this.repoTargets.get(target.repoGitRoot) !== target) {
1544
+ return;
1545
+ }
1546
+ const workingTreeTargets = new Set();
1547
+ await Promise.all(Array.from(target.workspaceKeys, async (workspaceKey) => {
1548
+ const workspaceTarget = this.workspaceTargets.get(workspaceKey);
1549
+ if (!workspaceTarget) {
1550
+ return;
1551
+ }
1552
+ this.invalidateCheckoutDiffCache(workspaceTarget.cwd, "base");
1553
+ if (workspaceTarget.latestFacts?.isGit) {
1554
+ this.invalidateCheckoutDiffCache(workspaceTarget.latestFacts.worktreeRoot, "base");
1555
+ }
1556
+ const workingTreeTarget = this.getWorkingTreeWatchTargetForWorkspace(workspaceTarget);
1557
+ if (workingTreeTarget) {
1558
+ workingTreeTargets.add(workingTreeTarget);
1559
+ }
1560
+ await this.refreshWorkspaceTarget(workspaceTarget, {
1561
+ force: false,
1562
+ refreshStructure: true,
1563
+ refreshWorktree: true,
1564
+ includeForge: false,
1565
+ emitUnchanged: true,
1566
+ reason: "git-metadata-watch-fallback",
1567
+ notify: true,
1568
+ queueIfBusy: true,
1569
+ movedRemoteRefs: new Set(),
1570
+ });
1571
+ }));
1572
+ for (const workingTreeTarget of workingTreeTargets) {
1573
+ this.notifyWorkingTreeConsumers(workingTreeTarget);
1574
+ }
1575
+ if (!target.closed && target.subscription === null) {
1576
+ target.fallbackPollTimer = setTimeout(poll, DEGRADED_GIT_POLL_INTERVAL_MS);
1577
+ }
1578
+ else {
1579
+ target.fallbackPolling = false;
1580
+ }
1581
+ };
1582
+ target.fallbackPollTimer = setTimeout(poll, DEGRADED_GIT_POLL_INTERVAL_MS);
1583
+ }
1584
+ scheduleWorkspaceRefresh(targetOrCwd, options) {
1585
+ const target = typeof targetOrCwd === "string"
1586
+ ? this.workspaceTargets.get(resolve(targetOrCwd))
1587
+ : targetOrCwd;
1588
+ if (!target || target.closed || this.workspaceTargets.get(target.cwd) !== target) {
1589
+ return;
1590
+ }
1591
+ const request = this.buildScheduledRefreshRequest(options);
1592
+ target.pendingDebounceRequest = this.mergeRefreshRequests(target.pendingDebounceRequest, request);
1593
+ if (target.debounceTimer) {
1594
+ clearTimeout(target.debounceTimer);
1595
+ }
1596
+ target.debounceTimer = setTimeout(() => {
1597
+ if (target.closed || this.workspaceTargets.get(target.cwd) !== target) {
1598
+ return;
1599
+ }
1600
+ target.debounceTimer = null;
1601
+ const merged = target.pendingDebounceRequest;
1602
+ target.pendingDebounceRequest = null;
1603
+ if (merged) {
1604
+ void this.refreshWorkspaceTarget(target, merged);
1605
+ }
1606
+ }, WORKSPACE_GIT_WATCH_DEBOUNCE_MS);
1607
+ }
1608
+ startWorkspaceSubscriptionTimers(target) {
1609
+ if (!target.observationReensureTimer) {
1610
+ const reensureObservation = () => {
1611
+ if (!this.isActiveObservedWorkspaceTarget(target)) {
1612
+ target.observationReensureTimer = null;
1613
+ return;
1614
+ }
1615
+ target.observationReensureTimer = setTimeout(reensureObservation, WORKSPACE_GIT_OBSERVATION_REENSURE_INTERVAL_MS);
1616
+ this.scheduleWorkspaceObservationSetup(target);
1617
+ };
1618
+ target.observationReensureTimer = setTimeout(reensureObservation, this.deps.getWorkspaceGitSelfHealPhaseMs(target.cwd));
1619
+ }
1620
+ this.updateForgePrStatusPollForTarget(target);
1621
+ }
1622
+ updateForgePrStatusPollForTarget(target) {
1623
+ if (target.listeners.size === 0) {
1624
+ this.stopForgePrStatusPollForTarget(target);
1625
+ return;
1626
+ }
1627
+ const git = target.latestGit;
1628
+ if (!git?.remoteUrl) {
1629
+ this.stopForgePrStatusPollForTarget(target);
1630
+ return;
1631
+ }
1632
+ const resolution = this.forgeResolver.resolveFromRemoteUrl(git.remoteUrl);
1633
+ if (!resolution) {
1634
+ this.stopForgePrStatusPollForTarget(target);
1635
+ return;
1636
+ }
1637
+ const pollTarget = this.resolveForgePrStatusPollTarget(target);
1638
+ const remoteUrl = git.remoteUrl;
1639
+ if (!pollTarget) {
1640
+ this.stopForgePrStatusPollForTarget(target);
1641
+ return;
1642
+ }
1643
+ const pollKey = buildWorkspaceForgePrStatusPollKey({
1644
+ forge: resolution.forge,
1645
+ remoteUrl,
1646
+ target: pollTarget,
1647
+ });
1648
+ const previousPollKey = target.forgePrStatusPollKey;
1649
+ if (target.forgePrStatusPollKey === pollKey && target.forgePrStatusPollSubscription) {
1650
+ return;
1651
+ }
1652
+ const pollImmediately = previousPollKey !== null && previousPollKey !== pollKey;
1653
+ this.stopForgePrStatusPollForTarget(target);
1654
+ target.forgePrStatusPollKey = pollKey;
1655
+ if (resolution.service.retainCurrentPullRequestStatusPoll) {
1656
+ target.forgePrStatusPollSubscription = resolution.service.retainCurrentPullRequestStatusPoll({
1657
+ cwd: target.cwd,
1658
+ headRef: pollTarget.headRef,
1659
+ ...(pollTarget.headSha ? { headSha: pollTarget.headSha } : {}),
1660
+ ...(pollTarget.headRepositoryOwner
1661
+ ? { headRepositoryOwner: pollTarget.headRepositoryOwner }
1662
+ : {}),
1663
+ onStatus: (status) => {
1664
+ if (!this.isActiveObservedWorkspaceTarget(target)) {
1665
+ return;
1666
+ }
1667
+ this.rememberForgePrStatusSnapshot(target, buildForgeSnapshotFromStatus(status, resolution.forge), {
1668
+ notify: true,
1669
+ });
1670
+ },
1671
+ onError: (error) => {
1672
+ this.logger.warn({
1673
+ err: error,
1674
+ cwd: target.cwd,
1675
+ forge: resolution.forge,
1676
+ headRef: pollTarget.headRef,
1677
+ headRepositoryOwner: pollTarget.headRepositoryOwner,
1678
+ reason: "self-heal-forge-pr-status",
1679
+ }, "Failed to run forge PR status self-heal refresh");
1680
+ },
1681
+ });
1682
+ return;
1683
+ }
1684
+ target.forgePrStatusPollSubscription = this.retainGenericForgePrStatusPoll({
1685
+ target,
1686
+ forge: resolution.forge,
1687
+ service: resolution.service,
1688
+ pollTarget,
1689
+ pollImmediately,
1690
+ });
1691
+ }
1692
+ retainGenericForgePrStatusPoll({ target, forge, service, pollTarget, pollImmediately, }) {
1693
+ let closed = false;
1694
+ let timer = null;
1695
+ let latestStatus = target.latestForge?.pullRequest ?? null;
1696
+ let consecutiveErrors = 0;
1697
+ const schedule = (delayMs) => {
1698
+ if (closed) {
1699
+ return;
1700
+ }
1701
+ timer = setTimeout(() => {
1702
+ timer = null;
1703
+ void poll();
1704
+ }, delayMs);
1705
+ };
1706
+ const poll = async () => {
1707
+ if (closed || !this.isActiveObservedWorkspaceTarget(target)) {
1708
+ return;
1709
+ }
1710
+ try {
1711
+ const status = await service.getCurrentPullRequestStatus({
1712
+ cwd: target.cwd,
1713
+ headRef: pollTarget.headRef,
1714
+ ...(pollTarget.headSha ? { headSha: pollTarget.headSha } : {}),
1715
+ ...(pollTarget.headRepositoryOwner
1716
+ ? { headRepositoryOwner: pollTarget.headRepositoryOwner }
1717
+ : {}),
1718
+ reason: "self-heal-forge-pr-status",
1719
+ });
1720
+ if (!closed && this.isActiveObservedWorkspaceTarget(target)) {
1721
+ latestStatus = status;
1722
+ consecutiveErrors = 0;
1723
+ this.rememberForgePrStatusSnapshot(target, buildForgeSnapshotFromStatus(status, forge), {
1724
+ notify: true,
1725
+ });
1726
+ }
1727
+ }
1728
+ catch (error) {
1729
+ consecutiveErrors += 1;
1730
+ this.logger.warn({
1731
+ err: error,
1732
+ cwd: target.cwd,
1733
+ forge,
1734
+ headRef: pollTarget.headRef,
1735
+ headRepositoryOwner: pollTarget.headRepositoryOwner,
1736
+ reason: "self-heal-forge-pr-status",
1737
+ }, "Failed to run forge PR status self-heal refresh");
1738
+ }
1739
+ finally {
1740
+ schedule(computeGenericForgeNextInterval(latestStatus, consecutiveErrors));
1741
+ }
1742
+ };
1743
+ // A git-only refresh clears forge state when the commit-aware poll identity
1744
+ // changes. Revalidate that new identity immediately instead of leaving the
1745
+ // PR panel empty for the full stable polling interval.
1746
+ schedule(pollImmediately ? 0 : computeGenericForgeNextInterval(latestStatus, consecutiveErrors));
1747
+ return {
1748
+ unsubscribe: () => {
1749
+ closed = true;
1750
+ if (timer) {
1751
+ clearTimeout(timer);
1752
+ timer = null;
1753
+ }
1754
+ },
1755
+ };
1756
+ }
1757
+ resolveForgePrStatusPollTarget(target) {
1758
+ const git = target.latestGit;
1759
+ if (!git?.currentBranch) {
1760
+ return null;
1761
+ }
1762
+ const lookupTarget = target.latestFacts?.isGit && target.latestFacts.currentBranch === git.currentBranch
1763
+ ? target.latestFacts.pullRequestLookupTarget
1764
+ : null;
1765
+ if (target.latestFacts?.isGit && target.latestFacts.paseoWorktree.isPaseoOwnedWorktree) {
1766
+ return lookupTarget;
1767
+ }
1768
+ if (lookupTarget) {
1769
+ return lookupTarget;
1770
+ }
1771
+ return { headRef: git.currentBranch };
1772
+ }
1773
+ stopForgePrStatusPollForTarget(target) {
1774
+ target.forgePrStatusPollSubscription?.unsubscribe();
1775
+ target.forgePrStatusPollSubscription = null;
1776
+ target.forgePrStatusPollKey = null;
1777
+ }
1778
+ async loadIgnoredDirs(rootPath) {
1779
+ const ignored = new Set();
1780
+ try {
1781
+ const result = await this.deps.runGitCommand(["ls-files", "-o", "-i", "--directory", "--exclude-standard"], { cwd: rootPath, env: READ_ONLY_GIT_ENV });
1782
+ for (const raw of result.stdout.split("\n")) {
1783
+ if (!raw.endsWith("/")) {
1784
+ continue;
1785
+ }
1786
+ const rel = raw.replace(/\/+$/, "");
1787
+ if (!rel) {
1788
+ continue;
1789
+ }
1790
+ ignored.add(resolve(rootPath, rel));
1791
+ }
1792
+ }
1793
+ catch (error) {
1794
+ this.logger.debug({ err: error, rootPath }, "Failed to load gitignore directories; falling back to name-based skip only");
1795
+ }
1796
+ return ignored;
1797
+ }
1798
+ async refreshWorkspaceTarget(target, request) {
1799
+ if (target.closed || this.workspaceTargets.get(target.cwd) !== target) {
1800
+ return;
1801
+ }
1802
+ try {
1803
+ await this.requestWorkspaceSnapshot(target, request);
1804
+ }
1805
+ catch (error) {
1806
+ if (this.disposed || target.closed) {
1807
+ return;
1808
+ }
1809
+ this.logger.warn({ err: error, cwd: target.cwd, reason: request.reason }, "Failed to refresh workspace git snapshot");
1810
+ }
1811
+ }
1812
+ requestWorkspaceSnapshot(target, request) {
1813
+ if (target.refreshState.status === "in-flight") {
1814
+ const active = target.refreshState.request;
1815
+ const addsWork = (request.force && !active.force) ||
1816
+ (request.refreshStructure && !active.refreshStructure) ||
1817
+ (request.refreshWorktree && !active.refreshWorktree) ||
1818
+ (request.includeForge && !active.includeForge) ||
1819
+ (request.emitUnchanged === true && active.emitUnchanged !== true) ||
1820
+ [...request.movedRemoteRefs].some((ref) => !active.movedRemoteRefs.has(ref));
1821
+ if (request.queueIfBusy || addsWork) {
1822
+ target.refreshState.queued = this.mergeRefreshRequests(target.refreshState.queued, request);
1823
+ }
1824
+ return target.refreshState.promise;
1825
+ }
1826
+ if (!request.force && !request.queueIfBusy && this.shouldThrottleNonForcedRefresh(target)) {
1827
+ return Promise.resolve(target.latestSnapshot);
1828
+ }
1829
+ const promise = this.runWorkspaceRefreshLoop(target, request).finally(() => {
1830
+ const state = target.refreshState;
1831
+ if (state.status === "in-flight" && state.promise === promise) {
1832
+ target.refreshState = { status: "idle" };
1833
+ }
1834
+ });
1835
+ target.refreshState = {
1836
+ status: "in-flight",
1837
+ promise,
1838
+ request,
1839
+ queued: null,
1840
+ };
1841
+ return promise;
1842
+ }
1843
+ normalizeRefreshRequest(options, defaultReason, notify) {
1844
+ if (options?.force && !options.reason) {
1845
+ throw new Error("WorkspaceGitService.getSnapshot force refresh requires a reason");
1846
+ }
1847
+ const force = options?.force === true;
1848
+ return {
1849
+ force,
1850
+ refreshStructure: true,
1851
+ refreshWorktree: true,
1852
+ includeForge: options?.includeForge ?? true,
1853
+ reason: options?.reason ?? defaultReason,
1854
+ notify,
1855
+ queueIfBusy: false,
1856
+ movedRemoteRefs: new Set(),
1857
+ };
1858
+ }
1859
+ shouldThrottleNonForcedRefresh(target) {
1860
+ if (!target.latestSnapshot || target.lastShellOutAtMs === null) {
1861
+ return false;
1862
+ }
1863
+ return this.deps.now().getTime() - target.lastShellOutAtMs < WORKSPACE_GIT_INTERNAL_MIN_GAP_MS;
1864
+ }
1865
+ buildScheduledRefreshRequest(options) {
1866
+ const scope = options?.scope;
1867
+ return {
1868
+ force: options?.force === true,
1869
+ refreshStructure: scope !== "worktree" && scope !== "refs",
1870
+ refreshWorktree: scope !== "structure" && scope !== "refs",
1871
+ includeForge: options?.includeForge ?? false,
1872
+ emitUnchanged: options?.emitUnchanged,
1873
+ reason: options?.reason ?? "watch",
1874
+ notify: true,
1875
+ queueIfBusy: options?.queueIfBusy ?? true,
1876
+ movedRemoteRefs: new Set(options?.movedRemoteRefs),
1877
+ };
1878
+ }
1879
+ mergeRefreshRequests(pending, request) {
1880
+ if (!pending) {
1881
+ return request;
1882
+ }
1883
+ const force = pending.force || request.force;
1884
+ const upgradesForce = request.force && !pending.force;
1885
+ const upgradesStructure = request.refreshStructure && !pending.refreshStructure;
1886
+ const upgradesWorktree = request.refreshWorktree && !pending.refreshWorktree;
1887
+ const upgradesForge = request.includeForge && !pending.includeForge;
1888
+ const upgradesEmit = request.emitUnchanged === true && pending.emitUnchanged !== true;
1889
+ const { merged: movedRemoteRefs, added: upgradesMovedRefs } = mergeSets(pending.movedRemoteRefs, request.movedRemoteRefs);
1890
+ return {
1891
+ force,
1892
+ refreshStructure: pending.refreshStructure || request.refreshStructure,
1893
+ refreshWorktree: pending.refreshWorktree || request.refreshWorktree,
1894
+ includeForge: pending.includeForge || request.includeForge,
1895
+ emitUnchanged: pending.emitUnchanged === true || request.emitUnchanged === true,
1896
+ reason: upgradesForce ||
1897
+ upgradesStructure ||
1898
+ upgradesWorktree ||
1899
+ upgradesForge ||
1900
+ upgradesEmit ||
1901
+ upgradesMovedRefs
1902
+ ? request.reason
1903
+ : pending.reason,
1904
+ notify: pending.notify || request.notify,
1905
+ queueIfBusy: pending.queueIfBusy || request.queueIfBusy,
1906
+ movedRemoteRefs,
1907
+ };
1908
+ }
1909
+ async runWorkspaceRefreshLoop(target, initialRequest) {
1910
+ let request = initialRequest;
1911
+ let snapshot = target.latestSnapshot ?? buildNotGitSnapshot(target.cwd);
1912
+ let failure = null;
1913
+ while (true) {
1914
+ if (request.emitUnchanged === true &&
1915
+ request.movedRemoteRefs.size === 0 &&
1916
+ target.latestSnapshot) {
1917
+ this.rememberSnapshot(target, target.latestSnapshot, {
1918
+ notify: request.notify,
1919
+ forceEmit: true,
1920
+ });
1921
+ }
1922
+ try {
1923
+ const runRefreshGitCommand = createRunGitCommand(`workspace-refresh:${request.reason}`);
1924
+ const admittedSnapshot = await this.workspaceRefreshLimit(() => {
1925
+ if (target.closed || this.workspaceTargets.get(target.cwd) !== target) {
1926
+ return null;
1927
+ }
1928
+ return this.refreshSnapshot(target, request, runRefreshGitCommand);
1929
+ });
1930
+ if (!admittedSnapshot) {
1931
+ break;
1932
+ }
1933
+ snapshot = admittedSnapshot;
1934
+ this.rememberSnapshot(target, snapshot, {
1935
+ notify: request.notify,
1936
+ forceEmit: request.force || (request.emitUnchanged === true && request.movedRemoteRefs.size > 0),
1937
+ });
1938
+ failure = null;
1939
+ }
1940
+ catch (error) {
1941
+ failure = { error };
1942
+ }
1943
+ if (this.disposed || target.closed || this.workspaceTargets.get(target.cwd) !== target) {
1944
+ break;
1945
+ }
1946
+ const state = target.refreshState;
1947
+ if (state.status !== "in-flight" || !state.queued) {
1948
+ break;
1949
+ }
1950
+ request = state.queued;
1951
+ state.queued = null;
1952
+ state.request = request;
1953
+ }
1954
+ if (failure) {
1955
+ throw failure.error;
1956
+ }
1957
+ return snapshot;
1958
+ }
1959
+ async refreshSnapshot(target, request, runRefreshGitCommand) {
1960
+ let facts = target.latestFacts;
1961
+ if (request.movedRemoteRefs.size > 0 && !request.refreshStructure && !request.refreshWorktree) {
1962
+ if (facts?.isGit && target.latestGit?.isGit) {
1963
+ try {
1964
+ await this.refreshRefDerivedSnapshot(target, facts, request.movedRemoteRefs, runRefreshGitCommand);
1965
+ return this.combineSnapshot(target);
1966
+ }
1967
+ catch (error) {
1968
+ this.logger.debug({ err: error, cwd: target.cwd, movedRemoteRefs: [...request.movedRemoteRefs] }, "Narrow remote ref refresh failed; using structural refresh");
1969
+ }
1970
+ }
1971
+ facts = await this.refreshGitSnapshot(target, {
1972
+ ...request,
1973
+ refreshStructure: true,
1974
+ refreshWorktree: true,
1975
+ }, runRefreshGitCommand);
1976
+ return this.combineSnapshot(target);
1977
+ }
1978
+ if (request.refreshStructure || !facts || !target.latestGit) {
1979
+ facts = await this.refreshGitSnapshot(target, request, runRefreshGitCommand);
1980
+ }
1981
+ else if (request.refreshWorktree) {
1982
+ await this.refreshWorktreeSnapshot(target, facts, runRefreshGitCommand);
1983
+ }
1984
+ if (!facts) {
1985
+ facts = await this.refreshGitSnapshot(target, request, runRefreshGitCommand);
1986
+ }
1987
+ if (request.includeForge) {
1988
+ await this.refreshForgeSnapshot(target, request, facts, runRefreshGitCommand);
1989
+ }
1990
+ const snapshot = this.combineSnapshot(target);
1991
+ target.latestSnapshotLoadedAtMs = this.deps.now().getTime();
1992
+ return snapshot;
1993
+ }
1994
+ async refreshRefDerivedSnapshot(target, facts, movedRemoteRefs, runRefreshGitCommand) {
1995
+ const latestGit = target.latestGit;
1996
+ if (!latestGit?.isGit) {
1997
+ throw new Error("Remote ref refresh requires a warmed Git snapshot");
1998
+ }
1999
+ target.lastShellOutAtMs = this.deps.now().getTime();
2000
+ const derived = await this.deps.getCheckoutRefDerivedState(target.cwd, facts, { aheadBehind: latestGit.aheadBehind, diffStat: latestGit.diffStat }, movedRemoteRefs, {
2001
+ paseoHome: this.paseoHome,
2002
+ worktreesRoot: this.worktreesRoot,
2003
+ logger: this.logger,
2004
+ facts,
2005
+ runGitCommand: runRefreshGitCommand,
2006
+ });
2007
+ target.latestFacts = { ...facts, upstreamStatus: derived.upstreamStatus };
2008
+ target.latestGit = {
2009
+ ...latestGit,
2010
+ aheadBehind: derived.aheadBehind,
2011
+ diffStat: derived.diffStat,
2012
+ upstreamRef: derived.upstreamStatus?.ref ?? null,
2013
+ aheadOfOrigin: derived.upstreamStatus?.aheadBehind.ahead ?? null,
2014
+ behindOfOrigin: derived.upstreamStatus?.aheadBehind.behind ?? null,
2015
+ };
2016
+ const loadedAtMs = this.deps.now().getTime();
2017
+ target.latestGitLoadedAtMs = loadedAtMs;
2018
+ }
2019
+ async refreshWorktreeSnapshot(target, facts, runRefreshGitCommand) {
2020
+ const latestGit = target.latestGit;
2021
+ if (!latestGit || !facts.isGit) {
2022
+ return;
2023
+ }
2024
+ target.lastShellOutAtMs = this.deps.now().getTime();
2025
+ const context = {
2026
+ paseoHome: this.paseoHome,
2027
+ worktreesRoot: this.worktreesRoot,
2028
+ logger: this.logger,
2029
+ facts,
2030
+ runGitCommand: runRefreshGitCommand,
2031
+ };
2032
+ const worktree = await this.deps.getCheckoutWorktreeState(target.cwd, context);
2033
+ target.latestGit = {
2034
+ ...latestGit,
2035
+ isDirty: worktree.isDirty,
2036
+ diffStat: worktree.diffStat,
2037
+ };
2038
+ const loadedAtMs = this.deps.now().getTime();
2039
+ target.latestGitLoadedAtMs = loadedAtMs;
2040
+ }
2041
+ async refreshGitSnapshot(target, request, runRefreshGitCommand) {
2042
+ const now = this.deps.now();
2043
+ target.lastShellOutAtMs = now.getTime();
2044
+ const cwd = target.cwd;
2045
+ const previousForgePrStatusPollKey = this.getForgePrStatusPollKey(target);
2046
+ const baseContext = {
2047
+ paseoHome: this.paseoHome,
2048
+ worktreesRoot: this.worktreesRoot,
2049
+ logger: this.logger,
2050
+ runGitCommand: runRefreshGitCommand,
2051
+ };
2052
+ const facts = await this.loadCheckoutFacts(target, baseContext);
2053
+ const context = { ...baseContext, facts };
2054
+ const checkoutStatus = await this.deps.getCheckoutStatus(cwd, context);
2055
+ if (!checkoutStatus.isGit) {
2056
+ target.latestGit = buildNotGitSnapshot(cwd).git;
2057
+ const loadedAtMs = this.deps.now().getTime();
2058
+ target.latestGitLoadedAtMs = loadedAtMs;
2059
+ target.latestForge = buildForgeUnavailableSnapshot();
2060
+ target.latestForgeLoadedAtMs = target.latestGitLoadedAtMs;
2061
+ return facts;
2062
+ }
2063
+ const refreshWorktree = request.refreshWorktree || target.latestGit === null;
2064
+ const diffStat = refreshWorktree
2065
+ ? await this.deps
2066
+ .getCheckoutShortstat(cwd, context, {
2067
+ force: request.force || target.latestGit !== null,
2068
+ })
2069
+ .catch(() => null)
2070
+ : (target.latestGit?.diffStat ?? null);
2071
+ target.latestGit = {
2072
+ isGit: true,
2073
+ repoRoot: checkoutStatus.repoRoot,
2074
+ mainRepoRoot: checkoutStatus.mainRepoRoot,
2075
+ currentBranch: checkoutStatus.currentBranch,
2076
+ remoteUrl: checkoutStatus.remoteUrl,
2077
+ isPaseoOwnedWorktree: checkoutStatus.isPaseoOwnedWorktree,
2078
+ isDirty: refreshWorktree
2079
+ ? checkoutStatus.isDirty
2080
+ : (target.latestGit?.isDirty ?? checkoutStatus.isDirty),
2081
+ baseRef: checkoutStatus.baseRef,
2082
+ aheadBehind: checkoutStatus.aheadBehind,
2083
+ upstreamRef: checkoutStatus.upstreamRef,
2084
+ aheadOfOrigin: checkoutStatus.aheadOfOrigin,
2085
+ behindOfOrigin: checkoutStatus.behindOfOrigin,
2086
+ hasRemote: checkoutStatus.hasRemote,
2087
+ diffStat,
2088
+ };
2089
+ const loadedAtMs = this.deps.now().getTime();
2090
+ target.latestGitLoadedAtMs = loadedAtMs;
2091
+ if (previousForgePrStatusPollKey !== this.getForgePrStatusPollKey(target)) {
2092
+ target.latestForge = buildForgeUnavailableSnapshot();
2093
+ target.latestForgeLoadedAtMs = target.latestGitLoadedAtMs;
2094
+ }
2095
+ return facts;
2096
+ }
2097
+ async refreshForgeSnapshot(target, request, facts, runRefreshGitCommand) {
2098
+ const remoteUrl = target.latestGit?.remoteUrl ?? null;
2099
+ const resolution = await this.forgeResolver.resolveFromRemoteUrlAsync(remoteUrl);
2100
+ // Every forge gates on the resolver alone: a cloud host matches synchronously
2101
+ // and a self-hosted/Enterprise host is recognized by the adapter probe (which
2102
+ // this async resolution populates), so GitHub Enterprise is no longer gated
2103
+ // out by a cloud-only identity check.
2104
+ if (!resolution) {
2105
+ target.latestForge = buildUnresolvedRemoteForgeSnapshot(remoteUrl);
2106
+ target.latestForgeLoadedAtMs = this.deps.now().getTime();
2107
+ return;
2108
+ }
2109
+ const forgeService = resolution.service;
2110
+ const forceForge = request.force && request.includeForge;
2111
+ if (forceForge) {
2112
+ forgeService.invalidate({ cwd: target.cwd });
2113
+ }
2114
+ const forgeSnapshot = await loadForgeSnapshot({
2115
+ cwd: target.cwd,
2116
+ forgeService,
2117
+ now: this.deps.now(),
2118
+ deps: this.deps,
2119
+ force: forceForge,
2120
+ reason: request.reason,
2121
+ facts,
2122
+ runGitCommand: runRefreshGitCommand,
2123
+ });
2124
+ // Carry the resolved forge (probe-aware) so the wire projection labels
2125
+ // self-managed GitLab hosts correctly instead of falling back to "github".
2126
+ target.latestForge = { ...forgeSnapshot, forge: resolution.forge };
2127
+ target.latestForgeLoadedAtMs = this.deps.now().getTime();
2128
+ }
2129
+ combineSnapshot(target) {
2130
+ if (!target.latestGit) {
2131
+ return target.latestSnapshot ?? buildNotGitSnapshot(target.cwd);
2132
+ }
2133
+ return {
2134
+ cwd: target.cwd,
2135
+ git: target.latestGit,
2136
+ forge: target.latestForge ?? buildForgeUnavailableSnapshot(),
2137
+ };
2138
+ }
2139
+ getForgePrStatusPollKey(target) {
2140
+ const git = target.latestGit;
2141
+ if (!git?.currentBranch || !git.remoteUrl) {
2142
+ return null;
2143
+ }
2144
+ const resolution = this.forgeResolver.resolveFromRemoteUrl(git.remoteUrl);
2145
+ if (!resolution) {
2146
+ return null;
2147
+ }
2148
+ const pollTarget = this.resolveForgePrStatusPollTarget(target);
2149
+ if (!pollTarget) {
2150
+ return null;
2151
+ }
2152
+ return buildWorkspaceForgePrStatusPollKey({
2153
+ forge: resolution.forge,
2154
+ remoteUrl: git.remoteUrl,
2155
+ target: pollTarget,
2156
+ });
2157
+ }
2158
+ rememberForgePrStatusSnapshot(target, github, options) {
2159
+ if (target.closed || this.workspaceTargets.get(target.cwd) !== target) {
2160
+ return;
2161
+ }
2162
+ target.latestForge = github;
2163
+ target.latestForgeLoadedAtMs = this.deps.now().getTime();
2164
+ this.rememberSnapshot(target, this.combineSnapshot(target), {
2165
+ notify: options?.notify,
2166
+ forceEmit: false,
2167
+ });
2168
+ }
2169
+ rememberSnapshot(target, snapshot, options) {
2170
+ target.latestSnapshot = snapshot;
2171
+ if (target.listeners.size > 0) {
2172
+ this.updateForgePrStatusPollForTarget(target);
2173
+ }
2174
+ const fingerprint = JSON.stringify(snapshot);
2175
+ const fingerprintMatches = target.latestFingerprint === fingerprint;
2176
+ if (fingerprintMatches && !options?.forceEmit) {
2177
+ return;
2178
+ }
2179
+ target.latestFingerprint = fingerprint;
2180
+ if (!options?.notify || target.listeners.size === 0) {
2181
+ return;
2182
+ }
2183
+ for (const listener of target.listeners) {
2184
+ listener(snapshot);
2185
+ }
2186
+ for (const listener of this.snapshotUpdatedListeners) {
2187
+ try {
2188
+ listener(snapshot);
2189
+ }
2190
+ catch (error) {
2191
+ this.logger.warn({ err: error, cwd: snapshot.cwd }, "Workspace git snapshot listener threw");
2192
+ }
2193
+ }
2194
+ }
2195
+ async runRepoFetch(target) {
2196
+ if (target.fetchInFlight) {
2197
+ return;
2198
+ }
2199
+ target.fetchInFlight = true;
2200
+ this.logger.debug({ repoGitRoot: target.repoGitRoot, cwd: target.cwd }, "Running background git fetch");
2201
+ let result = null;
2202
+ const eventsBeforeFetchSnapshot = [];
2203
+ try {
2204
+ try {
2205
+ result = await this.deps.runGitFetch(target.cwd, {
2206
+ onRefSnapshot: (phase) => {
2207
+ const events = target.bufferedFetchMetadataEvents.splice(0);
2208
+ if (phase === "before") {
2209
+ eventsBeforeFetchSnapshot.push(...events);
2210
+ }
2211
+ },
2212
+ }, createRunGitCommand("background-fetch"));
2213
+ }
2214
+ catch (error) {
2215
+ this.logger.warn({ err: error, repoGitRoot: target.repoGitRoot, cwd: target.cwd }, "Background git fetch failed");
2216
+ }
2217
+ this.applyRepoFetchResult(target, result, eventsBeforeFetchSnapshot);
2218
+ }
2219
+ finally {
2220
+ target.fetchInFlight = false;
2221
+ }
2222
+ }
2223
+ applyRepoFetchResult(target, result, eventsBeforeFetchSnapshot) {
2224
+ this.flushFetchMetadataEvents(target, eventsBeforeFetchSnapshot);
2225
+ if (!result || result.changes === null) {
2226
+ target.recentFetchRemoteRefChanges.clear();
2227
+ target.knownRemoteRefs = null;
2228
+ this.flushBufferedFetchMetadataEvents(target);
2229
+ if (result) {
2230
+ this.logger.warn({ err: result.error, repoGitRoot: target.repoGitRoot, cwd: target.cwd }, "Background git fetch ref classification failed; using structural refresh");
2231
+ }
2232
+ this.scheduleRepoMetadataRefresh(target, "repo-fetch-unclassified", false);
2233
+ return;
2234
+ }
2235
+ if (result.error) {
2236
+ this.logger.warn({ err: result.error, repoGitRoot: target.repoGitRoot, cwd: target.cwd }, "Background git fetch completed with errors after changing refs");
2237
+ }
2238
+ const expiresAtMs = this.deps.now().getTime() + FETCH_METADATA_ECHO_TTL_MS;
2239
+ const remoteRefShapeChanged = target.knownRemoteRefs !== null &&
2240
+ result.remoteRefs !== undefined &&
2241
+ !setsEqual(target.knownRemoteRefs, result.remoteRefs);
2242
+ if (result.remoteRefs) {
2243
+ target.knownRemoteRefs = new Set(result.remoteRefs);
2244
+ }
2245
+ target.recentFetchRemoteRefChanges.clear();
2246
+ for (const change of result.changes) {
2247
+ target.recentFetchRemoteRefChanges.set(change.ref, { change, expiresAtMs });
2248
+ }
2249
+ this.flushBufferedFetchMetadataEvents(target);
2250
+ if (result.nonRemoteRefsChanged === true ||
2251
+ remoteRefShapeChanged ||
2252
+ result.changes.some((change) => change.kind !== "moved")) {
2253
+ this.scheduleRepoMetadataRefresh(target, "repo-fetch-ref-shape", false);
2254
+ return;
2255
+ }
2256
+ if (result.changes.length === 0) {
2257
+ return;
2258
+ }
2259
+ const refreshes = new Map();
2260
+ for (const change of result.changes) {
2261
+ this.routeRemoteBranchRef(target, change.ref, refreshes, { narrow: true });
2262
+ }
2263
+ this.scheduleRepoMetadataRefresh(target, "repo-fetch", false, refreshes);
2264
+ }
2265
+ flushBufferedFetchMetadataEvents(target) {
2266
+ this.flushFetchMetadataEvents(target, target.bufferedFetchMetadataEvents.splice(0));
2267
+ }
2268
+ flushFetchMetadataEvents(target, events) {
2269
+ if (events.length === 0) {
2270
+ return;
2271
+ }
2272
+ const routedRefreshes = this.routeRepoMetadataEvents(target, events);
2273
+ this.scheduleRepoMetadataRefresh(target, "git-metadata-watch-after-fetch", routedRefreshes === null ||
2274
+ [...routedRefreshes.values()].some((refresh) => refresh.structural), routedRefreshes);
2275
+ }
2276
+ removeWorkspaceListener(cwd, listener) {
2277
+ const target = this.workspaceTargets.get(cwd);
2278
+ if (!target) {
2279
+ return;
2280
+ }
2281
+ target.listeners.delete(listener);
2282
+ if (target.listeners.size > 0) {
2283
+ return;
2284
+ }
2285
+ this.removeWorkspaceTarget(target);
2286
+ }
2287
+ removeWorkspaceTarget(target) {
2288
+ if (target.repoGitRoot) {
2289
+ const repoTarget = this.repoTargets.get(target.repoGitRoot);
2290
+ repoTarget?.workspaceKeys.delete(target.cwd);
2291
+ if (repoTarget && repoTarget.workspaceKeys.size === 0) {
2292
+ this.closeRepoTarget(repoTarget);
2293
+ this.repoTargets.delete(target.repoGitRoot);
2294
+ }
2295
+ else if (repoTarget?.cwd === target.cwd) {
2296
+ repoTarget.cwd = repoTarget.workspaceKeys.values().next().value ?? repoTarget.cwd;
2297
+ }
2298
+ }
2299
+ this.closeWorkspaceTarget(target);
2300
+ this.workspaceTargets.delete(target.cwd);
2301
+ }
2302
+ removeWorkingTreeWatchListener(cwd, listener) {
2303
+ const target = this.workingTreeWatchTargets.get(cwd);
2304
+ if (!target) {
2305
+ return;
2306
+ }
2307
+ target.listeners.delete(listener);
2308
+ if (target.listeners.size > 0 || target.workspaceKeys.size > 0) {
2309
+ return;
2310
+ }
2311
+ this.closeWorkingTreeWatchTarget(target);
2312
+ this.workingTreeWatchTargets.delete(cwd);
2313
+ }
2314
+ removeWorkspaceWorkingTreeLink(target, workspaceKey) {
2315
+ target.workspaceKeys.delete(workspaceKey);
2316
+ if (target.workspaceKeys.size > 0 || target.listeners.size > 0) {
2317
+ return;
2318
+ }
2319
+ this.closeWorkingTreeWatchTarget(target);
2320
+ if (this.workingTreeWatchTargets.get(target.cwd) === target) {
2321
+ this.workingTreeWatchTargets.delete(target.cwd);
2322
+ }
2323
+ }
2324
+ closeWorkingTreeWatchTargetIfUnused(target) {
2325
+ if (target.closed ||
2326
+ target.workspaceKeys.size > 0 ||
2327
+ target.listeners.size > 0 ||
2328
+ this.workingTreeWatchTargets.get(target.cwd) !== target) {
2329
+ return;
2330
+ }
2331
+ this.closeWorkingTreeWatchTarget(target);
2332
+ this.workingTreeWatchTargets.delete(target.cwd);
2333
+ }
2334
+ closeWorkspaceTarget(target) {
2335
+ target.closed = true;
2336
+ if (target.workingTreeWatchTarget) {
2337
+ this.removeWorkspaceWorkingTreeLink(target.workingTreeWatchTarget, target.cwd);
2338
+ target.workingTreeWatchTarget = null;
2339
+ }
2340
+ if (target.debounceTimer) {
2341
+ clearTimeout(target.debounceTimer);
2342
+ target.debounceTimer = null;
2343
+ }
2344
+ if (target.observationReensureTimer) {
2345
+ clearTimeout(target.observationReensureTimer);
2346
+ target.observationReensureTimer = null;
2347
+ }
2348
+ this.stopForgePrStatusPollForTarget(target);
2349
+ target.listeners.clear();
2350
+ }
2351
+ closeWorkingTreeWatchTarget(target) {
2352
+ target.closed = true;
2353
+ for (const alias of target.aliases) {
2354
+ if (this.workingTreeWatchAliases.get(alias) === target.cwd) {
2355
+ this.workingTreeWatchAliases.delete(alias);
2356
+ }
2357
+ }
2358
+ target.aliases.clear();
2359
+ if (target.fallbackPollTimer) {
2360
+ clearTimeout(target.fallbackPollTimer);
2361
+ target.fallbackPollTimer = null;
2362
+ }
2363
+ target.fallbackPolling = false;
2364
+ if (target.recovery.timer) {
2365
+ clearTimeout(target.recovery.timer);
2366
+ target.recovery.timer = null;
2367
+ }
2368
+ if (target.subscription) {
2369
+ const subscription = target.subscription;
2370
+ target.subscription = null;
2371
+ void subscription.unsubscribe().catch((error) => {
2372
+ this.logger.warn({ err: error, cwd: target.cwd }, "Failed to stop working tree watcher");
2373
+ });
2374
+ }
2375
+ target.workspaceKeys.clear();
2376
+ target.listeners.clear();
2377
+ }
2378
+ closeRepoTarget(target) {
2379
+ target.closed = true;
2380
+ if (target.intervalId) {
2381
+ clearInterval(target.intervalId);
2382
+ target.intervalId = null;
2383
+ }
2384
+ if (target.fallbackPollTimer) {
2385
+ clearTimeout(target.fallbackPollTimer);
2386
+ target.fallbackPollTimer = null;
2387
+ }
2388
+ target.fallbackPolling = false;
2389
+ if (target.recovery.timer) {
2390
+ clearTimeout(target.recovery.timer);
2391
+ target.recovery.timer = null;
2392
+ }
2393
+ if (target.subscription) {
2394
+ const subscription = target.subscription;
2395
+ target.subscription = null;
2396
+ void subscription.unsubscribe().catch((error) => {
2397
+ this.logger.warn({ err: error, repoGitRoot: target.repoGitRoot }, "Failed to stop repository metadata watcher");
2398
+ });
2399
+ }
2400
+ target.workspaceKeys.clear();
2401
+ }
2402
+ }
2403
+ async function loadForgeSnapshot(options) {
2404
+ const forgeService = options.forgeService;
2405
+ if (!forgeService) {
2406
+ return buildForgeSnapshot("no_remote", null, null);
2407
+ }
2408
+ // GitHub's isAuthenticated throws the precise CLI-missing / auth error; GitLab's
2409
+ // and Gitea's return false without throwing (the precise kind surfaces from
2410
+ // the PR-status lookup below instead), so probing them here can't change the
2411
+ // outcome and would just be a wasted CLI spawn on every refresh.
2412
+ if (forgeService.authProbeCanThrow) {
2413
+ try {
2414
+ await forgeService.isAuthenticated({ cwd: options.cwd });
2415
+ }
2416
+ catch (error) {
2417
+ return buildForgeSnapshot(forgeAuthStateFromError(error), null, null);
2418
+ }
2419
+ }
2420
+ try {
2421
+ const result = await options.deps.getPullRequestStatus(options.cwd, forgeService, {
2422
+ force: options.force,
2423
+ reason: options.reason,
2424
+ }, { facts: options.facts, runGitCommand: options.runGitCommand });
2425
+ return buildForgeSnapshot(result.authState, result.status, null);
2426
+ }
2427
+ catch (error) {
2428
+ // The auth probe succeeded, so a failure here is a command error, not an
2429
+ // auth problem — surface it as an error while keeping features enabled.
2430
+ return buildForgeSnapshot("authenticated", null, {
2431
+ message: error instanceof Error ? error.message : String(error),
2432
+ });
2433
+ }
2434
+ }
2435
+ function buildForgeSnapshot(authState, pullRequest, error) {
2436
+ return {
2437
+ featuresEnabled: authState === "authenticated",
2438
+ authState,
2439
+ pullRequest,
2440
+ error,
2441
+ };
2442
+ }
2443
+ function parseWorkspaceGitStashList(stdout, options) {
2444
+ const entries = [];
2445
+ const lines = stdout.trim().split("\n").filter(Boolean);
2446
+ for (const line of lines) {
2447
+ const sepIdx = line.indexOf("\0");
2448
+ if (sepIdx < 0) {
2449
+ continue;
2450
+ }
2451
+ const refPart = line.slice(0, sepIdx);
2452
+ const subject = line.slice(sepIdx + 1);
2453
+ const indexMatch = refPart.match(/\{(\d+)\}/);
2454
+ if (!indexMatch) {
2455
+ continue;
2456
+ }
2457
+ const index = Number(indexMatch[1]);
2458
+ const prefix = "paseo-auto-stash:";
2459
+ const prefixIdx = subject.indexOf(prefix);
2460
+ const isPaseo = prefixIdx >= 0;
2461
+ const branch = isPaseo ? subject.slice(prefixIdx + prefix.length).trim() || null : null;
2462
+ if (options.paseoOnly && !isPaseo) {
2463
+ continue;
2464
+ }
2465
+ entries.push({ index, message: subject, branch, isPaseo });
2466
+ }
2467
+ return entries;
2468
+ }
2469
+ function buildNotGitSnapshot(cwd) {
2470
+ return {
2471
+ cwd,
2472
+ git: {
2473
+ isGit: false,
2474
+ repoRoot: null,
2475
+ mainRepoRoot: null,
2476
+ currentBranch: null,
2477
+ remoteUrl: null,
2478
+ isPaseoOwnedWorktree: false,
2479
+ isDirty: null,
2480
+ baseRef: null,
2481
+ aheadBehind: null,
2482
+ upstreamRef: null,
2483
+ aheadOfOrigin: null,
2484
+ behindOfOrigin: null,
2485
+ hasRemote: false,
2486
+ diffStat: null,
2487
+ },
2488
+ forge: buildForgeUnavailableSnapshot(),
2489
+ };
2490
+ }
2491
+ function buildForgeUnavailableSnapshot() {
2492
+ return buildForgeSnapshot("no_remote", null, null);
2493
+ }
2494
+ /**
2495
+ * Snapshot for a remote whose host matched no registered forge and no
2496
+ * CLI-authenticated host. Deliberate choice: expose the hostname as the open
2497
+ * `forge` id with `authState: "unauthenticated"`, because a self-hosted
2498
+ * GitLab/Gitea becomes resolvable the moment its CLI is authenticated for
2499
+ * that host — so "authenticate" is the actionable next step. The trade-off:
2500
+ * a genuinely unsupported host (e.g. Bitbucket) also reads as a login
2501
+ * problem; clients that want to distinguish can check the id against the
2502
+ * forge registry.
2503
+ */
2504
+ function buildUnresolvedRemoteForgeSnapshot(remoteUrl) {
2505
+ const host = remoteUrl ? parseGitRemoteLocation(remoteUrl)?.host : null;
2506
+ if (!host) {
2507
+ return buildForgeUnavailableSnapshot();
2508
+ }
2509
+ return { ...buildForgeSnapshot("unauthenticated", null, null), forge: host };
2510
+ }
2511
+ function buildForgeSnapshotFromStatus(status, forge) {
2512
+ return { ...buildForgeSnapshot("authenticated", status, null), forge };
2513
+ }
2514
+ function buildWorkspaceForgePrStatusPollKey({ forge, remoteUrl, target, }) {
2515
+ return JSON.stringify([
2516
+ forge,
2517
+ remoteUrl,
2518
+ target.headRef,
2519
+ target.headSha ?? null,
2520
+ target.headRepositoryOwner ?? null,
2521
+ ]);
2522
+ }
2523
+ function computeGenericForgeNextInterval(status, consecutiveErrors) {
2524
+ const isPending = status?.checksStatus === "pending" ||
2525
+ status?.checks?.some((check) => check.status === "pending") === true;
2526
+ const baseInterval = isPending
2527
+ ? FORGE_PR_STATUS_POLL_FAST_INTERVAL_MS
2528
+ : FORGE_PR_STATUS_POLL_SLOW_INTERVAL_MS;
2529
+ if (consecutiveErrors <= 1) {
2530
+ return baseInterval;
2531
+ }
2532
+ return Math.min(baseInterval * 2 ** (consecutiveErrors - 1), FORGE_PR_STATUS_POLL_ERROR_BACKOFF_CAP_MS);
2533
+ }
2534
+ //# sourceMappingURL=workspace-git-service.js.map