@shepai/cli 1.70.1 → 1.71.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 (312) hide show
  1. package/dist/packages/core/src/application/ports/output/services/deployment-service.interface.d.ts +32 -0
  2. package/dist/packages/core/src/application/ports/output/services/deployment-service.interface.d.ts.map +1 -1
  3. package/dist/packages/core/src/infrastructure/services/deployment/deployment.service.d.ts +16 -2
  4. package/dist/packages/core/src/infrastructure/services/deployment/deployment.service.d.ts.map +1 -1
  5. package/dist/packages/core/src/infrastructure/services/deployment/deployment.service.js +46 -9
  6. package/dist/packages/core/src/infrastructure/services/deployment/log-ring-buffer.d.ts +23 -0
  7. package/dist/packages/core/src/infrastructure/services/deployment/log-ring-buffer.d.ts.map +1 -0
  8. package/dist/packages/core/src/infrastructure/services/deployment/log-ring-buffer.js +46 -0
  9. package/dist/src/presentation/web/app/actions/get-deployment-logs.d.ts +3 -0
  10. package/dist/src/presentation/web/app/actions/get-deployment-logs.d.ts.map +1 -0
  11. package/dist/src/presentation/web/app/actions/get-deployment-logs.js +9 -0
  12. package/dist/src/presentation/web/app/actions/get-feature-artifact.d.ts +2 -0
  13. package/dist/src/presentation/web/app/actions/get-feature-artifact.d.ts.map +1 -1
  14. package/dist/src/presentation/web/app/actions/get-feature-artifact.js +23 -1
  15. package/dist/src/presentation/web/app/api/deployment-logs/route.d.ts +15 -0
  16. package/dist/src/presentation/web/app/api/deployment-logs/route.d.ts.map +1 -0
  17. package/dist/src/presentation/web/app/api/deployment-logs/route.js +94 -0
  18. package/dist/src/presentation/web/components/common/base-drawer/base-drawer.js +2 -2
  19. package/dist/src/presentation/web/components/common/base-drawer/base-drawer.stories.js +1 -1
  20. package/dist/src/presentation/web/components/common/control-center-drawer/control-center-drawer.d.ts.map +1 -1
  21. package/dist/src/presentation/web/components/common/control-center-drawer/control-center-drawer.js +34 -4
  22. package/dist/src/presentation/web/components/common/deployment-status-badge/deployment-status-badge.d.ts +2 -1
  23. package/dist/src/presentation/web/components/common/deployment-status-badge/deployment-status-badge.d.ts.map +1 -1
  24. package/dist/src/presentation/web/components/common/deployment-status-badge/deployment-status-badge.js +16 -5
  25. package/dist/src/presentation/web/components/common/deployment-status-badge/deployment-status-badge.stories.d.ts +4 -0
  26. package/dist/src/presentation/web/components/common/deployment-status-badge/deployment-status-badge.stories.d.ts.map +1 -1
  27. package/dist/src/presentation/web/components/common/deployment-status-badge/deployment-status-badge.stories.js +8 -0
  28. package/dist/src/presentation/web/components/common/merge-review/merge-review.js +1 -1
  29. package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.js +1 -1
  30. package/dist/src/presentation/web/components/common/product-decisions-summary/index.d.ts +3 -0
  31. package/dist/src/presentation/web/components/common/product-decisions-summary/index.d.ts.map +1 -0
  32. package/dist/src/presentation/web/components/common/product-decisions-summary/index.js +1 -0
  33. package/dist/src/presentation/web/components/common/product-decisions-summary/product-decisions-summary-config.d.ts +23 -0
  34. package/dist/src/presentation/web/components/common/product-decisions-summary/product-decisions-summary-config.d.ts.map +1 -0
  35. package/dist/src/presentation/web/components/common/product-decisions-summary/product-decisions-summary-config.js +1 -0
  36. package/dist/src/presentation/web/components/common/product-decisions-summary/product-decisions-summary.d.ts +3 -0
  37. package/dist/src/presentation/web/components/common/product-decisions-summary/product-decisions-summary.d.ts.map +1 -0
  38. package/dist/src/presentation/web/components/common/product-decisions-summary/product-decisions-summary.js +13 -0
  39. package/dist/src/presentation/web/components/common/product-decisions-summary/product-decisions-summary.stories.d.ts +14 -0
  40. package/dist/src/presentation/web/components/common/product-decisions-summary/product-decisions-summary.stories.d.ts.map +1 -0
  41. package/dist/src/presentation/web/components/common/product-decisions-summary/product-decisions-summary.stories.js +74 -0
  42. package/dist/src/presentation/web/components/common/repository-node/repository-node.d.ts.map +1 -1
  43. package/dist/src/presentation/web/components/common/repository-node/repository-node.js +1 -1
  44. package/dist/src/presentation/web/components/common/server-log-viewer/index.d.ts +2 -0
  45. package/dist/src/presentation/web/components/common/server-log-viewer/index.d.ts.map +1 -0
  46. package/dist/src/presentation/web/components/common/server-log-viewer/index.js +1 -0
  47. package/dist/src/presentation/web/components/common/server-log-viewer/server-log-viewer.d.ts +15 -0
  48. package/dist/src/presentation/web/components/common/server-log-viewer/server-log-viewer.d.ts.map +1 -0
  49. package/dist/src/presentation/web/components/common/server-log-viewer/server-log-viewer.js +31 -0
  50. package/dist/src/presentation/web/components/common/server-log-viewer/server-log-viewer.stories.d.ts +18 -0
  51. package/dist/src/presentation/web/components/common/server-log-viewer/server-log-viewer.stories.d.ts.map +1 -0
  52. package/dist/src/presentation/web/components/common/server-log-viewer/server-log-viewer.stories.js +113 -0
  53. package/dist/src/presentation/web/components/common/tech-decisions-review/index.d.ts +1 -1
  54. package/dist/src/presentation/web/components/common/tech-decisions-review/index.d.ts.map +1 -1
  55. package/dist/src/presentation/web/components/common/tech-decisions-review/index.js +1 -1
  56. package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.d.ts +8 -1
  57. package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.d.ts.map +1 -1
  58. package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.js +11 -2
  59. package/dist/src/presentation/web/components/common/tech-review-tabs/index.d.ts +3 -0
  60. package/dist/src/presentation/web/components/common/tech-review-tabs/index.d.ts.map +1 -0
  61. package/dist/src/presentation/web/components/common/tech-review-tabs/index.js +1 -0
  62. package/dist/src/presentation/web/components/common/tech-review-tabs/tech-review-tabs-config.d.ts +17 -0
  63. package/dist/src/presentation/web/components/common/tech-review-tabs/tech-review-tabs-config.d.ts.map +1 -0
  64. package/dist/src/presentation/web/components/common/tech-review-tabs/tech-review-tabs-config.js +1 -0
  65. package/dist/src/presentation/web/components/common/tech-review-tabs/tech-review-tabs.d.ts +3 -0
  66. package/dist/src/presentation/web/components/common/tech-review-tabs/tech-review-tabs.d.ts.map +1 -0
  67. package/dist/src/presentation/web/components/common/tech-review-tabs/tech-review-tabs.js +12 -0
  68. package/dist/src/presentation/web/components/common/tech-review-tabs/tech-review-tabs.stories.d.ts +16 -0
  69. package/dist/src/presentation/web/components/common/tech-review-tabs/tech-review-tabs.stories.d.ts.map +1 -0
  70. package/dist/src/presentation/web/components/common/tech-review-tabs/tech-review-tabs.stories.js +110 -0
  71. package/dist/src/presentation/web/hooks/use-deployment-logs.d.ts +7 -0
  72. package/dist/src/presentation/web/hooks/use-deployment-logs.d.ts.map +1 -0
  73. package/dist/src/presentation/web/hooks/use-deployment-logs.js +50 -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/cache/.previewinfo +1 -1
  80. package/web/.next/cache/.rscinfo +1 -1
  81. package/web/.next/cache/.tsbuildinfo +1 -1
  82. package/web/.next/cache/config.json +3 -3
  83. package/web/.next/fallback-build-manifest.json +2 -2
  84. package/web/.next/prerender-manifest.json +3 -3
  85. package/web/.next/required-server-files.js +1 -1
  86. package/web/.next/required-server-files.json +1 -1
  87. package/web/.next/routes-manifest.json +6 -0
  88. package/web/.next/server/app/_global-error.html +2 -2
  89. package/web/.next/server/app/_global-error.rsc +1 -1
  90. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  91. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  92. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  93. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  94. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  95. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  96. package/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  97. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  98. package/web/.next/server/app/api/deployment-logs/route/app-paths-manifest.json +3 -0
  99. package/web/.next/server/app/api/deployment-logs/route/build-manifest.json +11 -0
  100. package/web/.next/server/app/api/deployment-logs/route/server-reference-manifest.json +4 -0
  101. package/web/.next/server/app/api/deployment-logs/route.js +6 -0
  102. package/web/.next/server/app/api/deployment-logs/route.js.map +5 -0
  103. package/web/.next/server/app/api/deployment-logs/route.js.nft.json +1 -0
  104. package/web/.next/server/app/api/deployment-logs/route_client-reference-manifest.js +2 -0
  105. package/web/.next/server/app/api/tools/[id]/install/route.js +1 -1
  106. package/web/.next/server/app/api/tools/[id]/install/route.js.nft.json +1 -1
  107. package/web/.next/server/app/page/server-reference-manifest.json +51 -36
  108. package/web/.next/server/app/page.js +1 -1
  109. package/web/.next/server/app/page.js.nft.json +1 -1
  110. package/web/.next/server/app/page_client-reference-manifest.js +1 -1
  111. package/web/.next/server/app/skills/page/server-reference-manifest.json +25 -10
  112. package/web/.next/server/app/skills/page.js +1 -1
  113. package/web/.next/server/app/skills/page.js.nft.json +1 -1
  114. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  115. package/web/.next/server/app/tools/page/server-reference-manifest.json +1 -1
  116. package/web/.next/server/app/tools/page.js.nft.json +1 -1
  117. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  118. package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
  119. package/web/.next/server/app/version/page.js +1 -1
  120. package/web/.next/server/app/version/page.js.nft.json +1 -1
  121. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  122. package/web/.next/server/app-paths-manifest.json +1 -0
  123. package/web/.next/server/chunks/744ca_web__next-internal_server_app_api_deployment-logs_route_actions_b785cd3a.js +3 -0
  124. package/web/.next/server/chunks/744ca_web__next-internal_server_app_api_deployment-logs_route_actions_b785cd3a.js.map +1 -0
  125. package/web/.next/server/chunks/[root-of-the-server]__9a136c79._.js +9 -0
  126. package/web/.next/server/chunks/[root-of-the-server]__9a136c79._.js.map +1 -0
  127. package/web/.next/server/chunks/{[root-of-the-server]__09413611._.js → [root-of-the-server]__e926de65._.js} +2 -2
  128. package/web/.next/server/chunks/{[root-of-the-server]__09413611._.js.map → [root-of-the-server]__e926de65._.js.map} +1 -1
  129. package/web/.next/server/chunks/ssr/[root-of-the-server]__08ba9bd3._.js +1 -1
  130. package/web/.next/server/chunks/ssr/[root-of-the-server]__08ba9bd3._.js.map +1 -1
  131. package/web/.next/server/chunks/ssr/[root-of-the-server]__5f968713._.js +3 -0
  132. package/web/.next/server/chunks/ssr/[root-of-the-server]__5f968713._.js.map +1 -0
  133. package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
  134. package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js.map +1 -1
  135. package/web/.next/server/chunks/ssr/{[root-of-the-server]__249c74f6._.js → [root-of-the-server]__6e8b5181._.js} +2 -2
  136. package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
  137. package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js.map +1 -1
  138. package/web/.next/server/chunks/ssr/[root-of-the-server]__970ba1be._.js +3 -0
  139. package/web/.next/server/chunks/ssr/[root-of-the-server]__970ba1be._.js.map +1 -0
  140. package/web/.next/server/chunks/ssr/[root-of-the-server]__97a1f9c2._.js +4 -0
  141. package/web/.next/server/chunks/ssr/[root-of-the-server]__97a1f9c2._.js.map +1 -0
  142. package/web/.next/server/chunks/ssr/[root-of-the-server]__9add7c3a._.js +2 -2
  143. package/web/.next/server/chunks/ssr/[root-of-the-server]__9add7c3a._.js.map +1 -1
  144. package/web/.next/server/chunks/ssr/[root-of-the-server]__ad7c18fa._.js +9 -0
  145. package/web/.next/server/chunks/ssr/[root-of-the-server]__ad7c18fa._.js.map +1 -0
  146. package/web/.next/server/chunks/ssr/[root-of-the-server]__b22d8535._.js +3 -0
  147. package/web/.next/server/chunks/ssr/[root-of-the-server]__b22d8535._.js.map +1 -0
  148. package/web/.next/server/chunks/ssr/_25e0eb34._.js +3 -0
  149. package/web/.next/server/chunks/ssr/_25e0eb34._.js.map +1 -0
  150. package/web/.next/server/chunks/ssr/_49bf495c._.js +1 -1
  151. package/web/.next/server/chunks/ssr/_49bf495c._.js.map +1 -1
  152. package/web/.next/server/chunks/ssr/_68b5e0de._.js +1 -1
  153. package/web/.next/server/chunks/ssr/_68b5e0de._.js.map +1 -1
  154. package/web/.next/server/chunks/ssr/_725584e5._.js +1 -1
  155. package/web/.next/server/chunks/ssr/_725584e5._.js.map +1 -1
  156. package/web/.next/server/chunks/ssr/_72ce07df._.js +3 -0
  157. package/web/.next/server/chunks/ssr/_72ce07df._.js.map +1 -0
  158. package/web/.next/server/chunks/ssr/{node_modules__pnpm_febcbea6._.js → node_modules__pnpm_3288606c._.js} +2 -2
  159. package/web/.next/server/chunks/ssr/{node_modules__pnpm_febcbea6._.js.map → node_modules__pnpm_3288606c._.js.map} +1 -1
  160. package/web/.next/server/chunks/ssr/src_presentation_web_components_5124369c._.js +3 -0
  161. package/web/.next/server/chunks/ssr/src_presentation_web_components_5124369c._.js.map +1 -0
  162. package/web/.next/server/chunks/ssr/src_presentation_web_components_ui_tabs_tsx_b226ea9b._.js +3 -0
  163. package/web/.next/server/chunks/ssr/src_presentation_web_components_ui_tabs_tsx_b226ea9b._.js.map +1 -0
  164. package/web/.next/server/pages/500.html +2 -2
  165. package/web/.next/server/server-reference-manifest.js +1 -1
  166. package/web/.next/server/server-reference-manifest.json +64 -42
  167. package/web/.next/standalone/src/presentation/web/.next/BUILD_ID +1 -1
  168. package/web/.next/standalone/src/presentation/web/.next/app-path-routes-manifest.json +1 -0
  169. package/web/.next/standalone/src/presentation/web/.next/build-manifest.json +2 -2
  170. package/web/.next/standalone/src/presentation/web/.next/prerender-manifest.json +3 -3
  171. package/web/.next/standalone/src/presentation/web/.next/required-server-files.json +1 -1
  172. package/web/.next/standalone/src/presentation/web/.next/routes-manifest.json +6 -0
  173. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.html +2 -2
  174. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.rsc +1 -1
  175. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  176. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  177. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  178. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  179. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  180. package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  181. package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  182. package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  183. package/web/.next/standalone/src/presentation/web/.next/server/app/api/deployment-logs/route/app-paths-manifest.json +3 -0
  184. package/web/.next/standalone/src/presentation/web/.next/server/app/api/deployment-logs/route/build-manifest.json +11 -0
  185. package/web/.next/standalone/src/presentation/web/.next/server/app/api/deployment-logs/route/server-reference-manifest.json +4 -0
  186. package/web/.next/standalone/src/presentation/web/.next/server/app/api/deployment-logs/route.js +6 -0
  187. package/web/.next/standalone/src/presentation/web/.next/server/app/api/deployment-logs/route.js.map +5 -0
  188. package/web/.next/standalone/src/presentation/web/.next/server/app/api/deployment-logs/route.js.nft.json +1 -0
  189. package/web/.next/standalone/src/presentation/web/.next/server/app/api/deployment-logs/route_client-reference-manifest.js +2 -0
  190. package/web/.next/standalone/src/presentation/web/.next/server/app/api/tools/[id]/install/route.js +1 -1
  191. package/web/.next/standalone/src/presentation/web/.next/server/app/api/tools/[id]/install/route.js.nft.json +1 -1
  192. package/web/.next/standalone/src/presentation/web/.next/server/app/page/server-reference-manifest.json +51 -36
  193. package/web/.next/standalone/src/presentation/web/.next/server/app/page.js +1 -1
  194. package/web/.next/standalone/src/presentation/web/.next/server/app/page.js.nft.json +1 -1
  195. package/web/.next/standalone/src/presentation/web/.next/server/app/page_client-reference-manifest.js +1 -1
  196. package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page/server-reference-manifest.json +25 -10
  197. package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page.js +1 -1
  198. package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page.js.nft.json +1 -1
  199. package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  200. package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page/server-reference-manifest.json +1 -1
  201. package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page.js.nft.json +1 -1
  202. package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  203. package/web/.next/standalone/src/presentation/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
  204. package/web/.next/standalone/src/presentation/web/.next/server/app/version/page.js +1 -1
  205. package/web/.next/standalone/src/presentation/web/.next/server/app/version/page.js.nft.json +1 -1
  206. package/web/.next/standalone/src/presentation/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  207. package/web/.next/standalone/src/presentation/web/.next/server/app-paths-manifest.json +1 -0
  208. package/web/.next/standalone/src/presentation/web/.next/server/chunks/744ca_web__next-internal_server_app_api_deployment-logs_route_actions_b785cd3a.js +3 -0
  209. package/web/.next/standalone/src/presentation/web/.next/server/chunks/[root-of-the-server]__9a136c79._.js +9 -0
  210. package/web/.next/standalone/src/presentation/web/.next/server/chunks/{[root-of-the-server]__09413611._.js → [root-of-the-server]__e926de65._.js} +2 -2
  211. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__08ba9bd3._.js +1 -1
  212. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__5f968713._.js +3 -0
  213. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
  214. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/{[root-of-the-server]__249c74f6._.js → [root-of-the-server]__6e8b5181._.js} +2 -2
  215. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
  216. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__970ba1be._.js +3 -0
  217. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__97a1f9c2._.js +4 -0
  218. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__9add7c3a._.js +2 -2
  219. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__ad7c18fa._.js +9 -0
  220. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__b22d8535._.js +3 -0
  221. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_25e0eb34._.js +3 -0
  222. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_49bf495c._.js +1 -1
  223. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_68b5e0de._.js +1 -1
  224. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_725584e5._.js +1 -1
  225. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_72ce07df._.js +3 -0
  226. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/{node_modules__pnpm_febcbea6._.js → node_modules__pnpm_3288606c._.js} +2 -2
  227. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_components_5124369c._.js +3 -0
  228. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_components_ui_tabs_tsx_b226ea9b._.js +3 -0
  229. package/web/.next/standalone/src/presentation/web/.next/server/pages/500.html +2 -2
  230. package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.js +1 -1
  231. package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.json +64 -42
  232. package/web/.next/standalone/src/presentation/web/app/actions/get-deployment-logs.ts +16 -0
  233. package/web/.next/standalone/src/presentation/web/app/actions/get-feature-artifact.ts +26 -1
  234. package/web/.next/standalone/src/presentation/web/app/api/deployment-logs/route.ts +112 -0
  235. package/web/.next/standalone/src/presentation/web/components/common/base-drawer/base-drawer.stories.tsx +1 -1
  236. package/web/.next/standalone/src/presentation/web/components/common/base-drawer/base-drawer.tsx +6 -2
  237. package/web/.next/standalone/src/presentation/web/components/common/control-center-drawer/control-center-drawer.tsx +44 -6
  238. package/web/.next/standalone/src/presentation/web/components/common/deployment-status-badge/deployment-status-badge.stories.tsx +10 -0
  239. package/web/.next/standalone/src/presentation/web/components/common/deployment-status-badge/deployment-status-badge.tsx +76 -23
  240. package/web/.next/standalone/src/presentation/web/components/common/merge-review/merge-review.tsx +1 -1
  241. package/web/.next/standalone/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.tsx +1 -1
  242. package/web/.next/standalone/src/presentation/web/components/common/product-decisions-summary/index.ts +6 -0
  243. package/web/.next/standalone/src/presentation/web/components/common/product-decisions-summary/product-decisions-summary-config.ts +24 -0
  244. package/web/.next/standalone/src/presentation/web/components/common/product-decisions-summary/product-decisions-summary.stories.tsx +87 -0
  245. package/web/.next/standalone/src/presentation/web/components/common/product-decisions-summary/product-decisions-summary.tsx +52 -0
  246. package/web/.next/standalone/src/presentation/web/components/common/repository-node/repository-node.tsx +5 -1
  247. package/web/.next/standalone/src/presentation/web/components/common/server-log-viewer/index.ts +6 -0
  248. package/web/.next/standalone/src/presentation/web/components/common/server-log-viewer/server-log-viewer.stories.tsx +168 -0
  249. package/web/.next/standalone/src/presentation/web/components/common/server-log-viewer/server-log-viewer.tsx +110 -0
  250. package/web/.next/standalone/src/presentation/web/components/common/tech-decisions-review/index.ts +1 -1
  251. package/web/.next/standalone/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.tsx +47 -29
  252. package/web/.next/standalone/src/presentation/web/components/common/tech-review-tabs/index.ts +2 -0
  253. package/web/.next/standalone/src/presentation/web/components/common/tech-review-tabs/tech-review-tabs-config.ts +17 -0
  254. package/web/.next/standalone/src/presentation/web/components/common/tech-review-tabs/tech-review-tabs.stories.tsx +129 -0
  255. package/web/.next/standalone/src/presentation/web/components/common/tech-review-tabs/tech-review-tabs.tsx +60 -0
  256. package/web/.next/standalone/src/presentation/web/hooks/use-deployment-logs.ts +67 -0
  257. package/web/.next/standalone/src/presentation/web/server.js +1 -1
  258. package/web/.next/static/chunks/01ae2241bd4b44b6.js +1 -0
  259. package/web/.next/static/chunks/20f7876f292cfd82.js +1 -0
  260. package/web/.next/static/chunks/224ed5f5dbd33154.css +2 -0
  261. package/web/.next/static/chunks/{87421ab1062a39b7.js → 3e1227e02ef8bcc6.js} +2 -2
  262. package/web/.next/static/chunks/{1ed0df845a1625f6.js → 62c8ebbd9c7bb287.js} +1 -1
  263. package/web/.next/static/chunks/673e0c1000a91948.js +1 -0
  264. package/web/.next/static/chunks/8b6df4f8e194d0ce.js +1 -0
  265. package/web/.next/static/chunks/b025563d959150a1.js +1 -0
  266. package/web/.next/static/chunks/{9db5c06001f3e664.js → c7fb052190a02a9c.js} +2 -2
  267. package/web/.next/static/chunks/d450d8db6be36b8d.js +1 -0
  268. package/web/.next/static/chunks/d9e3cf214ac2f386.js +1 -0
  269. package/web/.next/trace +1 -1
  270. package/web/.next/trace-build +1 -1
  271. package/web/.next/types/link.d.ts +1 -0
  272. package/web/.next/types/routes.d.ts +2 -1
  273. package/web/.next/types/validator.ts +9 -0
  274. package/web/.next/server/chunks/ssr/6769f_@radix-ui_react-roving-focus_dist_index_mjs_b3be3d8e._.js +0 -3
  275. package/web/.next/server/chunks/ssr/6769f_@radix-ui_react-roving-focus_dist_index_mjs_b3be3d8e._.js.map +0 -1
  276. package/web/.next/server/chunks/ssr/[root-of-the-server]__2ffb27f1._.js +0 -3
  277. package/web/.next/server/chunks/ssr/[root-of-the-server]__2ffb27f1._.js.map +0 -1
  278. package/web/.next/server/chunks/ssr/[root-of-the-server]__551fb7e1._.js +0 -4
  279. package/web/.next/server/chunks/ssr/[root-of-the-server]__551fb7e1._.js.map +0 -1
  280. package/web/.next/server/chunks/ssr/[root-of-the-server]__7f4180a1._.js +0 -3
  281. package/web/.next/server/chunks/ssr/[root-of-the-server]__7f4180a1._.js.map +0 -1
  282. package/web/.next/server/chunks/ssr/[root-of-the-server]__e41b5eec._.js +0 -9
  283. package/web/.next/server/chunks/ssr/[root-of-the-server]__e41b5eec._.js.map +0 -1
  284. package/web/.next/server/chunks/ssr/[root-of-the-server]__eaf6100f._.js +0 -3
  285. package/web/.next/server/chunks/ssr/[root-of-the-server]__eaf6100f._.js.map +0 -1
  286. package/web/.next/server/chunks/ssr/_28993370._.js +0 -3
  287. package/web/.next/server/chunks/ssr/_28993370._.js.map +0 -1
  288. package/web/.next/server/chunks/ssr/_690ea95f._.js +0 -3
  289. package/web/.next/server/chunks/ssr/_690ea95f._.js.map +0 -1
  290. package/web/.next/server/chunks/ssr/src_presentation_web_components_0286756b._.js +0 -3
  291. package/web/.next/server/chunks/ssr/src_presentation_web_components_0286756b._.js.map +0 -1
  292. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/6769f_@radix-ui_react-roving-focus_dist_index_mjs_b3be3d8e._.js +0 -3
  293. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__2ffb27f1._.js +0 -3
  294. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__551fb7e1._.js +0 -4
  295. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__7f4180a1._.js +0 -3
  296. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__e41b5eec._.js +0 -9
  297. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__eaf6100f._.js +0 -3
  298. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_28993370._.js +0 -3
  299. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_690ea95f._.js +0 -3
  300. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_components_0286756b._.js +0 -3
  301. package/web/.next/static/chunks/16e380b8dd9d11bc.js +0 -1
  302. package/web/.next/static/chunks/24e1d97cab8bad6d.js +0 -1
  303. package/web/.next/static/chunks/505c6a9e4c5d0808.js +0 -1
  304. package/web/.next/static/chunks/a186bbb822ccb655.css +0 -2
  305. package/web/.next/static/chunks/a5c59952485e875e.js +0 -1
  306. package/web/.next/static/chunks/a9626385607910b3.js +0 -1
  307. package/web/.next/static/chunks/d4379644a6145352.js +0 -1
  308. package/web/.next/static/chunks/fb703cf73aba2eb8.js +0 -1
  309. /package/web/.next/server/chunks/ssr/{[root-of-the-server]__249c74f6._.js.map → [root-of-the-server]__6e8b5181._.js.map} +0 -0
  310. /package/web/.next/static/{8xZoRkWykApYNlvamCGUe → F3mdpVVEgR5m2xHY_SnYx}/_buildManifest.js +0 -0
  311. /package/web/.next/static/{8xZoRkWykApYNlvamCGUe → F3mdpVVEgR5m2xHY_SnYx}/_clientMiddlewareManifest.json +0 -0
  312. /package/web/.next/static/{8xZoRkWykApYNlvamCGUe → F3mdpVVEgR5m2xHY_SnYx}/_ssgManifest.js +0 -0
