@otto-code/server 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (734) 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 +141 -0
  6. package/dist/scripts/supervisor-log-config.js +31 -0
  7. package/dist/scripts/supervisor.js +252 -0
  8. package/dist/server/executable-resolution/executable-resolution.d.ts +10 -0
  9. package/dist/server/executable-resolution/executable-resolution.js +118 -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 +28 -0
  13. package/dist/server/server/agent/activity-curator.js +227 -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-loading.d.ts +14 -0
  17. package/dist/server/server/agent/agent-loading.js +54 -0
  18. package/dist/server/server/agent/agent-manager.d.ts +470 -0
  19. package/dist/server/server/agent/agent-manager.js +3049 -0
  20. package/dist/server/server/agent/agent-personalities.d.ts +59 -0
  21. package/dist/server/server/agent/agent-personalities.js +103 -0
  22. package/dist/server/server/agent/agent-projections.d.ts +35 -0
  23. package/dist/server/server/agent/agent-projections.js +488 -0
  24. package/dist/server/server/agent/agent-prompt.d.ts +76 -0
  25. package/dist/server/server/agent/agent-prompt.js +230 -0
  26. package/dist/server/server/agent/agent-response-loop.d.ts +72 -0
  27. package/dist/server/server/agent/agent-response-loop.js +333 -0
  28. package/dist/server/server/agent/agent-sdk-types.d.ts +736 -0
  29. package/dist/server/server/agent/agent-sdk-types.js +22 -0
  30. package/dist/server/server/agent/agent-storage.d.ts +147 -0
  31. package/dist/server/server/agent/agent-storage.js +326 -0
  32. package/dist/server/server/agent/agent-stream-coalescer.d.ts +41 -0
  33. package/dist/server/server/agent/agent-stream-coalescer.js +166 -0
  34. package/dist/server/server/agent/agent-timeline-store-types.d.ts +50 -0
  35. package/dist/server/server/agent/agent-timeline-store-types.js +2 -0
  36. package/dist/server/server/agent/agent-timeline-store.d.ts +27 -0
  37. package/dist/server/server/agent/agent-timeline-store.js +230 -0
  38. package/dist/server/server/agent/audio-utils.d.ts +3 -0
  39. package/dist/server/server/agent/audio-utils.js +19 -0
  40. package/dist/server/server/agent/create-agent/create.d.ts +91 -0
  41. package/dist/server/server/agent/create-agent/create.js +370 -0
  42. package/dist/server/server/agent/create-agent-lifecycle-dispatch.d.ts +54 -0
  43. package/dist/server/server/agent/create-agent-lifecycle-dispatch.js +152 -0
  44. package/dist/server/server/agent/create-agent-mode.d.ts +13 -0
  45. package/dist/server/server/agent/create-agent-mode.js +62 -0
  46. package/dist/server/server/agent/create-agent-title.d.ts +10 -0
  47. package/dist/server/server/agent/create-agent-title.js +34 -0
  48. package/dist/server/server/agent/dictation-debug.d.ts +13 -0
  49. package/dist/server/server/agent/dictation-debug.js +50 -0
  50. package/dist/server/server/agent/effort-levels.d.ts +2 -0
  51. package/dist/server/server/agent/effort-levels.js +7 -0
  52. package/dist/server/server/agent/foreground-run-state.d.ts +50 -0
  53. package/dist/server/server/agent/foreground-run-state.js +160 -0
  54. package/dist/server/server/agent/import-sessions.d.ts +47 -0
  55. package/dist/server/server/agent/import-sessions.js +145 -0
  56. package/dist/server/server/agent/lifecycle-command.d.ts +73 -0
  57. package/dist/server/server/agent/lifecycle-command.js +92 -0
  58. package/dist/server/server/agent/mcp-server.d.ts +5 -0
  59. package/dist/server/server/agent/mcp-server.js +66 -0
  60. package/dist/server/server/agent/mcp-shared.d.ts +192 -0
  61. package/dist/server/server/agent/mcp-shared.js +201 -0
  62. package/dist/server/server/agent/pcm16-resampler.d.ts +14 -0
  63. package/dist/server/server/agent/pcm16-resampler.js +63 -0
  64. package/dist/server/server/agent/permission-response.d.ts +15 -0
  65. package/dist/server/server/agent/permission-response.js +14 -0
  66. package/dist/server/server/agent/personality-stats-store.d.ts +23 -0
  67. package/dist/server/server/agent/personality-stats-store.js +65 -0
  68. package/dist/server/server/agent/prompt-attachments.d.ts +7 -0
  69. package/dist/server/server/agent/prompt-attachments.js +117 -0
  70. package/dist/server/server/agent/provider-history-timestamps.d.ts +2 -0
  71. package/dist/server/server/agent/provider-history-timestamps.js +16 -0
  72. package/dist/server/server/agent/provider-launch-config.d.ts +43 -0
  73. package/dist/server/server/agent/provider-launch-config.js +167 -0
  74. package/dist/server/server/agent/provider-notices.d.ts +3 -0
  75. package/dist/server/server/agent/provider-notices.js +5 -0
  76. package/dist/server/server/agent/provider-registry.d.ts +41 -0
  77. package/dist/server/server/agent/provider-registry.js +532 -0
  78. package/dist/server/server/agent/provider-session-import.d.ts +10 -0
  79. package/dist/server/server/agent/provider-session-import.js +49 -0
  80. package/dist/server/server/agent/provider-snapshot-manager.d.ts +142 -0
  81. package/dist/server/server/agent/provider-snapshot-manager.js +690 -0
  82. package/dist/server/server/agent/providers/acp-agent.d.ts +353 -0
  83. package/dist/server/server/agent/providers/acp-agent.js +2439 -0
  84. package/dist/server/server/agent/providers/claude/agent.d.ts +66 -0
  85. package/dist/server/server/agent/providers/claude/agent.js +4535 -0
  86. package/dist/server/server/agent/providers/claude/feature-definitions.d.ts +8 -0
  87. package/dist/server/server/agent/providers/claude/feature-definitions.js +24 -0
  88. package/dist/server/server/agent/providers/claude/model-manifest.d.ts +90 -0
  89. package/dist/server/server/agent/providers/claude/model-manifest.js +205 -0
  90. package/dist/server/server/agent/providers/claude/models.d.ts +11 -0
  91. package/dist/server/server/agent/providers/claude/models.js +97 -0
  92. package/dist/server/server/agent/providers/claude/partial-json.d.ts +5 -0
  93. package/dist/server/server/agent/providers/claude/partial-json.js +306 -0
  94. package/dist/server/server/agent/providers/claude/project-dir.d.ts +6 -0
  95. package/dist/server/server/agent/providers/claude/project-dir.js +57 -0
  96. package/dist/server/server/agent/providers/claude/query.d.ts +17 -0
  97. package/dist/server/server/agent/providers/claude/query.js +86 -0
  98. package/dist/server/server/agent/providers/claude/rewind.d.ts +30 -0
  99. package/dist/server/server/agent/providers/claude/rewind.js +30 -0
  100. package/dist/server/server/agent/providers/claude/sidechain-tracker.d.ts +22 -0
  101. package/dist/server/server/agent/providers/claude/sidechain-tracker.js +232 -0
  102. package/dist/server/server/agent/providers/claude/task-notification-tool-call.d.ts +35 -0
  103. package/dist/server/server/agent/providers/claude/task-notification-tool-call.js +272 -0
  104. package/dist/server/server/agent/providers/claude/test-rewind-claude-sdk.d.ts +24 -0
  105. package/dist/server/server/agent/providers/claude/test-rewind-claude-sdk.js +23 -0
  106. package/dist/server/server/agent/providers/claude/tool-call-detail-parser.d.ts +3 -0
  107. package/dist/server/server/agent/providers/claude/tool-call-detail-parser.js +130 -0
  108. package/dist/server/server/agent/providers/claude/tool-call-mapper.d.ts +16 -0
  109. package/dist/server/server/agent/providers/claude/tool-call-mapper.js +129 -0
  110. package/dist/server/server/agent/providers/codex/app-server-transport.d.ts +90 -0
  111. package/dist/server/server/agent/providers/codex/app-server-transport.js +262 -0
  112. package/dist/server/server/agent/providers/codex/rewind.d.ts +21 -0
  113. package/dist/server/server/agent/providers/codex/rewind.js +46 -0
  114. package/dist/server/server/agent/providers/codex/test-utils/fake-app-server.d.ts +36 -0
  115. package/dist/server/server/agent/providers/codex/test-utils/fake-app-server.js +217 -0
  116. package/dist/server/server/agent/providers/codex/tool-call-detail-parser.d.ts +12 -0
  117. package/dist/server/server/agent/providers/codex/tool-call-detail-parser.js +104 -0
  118. package/dist/server/server/agent/providers/codex/tool-call-mapper.d.ts +24 -0
  119. package/dist/server/server/agent/providers/codex/tool-call-mapper.js +830 -0
  120. package/dist/server/server/agent/providers/codex-app-server-agent.d.ts +308 -0
  121. package/dist/server/server/agent/providers/codex-app-server-agent.js +4515 -0
  122. package/dist/server/server/agent/providers/codex-feature-definitions.d.ts +11 -0
  123. package/dist/server/server/agent/providers/codex-feature-definitions.js +45 -0
  124. package/dist/server/server/agent/providers/copilot-acp-agent.d.ts +26 -0
  125. package/dist/server/server/agent/providers/copilot-acp-agent.js +188 -0
  126. package/dist/server/server/agent/providers/cursor-acp-agent.d.ts +15 -0
  127. package/dist/server/server/agent/providers/cursor-acp-agent.js +18 -0
  128. package/dist/server/server/agent/providers/diagnostic-utils.d.ts +36 -0
  129. package/dist/server/server/agent/providers/diagnostic-utils.js +355 -0
  130. package/dist/server/server/agent/providers/generic-acp-agent.d.ts +42 -0
  131. package/dist/server/server/agent/providers/generic-acp-agent.js +160 -0
  132. package/dist/server/server/agent/providers/kiro-acp-agent.d.ts +17 -0
  133. package/dist/server/server/agent/providers/kiro-acp-agent.js +78 -0
  134. package/dist/server/server/agent/providers/mock-load-test-agent.d.ts +85 -0
  135. package/dist/server/server/agent/providers/mock-load-test-agent.js +1010 -0
  136. package/dist/server/server/agent/providers/mock-slow-provider.d.ts +14 -0
  137. package/dist/server/server/agent/providers/mock-slow-provider.js +39 -0
  138. package/dist/server/server/agent/providers/openai-compat-agent.d.ts +422 -0
  139. package/dist/server/server/agent/providers/openai-compat-agent.js +2536 -0
  140. package/dist/server/server/agent/providers/openai-compat-feature-definitions.d.ts +40 -0
  141. package/dist/server/server/agent/providers/openai-compat-feature-definitions.js +82 -0
  142. package/dist/server/server/agent/providers/openai-compat-mcp.d.ts +87 -0
  143. package/dist/server/server/agent/providers/openai-compat-mcp.js +353 -0
  144. package/dist/server/server/agent/providers/openai-compat-otto-tool-permissions.d.ts +29 -0
  145. package/dist/server/server/agent/providers/openai-compat-otto-tool-permissions.js +96 -0
  146. package/dist/server/server/agent/providers/openai-compat-tools.d.ts +69 -0
  147. package/dist/server/server/agent/providers/openai-compat-tools.js +1224 -0
  148. package/dist/server/server/agent/providers/opencode/paths.d.ts +2 -0
  149. package/dist/server/server/agent/providers/opencode/paths.js +7 -0
  150. package/dist/server/server/agent/providers/opencode/rewind.d.ts +18 -0
  151. package/dist/server/server/agent/providers/opencode/rewind.js +14 -0
  152. package/dist/server/server/agent/providers/opencode/server-manager.d.ts +91 -0
  153. package/dist/server/server/agent/providers/opencode/server-manager.js +425 -0
  154. package/dist/server/server/agent/providers/opencode/test-server-manager.d.ts +25 -0
  155. package/dist/server/server/agent/providers/opencode/test-server-manager.js +39 -0
  156. package/dist/server/server/agent/providers/opencode/test-utils/test-opencode-harness.d.ts +92 -0
  157. package/dist/server/server/agent/providers/opencode/test-utils/test-opencode-harness.js +260 -0
  158. package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.d.ts +3 -0
  159. package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.js +256 -0
  160. package/dist/server/server/agent/providers/opencode/tool-call-mapper.d.ts +13 -0
  161. package/dist/server/server/agent/providers/opencode/tool-call-mapper.js +53 -0
  162. package/dist/server/server/agent/providers/opencode-agent.d.ts +286 -0
  163. package/dist/server/server/agent/providers/opencode-agent.js +2830 -0
  164. package/dist/server/server/agent/providers/pi/agent.d.ts +132 -0
  165. package/dist/server/server/agent/providers/pi/agent.js +1649 -0
  166. package/dist/server/server/agent/providers/pi/cli-runtime.d.ts +21 -0
  167. package/dist/server/server/agent/providers/pi/cli-runtime.js +261 -0
  168. package/dist/server/server/agent/providers/pi/history-mapper.d.ts +9 -0
  169. package/dist/server/server/agent/providers/pi/history-mapper.js +140 -0
  170. package/dist/server/server/agent/providers/pi/rewind.d.ts +8 -0
  171. package/dist/server/server/agent/providers/pi/rewind.js +8 -0
  172. package/dist/server/server/agent/providers/pi/rpc-types.d.ts +208 -0
  173. package/dist/server/server/agent/providers/pi/rpc-types.js +2 -0
  174. package/dist/server/server/agent/providers/pi/runtime.d.ts +57 -0
  175. package/dist/server/server/agent/providers/pi/runtime.js +56 -0
  176. package/dist/server/server/agent/providers/pi/session-descriptor.d.ts +16 -0
  177. package/dist/server/server/agent/providers/pi/session-descriptor.js +346 -0
  178. package/dist/server/server/agent/providers/pi/test-utils/fake-pi.d.ts +83 -0
  179. package/dist/server/server/agent/providers/pi/test-utils/fake-pi.js +184 -0
  180. package/dist/server/server/agent/providers/pi/tool-call-mapper.d.ts +112 -0
  181. package/dist/server/server/agent/providers/pi/tool-call-mapper.js +284 -0
  182. package/dist/server/server/agent/providers/provider-image-output.d.ts +25 -0
  183. package/dist/server/server/agent/providers/provider-image-output.js +111 -0
  184. package/dist/server/server/agent/providers/provider-runner.d.ts +27 -0
  185. package/dist/server/server/agent/providers/provider-runner.js +81 -0
  186. package/dist/server/server/agent/providers/test-utils/session-stream-adapter.d.ts +3 -0
  187. package/dist/server/server/agent/providers/test-utils/session-stream-adapter.js +60 -0
  188. package/dist/server/server/agent/providers/tool-call-detail-primitives.d.ts +884 -0
  189. package/dist/server/server/agent/providers/tool-call-detail-primitives.js +778 -0
  190. package/dist/server/server/agent/providers/tool-call-mapper-utils.d.ts +25 -0
  191. package/dist/server/server/agent/providers/tool-call-mapper-utils.js +208 -0
  192. package/dist/server/server/agent/providers/trae-acp-agent.d.ts +15 -0
  193. package/dist/server/server/agent/providers/trae-acp-agent.js +18 -0
  194. package/dist/server/server/agent/recordings-debug.d.ts +3 -0
  195. package/dist/server/server/agent/recordings-debug.js +19 -0
  196. package/dist/server/server/agent/rewind/rewind.d.ts +10 -0
  197. package/dist/server/server/agent/rewind/rewind.js +29 -0
  198. package/dist/server/server/agent/rewind/test-rewind-session.d.ts +48 -0
  199. package/dist/server/server/agent/rewind/test-rewind-session.js +88 -0
  200. package/dist/server/server/agent/runtime-mcp-config.d.ts +14 -0
  201. package/dist/server/server/agent/runtime-mcp-config.js +53 -0
  202. package/dist/server/server/agent/structured-generation-providers.d.ts +29 -0
  203. package/dist/server/server/agent/structured-generation-providers.js +236 -0
  204. package/dist/server/server/agent/stt-debug.d.ts +10 -0
  205. package/dist/server/server/agent/stt-debug.js +33 -0
  206. package/dist/server/server/agent/stt-manager.d.ts +38 -0
  207. package/dist/server/server/agent/stt-manager.js +246 -0
  208. package/dist/server/server/agent/system-prompt.d.ts +2 -0
  209. package/dist/server/server/agent/system-prompt.js +8 -0
  210. package/dist/server/server/agent/timeline-append.d.ts +10 -0
  211. package/dist/server/server/agent/timeline-append.js +27 -0
  212. package/dist/server/server/agent/timeline-projection.d.ts +71 -0
  213. package/dist/server/server/agent/timeline-projection.js +373 -0
  214. package/dist/server/server/agent/tools/otto-tools.d.ts +80 -0
  215. package/dist/server/server/agent/tools/otto-tools.js +2912 -0
  216. package/dist/server/server/agent/tools/types.d.ts +36 -0
  217. package/dist/server/server/agent/tools/types.js +2 -0
  218. package/dist/server/server/agent/tts-debug.d.ts +8 -0
  219. package/dist/server/server/agent/tts-debug.js +24 -0
  220. package/dist/server/server/agent/tts-manager.d.ts +41 -0
  221. package/dist/server/server/agent/tts-manager.js +375 -0
  222. package/dist/server/server/agent-attention-policy.d.ts +29 -0
  223. package/dist/server/server/agent-attention-policy.js +36 -0
  224. package/dist/server/server/artifact/artifact-prompt.d.ts +2 -0
  225. package/dist/server/server/artifact/artifact-prompt.js +15 -0
  226. package/dist/server/server/artifact/artifact-service.d.ts +91 -0
  227. package/dist/server/server/artifact/artifact-service.js +419 -0
  228. package/dist/server/server/artifact/artifact-store.d.ts +24 -0
  229. package/dist/server/server/artifact/artifact-store.js +168 -0
  230. package/dist/server/server/artifact/artifact-watcher.d.ts +34 -0
  231. package/dist/server/server/artifact/artifact-watcher.js +146 -0
  232. package/dist/server/server/artifact/html-validator.d.ts +26 -0
  233. package/dist/server/server/artifact/html-validator.js +92 -0
  234. package/dist/server/server/atomic-file.d.ts +5 -0
  235. package/dist/server/server/atomic-file.js +19 -0
  236. package/dist/server/server/auth.d.ts +38 -0
  237. package/dist/server/server/auth.js +143 -0
  238. package/dist/server/server/auto-archive-on-merge/archive-if-safe.d.ts +40 -0
  239. package/dist/server/server/auto-archive-on-merge/archive-if-safe.js +92 -0
  240. package/dist/server/server/auto-archive-on-merge/index.d.ts +8 -0
  241. package/dist/server/server/auto-archive-on-merge/index.js +15 -0
  242. package/dist/server/server/bootstrap.d.ts +127 -0
  243. package/dist/server/server/bootstrap.js +1331 -0
  244. package/dist/server/server/browser-tools/broker.d.ts +45 -0
  245. package/dist/server/server/browser-tools/broker.js +390 -0
  246. package/dist/server/server/browser-tools/errors.d.ts +22 -0
  247. package/dist/server/server/browser-tools/errors.js +27 -0
  248. package/dist/server/server/browser-tools/policy.d.ts +10 -0
  249. package/dist/server/server/browser-tools/policy.js +16 -0
  250. package/dist/server/server/browser-tools/tools.d.ts +24 -0
  251. package/dist/server/server/browser-tools/tools.js +967 -0
  252. package/dist/server/server/chat/chat-mentions.d.ts +47 -0
  253. package/dist/server/server/chat/chat-mentions.js +113 -0
  254. package/dist/server/server/chat/chat-service.d.ts +78 -0
  255. package/dist/server/server/chat/chat-service.js +337 -0
  256. package/dist/server/server/checkout/status-projection.d.ts +19 -0
  257. package/dist/server/server/checkout/status-projection.js +117 -0
  258. package/dist/server/server/checkout-diff-manager.d.ts +41 -0
  259. package/dist/server/server/checkout-diff-manager.js +189 -0
  260. package/dist/server/server/checkout-git-utils.d.ts +11 -0
  261. package/dist/server/server/checkout-git-utils.js +34 -0
  262. package/dist/server/server/client-message-id.d.ts +3 -0
  263. package/dist/server/server/client-message-id.js +12 -0
  264. package/dist/server/server/config.d.ts +22 -0
  265. package/dist/server/server/config.js +330 -0
  266. package/dist/server/server/connection-offer.d.ts +20 -0
  267. package/dist/server/server/connection-offer.js +59 -0
  268. package/dist/server/server/daemon-config-store.d.ts +44 -0
  269. package/dist/server/server/daemon-config-store.js +530 -0
  270. package/dist/server/server/daemon-keypair.d.ts +8 -0
  271. package/dist/server/server/daemon-keypair.js +42 -0
  272. package/dist/server/server/daemon-version.d.ts +5 -0
  273. package/dist/server/server/daemon-version.js +22 -0
  274. package/dist/server/server/daemon-worker.d.ts +2 -0
  275. package/dist/server/server/daemon-worker.js +251 -0
  276. package/dist/server/server/dictation/dictation-stream-manager.d.ts +87 -0
  277. package/dist/server/server/dictation/dictation-stream-manager.js +572 -0
  278. package/dist/server/server/exports.d.ts +24 -0
  279. package/dist/server/server/exports.js +24 -0
  280. package/dist/server/server/file-download/token-store.d.ts +24 -0
  281. package/dist/server/server/file-download/token-store.js +40 -0
  282. package/dist/server/server/file-explorer/code-index.d.ts +28 -0
  283. package/dist/server/server/file-explorer/code-index.js +127 -0
  284. package/dist/server/server/file-explorer/file-search.d.ts +72 -0
  285. package/dist/server/server/file-explorer/file-search.js +297 -0
  286. package/dist/server/server/file-explorer/file-watcher.d.ts +40 -0
  287. package/dist/server/server/file-explorer/file-watcher.js +0 -0
  288. package/dist/server/server/file-explorer/gitignore.d.ts +39 -0
  289. package/dist/server/server/file-explorer/gitignore.js +191 -0
  290. package/dist/server/server/file-explorer/service.d.ts +103 -0
  291. package/dist/server/server/file-explorer/service.js +420 -0
  292. package/dist/server/server/file-upload/index.d.ts +27 -0
  293. package/dist/server/server/file-upload/index.js +158 -0
  294. package/dist/server/server/hostnames.d.ts +13 -0
  295. package/dist/server/server/hostnames.js +94 -0
  296. package/dist/server/server/json-utils.d.ts +11 -0
  297. package/dist/server/server/json-utils.js +45 -0
  298. package/dist/server/server/lifecycle-reasons.d.ts +4 -0
  299. package/dist/server/server/lifecycle-reasons.js +6 -0
  300. package/dist/server/server/logger.d.ts +29 -0
  301. package/dist/server/server/logger.js +125 -0
  302. package/dist/server/server/loop-service.d.ts +234 -0
  303. package/dist/server/server/loop-service.js +804 -0
  304. package/dist/server/server/managed-processes/managed-processes.d.ts +76 -0
  305. package/dist/server/server/managed-processes/managed-processes.js +326 -0
  306. package/dist/server/server/messages.d.ts +9 -0
  307. package/dist/server/server/messages.js +29 -0
  308. package/dist/server/server/migrations/backfill-workspace-id.migration.d.ts +9 -0
  309. package/dist/server/server/migrations/backfill-workspace-id.migration.js +64 -0
  310. package/dist/server/server/otto-env.d.ts +13 -0
  311. package/dist/server/server/otto-env.js +53 -0
  312. package/dist/server/server/otto-home.d.ts +2 -0
  313. package/dist/server/server/otto-home.js +19 -0
  314. package/dist/server/server/otto-worktree-service.d.ts +52 -0
  315. package/dist/server/server/otto-worktree-service.js +294 -0
  316. package/dist/server/server/package-version.d.ts +19 -0
  317. package/dist/server/server/package-version.js +60 -0
  318. package/dist/server/server/pagination/cursor.d.ts +16 -0
  319. package/dist/server/server/pagination/cursor.js +62 -0
  320. package/dist/server/server/pagination/sortable-pager.d.ts +24 -0
  321. package/dist/server/server/pagination/sortable-pager.js +68 -0
  322. package/dist/server/server/pairing-offer.d.ts +18 -0
  323. package/dist/server/server/pairing-offer.js +47 -0
  324. package/dist/server/server/pairing-qr.d.ts +7 -0
  325. package/dist/server/server/pairing-qr.js +45 -0
  326. package/dist/server/server/path-utils.d.ts +5 -0
  327. package/dist/server/server/path-utils.js +34 -0
  328. package/dist/server/server/persisted-config.d.ts +417 -0
  329. package/dist/server/server/persisted-config.js +471 -0
  330. package/dist/server/server/persistence-hooks.d.ts +31 -0
  331. package/dist/server/server/persistence-hooks.js +93 -0
  332. package/dist/server/server/pid-lock.d.ts +32 -0
  333. package/dist/server/server/pid-lock.js +170 -0
  334. package/dist/server/server/preview/dev-server-manager.d.ts +108 -0
  335. package/dist/server/server/preview/dev-server-manager.js +426 -0
  336. package/dist/server/server/preview/launch-config.d.ts +37 -0
  337. package/dist/server/server/preview/launch-config.js +63 -0
  338. package/dist/server/server/preview/preview-tools.d.ts +30 -0
  339. package/dist/server/server/preview/preview-tools.js +249 -0
  340. package/dist/server/server/private-files.d.ts +6 -0
  341. package/dist/server/server/private-files.js +37 -0
  342. package/dist/server/server/process-diagnostics.d.ts +17 -0
  343. package/dist/server/server/process-diagnostics.js +22 -0
  344. package/dist/server/server/push/notifications.d.ts +9 -0
  345. package/dist/server/server/push/notifications.js +15 -0
  346. package/dist/server/server/push/push-service.d.ts +20 -0
  347. package/dist/server/server/push/push-service.js +66 -0
  348. package/dist/server/server/push/token-store.d.ts +18 -0
  349. package/dist/server/server/push/token-store.js +68 -0
  350. package/dist/server/server/relay-transport.d.ts +31 -0
  351. package/dist/server/server/relay-transport.js +514 -0
  352. package/dist/server/server/resolve-workspace-id-for-path.d.ts +3 -0
  353. package/dist/server/server/resolve-workspace-id-for-path.js +41 -0
  354. package/dist/server/server/resolve-worktree-creation-intent.d.ts +32 -0
  355. package/dist/server/server/resolve-worktree-creation-intent.js +121 -0
  356. package/dist/server/server/schedule/cron.d.ts +4 -0
  357. package/dist/server/server/schedule/cron.js +81 -0
  358. package/dist/server/server/schedule/service.d.ts +89 -0
  359. package/dist/server/server/schedule/service.js +882 -0
  360. package/dist/server/server/schedule/store.d.ts +27 -0
  361. package/dist/server/server/schedule/store.js +190 -0
  362. package/dist/server/server/script-health-monitor.d.ts +39 -0
  363. package/dist/server/server/script-health-monitor.js +159 -0
  364. package/dist/server/server/script-proxy.d.ts +3 -0
  365. package/dist/server/server/script-proxy.js +2 -0
  366. package/dist/server/server/script-route-branch-handler.d.ts +10 -0
  367. package/dist/server/server/script-route-branch-handler.js +11 -0
  368. package/dist/server/server/script-status-projection.d.ts +36 -0
  369. package/dist/server/server/script-status-projection.js +200 -0
  370. package/dist/server/server/server-id.d.ts +17 -0
  371. package/dist/server/server/server-id.js +68 -0
  372. package/dist/server/server/service-proxy.d.ts +237 -0
  373. package/dist/server/server/service-proxy.js +714 -0
  374. package/dist/server/server/session/agent-config/agent-config-session.d.ts +59 -0
  375. package/dist/server/server/session/agent-config/agent-config-session.js +110 -0
  376. package/dist/server/server/session/agent-updates/agent-updates-service.d.ts +65 -0
  377. package/dist/server/server/session/agent-updates/agent-updates-service.js +232 -0
  378. package/dist/server/server/session/artifact/artifact-session.d.ts +45 -0
  379. package/dist/server/server/session/artifact/artifact-session.js +293 -0
  380. package/dist/server/server/session/chat/chat-schedule-loop-session.d.ts +120 -0
  381. package/dist/server/server/session/chat/chat-schedule-loop-session.js +489 -0
  382. package/dist/server/server/session/checkout/checkout-session.d.ts +146 -0
  383. package/dist/server/server/session/checkout/checkout-session.js +1000 -0
  384. package/dist/server/server/session/checkout/git-metadata-generator.d.ts +53 -0
  385. package/dist/server/server/session/checkout/git-metadata-generator.js +159 -0
  386. package/dist/server/server/session/daemon/daemon-self-update-session-controller.d.ts +32 -0
  387. package/dist/server/server/session/daemon/daemon-self-update-session-controller.js +88 -0
  388. package/dist/server/server/session/daemon/daemon-self-updater.d.ts +32 -0
  389. package/dist/server/server/session/daemon/daemon-self-updater.js +56 -0
  390. package/dist/server/server/session/daemon/daemon-session.d.ts +76 -0
  391. package/dist/server/server/session/daemon/daemon-session.js +148 -0
  392. package/dist/server/server/session/daemon/diagnostics.d.ts +41 -0
  393. package/dist/server/server/session/daemon/diagnostics.js +431 -0
  394. package/dist/server/server/session/daemon/install-origin.d.ts +7 -0
  395. package/dist/server/server/session/daemon/install-origin.js +64 -0
  396. package/dist/server/server/session/daemon/npm-global-cli.d.ts +29 -0
  397. package/dist/server/server/session/daemon/npm-global-cli.js +98 -0
  398. package/dist/server/server/session/files/workspace-files-session.d.ts +60 -0
  399. package/dist/server/server/session/files/workspace-files-session.js +518 -0
  400. package/dist/server/server/session/git-mutation/git-mutation-service.d.ts +34 -0
  401. package/dist/server/server/session/git-mutation/git-mutation-service.js +71 -0
  402. package/dist/server/server/session/project-config/project-config-session.d.ts +34 -0
  403. package/dist/server/server/session/project-config/project-config-session.js +125 -0
  404. package/dist/server/server/session/provider/provider-catalog-session.d.ts +74 -0
  405. package/dist/server/server/session/provider/provider-catalog-session.js +343 -0
  406. package/dist/server/server/session/voice/voice-session.d.ts +167 -0
  407. package/dist/server/server/session/voice/voice-session.js +912 -0
  408. package/dist/server/server/session/voice/voice-turn-controller.d.ts +38 -0
  409. package/dist/server/server/session/voice/voice-turn-controller.js +393 -0
  410. package/dist/server/server/session/workspace-git-observer/workspace-git-observer-service.d.ts +36 -0
  411. package/dist/server/server/session/workspace-git-observer/workspace-git-observer-service.js +134 -0
  412. package/dist/server/server/session/workspace-provisioning/workspace-provisioning-service.d.ts +34 -0
  413. package/dist/server/server/session/workspace-provisioning/workspace-provisioning-service.js +190 -0
  414. package/dist/server/server/session/workspace-scripts/workspace-scripts-service.d.ts +41 -0
  415. package/dist/server/server/session/workspace-scripts/workspace-scripts-service.js +100 -0
  416. package/dist/server/server/session.d.ts +450 -0
  417. package/dist/server/server/session.js +4763 -0
  418. package/dist/server/server/speech/audio.d.ts +10 -0
  419. package/dist/server/server/speech/audio.js +101 -0
  420. package/dist/server/server/speech/provider-resolver.d.ts +3 -0
  421. package/dist/server/server/speech/provider-resolver.js +7 -0
  422. package/dist/server/server/speech/providers/local/config.d.ts +30 -0
  423. package/dist/server/server/speech/providers/local/config.js +133 -0
  424. package/dist/server/server/speech/providers/local/models.d.ts +13 -0
  425. package/dist/server/server/speech/providers/local/models.js +21 -0
  426. package/dist/server/server/speech/providers/local/runtime.d.ts +31 -0
  427. package/dist/server/server/speech/providers/local/runtime.js +135 -0
  428. package/dist/server/server/speech/providers/local/sherpa/assets/silero_vad.onnx +0 -0
  429. package/dist/server/server/speech/providers/local/sherpa/model-catalog.d.ts +109 -0
  430. package/dist/server/server/speech/providers/local/sherpa/model-catalog.js +129 -0
  431. package/dist/server/server/speech/providers/local/sherpa/model-downloader.d.ts +16 -0
  432. package/dist/server/server/speech/providers/local/sherpa/model-downloader.js +195 -0
  433. package/dist/server/server/speech/providers/local/sherpa/sherpa-offline-recognizer.d.ts +49 -0
  434. package/dist/server/server/speech/providers/local/sherpa/sherpa-offline-recognizer.js +73 -0
  435. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.d.ts +9 -0
  436. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.js +107 -0
  437. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.d.ts +28 -0
  438. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.js +137 -0
  439. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-stt.d.ts +21 -0
  440. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-stt.js +133 -0
  441. package/dist/server/server/speech/providers/local/sherpa/sherpa-runtime-env.d.ts +18 -0
  442. package/dist/server/server/speech/providers/local/sherpa/sherpa-runtime-env.js +84 -0
  443. package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.d.ts +24 -0
  444. package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.js +145 -0
  445. package/dist/server/server/speech/providers/local/sherpa/silero-vad-provider.d.ts +19 -0
  446. package/dist/server/server/speech/providers/local/sherpa/silero-vad-provider.js +49 -0
  447. package/dist/server/server/speech/providers/local/sherpa/silero-vad-session.d.ts +38 -0
  448. package/dist/server/server/speech/providers/local/sherpa/silero-vad-session.js +176 -0
  449. package/dist/server/server/speech/providers/local/sherpa/tts-voices.d.ts +10 -0
  450. package/dist/server/server/speech/providers/local/sherpa/tts-voices.js +86 -0
  451. package/dist/server/server/speech/providers/local/worker-bytes.d.ts +4 -0
  452. package/dist/server/server/speech/providers/local/worker-bytes.js +9 -0
  453. package/dist/server/server/speech/providers/local/worker-client.d.ts +93 -0
  454. package/dist/server/server/speech/providers/local/worker-client.js +591 -0
  455. package/dist/server/server/speech/providers/local/worker-process.d.ts +2 -0
  456. package/dist/server/server/speech/providers/local/worker-process.js +270 -0
  457. package/dist/server/server/speech/providers/local/worker-protocol.d.ts +96 -0
  458. package/dist/server/server/speech/providers/local/worker-protocol.js +2 -0
  459. package/dist/server/server/speech/providers/openai/config.d.ts +19 -0
  460. package/dist/server/server/speech/providers/openai/config.js +160 -0
  461. package/dist/server/server/speech/providers/openai/runtime.d.ts +29 -0
  462. package/dist/server/server/speech/providers/openai/runtime.js +102 -0
  463. package/dist/server/server/speech/providers/openai/stt.d.ts +23 -0
  464. package/dist/server/server/speech/providers/openai/stt.js +209 -0
  465. package/dist/server/server/speech/providers/openai/tts.d.ts +20 -0
  466. package/dist/server/server/speech/providers/openai/tts.js +70 -0
  467. package/dist/server/server/speech/speech-config-resolver.d.ts +11 -0
  468. package/dist/server/server/speech/speech-config-resolver.js +132 -0
  469. package/dist/server/server/speech/speech-provider.d.ts +71 -0
  470. package/dist/server/server/speech/speech-provider.js +2 -0
  471. package/dist/server/server/speech/speech-runtime.d.ts +67 -0
  472. package/dist/server/server/speech/speech-runtime.js +615 -0
  473. package/dist/server/server/speech/speech-settings-options.d.ts +14 -0
  474. package/dist/server/server/speech/speech-settings-options.js +73 -0
  475. package/dist/server/server/speech/speech-types.d.ts +22 -0
  476. package/dist/server/server/speech/speech-types.js +8 -0
  477. package/dist/server/server/speech/turn-detection-provider.d.ts +23 -0
  478. package/dist/server/server/speech/turn-detection-provider.js +2 -0
  479. package/dist/server/server/utils/diff-highlighter.d.ts +57 -0
  480. package/dist/server/server/utils/diff-highlighter.js +279 -0
  481. package/dist/server/server/voice-config.d.ts +15 -0
  482. package/dist/server/server/voice-config.js +54 -0
  483. package/dist/server/server/voice-permission-policy.d.ts +4 -0
  484. package/dist/server/server/voice-permission-policy.js +13 -0
  485. package/dist/server/server/voice-types.d.ts +12 -0
  486. package/dist/server/server/voice-types.js +2 -0
  487. package/dist/server/server/web-ui.d.ts +10 -0
  488. package/dist/server/server/web-ui.js +205 -0
  489. package/dist/server/server/websocket/runtime-metrics.d.ts +94 -0
  490. package/dist/server/server/websocket/runtime-metrics.js +148 -0
  491. package/dist/server/server/websocket-server.d.ts +187 -0
  492. package/dist/server/server/websocket-server.js +1766 -0
  493. package/dist/server/server/workspace-archive-service.d.ts +65 -0
  494. package/dist/server/server/workspace-archive-service.js +229 -0
  495. package/dist/server/server/workspace-auto-name.d.ts +55 -0
  496. package/dist/server/server/workspace-auto-name.js +128 -0
  497. package/dist/server/server/workspace-bootstrap-dedupe.d.ts +34 -0
  498. package/dist/server/server/workspace-bootstrap-dedupe.js +23 -0
  499. package/dist/server/server/workspace-directory.d.ts +93 -0
  500. package/dist/server/server/workspace-directory.js +422 -0
  501. package/dist/server/server/workspace-git-metadata.d.ts +24 -0
  502. package/dist/server/server/workspace-git-metadata.js +55 -0
  503. package/dist/server/server/workspace-git-service.d.ts +270 -0
  504. package/dist/server/server/workspace-git-service.js +1423 -0
  505. package/dist/server/server/workspace-reconciliation-service.d.ts +57 -0
  506. package/dist/server/server/workspace-reconciliation-service.js +278 -0
  507. package/dist/server/server/workspace-registry-bootstrap.d.ts +13 -0
  508. package/dist/server/server/workspace-registry-bootstrap.js +121 -0
  509. package/dist/server/server/workspace-registry-model.d.ts +55 -0
  510. package/dist/server/server/workspace-registry-model.js +190 -0
  511. package/dist/server/server/workspace-registry.d.ts +117 -0
  512. package/dist/server/server/workspace-registry.js +194 -0
  513. package/dist/server/server/workspace-script-runtime-store.d.ts +28 -0
  514. package/dist/server/server/workspace-script-runtime-store.js +78 -0
  515. package/dist/server/server/workspace-service-env.d.ts +18 -0
  516. package/dist/server/server/workspace-service-env.js +85 -0
  517. package/dist/server/server/workspace-service-port-registry.d.ts +19 -0
  518. package/dist/server/server/workspace-service-port-registry.js +59 -0
  519. package/dist/server/server/worktree/commands.d.ts +55 -0
  520. package/dist/server/server/worktree/commands.js +107 -0
  521. package/dist/server/server/worktree-bootstrap.d.ts +76 -0
  522. package/dist/server/server/worktree-bootstrap.js +720 -0
  523. package/dist/server/server/worktree-branch-name-generator.d.ts +35 -0
  524. package/dist/server/server/worktree-branch-name-generator.js +91 -0
  525. package/dist/server/server/worktree-core.d.ts +31 -0
  526. package/dist/server/server/worktree-core.js +105 -0
  527. package/dist/server/server/worktree-errors.d.ts +12 -0
  528. package/dist/server/server/worktree-errors.js +28 -0
  529. package/dist/server/server/worktree-session.d.ts +152 -0
  530. package/dist/server/server/worktree-session.js +466 -0
  531. package/dist/server/services/git-hosting/bitbucket-cloud-service.d.ts +24 -0
  532. package/dist/server/services/git-hosting/bitbucket-cloud-service.js +754 -0
  533. package/dist/server/services/git-hosting/github-hosting-service.d.ts +4 -0
  534. package/dist/server/services/git-hosting/github-hosting-service.js +11 -0
  535. package/dist/server/services/git-hosting/hosting-http-client.d.ts +20 -0
  536. package/dist/server/services/git-hosting/hosting-http-client.js +131 -0
  537. package/dist/server/services/git-hosting/request-cache.d.ts +20 -0
  538. package/dist/server/services/git-hosting/request-cache.js +68 -0
  539. package/dist/server/services/git-hosting/resolver.d.ts +32 -0
  540. package/dist/server/services/git-hosting/resolver.js +152 -0
  541. package/dist/server/services/git-hosting/router.d.ts +4 -0
  542. package/dist/server/services/git-hosting/router.js +105 -0
  543. package/dist/server/services/git-hosting/status-poller.d.ts +39 -0
  544. package/dist/server/services/git-hosting/status-poller.js +149 -0
  545. package/dist/server/services/git-hosting/types.d.ts +53 -0
  546. package/dist/server/services/git-hosting/types.js +75 -0
  547. package/dist/server/services/github-service.d.ts +339 -0
  548. package/dist/server/services/github-service.js +2109 -0
  549. package/dist/server/services/quota-fetcher/manifest.d.ts +4 -0
  550. package/dist/server/services/quota-fetcher/manifest.js +52 -0
  551. package/dist/server/services/quota-fetcher/provider.d.ts +17 -0
  552. package/dist/server/services/quota-fetcher/provider.js +2 -0
  553. package/dist/server/services/quota-fetcher/providers/claude.d.ts +26 -0
  554. package/dist/server/services/quota-fetcher/providers/claude.js +217 -0
  555. package/dist/server/services/quota-fetcher/providers/codex.d.ts +23 -0
  556. package/dist/server/services/quota-fetcher/providers/codex.js +211 -0
  557. package/dist/server/services/quota-fetcher/providers/copilot.d.ts +17 -0
  558. package/dist/server/services/quota-fetcher/providers/copilot.js +75 -0
  559. package/dist/server/services/quota-fetcher/providers/cursor.d.ts +17 -0
  560. package/dist/server/services/quota-fetcher/providers/cursor.js +123 -0
  561. package/dist/server/services/quota-fetcher/providers/grok.d.ts +18 -0
  562. package/dist/server/services/quota-fetcher/providers/grok.js +89 -0
  563. package/dist/server/services/quota-fetcher/providers/kimi.d.ts +20 -0
  564. package/dist/server/services/quota-fetcher/providers/kimi.js +89 -0
  565. package/dist/server/services/quota-fetcher/providers/minimax.d.ts +29 -0
  566. package/dist/server/services/quota-fetcher/providers/minimax.js +227 -0
  567. package/dist/server/services/quota-fetcher/providers/zai.d.ts +17 -0
  568. package/dist/server/services/quota-fetcher/providers/zai.js +58 -0
  569. package/dist/server/services/quota-fetcher/service.d.ts +28 -0
  570. package/dist/server/services/quota-fetcher/service.js +58 -0
  571. package/dist/server/services/quota-fetcher/usage.d.ts +22 -0
  572. package/dist/server/services/quota-fetcher/usage.js +49 -0
  573. package/dist/server/terminal/activity/terminal-activity-tracker.d.ts +20 -0
  574. package/dist/server/terminal/activity/terminal-activity-tracker.js +59 -0
  575. package/dist/server/terminal/agent-hooks/agent-hook-installer.d.ts +62 -0
  576. package/dist/server/terminal/agent-hooks/agent-hook-installer.js +117 -0
  577. package/dist/server/terminal/agent-hooks/claude/claude-settings.d.ts +7 -0
  578. package/dist/server/terminal/agent-hooks/claude/claude-settings.js +88 -0
  579. package/dist/server/terminal/agent-hooks/claude/claude.d.ts +4 -0
  580. package/dist/server/terminal/agent-hooks/claude/claude.js +47 -0
  581. package/dist/server/terminal/agent-hooks/codex/codex-settings.d.ts +7 -0
  582. package/dist/server/terminal/agent-hooks/codex/codex-settings.js +99 -0
  583. package/dist/server/terminal/agent-hooks/codex/codex.d.ts +4 -0
  584. package/dist/server/terminal/agent-hooks/codex/codex.js +30 -0
  585. package/dist/server/terminal/agent-hooks/opencode/opencode-plugin.d.ts +4 -0
  586. package/dist/server/terminal/agent-hooks/opencode/opencode-plugin.js +46 -0
  587. package/dist/server/terminal/agent-hooks/opencode/opencode.d.ts +3 -0
  588. package/dist/server/terminal/agent-hooks/opencode/opencode.js +23 -0
  589. package/dist/server/terminal/agent-hooks/provider-registry.d.ts +24 -0
  590. package/dist/server/terminal/agent-hooks/provider-registry.js +36 -0
  591. package/dist/server/terminal/agent-hooks/terminal-agent-hook-setting.d.ts +10 -0
  592. package/dist/server/terminal/agent-hooks/terminal-agent-hook-setting.js +26 -0
  593. package/dist/server/terminal/shell-integration/zsh/.zshenv +17 -0
  594. package/dist/server/terminal/shell-integration/zsh/otto-integration.zsh +32 -0
  595. package/dist/server/terminal/terminal-capture.d.ts +12 -0
  596. package/dist/server/terminal/terminal-capture.js +43 -0
  597. package/dist/server/terminal/terminal-manager-factory.d.ts +6 -0
  598. package/dist/server/terminal/terminal-manager-factory.js +5 -0
  599. package/dist/server/terminal/terminal-manager.d.ts +78 -0
  600. package/dist/server/terminal/terminal-manager.js +319 -0
  601. package/dist/server/terminal/terminal-output-coalescer.d.ts +34 -0
  602. package/dist/server/terminal/terminal-output-coalescer.js +73 -0
  603. package/dist/server/terminal/terminal-restore.d.ts +18 -0
  604. package/dist/server/terminal/terminal-restore.js +52 -0
  605. package/dist/server/terminal/terminal-session-controller.d.ts +85 -0
  606. package/dist/server/terminal/terminal-session-controller.js +819 -0
  607. package/dist/server/terminal/terminal-ts-loader.mjs +20 -0
  608. package/dist/server/terminal/terminal-worker-process.d.ts +2 -0
  609. package/dist/server/terminal/terminal-worker-process.js +304 -0
  610. package/dist/server/terminal/terminal-worker-protocol.d.ts +119 -0
  611. package/dist/server/terminal/terminal-worker-protocol.js +2 -0
  612. package/dist/server/terminal/terminal.d.ts +151 -0
  613. package/dist/server/terminal/terminal.js +1155 -0
  614. package/dist/server/terminal/worker-terminal-manager.d.ts +20 -0
  615. package/dist/server/terminal/worker-terminal-manager.js +688 -0
  616. package/dist/server/utils/build-metadata-prompt.d.ts +19 -0
  617. package/dist/server/utils/build-metadata-prompt.js +29 -0
  618. package/dist/server/utils/checkout-git.d.ts +253 -0
  619. package/dist/server/utils/checkout-git.js +2241 -0
  620. package/dist/server/utils/directory-suggestions.d.ts +26 -0
  621. package/dist/server/utils/directory-suggestions.js +830 -0
  622. package/dist/server/utils/git-rev-parse-path.d.ts +3 -0
  623. package/dist/server/utils/git-rev-parse-path.js +21 -0
  624. package/dist/server/utils/github-remote.d.ts +9 -0
  625. package/dist/server/utils/github-remote.js +62 -0
  626. package/dist/server/utils/otto-config-file.d.ts +30 -0
  627. package/dist/server/utils/otto-config-file.js +90 -0
  628. package/dist/server/utils/path.d.ts +18 -0
  629. package/dist/server/utils/path.js +123 -0
  630. package/dist/server/utils/project-icon.d.ts +39 -0
  631. package/dist/server/utils/project-icon.js +364 -0
  632. package/dist/server/utils/promise-timeout.d.ts +9 -0
  633. package/dist/server/utils/promise-timeout.js +25 -0
  634. package/dist/server/utils/run-git-command.d.ts +37 -0
  635. package/dist/server/utils/run-git-command.js +232 -0
  636. package/dist/server/utils/spawn.d.ts +25 -0
  637. package/dist/server/utils/spawn.js +59 -0
  638. package/dist/server/utils/string-command-shell.d.ts +13 -0
  639. package/dist/server/utils/string-command-shell.js +37 -0
  640. package/dist/server/utils/tree-kill.d.ts +18 -0
  641. package/dist/server/utils/tree-kill.js +77 -0
  642. package/dist/server/utils/windows-command.d.ts +15 -0
  643. package/dist/server/utils/windows-command.js +41 -0
  644. package/dist/server/utils/worktree-metadata.d.ts +39 -0
  645. package/dist/server/utils/worktree-metadata.js +174 -0
  646. package/dist/server/utils/worktree.d.ts +205 -0
  647. package/dist/server/utils/worktree.js +1120 -0
  648. package/dist/server/web-ui/_expo/static/css/xterm-3bb1704bf6cb0876640973dc0244b4cb.css +1 -0
  649. package/dist/server/web-ui/_expo/static/css/xterm-3bb1704bf6cb0876640973dc0244b4cb.css.br +0 -0
  650. package/dist/server/web-ui/_expo/static/css/xterm-3bb1704bf6cb0876640973dc0244b4cb.css.gz +0 -0
  651. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-a25c6055b348629689f75618db2c83e1.js +1 -0
  652. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-a25c6055b348629689f75618db2c83e1.js.br +0 -0
  653. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-a25c6055b348629689f75618db2c83e1.js.gz +0 -0
  654. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-7dc26ea1611eb9d7c2971a6745e5bf5c.js +1 -0
  655. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-7dc26ea1611eb9d7c2971a6745e5bf5c.js.br +0 -0
  656. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-7dc26ea1611eb9d7c2971a6745e5bf5c.js.gz +0 -0
  657. package/dist/server/web-ui/_expo/static/js/web/index-ea91f496cee180fa5bf308c8cc177646.js +3199 -0
  658. package/dist/server/web-ui/_expo/static/js/web/index-ea91f496cee180fa5bf308c8cc177646.js.br +0 -0
  659. package/dist/server/web-ui/_expo/static/js/web/index-ea91f496cee180fa5bf308c8cc177646.js.gz +0 -0
  660. package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-b6b853a967343babf305512fe8c5958c.js +1 -0
  661. package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-b6b853a967343babf305512fe8c5958c.js.br +0 -0
  662. package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-b6b853a967343babf305512fe8c5958c.js.gz +0 -0
  663. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-17223e158406802adc686d02d946573d.js +3 -0
  664. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-17223e158406802adc686d02d946573d.js.br +0 -0
  665. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-17223e158406802adc686d02d946573d.js.gz +0 -0
  666. package/dist/server/web-ui/apple-touch-icon.png +0 -0
  667. package/dist/server/web-ui/assets/__node_modules/@expo-google-fonts/inter/400Regular/Inter_400Regular.51b6ad87261f18b6433ec52871ddfabc.ttf +0 -0
  668. package/dist/server/web-ui/assets/__node_modules/@expo-google-fonts/jetbrains-mono/400Regular/JetBrainsMono_400Regular.a0147b5ab9e4946e81879aef45313def.ttf +0 -0
  669. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/back-icon-mask.0a328cd9c1afd0afe8e3b1ec5165b1b4.png +0 -0
  670. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/back-icon.35ba0eaec5a4f5ed12ca16fabeae451d.png +0 -0
  671. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55.png +0 -0
  672. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@2x.png +0 -0
  673. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@3x.png +0 -0
  674. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@4x.png +0 -0
  675. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7.png +0 -0
  676. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@2x.png +0 -0
  677. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@3x.png +0 -0
  678. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@4x.png +0 -0
  679. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/search-icon.286d67d3f74808a60a78d3ebf1a5fb57.png +0 -0
  680. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/arrow_down.017bc6ba3fc25503e5eb5e53826d48a8.png +0 -0
  681. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/error.d1ea1496f9057eb392d5bbf3732a61b7.png +0 -0
  682. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/file.19eeb73b9593a38f8e9f418337fc7d10.png +0 -0
  683. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/forward.d8b800c443b8972542883e0b9de2bdc6.png +0 -0
  684. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/pkg.ab19f4cbc543357183a20571f68380a3.png +0 -0
  685. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/sitemap.412dd9275b6b48ad28f5e3d81bb1f626.png +0 -0
  686. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/unmatched.20e71bdf79e3a97bf55fd9e164041578.png +0 -0
  687. package/dist/server/web-ui/assets/assets/images/editor-apps/antigravity.6e91a685c33435e0b466a56db86cf141.png +0 -0
  688. package/dist/server/web-ui/assets/assets/images/editor-apps/clion.baa1f4eb572e962a6117bdbee95749e4.png +0 -0
  689. package/dist/server/web-ui/assets/assets/images/editor-apps/cursor.c31d6bce4fe9aadc3fe59962f4c4fcf3.png +0 -0
  690. package/dist/server/web-ui/assets/assets/images/editor-apps/finder.7f68fc2c475621a672e1be09309d5567.png +0 -0
  691. package/dist/server/web-ui/assets/assets/images/editor-apps/goland.0796ab2b9be2637fd1cdcde891fad3ca.png +0 -0
  692. package/dist/server/web-ui/assets/assets/images/editor-apps/intellij-idea.33bc9ff9c0815d8ad43f618c8c244401.png +0 -0
  693. package/dist/server/web-ui/assets/assets/images/editor-apps/phpstorm.c60b33bc7a8309143d232e14b76554c5.png +0 -0
  694. package/dist/server/web-ui/assets/assets/images/editor-apps/pycharm.88f25ac484989c45c25323e0adccfa9f.png +0 -0
  695. package/dist/server/web-ui/assets/assets/images/editor-apps/rider.1a1091dc3a0ede0461f0aa38a54f080a.png +0 -0
  696. package/dist/server/web-ui/assets/assets/images/editor-apps/rubymine.0e5b66fd7d43f8cbac0f05bba97c9a21.png +0 -0
  697. package/dist/server/web-ui/assets/assets/images/editor-apps/rustrover.3590ef05482369f41d3484c90272570d.png +0 -0
  698. package/dist/server/web-ui/assets/assets/images/editor-apps/vscode.832bdb4c685d930f1c864c793703600b.png +0 -0
  699. package/dist/server/web-ui/assets/assets/images/editor-apps/webstorm.aa5dc2cd8c20cc0a155c4c5c5ab3c5f5.png +0 -0
  700. package/dist/server/web-ui/assets/assets/images/editor-apps/zed.f3a670b7f9aa226da4fe53fb86f1abbd.png +0 -0
  701. package/dist/server/web-ui/assets/assets/images/favicon-dark-attention.3b2c331d11122d8f743c73a5878593be.png +0 -0
  702. package/dist/server/web-ui/assets/assets/images/favicon-dark-running.6077c2ab71021b31c82a42e0b42ad837.png +0 -0
  703. package/dist/server/web-ui/assets/assets/images/favicon-dark.12984efe6d435a13794a74cd2f858dcd.png +0 -0
  704. package/dist/server/web-ui/assets/assets/images/favicon-light-attention.3b2c331d11122d8f743c73a5878593be.png +0 -0
  705. package/dist/server/web-ui/assets/assets/images/favicon-light-running.6077c2ab71021b31c82a42e0b42ad837.png +0 -0
  706. package/dist/server/web-ui/assets/assets/images/favicon-light.12984efe6d435a13794a74cd2f858dcd.png +0 -0
  707. package/dist/server/web-ui/assets/assets/images/notification-icon.2394c3b427c0f5ee2bb84864d8fb0f45.png +0 -0
  708. package/dist/server/web-ui/favicon.ico +0 -0
  709. package/dist/server/web-ui/index.html +147 -0
  710. package/dist/server/web-ui/index.html.br +0 -0
  711. package/dist/server/web-ui/index.html.gz +0 -0
  712. package/dist/server/web-ui/manifest.json +27 -0
  713. package/dist/server/web-ui/manifest.json.br +0 -0
  714. package/dist/server/web-ui/manifest.json.gz +0 -0
  715. package/dist/server/web-ui/metadata.json +1 -0
  716. package/dist/server/web-ui/metadata.json.br +1 -0
  717. package/dist/server/web-ui/metadata.json.gz +0 -0
  718. package/dist/server/web-ui/pwa-icon-192.png +0 -0
  719. package/dist/server/web-ui/pwa-icon-512.png +0 -0
  720. package/dist/server/web-ui/robots.txt +2 -0
  721. package/dist/src/executable-resolution/executable-resolution.js +118 -0
  722. package/dist/src/executable-resolution/windows.js +65 -0
  723. package/dist/src/server/agent/provider-launch-config.js +167 -0
  724. package/dist/src/server/otto-env.js +53 -0
  725. package/dist/src/server/otto-home.js +19 -0
  726. package/dist/src/server/persisted-config.js +471 -0
  727. package/dist/src/server/pid-lock.js +170 -0
  728. package/dist/src/server/private-files.js +37 -0
  729. package/dist/src/server/speech/providers/local/sherpa/sherpa-runtime-env.js +84 -0
  730. package/dist/src/terminal/shell-integration/zsh/.zshenv +17 -0
  731. package/dist/src/terminal/shell-integration/zsh/otto-integration.zsh +32 -0
  732. package/dist/src/utils/spawn.js +59 -0
  733. package/dist/src/utils/windows-command.js +41 -0
  734. package/package.json +118 -0
