@shepai/cli 1.145.0-pr452.ae7b9df → 1.146.0-pr437.aa23c1e

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 (229) hide show
  1. package/apis/json-schema/FeatureFlags.yaml +5 -0
  2. package/dist/packages/core/src/application/ports/output/services/coasts-service.interface.d.ts +132 -0
  3. package/dist/packages/core/src/application/ports/output/services/coasts-service.interface.d.ts.map +1 -0
  4. package/dist/packages/core/src/application/ports/output/services/coasts-service.interface.js +12 -0
  5. package/dist/packages/core/src/application/ports/output/services/index.d.ts +1 -0
  6. package/dist/packages/core/src/application/ports/output/services/index.d.ts.map +1 -1
  7. package/dist/packages/core/src/domain/factories/settings-defaults.factory.d.ts.map +1 -1
  8. package/dist/packages/core/src/domain/factories/settings-defaults.factory.js +1 -0
  9. package/dist/packages/core/src/domain/generated/output.d.ts +4 -0
  10. package/dist/packages/core/src/domain/generated/output.d.ts.map +1 -1
  11. package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
  12. package/dist/packages/core/src/infrastructure/di/container.js +10 -0
  13. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.d.ts +1 -0
  14. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.d.ts.map +1 -1
  15. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.js +2 -0
  16. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/044-add-feature-flag-coasts-dev-server.d.ts +11 -0
  17. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/044-add-feature-flag-coasts-dev-server.d.ts.map +1 -0
  18. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/044-add-feature-flag-coasts-dev-server.js +17 -0
  19. package/dist/packages/core/src/infrastructure/repositories/sqlite-settings.repository.d.ts.map +1 -1
  20. package/dist/packages/core/src/infrastructure/repositories/sqlite-settings.repository.js +3 -2
  21. package/dist/packages/core/src/infrastructure/services/coasts.service.d.ts +42 -0
  22. package/dist/packages/core/src/infrastructure/services/coasts.service.d.ts.map +1 -0
  23. package/dist/packages/core/src/infrastructure/services/coasts.service.js +185 -0
  24. package/dist/src/presentation/cli/commands/coasts/index.d.ts +3 -0
  25. package/dist/src/presentation/cli/commands/coasts/index.d.ts.map +1 -0
  26. package/dist/src/presentation/cli/commands/coasts/index.js +7 -0
  27. package/dist/src/presentation/cli/commands/coasts/init.command.d.ts +3 -0
  28. package/dist/src/presentation/cli/commands/coasts/init.command.d.ts.map +1 -0
  29. package/dist/src/presentation/cli/commands/coasts/init.command.js +40 -0
  30. package/dist/src/presentation/cli/index.js +2 -0
  31. package/dist/src/presentation/web/app/actions/check-coastfile.d.ts +5 -0
  32. package/dist/src/presentation/web/app/actions/check-coastfile.d.ts.map +1 -0
  33. package/dist/src/presentation/web/app/actions/check-coastfile.js +16 -0
  34. package/dist/src/presentation/web/app/actions/generate-coastfile.d.ts +7 -0
  35. package/dist/src/presentation/web/app/actions/generate-coastfile.d.ts.map +1 -0
  36. package/dist/src/presentation/web/app/actions/generate-coastfile.js +22 -0
  37. package/dist/src/presentation/web/coasts-dev-server.d.ts +34 -0
  38. package/dist/src/presentation/web/coasts-dev-server.d.ts.map +1 -0
  39. package/dist/src/presentation/web/coasts-dev-server.js +69 -0
  40. package/dist/src/presentation/web/components/common/repository-node/repository-drawer.stories.d.ts.map +1 -1
  41. package/dist/src/presentation/web/components/common/repository-node/repository-drawer.stories.js +1 -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 +9 -2
  44. package/dist/src/presentation/web/components/common/repository-node/use-coasts-actions.d.ts +12 -0
  45. package/dist/src/presentation/web/components/common/repository-node/use-coasts-actions.d.ts.map +1 -0
  46. package/dist/src/presentation/web/components/common/repository-node/use-coasts-actions.js +76 -0
  47. package/dist/src/presentation/web/components/features/settings/feature-flags-settings-section.d.ts.map +1 -1
  48. package/dist/src/presentation/web/components/features/settings/feature-flags-settings-section.js +3 -0
  49. package/dist/src/presentation/web/components/features/settings/feature-flags-settings-section.stories.d.ts.map +1 -1
  50. package/dist/src/presentation/web/components/features/settings/feature-flags-settings-section.stories.js +3 -0
  51. package/dist/src/presentation/web/components/features/settings/settings-page-client.d.ts.map +1 -1
  52. package/dist/src/presentation/web/components/features/settings/settings-page-client.js +5 -0
  53. package/dist/src/presentation/web/components/features/settings/settings-page-client.stories.d.ts.map +1 -1
  54. package/dist/src/presentation/web/components/features/settings/settings-page-client.stories.js +1 -0
  55. package/dist/src/presentation/web/components/layouts/app-sidebar/app-sidebar.stories.d.ts.map +1 -1
  56. package/dist/src/presentation/web/components/layouts/app-sidebar/app-sidebar.stories.js +1 -0
  57. package/dist/src/presentation/web/dev-server.js +62 -1
  58. package/dist/src/presentation/web/hooks/feature-flags-context.d.ts.map +1 -1
  59. package/dist/src/presentation/web/hooks/feature-flags-context.js +1 -0
  60. package/dist/src/presentation/web/lib/feature-flags.d.ts +2 -0
  61. package/dist/src/presentation/web/lib/feature-flags.d.ts.map +1 -1
  62. package/dist/src/presentation/web/lib/feature-flags.js +5 -0
  63. package/dist/tsconfig.build.tsbuildinfo +1 -1
  64. package/package.json +2 -1
  65. package/web/.next/BUILD_ID +1 -1
  66. package/web/.next/build-manifest.json +2 -2
  67. package/web/.next/fallback-build-manifest.json +2 -2
  68. package/web/.next/prerender-manifest.json +3 -3
  69. package/web/.next/required-server-files.js +2 -2
  70. package/web/.next/required-server-files.json +2 -2
  71. package/web/.next/server/app/(dashboard)/@drawer/adopt/page/server-reference-manifest.json +86 -56
  72. package/web/.next/server/app/(dashboard)/@drawer/adopt/page.js +1 -1
  73. package/web/.next/server/app/(dashboard)/@drawer/adopt/page.js.nft.json +1 -1
  74. package/web/.next/server/app/(dashboard)/@drawer/adopt/page_client-reference-manifest.js +1 -1
  75. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +86 -56
  76. package/web/.next/server/app/(dashboard)/@drawer/create/page.js +1 -1
  77. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  78. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  79. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +102 -72
  80. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js +1 -1
  81. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  82. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  83. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +102 -72
  84. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js +1 -1
  85. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  86. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  87. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +82 -52
  88. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js +1 -1
  89. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  90. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  91. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +86 -56
  92. package/web/.next/server/app/(dashboard)/create/page.js +1 -1
  93. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  94. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  95. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +102 -72
  96. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js +1 -1
  97. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  98. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  99. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +102 -72
  100. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js +1 -1
  101. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  102. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  103. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +82 -52
  104. package/web/.next/server/app/(dashboard)/page.js +1 -1
  105. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  106. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  107. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +82 -52
  108. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js +1 -1
  109. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  110. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  111. package/web/.next/server/app/_global-error.html +2 -2
  112. package/web/.next/server/app/_global-error.rsc +1 -1
  113. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  114. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  115. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  116. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  117. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  118. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +3 -3
  119. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  120. package/web/.next/server/app/api/attachments/preview/route.js.nft.json +1 -1
  121. package/web/.next/server/app/api/evidence/route.js.nft.json +1 -1
  122. package/web/.next/server/app/api/graph-data/route.js.nft.json +1 -1
  123. package/web/.next/server/app/api/sessions/route.js.nft.json +1 -1
  124. package/web/.next/server/app/settings/page/server-reference-manifest.json +8 -8
  125. package/web/.next/server/app/settings/page.js.nft.json +1 -1
  126. package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  127. package/web/.next/server/app/skills/page/server-reference-manifest.json +8 -8
  128. package/web/.next/server/app/skills/page.js.nft.json +1 -1
  129. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  130. package/web/.next/server/app/tools/page/server-reference-manifest.json +8 -8
  131. package/web/.next/server/app/tools/page.js.nft.json +1 -1
  132. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  133. package/web/.next/server/app/version/page/server-reference-manifest.json +3 -3
  134. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  135. package/web/.next/server/chunks/403f9_next_567de315._.js +2 -2
  136. package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
  137. package/web/.next/server/chunks/[root-of-the-server]__c6e32a23._.js.map +1 -1
  138. package/web/.next/server/chunks/[root-of-the-server]__cd67a84c._.js.map +1 -1
  139. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  140. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  141. package/web/.next/server/chunks/ssr/[root-of-the-server]__0b150ddf._.js.map +1 -1
  142. package/web/.next/server/chunks/ssr/[root-of-the-server]__2138fa7e._.js +2 -2
  143. package/web/.next/server/chunks/ssr/[root-of-the-server]__2138fa7e._.js.map +1 -1
  144. package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js +1 -1
  145. package/web/.next/server/chunks/ssr/[root-of-the-server]__3ef34e4c._.js +1 -1
  146. package/web/.next/server/chunks/ssr/[root-of-the-server]__43f51aa6._.js +1 -1
  147. package/web/.next/server/chunks/ssr/[root-of-the-server]__43f51aa6._.js.map +1 -1
  148. package/web/.next/server/chunks/ssr/{[root-of-the-server]__29580090._.js → [root-of-the-server]__581769f7._.js} +2 -2
  149. package/web/.next/server/chunks/ssr/{[root-of-the-server]__29580090._.js.map → [root-of-the-server]__581769f7._.js.map} +1 -1
  150. package/web/.next/server/chunks/ssr/{[root-of-the-server]__dac5dbf1._.js → [root-of-the-server]__6df523d1._.js} +2 -2
  151. package/web/.next/server/chunks/ssr/{[root-of-the-server]__dac5dbf1._.js.map → [root-of-the-server]__6df523d1._.js.map} +1 -1
  152. package/web/.next/server/chunks/ssr/{[root-of-the-server]__fae8b355._.js → [root-of-the-server]__8004c676._.js} +2 -2
  153. package/web/.next/server/chunks/ssr/{[root-of-the-server]__c094882b._.js.map → [root-of-the-server]__8004c676._.js.map} +1 -1
  154. package/web/.next/server/chunks/ssr/[root-of-the-server]__815546bd._.js +1 -1
  155. package/web/.next/server/chunks/ssr/[root-of-the-server]__815546bd._.js.map +1 -1
  156. package/web/.next/server/chunks/ssr/{[root-of-the-server]__c094882b._.js → [root-of-the-server]__815f85e7._.js} +2 -2
  157. package/web/.next/server/chunks/ssr/{[root-of-the-server]__fae8b355._.js.map → [root-of-the-server]__815f85e7._.js.map} +1 -1
  158. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +2 -2
  159. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js.map +1 -1
  160. package/web/.next/server/chunks/ssr/[root-of-the-server]__d48c5b11._.js +1 -1
  161. package/web/.next/server/chunks/ssr/[root-of-the-server]__d48c5b11._.js.map +1 -1
  162. package/web/.next/server/chunks/ssr/_0020fddd._.js +1 -1
  163. package/web/.next/server/chunks/ssr/_0020fddd._.js.map +1 -1
  164. package/web/.next/server/chunks/ssr/{_0c5f56e3._.js → _45117016._.js} +3 -3
  165. package/web/.next/server/chunks/ssr/{_0c5f56e3._.js.map → _45117016._.js.map} +1 -1
  166. package/web/.next/server/chunks/ssr/_4b432739._.js +1 -1
  167. package/web/.next/server/chunks/ssr/_4b432739._.js.map +1 -1
  168. package/web/.next/server/chunks/ssr/_6256a985._.js +1 -1
  169. package/web/.next/server/chunks/ssr/_6256a985._.js.map +1 -1
  170. package/web/.next/server/chunks/ssr/{_c480d290._.js → _7b12d338._.js} +2 -2
  171. package/web/.next/server/chunks/ssr/{_c480d290._.js.map → _7b12d338._.js.map} +1 -1
  172. package/web/.next/server/chunks/ssr/_7dca1882._.js +1 -1
  173. package/web/.next/server/chunks/ssr/_7dca1882._.js.map +1 -1
  174. package/web/.next/server/chunks/ssr/_8fcc39d4._.js +1 -1
  175. package/web/.next/server/chunks/ssr/_8fcc39d4._.js.map +1 -1
  176. package/web/.next/server/chunks/ssr/{_b71645b4._.js → _9133ca98._.js} +2 -2
  177. package/web/.next/server/chunks/ssr/{_b71645b4._.js.map → _9133ca98._.js.map} +1 -1
  178. package/web/.next/server/chunks/ssr/{_1b719e7f._.js → _913a6589._.js} +2 -2
  179. package/web/.next/server/chunks/ssr/{_1b719e7f._.js.map → _913a6589._.js.map} +1 -1
  180. package/web/.next/server/chunks/ssr/_a93b44aa._.js +3 -0
  181. package/web/.next/server/chunks/ssr/{_5b89327c._.js.map → _a93b44aa._.js.map} +1 -1
  182. package/web/.next/server/chunks/ssr/{_64bdfc6f._.js → _c7d0d381._.js} +3 -3
  183. package/web/.next/server/chunks/ssr/{_64bdfc6f._.js.map → _c7d0d381._.js.map} +1 -1
  184. package/web/.next/server/chunks/ssr/_d4b20e29._.js.map +1 -1
  185. package/web/.next/server/chunks/ssr/_d8575088._.js +1 -1
  186. package/web/.next/server/chunks/ssr/_d8575088._.js.map +1 -1
  187. package/web/.next/server/chunks/ssr/{_55d763e2._.js → _e816b997._.js} +2 -2
  188. package/web/.next/server/chunks/ssr/{_37e8548b._.js.map → _e816b997._.js.map} +1 -1
  189. package/web/.next/server/chunks/ssr/_f39a1adb._.js +1 -1
  190. package/web/.next/server/chunks/ssr/_f39a1adb._.js.map +1 -1
  191. package/web/.next/server/chunks/ssr/{_37e8548b._.js → _f483d14b._.js} +2 -2
  192. package/web/.next/server/chunks/ssr/{_55d763e2._.js.map → _f483d14b._.js.map} +1 -1
  193. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
  194. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
  195. package/web/.next/server/chunks/ssr/src_presentation_web_0c3330d7._.js +3 -0
  196. package/web/.next/server/chunks/ssr/{src_presentation_web_36d135cd._.js.map → src_presentation_web_0c3330d7._.js.map} +1 -1
  197. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1b176e3c.js +1 -1
  198. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1b176e3c.js.map +1 -1
  199. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_bd9f0dda.js +1 -1
  200. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_bd9f0dda.js.map +1 -1
  201. package/web/.next/server/chunks/ssr/src_presentation_web_app_actions_open-ide_ts_baaca5d5._.js +1 -1
  202. package/web/.next/server/chunks/ssr/src_presentation_web_app_actions_open-ide_ts_baaca5d5._.js.map +1 -1
  203. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +1 -1
  204. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js.map +1 -1
  205. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  206. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  207. package/web/.next/server/pages/500.html +2 -2
  208. package/web/.next/server/server-reference-manifest.js +1 -1
  209. package/web/.next/server/server-reference-manifest.json +506 -350
  210. package/web/.next/static/chunks/{0b18c50740356276.css → 080d853d319c5cc5.css} +1 -1
  211. package/web/.next/static/chunks/{66dbc5a3e4f9a938.js → 179c3052fd19c46d.js} +1 -1
  212. package/web/.next/static/chunks/{f0d47ebee8ca8bc3.js → 1f4814c4adb31418.js} +1 -1
  213. package/web/.next/static/chunks/{62b396454129b531.js → 47d12705199052e7.js} +1 -1
  214. package/web/.next/static/chunks/{412d6a39406dcc01.js → 524add4103e8a3b9.js} +1 -1
  215. package/web/.next/static/chunks/{e7744ffb13a4a677.js → 6b7a1e5e9f1b014a.js} +1 -1
  216. package/web/.next/static/chunks/{08baac5434d9528e.js → 7d5e500fab64cfb5.js} +7 -7
  217. package/web/.next/static/chunks/816b98cd7e8330b5.js +1 -0
  218. package/web/.next/static/chunks/{b190938cb5fd9b35.js → 8e26be828072d7f6.js} +1 -1
  219. package/web/.next/static/chunks/{2f69a2c8803b4d03.js → 9d6689f6cc4f825f.js} +1 -1
  220. package/web/.next/static/chunks/{af3b565e34bea1e8.js → a511514839eda467.js} +1 -1
  221. package/web/.next/static/chunks/{9f1367bf0f603996.js → d540d45e05b43599.js} +1 -1
  222. package/web/.next/static/chunks/{9940f68284ee180e.js → ee3fb116e420b158.js} +1 -1
  223. package/web/.next/static/chunks/{4887b859bc457552.js → f5a7f4c2313fad01.js} +2 -2
  224. package/web/.next/server/chunks/ssr/_5b89327c._.js +0 -3
  225. package/web/.next/server/chunks/ssr/src_presentation_web_36d135cd._.js +0 -3
  226. package/web/.next/static/chunks/4f0adb1f7fe668dc.js +0 -1
  227. /package/web/.next/static/{myvK7Q1DabrQLkyfNQtH1 → MsLpLuZsb_IZtZfJuzG81}/_buildManifest.js +0 -0
  228. /package/web/.next/static/{myvK7Q1DabrQLkyfNQtH1 → MsLpLuZsb_IZtZfJuzG81}/_clientMiddlewareManifest.json +0 -0
  229. /package/web/.next/static/{myvK7Q1DabrQLkyfNQtH1 → MsLpLuZsb_IZtZfJuzG81}/_ssgManifest.js +0 -0