@@ -0,0 +1,110 @@
1
+ 'use client';
2
+
3
+ import { useRef, useEffect, useCallback } from 'react';
4
+ import { Terminal } from 'lucide-react';
5
+ import type { LogEntry } from '@shepai/core/application/ports/output/services/deployment-service.interface';
6
+ import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
7
+ import { useDeploymentLogs } from '@/hooks/use-deployment-logs';
8
+
9
+ export interface ServerLogViewerProps {
10
+ open: boolean;
11
+ onOpenChange: (open: boolean) => void;
12
+ targetId: string;
13
+ }
14
+
15
+ export interface ServerLogViewerContentProps {
16
+ open: boolean;
17
+ onOpenChange: (open: boolean) => void;
18
+ logs: LogEntry[];
19
+ isConnected: boolean;
20
+ }
21
+
22
+ const AUTO_SCROLL_THRESHOLD = 50;
23
+
24
+ export function ServerLogViewer({ open, onOpenChange, targetId }: ServerLogViewerProps) {
25
+ const { logs, isConnected } = useDeploymentLogs(open ? targetId : null);
26
+
27
+ return (
28
+ <ServerLogViewerContent
29
+ open={open}
30
+ onOpenChange={onOpenChange}
31
+ logs={logs}
32
+ isConnected={isConnected}
33
+ />
34
+ );
35
+ }
36
+
37
+ export function ServerLogViewerContent({
38
+ open,
39
+ onOpenChange,
40
+ logs,
41
+ isConnected,
42
+ }: ServerLogViewerContentProps) {
43
+ const scrollRef = useRef<HTMLDivElement>(null);
44
+ const isAtBottomRef = useRef(true);
45
+
46
+ const handleScroll = useCallback(() => {
47
+ const el = scrollRef.current;
48
+ if (!el) return;
49
+ isAtBottomRef.current =
50
+ el.scrollTop + el.clientHeight >= el.scrollHeight - AUTO_SCROLL_THRESHOLD;
51
+ }, []);
52
+
53
+ useEffect(() => {
54
+ if (isAtBottomRef.current && scrollRef.current) {
55
+ scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
56
+ }
57
+ }, [logs]);
58
+
59
+ return (
60
+ <Dialog open={open} onOpenChange={onOpenChange}>
61
+ <DialogContent
62
+ className="flex h-[calc(100vh-48px)] max-h-[calc(100vh-48px)] w-full max-w-[calc(100vw-48px)] flex-col gap-0 bg-zinc-950 p-0 text-zinc-100 sm:rounded-lg"
63
+ aria-describedby={undefined}
64
+ >
65
+ <DialogHeader className="flex flex-row items-center justify-between border-b border-zinc-800 px-4 py-3">
66
+ <div className="flex items-center gap-2">
67
+ <Terminal className="h-4 w-4 text-zinc-400" />
68
+ <DialogTitle className="text-sm font-medium text-zinc-100">Server Logs</DialogTitle>
69
+ </div>
70
+ <div className="flex items-center gap-2 pr-8">
71
+ <span
72
+ className={`inline-block h-2 w-2 rounded-full ${isConnected ? 'bg-green-500' : 'bg-zinc-500'}`}
73
+ />
74
+ <span className="text-xs text-zinc-400">
75
+ {isConnected ? 'Connected' : 'Disconnected'}
76
+ </span>
77
+ </div>
78
+ </DialogHeader>
79
+
80
+ <div
81
+ ref={scrollRef}
82
+ onScroll={handleScroll}
83
+ className="flex-1 overflow-auto p-4 font-mono text-sm leading-relaxed"
84
+ >
85
+ {logs.length === 0 ? (
86
+ <p className="text-zinc-500">Waiting for log output...</p>
87
+ ) : (
88
+ logs.map((entry) => (
89
+ <LogLine key={`${entry.timestamp}-${entry.stream}-${entry.line}`} entry={entry} />
90
+ ))
91
+ )}
92
+ {!isConnected && logs.length > 0 && (
93
+ <div className="mt-2 border-t border-zinc-800 pt-2 text-zinc-500">[Server stopped]</div>
94
+ )}
95
+ </div>
96
+ </DialogContent>
97
+ </Dialog>
98
+ );
99
+ }
100
+
101
+ function LogLine({ entry }: { entry: LogEntry }) {
102
+ return (
103
+ <div
104
+ data-stream={entry.stream}
105
+ className={entry.stream === 'stderr' ? 'text-red-400' : 'text-zinc-200'}
106
+ >
107
+ <span className="break-all whitespace-pre-wrap">{entry.line}</span>
108
+ </div>
109
+ );
110
+ }
@@ -1,4 +1,4 @@
1
- export { TechDecisionsReview } from './tech-decisions-review';
1
+ export { TechDecisionsReview, TechDecisionsContent } from './tech-decisions-review';
2
2
  export { TechDecisionsDrawer } from './tech-decisions-drawer';
