@shepai/cli 1.116.0 → 1.116.1-pr369.ea52340

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 (245) hide show
  1. package/dist/eslint.config.mjs +3 -0
  2. package/dist/packages/core/src/application/ports/output/services/git-pr-service.interface.d.ts +14 -0
  3. package/dist/packages/core/src/application/ports/output/services/git-pr-service.interface.d.ts.map +1 -1
  4. package/dist/packages/core/src/application/ports/output/services/worktree-service.interface.d.ts +2 -1
  5. package/dist/packages/core/src/application/ports/output/services/worktree-service.interface.d.ts.map +1 -1
  6. package/dist/packages/core/src/application/use-cases/features/cleanup-feature-worktree.use-case.d.ts.map +1 -1
  7. package/dist/packages/core/src/application/use-cases/features/cleanup-feature-worktree.use-case.js +6 -1
  8. package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.d.ts +3 -1
  9. package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.d.ts.map +1 -1
  10. package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.js +30 -2
  11. package/dist/packages/core/src/application/use-cases/features/delete-feature.use-case.js +1 -1
  12. package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
  13. package/dist/packages/core/src/infrastructure/di/container.js +4 -6
  14. package/dist/packages/core/src/infrastructure/services/agents/common/executors/claude-code-executor.service.d.ts.map +1 -1
  15. package/dist/packages/core/src/infrastructure/services/agents/common/executors/claude-code-executor.service.js +6 -1
  16. package/dist/packages/core/src/infrastructure/services/agents/common/executors/cursor-executor.service.d.ts +12 -1
  17. package/dist/packages/core/src/infrastructure/services/agents/common/executors/cursor-executor.service.d.ts.map +1 -1
  18. package/dist/packages/core/src/infrastructure/services/agents/common/executors/cursor-executor.service.js +98 -26
  19. package/dist/packages/core/src/infrastructure/services/agents/common/executors/gemini-cli-executor.service.d.ts.map +1 -1
  20. package/dist/packages/core/src/infrastructure/services/agents/common/executors/gemini-cli-executor.service.js +13 -1
  21. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.d.ts.map +1 -1
  22. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.js +1 -0
  23. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.d.ts.map +1 -1
  24. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.js +18 -1
  25. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/evidence.node.d.ts.map +1 -1
  26. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/evidence.node.js +1 -0
  27. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/fast-implement.node.d.ts.map +1 -1
  28. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/fast-implement.node.js +1 -0
  29. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/implement.node.d.ts.map +1 -1
  30. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/implement.node.js +1 -0
  31. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/ci-watch-fix-loop.d.ts.map +1 -1
  32. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/ci-watch-fix-loop.js +13 -1
  33. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge.node.d.ts +4 -0
  34. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge.node.d.ts.map +1 -1
  35. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge.node.js +9 -17
  36. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.d.ts +2 -0
  37. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.d.ts.map +1 -1
  38. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.js +8 -4
  39. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/implement.prompt.js +7 -4
  40. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/repair.node.d.ts.map +1 -1
  41. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/repair.node.js +1 -0
  42. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/validate.node.d.ts.map +1 -1
  43. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/validate.node.js +1 -0
  44. package/dist/packages/core/src/infrastructure/services/git/git-pr.service.d.ts +1 -0
  45. package/dist/packages/core/src/infrastructure/services/git/git-pr.service.d.ts.map +1 -1
  46. package/dist/packages/core/src/infrastructure/services/git/git-pr.service.js +71 -1
  47. package/dist/packages/core/src/infrastructure/services/git/worktree.service.d.ts +1 -1
  48. package/dist/packages/core/src/infrastructure/services/git/worktree.service.d.ts.map +1 -1
  49. package/dist/packages/core/src/infrastructure/services/git/worktree.service.js +5 -3
  50. package/dist/packages/core/src/infrastructure/services/ide-launchers/compute-worktree-path.d.ts.map +1 -1
  51. package/dist/packages/core/src/infrastructure/services/ide-launchers/compute-worktree-path.js +3 -1
  52. package/dist/packages/core/src/infrastructure/services/ide-launchers/json-driven-ide-launcher.service.d.ts.map +1 -1
  53. package/dist/packages/core/src/infrastructure/services/ide-launchers/json-driven-ide-launcher.service.js +5 -1
  54. package/dist/packages/core/src/infrastructure/services/pr-sync/pr-sync-watcher.service.d.ts +5 -0
  55. package/dist/packages/core/src/infrastructure/services/pr-sync/pr-sync-watcher.service.d.ts.map +1 -1
  56. package/dist/packages/core/src/infrastructure/services/pr-sync/pr-sync-watcher.service.js +56 -0
  57. package/dist/packages/core/src/infrastructure/services/webhooks/github-webhook-runtime.service.d.ts +43 -0
  58. package/dist/packages/core/src/infrastructure/services/webhooks/github-webhook-runtime.service.d.ts.map +1 -0
  59. package/dist/packages/core/src/infrastructure/services/webhooks/github-webhook-runtime.service.js +208 -0
  60. package/dist/packages/core/src/infrastructure/services/webhooks/github-webhook.service.d.ts +25 -0
  61. package/dist/packages/core/src/infrastructure/services/webhooks/github-webhook.service.d.ts.map +1 -0
  62. package/dist/packages/core/src/infrastructure/services/webhooks/github-webhook.service.js +99 -0
  63. package/dist/packages/core/src/infrastructure/services/webhooks/webhook-secret.service.d.ts +3 -0
  64. package/dist/packages/core/src/infrastructure/services/webhooks/webhook-secret.service.d.ts.map +1 -0
  65. package/dist/packages/core/src/infrastructure/services/webhooks/webhook-secret.service.js +19 -0
  66. package/dist/src/presentation/cli/commands/_serve.command.d.ts.map +1 -1
  67. package/dist/src/presentation/cli/commands/_serve.command.js +23 -0
  68. package/dist/src/presentation/cli/commands/ui.command.d.ts.map +1 -1
  69. package/dist/src/presentation/cli/commands/ui.command.js +16 -0
  70. package/dist/src/presentation/web/app/api/webhooks/github/route.d.ts +3 -0
  71. package/dist/src/presentation/web/app/api/webhooks/github/route.d.ts.map +1 -0
  72. package/dist/src/presentation/web/app/api/webhooks/github/route.js +38 -0
  73. package/dist/src/presentation/web/dev-server.js +23 -0
  74. package/dist/tsconfig.build.tsbuildinfo +1 -1
  75. package/package.json +1 -1
  76. package/web/.next/BUILD_ID +1 -1
  77. package/web/.next/app-path-routes-manifest.json +1 -0
  78. package/web/.next/build-manifest.json +2 -2
  79. package/web/.next/fallback-build-manifest.json +2 -2
  80. package/web/.next/prerender-manifest.json +3 -3
  81. package/web/.next/required-server-files.js +3 -3
  82. package/web/.next/required-server-files.json +3 -3
  83. package/web/.next/routes-manifest.json +6 -0
  84. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +20 -20
  85. package/web/.next/server/app/(dashboard)/@drawer/create/page.js +1 -1
  86. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  87. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  88. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +26 -26
  89. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js +1 -1
  90. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  91. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  92. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +26 -26
  93. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js +1 -1
  94. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  95. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  96. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +18 -18
  97. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js +1 -1
  98. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  99. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  100. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +20 -20
  101. package/web/.next/server/app/(dashboard)/create/page.js +1 -1
  102. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  103. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  104. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +26 -26
  105. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js +1 -1
  106. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  107. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  108. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +26 -26
  109. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js +1 -1
  110. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  111. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  112. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +18 -18
  113. package/web/.next/server/app/(dashboard)/page.js +1 -1
  114. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  115. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  116. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +18 -18
  117. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js +1 -1
  118. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  119. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  120. package/web/.next/server/app/_global-error.html +2 -2
  121. package/web/.next/server/app/_global-error.rsc +1 -1
  122. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  123. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  124. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  125. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  126. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  127. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  128. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  129. package/web/.next/server/app/api/agent-events/route.js +1 -1
  130. package/web/.next/server/app/api/agent-events/route.js.nft.json +1 -1
  131. package/web/.next/server/app/api/attachments/preview/route.js.nft.json +1 -1
  132. package/web/.next/server/app/api/evidence/route.js.nft.json +1 -1
  133. package/web/.next/server/app/api/graph-data/route.js +1 -1
  134. package/web/.next/server/app/api/graph-data/route.js.nft.json +1 -1
  135. package/web/.next/server/app/api/webhooks/github/route/app-paths-manifest.json +3 -0
  136. package/web/.next/server/app/api/webhooks/github/route/build-manifest.json +11 -0
  137. package/web/.next/server/app/api/webhooks/github/route/server-reference-manifest.json +4 -0
  138. package/web/.next/server/app/api/webhooks/github/route.js +7 -0
  139. package/web/.next/server/app/api/webhooks/github/route.js.map +5 -0
  140. package/web/.next/server/app/api/webhooks/github/route.js.nft.json +1 -0
  141. package/web/.next/server/app/api/webhooks/github/route_client-reference-manifest.js +2 -0
  142. package/web/.next/server/app/settings/page/server-reference-manifest.json +5 -5
  143. package/web/.next/server/app/settings/page.js.nft.json +1 -1
  144. package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  145. package/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
  146. package/web/.next/server/app/skills/page.js +1 -1
  147. package/web/.next/server/app/skills/page.js.nft.json +1 -1
  148. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  149. package/web/.next/server/app/tools/page/server-reference-manifest.json +6 -6
  150. package/web/.next/server/app/tools/page.js +1 -1
  151. package/web/.next/server/app/tools/page.js.nft.json +1 -1
  152. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  153. package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
  154. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  155. package/web/.next/server/app-paths-manifest.json +1 -0
  156. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_0ab2579c.js +4 -0
  157. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_0ab2579c.js.map +1 -0
  158. package/web/.next/server/chunks/744ca_web__next-internal_server_app_api_webhooks_github_route_actions_1b0d0c38.js +3 -0
  159. package/web/.next/server/chunks/744ca_web__next-internal_server_app_api_webhooks_github_route_actions_1b0d0c38.js.map +1 -0
  160. package/web/.next/server/chunks/[root-of-the-server]__1fd12120._.js +3 -0
  161. package/web/.next/server/chunks/{[root-of-the-server]__7d5492a0._.js.map → [root-of-the-server]__1fd12120._.js.map} +1 -1
  162. package/web/.next/server/chunks/[root-of-the-server]__67fab82a._.js +3 -0
  163. package/web/.next/server/chunks/{[root-of-the-server]__cd67a84c._.js.map → [root-of-the-server]__67fab82a._.js.map} +1 -1
  164. package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
  165. package/web/.next/server/chunks/[root-of-the-server]__ea37e7e1._.js +3 -0
  166. package/web/.next/server/chunks/[root-of-the-server]__ea37e7e1._.js.map +1 -0
  167. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  168. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  169. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_a1104008.js +1 -1
  170. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_a1104008.js.map +1 -1
  171. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_92642200.js +1 -1
  172. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_92642200.js.map +1 -1
  173. package/web/.next/server/chunks/ssr/[root-of-the-server]__039967e3._.js +1 -1
  174. package/web/.next/server/chunks/ssr/[root-of-the-server]__039967e3._.js.map +1 -1
  175. package/web/.next/server/chunks/ssr/[root-of-the-server]__07a39ff2._.js +1 -1
  176. package/web/.next/server/chunks/ssr/[root-of-the-server]__11033878._.js +1 -1
  177. package/web/.next/server/chunks/ssr/[root-of-the-server]__11033878._.js.map +1 -1
  178. package/web/.next/server/chunks/ssr/[root-of-the-server]__2773312c._.js +1 -1
  179. package/web/.next/server/chunks/ssr/[root-of-the-server]__2773312c._.js.map +1 -1
  180. package/web/.next/server/chunks/ssr/[root-of-the-server]__5836d236._.js +4 -0
  181. package/web/.next/server/chunks/ssr/{[root-of-the-server]__24dd0927._.js.map → [root-of-the-server]__5836d236._.js.map} +1 -1
  182. package/web/.next/server/chunks/ssr/[root-of-the-server]__5d87af2e._.js +1 -1
  183. package/web/.next/server/chunks/ssr/[root-of-the-server]__6367aea0._.js +1 -1
  184. package/web/.next/server/chunks/ssr/[root-of-the-server]__6367aea0._.js.map +1 -1
  185. package/web/.next/server/chunks/ssr/[root-of-the-server]__8cb3333c._.js +4 -0
  186. package/web/.next/server/chunks/ssr/[root-of-the-server]__8cb3333c._.js.map +1 -0
  187. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +2 -2
  188. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js.map +1 -1
  189. package/web/.next/server/chunks/ssr/[root-of-the-server]__cbd8062c._.js +1 -1
  190. package/web/.next/server/chunks/ssr/[root-of-the-server]__cbd8062c._.js.map +1 -1
  191. package/web/.next/server/chunks/ssr/[root-of-the-server]__e70c5627._.js +1 -1
  192. package/web/.next/server/chunks/ssr/[root-of-the-server]__e70c5627._.js.map +1 -1
  193. package/web/.next/server/chunks/ssr/[root-of-the-server]__fdc75809._.js +1 -1
  194. package/web/.next/server/chunks/ssr/[root-of-the-server]__fdc75809._.js.map +1 -1
  195. package/web/.next/server/chunks/ssr/_135edb9c._.js +1 -1
  196. package/web/.next/server/chunks/ssr/_135edb9c._.js.map +1 -1
  197. package/web/.next/server/chunks/ssr/{_9f9a0a13._.js → _5fceca1d._.js} +2 -2
  198. package/web/.next/server/chunks/ssr/{_9f9a0a13._.js.map → _5fceca1d._.js.map} +1 -1
  199. package/web/.next/server/chunks/ssr/{_28c112df._.js → _74b6a797._.js} +2 -2
  200. package/web/.next/server/chunks/ssr/{_28c112df._.js.map → _74b6a797._.js.map} +1 -1
  201. package/web/.next/server/chunks/ssr/_8dacd1e7._.js +1 -1
  202. package/web/.next/server/chunks/ssr/_8dacd1e7._.js.map +1 -1
  203. package/web/.next/server/chunks/ssr/{_07566303._.js → _bbb7316f._.js} +2 -2
  204. package/web/.next/server/chunks/ssr/{_07566303._.js.map → _bbb7316f._.js.map} +1 -1
  205. package/web/.next/server/chunks/ssr/_cc77a143._.js +1 -1
  206. package/web/.next/server/chunks/ssr/_cc77a143._.js.map +1 -1
  207. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
  208. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
  209. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_888633e1.js +1 -1
  210. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_888633e1.js.map +1 -1
  211. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js +1 -1
  212. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js.map +1 -1
  213. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js +1 -1
  214. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js.map +1 -1
  215. package/web/.next/server/chunks/ssr/src_presentation_web_ce7cbc3c._.js +2 -2
  216. package/web/.next/server/chunks/ssr/src_presentation_web_ce7cbc3c._.js.map +1 -1
  217. package/web/.next/server/chunks/ssr/src_presentation_web_components_bf50c527._.js +1 -1
  218. package/web/.next/server/chunks/ssr/src_presentation_web_components_de814675._.js +1 -1
  219. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  220. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  221. package/web/.next/server/chunks/ssr/src_presentation_web_e2604413._.js +2 -2
  222. package/web/.next/server/chunks/ssr/src_presentation_web_e2604413._.js.map +1 -1
  223. package/web/.next/server/pages/500.html +2 -2
  224. package/web/.next/server/server-reference-manifest.js +1 -1
  225. package/web/.next/server/server-reference-manifest.json +31 -31
  226. package/web/.next/static/chunks/{685adf3a56420f0b.js → 0aebffb399bbb9ed.js} +1 -1
  227. package/web/.next/static/chunks/2e8262cd524e9f0c.js +2 -0
  228. package/web/.next/static/chunks/{6168a928704dfc29.js → 2fbf145a6771f83d.js} +1 -1
  229. package/web/.next/static/chunks/{526482abdde534e5.js → 55f4d0cdbd44c85c.js} +1 -1
  230. package/web/.next/static/chunks/{43102414475749cf.js → 64fff64abb23a98a.js} +1 -1
  231. package/web/.next/static/chunks/{8131c822c4d545e5.js → 692809ab808fb5b0.js} +1 -1
  232. package/web/.next/static/chunks/{28524a4debc4ab27.js → 739ad28b1bd6139f.js} +1 -1
  233. package/web/.next/static/chunks/{9c68af62b0ac608c.js → 79cb8d40234e2dae.js} +1 -1
  234. package/web/.next/static/chunks/80027601774ec110.js +1 -0
  235. package/web/.next/static/chunks/{4b2abcc77ae796bd.js → e8c2d1bb5972372a.js} +1 -1
  236. package/web/.next/server/chunks/[root-of-the-server]__7d5492a0._.js +0 -3
  237. package/web/.next/server/chunks/[root-of-the-server]__cd67a84c._.js +0 -3
  238. package/web/.next/server/chunks/ssr/[root-of-the-server]__24dd0927._.js +0 -4
  239. package/web/.next/server/chunks/ssr/[root-of-the-server]__89e8a5cc._.js +0 -4
  240. package/web/.next/server/chunks/ssr/[root-of-the-server]__89e8a5cc._.js.map +0 -1
  241. package/web/.next/static/chunks/281ebd968bf7607f.js +0 -1
  242. package/web/.next/static/chunks/c51298d5a17232b2.js +0 -2
  243. /package/web/.next/static/{0KO3WOdJ7F-5vNEe_BKUA → uDyTlPWSuePQAmkQTwP4z}/_buildManifest.js +0 -0
  244. /package/web/.next/static/{0KO3WOdJ7F-5vNEe_BKUA → uDyTlPWSuePQAmkQTwP4z}/_clientMiddlewareManifest.json +0 -0
  245. /package/web/.next/static/{0KO3WOdJ7F-5vNEe_BKUA → uDyTlPWSuePQAmkQTwP4z}/_ssgManifest.js +0 -0