@@ -0,0 +1,185 @@
1
+ /**
2
+ * Coasts Service Implementation
3
+ *
4
+ * Infrastructure adapter wrapping the coast CLI binary for containerized
5
+ * runtime isolation. Uses constructor-injected ExecFunction for subprocess
6
+ * invocation and IStructuredAgentCaller for AI-powered Coastfile generation.
7
+ *
8
+ * Following Clean Architecture:
9
+ * - Implements the ICoastsService application port
10
+ * - Lives in the infrastructure layer
11
+ * - No direct child_process imports (injected via ExecFunction)
12
+ */
13
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
14
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
15
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
16
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
17
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
18
+ };
19
+ var __metadata = (this && this.__metadata) || function (k, v) {
20
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
21
+ };
22
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
23
+ return function (target, key) { decorator(target, key, paramIndex); }
24
+ };
25
+ import { existsSync, writeFileSync } from 'node:fs';
26
+ import path from 'node:path';
27
+ import { injectable, inject } from 'tsyringe';
28
+ import { IS_WINDOWS } from '../platform.js';
29
+ /** Timeout for coast build (may need to pull Docker images). */
30
+ const BUILD_TIMEOUT_MS = 30_000;
31
+ /** Timeout for all other coast CLI commands. */
32
+ const DEFAULT_TIMEOUT_MS = 10_000;
33
+ /** JSON schema for Coastfile generation via structured agent caller. */
34
+ const COASTFILE_SCHEMA = {
35
+ type: 'object',
36
+ properties: {
37
+ content: {
38
+ type: 'string',
39
+ description: 'The complete Coastfile content in TOML format',
40
+ },
41
+ warnings: {
42
+ type: 'array',
43
+ items: { type: 'string' },
44
+ description: 'Any warnings or notes about the generated Coastfile',
45
+ },
46
+ },
47
+ required: ['content'],
48
+ additionalProperties: false,
49
+ };
50
+ let CoastsService = class CoastsService {
51
+ execFile;
52
+ structuredCaller;
53
+ cachedInstallationPrompt = null;
54
+ isWindows;
55
+ constructor(execFile, structuredCaller, isWindows) {
56
+ this.execFile = execFile;
57
+ this.structuredCaller = structuredCaller;
58
+ this.isWindows = isWindows ?? IS_WINDOWS;
59
+ }
60
+ async checkPrerequisites(workDir) {
61
+ if (this.isWindows) {
62
+ return {
63
+ coastBinary: false,
64
+ docker: false,
65
+ coastdRunning: false,
66
+ allMet: false,
67
+ missingMessages: [
68
+ 'Coasts dev server is not supported on Windows. See https://coasts.dev/docs for platform support.',
69
+ ],
70
+ };
71
+ }
72
+ const [coastResult, dockerResult, coastdResult] = await Promise.allSettled([
73
+ this.checkCoastBinary(),
74
+ this.checkDocker(),
75
+ this.checkCoastdRunning(workDir),
76
+ ]);
77
+ const coastBinary = coastResult.status === 'fulfilled';
78
+ const docker = dockerResult.status === 'fulfilled';
79
+ const coastdRunning = coastdResult.status === 'fulfilled';
80
+ const missingMessages = [];
81
+ if (!coastBinary) {
82
+ missingMessages.push('coast binary not found on PATH. Install it with: curl -fsSL https://coasts.dev/install | sh. See https://coasts.dev/docs');
83
+ }
84
+ if (!docker) {
85
+ missingMessages.push('Docker daemon is not reachable. Start Docker Desktop or run: sudo systemctl start docker');
86
+ }
87
+ if (!coastdRunning) {
88
+ missingMessages.push('coastd daemon is not running. Start it with: coastd &. See https://coasts.dev/docs/daemon');
89
+ }
90
+ return {
91
+ coastBinary,
92
+ docker,
93
+ coastdRunning,
94
+ allMet: coastBinary && docker && coastdRunning,
95
+ missingMessages,
96
+ };
97
+ }
98
+ async build(workDir) {
99
+ await this.execCoast(['build'], workDir, BUILD_TIMEOUT_MS);
100
+ }
101
+ async run(workDir) {
102
+ const { stdout } = await this.execCoast(['run'], workDir);
103
+ return this.parseCoastInstance(stdout);
104
+ }
105
+ async stop(workDir) {
106
+ try {
107
+ await this.execCoast(['stop'], workDir);
108
+ }
109
+ catch {
110
+ // No-op if no instance is running
111
+ }
112
+ }
113
+ async lookup(workDir) {
114
+ try {
115
+ const { stdout } = await this.execCoast(['lookup'], workDir);
116
+ return this.parseCoastInstance(stdout);
117
+ }
118
+ catch {
119
+ return null;
120
+ }
121
+ }
122
+ async isRunning(workDir) {
123
+ const instance = await this.lookup(workDir);
124
+ return instance !== null;
125
+ }
126
+ async checkout(workDir) {
127
+ await this.execCoast(['checkout'], workDir);
128
+ }
129
+ async getInstallationPrompt() {
130
+ if (this.cachedInstallationPrompt !== null) {
131
+ return this.cachedInstallationPrompt;
132
+ }
133
+ const { stdout } = await this.execFile('coast', ['installation-prompt'], {
134
+ timeout: DEFAULT_TIMEOUT_MS,
135
+ });
136
+ this.cachedInstallationPrompt = stdout;
137
+ return stdout;
138
+ }
139
+ async generateCoastfile(workDir) {
140
+ const installationPrompt = await this.getInstallationPrompt();
141
+ const prompt = `${installationPrompt}\n\nAnalyze the project at the working directory and generate a Coastfile.\nReturn the complete Coastfile content as valid TOML in the "content" field.`;
142
+ const result = await this.structuredCaller.call(prompt, COASTFILE_SCHEMA, {
143
+ allowedTools: [],
144
+ silent: true,
145
+ maxTurns: 10,
146
+ });
147
+ const coastfilePath = path.join(workDir, 'Coastfile');
148
+ writeFileSync(coastfilePath, result.content, 'utf-8');
149
+ return coastfilePath;
150
+ }
151
+ async hasCoastfile(workDir) {
152
+ return existsSync(path.join(workDir, 'Coastfile'));
153
+ }
154
+ // --- Private helpers ---
155
+ async checkCoastBinary() {
156
+ await this.execFile('coast', ['--version'], { timeout: 500 });
157
+ }
158
+ async checkDocker() {
159
+ await this.execFile('docker', ['info'], { timeout: 500 });
160
+ }
161
+ async checkCoastdRunning(workDir) {
162
+ await this.execFile('coast', ['ls'], { cwd: workDir, timeout: 500 });
163
+ }
164
+ async execCoast(args, workDir, timeout = DEFAULT_TIMEOUT_MS) {
165
+ return this.execFile('coast', args, { cwd: workDir, timeout });
166
+ }
167
+ /**
168
+ * Parse coast CLI output to extract port and URL from stdout.
169
+ * Looks for patterns like "port 3000" and "http://localhost:3000".
170
+ */
171
+ parseCoastInstance(stdout) {
172
+ const portMatch = stdout.match(/port\s+(\d+)/i);
173
+ const urlMatch = stdout.match(/(https?:\/\/[^\s]+)/i);
174
+ const port = portMatch ? parseInt(portMatch[1], 10) : 3000;
175
+ const url = urlMatch ? urlMatch[1] : `http://localhost:${port}`;
176
+ return { port, url };
177
+ }
178
+ };
179
+ CoastsService = __decorate([
180
+ injectable(),
181
+ __param(0, inject('ExecFunction')),
182
+ __param(1, inject('IStructuredAgentCaller')),
183
+ __metadata("design:paramtypes", [Function, Object, Boolean])
184
+ ], CoastsService);
185
+ export { CoastsService };
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function createCoastsCommand(): Command;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/coasts/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,wBAAgB,mBAAmB,IAAI,OAAO,CAI7C"}
@@ -0,0 +1,7 @@
1
+ import { Command } from 'commander';
2
+ import { createInitCommand } from './init.command.js';
3
+ export function createCoastsCommand() {
4
+ return new Command('coasts')
5
+ .description('Manage Coasts containerized runtime')
6
+ .addCommand(createInitCommand());
7
+ }
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function createInitCommand(): Command;
3
+ //# sourceMappingURL=init.command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.command.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/coasts/init.command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,wBAAgB,iBAAiB,IAAI,OAAO,CA0C3C"}
@@ -0,0 +1,40 @@
1
+ import { Command } from 'commander';
2
+ import { container } from '../../../../../packages/core/src/infrastructure/di/container.js';
3
+ import { messages, spinner } from '../../ui/index.js';
4
+ export function createInitCommand() {
5
+ return new Command('init')
6
+ .description('Generate a Coastfile for the current repository')
7
+ .option('-f, --force', 'Overwrite existing Coastfile without prompting')
8
+ .action(async (options) => {
9
+ const workDir = process.cwd();
10
+ try {
11
+ const coastsService = container.resolve('ICoastsService');
12
+ // Check if Coastfile already exists
13
+ const exists = await coastsService.hasCoastfile(workDir);
14
+ if (exists && !options.force) {
15
+ messages.warning('Coastfile already exists. Use --force to regenerate.');
16
+ return;
17
+ }
18
+ // Check prerequisites
19
+ const prereqs = await coastsService.checkPrerequisites(workDir);
20
+ if (!prereqs.allMet) {
21
+ for (const msg of prereqs.missingMessages) {
22
+ messages.error(msg);
23
+ }
24
+ process.exitCode = 1;
25
+ return;
26
+ }
27
+ // Generate Coastfile
28
+ const coastfilePath = await spinner('Generating Coastfile via AI agent...', () => coastsService.generateCoastfile(workDir));
29
+ messages.success(`Coastfile generated at ${coastfilePath}`);
30
+ // Build container
31
+ await spinner('Building coast container...', () => coastsService.build(workDir));
32
+ messages.success('Coast container built successfully.');
33
+ }
34
+ catch (error) {
35
+ const err = error instanceof Error ? error : new Error(String(error));
36
+ messages.error('Failed to initialize Coasts', err);
37
+ process.exitCode = 1;
38
+ }
39
+ });
40
+ }
@@ -42,6 +42,7 @@ import { createIdeOpenCommand } from './commands/ide-open.command.js';
42
42
  import { createInstallCommand } from './commands/install.command.js';