3
3
  export type {
4
4
  TechDecisionsReviewProps,
@@ -7,7 +7,11 @@ import { Check, ChevronRight, GitCompareArrows, Layers } from 'lucide-react';
7
7
  import { Badge } from '@/components/ui/badge';
8
8
  import { DrawerActionBar } from '@/components/common/drawer-action-bar';
9
9
  import { useSoundAction } from '@/hooks/use-sound-action';
10
- import type { TechDecisionsReviewProps, TechDecision } from './tech-decisions-review-config';
10
+ import type {
11
+ TechDecisionsReviewProps,
12
+ TechDecisionsReviewData,
13
+ TechDecision,
14
+ } from './tech-decisions-review-config';
11
15
 
12
16
  const markdownComponents: Components = {
13
17
  p: ({ children }) => (
@@ -119,6 +123,44 @@ function DecisionCard({ decision, index }: { decision: TechDecision; index: numb
119
123
  );
120
124
  }
121
125
 
126
+ /**
127
+ * Renders the tech decisions content (header + decision cards) without the action bar.
128
+ * Used by TechReviewTabs to compose with a shared DrawerActionBar.
129
+ */
130
+ export function TechDecisionsContent({ data }: { data: TechDecisionsReviewData }) {
131
+ const { summary, decisions } = data;
132
+
133
+ if (decisions.length === 0) return null;
134
+
135
+ return (
136
+ <div className="space-y-4 p-4">
137
+ {/* Header */}
138
+ <div className="flex items-start gap-3">
139
+ <div className="mt-1.5 h-2.5 w-2.5 shrink-0 rounded-full bg-blue-500" />
140
+ <div className="flex-1">
141
+ <h2 className="text-foreground text-sm font-bold">
142
+ Technical Implementation Plan Review
143
+ </h2>
144
+ {summary ? (
145
+ <p className="text-muted-foreground mt-1 text-xs leading-relaxed">{summary}</p>
146
+ ) : null}
147
+ </div>
148
+ </div>
149
+
150
+ {/* Section heading */}
151
+ <div className="flex items-center gap-2 pt-1">
152
+ <GitCompareArrows className="text-primary h-4 w-4" />
153
+ <h3 className="text-foreground text-sm font-bold">Technical Decisions</h3>
154
+ </div>
155
+
156
+ {/* Decision cards */}
157
+ {decisions.map((decision, i) => (
158
+ <DecisionCard key={decision.title} decision={decision} index={i} />
159
+ ))}
160
+ </div>
161
+ );
162
+ }
163
+
122
164
  export function TechDecisionsReview({
123
165
  data,
124
166
  onApprove,
@@ -126,36 +168,12 @@ export function TechDecisionsReview({
126
168
  isProcessing = false,
127
169
  isRejecting = false,
128
170
  }: TechDecisionsReviewProps) {
129
- const { summary, decisions } = data;
130
-
131
- if (decisions.length === 0) return null;
171
+ if (data.decisions.length === 0) return null;
132
172
 
133
173
  return (
134
- <div className="flex flex-1 flex-col">
135
- <div className="flex-1 space-y-4 overflow-y-auto p-4">
136
- {/* Header */}
137
- <div className="flex items-start gap-3">
138
- <div className="mt-1.5 h-2.5 w-2.5 shrink-0 rounded-full bg-blue-500" />
139
- <div className="flex-1">
140
- <h2 className="text-foreground text-sm font-bold">
141
- Technical Implementation Plan Review
142
- </h2>
143
- {summary ? (
144
- <p className="text-muted-foreground mt-1 text-xs leading-relaxed">{summary}</p>
145
- ) : null}
146
- </div>
147
- </div>
148
-
149
- {/* Section heading */}
150
- <div className="flex items-center gap-2 pt-1">
151
- <GitCompareArrows className="text-primary h-4 w-4" />
152
- <h3 className="text-foreground text-sm font-bold">Technical Decisions</h3>
153
- </div>
154
-
155
- {/* Decision cards */}
156
- {decisions.map((decision, i) => (
157
- <DecisionCard key={decision.title} decision={decision} index={i} />
158
- ))}
174
+ <div className="flex min-h-0 flex-1 flex-col">
175
+ <div className="flex-1 overflow-y-auto">
176
+ <TechDecisionsContent data={data} />
159
177
  </div>
160
178
 
161
179
  <DrawerActionBar
@@ -0,0 +1,2 @@
1
+ export { TechReviewTabs } from './tech-review-tabs';
2
+ export type { TechReviewTabsProps } from './tech-review-tabs-config';
@@ -0,0 +1,17 @@
1
+ import type { TechDecisionsReviewData } from '@/components/common/tech-decisions-review';
2
+ import type { ProductDecisionsSummaryData } from '@/components/common/product-decisions-summary';
3
+
4
+ export interface TechReviewTabsProps {
5
+ /** Tech decisions data from the research artifact */
6
+ techData: TechDecisionsReviewData;
7
+ /** Product decisions data — null while loading, undefined if unavailable */
8
+ productData?: ProductDecisionsSummaryData | null;
9
+ /** Approve plan callback */
10
+ onApprove: () => void;
11
+ /** Reject plan callback */
12
+ onReject?: (feedback: string) => void;
13
+ /** Controls disabled state during loading */
14
+ isProcessing?: boolean;
15
+ /** Whether a reject operation is in flight */
16
+ isRejecting?: boolean;
17
+ }
@@ -0,0 +1,129 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { fn } from '@storybook/test';
3
+ import { TechReviewTabs } from './tech-review-tabs';
4
+ import type { TechDecisionsReviewData } from '@/components/common/tech-decisions-review';
5
+ import type { ProductDecisionsSummaryData } from '@/components/common/product-decisions-summary';
6
+
7
+ const mockTechData: TechDecisionsReviewData = {
8
+ name: 'Agent Executor Abstraction',
9
+ summary:
10
+ 'Research into the best approach for abstracting agent executors to support multiple AI backends.',
11
+ technologies: ['TypeScript', 'tsyringe', 'LangGraph', 'Claude API'],
12
+ decisions: [
13
+ {
14
+ title: 'Agent Execution Framework',
15
+ chosen: 'LangGraph',
16
+ rejected: ['Custom state machine', 'Temporal.io', 'Step Functions'],
17
+ rationale:
18
+ 'LangGraph provides built-in checkpointing, human-in-the-loop support, and integrates natively with LangChain.',
19
+ },
20
+ {
21
+ title: 'Dependency Injection',
22
+ chosen: 'tsyringe',
23
+ rejected: ['InversifyJS', 'TypeDI', 'Manual DI'],
24
+ rationale: 'tsyringe is lightweight, uses standard decorators, and has minimal overhead.',
25
+ },
26
+ {
27
+ title: 'Inter-Process Communication',
28
+ chosen: 'Server-Sent Events (SSE)',
29
+ rejected: ['WebSockets', 'Long Polling', 'gRPC'],
30
+ rationale:
31
+ 'SSE provides a simple one-way streaming protocol for agent status updates to the UI.',
32
+ },
33
+ ],
34
+ };
35
+
36
+ const mockProductData: ProductDecisionsSummaryData = {
37
+ question: 'Goal',
38
+ context: 'Add multi-agent support to the platform',
39
+ questions: [
40
+ {
41
+ question: 'Which authentication strategy should we use?',
42
+ selectedOption: 'OAuth 2.0',
43
+ rationale: 'Industry standard with broad provider support.',
44
+ wasRecommended: true,
45
+ },
46
+ {
47
+ question: 'How should we handle session management?',
48
+ selectedOption: 'JWT tokens',
49
+ rationale: 'Stateless and scalable across services.',
50
+ wasRecommended: false,
51
+ },
52
+ {
53
+ question: 'What level of MFA should we support?',
54
+ selectedOption: 'Optional TOTP',
55
+ rationale: 'Balances security with user convenience.',
56
+ wasRecommended: true,
57
+ },
58
+ ],
59
+ };
60
+
61
+ const meta: Meta<typeof TechReviewTabs> = {
62
+ title: 'Drawers/Review/TechReviewTabs',
63
+ component: TechReviewTabs,
64
+ tags: ['autodocs'],
65
+ parameters: {
66
+ layout: 'fullscreen',
67
+ },
68
+ decorators: [
69
+ (Story) => (
70
+ <div style={{ height: '600px', width: '400px', border: '1px solid var(--color-border)' }}>
71
+ <Story />
72
+ </div>
73
+ ),
74
+ ],
75
+ };
76
+
77
+ export default meta;
78
+ type Story = StoryObj<typeof TechReviewTabs>;
79
+
80
+ /** Default — both tabs with data, Technical tab active. */
81
+ export const Default: Story = {
82
+ args: {
83
+ techData: mockTechData,
84
+ productData: mockProductData,
85
+ onReject: fn().mockName('onReject'),
86
+ onApprove: fn().mockName('onApprove'),
87
+ },
88
+ };
89
+
90
+ /** Product data loading — spinner in the Product tab. */
91
+ export const ProductDataLoading: Story = {
92
+ args: {
93
+ techData: mockTechData,
94
+ productData: null,
95
+ onReject: fn().mockName('onReject'),
96
+ onApprove: fn().mockName('onApprove'),
97
+ },
98
+ };
99
+
100
+ /** Product data unavailable — fallback message in the Product tab. */
101
+ export const ProductDataUnavailable: Story = {
102
+ args: {
103
+ techData: mockTechData,
104
+ productData: undefined,
105
+ onReject: fn().mockName('onReject'),
106
+ onApprove: fn().mockName('onApprove'),
107
+ },
108
+ };
109
+
110
+ /** Processing state — approve button disabled. */
111
+ export const Processing: Story = {
112
+ args: {
113
+ techData: mockTechData,
114
+ productData: mockProductData,
115
+ onApprove: fn().mockName('onApprove'),
116
+ isProcessing: true,
117
+ },
118
+ };
119
+
120
+ /** Rejecting state — reject input disabled. */
121
+ export const Rejecting: Story = {
122
+ args: {
123
+ techData: mockTechData,
124
+ productData: mockProductData,
125
+ onReject: fn().mockName('onReject'),
126
+ onApprove: fn().mockName('onApprove'),
127
+ isRejecting: true,
128
+ },
129
+ };
@@ -0,0 +1,60 @@
1
+ 'use client';
2
+
3
+ import { Check, Loader2 } from 'lucide-react';
4
+ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
5
+ import { DrawerActionBar } from '@/components/common/drawer-action-bar';
6
+ import { TechDecisionsContent } from '@/components/common/tech-decisions-review';
7
+ import { ProductDecisionsSummary } from '@/components/common/product-decisions-summary';
8
+ import type { TechReviewTabsProps } from './tech-review-tabs-config';
9
+
10
+ export function TechReviewTabs({
11
+ techData,
12
+ productData,
13
+ onApprove,
14
+ onReject,
15
+ isProcessing = false,
16
+ isRejecting = false,
17
+ }: TechReviewTabsProps) {
18
+ if (techData.decisions.length === 0) return null;
19
+
20
+ return (
21
+ <div className="flex min-h-0 flex-1 flex-col">
22
+ <Tabs defaultValue="technical" className="flex min-h-0 flex-1 flex-col">
23
+ <div className="shrink-0 px-4 pt-4">
24
+ <TabsList className="grid w-full grid-cols-2">
25
+ <TabsTrigger value="product">Product</TabsTrigger>
26
+ <TabsTrigger value="technical">Technical</TabsTrigger>
27
+ </TabsList>
28
+ </div>
29
+
30
+ <TabsContent value="product" className="mt-0 flex-1 overflow-y-auto">
31
+ {productData === null ? (
32
+ <div className="flex items-center justify-center p-8" data-testid="product-loading">
33
+ <Loader2 className="text-muted-foreground h-6 w-6 animate-spin" />
34
+ </div>
35
+ ) : productData ? (
36
+ <ProductDecisionsSummary data={productData} />
37
+ ) : (
38
+ <p className="text-muted-foreground p-4 text-center text-sm">
39
+ No product decisions available.
40
+ </p>
41
+ )}
42
+ </TabsContent>
43
+
44
+ <TabsContent value="technical" className="mt-0 flex-1 overflow-y-auto">
45
+ <TechDecisionsContent data={techData} />
46
+ </TabsContent>
47
+ </Tabs>
48
+
49
+ <DrawerActionBar
50
+ onReject={onReject}
51
+ onApprove={onApprove}
52
+ approveLabel="Approve Plan"
53
+ approveIcon={<Check className="mr-1.5 h-4 w-4" />}
54
+ revisionPlaceholder="Ask AI to revise the plan..."
55
+ isProcessing={isProcessing}
56
+ isRejecting={isRejecting}
57
+ />
58
+ </div>
59
+ );
60
+ }
@@ -0,0 +1,67 @@
1
+ 'use client';
2
+
3
+ import { useState, useEffect, useRef, useCallback } from 'react';
4
+ import type { LogEntry } from '@shepai/core/application/ports/output/services/deployment-service.interface';
5
+ import { getDeploymentLogs } from '@/app/actions/get-deployment-logs';
6
+
7
+ export interface UseDeploymentLogsResult {
8
+ logs: LogEntry[];
9
+ isConnected: boolean;
10
+ }
11
+
12
+ export function useDeploymentLogs(targetId: string | null | undefined): UseDeploymentLogsResult {
13
+ const [logs, setLogs] = useState<LogEntry[]>([]);
14
+ const [isConnected, setIsConnected] = useState(false);
15
+ const eventSourceRef = useRef<EventSource | null>(null);
16
+
17
+ const cleanup = useCallback(() => {
18
+ if (eventSourceRef.current) {
19
+ eventSourceRef.current.close();
20
+ eventSourceRef.current = null;
21
+ }
22
+ setIsConnected(false);
23
+ }, []);
24
+
25
+ useEffect(() => {
26
+ if (!targetId) {
27
+ setLogs([]);
28
+ setIsConnected(false);
29
+ return;
30
+ }
31
+
32
+ // Fetch initial logs
33
+ getDeploymentLogs(targetId)
34
+ .then((initialLogs) => {
35
+ if (initialLogs) {
36
+ setLogs(initialLogs);
37
+ }
38
+ })
39
+ .catch(() => {
40
+ // Initial fetch failed — logs stay empty, SSE will still connect
41
+ });
42
+
43
+ // Connect EventSource for live updates
44
+ const es = new EventSource(`/api/deployment-logs?targetId=${targetId}`);
45
+ eventSourceRef.current = es;
46
+
47
+ es.onopen = () => {
48
+ setIsConnected(true);
49
+ };
50
+
51
+ es.addEventListener('log', (event: MessageEvent) => {
52
+ const entry: LogEntry = JSON.parse(event.data);
53
+ setLogs((prev) => [...prev, entry]);
54
+ });
55
+
56
+ es.onerror = () => {
57
+ setIsConnected(false);
58
+ };
59
+
60
+ return () => {
61
+ es.close();
62
+ eventSourceRef.current = null;
63
+ };
64
+ }, [targetId, cleanup]);
65
+
66
+ return { logs, isConnected };
67
+ }
@@ -15,7 +15,7 @@ const currentPort = parseInt(process.env.PORT, 10) || 3000
15
15
  const hostname = process.env.HOSTNAME || '0.0.0.0'
16
16
 
17
17
  let keepAliveTimeout = parseInt(process.env.KEEP_ALIVE_TIMEOUT, 10)
18
- const nextConfig = {"env":{"NEXT_PUBLIC_SHEP_VERSION":"1.70.0","NEXT_PUBLIC_SHEP_PACKAGE_NAME":"@shepai/cli","NEXT_PUBLIC_SHEP_DESCRIPTION":"Autonomous AI Native SDLC Platform - Automate the development cycle from idea to deploy"},"webpack":null,"typescript":{"ignoreBuildErrors":false},"typedRoutes":true,"distDir":"./.next","cleanDistDir":true,"assetPrefix":"","cacheMaxMemorySize":52428800,"configOrigin":"next.config.ts","useFileSystemPublicRoutes":true,"generateEtags":true,"pageExtensions":["tsx","ts","jsx","js"],"poweredByHeader":true,"compress":true,"images":{"deviceSizes":[640,750,828,1080,1200,1920,2048,3840],"imageSizes":[32,48,64,96,128,256,384],"path":"/_next/image","loader":"default","loaderFile":"","domains":[],"disableStaticImages":false,"minimumCacheTTL":14400,"formats":["image/webp"],"maximumRedirects":3,"maximumResponseBody":50000000,"dangerouslyAllowLocalIP":false,"dangerouslyAllowSVG":false,"contentSecurityPolicy":"script-src 'none'; frame-src 'none'; sandbox;","contentDispositionType":"attachment","localPatterns":[{"pathname":"**","search":""}],"remotePatterns":[],"qualities":[75],"unoptimized":false},"devIndicators":{"position":"bottom-left"},"onDemandEntries":{"maxInactiveAge":60000,"pagesBufferLength":5},"basePath":"","sassOptions":{},"trailingSlash":false,"i18n":null,"productionBrowserSourceMaps":false,"excludeDefaultMomentLocales":true,"reactProductionProfiling":false,"reactStrictMode":null,"reactMaxHeadersLength":6000,"httpAgentOptions":{"keepAlive":true},"logging":{},"compiler":{},"expireTime":31536000,"staticPageGenerationTimeout":60,"output":"standalone","modularizeImports":{"@mui/icons-material":{"transform":"@mui/icons-material/{{member}}"},"lodash":{"transform":"lodash/{{member}}"}},"outputFileTracingRoot":"/home/runner/work/cli/cli","cacheComponents":false,"cacheLife":{"default":{"stale":300,"revalidate":900,"expire":4294967294},"seconds":{"stale":30,"revalidate":1,"expire":60},"minutes":{"stale":300,"revalidate":60,"expire":3600},"hours":{"stale":300,"revalidate":3600,"expire":86400},"days":{"stale":300,"revalidate":86400,"expire":604800},"weeks":{"stale":300,"revalidate":604800,"expire":2592000},"max":{"stale":300,"revalidate":2592000,"expire":31536000}},"cacheHandlers":{},"experimental":{"useSkewCookie":false,"cssChunking":true,"multiZoneDraftMode":false,"appNavFailHandling":false,"prerenderEarlyExit":true,"serverMinification":true,"linkNoTouchStart":false,"caseSensitiveRoutes":false,"dynamicOnHover":false,"preloadEntriesOnStart":true,"clientRouterFilter":true,"clientRouterFilterRedirects":false,"fetchCacheKeyPrefix":"","proxyPrefetch":"flexible","optimisticClientCache":true,"manualClientBasePath":false,"cpus":3,"memoryBasedWorkersCount":false,"imgOptConcurrency":null,"imgOptTimeoutInSeconds":7,"imgOptMaxInputPixels":268402689,"imgOptSequentialRead":null,"imgOptSkipMetadata":null,"isrFlushToDisk":true,"workerThreads":false,"optimizeCss":false,"nextScriptWorkers":false,"scrollRestoration":false,"externalDir":false,"disableOptimizedLoading":false,"gzipSize":true,"craCompat":false,"esmExternals":true,"fullySpecified":false,"swcTraceProfiling":false,"forceSwcTransforms":false,"largePageDataBytes":128000,"typedEnv":false,"parallelServerCompiles":false,"parallelServerBuildTraces":false,"ppr":false,"authInterrupts":false,"webpackMemoryOptimizations":false,"optimizeServerReact":true,"viewTransition":false,"removeUncaughtErrorAndRejectionListeners":false,"validateRSCRequestHeaders":false,"staleTimes":{"dynamic":0,"static":300},"reactDebugChannel":false,"serverComponentsHmrCache":true,"staticGenerationMaxConcurrency":8,"staticGenerationMinPagesPerWorker":25,"transitionIndicator":false,"inlineCss":false,"useCache":false,"globalNotFound":false,"browserDebugInfoInTerminal":false,"lockDistDir":true,"isolatedDevBuild":true,"proxyClientMaxBodySize":10485760,"hideLogsAfterAbort":false,"mcpServer":true,"turbopackFileSystemCacheForDev":true,"turbopackFileSystemCacheForBuild":false,"turbopackInferModuleSideEffects":false,"optimizePackageImports":["lucide-react","date-fns","lodash-es","ramda","antd","react-bootstrap","ahooks","@ant-design/icons","@headlessui/react","@headlessui-float/react","@heroicons/react/20/solid","@heroicons/react/24/solid","@heroicons/react/24/outline","@visx/visx","@tremor/react","rxjs","@mui/material","@mui/icons-material","recharts","react-use","effect","@effect/schema","@effect/platform","@effect/platform-node","@effect/platform-browser","@effect/platform-bun","@effect/sql","@effect/sql-mssql","@effect/sql-mysql2","@effect/sql-pg","@effect/sql-sqlite-node","@effect/sql-sqlite-bun","@effect/sql-sqlite-wasm","@effect/sql-sqlite-react-native","@effect/rpc","@effect/rpc-http","@effect/typeclass","@effect/experimental","@effect/opentelemetry","@material-ui/core","@material-ui/icons","@tabler/icons-react","mui-core","react-icons/ai","react-icons/bi","react-icons/bs","react-icons/cg","react-icons/ci","react-icons/di","react-icons/fa","react-icons/fa6","react-icons/fc","react-icons/fi","react-icons/gi","react-icons/go","react-icons/gr","react-icons/hi","react-icons/hi2","react-icons/im","react-icons/io","react-icons/io5","react-icons/lia","react-icons/lib","react-icons/lu","react-icons/md","react-icons/pi","react-icons/ri","react-icons/rx","react-icons/si","react-icons/sl","react-icons/tb","react-icons/tfi","react-icons/ti","react-icons/vsc","react-icons/wi"],"trustHostHeader":false,"isExperimentalCompile":false},"htmlLimitedBots":"[\\w-]+-Google|Google-[\\w-]+|Chrome-Lighthouse|Slurp|DuckDuckBot|baiduspider|yandex|sogou|bitlybot|tumblr|vkShare|quora link preview|redditbot|ia_archiver|Bingbot|BingPreview|applebot|facebookexternalhit|facebookcatalog|Twitterbot|LinkedInBot|Slackbot|Discordbot|WhatsApp|SkypeUriPreview|Yeti|googleweblight","bundlePagesRouterDependencies":false,"configFileName":"next.config.ts","turbopack":{"root":"/home/runner/work/cli/cli"},"serverExternalPackages":["tsyringe","reflect-metadata","better-sqlite3","node:os","node:child_process","node:fs"],"distDirRoot":".next"}
18
+ const nextConfig = {"env":{"NEXT_PUBLIC_SHEP_VERSION":"1.70.2","NEXT_PUBLIC_SHEP_PACKAGE_NAME":"@shepai/cli","NEXT_PUBLIC_SHEP_DESCRIPTION":"Autonomous AI Native SDLC Platform - Automate the development cycle from idea to deploy"},"webpack":null,"typescript":{"ignoreBuildErrors":false},"typedRoutes":true,"distDir":"./.next","cleanDistDir":true,"assetPrefix":"","cacheMaxMemorySize":52428800,"configOrigin":"next.config.ts","useFileSystemPublicRoutes":true,"generateEtags":true,"pageExtensions":["tsx","ts","jsx","js"],"poweredByHeader":true,"compress":true,"images":{"deviceSizes":[640,750,828,1080,1200,1920,2048,3840],"imageSizes":[32,48,64,96,128,256,384],"path":"/_next/image","loader":"default","loaderFile":"","domains":[],"disableStaticImages":false,"minimumCacheTTL":14400,"formats":["image/webp"],"maximumRedirects":3,"maximumResponseBody":50000000,"dangerouslyAllowLocalIP":false,"dangerouslyAllowSVG":false,"contentSecurityPolicy":"script-src 'none'; frame-src 'none'; sandbox;","contentDispositionType":"attachment","localPatterns":[{"pathname":"**","search":""}],"remotePatterns":[],"qualities":[75],"unoptimized":false},"devIndicators":{"position":"bottom-left"},"onDemandEntries":{"maxInactiveAge":60000,"pagesBufferLength":5},"basePath":"","sassOptions":{},"trailingSlash":false,"i18n":null,"productionBrowserSourceMaps":false,"excludeDefaultMomentLocales":true,"reactProductionProfiling":false,"reactStrictMode":null,"reactMaxHeadersLength":6000,"httpAgentOptions":{"keepAlive":true},"logging":{},"compiler":{},"expireTime":31536000,"staticPageGenerationTimeout":60,"output":"standalone","modularizeImports":{"@mui/icons-material":{"transform":"@mui/icons-material/{{member}}"},"lodash":{"transform":"lodash/{{member}}"}},"outputFileTracingRoot":"/home/runner/work/cli/cli","cacheComponents":false,"cacheLife":{"default":{"stale":300,"revalidate":900,"expire":4294967294},"seconds":{"stale":30,"revalidate":1,"expire":60},"minutes":{"stale":300,"revalidate":60,"expire":3600},"hours":{"stale":300,"revalidate":3600,"expire":86400},"days":{"stale":300,"revalidate":86400,"expire":604800},"weeks":{"stale":300,"revalidate":604800,"expire":2592000},"max":{"stale":300,"revalidate":2592000,"expire":31536000}},"cacheHandlers":{},"experimental":{"useSkewCookie":false,"cssChunking":true,"multiZoneDraftMode":false,"appNavFailHandling":false,"prerenderEarlyExit":true,"serverMinification":true,"linkNoTouchStart":false,"caseSensitiveRoutes":false,"dynamicOnHover":false,"preloadEntriesOnStart":true,"clientRouterFilter":true,"clientRouterFilterRedirects":false,"fetchCacheKeyPrefix":"","proxyPrefetch":"flexible","optimisticClientCache":true,"manualClientBasePath":false,"cpus":3,"memoryBasedWorkersCount":false,"imgOptConcurrency":null,"imgOptTimeoutInSeconds":7,"imgOptMaxInputPixels":268402689,"imgOptSequentialRead":null,"imgOptSkipMetadata":null,"isrFlushToDisk":true,"workerThreads":false,"optimizeCss":false,"nextScriptWorkers":false,"scrollRestoration":false,"externalDir":false,"disableOptimizedLoading":false,"gzipSize":true,"craCompat":false,"esmExternals":true,"fullySpecified":false,"swcTraceProfiling":false,"forceSwcTransforms":false,"largePageDataBytes":128000,"typedEnv":false,"parallelServerCompiles":false,"parallelServerBuildTraces":false,"ppr":false,"authInterrupts":false,"webpackMemoryOptimizations":false,"optimizeServerReact":true,"viewTransition":false,"removeUncaughtErrorAndRejectionListeners":false,"validateRSCRequestHeaders":false,"staleTimes":{"dynamic":0,"static":300},"reactDebugChannel":false,"serverComponentsHmrCache":true,"staticGenerationMaxConcurrency":8,"staticGenerationMinPagesPerWorker":25,"transitionIndicator":false,"inlineCss":false,"useCache":false,"globalNotFound":false,"browserDebugInfoInTerminal":false,"lockDistDir":true,"isolatedDevBuild":true,"proxyClientMaxBodySize":10485760,"hideLogsAfterAbort":false,"mcpServer":true,"turbopackFileSystemCacheForDev":true,"turbopackFileSystemCacheForBuild":false,"turbopackInferModuleSideEffects":false,"optimizePackageImports":["lucide-react","date-fns","lodash-es","ramda","antd","react-bootstrap","ahooks","@ant-design/icons","@headlessui/react","@headlessui-float/react","@heroicons/react/20/solid","@heroicons/react/24/solid","@heroicons/react/24/outline","@visx/visx","@tremor/react","rxjs","@mui/material","@mui/icons-material","recharts","react-use","effect","@effect/schema","@effect/platform","@effect/platform-node","@effect/platform-browser","@effect/platform-bun","@effect/sql","@effect/sql-mssql","@effect/sql-mysql2","@effect/sql-pg","@effect/sql-sqlite-node","@effect/sql-sqlite-bun","@effect/sql-sqlite-wasm","@effect/sql-sqlite-react-native","@effect/rpc","@effect/rpc-http","@effect/typeclass","@effect/experimental","@effect/opentelemetry","@material-ui/core","@material-ui/icons","@tabler/icons-react","mui-core","react-icons/ai","react-icons/bi","react-icons/bs","react-icons/cg","react-icons/ci","react-icons/di","react-icons/fa","react-icons/fa6","react-icons/fc","react-icons/fi","react-icons/gi","react-icons/go","react-icons/gr","react-icons/hi","react-icons/hi2","react-icons/im","react-icons/io","react-icons/io5","react-icons/lia","react-icons/lib","react-icons/lu","react-icons/md","react-icons/pi","react-icons/ri","react-icons/rx","react-icons/si","react-icons/sl","react-icons/tb","react-icons/tfi","react-icons/ti","react-icons/vsc","react-icons/wi"],"trustHostHeader":false,"isExperimentalCompile":false},"htmlLimitedBots":"[\\w-]+-Google|Google-[\\w-]+|Chrome-Lighthouse|Slurp|DuckDuckBot|baiduspider|yandex|sogou|bitlybot|tumblr|vkShare|quora link preview|redditbot|ia_archiver|Bingbot|BingPreview|applebot|facebookexternalhit|facebookcatalog|Twitterbot|LinkedInBot|Slackbot|Discordbot|WhatsApp|SkypeUriPreview|Yeti|googleweblight","bundlePagesRouterDependencies":false,"configFileName":"next.config.ts","turbopack":{"root":"/home/runner/work/cli/cli"},"serverExternalPackages":["tsyringe","reflect-metadata","better-sqlite3","node:os","node:child_process","node:fs"],"distDirRoot":".next"}
19
19
 
20
20
  process.env.__NEXT_PRIVATE_STANDALONE_CONFIG = JSON.stringify(nextConfig)
21
21
 
@@ -0,0 +1 @@
1
+ (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,30702,e=>{"use strict";let a=(0,e.i(3645).default)("external-link",[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"M10 14 21 3",key:"gplh6r"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",key:"a6xqqp"}]]);e.s(["ExternalLink",()=>a],30702)},38573,e=>{"use strict";let a=(0,e.i(3645).default)("terminal",[["path",{d:"M12 19h8",key:"baeox8"}],["path",{d:"m4 17 6-6-6-6",key:"1yngyt"}]]);e.s(["Terminal",()=>a],38573)},2287,60253,e=>{"use strict";var a=e.i(20314),t=e.i(79054),s=e.i(90033),l=e.i(90537);e.s(["X",()=>l.default],60253);var l=l,r=e.i(31777);let i=s.Dialog.Root;s.Dialog.Trigger;let n=s.Dialog.Portal;s.Dialog.Close;let o=t.forwardRef(({className:e,...t},l)=>(0,a.jsx)(s.Dialog.Overlay,{ref:l,className:(0,r.cn)("data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80",e),...t}));o.displayName=s.Dialog.Overlay.displayName;let d=t.forwardRef(({className:e,children:t,...i},d)=>(0,a.jsxs)(n,{children:[(0,a.jsx)(o,{}),(0,a.jsxs)(s.Dialog.Content,{ref:d,className:(0,r.cn)("bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] fixed top-[50%] left-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border p-6 shadow-lg duration-200 sm:rounded-lg",e),...i,children:[t,(0,a.jsxs)(s.Dialog.Close,{className:"ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-none disabled:pointer-events-none",children:[(0,a.jsx)(l.default,{className:"h-4 w-4"}),(0,a.jsx)("span",{className:"sr-only",children:"Close"})]})]})]}));d.displayName=s.Dialog.Content.displayName;let c=({className:e,...t})=>(0,a.jsx)("div",{className:(0,r.cn)("flex flex-col space-y-1.5 text-center sm:text-left",e),...t});c.displayName="DialogHeader";let u=t.forwardRef(({className:e,...t},l)=>(0,a.jsx)(s.Dialog.Title,{ref:l,className:(0,r.cn)("text-lg leading-none font-semibold tracking-tight",e),...t}));u.displayName=s.Dialog.Title.displayName;let m=t.forwardRef(({className:e,...t},l)=>(0,a.jsx)(s.Dialog.Description,{ref:l,className:(0,r.cn)("text-muted-foreground text-sm",e),...t}));m.displayName=s.Dialog.Description.displayName,e.s(["Dialog",()=>i,"DialogContent",()=>d,"DialogDescription",()=>m,"DialogHeader",()=>c,"DialogTitle",()=>u],2287)},81846,e=>{"use strict";var a=e.i(20314),t=e.i(94237),s=e.i(31777);let l=(0,t.cva)("inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:outline-none",{variants:{variant:{default:"border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80",secondary:"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",destructive:"border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80",outline:"text-foreground"}},defaultVariants:{variant:"default"}});function r({className:e,variant:t,...r}){return(0,a.jsx)("div",{className:(0,s.cn)(l({variant:t}),e),...r})}e.s(["Badge",()=>r])},956,e=>{"use strict";var a=e.i(20314),t=e.i(79054),s=e.i(31777);let l=t.forwardRef(({className:e,...t},l)=>(0,a.jsx)("div",{ref:l,className:(0,s.cn)("bg-card text-card-foreground rounded-xl border shadow",e),...t}));l.displayName="Card";let r=t.forwardRef(({className:e,...t},l)=>(0,a.jsx)("div",{ref:l,className:(0,s.cn)("flex flex-col space-y-1.5 p-6",e),...t}));r.displayName="CardHeader";let i=t.forwardRef(({className:e,...t},l)=>(0,a.jsx)("div",{ref:l,className:(0,s.cn)("leading-none font-semibold tracking-tight",e),...t}));i.displayName="CardTitle";let n=t.forwardRef(({className:e,...t},l)=>(0,a.jsx)("div",{ref:l,className:(0,s.cn)("text-muted-foreground text-sm",e),...t}));n.displayName="CardDescription";let o=t.forwardRef(({className:e,...t},l)=>(0,a.jsx)("div",{ref:l,className:(0,s.cn)("p-6 pt-0",e),...t}));o.displayName="CardContent",t.forwardRef(({className:e,...t},l)=>(0,a.jsx)("div",{ref:l,className:(0,s.cn)("flex items-center p-6 pt-0",e),...t})).displayName="CardFooter",e.s(["Card",()=>l,"CardContent",()=>o,"CardDescription",()=>n,"CardHeader",()=>r,"CardTitle",()=>i])},38752,e=>{"use strict";var a=e.i(20314);e.i(1650);var t=e.i(11495),s=e.i(45811),l=e.i(81846),r=e.i(25235),i=e.i(19933);function n({skill:e,onClose:n}){return(0,a.jsx)(t.BaseDrawer,{open:null!==e,onClose:n,size:"sm",modal:!0,"data-testid":"skill-detail-drawer",header:e?(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(s.DrawerTitle,{children:e.displayName}),(0,a.jsx)(s.DrawerDescription,{children:e.name})]}):void 0,children:e?(0,a.jsxs)("div",{className:"px-4 pb-4",children:[(0,a.jsx)("p",{className:"text-muted-foreground text-sm",children:e.description}),(0,a.jsxs)("div",{className:"mt-4 flex flex-wrap items-center gap-1.5",children:[(0,a.jsx)(l.Badge,{variant:"project"===e.source?"secondary":"outline",children:"project"===e.source?"Project":"Global"}),(0,a.jsx)(l.Badge,{variant:"outline",children:e.category}),e.context?(0,a.jsx)(l.Badge,{variant:"outline",children:e.context}):null]}),e.allowedTools?(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(r.Separator,{className:"my-4"}),(0,a.jsxs)("div",{children:[(0,a.jsx)("h3",{className:"text-sm font-semibold",children:"Allowed Tools"}),(0,a.jsx)("p",{className:"text-muted-foreground mt-1 text-sm",children:e.allowedTools})]})]}):null,e.resources.length>0?(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(r.Separator,{className:"my-4"}),(0,a.jsxs)("div",{children:[(0,a.jsx)("h3",{className:"text-sm font-semibold",children:"Resources"}),(0,a.jsx)("ul",{className:"mt-2 space-y-1.5",children:e.resources.map(e=>(0,a.jsxs)("li",{className:"text-muted-foreground flex items-center gap-2 text-sm",children:[(0,a.jsx)(i.FolderOpen,{className:"size-3.5 shrink-0"}),(0,a.jsxs)("span",{children:[e.name,"/ — ",e.fileCount," ",1===e.fileCount?"file":"files"]})]},e.name))})]})]}):null,e.body?(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(r.Separator,{className:"my-4"}),(0,a.jsx)("pre",{className:"text-muted-foreground text-sm leading-relaxed whitespace-pre-wrap",children:e.body})]}):null]}):null})}e.s(["SkillDetailDrawer",()=>n])},16919,e=>{"use strict";var a=e.i(20314),t=e.i(79054);let s=(0,e.i(3645).default)("search",[["path",{d:"m21 21-4.34-4.34",key:"14j7rj"}],["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}]]);var l=e.i(12103),r=e.i(98127),i=e.i(35364),n=e.i(31777);function o({title:e,description:t,children:s,className:l}){return(0,a.jsxs)("header",{className:(0,n.cn)("flex items-center justify-between gap-4",l),children:[(0,a.jsxs)("div",{className:"space-y-1",children:[(0,a.jsx)("h1",{className:"text-2xl font-bold tracking-tight",children:e}),t?(0,a.jsx)("p",{className:"text-muted-foreground",children:t}):null]}),s?(0,a.jsx)("div",{"data-slot":"actions",children:s}):null]})}e.i(54793);var d=e.i(7729),c=e.i(956),u=e.i(81846),m=e.i(19933);function x({skill:e,onSelect:t}){return(0,a.jsxs)(c.Card,{className:"hover:border-primary/50 cursor-pointer transition-colors",role:"button",tabIndex:0,onClick:()=>t(e),onKeyDown:a=>{("Enter"===a.key||" "===a.key)&&(a.preventDefault(),t(e))},"data-testid":`skill-card-${e.name}`,children:[(0,a.jsxs)(c.CardHeader,{className:"pb-3",children:[(0,a.jsx)(c.CardTitle,{className:"text-base",children:e.displayName}),(0,a.jsx)("p",{className:"text-muted-foreground font-mono text-xs",children:e.name})]}),(0,a.jsxs)(c.CardContent,{className:"space-y-3",children:[(0,a.jsx)("p",{className:"text-muted-foreground line-clamp-2 text-sm",children:e.description}),(0,a.jsxs)("div",{className:"flex flex-wrap items-center gap-1.5",children:[(0,a.jsx)(u.Badge,{variant:"project"===e.source?"secondary":"outline",children:"project"===e.source?"Project":"Global"}),e.context?(0,a.jsx)(u.Badge,{variant:"outline",children:e.context}):null,e.allowedTools?(0,a.jsx)(u.Badge,{variant:"outline",children:"Tools"}):null,e.resources.length>0?(0,a.jsxs)("span",{className:"text-muted-foreground inline-flex items-center gap-1 text-xs",children:[(0,a.jsx)(m.FolderOpen,{className:"size-3"}),e.resources.length," ",1===e.resources.length?"resource":"resources"]}):null]})]})]})}let f=["Workflow","Code Generation","Analysis","Reference"];function p({skills:e,onSkillSelect:t}){let s=function(e){let a=new Map;for(let t of e){let e=a.get(t.category)??[];e.push(t),a.set(t.category,e)}return a}(e);return(0,a.jsx)("div",{className:"space-y-8",children:f.map(e=>{let l=s.get(e);return l&&0!==l.length?(0,a.jsxs)("section",{children:[(0,a.jsxs)("h2",{className:"mb-4 text-lg font-semibold",children:[e," ",(0,a.jsxs)("span",{className:"text-muted-foreground text-sm font-normal",children:["(",l.length,")"]})]}),(0,a.jsx)("div",{className:"grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3",children:l.map(e=>(0,a.jsx)(x,{skill:e,onSelect:t},e.name))})]},e):null})})}let g=[{label:"All",value:null},{label:"Workflow",value:"Workflow"},{label:"Code Generation",value:"Code Generation"},{label:"Analysis",value:"Analysis"},{label:"Reference",value:"Reference"}];function h({activeCategory:e,onCategoryChange:t,counts:s}){return(0,a.jsx)("div",{className:"flex flex-wrap gap-2",role:"group","aria-label":"Filter by category",children:g.map(({label:l,value:r})=>(0,a.jsxs)(i.Button,{variant:e===r?"default":"outline",size:"sm",onClick:()=>t(r),children:[l,s&&r?(0,a.jsxs)("span",{className:"ml-1 text-xs opacity-70",children:["(",s[r],")"]}):null]},l))})}var j=e.i(38752);function y({skills:e}){let[n,c]=(0,t.useState)(""),[u,m]=(0,t.useState)(null),[x,f]=(0,t.useState)(null),g=(0,t.useMemo)(()=>(function(e){let a={Workflow:0,"Code Generation":0,Analysis:0,Reference:0};for(let t of e)a[t.category]++;return a})(e),[e]),y=(0,t.useMemo)(()=>{let a=n.toLowerCase();return e.filter(e=>{if(u&&e.category!==u)return!1;if(a){let t=e.name.toLowerCase().includes(a),s=e.description.toLowerCase().includes(a);if(!t&&!s)return!1}return!0})},[e,n,u]);return 0===e.length?(0,a.jsxs)("div",{className:"flex flex-col gap-6 p-6",children:[(0,a.jsx)(o,{title:"Skills",description:"Claude Code skills installed in this project"}),(0,a.jsx)(d.EmptyState,{icon:(0,a.jsx)(l.Puzzle,{className:"size-10"}),title:"No skills found",description:"No Claude Code skills are installed. Add skills to .claude/skills/ to get started."})]}):(0,a.jsxs)("div",{className:"flex flex-col gap-6 p-6",children:[(0,a.jsx)(o,{title:"Skills",description:"Claude Code skills installed in this project"}),(0,a.jsxs)("div",{className:"relative",children:[(0,a.jsx)(s,{className:"text-muted-foreground absolute top-1/2 left-3 size-4 -translate-y-1/2"}),(0,a.jsx)(r.Input,{placeholder:"Search skills...",value:n,onChange:e=>c(e.target.value),className:"pl-9"})]}),(0,a.jsx)(h,{activeCategory:u,onCategoryChange:m,counts:g}),y.length>0?(0,a.jsx)(p,{skills:y,onSkillSelect:f}):(0,a.jsx)(d.EmptyState,{icon:(0,a.jsx)(s,{className:"size-10"}),title:"No matching skills",description:"No skills match your current search and filter criteria.",action:(0,a.jsx)(i.Button,{variant:"outline",onClick:()=>{c(""),m(null)},children:"Clear filters"})}),(0,a.jsx)(j.SkillDetailDrawer,{skill:x,onClose:()=>f(null)})]})}e.s(["SkillsPageClient",()=>y],16919)}]);
@@ -0,0 +1 @@
1
+ (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,24270,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"warnOnce",{enumerable:!0,get:function(){return n}});let n=e=>{}},66033,e=>{"use strict";var t=e.i(79054);e.i(20314);var r=t.createContext(void 0);function n(e){let n=t.useContext(r);return e||n||"ltr"}e.s(["useDirection",()=>n])},81975,e=>{"use strict";let t=(0,e.i(3645).default)("wrench",[["path",{d:"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z",key:"1ngwbx"}]]);e.s(["Wrench",()=>t],81975)},12103,e=>{"use strict";let t=(0,e.i(3645).default)("puzzle",[["path",{d:"M15.39 4.39a1 1 0 0 0 1.68-.474 2.5 2.5 0 1 1 3.014 3.015 1 1 0 0 0-.474 1.68l1.683 1.682a2.414 2.414 0 0 1 0 3.414L19.61 15.39a1 1 0 0 1-1.68-.474 2.5 2.5 0 1 0-3.014 3.015 1 1 0 0 1 .474 1.68l-1.683 1.682a2.414 2.414 0 0 1-3.414 0L8.61 19.61a1 1 0 0 0-1.68.474 2.5 2.5 0 1 1-3.014-3.015 1 1 0 0 0 .474-1.68l-1.683-1.682a2.414 2.414 0 0 1 0-3.414L4.39 8.61a1 1 0 0 1 1.68.474 2.5 2.5 0 1 0 3.014-3.015 1 1 0 0 1-.474-1.68l1.683-1.682a2.414 2.414 0 0 1 3.414 0z",key:"w46dr5"}]]);e.s(["Puzzle",()=>t],12103)},80764,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"useMergedRef",{enumerable:!0,get:function(){return o}});let n=e.r(79054);function o(e,t){let r=(0,n.useRef)(null),o=(0,n.useRef)(null);return(0,n.useCallback)(n=>{if(null===n){let e=r.current;e&&(r.current=null,e());let t=o.current;t&&(o.current=null,t())}else e&&(r.current=u(e,n)),t&&(o.current=u(t,n))},[e,t])}function u(e,t){if("function"!=typeof e)return e.current=t,()=>{e.current=null};{let r=e(t);return"function"==typeof r?r:()=>e(null)}}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},76314,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={assign:function(){return l},searchParamsToUrlQuery:function(){return u},urlQueryToSearchParams:function(){return i}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});function u(e){let t={};for(let[r,n]of e.entries()){let e=t[r];void 0===e?t[r]=n:Array.isArray(e)?e.push(n):t[r]=[e,n]}return t}function a(e){return"string"==typeof e?e:("number"!=typeof e||isNaN(e))&&"boolean"!=typeof e?"":String(e)}function i(e){let t=new URLSearchParams;for(let[r,n]of Object.entries(e))if(Array.isArray(n))for(let e of n)t.append(r,a(e));else t.set(r,a(n));return t}function l(e,...t){for(let r of t){for(let t of r.keys())e.delete(t);for(let[t,n]of r.entries())e.append(t,n)}return e}},95889,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={formatUrl:function(){return i},formatWithValidation:function(){return c},urlObjectKeys:function(){return l}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let u=e.r(44066)._(e.r(76314)),a=/https?|ftp|gopher|file/;function i(e){let{auth:t,hostname:r}=e,n=e.protocol||"",o=e.pathname||"",i=e.hash||"",l=e.query||"",c=!1;t=t?encodeURIComponent(t).replace(/%3A/i,":")+"@":"",e.host?c=t+e.host:r&&(c=t+(~r.indexOf(":")?`[${r}]`:r),e.port&&(c+=":"+e.port)),l&&"object"==typeof l&&(l=String(u.urlQueryToSearchParams(l)));let s=e.search||l&&`?${l}`||"";return n&&!n.endsWith(":")&&(n+=":"),e.slashes||(!n||a.test(n))&&!1!==c?(c="//"+(c||""),o&&"/"!==o[0]&&(o="/"+o)):c||(c=""),i&&"#"!==i[0]&&(i="#"+i),s&&"?"!==s[0]&&(s="?"+s),o=o.replace(/[?#]/g,encodeURIComponent),s=s.replace("#","%23"),`${n}${c}${o}${s}${i}`}let l=["auth","hash","host","hostname","href","path","pathname","port","protocol","query","search","slashes"];function c(e){return i(e)}},58464,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={DecodeError:function(){return m},MiddlewareNotFoundError:function(){return _},MissingStaticPage:function(){return P},NormalizeError:function(){return b},PageNotFoundError:function(){return v},SP:function(){return y},ST:function(){return g},WEB_VITALS:function(){return u},execOnce:function(){return a},getDisplayName:function(){return f},getLocationOrigin:function(){return c},getURL:function(){return s},isAbsoluteUrl:function(){return l},isResSent:function(){return p},loadGetInitialProps:function(){return h},normalizeRepeatedSlashes:function(){return d},stringifyError:function(){return O}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let u=["CLS","FCP","FID","INP","LCP","TTFB"];function a(e){let t,r=!1;return(...n)=>(r||(r=!0,t=e(...n)),t)}let i=/^[a-zA-Z][a-zA-Z\d+\-.]*?:/,l=e=>i.test(e);function c(){let{protocol:e,hostname:t,port:r}=window.location;return`${e}//${t}${r?":"+r:""}`}function s(){let{href:e}=window.location,t=c();return e.substring(t.length)}function f(e){return"string"==typeof e?e:e.displayName||e.name||"Unknown"}function p(e){return e.finished||e.headersSent}function d(e){let t=e.split("?");return t[0].replace(/\\/g,"/").replace(/\/\/+/g,"/")+(t[1]?`?${t.slice(1).join("?")}`:"")}async function h(e,t){let r=t.res||t.ctx&&t.ctx.res;if(!e.getInitialProps)return t.ctx&&t.Component?{pageProps:await h(t.Component,t.ctx)}:{};let n=await e.getInitialProps(t);if(r&&p(r))return n;if(!n)throw Object.defineProperty(Error(`"${f(e)}.getInitialProps()" should resolve to an object. But found "${n}" instead.`),"__NEXT_ERROR_CODE",{value:"E394",enumerable:!1,configurable:!0});return n}let y="u">typeof performance,g=y&&["mark","measure","getEntriesByName"].every(e=>"function"==typeof performance[e]);class m extends Error{}class b extends Error{}class v extends Error{constructor(e){super(),this.code="ENOENT",this.name="PageNotFoundError",this.message=`Cannot find module for page: ${e}`}}class P extends Error{constructor(e,t){super(),this.message=`Failed to load static file for page: ${e} ${t}`}}class _ extends Error{constructor(){super(),this.code="ENOENT",this.message="Cannot find the middleware module"}}function O(e){return JSON.stringify({message:e.message,stack:e.stack})}},51380,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"isLocalURL",{enumerable:!0,get:function(){return u}});let n=e.r(58464),o=e.r(53626);function u(e){if(!(0,n.isAbsoluteUrl)(e))return!0;try{let t=(0,n.getLocationOrigin)(),r=new URL(e,t);return r.origin===t&&(0,o.hasBasePath)(r.pathname)}catch(e){return!1}}},38670,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"errorOnce",{enumerable:!0,get:function(){return n}});let n=e=>{}},24035,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={default:function(){return m},useLinkStatus:function(){return v}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let u=e.r(44066),a=e.r(20314),i=u._(e.r(79054)),l=e.r(95889),c=e.r(18152),s=e.r(80764),f=e.r(58464),p=e.r(99267);e.r(24270);let d=e.r(59624),h=e.r(51380),y=e.r(95555);function g(e){return"string"==typeof e?e:(0,l.formatUrl)(e)}function m(t){var r;let n,o,u,[l,m]=(0,i.useOptimistic)(d.IDLE_LINK_STATUS),v=(0,i.useRef)(null),{href:P,as:_,children:O,prefetch:E=null,passHref:j,replace:C,shallow:S,scroll:T,onClick:R,onMouseEnter:L,onTouchStart:w,legacyBehavior:x=!1,onNavigate:M,ref:N,unstable_dynamicOnHover:A,...U}=t;n=O,x&&("string"==typeof n||"number"==typeof n)&&(n=(0,a.jsx)("a",{children:n}));let k=i.default.useContext(c.AppRouterContext),$=!1!==E,I=!1!==E?null===(r=E)||"auto"===r?y.FetchStrategy.PPR:y.FetchStrategy.Full:y.FetchStrategy.PPR,{href:z,as:F}=i.default.useMemo(()=>{let e=g(P);return{href:e,as:_?g(_):e}},[P,_]);if(x){if(n?.$$typeof===Symbol.for("react.lazy"))throw Object.defineProperty(Error("`<Link legacyBehavior>` received a direct child that is either a Server Component, or JSX that was loaded with React.lazy(). This is not supported. Either remove legacyBehavior, or make the direct child a Client Component that renders the Link's `<a>` tag."),"__NEXT_ERROR_CODE",{value:"E863",enumerable:!1,configurable:!0});o=i.default.Children.only(n)}let D=x?o&&"object"==typeof o&&o.ref:N,B=i.default.useCallback(e=>(null!==k&&(v.current=(0,d.mountLinkInstance)(e,z,k,I,$,m)),()=>{v.current&&((0,d.unmountLinkForCurrentNavigation)(v.current),v.current=null),(0,d.unmountPrefetchableInstance)(e)}),[$,z,k,I,m]),K={ref:(0,s.useMergedRef)(B,D),onClick(t){x||"function"!=typeof R||R(t),x&&o.props&&"function"==typeof o.props.onClick&&o.props.onClick(t),!k||t.defaultPrevented||function(t,r,n,o,u,a,l){if("u">typeof window){let c,{nodeName:s}=t.currentTarget;if("A"===s.toUpperCase()&&((c=t.currentTarget.getAttribute("target"))&&"_self"!==c||t.metaKey||t.ctrlKey||t.shiftKey||t.altKey||t.nativeEvent&&2===t.nativeEvent.which)||t.currentTarget.hasAttribute("download"))return;if(!(0,h.isLocalURL)(r)){u&&(t.preventDefault(),location.replace(r));return}if(t.preventDefault(),l){let e=!1;if(l({preventDefault:()=>{e=!0}}),e)return}let{dispatchNavigateAction:f}=e.r(81574);i.default.startTransition(()=>{f(n||r,u?"replace":"push",a??!0,o.current)})}}(t,z,F,v,C,T,M)},onMouseEnter(e){x||"function"!=typeof L||L(e),x&&o.props&&"function"==typeof o.props.onMouseEnter&&o.props.onMouseEnter(e),k&&$&&(0,d.onNavigationIntent)(e.currentTarget,!0===A)},onTouchStart:function(e){x||"function"!=typeof w||w(e),x&&o.props&&"function"==typeof o.props.onTouchStart&&o.props.onTouchStart(e),k&&$&&(0,d.onNavigationIntent)(e.currentTarget,!0===A)}};return(0,f.isAbsoluteUrl)(F)?K.href=F:x&&!j&&("a"!==o.type||"href"in o.props)||(K.href=(0,p.addBasePath)(F)),u=x?i.default.cloneElement(o,K):(0,a.jsx)("a",{...U,...K,children:n}),(0,a.jsx)(b.Provider,{value:l,children:u})}e.r(38670);let b=(0,i.createContext)(d.IDLE_LINK_STATUS),v=()=>(0,i.useContext)(b);("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)}]);