@@ -0,0 +1,2109 @@
1
+ import { z } from "zod";
2
+ import { parseBitbucketCloudRemoteUrl } from "@otto-code/protocol/git-remote";
3
+ import { findExecutable } from "../executable-resolution/executable-resolution.js";
4
+ import { resolveGitHubRemote } from "../utils/github-remote.js";
5
+ import { runGitCommand } from "../utils/run-git-command.js";
6
+ import { execCommand } from "../utils/spawn.js";
7
+ const DEFAULT_GITHUB_CACHE_TTL_MS = 30000;
8
+ const CHECK_ANNOTATION_PAGE_MAX = 20;
9
+ const CHECK_LOG_TAIL_MAX_LINES = 200;
10
+ const CHECK_LOG_TAIL_MAX_BYTES = 16 * 1024;
11
+ const CHECK_LOG_TAIL_CACHE_MAX_ENTRIES = 128;
12
+ const ACTIONS_JOB_PAGE_MAX = 100;
13
+ const FAILED_CHECK_JOB_LIMIT = 5;
14
+ export const GITHUB_POLL_FAST_INTERVAL_MS = 20000;
15
+ export const GITHUB_POLL_SLOW_INTERVAL_MS = 120000;
16
+ export const GITHUB_POLL_ERROR_BACKOFF_CAP_MS = 300000;
17
+ const GITHUB_ENV = {
18
+ GIT_TERMINAL_PROMPT: "0",
19
+ };
20
+ const LabelSchema = z.object({
21
+ name: z.string().optional(),
22
+ });
23
+ const GitHubIssueSummarySchema = z.object({
24
+ number: z.number(),
25
+ title: z.string().catch(""),
26
+ url: z.string().catch(""),
27
+ state: z.string().catch(""),
28
+ body: z.string().nullable().catch(null),
29
+ labels: z.array(LabelSchema).catch([]),
30
+ updatedAt: z.string().catch(""),
31
+ });
32
+ const HostingPullRequestSummarySchema = z.object({
33
+ number: z.number(),
34
+ title: z.string().catch(""),
35
+ url: z.string().catch(""),
36
+ state: z.string().catch(""),
37
+ body: z.string().nullable().catch(null),
38
+ baseRefName: z.string().catch(""),
39
+ headRefName: z.string().catch(""),
40
+ labels: z.array(LabelSchema).catch([]),
41
+ updatedAt: z.string().catch(""),
42
+ });
43
+ const PullRequestCheckRunNodeSchema = z.object({
44
+ __typename: z.literal("CheckRun"),
45
+ databaseId: z.number().nullable().optional(),
46
+ name: z.string(),
47
+ workflowName: z.string().nullable().optional(),
48
+ conclusion: z.string().nullable().optional(),
49
+ status: z.string().nullable().optional(),
50
+ detailsUrl: z.string().nullable().optional(),
51
+ startedAt: z.string().nullable().optional(),
52
+ completedAt: z.string().nullable().optional(),
53
+ checkSuite: z
54
+ .object({
55
+ workflowRun: z
56
+ .object({
57
+ databaseId: z.number().nullable().optional(),
58
+ })
59
+ .nullable()
60
+ .optional(),
61
+ })
62
+ .nullable()
63
+ .optional(),
64
+ });
65
+ const PullRequestStatusContextNodeSchema = z.object({
66
+ __typename: z.literal("StatusContext"),
67
+ context: z.string(),
68
+ state: z.string().nullable().optional(),
69
+ targetUrl: z.string().nullable().optional(),
70
+ createdAt: z.string().nullable().optional(),
71
+ });
72
+ const PullRequestStatusCheckRollupNodeSchema = z.discriminatedUnion("__typename", [
73
+ PullRequestCheckRunNodeSchema,
74
+ PullRequestStatusContextNodeSchema,
75
+ ]);
76
+ const PullRequestStatusCheckRollupArraySchema = z.array(z.unknown());
77
+ const LegacyPullRequestStatusCheckRollupSchema = z.object({
78
+ contexts: z.array(z.unknown()),
79
+ });
80
+ const GitHubCheckRunDetailsSchema = z.object({
81
+ id: z.number(),
82
+ name: z.string().catch(""),
83
+ status: z.string().nullable().optional(),
84
+ conclusion: z.string().nullable().optional(),
85
+ html_url: z.string().nullable().optional(),
86
+ details_url: z.string().nullable().optional(),
87
+ output: z
88
+ .object({
89
+ title: z.string().nullable().optional(),
90
+ summary: z.string().nullable().optional(),
91
+ text: z.string().nullable().optional(),
92
+ })
93
+ .nullable()
94
+ .optional(),
95
+ check_suite: z
96
+ .object({
97
+ workflow_run: z
98
+ .object({
99
+ id: z.number().nullable().optional(),
100
+ })
101
+ .nullable()
102
+ .optional(),
103
+ })
104
+ .nullable()
105
+ .optional(),
106
+ });
107
+ const GitHubCheckAnnotationSchema = z.object({
108
+ path: z.string().optional(),
109
+ start_line: z.number().optional(),
110
+ end_line: z.number().optional(),
111
+ annotation_level: z.string().optional(),
112
+ message: z.string().optional(),
113
+ title: z.string().optional(),
114
+ raw_details: z.string().optional(),
115
+ });
116
+ const GitHubCheckAnnotationsSchema = z.array(GitHubCheckAnnotationSchema).catch([]);
117
+ const GitHubActionsJobSchema = z.object({
118
+ id: z.number(),
119
+ name: z.string().catch(""),
120
+ status: z.string().nullable().optional(),
121
+ conclusion: z.string().nullable().optional(),
122
+ html_url: z.string().nullable().optional(),
123
+ completed_at: z.string().nullable().optional(),
124
+ });
125
+ const GitHubActionsJobsSchema = z.object({
126
+ jobs: z.array(GitHubActionsJobSchema).catch([]),
127
+ });
128
+ const PullRequestReviewDecisionSchema = z
129
+ .enum(["APPROVED", "CHANGES_REQUESTED", "REVIEW_REQUIRED"])
130
+ .nullable()
131
+ .catch(null);
132
+ const HeadRepositoryOwnerSchema = z
133
+ .object({
134
+ login: z.string().optional(),
135
+ })
136
+ .nullable()
137
+ .optional();
138
+ const PullRequestMergeableSchema = z.enum(["MERGEABLE", "CONFLICTING", "UNKNOWN"]).catch("UNKNOWN");
139
+ const GitHubAutoMergeRequestSchema = z
140
+ .object({
141
+ enabledAt: z.string().nullable().optional().catch(null),
142
+ mergeMethod: z.string().nullable().optional().catch(null),
143
+ enabledBy: z
144
+ .object({
145
+ login: z.string().nullable().optional().catch(null),
146
+ })
147
+ .nullable()
148
+ .optional()
149
+ .catch(null),
150
+ })
151
+ .nullable()
152
+ .optional()
153
+ .catch(null);
154
+ const GitHubPullRequestFactsGraphqlSchema = z.object({
155
+ data: z.object({
156
+ repository: z
157
+ .object({
158
+ autoMergeAllowed: z.boolean().optional().catch(false),
159
+ mergeCommitAllowed: z.boolean().optional().catch(false),
160
+ squashMergeAllowed: z.boolean().optional().catch(false),
161
+ rebaseMergeAllowed: z.boolean().optional().catch(false),
162
+ viewerDefaultMergeMethod: z.string().nullable().optional().catch(null),
163
+ pullRequest: z
164
+ .object({
165
+ mergeStateStatus: z.string().nullable().optional().catch(null),
166
+ autoMergeRequest: GitHubAutoMergeRequestSchema,
167
+ viewerCanEnableAutoMerge: z.boolean().optional().catch(false),
168
+ viewerCanDisableAutoMerge: z.boolean().optional().catch(false),
169
+ viewerCanMergeAsAdmin: z.boolean().optional().catch(false),
170
+ viewerCanUpdateBranch: z.boolean().optional().catch(false),
171
+ isMergeQueueEnabled: z.boolean().optional().catch(false),
172
+ isInMergeQueue: z.boolean().optional().catch(false),
173
+ })
174
+ .nullable()
175
+ .optional()
176
+ .catch(null),
177
+ })
178
+ .nullable()
179
+ .optional()
180
+ .catch(null),
181
+ }),
182
+ });
183
+ const CurrentPullRequestStatusSchema = z.object({
184
+ number: z.number().optional(),
185
+ url: z.string().catch(""),
186
+ title: z.string().catch(""),
187
+ state: z.string().catch(""),
188
+ isDraft: z.boolean().optional().catch(false),
189
+ baseRefName: z.string().catch(""),
190
+ headRefName: z.string().catch(""),
191
+ mergedAt: z.string().nullable().optional(),
192
+ statusCheckRollup: z.unknown().optional(),
193
+ reviewDecision: z.unknown().optional(),
194
+ mergeable: PullRequestMergeableSchema.optional().default("UNKNOWN"),
195
+ headRepositoryOwner: HeadRepositoryOwnerSchema,
196
+ });
197
+ const TimelineAuthorSchema = z
198
+ .object({
199
+ login: z.string().optional(),
200
+ url: z.string().nullable().optional(),
201
+ avatarUrl: z.string().nullable().optional(),
202
+ })
203
+ .nullable()
204
+ .optional();
205
+ const PullRequestTimelineReviewNodeSchema = z.object({
206
+ id: z.string().catch(""),
207
+ state: z.string().catch(""),
208
+ body: z.string().nullable().catch(null),
209
+ bodyHTML: z.string().nullable().catch(null),
210
+ url: z.string().catch(""),
211
+ submittedAt: z.string().nullable().catch(null),
212
+ author: TimelineAuthorSchema,
213
+ });
214
+ const PullRequestTimelineCommentNodeSchema = z.object({
215
+ id: z.string().catch(""),
216
+ body: z.string().nullable().catch(null),
217
+ bodyHTML: z.string().nullable().catch(null),
218
+ url: z.string().catch(""),
219
+ createdAt: z.string().nullable().catch(null),
220
+ author: TimelineAuthorSchema,
221
+ });
222
+ const PullRequestReviewThreadCommentNodeSchema = PullRequestTimelineCommentNodeSchema.extend({
223
+ pullRequestReview: z
224
+ .object({ id: z.string().catch("") })
225
+ .nullable()
226
+ .optional()
227
+ .catch(null),
228
+ });
229
+ const PullRequestReviewThreadNodeSchema = z.object({
230
+ id: z.string().catch(""),
231
+ path: z.string().catch(""),
232
+ line: z.number().nullable().optional().catch(null),
233
+ startLine: z.number().nullable().optional().catch(null),
234
+ isResolved: z.boolean().catch(false),
235
+ isOutdated: z.boolean().catch(false),
236
+ comments: z
237
+ .object({
238
+ nodes: z.array(PullRequestReviewThreadCommentNodeSchema).catch([]),
239
+ pageInfo: z.object({ hasNextPage: z.boolean().catch(false) }).catch({ hasNextPage: false }),
240
+ })
241
+ .catch({ nodes: [], pageInfo: { hasNextPage: false } }),
242
+ });
243
+ const PullRequestTimelinePageInfoSchema = z.object({
244
+ hasNextPage: z.boolean().catch(false),
245
+ });
246
+ const PullRequestTimelineGraphqlSchema = z.object({
247
+ data: z
248
+ .object({
249
+ repository: z
250
+ .object({
251
+ pullRequest: z
252
+ .object({
253
+ number: z.number().optional(),
254
+ reviews: z
255
+ .object({
256
+ nodes: z.array(PullRequestTimelineReviewNodeSchema).catch([]),
257
+ pageInfo: PullRequestTimelinePageInfoSchema.catch({ hasNextPage: false }),
258
+ })
259
+ .catch({ nodes: [], pageInfo: { hasNextPage: false } }),
260
+ comments: z
261
+ .object({
262
+ nodes: z.array(PullRequestTimelineCommentNodeSchema).catch([]),
263
+ pageInfo: PullRequestTimelinePageInfoSchema.catch({ hasNextPage: false }),
264
+ })
265
+ .catch({ nodes: [], pageInfo: { hasNextPage: false } }),
266
+ reviewThreads: z
267
+ .object({
268
+ nodes: z.array(PullRequestReviewThreadNodeSchema).catch([]),
269
+ pageInfo: PullRequestTimelinePageInfoSchema.catch({ hasNextPage: false }),
270
+ })
271
+ .catch({ nodes: [], pageInfo: { hasNextPage: false } }),
272
+ })
273
+ .nullable()
274
+ .optional(),
275
+ })
276
+ .nullable()
277
+ .optional(),
278
+ })
279
+ .optional(),
280
+ });
281
+ const GitHubRepoViewSchema = z.object({
282
+ owner: z
283
+ .object({
284
+ login: z.string().optional(),
285
+ })
286
+ .nullable()
287
+ .optional(),
288
+ name: z.string().optional(),
289
+ parent: z
290
+ .object({
291
+ owner: z
292
+ .object({
293
+ login: z.string().optional(),
294
+ })
295
+ .nullable()
296
+ .optional(),
297
+ name: z.string().optional(),
298
+ })
299
+ .nullable()
300
+ .optional(),
301
+ });
302
+ const PullRequestCheckoutTargetSchema = z.object({
303
+ data: z.object({
304
+ repository: z.object({
305
+ pullRequest: z
306
+ .object({
307
+ number: z.number(),
308
+ baseRefName: z.string().catch(""),
309
+ headRefName: z.string().catch(""),
310
+ isCrossRepository: z.boolean().catch(false),
311
+ headRepositoryOwner: z
312
+ .object({
313
+ login: z.string().catch(""),
314
+ })
315
+ .nullable()
316
+ .optional(),
317
+ headRepository: z
318
+ .object({
319
+ sshUrl: z.string().nullable().optional(),
320
+ url: z.string().nullable().optional(),
321
+ })
322
+ .nullable()
323
+ .optional(),
324
+ })
325
+ .nullable(),
326
+ }),
327
+ }),
328
+ });
329
+ const PULL_REQUEST_CHECKOUT_TARGET_QUERY = `
330
+ query PullRequestCheckoutTarget($owner: String!, $name: String!, $number: Int!) {
331
+ repository(owner: $owner, name: $name) {
332
+ pullRequest(number: $number) {
333
+ number
334
+ baseRefName
335
+ headRefName
336
+ isCrossRepository
337
+ headRepositoryOwner {
338
+ login
339
+ }
340
+ headRepository {
341
+ sshUrl
342
+ url
343
+ }
344
+ }
345
+ }
346
+ }`;
347
+ const CURRENT_PR_STATUS_BASE_FIELDS = "number,url,title,state,isDraft,baseRefName,headRefName,mergedAt,reviewDecision,mergeable,headRepositoryOwner";
348
+ const CURRENT_PR_STATUS_FIELDS = `${CURRENT_PR_STATUS_BASE_FIELDS},statusCheckRollup`;
349
+ const PULL_REQUEST_STATUS_FACTS_QUERY = `
350
+ query PullRequestStatusFacts($owner: String!, $name: String!, $number: Int!) {
351
+ repository(owner: $owner, name: $name) {
352
+ autoMergeAllowed
353
+ mergeCommitAllowed
354
+ squashMergeAllowed
355
+ rebaseMergeAllowed
356
+ viewerDefaultMergeMethod
357
+ pullRequest(number: $number) {
358
+ mergeStateStatus
359
+ autoMergeRequest {
360
+ enabledAt
361
+ mergeMethod
362
+ enabledBy {
363
+ login
364
+ }
365
+ }
366
+ viewerCanEnableAutoMerge
367
+ viewerCanDisableAutoMerge
368
+ viewerCanMergeAsAdmin
369
+ viewerCanUpdateBranch
370
+ isMergeQueueEnabled
371
+ isInMergeQueue
372
+ }
373
+ }
374
+ }`;
375
+ const PULL_REQUEST_TIMELINE_QUERY = `
376
+ query PullRequestTimeline($owner: String!, $name: String!, $number: Int!) {
377
+ repository(owner: $owner, name: $name) {
378
+ pullRequest(number: $number) {
379
+ number
380
+ reviews(first: 100) {
381
+ nodes {
382
+ id
383
+ state
384
+ body
385
+ bodyHTML
386
+ url
387
+ submittedAt
388
+ author {
389
+ login
390
+ url
391
+ avatarUrl
392
+ }
393
+ }
394
+ pageInfo {
395
+ hasNextPage
396
+ }
397
+ }
398
+ comments(first: 100) {
399
+ nodes {
400
+ id
401
+ body
402
+ bodyHTML
403
+ url
404
+ createdAt
405
+ author {
406
+ login
407
+ url
408
+ avatarUrl
409
+ }
410
+ }
411
+ pageInfo {
412
+ hasNextPage
413
+ }
414
+ }
415
+ reviewThreads(first: 100) {
416
+ nodes {
417
+ id
418
+ path
419
+ line
420
+ startLine
421
+ isResolved
422
+ isOutdated
423
+ comments(first: 100) {
424
+ nodes {
425
+ id
426
+ body
427
+ bodyHTML
428
+ url
429
+ createdAt
430
+ author {
431
+ login
432
+ url
433
+ avatarUrl
434
+ }
435
+ pullRequestReview {
436
+ id
437
+ }
438
+ }
439
+ pageInfo {
440
+ hasNextPage
441
+ }
442
+ }
443
+ }
444
+ pageInfo {
445
+ hasNextPage
446
+ }
447
+ }
448
+ }
449
+ }
450
+ }`;
451
+ const DIRECT_PULL_REQUEST_MERGE_STATE_ALLOWLIST = new Set(["CLEAN", "HAS_HOOKS"]);
452
+ export class GitHubCliMissingError extends Error {
453
+ constructor() {
454
+ super("GitHub CLI (gh) is not installed or not in PATH");
455
+ this.kind = "missing-cli";
456
+ this.name = "GitHubCliMissingError";
457
+ }
458
+ }
459
+ export class GitHubAuthenticationError extends Error {
460
+ constructor(params) {
461
+ super("GitHub CLI authentication failed");
462
+ this.kind = "auth-failure";
463
+ this.name = "GitHubAuthenticationError";
464
+ this.stderr = params.stderr;
465
+ }
466
+ }
467
+ export class GitHubCommandError extends Error {
468
+ constructor(params) {
469
+ super(`GitHub CLI command failed: gh ${params.args.join(" ")}`);
470
+ this.kind = "command-error";
471
+ this.name = "GitHubCommandError";
472
+ this.args = [...params.args];
473
+ this.cwd = params.cwd;
474
+ this.exitCode = params.exitCode;
475
+ this.stderr = params.stderr;
476
+ }
477
+ }
478
+ export function createGitHubService(options = {}) {
479
+ const ttlMs = options.ttlMs ?? DEFAULT_GITHUB_CACHE_TTL_MS;
480
+ const deps = {
481
+ runner: options.runner ?? runGhCommand,
482
+ resolveGhPath: options.resolveGhPath ?? resolveGhPath,
483
+ now: options.now ?? Date.now,
484
+ };
485
+ const cache = new Map();
486
+ const inFlight = new Map();
487
+ const pollTargets = new Map();
488
+ const checkLogTailCache = new Map();
489
+ let api;
490
+ async function cached(params) {
491
+ if (params.readOptions?.force && !params.readOptions.reason) {
492
+ throw new Error("GitHubService forced read requires a reason");
493
+ }
494
+ const key = buildCacheKey({
495
+ cwd: params.cwd,
496
+ method: params.method,
497
+ args: params.args,
498
+ });
499
+ const cachedEntry = cache.get(key);
500
+ const now = deps.now();
501
+ if (!params.readOptions?.force && cachedEntry && cachedEntry.expiresAt > now) {
502
+ return cachedEntry.value;
503
+ }
504
+ const existing = inFlight.get(key);
505
+ if (existing && (!params.readOptions?.force || existing.force)) {
506
+ return existing.promise;
507
+ }
508
+ const request = params
509
+ .load()
510
+ .then((value) => {
511
+ if (inFlight.get(key)?.promise === request) {
512
+ cache.set(key, {
513
+ value,
514
+ cwd: params.cwd,
515
+ expiresAt: deps.now() + ttlMs,
516
+ });
517
+ }
518
+ return value;
519
+ })
520
+ .finally(() => {
521
+ if (inFlight.get(key)?.promise === request) {
522
+ inFlight.delete(key);
523
+ }
524
+ });
525
+ inFlight.set(key, {
526
+ cwd: params.cwd,
527
+ promise: request,
528
+ force: params.readOptions?.force === true,
529
+ });
530
+ return request;
531
+ }
532
+ async function run(args, runOptions) {
533
+ const ghPath = await deps.resolveGhPath();
534
+ if (!ghPath) {
535
+ throw new GitHubCliMissingError();
536
+ }
537
+ try {
538
+ const result = await deps.runner(args, runOptions);
539
+ return result.stdout.trim();
540
+ }
541
+ catch (error) {
542
+ throw normalizeGitHubCommandError(error, {
543
+ args,
544
+ cwd: runOptions.cwd,
545
+ });
546
+ }
547
+ }
548
+ function getPollTargetKey(target) {
549
+ return buildCacheKey({
550
+ cwd: target.cwd,
551
+ method: "getCurrentPullRequestStatus",
552
+ args: {
553
+ headRef: target.headRef,
554
+ headRepositoryOwner: target.headRepositoryOwner,
555
+ },
556
+ });
557
+ }
558
+ function updatePollTargetAfterSuccess(update) {
559
+ const target = pollTargets.get(getPollTargetKey(update));
560
+ if (!target) {
561
+ return;
562
+ }
563
+ target.latestStatus = update.status;
564
+ target.consecutiveErrors = 0;
565
+ if (update.notify) {
566
+ for (const callback of target.callbacks) {
567
+ callback(update.status);
568
+ }
569
+ }
570
+ scheduleGitHubPoll(target);
571
+ }
572
+ function scheduleGitHubPoll(target) {
573
+ scheduleGitHubPollAfter(target, computeGithubNextInterval(target.latestStatus, target.consecutiveErrors));
574
+ }
575
+ function scheduleImmediateGitHubPoll(target) {
576
+ scheduleGitHubPollAfter(target, 0);
577
+ }
578
+ function scheduleGitHubPollAfter(target, delayMs) {
579
+ if (target.retainCount <= 0) {
580
+ return;
581
+ }
582
+ if (target.timer) {
583
+ clearTimeout(target.timer);
584
+ }
585
+ target.timer = setTimeout(() => {
586
+ target.timer = null;
587
+ void runGitHubPoll(target);
588
+ }, delayMs);
589
+ }
590
+ async function runGitHubPoll(target) {
591
+ try {
592
+ await api.getCurrentPullRequestStatus({
593
+ cwd: target.cwd,
594
+ headRef: target.headRef,
595
+ headRepositoryOwner: target.headRepositoryOwner,
596
+ reason: "self-heal-github",
597
+ });
598
+ }
599
+ catch (error) {
600
+ target.consecutiveErrors += 1;
601
+ for (const callback of target.errorCallbacks) {
602
+ callback(error);
603
+ }
604
+ scheduleGitHubPoll(target);
605
+ }
606
+ }
607
+ function closeGitHubPollTarget(target) {
608
+ if (target.timer) {
609
+ clearTimeout(target.timer);
610
+ target.timer = null;
611
+ }
612
+ target.retainCount = 0;
613
+ target.callbacks.clear();
614
+ target.errorCallbacks.clear();
615
+ }
616
+ api = {
617
+ listPullRequests(input) {
618
+ return cached({
619
+ cwd: input.cwd,
620
+ method: "listPullRequests",
621
+ args: { query: input.query ?? "", limit: input.limit ?? 20 },
622
+ readOptions: input,
623
+ load: async () => {
624
+ const stdout = await run([
625
+ "pr",
626
+ "list",
627
+ "--search",
628
+ input.query ?? "",
629
+ "--json",
630
+ "number,title,url,state,body,labels,baseRefName,headRefName,updatedAt",
631
+ "--limit",
632
+ String(input.limit ?? 20),
633
+ ], { cwd: input.cwd });
634
+ return parsePullRequestSummaries(stdout);
635
+ },
636
+ });
637
+ },
638
+ listIssues(input) {
639
+ return cached({
640
+ cwd: input.cwd,
641
+ method: "listIssues",
642
+ args: { query: input.query ?? "", limit: input.limit ?? 20 },
643
+ readOptions: input,
644
+ load: async () => {
645
+ const stdout = await run([
646
+ "issue",
647
+ "list",
648
+ "--search",
649
+ input.query ?? "",
650
+ "--json",
651
+ "number,title,url,state,body,labels,updatedAt",
652
+ "--limit",
653
+ String(input.limit ?? 20),
654
+ ], { cwd: input.cwd });
655
+ return parseIssueSummaries(stdout);
656
+ },
657
+ });
658
+ },
659
+ getPullRequest(input) {
660
+ return cached({
661
+ cwd: input.cwd,
662
+ method: "getPullRequest",
663
+ args: { number: input.number },
664
+ readOptions: input,
665
+ load: async () => {
666
+ const stdout = await run([
667
+ "pr",
668
+ "view",
669
+ String(input.number),
670
+ "--json",
671
+ "number,title,url,state,body,labels,baseRefName,headRefName,updatedAt",
672
+ ], { cwd: input.cwd });
673
+ return parsePullRequestSummary(stdout);
674
+ },
675
+ });
676
+ },
677
+ async getPullRequestHeadRef(input) {
678
+ const pullRequest = await this.getPullRequest(input);
679
+ return pullRequest.headRefName;
680
+ },
681
+ getPullRequestCheckoutTarget(input) {
682
+ return cached({
683
+ cwd: input.cwd,
684
+ method: "getPullRequestCheckoutTarget",
685
+ args: { number: input.number },
686
+ readOptions: input,
687
+ load: async () => {
688
+ const repo = await getGitHubRepoView({ cwd: input.cwd, run });
689
+ const owner = repo?.owner?.login;
690
+ const name = repo?.name;
691
+ if (!owner || !name) {
692
+ throw new Error("Unable to resolve GitHub repository for pull request checkout");
693
+ }
694
+ const stdout = await run([
695
+ "api",
696
+ "graphql",
697
+ "-f",
698
+ `query=${PULL_REQUEST_CHECKOUT_TARGET_QUERY}`,
699
+ "-F",
700
+ `owner=${owner}`,
701
+ "-F",
702
+ `name=${name}`,
703
+ "-F",
704
+ `number=${input.number}`,
705
+ ], { cwd: input.cwd });
706
+ return parsePullRequestCheckoutTarget(stdout);
707
+ },
708
+ });
709
+ },
710
+ getCurrentPullRequestStatus(input) {
711
+ return cached({
712
+ cwd: input.cwd,
713
+ method: "getCurrentPullRequestStatus",
714
+ args: {
715
+ headRef: input.headRef,
716
+ headRepositoryOwner: input.headRepositoryOwner,
717
+ },
718
+ readOptions: input,
719
+ load: async () => {
720
+ const status = await resolveCurrentPullRequestView({
721
+ cwd: input.cwd,
722
+ headRef: input.headRef,
723
+ headRepositoryOwner: input.headRepositoryOwner,
724
+ run,
725
+ });
726
+ return addCurrentPullRequestGithubFacts({ cwd: input.cwd, status, run });
727
+ },
728
+ }).then((status) => {
729
+ updatePollTargetAfterSuccess({
730
+ cwd: input.cwd,
731
+ headRef: input.headRef,
732
+ headRepositoryOwner: input.headRepositoryOwner,
733
+ status,
734
+ notify: input.reason === "self-heal-github",
735
+ });
736
+ return status;
737
+ });
738
+ },
739
+ getPullRequestTimeline(input) {
740
+ return cached({
741
+ cwd: input.cwd,
742
+ method: "getPullRequestTimeline",
743
+ args: { prNumber: input.prNumber },
744
+ readOptions: input,
745
+ load: async () => {
746
+ try {
747
+ const stdout = await run([
748
+ "api",
749
+ "graphql",
750
+ "-f",
751
+ `query=${PULL_REQUEST_TIMELINE_QUERY}`,
752
+ "-F",
753
+ `owner=${input.repoOwner}`,
754
+ "-F",
755
+ `name=${input.repoName}`,
756
+ "-F",
757
+ `number=${input.prNumber}`,
758
+ ], { cwd: input.cwd });
759
+ return parsePullRequestTimeline(stdout, {
760
+ prNumber: input.prNumber,
761
+ repoOwner: input.repoOwner,
762
+ repoName: input.repoName,
763
+ });
764
+ }
765
+ catch (error) {
766
+ return {
767
+ prNumber: input.prNumber,
768
+ repoOwner: input.repoOwner,
769
+ repoName: input.repoName,
770
+ items: [],
771
+ truncated: false,
772
+ error: mapPullRequestTimelineError(error),
773
+ };
774
+ }
775
+ },
776
+ });
777
+ },
778
+ getGitHubCheckDetails(input) {
779
+ return cached({
780
+ cwd: input.cwd,
781
+ method: "getGitHubCheckDetails",
782
+ args: {
783
+ repoOwner: input.repoOwner,
784
+ repoName: input.repoName,
785
+ checkRunId: input.checkRunId,
786
+ workflowRunId: input.workflowRunId,
787
+ },
788
+ readOptions: input,
789
+ load: async () => {
790
+ const repoPath = `repos/${input.repoOwner}/${input.repoName}`;
791
+ const checkRun = parseGitHubCheckRunDetails(await run(["api", `${repoPath}/check-runs/${input.checkRunId}`], { cwd: input.cwd }));
792
+ const annotations = parseGitHubCheckAnnotations(await run([
793
+ "api",
794
+ `${repoPath}/check-runs/${input.checkRunId}/annotations`,
795
+ "-f",
796
+ `per_page=${CHECK_ANNOTATION_PAGE_MAX}`,
797
+ ], {
798
+ cwd: input.cwd,
799
+ }));
800
+ const workflowRunId = input.workflowRunId ?? checkRun.workflowRunId ?? null;
801
+ const failedJobs = [];
802
+ let truncated = annotations.length >= CHECK_ANNOTATION_PAGE_MAX;
803
+ if (typeof workflowRunId === "number") {
804
+ const jobs = parseGitHubActionsJobs(await run([
805
+ "api",
806
+ `${repoPath}/actions/runs/${workflowRunId}/jobs`,
807
+ "-f",
808
+ `per_page=${ACTIONS_JOB_PAGE_MAX}`,
809
+ ], {
810
+ cwd: input.cwd,
811
+ }));
812
+ const failed = jobs.filter(isFailedActionsJob);
813
+ truncated || (truncated = jobs.length >= ACTIONS_JOB_PAGE_MAX);
814
+ truncated || (truncated = failed.length > FAILED_CHECK_JOB_LIMIT);
815
+ for (const job of failed.slice(0, FAILED_CHECK_JOB_LIMIT)) {
816
+ const log = await getCachedCheckLogTail({
817
+ cwd: input.cwd,
818
+ repoPath,
819
+ job,
820
+ run,
821
+ cache: checkLogTailCache,
822
+ });
823
+ truncated || (truncated = log.logTruncated);
824
+ failedJobs.push({
825
+ jobId: job.jobId,
826
+ name: job.name,
827
+ status: job.status,
828
+ conclusion: job.conclusion,
829
+ url: job.url,
830
+ logTail: log.logTail,
831
+ logTruncated: log.logTruncated,
832
+ });
833
+ }
834
+ }
835
+ return {
836
+ checkRunId: checkRun.checkRunId,
837
+ workflowRunId,
838
+ name: checkRun.name,
839
+ status: checkRun.status,
840
+ conclusion: checkRun.conclusion,
841
+ url: checkRun.url,
842
+ detailsUrl: checkRun.detailsUrl,
843
+ output: checkRun.output,
844
+ annotations,
845
+ failedJobs,
846
+ truncated,
847
+ };
848
+ },
849
+ });
850
+ },
851
+ async searchIssuesAndPrs(input) {
852
+ if (input.force && !input.reason) {
853
+ throw new Error("GitHubService forced read requires a reason");
854
+ }
855
+ const kinds = input.kinds ?? ["github-issue", "github-pr"];
856
+ const shouldFetchIssues = kinds.includes("github-issue");
857
+ const shouldFetchPullRequests = kinds.includes("github-pr");
858
+ const readOptions = input.force
859
+ ? { force: true, reason: input.reason }
860
+ : { force: false, reason: input.reason };
861
+ const query = normalizeGitHubSearchQuery(input.query);
862
+ const [issuesResult, prsResult] = await Promise.allSettled([
863
+ shouldFetchIssues
864
+ ? this.listIssues({
865
+ cwd: input.cwd,
866
+ query,
867
+ limit: input.limit,
868
+ ...readOptions,
869
+ })
870
+ : Promise.resolve(null),
871
+ shouldFetchPullRequests
872
+ ? this.listPullRequests({
873
+ cwd: input.cwd,
874
+ query,
875
+ limit: input.limit,
876
+ ...readOptions,
877
+ })
878
+ : Promise.resolve(null),
879
+ ]);
880
+ const items = [];
881
+ const requestedResults = [
882
+ shouldFetchIssues ? issuesResult : null,
883
+ shouldFetchPullRequests ? prsResult : null,
884
+ ].filter((result) => result !== null);
885
+ if (requestedResults.length > 0 &&
886
+ requestedResults.every((result) => result.status === "rejected" &&
887
+ (result.reason instanceof GitHubCliMissingError ||
888
+ result.reason instanceof GitHubAuthenticationError))) {
889
+ return { items: [], githubFeaturesEnabled: false };
890
+ }
891
+ if (shouldFetchIssues && issuesResult.status === "fulfilled") {
892
+ for (const item of issuesResult.value ?? []) {
893
+ items.push({
894
+ kind: "issue",
895
+ number: item.number,
896
+ title: item.title,
897
+ url: item.url,
898
+ state: item.state,
899
+ body: item.body,
900
+ labels: item.labels,
901
+ baseRefName: null,
902
+ headRefName: null,
903
+ updatedAt: item.updatedAt,
904
+ });
905
+ }
906
+ }
907
+ if (shouldFetchPullRequests && prsResult.status === "fulfilled") {
908
+ for (const item of prsResult.value ?? []) {
909
+ items.push({
910
+ kind: "pr",
911
+ number: item.number,
912
+ title: item.title,
913
+ url: item.url,
914
+ state: item.state,
915
+ body: item.body,
916
+ labels: item.labels,
917
+ baseRefName: item.baseRefName,
918
+ headRefName: item.headRefName,
919
+ updatedAt: item.updatedAt,
920
+ });
921
+ }
922
+ }
923
+ items.sort((left, right) => {
924
+ const leftTime = parseOptionalTime(left.updatedAt ?? null);
925
+ const rightTime = parseOptionalTime(right.updatedAt ?? null);
926
+ return rightTime - leftTime;
927
+ });
928
+ return { items, githubFeaturesEnabled: true };
929
+ },
930
+ async createPullRequest(input) {
931
+ const args = ["api", "-X", "POST", `repos/${input.repo}/pulls`, "-f", `title=${input.title}`];
932
+ args.push("-f", `head=${input.head}`);
933
+ args.push("-f", `base=${input.base}`);
934
+ if (input.body) {
935
+ args.push("-f", `body=${input.body}`);
936
+ }
937
+ const stdout = await run(args, { cwd: input.cwd });
938
+ const parsed = z
939
+ .object({
940
+ url: z.string(),
941
+ number: z.number(),
942
+ })
943
+ .parse(JSON.parse(stdout || "{}"));
944
+ return parsed;
945
+ },
946
+ async mergePullRequest(input) {
947
+ assertDirectPullRequestMergeReady(input);
948
+ await run(["pr", "merge", String(input.prNumber), `--${input.mergeMethod}`], {
949
+ cwd: input.cwd,
950
+ envOverlay: { GH_PROMPT_DISABLED: "1" },
951
+ });
952
+ return { success: true };
953
+ },
954
+ async enablePullRequestAutoMerge(input) {
955
+ assertPullRequestAutoMergeEnableReady(input);
956
+ await run(["pr", "merge", String(input.prNumber), "--auto", `--${input.mergeMethod}`], {
957
+ cwd: input.cwd,
958
+ envOverlay: { GH_PROMPT_DISABLED: "1" },
959
+ });
960
+ return { success: true };
961
+ },
962
+ async disablePullRequestAutoMerge(input) {
963
+ assertPullRequestAutoMergeDisableReady(input);
964
+ await run(["pr", "merge", String(input.prNumber), "--disable-auto"], {
965
+ cwd: input.cwd,
966
+ envOverlay: { GH_PROMPT_DISABLED: "1" },
967
+ });
968
+ return { success: true };
969
+ },
970
+ isAuthenticated(input) {
971
+ return cached({
972
+ cwd: input.cwd,
973
+ method: "isAuthenticated",
974
+ args: {},
975
+ readOptions: input,
976
+ load: async () => {
977
+ try {
978
+ await run(["auth", "status"], { cwd: input.cwd });
979
+ return true;
980
+ }
981
+ catch (error) {
982
+ if (isGitHubAuthenticationError(error)) {
983
+ throw error;
984
+ }
985
+ if (error instanceof GitHubCommandError && isAuthFailureText(error.stderr)) {
986
+ throw new GitHubAuthenticationError({ stderr: error.stderr });
987
+ }
988
+ throw error;
989
+ }
990
+ },
991
+ });
992
+ },
993
+ retainCurrentPullRequestStatusPoll(input) {
994
+ const key = getPollTargetKey(input);
995
+ let target = pollTargets.get(key);
996
+ if (!target) {
997
+ target = {
998
+ cwd: input.cwd,
999
+ headRef: input.headRef,
1000
+ headRepositoryOwner: input.headRepositoryOwner,
1001
+ retainCount: 0,
1002
+ timer: null,
1003
+ latestStatus: null,
1004
+ consecutiveErrors: 0,
1005
+ callbacks: new Set(),
1006
+ errorCallbacks: new Set(),
1007
+ };
1008
+ pollTargets.set(key, target);
1009
+ }
1010
+ const isNewlyRetained = target.retainCount === 0;
1011
+ target.retainCount += 1;
1012
+ if (input.onStatus) {
1013
+ target.callbacks.add(input.onStatus);
1014
+ }
1015
+ if (input.onError) {
1016
+ target.errorCallbacks.add(input.onError);
1017
+ }
1018
+ if (isNewlyRetained) {
1019
+ scheduleImmediateGitHubPoll(target);
1020
+ }
1021
+ else {
1022
+ scheduleGitHubPoll(target);
1023
+ }
1024
+ let unsubscribed = false;
1025
+ return {
1026
+ unsubscribe: () => {
1027
+ if (unsubscribed) {
1028
+ return;
1029
+ }
1030
+ unsubscribed = true;
1031
+ if (input.onStatus) {
1032
+ target.callbacks.delete(input.onStatus);
1033
+ }
1034
+ if (input.onError) {
1035
+ target.errorCallbacks.delete(input.onError);
1036
+ }
1037
+ target.retainCount -= 1;
1038
+ if (target.retainCount > 0) {
1039
+ return;
1040
+ }
1041
+ closeGitHubPollTarget(target);
1042
+ pollTargets.delete(key);
1043
+ },
1044
+ };
1045
+ },
1046
+ invalidate(input) {
1047
+ // Local checkout mutations that can alter the current PR identity or PR status
1048
+ // must call this with the affected cwd before broadcasting fresh git state.
1049
+ for (const [key, entry] of cache.entries()) {
1050
+ if (entry.cwd === input.cwd) {
1051
+ cache.delete(key);
1052
+ }
1053
+ }
1054
+ for (const [key, entry] of inFlight.entries()) {
1055
+ if (entry.cwd === input.cwd) {
1056
+ inFlight.delete(key);
1057
+ }
1058
+ }
1059
+ },
1060
+ dispose() {
1061
+ for (const target of pollTargets.values()) {
1062
+ closeGitHubPollTarget(target);
1063
+ }
1064
+ pollTargets.clear();
1065
+ },
1066
+ };
1067
+ return api;
1068
+ }
1069
+ function assertDirectPullRequestMergeReady(input) {
1070
+ const github = input.status?.github;
1071
+ if (!github) {
1072
+ throw new Error("GitHub merge facts are unavailable for this pull request");
1073
+ }
1074
+ if (!DIRECT_PULL_REQUEST_MERGE_STATE_ALLOWLIST.has(github.mergeStateStatus ?? "")) {
1075
+ throw new Error("GitHub does not report this pull request as ready for direct merge");
1076
+ }
1077
+ if (github.isMergeQueueEnabled || github.isInMergeQueue) {
1078
+ throw new Error("Direct merge is not available because this repository uses a merge queue");
1079
+ }
1080
+ if (github.autoMergeRequest !== null) {
1081
+ throw new Error("Direct merge is not available because auto-merge is already enabled");
1082
+ }
1083
+ if (!isPullRequestMergeMethodAllowed(github.repository, input.mergeMethod)) {
1084
+ throw new Error(`Direct merge is not available because ${input.mergeMethod} is disabled`);
1085
+ }
1086
+ }
1087
+ export function assertPullRequestAutoMergeEnableReady(input) {
1088
+ const github = input.status?.github;
1089
+ if (!github) {
1090
+ throw new Error("GitHub auto-merge facts are unavailable for this pull request");
1091
+ }
1092
+ if (github.mergeStateStatus !== "BLOCKED") {
1093
+ throw new Error("GitHub does not report this pull request as blocked for auto-merge");
1094
+ }
1095
+ if (!github.viewerCanEnableAutoMerge) {
1096
+ throw new Error("GitHub does not allow this viewer to enable auto-merge");
1097
+ }
1098
+ if (!github.repository.autoMergeAllowed) {
1099
+ throw new Error("Auto-merge is disabled for this repository");
1100
+ }
1101
+ if (!isPullRequestMergeMethodAllowed(github.repository, input.mergeMethod)) {
1102
+ throw new Error(`Auto-merge is not available because ${input.mergeMethod} is disabled`);
1103
+ }
1104
+ if (github.autoMergeRequest !== null) {
1105
+ throw new Error("Auto-merge is already enabled for this pull request");
1106
+ }
1107
+ if (github.isMergeQueueEnabled || github.isInMergeQueue) {
1108
+ throw new Error("Auto-merge is not available because this repository uses a merge queue");
1109
+ }
1110
+ if (input.status?.mergeable === "CONFLICTING") {
1111
+ throw new Error("Auto-merge is not available because this pull request has conflicts");
1112
+ }
1113
+ }
1114
+ export function assertPullRequestAutoMergeDisableReady(input) {
1115
+ const github = input.status?.github;
1116
+ if (!github) {
1117
+ throw new Error("GitHub auto-merge facts are unavailable for this pull request");
1118
+ }
1119
+ if (github.autoMergeRequest === null) {
1120
+ throw new Error("Auto-merge is not enabled for this pull request");
1121
+ }
1122
+ if (!github.viewerCanDisableAutoMerge) {
1123
+ throw new Error("GitHub does not allow this viewer to disable auto-merge");
1124
+ }
1125
+ if (github.isMergeQueueEnabled || github.isInMergeQueue) {
1126
+ throw new Error("Auto-merge is not available because this repository uses a merge queue");
1127
+ }
1128
+ }
1129
+ export function isPullRequestMergeMethodAllowed(repository, method) {
1130
+ if (method === "squash") {
1131
+ return repository.squashMergeAllowed;
1132
+ }
1133
+ if (method === "merge") {
1134
+ return repository.mergeCommitAllowed;
1135
+ }
1136
+ return repository.rebaseMergeAllowed;
1137
+ }
1138
+ export function computeGithubNextInterval(status, consecutiveErrors) {
1139
+ const baseInterval = isGitHubStatusPending(status)
1140
+ ? GITHUB_POLL_FAST_INTERVAL_MS
1141
+ : GITHUB_POLL_SLOW_INTERVAL_MS;
1142
+ if (consecutiveErrors <= 1) {
1143
+ return baseInterval;
1144
+ }
1145
+ return Math.min(baseInterval * 2 ** (consecutiveErrors - 1), GITHUB_POLL_ERROR_BACKOFF_CAP_MS);
1146
+ }
1147
+ function isGitHubStatusPending(status) {
1148
+ if (!status) {
1149
+ return false;
1150
+ }
1151
+ if (status.checksStatus === "pending") {
1152
+ return true;
1153
+ }
1154
+ return status.checks.some((check) => check.status === "pending");
1155
+ }
1156
+ async function resolveGhPath() {
1157
+ return findExecutable("gh");
1158
+ }
1159
+ async function runGhCommand(args, options) {
1160
+ return execCommand("gh", args, {
1161
+ cwd: options.cwd,
1162
+ envOverlay: { ...GITHUB_ENV, ...options.envOverlay },
1163
+ maxBuffer: 10 * 1024 * 1024,
1164
+ });
1165
+ }
1166
+ const GITHUB_ISSUE_OR_PR_URL_PATTERN = /^https?:\/\/github\.com\/[^/\s]+\/[^/\s]+\/(?:pull|issues)\/(\d+)(?:[/?#].*)?$/i;
1167
+ function normalizeGitHubSearchQuery(query) {
1168
+ const trimmed = query.trim();
1169
+ const match = trimmed.match(GITHUB_ISSUE_OR_PR_URL_PATTERN);
1170
+ return match ? match[1] : query;
1171
+ }
1172
+ function buildCacheKey(params) {
1173
+ return `${params.cwd}:${params.method}:${stableStringify(params.args)}`;
1174
+ }
1175
+ function stableStringify(value) {
1176
+ return JSON.stringify(sortJsonValue(value));
1177
+ }
1178
+ function sortJsonValue(value) {
1179
+ if (Array.isArray(value)) {
1180
+ return value.map(sortJsonValue);
1181
+ }
1182
+ if (!value || typeof value !== "object") {
1183
+ return value;
1184
+ }
1185
+ const entries = Object.entries(value).sort(([left], [right]) => left.localeCompare(right));
1186
+ const sorted = {};
1187
+ for (const [key, entryValue] of entries) {
1188
+ sorted[key] = sortJsonValue(entryValue);
1189
+ }
1190
+ return sorted;
1191
+ }
1192
+ function normalizeGitHubCommandError(error, context) {
1193
+ if (error instanceof GitHubAuthenticationError) {
1194
+ return error;
1195
+ }
1196
+ if (error instanceof GitHubCommandError) {
1197
+ if (isAuthFailureText(error.stderr)) {
1198
+ return new GitHubAuthenticationError({ stderr: error.stderr });
1199
+ }
1200
+ return error;
1201
+ }
1202
+ const failure = toCommandFailureLike(error);
1203
+ if (failure.code === "ENOENT") {
1204
+ return new GitHubCliMissingError();
1205
+ }
1206
+ const stderr = bufferOrStringToString(failure.stderr);
1207
+ const message = failure.message ?? "";
1208
+ if (isAuthFailureText(stderr) || isAuthFailureText(message)) {
1209
+ return new GitHubAuthenticationError({ stderr });
1210
+ }
1211
+ return new GitHubCommandError({
1212
+ args: context.args,
1213
+ cwd: context.cwd,
1214
+ exitCode: typeof failure.code === "number" ? failure.code : null,
1215
+ stderr: stderr || message,
1216
+ });
1217
+ }
1218
+ function toCommandFailureLike(error) {
1219
+ if (!error || typeof error !== "object") {
1220
+ return { message: String(error) };
1221
+ }
1222
+ const record = error;
1223
+ return {
1224
+ code: typeof record.code === "string" || typeof record.code === "number" || record.code === null
1225
+ ? record.code
1226
+ : undefined,
1227
+ stderr: typeof record.stderr === "string" || Buffer.isBuffer(record.stderr)
1228
+ ? record.stderr
1229
+ : undefined,
1230
+ stdout: typeof record.stdout === "string" || Buffer.isBuffer(record.stdout)
1231
+ ? record.stdout
1232
+ : undefined,
1233
+ message: typeof record.message === "string" ? record.message : undefined,
1234
+ };
1235
+ }
1236
+ function bufferOrStringToString(value) {
1237
+ if (Buffer.isBuffer(value)) {
1238
+ return value.toString("utf8");
1239
+ }
1240
+ return value ?? "";
1241
+ }
1242
+ function isGitHubAuthenticationError(error) {
1243
+ return error instanceof GitHubAuthenticationError;
1244
+ }
1245
+ function isAuthFailureText(text) {
1246
+ const normalized = text.toLowerCase();
1247
+ return (normalized.includes("gh auth login") ||
1248
+ normalized.includes("not logged into any github hosts") ||
1249
+ normalized.includes("authentication failed") ||
1250
+ normalized.includes("authentication required") ||
1251
+ normalized.includes("bad credentials") ||
1252
+ normalized.includes("http 401"));
1253
+ }
1254
+ function isNoPullRequestFoundError(error) {
1255
+ if (!(error instanceof GitHubCommandError)) {
1256
+ return false;
1257
+ }
1258
+ const text = error.stderr.toLowerCase();
1259
+ return text.includes("no pull requests found");
1260
+ }
1261
+ function isStatusCheckRollupPermissionError(error) {
1262
+ if (!(error instanceof GitHubCommandError)) {
1263
+ return false;
1264
+ }
1265
+ return error.stderr.toLowerCase().includes("statuscheckrollup");
1266
+ }
1267
+ async function resolveCurrentPullRequestView(options) {
1268
+ const viewCandidate = await tryCurrentPullRequestView(options);
1269
+ const viewMatch = viewCandidate
1270
+ ? pickPullRequestCandidate({
1271
+ candidates: [viewCandidate],
1272
+ headRef: options.headRef,
1273
+ headRepositoryOwner: options.headRepositoryOwner,
1274
+ })
1275
+ : null;
1276
+ if (viewMatch) {
1277
+ return viewMatch.status;
1278
+ }
1279
+ let listHeadRef = options.headRef;
1280
+ let listRepo;
1281
+ let headRepositoryOwner = options.headRepositoryOwner;
1282
+ if (!headRepositoryOwner) {
1283
+ const repo = await getGitHubRepoView(options);
1284
+ const forkOwner = repo?.owner?.login;
1285
+ const parentOwner = repo?.parent?.owner?.login;
1286
+ const parentName = repo?.parent?.name;
1287
+ if (!forkOwner || !parentOwner || !parentName) {
1288
+ return null;
1289
+ }
1290
+ listHeadRef = `${forkOwner}:${options.headRef}`;
1291
+ listRepo = `${parentOwner}/${parentName}`;
1292
+ headRepositoryOwner = forkOwner;
1293
+ }
1294
+ const candidates = await listCurrentPullRequestCandidates({
1295
+ cwd: options.cwd,
1296
+ headRef: listHeadRef,
1297
+ run: options.run,
1298
+ repo: listRepo,
1299
+ });
1300
+ const match = pickPullRequestCandidate({
1301
+ candidates,
1302
+ headRef: options.headRef,
1303
+ headRepositoryOwner,
1304
+ });
1305
+ return match?.status ?? null;
1306
+ }
1307
+ async function addCurrentPullRequestGithubFacts(options) {
1308
+ const { status } = options;
1309
+ if (!status?.repoOwner || !status.repoName || typeof status.number !== "number") {
1310
+ return status;
1311
+ }
1312
+ const facts = await loadPullRequestGithubFacts({
1313
+ cwd: options.cwd,
1314
+ owner: status.repoOwner,
1315
+ name: status.repoName,
1316
+ number: status.number,
1317
+ run: options.run,
1318
+ });
1319
+ if (!facts) {
1320
+ return status;
1321
+ }
1322
+ return {
1323
+ ...status,
1324
+ github: facts,
1325
+ };
1326
+ }
1327
+ async function loadPullRequestGithubFacts(options) {
1328
+ try {
1329
+ const stdout = await options.run([
1330
+ "api",
1331
+ "graphql",
1332
+ "-f",
1333
+ `query=${PULL_REQUEST_STATUS_FACTS_QUERY}`,
1334
+ "-F",
1335
+ `owner=${options.owner}`,
1336
+ "-F",
1337
+ `name=${options.name}`,
1338
+ "-F",
1339
+ `number=${options.number}`,
1340
+ ], { cwd: options.cwd });
1341
+ return parsePullRequestGithubFacts(stdout);
1342
+ }
1343
+ catch (error) {
1344
+ if (error instanceof GitHubCommandError ||
1345
+ error instanceof z.ZodError ||
1346
+ error instanceof SyntaxError) {
1347
+ return null;
1348
+ }
1349
+ throw error;
1350
+ }
1351
+ }
1352
+ async function tryCurrentPullRequestView(options) {
1353
+ try {
1354
+ const stdout = await runCurrentPullRequestStatusCommand({
1355
+ cwd: options.cwd,
1356
+ run: options.run,
1357
+ args: ["pr", "view"],
1358
+ });
1359
+ return parseCurrentPullRequestCandidate(stdout, options.headRef);
1360
+ }
1361
+ catch (error) {
1362
+ if (isNoPullRequestFoundError(error)) {
1363
+ return null;
1364
+ }
1365
+ throw error;
1366
+ }
1367
+ }
1368
+ async function listCurrentPullRequestCandidates(options) {
1369
+ const args = ["pr", "list"];
1370
+ if (options.repo) {
1371
+ args.push("--repo", options.repo);
1372
+ }
1373
+ args.push("--state", "all", "--head", options.headRef, "--limit", "10");
1374
+ try {
1375
+ const stdout = await runCurrentPullRequestStatusCommand({
1376
+ cwd: options.cwd,
1377
+ run: options.run,
1378
+ args,
1379
+ });
1380
+ return parseCurrentPullRequestCandidateList(stdout, options.headRef);
1381
+ }
1382
+ catch (error) {
1383
+ if (isNoPullRequestFoundError(error)) {
1384
+ return [];
1385
+ }
1386
+ throw error;
1387
+ }
1388
+ }
1389
+ async function runCurrentPullRequestStatusCommand(options) {
1390
+ try {
1391
+ return await options.run([...options.args, "--json", CURRENT_PR_STATUS_FIELDS], {
1392
+ cwd: options.cwd,
1393
+ });
1394
+ }
1395
+ catch (error) {
1396
+ if (!isStatusCheckRollupPermissionError(error)) {
1397
+ throw error;
1398
+ }
1399
+ return options.run([...options.args, "--json", CURRENT_PR_STATUS_BASE_FIELDS], {
1400
+ cwd: options.cwd,
1401
+ });
1402
+ }
1403
+ }
1404
+ async function getGitHubRepoView(options) {
1405
+ try {
1406
+ const stdout = await options.run(["repo", "view", "--json", "owner,name,parent"], {
1407
+ cwd: options.cwd,
1408
+ });
1409
+ return GitHubRepoViewSchema.parse(JSON.parse(stdout || "{}"));
1410
+ }
1411
+ catch {
1412
+ return null;
1413
+ }
1414
+ }
1415
+ function parseCurrentPullRequestCandidate(stdout, fallbackHeadRefName) {
1416
+ const item = CurrentPullRequestStatusSchema.parse(JSON.parse(stdout || "{}"));
1417
+ return toCurrentPullRequestCandidate(item, fallbackHeadRefName);
1418
+ }
1419
+ function parseCurrentPullRequestCandidateList(stdout, fallbackHeadRefName) {
1420
+ const items = z.array(CurrentPullRequestStatusSchema).parse(JSON.parse(stdout || "[]"));
1421
+ return items
1422
+ .map((item) => toCurrentPullRequestCandidate(item, fallbackHeadRefName))
1423
+ .filter((candidate) => candidate !== null);
1424
+ }
1425
+ function parsePullRequestGithubFacts(stdout) {
1426
+ const parsed = GitHubPullRequestFactsGraphqlSchema.parse(JSON.parse(stdout || "{}"));
1427
+ const repository = parsed.data.repository;
1428
+ const pullRequest = repository?.pullRequest;
1429
+ if (!repository || !pullRequest) {
1430
+ return null;
1431
+ }
1432
+ return {
1433
+ mergeStateStatus: pullRequest.mergeStateStatus ?? null,
1434
+ autoMergeRequest: toGitHubAutoMergeRequest(pullRequest.autoMergeRequest),
1435
+ viewerCanEnableAutoMerge: pullRequest.viewerCanEnableAutoMerge ?? false,
1436
+ viewerCanDisableAutoMerge: pullRequest.viewerCanDisableAutoMerge ?? false,
1437
+ viewerCanMergeAsAdmin: pullRequest.viewerCanMergeAsAdmin ?? false,
1438
+ viewerCanUpdateBranch: pullRequest.viewerCanUpdateBranch ?? false,
1439
+ repository: toGitHubRepositoryMergePolicy(repository),
1440
+ isMergeQueueEnabled: pullRequest.isMergeQueueEnabled ?? false,
1441
+ isInMergeQueue: pullRequest.isInMergeQueue ?? false,
1442
+ };
1443
+ }
1444
+ function toGitHubAutoMergeRequest(request) {
1445
+ if (!request) {
1446
+ return null;
1447
+ }
1448
+ return {
1449
+ enabledAt: request.enabledAt ?? null,
1450
+ mergeMethod: request.mergeMethod ?? null,
1451
+ enabledBy: request.enabledBy?.login ?? null,
1452
+ };
1453
+ }
1454
+ function toGitHubRepositoryMergePolicy(repository) {
1455
+ return {
1456
+ autoMergeAllowed: repository.autoMergeAllowed ?? false,
1457
+ mergeCommitAllowed: repository.mergeCommitAllowed ?? false,
1458
+ squashMergeAllowed: repository.squashMergeAllowed ?? false,
1459
+ rebaseMergeAllowed: repository.rebaseMergeAllowed ?? false,
1460
+ viewerDefaultMergeMethod: repository.viewerDefaultMergeMethod ?? null,
1461
+ };
1462
+ }
1463
+ function toCurrentPullRequestCandidate(item, fallbackHeadRefName) {
1464
+ const status = toCurrentPullRequestStatus(item, fallbackHeadRefName);
1465
+ if (!status) {
1466
+ return null;
1467
+ }
1468
+ const headRepositoryOwner = item.headRepositoryOwner?.login;
1469
+ return {
1470
+ status,
1471
+ ...(headRepositoryOwner ? { headRepositoryOwner } : {}),
1472
+ };
1473
+ }
1474
+ function isCandidateForHeadRef(candidate, headRef) {
1475
+ return candidate.status.headRefName === headRef && hasResolvedRepoIdentity(candidate.status);
1476
+ }
1477
+ function hasResolvedRepoIdentity(status) {
1478
+ return Boolean(status.repoOwner && status.repoName);
1479
+ }
1480
+ function pickPullRequestCandidate(options) {
1481
+ const matching = options.candidates.filter((candidate) => {
1482
+ if (!isCandidateForHeadRef(candidate, options.headRef)) {
1483
+ return false;
1484
+ }
1485
+ if (!options.headRepositoryOwner) {
1486
+ return true;
1487
+ }
1488
+ return candidate.headRepositoryOwner === options.headRepositoryOwner;
1489
+ });
1490
+ matching.sort(comparePullRequestCandidatePreference);
1491
+ return matching[0] ?? null;
1492
+ }
1493
+ function comparePullRequestCandidatePreference(left, right) {
1494
+ return getPullRequestStateRank(left.status) - getPullRequestStateRank(right.status);
1495
+ }
1496
+ function getPullRequestStateRank(status) {
1497
+ if (status.state === "open" || status.isDraft) {
1498
+ return 0;
1499
+ }
1500
+ if (status.state === "merged") {
1501
+ return 1;
1502
+ }
1503
+ return 2;
1504
+ }
1505
+ function parsePullRequestSummaries(stdout) {
1506
+ const parsed = z.array(HostingPullRequestSummarySchema).parse(JSON.parse(stdout || "[]"));
1507
+ return parsed.map(toPullRequestSummary);
1508
+ }
1509
+ function parsePullRequestSummary(stdout) {
1510
+ return toPullRequestSummary(HostingPullRequestSummarySchema.parse(JSON.parse(stdout || "{}")));
1511
+ }
1512
+ function parsePullRequestCheckoutTarget(stdout) {
1513
+ const parsed = PullRequestCheckoutTargetSchema.parse(JSON.parse(stdout || "{}"));
1514
+ const pullRequest = parsed.data.repository.pullRequest;
1515
+ if (!pullRequest) {
1516
+ throw new Error("Pull request not found");
1517
+ }
1518
+ return {
1519
+ number: pullRequest.number,
1520
+ baseRefName: pullRequest.baseRefName,
1521
+ headRefName: pullRequest.headRefName,
1522
+ headOwnerLogin: pullRequest.headRepositoryOwner?.login || null,
1523
+ headRepositorySshUrl: pullRequest.headRepository?.sshUrl || null,
1524
+ headRepositoryUrl: pullRequest.headRepository?.url || null,
1525
+ isCrossRepository: pullRequest.isCrossRepository,
1526
+ };
1527
+ }
1528
+ function toPullRequestSummary(item) {
1529
+ return {
1530
+ number: item.number,
1531
+ title: item.title,
1532
+ url: item.url,
1533
+ state: item.state,
1534
+ body: item.body,
1535
+ baseRefName: item.baseRefName,
1536
+ headRefName: item.headRefName,
1537
+ labels: item.labels.map((label) => label.name ?? "").filter((name) => name.length > 0),
1538
+ updatedAt: item.updatedAt,
1539
+ };
1540
+ }
1541
+ function parseIssueSummaries(stdout) {
1542
+ const parsed = z.array(GitHubIssueSummarySchema).parse(JSON.parse(stdout || "[]"));
1543
+ return parsed.map((item) => ({
1544
+ number: item.number,
1545
+ title: item.title,
1546
+ url: item.url,
1547
+ state: item.state,
1548
+ body: item.body,
1549
+ labels: item.labels.map((label) => label.name ?? "").filter((name) => name.length > 0),
1550
+ updatedAt: item.updatedAt,
1551
+ }));
1552
+ }
1553
+ function parsePullRequestTimeline(stdout, identity) {
1554
+ const parsed = PullRequestTimelineGraphqlSchema.parse(JSON.parse(stdout || "{}"));
1555
+ const pullRequest = parsed.data?.repository?.pullRequest;
1556
+ const reviewThreadItems = pullRequest
1557
+ ? pullRequest.reviewThreads.nodes.flatMap(toPullRequestTimelineReviewThreadItems)
1558
+ : [];
1559
+ const reviewThreadItemIds = new Set(reviewThreadItems.map((item) => item.id).filter((id) => id.length > 0));
1560
+ const items = pullRequest
1561
+ ? [
1562
+ ...pullRequest.reviews.nodes.flatMap(toPullRequestTimelineReviewItem),
1563
+ ...pullRequest.comments.nodes
1564
+ .filter((comment) => !reviewThreadItemIds.has(comment.id))
1565
+ .map(toPullRequestTimelineCommentItem),
1566
+ ...reviewThreadItems,
1567
+ ].sort(compareTimelineItems)
1568
+ : [];
1569
+ return {
1570
+ prNumber: pullRequest?.number ?? identity.prNumber,
1571
+ repoOwner: identity.repoOwner,
1572
+ repoName: identity.repoName,
1573
+ items,
1574
+ // S3 deliberately caps timeline fetches at the first 100 reviews, comments, and review threads.
1575
+ truncated: Boolean(pullRequest?.reviews.pageInfo.hasNextPage ||
1576
+ pullRequest?.comments.pageInfo.hasNextPage ||
1577
+ pullRequest?.reviewThreads.pageInfo.hasNextPage ||
1578
+ pullRequest?.reviewThreads.nodes.some((thread) => thread.comments.pageInfo.hasNextPage)),
1579
+ error: pullRequest ? null : { kind: "not_found", message: "Pull request not found" },
1580
+ };
1581
+ }
1582
+ function toPullRequestTimelineReviewItem(review) {
1583
+ const reviewState = mapTimelineReviewState(review.state, review.body ?? "");
1584
+ if (!reviewState) {
1585
+ return [];
1586
+ }
1587
+ return [
1588
+ {
1589
+ kind: "review",
1590
+ id: review.id,
1591
+ author: review.author?.login ?? "unknown",
1592
+ authorUrl: review.author?.url ?? null,
1593
+ avatarUrl: review.author?.avatarUrl ?? null,
1594
+ body: normalizeGitHubTimelineBody(review.body ?? "", review.bodyHTML ?? ""),
1595
+ createdAt: parseOptionalTime(review.submittedAt ?? null),
1596
+ url: review.url,
1597
+ reviewState,
1598
+ },
1599
+ ];
1600
+ }
1601
+ function toPullRequestTimelineCommentItem(comment) {
1602
+ return {
1603
+ kind: "comment",
1604
+ id: comment.id,
1605
+ author: comment.author?.login ?? "unknown",
1606
+ authorUrl: comment.author?.url ?? null,
1607
+ avatarUrl: comment.author?.avatarUrl ?? null,
1608
+ body: normalizeGitHubTimelineBody(comment.body ?? "", comment.bodyHTML ?? ""),
1609
+ createdAt: parseOptionalTime(comment.createdAt ?? null),
1610
+ url: comment.url,
1611
+ };
1612
+ }
1613
+ const RAW_MARKDOWN_IMAGE_RE = /!\[[^\]]*\]\(\s*([^\s)]+)(?:\s+["'][^)]*["'])?\s*\)/g;
1614
+ const HTML_IMAGE_RE = /<img\b[^>]*\bsrc\s*=\s*(["'])(.*?)\1[^>]*>/gi;
1615
+ const GITHUB_RENDERED_IMAGE_HOSTS = new Set([
1616
+ "camo.githubusercontent.com",
1617
+ "private-user-images.githubusercontent.com",
1618
+ ]);
1619
+ function normalizeGitHubTimelineBody(body, bodyHTML) {
1620
+ const rawImages = extractRawImageSourceReferences(body);
1621
+ if (rawImages.length === 0) {
1622
+ return body;
1623
+ }
1624
+ const renderedSources = extractRenderedImageSources(bodyHTML);
1625
+ if (renderedSources.length !== rawImages.length) {
1626
+ return body;
1627
+ }
1628
+ let cursor = 0;
1629
+ let normalized = "";
1630
+ for (let index = 0; index < rawImages.length; index += 1) {
1631
+ const rawImage = rawImages[index];
1632
+ const renderedSrc = renderedSources[index];
1633
+ if (!rawImage ||
1634
+ !renderedSrc ||
1635
+ !isRawGitHubAttachmentSource(rawImage.src) ||
1636
+ !isGitHubRenderedImageSource(renderedSrc)) {
1637
+ return body;
1638
+ }
1639
+ normalized += body.slice(cursor, rawImage.start);
1640
+ normalized += renderedSrc;
1641
+ cursor = rawImage.end;
1642
+ }
1643
+ normalized += body.slice(cursor);
1644
+ return normalized;
1645
+ }
1646
+ function extractRawImageSourceReferences(source) {
1647
+ const references = [
1648
+ ...extractHtmlImageSourceReferences(source),
1649
+ ...extractMarkdownImageSourceReferences(source),
1650
+ ];
1651
+ return references.sort((left, right) => left.start - right.start);
1652
+ }
1653
+ function extractRenderedImageSources(source) {
1654
+ return extractHtmlImageSourceReferences(source).map((reference) => reference.src);
1655
+ }
1656
+ function extractHtmlImageSourceReferences(source) {
1657
+ const references = [];
1658
+ HTML_IMAGE_RE.lastIndex = 0;
1659
+ let match;
1660
+ while ((match = HTML_IMAGE_RE.exec(source)) !== null) {
1661
+ const src = decodeHtmlAttribute(match[2] ?? "");
1662
+ if (!src) {
1663
+ continue;
1664
+ }
1665
+ const rawAttributeSrc = match[2] ?? "";
1666
+ const start = match.index + match[0].indexOf(rawAttributeSrc);
1667
+ references.push({ src, start, end: start + rawAttributeSrc.length });
1668
+ }
1669
+ return references;
1670
+ }
1671
+ function extractMarkdownImageSourceReferences(source) {
1672
+ const references = [];
1673
+ RAW_MARKDOWN_IMAGE_RE.lastIndex = 0;
1674
+ let match;
1675
+ while ((match = RAW_MARKDOWN_IMAGE_RE.exec(source)) !== null) {
1676
+ const src = match[1] ?? "";
1677
+ if (!src) {
1678
+ continue;
1679
+ }
1680
+ const start = match.index + match[0].indexOf(src);
1681
+ references.push({ src, start, end: start + src.length });
1682
+ }
1683
+ return references;
1684
+ }
1685
+ function isRawGitHubAttachmentSource(src) {
1686
+ try {
1687
+ const url = new URL(src);
1688
+ return (url.protocol === "https:" &&
1689
+ url.hostname === "github.com" &&
1690
+ url.pathname.startsWith("/user-attachments/assets/"));
1691
+ }
1692
+ catch {
1693
+ return false;
1694
+ }
1695
+ }
1696
+ function isGitHubRenderedImageSource(src) {
1697
+ try {
1698
+ const url = new URL(src);
1699
+ return url.protocol === "https:" && GITHUB_RENDERED_IMAGE_HOSTS.has(url.hostname);
1700
+ }
1701
+ catch {
1702
+ return false;
1703
+ }
1704
+ }
1705
+ function decodeHtmlAttribute(value) {
1706
+ return value
1707
+ .replaceAll("&amp;", "&")
1708
+ .replaceAll("&quot;", '"')
1709
+ .replaceAll("&#39;", "'")
1710
+ .replaceAll("&lt;", "<")
1711
+ .replaceAll("&gt;", ">");
1712
+ }
1713
+ function toPullRequestTimelineReviewThreadItems(thread) {
1714
+ return thread.comments.nodes.map((comment) => ({
1715
+ ...toPullRequestTimelineCommentItem(comment),
1716
+ ...(comment.pullRequestReview?.id ? { reviewId: comment.pullRequestReview.id } : {}),
1717
+ location: {
1718
+ path: thread.path,
1719
+ ...(thread.line !== null && thread.line !== undefined ? { line: thread.line } : {}),
1720
+ ...(thread.startLine !== null && thread.startLine !== undefined
1721
+ ? { startLine: thread.startLine }
1722
+ : {}),
1723
+ ...(thread.id ? { threadId: thread.id } : {}),
1724
+ isResolved: thread.isResolved,
1725
+ isOutdated: thread.isOutdated,
1726
+ },
1727
+ }));
1728
+ }
1729
+ function parseGitHubCheckRunDetails(stdout) {
1730
+ const parsed = GitHubCheckRunDetailsSchema.parse(JSON.parse(stdout || "{}"));
1731
+ return {
1732
+ checkRunId: parsed.id,
1733
+ workflowRunId: parsed.check_suite?.workflow_run?.id ?? null,
1734
+ name: parsed.name,
1735
+ status: parsed.status,
1736
+ conclusion: parsed.conclusion,
1737
+ url: parsed.html_url,
1738
+ detailsUrl: parsed.details_url,
1739
+ output: parsed.output,
1740
+ annotations: [],
1741
+ failedJobs: [],
1742
+ truncated: false,
1743
+ };
1744
+ }
1745
+ function parseGitHubCheckAnnotations(stdout) {
1746
+ return GitHubCheckAnnotationsSchema.parse(JSON.parse(stdout || "[]")).map((annotation) => {
1747
+ const result = {};
1748
+ if (annotation.path)
1749
+ result.path = annotation.path;
1750
+ if (annotation.start_line !== undefined)
1751
+ result.startLine = annotation.start_line;
1752
+ if (annotation.end_line !== undefined)
1753
+ result.endLine = annotation.end_line;
1754
+ if (annotation.annotation_level)
1755
+ result.annotationLevel = annotation.annotation_level;
1756
+ if (annotation.message)
1757
+ result.message = annotation.message;
1758
+ if (annotation.title)
1759
+ result.title = annotation.title;
1760
+ if (annotation.raw_details)
1761
+ result.rawDetails = annotation.raw_details;
1762
+ return result;
1763
+ });
1764
+ }
1765
+ function parseGitHubActionsJobs(stdout) {
1766
+ return GitHubActionsJobsSchema.parse(JSON.parse(stdout || "{}")).jobs.map((job) => {
1767
+ const result = {
1768
+ jobId: job.id,
1769
+ name: job.name,
1770
+ status: job.status,
1771
+ conclusion: job.conclusion,
1772
+ url: job.html_url,
1773
+ };
1774
+ if (job.completed_at)
1775
+ result.completedAt = job.completed_at;
1776
+ return result;
1777
+ });
1778
+ }
1779
+ function isFailedActionsJob(job) {
1780
+ return (job.conclusion === "failure" ||
1781
+ job.conclusion === "cancelled" ||
1782
+ job.conclusion === "timed_out" ||
1783
+ job.conclusion === "action_required");
1784
+ }
1785
+ async function getCachedCheckLogTail(input) {
1786
+ const key = `${input.job.jobId}:${input.job.completedAt ?? ""}`;
1787
+ const cached = input.cache.get(key);
1788
+ if (cached) {
1789
+ input.cache.delete(key);
1790
+ input.cache.set(key, cached);
1791
+ return cached;
1792
+ }
1793
+ const capped = capCheckLogTail(await input.run(["api", `${input.repoPath}/actions/jobs/${input.job.jobId}/logs`], {
1794
+ cwd: input.cwd,
1795
+ }));
1796
+ input.cache.set(key, capped);
1797
+ while (input.cache.size > CHECK_LOG_TAIL_CACHE_MAX_ENTRIES) {
1798
+ const oldestKey = input.cache.keys().next().value;
1799
+ if (!oldestKey) {
1800
+ break;
1801
+ }
1802
+ input.cache.delete(oldestKey);
1803
+ }
1804
+ return capped;
1805
+ }
1806
+ function capCheckLogTail(log) {
1807
+ const lines = log.split("\n");
1808
+ let truncated = lines.length > CHECK_LOG_TAIL_MAX_LINES;
1809
+ let tail = lines.slice(-CHECK_LOG_TAIL_MAX_LINES).join("\n");
1810
+ if (Buffer.byteLength(tail, "utf8") > CHECK_LOG_TAIL_MAX_BYTES) {
1811
+ truncated = true;
1812
+ tail = utf8SuffixWithinBytes(tail, CHECK_LOG_TAIL_MAX_BYTES);
1813
+ }
1814
+ return { logTail: tail, logTruncated: truncated };
1815
+ }
1816
+ function utf8SuffixWithinBytes(value, maxBytes) {
1817
+ let lowerBound = 0;
1818
+ let upperBound = value.length;
1819
+ while (lowerBound < upperBound) {
1820
+ const midpoint = Math.floor((lowerBound + upperBound) / 2);
1821
+ if (Buffer.byteLength(value.slice(midpoint), "utf8") > maxBytes) {
1822
+ lowerBound = midpoint + 1;
1823
+ }
1824
+ else {
1825
+ upperBound = midpoint;
1826
+ }
1827
+ }
1828
+ return value.slice(lowerBound);
1829
+ }
1830
+ function mapTimelineReviewState(state, body) {
1831
+ switch (state) {
1832
+ case "APPROVED":
1833
+ return "approved";
1834
+ case "CHANGES_REQUESTED":
1835
+ return "changes_requested";
1836
+ case "COMMENTED":
1837
+ return "commented";
1838
+ case "DISMISSED":
1839
+ case "PENDING":
1840
+ return body.trim().length > 0 ? "commented" : null;
1841
+ default:
1842
+ return body.trim().length > 0 ? "commented" : null;
1843
+ }
1844
+ }
1845
+ function compareTimelineItems(left, right) {
1846
+ if (left.createdAt !== right.createdAt) {
1847
+ return left.createdAt - right.createdAt;
1848
+ }
1849
+ return left.id.localeCompare(right.id);
1850
+ }
1851
+ function mapPullRequestTimelineError(error) {
1852
+ if (error instanceof GitHubCommandError) {
1853
+ return {
1854
+ kind: classifyPullRequestTimelineError(error.stderr),
1855
+ message: error.stderr || error.message,
1856
+ };
1857
+ }
1858
+ if (error instanceof GitHubAuthenticationError) {
1859
+ return {
1860
+ kind: "forbidden",
1861
+ message: error.stderr || error.message,
1862
+ };
1863
+ }
1864
+ return {
1865
+ kind: "unknown",
1866
+ message: error instanceof Error ? error.message : String(error),
1867
+ };
1868
+ }
1869
+ function classifyPullRequestTimelineError(stderr) {
1870
+ const normalized = stderr.toLowerCase();
1871
+ if (normalized.includes("could not resolve to a pullrequest") ||
1872
+ normalized.includes("pull request not found") ||
1873
+ normalized.includes("pullrequest not found")) {
1874
+ return "not_found";
1875
+ }
1876
+ if (normalized.includes("forbidden") ||
1877
+ normalized.includes("resource not accessible") ||
1878
+ normalized.includes("permission") ||
1879
+ normalized.includes("access denied") ||
1880
+ normalized.includes("requires authentication") ||
1881
+ normalized.includes("http 403")) {
1882
+ return "forbidden";
1883
+ }
1884
+ return "unknown";
1885
+ }
1886
+ function toCurrentPullRequestStatus(item, fallbackHeadRefName) {
1887
+ if (!item.url || !item.title) {
1888
+ return null;
1889
+ }
1890
+ const repoIdentity = parseGitHubPullRequestRepo(item.url);
1891
+ const mergedAt = typeof item.mergedAt === "string" && item.mergedAt.trim().length > 0 ? item.mergedAt : null;
1892
+ let state;
1893
+ if (mergedAt !== null) {
1894
+ state = "merged";
1895
+ }
1896
+ else if (item.state.trim().length > 0) {
1897
+ state = item.state.toLowerCase();
1898
+ }
1899
+ else {
1900
+ state = "";
1901
+ }
1902
+ const checks = parseStatusCheckRollup(item.statusCheckRollup);
1903
+ return {
1904
+ ...(typeof item.number === "number" ? { number: item.number } : {}),
1905
+ ...(repoIdentity ? { repoOwner: repoIdentity.owner, repoName: repoIdentity.name } : {}),
1906
+ url: item.url,
1907
+ title: item.title,
1908
+ state,
1909
+ baseRefName: item.baseRefName,
1910
+ headRefName: item.headRefName || fallbackHeadRefName,
1911
+ isMerged: mergedAt !== null,
1912
+ isDraft: item.isDraft ?? false,
1913
+ mergeable: item.mergeable,
1914
+ checks,
1915
+ checksStatus: computeChecksStatus(checks),
1916
+ reviewDecision: mapReviewDecision(item.reviewDecision),
1917
+ };
1918
+ }
1919
+ function parseGitHubPullRequestRepo(url) {
1920
+ try {
1921
+ const parsed = new URL(url);
1922
+ if (parsed.hostname !== "github.com") {
1923
+ return null;
1924
+ }
1925
+ const [owner, name, kind] = parsed.pathname.split("/").filter(Boolean);
1926
+ if (!owner || !name || kind !== "pull") {
1927
+ return null;
1928
+ }
1929
+ return { owner, name };
1930
+ }
1931
+ catch {
1932
+ return null;
1933
+ }
1934
+ }
1935
+ export function parseStatusCheckRollup(value) {
1936
+ const directContexts = PullRequestStatusCheckRollupArraySchema.safeParse(value);
1937
+ if (!directContexts.success) {
1938
+ const legacyContexts = LegacyPullRequestStatusCheckRollupSchema.safeParse(value);
1939
+ if (!legacyContexts.success) {
1940
+ return [];
1941
+ }
1942
+ return parseStatusCheckRollup(legacyContexts.data.contexts);
1943
+ }
1944
+ const dedupedChecks = new Map();
1945
+ for (const entry of directContexts.data) {
1946
+ const parsed = PullRequestStatusCheckRollupNodeSchema.safeParse(entry);
1947
+ if (!parsed.success) {
1948
+ continue;
1949
+ }
1950
+ const check = buildPullRequestCheck(parsed.data);
1951
+ if (!check) {
1952
+ continue;
1953
+ }
1954
+ const existing = dedupedChecks.get(check.name);
1955
+ if (!existing || check.recency > existing.recency) {
1956
+ dedupedChecks.set(check.name, check);
1957
+ }
1958
+ }
1959
+ return Array.from(dedupedChecks.values(), ({ recency: _recency, ...check }) => check);
1960
+ }
1961
+ function buildPullRequestCheck(context) {
1962
+ if (context.__typename === "CheckRun") {
1963
+ return {
1964
+ name: context.name,
1965
+ status: mapCheckRunStatus(context.status, context.conclusion),
1966
+ url: typeof context.detailsUrl === "string" ? context.detailsUrl : null,
1967
+ ...(typeof context.workflowName === "string" && context.workflowName.trim().length > 0
1968
+ ? { workflow: context.workflowName }
1969
+ : {}),
1970
+ ...(typeof context.databaseId === "number" ? { checkRunId: context.databaseId } : {}),
1971
+ ...(typeof context.checkSuite?.workflowRun?.databaseId === "number"
1972
+ ? { workflowRunId: context.checkSuite.workflowRun.databaseId }
1973
+ : {}),
1974
+ ...formatCheckRunDuration(context),
1975
+ recency: getCheckRunRecency(context),
1976
+ };
1977
+ }
1978
+ if (context.__typename === "StatusContext") {
1979
+ return {
1980
+ name: context.context,
1981
+ status: mapStatusContextState(context.state),
1982
+ url: typeof context.targetUrl === "string" ? context.targetUrl : null,
1983
+ recency: getStatusContextRecency(context),
1984
+ };
1985
+ }
1986
+ return null;
1987
+ }
1988
+ function mapCheckRunStatus(status, conclusion) {
1989
+ if (status !== "COMPLETED") {
1990
+ return "pending";
1991
+ }
1992
+ switch (conclusion) {
1993
+ case "SUCCESS":
1994
+ return "success";
1995
+ case "FAILURE":
1996
+ case "TIMED_OUT":
1997
+ case "ACTION_REQUIRED":
1998
+ return "failure";
1999
+ case "CANCELLED":
2000
+ return "cancelled";
2001
+ case "SKIPPED":
2002
+ case "NEUTRAL":
2003
+ return "skipped";
2004
+ default:
2005
+ return "pending";
2006
+ }
2007
+ }
2008
+ function mapStatusContextState(state) {
2009
+ switch (state) {
2010
+ case "SUCCESS":
2011
+ return "success";
2012
+ case "FAILURE":
2013
+ case "ERROR":
2014
+ return "failure";
2015
+ case "EXPECTED":
2016
+ case "PENDING":
2017
+ return "pending";
2018
+ default:
2019
+ return "pending";
2020
+ }
2021
+ }
2022
+ function getCheckRunRecency(context) {
2023
+ const workflowRunId = context.checkSuite?.workflowRun?.databaseId;
2024
+ if (typeof workflowRunId === "number") {
2025
+ return workflowRunId;
2026
+ }
2027
+ return parseOptionalTime(context.completedAt ?? context.startedAt ?? null);
2028
+ }
2029
+ function formatCheckRunDuration(context) {
2030
+ const startedAt = parseOptionalTime(context.startedAt ?? null);
2031
+ const completedAt = parseOptionalTime(context.completedAt ?? null);
2032
+ if (startedAt <= 0 || completedAt <= 0 || completedAt < startedAt) {
2033
+ return {};
2034
+ }
2035
+ const durationSeconds = Math.floor((completedAt - startedAt) / 1000);
2036
+ return { duration: formatDurationSeconds(durationSeconds) };
2037
+ }
2038
+ function formatDurationSeconds(totalSeconds) {
2039
+ const hours = Math.floor(totalSeconds / 3600);
2040
+ const minutes = Math.floor((totalSeconds % 3600) / 60);
2041
+ const seconds = totalSeconds % 60;
2042
+ const parts = [];
2043
+ if (hours > 0) {
2044
+ parts.push(`${hours}h`);
2045
+ }
2046
+ if (minutes > 0) {
2047
+ parts.push(`${minutes}m`);
2048
+ }
2049
+ if (seconds > 0 || parts.length === 0) {
2050
+ parts.push(`${seconds}s`);
2051
+ }
2052
+ return parts.join(" ");
2053
+ }
2054
+ function getStatusContextRecency(context) {
2055
+ return parseOptionalTime(context.createdAt ?? null);
2056
+ }
2057
+ function parseOptionalTime(timestamp) {
2058
+ if (!timestamp) {
2059
+ return 0;
2060
+ }
2061
+ const time = Date.parse(timestamp);
2062
+ return Number.isNaN(time) ? 0 : time;
2063
+ }
2064
+ function computeChecksStatus(checks) {
2065
+ if (checks.length === 0) {
2066
+ return "none";
2067
+ }
2068
+ if (checks.some((check) => check.status === "failure")) {
2069
+ return "failure";
2070
+ }
2071
+ if (checks.some((check) => check.status === "pending")) {
2072
+ return "pending";
2073
+ }
2074
+ return "success";
2075
+ }
2076
+ function mapReviewDecision(value) {
2077
+ const reviewDecision = PullRequestReviewDecisionSchema.parse(value);
2078
+ if (reviewDecision === "APPROVED") {
2079
+ return "approved";
2080
+ }
2081
+ if (reviewDecision === "CHANGES_REQUESTED") {
2082
+ return "changes_requested";
2083
+ }
2084
+ if (reviewDecision === "REVIEW_REQUIRED") {
2085
+ return "pending";
2086
+ }
2087
+ return null;
2088
+ }
2089
+ // Resolves the "owner/name" identity of the origin remote for any supported
2090
+ // hosting provider (GitHub incl. SSH aliases, Bitbucket Cloud). The name
2091
+ // predates multi-provider support.
2092
+ export async function resolveGitHubRepo(cwd) {
2093
+ try {
2094
+ const { stdout } = await runGitCommand(["config", "--get", "remote.origin.url"], {
2095
+ cwd,
2096
+ env: { ...process.env, GIT_OPTIONAL_LOCKS: "0" },
2097
+ });
2098
+ const remoteUrl = stdout.trim();
2099
+ const github = await resolveGitHubRemote({ remoteUrl });
2100
+ if (github) {
2101
+ return github.repo;
2102
+ }
2103
+ return parseBitbucketCloudRemoteUrl(remoteUrl)?.repo ?? null;
2104
+ }
2105
+ catch {
2106
+ return null;
2107
+ }
2108
+ }
2109
+ //# sourceMappingURL=github-service.js.map