43
43
  import { createUpgradeCommand } from './commands/upgrade.command.js';
44
44
  import { createToolsCommand } from './commands/tools.command.js';
45
+ import { createCoastsCommand } from './commands/coasts/index.js';
45
46
  import { messages } from './ui/index.js';
46
47
  // Daemon lifecycle commands
47
48
  import { createStartCommand } from './commands/start.command.js';
@@ -110,6 +111,7 @@ async function bootstrap() {
110
111
  program.addCommand(createInstallCommand());
111
112
  program.addCommand(createToolsCommand());
112
113
  program.addCommand(createUpgradeCommand());
114
+ program.addCommand(createCoastsCommand());
113
115
  // Daemon lifecycle commands (task-9)
114
116
  program.addCommand(createStartCommand());
115
117
  program.addCommand(createStopCommand());
@@ -0,0 +1,5 @@
1
+ export interface CheckCoastfileResult {
2
+ exists: boolean;
3
+ }
4
+ export declare function checkCoastfileAction(repositoryPath: string): Promise<CheckCoastfileResult>;
5
+ //# sourceMappingURL=check-coastfile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-coastfile.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/check-coastfile.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,wBAAsB,oBAAoB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAYhG"}
@@ -0,0 +1,16 @@
1
+ 'use server';
2
+ import path from 'node:path';
3
+ import { resolve } from '../../lib/server-container.js';
4
+ export async function checkCoastfileAction(repositoryPath) {
5
+ if (!repositoryPath || !path.isAbsolute(repositoryPath)) {
6
+ return { exists: false };
7
+ }
8
+ try {
9
+ const coastsService = resolve('ICoastsService');
10
+ const exists = await coastsService.hasCoastfile(repositoryPath);
11
+ return { exists };
12
+ }
13
+ catch {
14
+ return { exists: false };
15
+ }
16
+ }
@@ -0,0 +1,7 @@
1
+ export interface GenerateCoastfileResult {
2
+ success: boolean;
3
+ coastfilePath?: string;
4
+ error?: string;
5
+ }
6
+ export declare function generateCoastfileAction(repositoryPath: string): Promise<GenerateCoastfileResult>;
7
+ //# sourceMappingURL=generate-coastfile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-coastfile.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/generate-coastfile.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,uBAAuB,CAC3C,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,uBAAuB,CAAC,CAkBlC"}
@@ -0,0 +1,22 @@
1
+ 'use server';
2
+ import path from 'node:path';
3
+ import { existsSync } from 'node:fs';
4
+ import { resolve } from '../../lib/server-container.js';
5
+ export async function generateCoastfileAction(repositoryPath) {
6
+ if (!repositoryPath || !path.isAbsolute(repositoryPath)) {
7
+ return { success: false, error: 'repositoryPath must be an absolute path' };
8
+ }
9
+ if (!existsSync(repositoryPath)) {
10
+ return { success: false, error: `Directory does not exist: ${repositoryPath}` };
11
+ }
12
+ try {
13
+ const coastsService = resolve('ICoastsService');
14
+ const coastfilePath = await coastsService.generateCoastfile(repositoryPath);
15
+ await coastsService.build(repositoryPath);
16
+ return { success: true, coastfilePath };
17
+ }
18
+ catch (error) {
19
+ const message = error instanceof Error ? error.message : 'Failed to generate Coastfile';
20
+ return { success: false, error: message };
21
+ }
22
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Coasts Dev Server Startup & Shutdown
3
+ *
4
+ * Extracted from dev-server.ts for testability. Provides the Coasts startup
5
+ * sequence (prerequisite checks, Coastfile existence check, build, run) and
6
+ * graceful shutdown logic.
7
+ *
8
+ * All log messages use [dev-server:coasts] prefix per NFR-10.
9
+ */
10
+ import type { ICoastsService, CoastInstance } from '../../../packages/core/src/application/ports/output/services/coasts-service.interface.js';
11
+ /**
12
+ * Start the dev server in Coasts mode.
13
+ *
14
+ * Sequence:
15
+ * 1. Check prerequisites (coast binary, Docker, coastd daemon)
16
+ * 2. Check for Coastfile — fail if missing
17
+ * 3. Build the coast container image
18
+ * 4. Run the coast instance
19
+ *
20
+ * @param coastsService - Resolved ICoastsService from the DI container
21
+ * @param workDir - Working directory (repo/worktree root)
22
+ * @returns The running CoastInstance with port and URL
23
+ * @throws Error if prerequisites are not met or any step fails
24
+ */
25
+ export declare function startCoastsDevServer(coastsService: ICoastsService, workDir: string): Promise<CoastInstance>;
26
+ /**
27
+ * Gracefully shut down the Coasts instance.
28
+ * Catches and logs errors to prevent shutdown failures.
29
+ *
30
+ * @param coastsService - The ICoastsService instance, or null if not in Coasts mode
31
+ * @param workDir - Working directory for the coast instance
32
+ */
33
+ export declare function shutdownCoasts(coastsService: ICoastsService | null, workDir: string): Promise<void>;
34
+ //# sourceMappingURL=coasts-dev-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coasts-dev-server.d.ts","sourceRoot":"","sources":["../../../../src/presentation/web/coasts-dev-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACd,MAAM,yEAAyE,CAAC;AAEjF;;;;;;;;;;;;;GAaG;AACH,wBAAsB,oBAAoB,CACxC,aAAa,EAAE,cAAc,EAC7B,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,aAAa,CAAC,CAiCxB;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,aAAa,EAAE,cAAc,GAAG,IAAI,EACpC,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAUf"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Coasts Dev Server Startup & Shutdown
3
+ *
4
+ * Extracted from dev-server.ts for testability. Provides the Coasts startup
5
+ * sequence (prerequisite checks, Coastfile existence check, build, run) and
6
+ * graceful shutdown logic.
7
+ *
8
+ * All log messages use [dev-server:coasts] prefix per NFR-10.
9
+ */
10
+ /**
11
+ * Start the dev server in Coasts mode.
12
+ *
13
+ * Sequence:
14
+ * 1. Check prerequisites (coast binary, Docker, coastd daemon)
15
+ * 2. Check for Coastfile — fail if missing
16
+ * 3. Build the coast container image
17
+ * 4. Run the coast instance
18
+ *
19
+ * @param coastsService - Resolved ICoastsService from the DI container
20
+ * @param workDir - Working directory (repo/worktree root)
21
+ * @returns The running CoastInstance with port and URL
22
+ * @throws Error if prerequisites are not met or any step fails
23
+ */
24
+ export async function startCoastsDevServer(coastsService, workDir) {
25
+ // Step 1: Check prerequisites
26
+ console.log('[dev-server:coasts] Checking prerequisites...');
27
+ const prereqs = await coastsService.checkPrerequisites(workDir);
28
+ if (!prereqs.allMet) {
29
+ const messages = prereqs.missingMessages.map((m) => ` - ${m}`).join('\n');
30
+ throw new Error(`[dev-server:coasts] Prerequisites not met:\n${messages}`);
31
+ }
32
+ console.log('[dev-server:coasts] All prerequisites met.');
33
+ // Step 2: Check for Coastfile — fail if missing (generate on-demand via CLI or web UI)
34
+ const hasCoastfile = await coastsService.hasCoastfile(workDir);
35
+ if (!hasCoastfile) {
36
+ throw new Error(`[dev-server:coasts] No Coastfile found in ${workDir} (expected: Coastfile).\n` +
37
+ 'Generate one with:\n' +
38
+ ' - CLI: shep coasts init\n' +
39
+ ' - Web UI: Use the "Generate Coastfile" button on the repository node');
40
+ }
41
+ // Step 3: Build the coast container image
42
+ console.log('[dev-server:coasts] Building coast container...');
43
+ await coastsService.build(workDir);
44
+ console.log('[dev-server:coasts] Build complete.');
45
+ // Step 4: Run the coast instance
46
+ console.log('[dev-server:coasts] Starting coast instance...');
47
+ const instance = await coastsService.run(workDir);
48
+ console.log(`[dev-server:coasts] Ready at ${instance.url}`);
49
+ return instance;
50
+ }
51
+ /**
52
+ * Gracefully shut down the Coasts instance.
53
+ * Catches and logs errors to prevent shutdown failures.
54
+ *
55
+ * @param coastsService - The ICoastsService instance, or null if not in Coasts mode
56
+ * @param workDir - Working directory for the coast instance
57
+ */
58
+ export async function shutdownCoasts(coastsService, workDir) {
59
+ if (!coastsService)
60
+ return;
61
+ try {
62
+ console.log('[dev-server:coasts] Stopping coast instance...');
63
+ await coastsService.stop(workDir);
64
+ console.log('[dev-server:coasts] Coast instance stopped.');
65
+ }
66
+ catch (error) {
67
+ console.warn('[dev-server:coasts] Failed to stop coast instance:', error);
68
+ }
69
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"repository-drawer.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/repository-node/repository-drawer.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAGvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAGvD,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,gBAAgB,CAOvC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAqB/C,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAUtB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAIzB,CAAC;AAuBF,2EAA2E;AAC3E,eAAO,MAAM,QAAQ,EAAE,KAEtB,CAAC;AAkCF,0FAA0F;AAC1F,eAAO,MAAM,iBAAiB,EAAE,KAE/B,CAAC"}
1
+ {"version":3,"file":"repository-drawer.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/repository-node/repository-drawer.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAGvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAGvD,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,gBAAgB,CAOvC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAqB/C,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAUtB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAIzB,CAAC;AAuBF,2EAA2E;AAC3E,eAAO,MAAM,QAAQ,EAAE,KAEtB,CAAC;AAmCF,0FAA0F;AAC1F,eAAO,MAAM,iBAAiB,EAAE,KAE/B,CAAC"}
@@ -57,6 +57,7 @@ function WithGitOpsTemplate({ data }) {
57
57
  adoptBranch: true,
58
58
  gitRebaseSync: true,
59
59
  reactFileManager: true,
60
+ coastsDevServer: true,
60
61
  };
61
62
  return (_jsx(FeatureFlagsProvider, { flags: allEnabledFlags, children: _jsxs("div", { style: { height: '100vh', background: '#f8fafc', padding: '2rem' }, children: [_jsx("button", { type: "button", onClick: () => setSelected(data), style: { padding: '8px 16px', border: '1px solid #ccc', borderRadius: '6px' }, children: "Open Drawer" }), _jsx(RepositoryDrawer, { data: selected, onClose: () => setSelected(null) })] }) }));
62
63
  }
@@ -1 +1 @@
1
- {"version":3,"file":"repository-node.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/repository-node/repository-node.tsx"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAOnE,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,QAAQ,GACT,EAAE;IACD,IAAI,EAAE,kBAAkB,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,2CA0aA"}
1
+ {"version":3,"file":"repository-node.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/repository-node/repository-node.tsx"],"names":[],"mappings":"AAoCA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAQnE,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,QAAQ,GACT,EAAE;IACD,IAAI,EAAE,kBAAkB,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,2CAwdA"}
@@ -3,7 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
3
3
  import { useState, useCallback } from 'react';
4
4
  import { Handle, Position } from '@xyflow/react';
5
5
  import { useRouter } from 'next/navigation';
6
- import { Github, Plus, Code2, Terminal, FolderOpen, Trash2, Play, Square, GitBranch, GitCommitHorizontal, ArrowDown, User, RotateCcw, } from 'lucide-react';
6
+ import { Github, Plus, Code2, Terminal, FolderOpen, Trash2, Play, Square, GitBranch, GitCommitHorizontal, ArrowDown, User, RotateCcw, FileCode2, } from 'lucide-react';
7
7
  import { cn } from '../../../lib/utils.js';
8
8
  import { ActionButton } from '../../common/action-button/index.js';
9
9
  import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '../../ui/dialog.js';
@@ -12,6 +12,7 @@ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../../
12
12
  import { useDeployAction } from '../../../hooks/use-deploy-action.js';
13
13
  import { useFeatureFlags } from '../../../hooks/feature-flags-context.js';
14
14
  import { useRepositoryActions } from './use-repository-actions.js';
15
+ import { useCoastsActions } from './use-coasts-actions.js';
15
16
  import { FeatureSessionsDropdown, } from '../../common/feature-node/feature-sessions-dropdown.js';
16
17
  export function RepositoryNode({ data, selected, }) {
17
18
  const router = useRouter();
@@ -25,6 +26,7 @@ export function RepositoryNode({ data, selected, }) {
25
26
  repositoryPath: data.repositoryPath,
26
27
  }
27
28
  : null);
29
+ const coastsActions = useCoastsActions(data.repositoryPath ? { repositoryPath: data.repositoryPath } : null);
28
30
  const isDeploymentActive = deployAction.status === 'Booting' || deployAction.status === 'Ready';
29
31
  const handleCreateFromSession = useCallback((session, sessionFilePath) => {
30
32
  if (!data.repositoryPath)
@@ -84,5 +86,10 @@ export function RepositoryNode({ data, selected, }) {
84
86
  ? 'Retry'
85
87
  : isDeploymentActive
86
88
  ? 'Stop Dev Server'
87
- : 'Start Dev Server', onClick: isDeploymentActive ? deployAction.stop : deployAction.deploy, loading: deployAction.deployLoading || deployAction.stopLoading, error: false, icon: deployAction.deployError ? RotateCcw : isDeploymentActive ? Square : Play, iconOnly: true, variant: "ghost", size: "icon-xs" }) }) }), _jsx(TooltipContent, { children: isDeploymentActive ? 'Stop Dev Server' : 'Start Dev Server' })] }) })] }) })) : null] }), data.onAdd || data.showHandles ? (_jsx(Handle, { type: "source", position: Position.Right, isConnectable: !data.showHandles, className: "opacity-0!", style: { top: 70 } })) : null] }));
89
+ : 'Start Dev Server', onClick: isDeploymentActive ? deployAction.stop : deployAction.deploy, loading: deployAction.deployLoading || deployAction.stopLoading, error: false, icon: deployAction.deployError ? RotateCcw : isDeploymentActive ? Square : Play, iconOnly: true, variant: "ghost", size: "icon-xs" }) }) }), _jsx(TooltipContent, { children: isDeploymentActive ? 'Stop Dev Server' : 'Start Dev Server' })] }) })] }) })) : null, featureFlags.coastsDevServer && data.repositoryPath ? (_jsx("div", { "data-testid": "repository-node-coastfile", className: "border-t px-4 py-2", onClick: (e) => e.stopPropagation(), children: _jsxs("div", { className: "flex items-center gap-2 text-xs", children: [_jsx("span", { className: "text-muted-foreground", children: coastsActions.coastfileExists ? 'Coastfile' : 'No Coastfile' }), _jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("span", { className: "ml-auto flex items-center", children: _jsx(ActionButton, { label: coastsActions.coastfileExists
90
+ ? 'Regenerate Coastfile'
91
+ : 'Generate Coastfile', onClick: coastsActions.generateCoastfile, loading: coastsActions.generating || coastsActions.checkLoading, error: !!coastsActions.error, icon: FileCode2, iconOnly: true, variant: "ghost", size: "icon-xs" }) }) }), _jsx(TooltipContent, { children: coastsActions.error ??
92
+ (coastsActions.coastfileExists
93
+ ? 'Regenerate Coastfile'
94
+ : 'Generate Coastfile') })] }) })] }) })) : null] }), data.onAdd || data.showHandles ? (_jsx(Handle, { type: "source", position: Position.Right, isConnectable: !data.showHandles, className: "opacity-0!", style: { top: 70 } })) : null] }));
88
95
  }