@@ -0,0 +1,208 @@
1
+ import http from 'node:http';
2
+ import { spawn } from 'node:child_process';
3
+ import { SdlcLifecycle } from '../../../domain/generated/output.js';
4
+ import { findAvailablePort } from '../port.service.js';
5
+ import { getOrCreateGitHubWebhookSecret } from './webhook-secret.service.js';
6
+ const DEFAULT_GATEWAY_PORT = 4590;
7
+ const DEFAULT_RECONCILE_INTERVAL_MS = 60_000;
8
+ const TUNNEL_READY_TIMEOUT_MS = 15_000;
9
+ const GITHUB_WEBHOOK_CALLBACK_PATH = '/api/webhooks/github?source=shep';
10
+ const ENABLE_ENV = 'SHEP_ENABLE_GITHUB_WEBHOOKS';
11
+ const defaultDeps = {
12
+ createServer: http.createServer,
13
+ spawnProcess: spawn,
14
+ findAvailablePort,
15
+ fetchImpl: fetch,
16
+ getSecret: getOrCreateGitHubWebhookSecret,
17
+ logInfo: (message) => process.stdout.write(`${message}\n`),
18
+ logWarn: (message) => process.stderr.write(`${message}\n`),
19
+ };
20
+ export function isGitHubWebhookRuntimeEnabled() {
21
+ return process.env[ENABLE_ENV] === '1' || process.env[ENABLE_ENV] === 'true';
22
+ }
23
+ export class GitHubWebhookRuntimeService {
24
+ featureRepo;
25
+ webhookService;
26
+ appPort;
27
+ reconcileIntervalMs;
28
+ deps;
29
+ gatewayServer = null;
30
+ tunnelProcess = null;
31
+ reconcileTimer = null;
32
+ publicBaseUrl = null;
33
+ gatewayPort = null;
34
+ secret = null;
35
+ constructor(featureRepo, webhookService, appPort, reconcileIntervalMs = DEFAULT_RECONCILE_INTERVAL_MS, deps = {}) {
36
+ this.featureRepo = featureRepo;
37
+ this.webhookService = webhookService;
38
+ this.appPort = appPort;
39
+ this.reconcileIntervalMs = reconcileIntervalMs;
40
+ this.deps = { ...defaultDeps, ...deps };
41
+ }
42
+ getPublicBaseUrl() {
43
+ return this.publicBaseUrl;
44
+ }
45
+ getGatewayPort() {
46
+ return this.gatewayPort;
47
+ }
48
+ async start() {
49
+ if (!isGitHubWebhookRuntimeEnabled()) {
50
+ return null;
51
+ }
52
+ if (this.publicBaseUrl) {
53
+ return this.publicBaseUrl;
54
+ }
55
+ this.secret = this.deps.getSecret();
56
+ try {
57
+ this.gatewayPort = await this.deps.findAvailablePort(DEFAULT_GATEWAY_PORT);
58
+ await this.startGateway();
59
+ this.publicBaseUrl = await this.startTunnel();
60
+ await this.reconcileHooks();
61
+ this.reconcileTimer = setInterval(() => {
62
+ void this.reconcileHooks();
63
+ }, this.reconcileIntervalMs);
64
+ this.reconcileTimer.unref?.();
65
+ return this.publicBaseUrl;
66
+ }
67
+ catch (error) {
68
+ await this.stop();
69
+ throw error;
70
+ }
71
+ }
72
+ async stop() {
73
+ if (this.reconcileTimer) {
74
+ clearInterval(this.reconcileTimer);
75
+ this.reconcileTimer = null;
76
+ }
77
+ if (this.tunnelProcess) {
78
+ this.tunnelProcess.kill('SIGTERM');
79
+ this.tunnelProcess = null;
80
+ }
81
+ if (this.gatewayServer) {
82
+ await new Promise((resolve) => {
83
+ this.gatewayServer.close(() => resolve());
84
+ });
85
+ this.gatewayServer = null;
86
+ }
87
+ this.publicBaseUrl = null;
88
+ this.gatewayPort = null;
89
+ }
90
+ async startGateway() {
91
+ const port = this.gatewayPort;
92
+ if (!port) {
93
+ throw new Error('Gateway port not allocated');
94
+ }
95
+ const server = this.deps.createServer((req, res) => {
96
+ void this.handleGatewayRequest(req, res);
97
+ });
98
+ await new Promise((resolve, reject) => {
99
+ server.once('error', reject);
100
+ server.listen(port, '127.0.0.1', () => resolve());
101
+ });
102
+ this.gatewayServer = server;
103
+ }
104
+ async handleGatewayRequest(req, res) {
105
+ if (!req.url?.startsWith('/api/webhooks/')) {
106
+ res.statusCode = 404;
107
+ res.end('Not found');
108
+ return;
109
+ }
110
+ const body = await this.readRequestBody(req);
111
+ const headers = new Headers();
112
+ for (const [key, value] of Object.entries(req.headers)) {
113
+ if (!value)
114
+ continue;
115
+ if (key === 'host' || key === 'connection' || key === 'content-length')
116
+ continue;
117
+ if (Array.isArray(value)) {
118
+ for (const item of value)
119
+ headers.append(key, item);
120
+ }
121
+ else {
122
+ headers.set(key, value);
123
+ }
124
+ }
125
+ const requestBody = this.requestCanHaveBody(req.method) ? new Uint8Array(body) : undefined;
126
+ const response = await this.deps.fetchImpl(`http://127.0.0.1:${this.appPort}${req.url}`, {
127
+ method: req.method,
128
+ headers,
129
+ body: requestBody,
130
+ });
131
+ res.statusCode = response.status;
132
+ response.headers.forEach((value, key) => {
133
+ res.setHeader(key, value);
134
+ });
135
+ const buffer = Buffer.from(await response.arrayBuffer());
136
+ res.end(buffer);
137
+ }
138
+ requestCanHaveBody(method) {
139
+ return method !== undefined && method !== 'GET' && method !== 'HEAD';
140
+ }
141
+ async readRequestBody(req) {
142
+ const chunks = [];
143
+ for await (const chunk of req) {
144
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
145
+ }
146
+ return Buffer.concat(chunks);
147
+ }
148
+ async startTunnel() {
149
+ const port = this.gatewayPort;
150
+ if (!port) {
151
+ throw new Error('Gateway port not allocated');
152
+ }
153
+ const child = this.deps.spawnProcess(process.env.SHEP_CLOUDFLARED_BIN ?? 'cloudflared', ['tunnel', '--url', `http://127.0.0.1:${port}`], { stdio: ['ignore', 'pipe', 'pipe'] });
154
+ this.tunnelProcess = child;
155
+ const publicUrl = await new Promise((resolve, reject) => {
156
+ const timeout = setTimeout(() => {
157
+ cleanup();
158
+ reject(new Error('Timed out waiting for cloudflared public URL'));
159
+ }, TUNNEL_READY_TIMEOUT_MS);
160
+ const onData = (chunk) => {
161
+ const match = String(chunk).match(/https:\/\/[a-zA-Z0-9.-]+\.trycloudflare\.com/);
162
+ if (!match)
163
+ return;
164
+ cleanup();
165
+ resolve(match[0]);
166
+ };
167
+ const onExit = (code) => {
168
+ cleanup();
169
+ reject(new Error(`cloudflared exited before URL was ready (code ${code ?? 'unknown'})`));
170
+ };
171
+ const cleanup = () => {
172
+ clearTimeout(timeout);
173
+ child.stdout?.off('data', onData);
174
+ child.stderr?.off('data', onData);
175
+ child.off('exit', onExit);
176
+ };
177
+ child.stdout?.on('data', onData);
178
+ child.stderr?.on('data', onData);
179
+ child.on('exit', onExit);
180
+ });
181
+ this.deps.logInfo(`[GitHubWebhookRuntime] Tunnel ready at ${publicUrl}`);
182
+ return publicUrl;
183
+ }
184
+ async reconcileHooks() {
185
+ if (!this.publicBaseUrl || !this.secret)
186
+ return;
187
+ const features = await this.featureRepo.list({ lifecycle: SdlcLifecycle.Review });
188
+ const repoPaths = [
189
+ ...new Set(features.map((feature) => feature.repositoryPath).filter(Boolean)),
190
+ ];
191
+ for (const repoPath of repoPaths) {
192
+ try {
193
+ const result = await this.webhookService.ensureRepositoryWebhook(repoPath, {
194
+ callbackUrl: `${this.publicBaseUrl}${GITHUB_WEBHOOK_CALLBACK_PATH}`,
195
+ secret: this.secret,
196
+ events: ['pull_request', 'check_suite'],
197
+ });
198
+ if (result.action !== 'unchanged' && result.action !== 'skipped') {
199
+ this.deps.logInfo(`[GitHubWebhookRuntime] ${result.action} webhook for ${repoPath} -> ${result.callbackUrl ?? 'n/a'}`);
200
+ }
201
+ }
202
+ catch (error) {
203
+ const msg = error instanceof Error ? error.message : String(error);
204
+ this.deps.logWarn(`[GitHubWebhookRuntime] Failed to reconcile ${repoPath}: ${msg}`);
205
+ }
206
+ }
207
+ }
208
+ }
@@ -0,0 +1,25 @@
1
+ import type { ExecFunction } from '../git/worktree.service.js';
2
+ import type { IGitPrService } from '../../../application/ports/output/services/git-pr-service.interface.js';
3
+ export interface GitHubWebhookConfig {
4
+ callbackUrl: string;
5
+ secret: string;
6
+ events: string[];
7
+ }
8
+ export interface GitHubWebhookSyncResult {
9
+ action: 'created' | 'updated' | 'unchanged' | 'skipped';
10
+ hookId?: number;
11
+ callbackUrl?: string;
12
+ }
13
+ declare const SHEP_WEBHOOK_MARKER = "source=shep";
14
+ export declare class GitHubWebhookService {
15
+ private readonly execFile;
16
+ private readonly gitPrService;
17
+ constructor(execFile: ExecFunction, gitPrService: Pick<IGitPrService, 'getRemoteUrl'>);
18
+ ensureRepositoryWebhook(cwd: string, config: GitHubWebhookConfig): Promise<GitHubWebhookSyncResult>;
19
+ private listHooks;
20
+ private buildMutationArgs;
21
+ private isHookUpToDate;
22
+ private parseHookPayload;
23
+ }
24
+ export { SHEP_WEBHOOK_MARKER };
25
+ //# sourceMappingURL=github-webhook.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-webhook.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/webhooks/github-webhook.service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qEAAqE,CAAC;AAEzG,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAYD,QAAA,MAAM,mBAAmB,gBAAgB,CAAC;AAkB1C,qBAAa,oBAAoB;IAE7B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,YAAY;gBADZ,QAAQ,EAAE,YAAY,EACtB,YAAY,EAAE,IAAI,CAAC,aAAa,EAAE,cAAc,CAAC;IAG9D,uBAAuB,CAC3B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC,uBAAuB,CAAC;YAmDrB,SAAS;IAKvB,OAAO,CAAC,iBAAiB;IAuBzB,OAAO,CAAC,cAAc;IAatB,OAAO,CAAC,gBAAgB;CAIzB;AAED,OAAO,EAAE,mBAAmB,EAAE,CAAC"}
@@ -0,0 +1,99 @@
1
+ const SHEP_WEBHOOK_MARKER = 'source=shep';
2
+ function parseGitHubOwnerRepo(remoteUrl) {
3
+ if (!remoteUrl)
4
+ return null;
5
+ const httpsMatch = remoteUrl.match(/^https:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?$/);
6
+ if (httpsMatch) {
7
+ return { owner: httpsMatch[1], repo: httpsMatch[2] };
8
+ }
9
+ const sshMatch = remoteUrl.match(/^git@github\.com:([^/]+)\/([^/]+?)(?:\.git)?$/);
10
+ if (sshMatch) {
11
+ return { owner: sshMatch[1], repo: sshMatch[2] };
12
+ }
13
+ return null;
14
+ }
15
+ export class GitHubWebhookService {
16
+ execFile;
17
+ gitPrService;
18
+ constructor(execFile, gitPrService) {
19
+ this.execFile = execFile;
20
+ this.gitPrService = gitPrService;
21
+ }
22
+ async ensureRepositoryWebhook(cwd, config) {
23
+ const remoteUrl = await this.gitPrService.getRemoteUrl(cwd);
24
+ const repo = parseGitHubOwnerRepo(remoteUrl);
25
+ if (!repo) {
26
+ return { action: 'skipped' };
27
+ }
28
+ const hooksPath = `repos/${repo.owner}/${repo.repo}/hooks`;
29
+ const hooks = await this.listHooks(cwd, hooksPath);
30
+ const existing = hooks.find((hook) => hook.config?.url?.includes(SHEP_WEBHOOK_MARKER));
31
+ if (!existing) {
32
+ const created = await this.execFile('gh', ['api', hooksPath, '--method', 'POST', ...this.buildMutationArgs(config)], { cwd });
33
+ const payload = this.parseHookPayload(created.stdout);
34
+ return {
35
+ action: 'created',
36
+ hookId: payload?.id,
37
+ callbackUrl: config.callbackUrl,
38
+ };
39
+ }
40
+ if (this.isHookUpToDate(existing, config)) {
41
+ return {
42
+ action: 'unchanged',
43
+ hookId: existing.id,
44
+ callbackUrl: config.callbackUrl,
45
+ };
46
+ }
47
+ await this.execFile('gh', [
48
+ 'api',
49
+ `${hooksPath}/${existing.id}`,
50
+ '--method',
51
+ 'PATCH',
52
+ ...this.buildMutationArgs(config),
53
+ ], { cwd });
54
+ return {
55
+ action: 'updated',
56
+ hookId: existing.id,
57
+ callbackUrl: config.callbackUrl,
58
+ };
59
+ }
60
+ async listHooks(cwd, hooksPath) {
61
+ const result = await this.execFile('gh', ['api', hooksPath], { cwd });
62
+ return JSON.parse(result.stdout) ?? [];
63
+ }
64
+ buildMutationArgs(config) {
65
+ const args = [
66
+ '-f',
67
+ 'name=web',
68
+ '-f',
69
+ 'active=true',
70
+ '-f',
71
+ `config[url]=${config.callbackUrl}`,
72
+ '-f',
73
+ 'config[content_type]=json',
74
+ '-f',
75
+ `config[secret]=${config.secret}`,
76
+ '-f',
77
+ 'config[insecure_ssl]=0',
78
+ ];
79
+ for (const event of config.events) {
80
+ args.push('-f', `events[]=${event}`);
81
+ }
82
+ return args;
83
+ }
84
+ isHookUpToDate(hook, config) {
85
+ const actualEvents = [...(hook.events ?? [])].sort();
86
+ const desiredEvents = [...config.events].sort();
87
+ return (hook.active === true &&
88
+ hook.config?.url === config.callbackUrl &&
89
+ hook.config?.content_type === 'json' &&
90
+ actualEvents.length === desiredEvents.length &&
91
+ actualEvents.every((event, index) => event === desiredEvents[index]));
92
+ }
93
+ parseHookPayload(stdout) {
94
+ if (!stdout.trim())
95
+ return null;
96
+ return JSON.parse(stdout);
97
+ }
98
+ }
99
+ export { SHEP_WEBHOOK_MARKER };
@@ -0,0 +1,3 @@
1
+ export declare function getGitHubWebhookSecretPath(): string;
2
+ export declare function getOrCreateGitHubWebhookSecret(): string;
3
+ //# sourceMappingURL=webhook-secret.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook-secret.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/webhooks/webhook-secret.service.ts"],"names":[],"mappings":"AAQA,wBAAgB,0BAA0B,IAAI,MAAM,CAEnD;AAED,wBAAgB,8BAA8B,IAAI,MAAM,CAUvD"}
@@ -0,0 +1,19 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { randomBytes } from 'node:crypto';
4
+ import { getShepHomeDir } from '../filesystem/shep-directory.service.js';
5
+ const WEBHOOK_SECRET_DIR = 'webhooks';
6
+ const GITHUB_SECRET_FILE = 'github.secret';
7
+ export function getGitHubWebhookSecretPath() {
8
+ return join(getShepHomeDir(), WEBHOOK_SECRET_DIR, GITHUB_SECRET_FILE);
9
+ }
10
+ export function getOrCreateGitHubWebhookSecret() {
11
+ const secretPath = getGitHubWebhookSecretPath();
12
+ if (existsSync(secretPath)) {
13
+ return readFileSync(secretPath, 'utf8').trim();
14
+ }
15
+ mkdirSync(join(getShepHomeDir(), WEBHOOK_SECRET_DIR), { recursive: true });
16
+ const secret = randomBytes(32).toString('hex');
17
+ writeFileSync(secretPath, `${secret}\n`, { mode: 0o600 });
18
+ return secret;
19
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"_serve.command.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/cli/commands/_serve.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,OAAO,EAAwB,MAAM,WAAW,CAAC;AAwB1D;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CA0D5C"}
1
+ {"version":3,"file":"_serve.command.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/cli/commands/_serve.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,OAAO,EAAwB,MAAM,WAAW,CAAC;AAoC1D;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAqF5C"}
@@ -29,6 +29,10 @@ import { container } from '../../../../packages/core/src/infrastructure/di/conta
29
29
  import { setVersionEnvVars } from '../../../../packages/core/src/infrastructure/services/version.service.js';