@@ -0,0 +1,12 @@
1
+ export interface CoastsActionsInput {
2
+ repositoryPath: string;
3
+ }
4
+ export interface CoastsActionsState {
5
+ coastfileExists: boolean;
6
+ generating: boolean;
7
+ checkLoading: boolean;
8
+ error: string | null;
9
+ generateCoastfile: () => Promise<void>;
10
+ }
11
+ export declare function useCoastsActions(input: CoastsActionsInput | null): CoastsActionsState;
12
+ //# sourceMappingURL=use-coasts-actions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-coasts-actions.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/repository-node/use-coasts-actions.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,kBAAkB;IACjC,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,eAAe,EAAE,OAAO,CAAC;IACzB,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,iBAAiB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC;AAID,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI,GAAG,kBAAkB,CA0ErF"}
@@ -0,0 +1,76 @@
1
+ 'use client';
2
+ import { useState, useCallback, useRef, useEffect } from 'react';
3
+ import { generateCoastfileAction } from '../../../app/actions/generate-coastfile.js';
4
+ import { checkCoastfileAction } from '../../../app/actions/check-coastfile.js';
5
+ const ERROR_CLEAR_DELAY = 5000;
6
+ export function useCoastsActions(input) {
7
+ const repoPath = input?.repositoryPath ?? null;
8
+ const [coastfileExists, setCoastfileExists] = useState(false);
9
+ const [generating, setGenerating] = useState(false);
10
+ const [checkLoading, setCheckLoading] = useState(!!repoPath);
11
+ const [error, setError] = useState(null);
12
+ const errorTimerRef = useRef(null);
13
+ useEffect(() => {
14
+ const ref = errorTimerRef;
15
+ return () => {
16
+ if (ref.current)
17
+ clearTimeout(ref.current);
18
+ };
19
+ }, []);
20
+ // Check coastfile existence on mount — use repoPath (string) as dep to avoid infinite re-renders
21
+ useEffect(() => {
22
+ if (!repoPath)
23
+ return;
24
+ let cancelled = false;
25
+ setCheckLoading(true);
26
+ checkCoastfileAction(repoPath)
27
+ .then((result) => {
28
+ if (!cancelled) {
29
+ setCoastfileExists(result.exists);
30
+ setCheckLoading(false);
31
+ }
32
+ })
33
+ .catch(() => {
34
+ if (!cancelled) {
35
+ setCoastfileExists(false);
36
+ setCheckLoading(false);
37
+ }
38
+ });
39
+ return () => {
40
+ cancelled = true;
41
+ };
42
+ }, [repoPath]);
43
+ const handleGenerate = useCallback(async () => {
44
+ if (!repoPath || generating)
45
+ return;
46
+ if (errorTimerRef.current)
47
+ clearTimeout(errorTimerRef.current);
48
+ setGenerating(true);
49
+ setError(null);
50
+ try {
51
+ const result = await generateCoastfileAction(repoPath);
52
+ if (result.success) {
53
+ setCoastfileExists(true);
54
+ }
55
+ else {
56
+ setError(result.error ?? 'Failed to generate Coastfile');
57
+ errorTimerRef.current = setTimeout(() => setError(null), ERROR_CLEAR_DELAY);
58
+ }
59
+ }
60
+ catch (err) {
61
+ const message = err instanceof Error ? err.message : 'Failed to generate Coastfile';
62
+ setError(message);
63
+ errorTimerRef.current = setTimeout(() => setError(null), ERROR_CLEAR_DELAY);
64
+ }
65
+ finally {
66
+ setGenerating(false);
67
+ }
68
+ }, [repoPath, generating]);
69
+ return {
70
+ coastfileExists,
71
+ generating,
72
+ checkLoading,
73
+ error,
74
+ generateCoastfile: handleGenerate,
75
+ };
76
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"feature-flags-settings-section.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/feature-flags-settings-section.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AAiCzE,MAAM,WAAW,gCAAgC;IAC/C,YAAY,EAAE,YAAY,CAAC;CAC5B;AAED,wBAAgB,2BAA2B,CAAC,EAAE,YAAY,EAAE,EAAE,gCAAgC,2CAgE7F"}
1
+ {"version":3,"file":"feature-flags-settings-section.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/feature-flags-settings-section.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AAqCzE,MAAM,WAAW,gCAAgC;IAC/C,YAAY,EAAE,YAAY,CAAC;CAC5B;AAED,wBAAgB,2BAA2B,CAAC,EAAE,YAAY,EAAE,EAAE,gCAAgC,2CAgE7F"}
@@ -15,6 +15,7 @@ const FLAG_DESCRIPTIONS = {
15
15
  adoptBranch: 'Enable the ability to adopt existing branches as tracked features',
16
16
  gitRebaseSync: 'Enable git rebase-on-main and sync-main operations in the web UI',
17
17
  reactFileManager: 'Use the built-in React file manager instead of the native OS folder picker. Also serves as automatic fallback when the native picker is unavailable.',
18
+ coastsDevServer: 'Enable Coasts containerized runtime isolation for the dev server, providing per-worktree isolation via Docker containers',
18
19
  };
19
20
  const FLAG_LABELS = {
20
21
  skills: 'Skills',
@@ -24,6 +25,7 @@ const FLAG_LABELS = {
24
25
  adoptBranch: 'Adopt Branch',
25
26
  gitRebaseSync: 'Git Rebase & Sync',
26
27
  reactFileManager: 'React File Manager',
28
+ coastsDevServer: 'Coasts Dev Server',
27
29
  };
28
30
  const FLAG_KEYS = [
29
31
  'skills',
@@ -33,6 +35,7 @@ const FLAG_KEYS = [
33
35
  'adoptBranch',
34
36
  'gitRebaseSync',
35
37
  'reactFileManager',
38
+ 'coastsDevServer',
36
39
  ];
37
40
  export function FeatureFlagsSettingsSection({ featureFlags }) {
38
41
  const [flags, setFlags] = useState({ ...featureFlags });
@@ -1 +1 @@
1
- {"version":3,"file":"feature-flags-settings-section.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/feature-flags-settings-section.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAE/E,QAAA,MAAM,IAAI;;;;;;;CAO0C,CAAC;AAErD,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,OAAO,EAAE,KAYrB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KAYxB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAYzB,CAAC"}
1
+ {"version":3,"file":"feature-flags-settings-section.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/feature-flags-settings-section.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAE/E,QAAA,MAAM,IAAI;;;;;;;CAO0C,CAAC;AAErD,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,OAAO,EAAE,KAarB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KAaxB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAazB,CAAC"}