30
30
  import { resolveWebDir } from '../../../../packages/core/src/infrastructure/services/web-server.service.js';
31
31
  import { initializeNotificationWatcher, getNotificationWatcher, } from '../../../../packages/core/src/infrastructure/services/notifications/notification-watcher.service.js';
32
+ import { initializePrSyncWatcher, getPrSyncWatcher, } from '../../../../packages/core/src/infrastructure/services/pr-sync/pr-sync-watcher.service.js';
33
+ import { getExistingConnection } from '../../../../packages/core/src/infrastructure/persistence/sqlite/connection.js';
34
+ import { GitHubWebhookRuntimeService, isGitHubWebhookRuntimeEnabled, } from '../../../../packages/core/src/infrastructure/services/webhooks/github-webhook-runtime.service.js';
35
+ import { GitHubWebhookService } from '../../../../packages/core/src/infrastructure/services/webhooks/github-webhook.service.js';
32
36
  function parsePort(value) {
33
37
  const port = parseInt(value, 10);
34
38
  if (isNaN(port) || port < 1024 || port > 65535) {
@@ -62,6 +66,23 @@ export function createServeCommand() {
62
66
  const notificationService = container.resolve('INotificationService');
63
67
  initializeNotificationWatcher(runRepo, phaseTimingRepo, featureRepo, notificationService);
64
68
  getNotificationWatcher().start();
69
+ const gitPrService = container.resolve('IGitPrService');
70
+ const db = getExistingConnection();
71
+ initializePrSyncWatcher(featureRepo, runRepo, gitPrService, notificationService, undefined, db);
72
+ getPrSyncWatcher().start();
73
+ let webhookRuntime = null;
74
+ if (isGitHubWebhookRuntimeEnabled()) {
75
+ try {
76
+ const execFile = container.resolve('ExecFunction');
77
+ const webhookService = new GitHubWebhookService(execFile, gitPrService);
78
+ webhookRuntime = new GitHubWebhookRuntimeService(featureRepo, webhookService, port);
79
+ await webhookRuntime.start();
80
+ }
81
+ catch (error) {
82
+ const err = error instanceof Error ? error : new Error(String(error));
83
+ process.stderr.write(`[_serve] GitHub webhook runtime disabled: ${err.message}\n`);
84
+ }
85
+ }
65
86
  // Graceful shutdown handler — identical pattern to ui.command.ts
66
87
  let isShuttingDown = false;
67
88
  const shutdown = async () => {
@@ -71,6 +92,8 @@ export function createServeCommand() {
71
92
  // Force exit after 5s if graceful shutdown stalls
72
93
  const forceExit = setTimeout(() => process.exit(0), 5000);
73
94
  forceExit.unref();
95
+ await webhookRuntime?.stop();
96
+ getPrSyncWatcher().stop();
74
97
  getNotificationWatcher().stop();
75
98
  const deploymentService = container.resolve('IDeploymentService');
76
99
  deploymentService.stopAll();
@@ -1 +1 @@
1
- {"version":3,"file":"ui.command.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/cli/commands/ui.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,OAAO,EAAwB,MAAM,WAAW,CAAC;AAgC1D;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CA0FzC"}
1
+ {"version":3,"file":"ui.command.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/cli/commands/ui.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,OAAO,EAAwB,MAAM,WAAW,CAAC;AAsC1D;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAwGzC"}
@@ -23,6 +23,8 @@ import { initializeNotificationWatcher, getNotificationWatcher, } from '../../..
23
23
  import { initializePrSyncWatcher, getPrSyncWatcher, } from '../../../../packages/core/src/infrastructure/services/pr-sync/pr-sync-watcher.service.js';
24
24
  import { getExistingConnection } from '../../../../packages/core/src/infrastructure/persistence/sqlite/connection.js';
25
25
  import { BrowserOpenerService } from '../../../../packages/core/src/infrastructure/services/browser-opener.service.js';
26
+ import { GitHubWebhookRuntimeService, isGitHubWebhookRuntimeEnabled, } from '../../../../packages/core/src/infrastructure/services/webhooks/github-webhook-runtime.service.js';
27
+ import { GitHubWebhookService } from '../../../../packages/core/src/infrastructure/services/webhooks/github-webhook.service.js';
26
28
  import { colors, fmt, messages } from '../ui/index.js';
27
29
  function parsePort(value) {
28
30
  const port = parseInt(value, 10);
@@ -70,6 +72,19 @@ Examples:
70
72
  const db = getExistingConnection();
71
73
  initializePrSyncWatcher(featureRepo, runRepo, gitPrService, notificationService, undefined, db);
72
74
  getPrSyncWatcher().start();
75
+ let webhookRuntime = null;
76
+ if (isGitHubWebhookRuntimeEnabled()) {
77
+ try {
78
+ const execFile = container.resolve('ExecFunction');
79
+ const webhookService = new GitHubWebhookService(execFile, gitPrService);
80
+ webhookRuntime = new GitHubWebhookRuntimeService(featureRepo, webhookService, port);
81
+ await webhookRuntime.start();
82
+ }
83
+ catch (error) {
84
+ const err = error instanceof Error ? error : new Error(String(error));
85
+ messages.warning(`GitHub webhook runtime disabled: ${err.message}`);
86
+ }
87
+ }
73
88
  const url = `http://localhost:${port}`;
74
89
  messages.success(`Server ready at ${fmt.code(url)}`);
75
90
  messages.info('Press Ctrl+C to stop');
@@ -91,6 +106,7 @@ Examples:
91
106
  // Force exit after 5s if graceful shutdown stalls
92
107
  const forceExit = setTimeout(() => process.exit(0), 5000);
93
108
  forceExit.unref();
109
+ await webhookRuntime?.stop();
94
110
  getPrSyncWatcher().stop();
95
111
  getNotificationWatcher().stop();
96
112
  await service.stop();
@@ -0,0 +1,3 @@
1
+ export declare const dynamic = "force-dynamic";
2
+ export declare function POST(request: Request): Promise<Response>;
3
+ //# sourceMappingURL=route.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../../src/presentation/web/app/api/webhooks/github/route.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,OAAO,kBAAkB,CAAC;AAiBvC,wBAAsB,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CA2B9D"}
@@ -0,0 +1,38 @@
1
+ import { createHmac, timingSafeEqual } from 'node:crypto';
2
+ import { getPrSyncWatcher, hasPrSyncWatcher, } from '../../../../../../../packages/core/src/infrastructure/services/pr-sync/pr-sync-watcher.service.js';
3
+ import { getOrCreateGitHubWebhookSecret } from '../../../../../../../packages/core/src/infrastructure/services/webhooks/webhook-secret.service.js';
4
+ export const dynamic = 'force-dynamic';
5
+ function isValidSignature(rawBody, signatureHeader, secret) {
6
+ if (!signatureHeader?.startsWith('sha256='))
7
+ return false;
8
+ const digest = createHmac('sha256', secret).update(rawBody).digest('hex');
9
+ const expected = Buffer.from(`sha256=${digest}`);
10
+ const received = Buffer.from(signatureHeader);
11
+ if (expected.length !== received.length)
12
+ return false;
13
+ return timingSafeEqual(expected, received);
14
+ }
15
+ export async function POST(request) {
16
+ const rawBody = await request.text();
17
+ const secret = getOrCreateGitHubWebhookSecret();
18
+ const signature = request.headers.get('x-hub-signature-256');
19
+ if (!isValidSignature(rawBody, signature, secret)) {
20
+ return Response.json({ error: 'Invalid GitHub webhook signature' }, { status: 401 });
21
+ }
22
+ let payload;
23
+ try {
24
+ payload = JSON.parse(rawBody);
25
+ }
26
+ catch {
27
+ return Response.json({ error: 'Invalid JSON payload' }, { status: 400 });
28
+ }
29
+ const fullName = payload.repository?.full_name;
30
+ if (!fullName) {
31
+ return Response.json({ error: 'Missing repository.full_name' }, { status: 400 });
32
+ }
33
+ if (!hasPrSyncWatcher()) {
34
+ return Response.json({ accepted: true, refreshed: false }, { status: 202 });
35
+ }
36
+ const refreshed = await getPrSyncWatcher().syncRepositoryByGitHubFullName(fullName);
37
+ return Response.json({ accepted: true, refreshed }, { status: 202 });
38
+ }
@@ -20,6 +20,8 @@ import { initializeSettings } from '../../../packages/core/src/infrastructure/se
20
20
  import { initializeNotificationWatcher, getNotificationWatcher, } from '../../../packages/core/src/infrastructure/services/notifications/notification-watcher.service.js';
21
21
  import { initializePrSyncWatcher, getPrSyncWatcher, } from '../../../packages/core/src/infrastructure/services/pr-sync/pr-sync-watcher.service.js';
22
22
  import { getExistingConnection } from '../../../packages/core/src/infrastructure/persistence/sqlite/connection.js';
23
+ import { GitHubWebhookRuntimeService, isGitHubWebhookRuntimeEnabled, } from '../../../packages/core/src/infrastructure/services/webhooks/github-webhook-runtime.service.js';
24
+ import { GitHubWebhookService } from '../../../packages/core/src/infrastructure/services/webhooks/github-webhook.service.js';
23
25
  const DEFAULT_PORT = 3000;
24
26
  async function isPortAvailable(port) {
25
27
  return new Promise((resolve) => {
@@ -68,6 +70,19 @@ async function main() {
68
70
  const db = getExistingConnection();
69
71
  initializePrSyncWatcher(featureRepo, runRepo, gitPrService, notificationService, undefined, db);
70
72
  getPrSyncWatcher().start();
73
+ let webhookRuntime = null;
74
+ if (isGitHubWebhookRuntimeEnabled()) {
75
+ try {
76
+ const execFile = container.resolve('ExecFunction');
77
+ const webhookService = new GitHubWebhookService(execFile, gitPrService);
78
+ webhookRuntime = new GitHubWebhookRuntimeService(featureRepo, webhookService, port);
79
+ await webhookRuntime.start();
80
+ }
81
+ catch (error) {
82
+ console.warn('[dev-server] GitHub webhook runtime disabled:', error);
83
+ }
84
+ }
85
+ globalThis.__shepGithubWebhookRuntime = webhookRuntime;
71
86
  }
72
87
  catch (error) {
73
88
  console.warn('[dev-server] DI initialization failed — features will be empty:', error);
@@ -107,6 +122,14 @@ async function main() {
107
122
  console.log('\n[dev-server] Shutting down...');
108
123
  const forceExit = setTimeout(() => process.exit(0), 2000);
109
124
  try {
125
+ try {
126
+ const webhookRuntime = globalThis
127
+ .__shepGithubWebhookRuntime;
128
+ await webhookRuntime?.stop();
129
+ }
130
+ catch {
131
+ /* runtime not initialized */
132
+ }
110
133
  try {
111
134
  getNotificationWatcher().stop();
112
135
  }