kasy-cli 1.21.8 → 1.22.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 (269) hide show
  1. package/lib/commands/add.js +93 -80
  2. package/lib/commands/configure.js +100 -32
  3. package/lib/commands/doctor.js +28 -2
  4. package/lib/commands/new.js +86 -38
  5. package/lib/commands/notifications.js +1 -1
  6. package/lib/commands/remove.js +43 -15
  7. package/lib/commands/run.js +2 -2
  8. package/lib/commands/update.js +2 -2
  9. package/lib/scaffold/CHANGELOG.json +14 -0
  10. package/lib/scaffold/backends/api/generator.js +14 -14
  11. package/lib/scaffold/backends/api/patch/README.md +83 -0
  12. package/lib/scaffold/backends/api/patch/lib/core/data/api/storage_api.dart +1 -1
  13. package/lib/scaffold/backends/api/patch/lib/core/data/entities/user_entity.dart +5 -0
  14. package/lib/scaffold/backends/api/patch/lib/{environnements.dart → environments.dart} +3 -11
  15. package/lib/scaffold/backends/api/patch/lib/features/ai_chat/api/ai_chat_api.dart +108 -0
  16. package/lib/scaffold/backends/api/patch/lib/features/ai_chat/api/ai_chat_conversation_entity.dart +51 -0
  17. package/lib/scaffold/backends/api/patch/lib/features/{llm_chat/api/llm_chat_message_entity.dart → ai_chat/api/ai_chat_message_entity.dart} +5 -5
  18. package/lib/scaffold/backends/api/patch/lib/features/{llm_chat/providers/llm_chat_notifier.dart → ai_chat/providers/ai_chat_notifier.dart} +71 -38
  19. package/lib/scaffold/backends/api/patch/lib/features/authentication/api/authentication_api.dart +2 -2
  20. package/lib/scaffold/backends/api/patch/lib/features/feedbacks/api/feature_request_api.dart +54 -0
  21. package/lib/scaffold/backends/api/patch/lib/features/onboarding/models/user_info.dart +16 -16
  22. package/lib/scaffold/backends/api/patch/lib/features/onboarding/ui/components/onboarding_att_setup.dart +4 -3
  23. package/lib/scaffold/backends/api/patch/lib/features/onboarding/ui/widgets/onboarding_radio_question.dart +38 -28
  24. package/lib/scaffold/backends/api/patch/lib/features/settings/ui/components/admin/admin_users_api.dart +100 -0
  25. package/lib/scaffold/backends/api/patch/lib/features/{subscription → subscriptions}/api/entities/subscription_entity.dart +13 -0
  26. package/lib/scaffold/backends/api/patch/lib/features/subscriptions/api/stripe_backend_api.dart +60 -0
  27. package/lib/scaffold/backends/api/patch/lib/features/{subscription → subscriptions}/api/subscription_api.dart +1 -1
  28. package/lib/scaffold/backends/api/pubspec.yaml.tpl +4 -5
  29. package/lib/scaffold/backends/firebase/deploy.js +87 -13
  30. package/lib/scaffold/backends/firebase/enable-auth-via-cli.js +14 -6
  31. package/lib/scaffold/backends/firebase/generator.js +5 -5
  32. package/lib/scaffold/backends/firebase/setup-from-scratch.js +69 -45
  33. package/lib/scaffold/backends/firebase/tokens.js +4 -4
  34. package/lib/scaffold/backends/supabase/deploy.js +63 -11
  35. package/lib/scaffold/backends/supabase/edge-functions/admin-list-users/index.ts +149 -0
  36. package/lib/scaffold/backends/supabase/edge-functions/{llm-chat → ai-chat}/index.ts +19 -19
  37. package/lib/scaffold/backends/supabase/edge-functions/revenuecat-webhook/index.ts +2 -0
  38. package/lib/scaffold/backends/supabase/edge-functions/stripe-create-checkout-session/index.ts +123 -0
  39. package/lib/scaffold/backends/supabase/edge-functions/stripe-create-portal-session/index.ts +97 -0
  40. package/lib/scaffold/backends/supabase/edge-functions/stripe-list-prices/index.ts +83 -0
  41. package/lib/scaffold/backends/supabase/edge-functions/stripe-webhook/index.ts +138 -0
  42. package/lib/scaffold/backends/supabase/generator.js +17 -17
  43. package/lib/scaffold/backends/supabase/migrations/20240101000009_ai_messages.sql +50 -0
  44. package/lib/scaffold/backends/supabase/migrations/20240101000012_stripe_customers.sql +36 -0
  45. package/lib/scaffold/backends/supabase/migrations/20240101000013_admin_role.sql +62 -0
  46. package/lib/scaffold/backends/supabase/patch/lib/core/data/entities/user_entity.dart +4 -0
  47. package/lib/scaffold/backends/supabase/patch/lib/{environnements.dart → environments.dart} +3 -13
  48. package/lib/scaffold/backends/supabase/patch/lib/features/ai_chat/api/ai_chat_api.dart +95 -0
  49. package/lib/scaffold/backends/supabase/patch/lib/features/ai_chat/api/ai_chat_conversation_entity.dart +52 -0
  50. package/lib/scaffold/backends/supabase/patch/lib/features/{llm_chat/api/llm_chat_message_entity.dart → ai_chat/api/ai_chat_message_entity.dart} +6 -6
  51. package/lib/scaffold/backends/supabase/patch/lib/features/{llm_chat/providers/llm_chat_notifier.dart → ai_chat/providers/ai_chat_notifier.dart} +63 -35
  52. package/lib/scaffold/backends/supabase/patch/lib/features/authentication/api/authentication_api.dart +1 -1
  53. package/lib/scaffold/backends/supabase/patch/lib/features/feedbacks/api/feature_request_api.dart +46 -0
  54. package/lib/scaffold/backends/supabase/patch/lib/features/onboarding/models/user_info.dart +16 -16
  55. package/lib/scaffold/backends/supabase/patch/lib/features/onboarding/ui/components/onboarding_att_setup.dart +4 -3
  56. package/lib/scaffold/backends/supabase/patch/lib/features/onboarding/ui/widgets/onboarding_radio_question.dart +38 -28
  57. package/lib/scaffold/backends/supabase/patch/lib/features/settings/ui/components/admin/admin_users_api.dart +93 -0
  58. package/lib/scaffold/backends/supabase/patch/lib/features/{subscription → subscriptions}/api/entities/subscription_entity.dart +13 -0
  59. package/lib/scaffold/backends/supabase/patch/lib/features/subscriptions/api/stripe_backend_api.dart +52 -0
  60. package/lib/scaffold/backends/supabase/patch/lib/features/{subscription → subscriptions}/api/subscription_api.dart +1 -1
  61. package/lib/scaffold/backends/supabase/pubspec.yaml.tpl +4 -5
  62. package/lib/scaffold/backends/supabase/tokens.js +3 -3
  63. package/lib/scaffold/catalog.js +9 -11
  64. package/lib/scaffold/generate.js +45 -31
  65. package/lib/scaffold/shared/generator-utils.js +188 -81
  66. package/lib/scaffold/shared/sort-imports.js +191 -0
  67. package/lib/scaffold/shared/template-strings.js +3 -3
  68. package/lib/utils/checks.js +2 -2
  69. package/lib/utils/i18n/messages-en.js +50 -35
  70. package/lib/utils/i18n/messages-es.js +50 -35
  71. package/lib/utils/i18n/messages-pt.js +52 -37
  72. package/lib/utils/updates.js +15 -15
  73. package/package.json +1 -1
  74. package/templates/firebase/.env.example +2 -2
  75. package/templates/firebase/android/app/src/main/res/drawable/background.png +0 -0
  76. package/templates/firebase/android/app/src/main/res/drawable-night/background.png +0 -0
  77. package/templates/firebase/android/app/src/main/res/drawable-night-v21/background.png +0 -0
  78. package/templates/firebase/android/app/src/main/res/drawable-v21/background.png +0 -0
  79. package/templates/firebase/android/app/src/main/res/values-night-v31/styles.xml +1 -1
  80. package/templates/firebase/android/app/src/main/res/values-v31/styles.xml +1 -1
  81. package/templates/firebase/assets/images/logo_wordmark_dark.png +0 -0
  82. package/templates/firebase/assets/images/logo_wordmark_light.png +0 -0
  83. package/templates/firebase/docs/revenuecat-setup.es.md +1 -1
  84. package/templates/firebase/docs/revenuecat-setup.pt.md +1 -1
  85. package/templates/firebase/firestore.rules +24 -5
  86. package/templates/firebase/functions/package-lock.json +22 -1
  87. package/templates/firebase/functions/package.json +2 -1
  88. package/templates/firebase/functions/src/admin/functions.ts +113 -0
  89. package/templates/firebase/functions/src/{llm_chat → ai_chat}/index.ts +16 -16
  90. package/templates/firebase/functions/src/index.ts +8 -2
  91. package/templates/firebase/functions/src/notifications/device_triggers.ts +2 -2
  92. package/templates/firebase/functions/src/notifications/triggers.ts +3 -3
  93. package/templates/firebase/functions/src/subscriptions/models/subscription_status.ts +2 -0
  94. package/templates/firebase/functions/src/subscriptions/stripe_functions.ts +222 -0
  95. package/templates/firebase/functions/src/subscriptions/subscriptions_functions.ts +2 -2
  96. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png +0 -0
  97. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchBackground.imageset/darkbackground.png +0 -0
  98. package/templates/firebase/lib/components/components.dart +4 -1
  99. package/templates/firebase/lib/components/kasy_app_bar.dart +22 -7
  100. package/templates/firebase/lib/components/kasy_avatar.dart +7 -6
  101. package/templates/firebase/lib/components/kasy_button.dart +23 -99
  102. package/templates/firebase/lib/components/kasy_dialog.dart +11 -11
  103. package/templates/firebase/lib/components/kasy_image_viewer.dart +84 -0
  104. package/templates/firebase/lib/components/{kasy_sidebar_pro.dart → kasy_sidebar.dart} +692 -425
  105. package/templates/firebase/lib/components/kasy_status_tag.dart +91 -0
  106. package/templates/firebase/lib/components/kasy_text_area.dart +1 -3
  107. package/templates/firebase/lib/components/kasy_text_field.dart +5 -6
  108. package/templates/firebase/lib/components/kasy_text_field_otp.dart +1 -3
  109. package/templates/firebase/lib/components/kasy_toast.dart +2 -2
  110. package/templates/firebase/lib/components/kasy_web_header.dart +209 -0
  111. package/templates/firebase/lib/core/ads/ads_provider.dart +1 -1
  112. package/templates/firebase/lib/core/bottom_menu/bottom_menu.dart +57 -4
  113. package/templates/firebase/lib/core/bottom_menu/bottom_router.dart +19 -91
  114. package/templates/firebase/lib/core/bottom_menu/kasy_bottom_bar_factory.dart +196 -96
  115. package/templates/firebase/lib/core/bottom_menu/web_content_wrapper.dart +41 -0
  116. package/templates/firebase/lib/core/config/app_env.dart +5 -11
  117. package/templates/firebase/lib/core/config/features.dart +5 -4
  118. package/templates/firebase/lib/core/data/api/analytics_api.dart +1 -1
  119. package/templates/firebase/lib/core/data/api/http_client.dart +1 -1
  120. package/templates/firebase/lib/core/data/entities/user_entity.dart +3 -0
  121. package/templates/firebase/lib/core/data/models/entitlement.dart +35 -0
  122. package/templates/firebase/lib/core/data/models/subscription.dart +13 -186
  123. package/templates/firebase/lib/core/data/models/user.dart +11 -0
  124. package/templates/firebase/lib/core/data/repositories/user_repository.dart +1 -1
  125. package/templates/firebase/lib/core/home_widgets/home_widget_background_task.dart +1 -1
  126. package/templates/firebase/lib/core/home_widgets/home_widget_mywidget_service.dart +1 -1
  127. package/templates/firebase/lib/core/icons/kasy_icons.dart +31 -1
  128. package/templates/firebase/lib/core/rating/api/rating_api.dart +2 -2
  129. package/templates/firebase/lib/core/states/logout_action.dart +25 -0
  130. package/templates/firebase/lib/core/states/user_state_notifier.dart +3 -3
  131. package/templates/firebase/lib/core/theme/colors.dart +488 -188
  132. package/templates/firebase/lib/core/theme/radius.dart +22 -11
  133. package/templates/firebase/lib/core/theme/shadows.dart +66 -0
  134. package/templates/firebase/lib/core/theme/texts.dart +75 -41
  135. package/templates/firebase/lib/core/theme/universal_theme.dart +9 -4
  136. package/templates/firebase/lib/core/web_device_preview/web_device_preview.dart +5 -4
  137. package/templates/firebase/lib/core/web_viewport_scale.dart +52 -0
  138. package/templates/firebase/lib/core/widgets/kasy_brand_badge.dart +118 -0
  139. package/templates/firebase/lib/core/widgets/kasy_brand_logo.dart +40 -0
  140. package/templates/firebase/lib/core/widgets/kasy_focus_ring.dart +125 -0
  141. package/templates/firebase/lib/core/widgets/kasy_hover.dart +33 -13
  142. package/templates/firebase/lib/core/widgets/kasy_pressable_depth.dart +18 -13
  143. package/templates/firebase/lib/{environnements.dart → environments.dart} +3 -14
  144. package/templates/firebase/lib/features/ai_chat/ai_chat_page.dart +159 -0
  145. package/templates/firebase/lib/features/ai_chat/api/ai_chat_api.dart +107 -0
  146. package/templates/firebase/lib/features/ai_chat/api/ai_chat_conversation_entity.dart +64 -0
  147. package/templates/firebase/lib/features/{llm_chat/api/llm_chat_message_entity.dart → ai_chat/api/ai_chat_message_entity.dart} +6 -6
  148. package/templates/firebase/lib/features/{llm_chat/providers/llm_chat_notifier.dart → ai_chat/providers/ai_chat_notifier.dart} +73 -38
  149. package/templates/firebase/lib/features/ai_chat/providers/ai_conversations_notifier.dart +103 -0
  150. package/templates/firebase/lib/features/{llm_chat/ui/widgets/llm_chat_avatars.dart → ai_chat/ui/widgets/ai_chat_avatars.dart} +13 -13
  151. package/templates/firebase/lib/features/{llm_chat/ui/widgets/llm_chat_composer.dart → ai_chat/ui/widgets/ai_chat_composer.dart} +10 -10
  152. package/templates/firebase/lib/features/{llm_chat/llm_chat_page.dart → ai_chat/ui/widgets/ai_chat_conversation_view.dart} +80 -67
  153. package/templates/firebase/lib/features/ai_chat/ui/widgets/ai_conversation_list.dart +285 -0
  154. package/templates/firebase/lib/features/ai_chat/ui/widgets/ai_conversation_tile.dart +163 -0
  155. package/templates/firebase/lib/features/authentication/api/authentication_api.dart +52 -13
  156. package/templates/firebase/lib/features/authentication/api/popup_dismiss_watcher.dart +12 -0
  157. package/templates/firebase/lib/features/authentication/api/popup_dismiss_watcher_web.dart +35 -0
  158. package/templates/firebase/lib/features/authentication/ui/recover_password_page.dart +108 -68
  159. package/templates/firebase/lib/features/authentication/ui/signin_page.dart +38 -51
  160. package/templates/firebase/lib/features/authentication/ui/signup_page.dart +38 -51
  161. package/templates/firebase/lib/features/authentication/ui/widgets/auth_card_scaffold.dart +118 -0
  162. package/templates/firebase/lib/features/authentication/ui/widgets/recover_password_result.dart +61 -44
  163. package/templates/firebase/lib/features/feedbacks/api/feature_request_api.dart +32 -0
  164. package/templates/firebase/lib/features/feedbacks/models/feedback_state.dart +5 -5
  165. package/templates/firebase/lib/features/feedbacks/providers/feedback_page_notifier.dart +2 -2
  166. package/templates/firebase/lib/features/home/design_system_page.dart +808 -170
  167. package/templates/firebase/lib/features/home/home_components_page.dart +6 -3
  168. package/templates/firebase/lib/features/home/home_components_preview_page.dart +6 -6
  169. package/templates/firebase/lib/features/home/home_components_preview_registry.dart +325 -186
  170. package/templates/firebase/lib/features/home/home_feed.dart +289 -0
  171. package/templates/firebase/lib/features/home/home_image_grid.dart +355 -0
  172. package/templates/firebase/lib/features/home/home_page.dart +11 -250
  173. package/templates/firebase/lib/features/{local_reminder → local_reminders}/providers/reminder_notifier.dart +1 -1
  174. package/templates/firebase/lib/features/{local_reminder → local_reminders}/ui/reminder_page.dart +2 -2
  175. package/templates/firebase/lib/features/notifications/shared/att_permission.dart +1 -1
  176. package/templates/firebase/lib/features/notifications/ui/request_notification_permission.dart +25 -61
  177. package/templates/firebase/lib/features/notifications/ui/widgets/permission_request_view.dart +117 -0
  178. package/templates/firebase/lib/features/onboarding/models/user_info.dart +16 -16
  179. package/templates/firebase/lib/features/onboarding/ui/components/onboarding_att_setup.dart +4 -3
  180. package/templates/firebase/lib/features/onboarding/ui/components/onboarding_features.dart +7 -9
  181. package/templates/firebase/lib/features/onboarding/ui/components/onboarding_loader.dart +71 -48
  182. package/templates/firebase/lib/features/onboarding/ui/components/onboarding_notifications_setup.dart +3 -2
  183. package/templates/firebase/lib/features/onboarding/ui/components/onboarding_questions.dart +5 -5
  184. package/templates/firebase/lib/features/onboarding/ui/onboarding_page.dart +4 -4
  185. package/templates/firebase/lib/features/onboarding/ui/widgets/onboarding_background.dart +4 -2
  186. package/templates/firebase/lib/features/onboarding/ui/widgets/onboarding_feature.dart +39 -121
  187. package/templates/firebase/lib/features/onboarding/ui/widgets/onboarding_illustration_scaffold.dart +105 -70
  188. package/templates/firebase/lib/features/onboarding/ui/widgets/onboarding_module_mockups.dart +639 -0
  189. package/templates/firebase/lib/features/onboarding/ui/widgets/onboarding_progress.dart +62 -50
  190. package/templates/firebase/lib/features/onboarding/ui/widgets/onboarding_radio_question.dart +38 -28
  191. package/templates/firebase/lib/features/onboarding/ui/widgets/onboarding_step_header.dart +75 -0
  192. package/templates/firebase/lib/features/onboarding/ui/widgets/onboarding_sticky_footer.dart +16 -5
  193. package/templates/firebase/lib/features/onboarding/ui/widgets/selectable_row_tile.dart +26 -22
  194. package/templates/firebase/lib/features/settings/settings_page.dart +601 -90
  195. package/templates/firebase/lib/features/settings/ui/components/admin/admin_page.dart +1193 -0
  196. package/templates/firebase/lib/features/settings/ui/components/admin/admin_paywalls.dart +1 -1
  197. package/templates/firebase/lib/features/settings/ui/components/admin/admin_routes.dart +2 -3
  198. package/templates/firebase/lib/features/settings/ui/components/admin/admin_users_api.dart +86 -0
  199. package/templates/firebase/lib/features/settings/ui/components/admin/admin_users_tab.dart +1215 -0
  200. package/templates/firebase/lib/features/settings/ui/components/admin/send_push_notification_page.dart +236 -0
  201. package/templates/firebase/lib/features/settings/ui/components/avatar_component.dart +3 -3
  202. package/templates/firebase/lib/features/settings/ui/widgets/kasy_user_avatar.dart +77 -0
  203. package/templates/firebase/lib/features/settings/ui/widgets/settings_tile.dart +1 -0
  204. package/templates/firebase/lib/features/{subscription → subscriptions}/api/entities/subscription_entity.dart +17 -0
  205. package/templates/firebase/lib/features/{subscription → subscriptions}/api/inapp_subscription_api.dart +67 -46
  206. package/templates/firebase/lib/features/subscriptions/api/revenuecat_product.dart +189 -0
  207. package/templates/firebase/lib/features/subscriptions/api/stripe_backend_api.dart +55 -0
  208. package/templates/firebase/lib/features/subscriptions/api/stripe_payment_api.dart +82 -0
  209. package/templates/firebase/lib/features/subscriptions/api/stripe_product.dart +178 -0
  210. package/templates/firebase/lib/features/{subscription → subscriptions}/api/subscription_api.dart +1 -1
  211. package/templates/firebase/lib/features/subscriptions/api/subscription_payment_api.dart +53 -0
  212. package/templates/firebase/lib/features/subscriptions/api/subscription_payment_api_provider.dart +21 -0
  213. package/templates/firebase/lib/features/{subscription → subscriptions}/providers/premium_page_provider.dart +9 -6
  214. package/templates/firebase/lib/features/{subscription → subscriptions}/repositories/subscription_repository.dart +26 -30
  215. package/{lib/scaffold/backends/supabase/patch/lib/features/subscription → templates/firebase/lib/features/subscriptions}/shared/maybeshow_premium.dart +0 -2
  216. package/templates/firebase/lib/features/subscriptions/shared/subscription_management.dart +45 -0
  217. package/templates/firebase/lib/features/{subscription → subscriptions}/ui/component/active_premium_content.dart +28 -4
  218. package/templates/firebase/lib/features/{subscription → subscriptions}/ui/component/paywall_minimal.dart +7 -7
  219. package/templates/firebase/lib/features/{subscription → subscriptions}/ui/component/paywall_row.dart +8 -8
  220. package/templates/firebase/lib/features/{subscription → subscriptions}/ui/component/paywall_with_switch.dart +7 -7
  221. package/templates/firebase/lib/features/{subscription → subscriptions}/ui/component/premium_content.dart +7 -7
  222. package/templates/firebase/lib/features/{subscription → subscriptions}/ui/component/premium_page_factory.dart +5 -5
  223. package/templates/firebase/lib/features/{subscription → subscriptions}/ui/premium_page.dart +5 -5
  224. package/templates/firebase/lib/features/{subscription → subscriptions}/ui/widgets/comparison_table.dart +1 -1
  225. package/templates/firebase/lib/features/{subscription → subscriptions}/ui/widgets/paywall_empty_state.dart +4 -4
  226. package/templates/firebase/lib/features/{subscription → subscriptions}/ui/widgets/premium_bottom_menu.dart +3 -4
  227. package/templates/firebase/lib/features/{subscription → subscriptions}/ui/widgets/selectable_col.dart +1 -1
  228. package/templates/firebase/lib/i18n/en.i18n.json +171 -46
  229. package/templates/firebase/lib/i18n/es.i18n.json +175 -50
  230. package/templates/firebase/lib/i18n/pt.i18n.json +166 -41
  231. package/templates/firebase/lib/main.dart +6 -3
  232. package/templates/firebase/lib/router.dart +15 -23
  233. package/templates/firebase/pubspec.yaml +4 -5
  234. package/templates/firebase/test/core/data/repositories/user_repository_test.dart +3 -3
  235. package/templates/firebase/test/core/states/user_state_notifier_test.dart +4 -4
  236. package/templates/firebase/test/core/widgets/focus_ring_shape_test.dart +55 -0
  237. package/templates/firebase/test/features/{subscription → subscriptions}/api/fake_inapp_subscription_api.dart +11 -4
  238. package/templates/firebase/test/features/{subscription → subscriptions}/api/fake_revenuecat_product.dart +1 -0
  239. package/templates/firebase/test/features/{subscription → subscriptions}/api/fake_subscription_api.dart +2 -2
  240. package/templates/firebase/test/features/{subscription → subscriptions}/subscription_page_test.dart +4 -4
  241. package/templates/firebase/test/test_utils.dart +6 -6
  242. package/templates/firebase/web/index.html +5 -2
  243. package/lib/scaffold/backends/api/patch/lib/features/llm_chat/api/llm_chat_api.dart +0 -58
  244. package/lib/scaffold/backends/api/patch/lib/features/subscription/shared/maybeshow_premium.dart +0 -86
  245. package/lib/scaffold/backends/supabase/migrations/20240101000009_llm_messages.sql +0 -22
  246. package/lib/scaffold/backends/supabase/patch/lib/features/llm_chat/api/llm_chat_api.dart +0 -47
  247. package/templates/firebase/assets/images/onboarding/authentication-login-template.jpg +0 -0
  248. package/templates/firebase/assets/images/onboarding/img2.jpg +0 -0
  249. package/templates/firebase/assets/images/onboarding/img3.jpg +0 -0
  250. package/templates/firebase/assets/images/onboarding/notifications.png +0 -0
  251. package/templates/firebase/assets/images/onboarding/purchase.png +0 -0
  252. package/templates/firebase/lib/core/sidebar/kasy_sidebar.dart +0 -2021
  253. package/templates/firebase/lib/features/authentication/ui/widgets/auth_brand.dart +0 -35
  254. package/templates/firebase/lib/features/home/home_features_page.dart +0 -207
  255. package/templates/firebase/lib/features/llm_chat/api/llm_chat_api.dart +0 -50
  256. package/templates/firebase/lib/features/settings/ui/components/admin/admin_bottom_sheet.dart +0 -316
  257. package/templates/firebase/lib/features/subscription/shared/maybeshow_premium.dart +0 -85
  258. /package/templates/firebase/lib/features/{local_reminder → local_reminders}/repositories/reminder_preferences.dart +0 -0
  259. /package/templates/firebase/lib/features/{subscription → subscriptions}/providers/models/premium_state.dart +0 -0
  260. /package/templates/firebase/lib/features/{subscription → subscriptions}/ui/widgets/feature_line.dart +0 -0
  261. /package/templates/firebase/lib/features/{subscription → subscriptions}/ui/widgets/premium_background.dart +0 -0
  262. /package/templates/firebase/lib/features/{subscription → subscriptions}/ui/widgets/premium_background_gradient.dart +0 -0
  263. /package/templates/firebase/lib/features/{subscription → subscriptions}/ui/widgets/premium_banner.dart +0 -0
  264. /package/templates/firebase/lib/features/{subscription → subscriptions}/ui/widgets/premium_card.dart +0 -0
  265. /package/templates/firebase/lib/features/{subscription → subscriptions}/ui/widgets/premium_close_button.dart +0 -0
  266. /package/templates/firebase/lib/features/{subscription → subscriptions}/ui/widgets/premium_feature.dart +0 -0
  267. /package/templates/firebase/lib/features/{subscription → subscriptions}/ui/widgets/selectable_row.dart +0 -0
  268. /package/templates/firebase/lib/features/{subscription → subscriptions}/ui/widgets/trial_switcher.dart +0 -0
  269. /package/templates/firebase/lib/features/{subscription → subscriptions}/ui/widgets/unsubscribe_feedback_popup.dart +0 -0
@@ -0,0 +1,191 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Sorts Dart `import`/`export`/`part` directives to satisfy the
5
+ * `directives_ordering` lint, which otherwise fires across generated projects
6
+ * because renaming the `kasy_kit` package to the project's name breaks the
7
+ * source's alphabetical order.
8
+ *
9
+ * Order:
10
+ * 1. dart: imports
11
+ * 2. package: imports (alphabetical)
12
+ * 3. relative imports (alphabetical)
13
+ * 4. part / part of (kept after imports)
14
+ *
15
+ * Comments above the first directive (license / ignore_for_file) and the full
16
+ * directive line (with `as`/`show`/`hide`/conditional `if`) are preserved.
17
+ * Generated files (.g.dart / .freezed.dart) are skipped.
18
+ */
19
+
20
+ const fs = require('fs');
21
+ const path = require('path');
22
+
23
+ const DIRECTIVE_RE = /^(import|export|part)\s+['"]([^'"]+)['"](.*?);?\s*$/;
24
+
25
+ // Groups, in output order:
26
+ // 0 import dart: 1 import package: 2 import relative
27
+ // 3 export dart: 4 export package: 5 export relative
28
+ // 6 part / part of
29
+ const OTHER_GROUP = 7;
30
+
31
+ function classify(line) {
32
+ const m = line.match(DIRECTIVE_RE);
33
+ if (!m) return OTHER_GROUP;
34
+ const keyword = m[1];
35
+ const uri = m[2];
36
+ if (keyword === 'part') return 6;
37
+ const base = uri.startsWith('dart:') ? 0 : uri.startsWith('package:') ? 1 : 2;
38
+ return keyword === 'export' ? base + 3 : base;
39
+ }
40
+
41
+ function sortKey(line) {
42
+ const m = line.match(DIRECTIVE_RE);
43
+ return m ? m[2] : '';
44
+ }
45
+
46
+ const DIRECTIVE_START_RE = /^(import|export|part)\b/;
47
+
48
+ function isHeaderComment(trimmed) {
49
+ return (
50
+ trimmed.startsWith('//') ||
51
+ trimmed.startsWith('/*') ||
52
+ trimmed.startsWith('*') ||
53
+ trimmed.startsWith('@')
54
+ );
55
+ }
56
+
57
+ // ASCII / code-unit ordering matches the Dart analyzer (where '/' (0x2F) sorts
58
+ // before '_' (0x5F), so 'flutter/material' < 'flutter_riverpod'). localeCompare
59
+ // gets this wrong. A directive may span multiple physical lines (e.g.
60
+ // `import '...'` then ` as foo;`, or a conditional `import '...' if (...) '...';`),
61
+ // so we accumulate lines until one ends with ';' and sort each unit by its first URI.
62
+ function processContent(original) {
63
+ const lines = original.split('\n');
64
+
65
+ // Find the first directive; bail if real code appears before any directive.
66
+ let firstDir = -1;
67
+ for (let k = 0; k < lines.length; k++) {
68
+ const t = lines[k].trim();
69
+ if (DIRECTIVE_START_RE.test(t)) {
70
+ firstDir = k;
71
+ break;
72
+ }
73
+ if (t !== '' && !isHeaderComment(t)) break;
74
+ }
75
+ if (firstDir === -1) return { changed: false, content: original };
76
+
77
+ const prefix = lines.slice(0, firstDir); // license / ignore_for_file — kept verbatim
78
+
79
+ // Parse directive units. A unit carries any comment lines directly above it
80
+ // (e.g. `// ignore: depend_on_referenced_packages`) so the comment travels
81
+ // with its import when reordered. A directive may also span multiple physical
82
+ // lines until one ends with ';'.
83
+ let i = firstDir;
84
+ const units = [];
85
+ let pending = [];
86
+ while (i < lines.length) {
87
+ const t = lines[i].trim();
88
+ if (t === '') {
89
+ i++;
90
+ continue;
91
+ }
92
+ if (isHeaderComment(t)) {
93
+ pending.push(lines[i]);
94
+ i++;
95
+ continue;
96
+ }
97
+ if (!DIRECTIVE_START_RE.test(t)) break; // first real code
98
+ const dir = [...pending, lines[i]];
99
+ pending = [];
100
+ while (!lines[i].trim().endsWith(';') && i + 1 < lines.length) {
101
+ i++;
102
+ dir.push(lines[i]);
103
+ }
104
+ i++;
105
+ const dirLine = dir.find((l) => DIRECTIVE_START_RE.test(l.trim())).trim();
106
+ units.push({ group: classify(dirLine), key: sortKey(dirLine), lines: dir });
107
+ }
108
+
109
+ // Any comment lines that weren't attached to an import belong to the body.
110
+ const bodyLines = [...pending, ...lines.slice(i)];
111
+
112
+ units.sort((a, b) =>
113
+ a.group !== b.group
114
+ ? a.group - b.group
115
+ : a.key < b.key
116
+ ? -1
117
+ : a.key > b.key
118
+ ? 1
119
+ : 0,
120
+ );
121
+
122
+ // Rebuild with a blank line between distinct groups.
123
+ const rebuilt = [];
124
+ let lastGroup = -1;
125
+ for (const u of units) {
126
+ if (lastGroup !== -1 && u.group !== lastGroup) rebuilt.push('');
127
+ rebuilt.push(...u.lines);
128
+ lastGroup = u.group;
129
+ }
130
+
131
+ const out = [...prefix, ...rebuilt];
132
+ if (bodyLines.length && bodyLines[0].trim() !== '') out.push('');
133
+ out.push(...bodyLines);
134
+
135
+ const newContent = out.join('\n');
136
+ if (newContent === original) return { changed: false, content: original };
137
+ return { changed: true, content: newContent };
138
+ }
139
+
140
+ function walkDartFiles(dir) {
141
+ const out = [];
142
+ let entries;
143
+ try {
144
+ entries = fs.readdirSync(dir, { withFileTypes: true });
145
+ } catch {
146
+ return out;
147
+ }
148
+ for (const entry of entries) {
149
+ const full = path.join(dir, entry.name);
150
+ if (entry.isDirectory()) {
151
+ if (['build', '.dart_tool', 'node_modules', '.git'].includes(entry.name)) {
152
+ continue;
153
+ }
154
+ out.push(...walkDartFiles(full));
155
+ } else if (
156
+ entry.isFile() &&
157
+ entry.name.endsWith('.dart') &&
158
+ !entry.name.endsWith('.g.dart') &&
159
+ !entry.name.endsWith('.freezed.dart')
160
+ ) {
161
+ out.push(full);
162
+ }
163
+ }
164
+ return out;
165
+ }
166
+
167
+ /**
168
+ * Sorts directives in every .dart file under the given directories (in place).
169
+ * Returns the number of files changed. Never throws on a single bad file.
170
+ */
171
+ function sortImportsInDirs(dirs) {
172
+ let changed = 0;
173
+ for (const dir of dirs) {
174
+ if (!fs.existsSync(dir)) continue;
175
+ for (const file of walkDartFiles(dir)) {
176
+ try {
177
+ const original = fs.readFileSync(file, 'utf8');
178
+ const result = processContent(original);
179
+ if (result.changed) {
180
+ fs.writeFileSync(file, result.content, 'utf8');
181
+ changed++;
182
+ }
183
+ } catch {
184
+ // skip unreadable/odd files — sorting is best-effort cosmetics
185
+ }
186
+ }
187
+ }
188
+ return changed;
189
+ }
190
+
191
+ module.exports = { sortImportsInDirs, processContent };
@@ -37,7 +37,7 @@ const TEMPLATE_STRINGS = {
37
37
  revenuecatProd: '# Production keys — auto-used on physical devices',
38
38
  sentry: '# Sentry (prod only)',
39
39
  mixpanel: '# Mixpanel',
40
- llmChat: '# LLM Chat — Cloud/Edge Function endpoint (API key stays on the server, not here)',
40
+ aiChat: '# AI Chat — Cloud/Edge Function endpoint (API key stays on the server, not here)',
41
41
  },
42
42
  },
43
43
  pt: {
@@ -71,7 +71,7 @@ const TEMPLATE_STRINGS = {
71
71
  revenuecatProd: '# Chaves de produção — usadas automaticamente em dispositivo físico',
72
72
  sentry: '# Sentry (apenas prod)',
73
73
  mixpanel: '# Mixpanel',
74
- llmChat: '# LLM Chat — endpoint da Cloud/Edge Function (a chave de API fica no servidor, não aqui)',
74
+ aiChat: '# AI Chat — endpoint da Cloud/Edge Function (a chave de API fica no servidor, não aqui)',
75
75
  },
76
76
  },
77
77
  es: {
@@ -105,7 +105,7 @@ const TEMPLATE_STRINGS = {
105
105
  revenuecatProd: '# Claves de producción — se usan automáticamente en dispositivo físico',
106
106
  sentry: '# Sentry (solo prod)',
107
107
  mixpanel: '# Mixpanel',
108
- llmChat: '# LLM Chat — endpoint de Cloud/Edge Function (la clave de API queda en el servidor, no aquí)',
108
+ aiChat: '# AI Chat — endpoint de Cloud/Edge Function (la clave de API queda en el servidor, no aquí)',
109
109
  },
110
110
  },
111
111
  };
@@ -8,9 +8,9 @@ const { promptOpenBrowser } = require('./browser');
8
8
 
9
9
  const execAsync = promisify(exec);
10
10
 
11
- // Timeout para verificar se uma ferramenta está instalada (15 s é mais que suficiente)
11
+ // Timeout to check whether a tool is installed (15 s is more than enough)
12
12
  const TOOL_CHECK_TIMEOUT = 15_000;
13
- // Timeout para instalação automática de ferramentas (5 min)
13
+ // Timeout for automatic tool installation (5 min)
14
14
  const INSTALL_TIMEOUT = 300_000;
15
15
  const MAX_BUFFER = 50 * 1024 * 1024;
16
16
 
@@ -43,7 +43,7 @@ module.exports = {
43
43
  'cli.command.setup.langName': 'lang',
44
44
  'cli.command.setup.langOption': 'Prompt language (en, pt, es)',
45
45
  'cli.command.setup.backendOption': 'Backend adapter (firebase, supabase, api)',
46
- 'cli.command.setup.featuresOption': 'Comma separated optional features (web,widget,llm_chat,revenuecat,ci)',
46
+ 'cli.command.setup.featuresOption': 'Comma separated optional features (web,widget,ai_chat,revenuecat,ci)',
47
47
  'cli.command.help.paramName': 'command',
48
48
  'cli.command.doctor.description': 'Check if your computer is ready to run Kasy',
49
49
  'cli.command.modules.description': 'Show what comes included and what you can add',
@@ -109,15 +109,15 @@ module.exports = {
109
109
  'modules.backend.supabase.description': 'Supabase backend adapter',
110
110
  'modules.backend.api.description': 'REST/GraphQL API backend adapter',
111
111
  'modules.feature.sentry.description': 'Sentry error tracking and crash reporting',
112
- 'modules.feature.analytics.description': 'Analytics event tracking (Firebase Analytics)',
112
+ 'modules.feature.analytics.description': 'Analytics event tracking (Mixpanel)',
113
113
  'modules.feature.facebook.description': 'Facebook Login and Meta Ads event tracking (always bundled together)',
114
114
  'modules.feature.revenuecat.description': 'Enables real in-app payments on the Subscriptions screen',
115
115
  'modules.feature.onboarding.description': 'Welcome flow shown on first launch',
116
116
  'modules.feature.web.description': 'Web/PWA support',
117
117
  'modules.feature.widget.description': 'iOS/Android home screen widget integration',
118
- 'modules.feature.llm_chat.description': 'AI chat screen with OpenAI or Gemini',
118
+ 'modules.feature.ai_chat.description': 'AI chat screen with OpenAI or Gemini',
119
119
  'modules.feature.feedback.description': 'In-app feature requests and voting',
120
- 'modules.feature.local_notifications.description': 'Local reminders scheduled by the user (no server required)',
120
+ 'modules.feature.local_reminders.description': 'Local reminders scheduled by the user (no server required)',
121
121
  'modules.feature.ci.description': 'CI/CD: GitHub/GitLab (tests + build) + Codemagic (publish to stores)',
122
122
  'checks.checking': 'Checking {name}...',
123
123
  'checks.found': '{name} found',
@@ -268,6 +268,9 @@ module.exports = {
268
268
  'new.supabase.created': 'Project created successfully.',
269
269
  'new.supabase.createFailed': 'Could not create project',
270
270
  'new.supabase.loginHint': 'Run: supabase login. Then enter your existing project URL and key below.',
271
+ 'new.supabase.createFailed.freeLimit': 'Your Supabase free plan reached the project limit for this organization.',
272
+ 'new.supabase.freeLimit.title': 'How to unblock',
273
+ 'new.supabase.freeLimit.options': '• Delete a project you no longer use\n• Pick another organization (if you have more than one)\n• Or upgrade your plan in the Supabase dashboard\nThen run kasy new again.',
271
274
  'new.supabase.setup': 'Linking project and deploying…',
272
275
  'new.supabase.setupManual': 'Run manually: supabase link, supabase db push, supabase functions deploy',
273
276
  'new.supabase.passwordSaved': 'Database password auto-generated and saved to .kasy/supabase.json (gitignored).',
@@ -345,8 +348,10 @@ module.exports = {
345
348
  'configure.section.sentry': 'Sentry (Crash Reports)',
346
349
  'configure.section.mixpanel': 'Mixpanel (Analytics)',
347
350
  'configure.section.revenuecat': 'RevenueCat (Subscriptions)',
351
+ 'configure.section.stripe': 'Stripe (Web Payments)',
352
+ 'configure.stripe.apiNote': 'API backend: set STRIPE_SECRET_KEY + STRIPE_WEBHOOK_SECRET on your own server (see Stripe-Guia.md). The CLI cannot store them for you.',
348
353
  'configure.section.facebook': 'Facebook (Login + Ads)',
349
- 'configure.section.llmChat': 'AI Chat (LLM)',
354
+ 'configure.section.aiChat': 'AI Chat',
350
355
  'configure.savedFacebook': 'Facebook credentials written to Info.plist and strings.xml.',
351
356
  'configure.facebookPlistMissing': 'ios/Runner/Info.plist not found — Facebook iOS was not updated.',
352
357
  'configure.facebookStringsMissing': 'android/.../strings.xml not found — Facebook Android was not updated.',
@@ -501,7 +506,13 @@ module.exports = {
501
506
  'doctor.revenuecat.prefixMismatch': 'Key has wrong prefix: {key} should start with {expected}',
502
507
  'doctor.revenuecat.keysTest': 'Only Test Store keys (test_) configured — store releases require appl_/goog_, otherwise the app crashes',
503
508
  'doctor.revenuecat.webhookUrlSupabase': 'Webhook URL (paste in RevenueCat → Integrations → Webhooks)',
504
- 'doctor.revenuecat.webhookUrlFirebase': 'Webhook URL: Firebase Console → Functions → subscriptionsOnRcPremiumUpdate',
509
+ 'doctor.revenuecat.webhookUrlFirebase': 'Webhook URL: Firebase Console → Functions → subscriptions-revenuecatWebhook',
510
+ 'doctor.stripe.title': 'Stripe (Web Payments)',
511
+ 'doctor.stripe.serverSide': 'Server-side only — no Stripe key ships in the app (hosted Checkout).',
512
+ 'doctor.stripe.secretsFirebase': 'Set STRIPE_SECRET_KEY + STRIPE_WEBHOOK_SECRET via `kasy configure stripe`, then `kasy deploy`.',
513
+ 'doctor.stripe.secretsSupabase': 'Secrets set with `supabase secrets set` (done at `kasy new` if provided).',
514
+ 'doctor.stripe.secretsApi': 'Configure STRIPE_SECRET_KEY + STRIPE_WEBHOOK_SECRET on your own server (see Stripe-Guia.md).',
515
+ 'doctor.stripe.webhookUrl': 'Stripe webhook URL (add in Stripe → Developers → Webhooks)',
505
516
 
506
517
  'update.iosRelease.success': 'iOS release files updated',
507
518
  'add.iosRelease.success': 'iOS release files added',
@@ -548,14 +559,15 @@ module.exports = {
548
559
  'new.modules.header.feedback': '── Feedback (Firebase + Supabase) ──',
549
560
  'new.modules.header.ci': '── CI/CD ──',
550
561
  'new.modules.header.monetization': '── Monetization ──',
551
- 'new.firebase.module.revenuecat': '💰 RevenueCat (enables Subscriptions)',
562
+ 'new.firebase.module.revenuecat': '💰 RevenueCat (mobile subscriptions)',
563
+ 'new.firebase.module.stripe': '🌐 Stripe (web subscriptions)',
552
564
  'new.firebase.module.sentry': '🚨 Crash Reports (Sentry)',
553
565
  'new.firebase.module.analytics': '📊 Analytics (Mixpanel)',
554
566
  'new.firebase.module.facebook': '👤 Facebook (Login + Ads)',
555
567
  'new.firebase.module.web': '🌐 Web Support (PWA)',
556
568
  'new.firebase.module.widget': '📱 Home Widget (iOS/Android)',
557
- 'new.firebase.module.llm_chat': '🤖 AI Chat (OpenAI/Gemini)',
558
- 'new.firebase.module.local_notifications': '🔔 Local Reminders (no server)',
569
+ 'new.firebase.module.ai_chat': '🤖 AI Chat (OpenAI/Gemini)',
570
+ 'new.firebase.module.local_reminders': '🔔 Local Reminders (no server)',
559
571
  'new.firebase.module.feedback': '💬 Feature Requests (requires Firebase or Supabase)',
560
572
  'new.firebase.module.ci': '⚙️ CI/CD (GitHub + Codemagic)',
561
573
  'new.firebase.module.onboarding': '👋 Onboarding (welcome flow)',
@@ -579,10 +591,12 @@ module.exports = {
579
591
  'new.firebase.q.revenuecat.ios': 'RevenueCat API key for iOS',
580
592
  'new.firebase.q.paywall': 'Which paywall style?',
581
593
  'new.firebase.q.paywall.hint': 'Layout of the subscription screen — you can change it later in RevenueCat',
582
- 'new.firebase.q.revenuecat.web': 'Enable subscriptions on web (RevenueCat Web Billing)?',
583
- 'new.firebase.q.revenuecat.web.hint': 'Requires Web Billing setup in RevenueCat dashboard + Stripe. Leave unchecked if not needed.',
584
- 'new.firebase.q.revenuecat.webKey': 'RevenueCat Web Billing API key (rcb_xxx or rcb_sb_xxx, optional — configure later)',
585
- 'new.firebase.success.revenuecatWeb': ' RevenueCat Web: add RC_WEB_API_KEY (launch.json) for web subscriptions',
594
+ 'new.firebase.q.stripe.secretKey': 'Stripe Secret Key (sk_test_… / sk_live_…) — optional, configure later',
595
+ 'new.firebase.q.stripe.webhookSecret': 'Stripe Webhook Signing Secret (whsec_…) optional, configure later',
596
+ 'new.firebase.q.stripe.webhookSecret.hint': 'From Stripe Developers Webhooks your endpoint',
597
+ 'new.firebase.q.stripe.webhookSecret.invalid': 'Webhook signing secret must start with whsec_.',
598
+ 'new.firebase.q.stripe.productId': 'Stripe Product ID (prod_…) — optional, limits the paywall to one product',
599
+ 'new.firebase.q.stripe.productId.hint': 'Leave blank to list all active recurring prices',
586
600
  'new.firebase.q.sentry.dsn': 'Sentry DSN (leave blank to configure later)',
587
601
  'new.firebase.q.sentry.dsn.invalid': 'Invalid DSN. Expected format: https://key@host/project-id',
588
602
  'new.firebase.q.mixpanel.token': 'Mixpanel Token (leave blank to configure later)',
@@ -594,7 +608,6 @@ module.exports = {
594
608
  'new.firebase.q.revenuecat.android.required': 'RevenueCat Android key is required.',
595
609
  'new.firebase.q.revenuecat.ios.required': 'RevenueCat iOS key is required.',
596
610
  'new.firebase.q.revenuecat.metaDataset.invalid': 'Pixel ID must be numeric (e.g. 1234567890).',
597
- 'new.firebase.q.revenuecat.webKey.invalid': 'Web Billing key must start with rcb_ (e.g. rcb_sb_xxx or rcb_xxx).',
598
611
 
599
612
  'new.firebase.confirm.title': 'Configuration summary:',
600
613
  'new.firebase.confirm.app': 'App',
@@ -707,6 +720,8 @@ module.exports = {
707
720
  'new.outdated.upgraded': 'kasy updated! Run kasy new again.',
708
721
  'new.success.title': 'Project created successfully!',
709
722
  'new.success.featuresInstalled': 'Features enabled:',
723
+ 'new.success.bundleId': 'App identifier (bundle ID)',
724
+ 'new.success.bundleId.hint': "Your app's unique identifier on Android, iOS and Firebase (push).",
710
725
  'new.success.nextSteps': 'Next steps:',
711
726
  'new.success.step.cd': 'Go to your project folder:',
712
727
  'new.success.step.deploy': 'Push the server to Firebase (DB + functions):',
@@ -916,7 +931,7 @@ module.exports = {
916
931
  'notifications.error.notKasyProject': 'No kit_setup.json found. Run this command from inside a Kasy project.',
917
932
  'notifications.error.noI18n': 'lib/i18n/*.i18n.json not found in this project.',
918
933
  'notifications.error.noFeatures': 'lib/core/config/features.dart not found.',
919
- 'notifications.error.notEnabled': 'Local notifications are disabled. Run: kasy add local_notifications',
934
+ 'notifications.error.notEnabled': 'Local notifications are disabled. Run: kasy add local_reminders',
920
935
  'notifications.error.cancelled': 'Cancelled.',
921
936
  'notifications.prompt.intro': 'Local notification texts',
922
937
  'notifications.prompt.hint': 'Home demo = instant test from Features. Reminder = scheduled alert from Settings.',
@@ -959,26 +974,26 @@ module.exports = {
959
974
  // Legacy keys — kept for compatibility with old scripts.
960
975
  'add.prompt.rcAndroidKey': 'RevenueCat Android API key (leave blank to configure later):',
961
976
  'add.prompt.rcIosKey': 'RevenueCat iOS API key (leave blank to configure later):',
962
- 'add.note.facebook': 'Add your Facebook App ID and token in .vscode/launch.json (FB_APP_ID, FB_TOKEN).',
963
- 'new.q.llm_chat.configureNow': 'Configure the LLM Chat agent now?',
964
- 'new.q.llm_chat.configureNow.hint': 'You can skip and run "kasy add llm_chat" later',
965
- 'add.llm_chat.reconfigure': 'Feature already active — reconfiguring credentials only.',
966
- 'add.prompt.llmProvider': 'LLM provider:',
967
- 'add.prompt.llmSystemPrompt': 'Agent system prompt (leave blank for none):\n Example: "You are a support assistant for the Fitsync app. Only answer about workouts."\n >',
968
- 'add.prompt.llmApiKey': 'API key (OpenAI or Gemini) — stored as server secret, never in the app (leave blank to set later):',
969
- 'add.prompt.llmEndpoint': 'Your LLM endpoint URL (leave blank to configure later):',
970
- 'add.llm_chat.settingSecret': 'Storing API key as server secret...',
971
- 'add.llm_chat.secretSet': 'API key stored as secret',
972
- 'add.llm_chat.secretFailed': 'Could not set secret automatically — set it manually (see instructions below)',
973
- 'add.llm_chat.skipSecret': 'API key skipped — set it later via the server CLI before deploying',
974
- 'add.llm_chat.deploying': 'Deploying LLM function to server...',
975
- 'add.llm_chat.deployed': 'LLM function deployed successfully',
976
- 'add.llm_chat.deployFailed': 'Auto-deploy failed — deploy manually (see instructions below)',
977
- 'add.llm_chat.nextSteps.firebase': '\n Next steps:\n 1. The LLM_CHAT_ENDPOINT in .vscode/launch.json has been pre-filled.\n 2. Run the app: kasy run\n',
978
- 'add.llm_chat.nextSteps.firebase.deployFailed': '\n Next steps:\n 1. Deploy manually: firebase deploy --only functions:llmChat\n 2. The LLM_CHAT_ENDPOINT in .vscode/launch.json has been pre-filled.\n 3. Run the app: kasy run\n',
979
- 'add.llm_chat.nextSteps.supabase': '\n Next steps:\n 1. The LLM_CHAT_ENDPOINT in .vscode/launch.json has been pre-filled.\n 2. Run the app: kasy run\n',
980
- 'add.llm_chat.nextSteps.supabase.deployFailed': '\n Next steps:\n 1. Deploy manually: supabase functions deploy llm-chat --no-verify-jwt\n 2. The LLM_CHAT_ENDPOINT in .vscode/launch.json has been pre-filled.\n 3. Run the app: kasy run\n',
981
- 'add.llm_chat.nextSteps.api': '\n Next steps:\n 1. Create an endpoint on your server that accepts {message, history} and calls your LLM.\n 2. Update LLM_CHAT_ENDPOINT in .vscode/launch.json with your endpoint URL.\n 3. Run the app: kasy run\n',
977
+ 'add.note.facebook': 'Add your Facebook App ID and token in .vscode/launch.json (FB_APP_ID, FB_CLIENT_TOKEN).',
978
+ 'new.q.ai_chat.configureNow': 'Configure the AI Chat agent now?',
979
+ 'new.q.ai_chat.configureNow.hint': 'You can skip and run "kasy add ai_chat" later',
980
+ 'add.ai_chat.reconfigure': 'Feature already active — reconfiguring credentials only.',
981
+ 'add.prompt.aiProvider': 'AI provider:',
982
+ 'add.prompt.aiSystemPrompt': 'Agent system prompt (leave blank for none):\n Example: "You are a support assistant for the Fitsync app. Only answer about workouts."\n >',
983
+ 'add.prompt.aiApiKey': 'API key (OpenAI or Gemini) — stored as server secret, never in the app (leave blank to set later):',
984
+ 'add.prompt.aiEndpoint': 'Your AI endpoint URL (leave blank to configure later):',
985
+ 'add.ai_chat.settingSecret': 'Storing API key as server secret...',
986
+ 'add.ai_chat.secretSet': 'API key stored as secret',
987
+ 'add.ai_chat.secretFailed': 'Could not set secret automatically — set it manually (see instructions below)',
988
+ 'add.ai_chat.skipSecret': 'API key skipped — set it later via the server CLI before deploying',
989
+ 'add.ai_chat.deploying': 'Deploying AI function to server...',
990
+ 'add.ai_chat.deployed': 'AI function deployed successfully',
991
+ 'add.ai_chat.deployFailed': 'Auto-deploy failed — deploy manually (see instructions below)',
992
+ 'add.ai_chat.nextSteps.firebase': '\n Next steps:\n 1. The AI_CHAT_ENDPOINT in .vscode/launch.json has been pre-filled.\n 2. Run the app: kasy run\n',
993
+ 'add.ai_chat.nextSteps.firebase.deployFailed': '\n Next steps:\n 1. Deploy manually: firebase deploy --only functions:aiChat\n 2. The AI_CHAT_ENDPOINT in .vscode/launch.json has been pre-filled.\n 3. Run the app: kasy run\n',
994
+ 'add.ai_chat.nextSteps.supabase': '\n Next steps:\n 1. The AI_CHAT_ENDPOINT in .vscode/launch.json has been pre-filled.\n 2. Run the app: kasy run\n',
995
+ 'add.ai_chat.nextSteps.supabase.deployFailed': '\n Next steps:\n 1. Deploy manually: supabase functions deploy ai-chat --no-verify-jwt\n 2. The AI_CHAT_ENDPOINT in .vscode/launch.json has been pre-filled.\n 3. Run the app: kasy run\n',
996
+ 'add.ai_chat.nextSteps.api': '\n Next steps:\n 1. Create an endpoint on your server that accepts {message, history} and calls your AI.\n 2. Update AI_CHAT_ENDPOINT in .vscode/launch.json with your endpoint URL.\n 3. Run the app: kasy run\n',
982
997
  'cli.command.remove.description': 'Remove a feature you no longer use (e.g.: kasy remove sentry)',
983
998
  'remove.error.noModule': 'Provide a feature name. Usage: kasy remove <feature>',
984
999
  'remove.error.notKasyProject': 'No kit_setup.json found. Run this command from inside a Kasy project.',
@@ -43,7 +43,7 @@ module.exports = {
43
43
  'cli.command.setup.langName': 'idioma',
44
44
  'cli.command.setup.langOption': 'Idioma de prompts (en, pt, es)',
45
45
  'cli.command.setup.backendOption': 'Adapter de backend (firebase, supabase, api)',
46
- 'cli.command.setup.featuresOption': 'Features opcionales separadas por coma (web,widget,llm_chat,revenuecat,ci)',
46
+ 'cli.command.setup.featuresOption': 'Features opcionales separadas por coma (web,widget,ai_chat,revenuecat,ci)',
47
47
  'cli.command.help.paramName': 'comando',
48
48
  'cli.command.doctor.description': 'Verifica si tu computadora está lista para correr Kasy',
49
49
  'cli.command.modules.description': 'Muestra lo que viene incluido y lo que puedes añadir',
@@ -109,15 +109,15 @@ module.exports = {
109
109
  'modules.backend.supabase.description': 'Adapter de backend Supabase',
110
110
  'modules.backend.api.description': 'Adapter de backend API REST/GraphQL',
111
111
  'modules.feature.sentry.description': 'Seguimiento de errores y crashes con Sentry',
112
- 'modules.feature.analytics.description': 'Seguimiento de eventos de analytics (Firebase Analytics)',
112
+ 'modules.feature.analytics.description': 'Seguimiento de eventos de analytics (Mixpanel)',
113
113
  'modules.feature.facebook.description': 'Login de Facebook y seguimiento de eventos Meta Ads (siempre juntos)',
114
114
  'modules.feature.revenuecat.description': 'Habilita pagos reales en la pantalla de Subscriptions',
115
115
  'modules.feature.onboarding.description': 'Flujo de bienvenida mostrado en el primer acceso',
116
116
  'modules.feature.web.description': 'Soporte Web/PWA',
117
117
  'modules.feature.widget.description': 'Widget de pantalla inicial iOS/Android',
118
- 'modules.feature.llm_chat.description': 'Pantalla de chat con IA usando OpenAI o Gemini',
118
+ 'modules.feature.ai_chat.description': 'Pantalla de chat con IA usando OpenAI o Gemini',
119
119
  'modules.feature.feedback.description': 'Solicitudes y votacion de features dentro de la app',
120
- 'modules.feature.local_notifications.description': 'Recordatorios locales programados por el usuario (sin servidor)',
120
+ 'modules.feature.local_reminders.description': 'Recordatorios locales programados por el usuario (sin servidor)',
121
121
  'modules.feature.ci.description': 'CI/CD: GitHub/GitLab (tests + build) + Codemagic (publicación en tiendas)',
122
122
  'checks.checking': 'Verificando {name}...',
123
123
  'checks.found': '{name} encontrado',
@@ -270,6 +270,9 @@ module.exports = {
270
270
  'new.supabase.created': 'Proyecto creado correctamente.',
271
271
  'new.supabase.createFailed': 'No se pudo crear el proyecto',
272
272
  'new.supabase.loginHint': 'Ejecuta: supabase login. Luego ingresa la URL y clave de tu proyecto existente.',
273
+ 'new.supabase.createFailed.freeLimit': 'Tu plan gratis de Supabase alcanzó el límite de proyectos en esta organización.',
274
+ 'new.supabase.freeLimit.title': 'Cómo desbloquear',
275
+ 'new.supabase.freeLimit.options': '• Borra un proyecto que ya no uses\n• Elige otra organización (si tienes más de una)\n• O mejora tu plan en el panel de Supabase\nLuego ejecuta kasy new de nuevo.',
273
276
  'new.supabase.setup': 'Vinculando proyecto y desplegando…',
274
277
  'new.supabase.setupManual': 'Ejecuta manualmente: supabase link, supabase db push, supabase functions deploy',
275
278
  'new.supabase.passwordSaved': 'Contraseña de la base generada y guardada en .kasy/supabase.json (gitignored).',
@@ -347,8 +350,10 @@ module.exports = {
347
350
  'configure.section.sentry': 'Sentry (Crash Reports)',
348
351
  'configure.section.mixpanel': 'Mixpanel (Analytics)',
349
352
  'configure.section.revenuecat': 'RevenueCat (Suscripciones)',
353
+ 'configure.section.stripe': 'Stripe (Pagos en Web)',
354
+ 'configure.stripe.apiNote': 'Backend API: configura STRIPE_SECRET_KEY + STRIPE_WEBHOOK_SECRET en tu propio servidor (ver Stripe-Guia.md). La CLI no puede guardarlas.',
350
355
  'configure.section.facebook': 'Facebook (Login + Ads)',
351
- 'configure.section.llmChat': 'AI Chat (LLM)',
356
+ 'configure.section.aiChat': 'AI Chat',
352
357
  'configure.savedFacebook': 'Credenciales de Facebook escritas en Info.plist y strings.xml.',
353
358
  'configure.facebookPlistMissing': 'ios/Runner/Info.plist no encontrado — Facebook iOS no fue actualizado.',
354
359
  'configure.facebookStringsMissing': 'android/.../strings.xml no encontrado — Facebook Android no fue actualizado.',
@@ -503,7 +508,13 @@ module.exports = {
503
508
  'doctor.revenuecat.prefixMismatch': 'Clave con prefijo incorrecto: {key} debe empezar con {expected}',
504
509
  'doctor.revenuecat.keysTest': 'Solo claves Test Store (test_) configuradas — los releases en la tienda requieren appl_/goog_, sino el app crashea',
505
510
  'doctor.revenuecat.webhookUrlSupabase': 'URL del webhook (pega en RevenueCat → Integrations → Webhooks)',
506
- 'doctor.revenuecat.webhookUrlFirebase': 'URL del webhook: Firebase Console → Functions → subscriptionsOnRcPremiumUpdate',
511
+ 'doctor.revenuecat.webhookUrlFirebase': 'URL del webhook: Firebase Console → Functions → subscriptions-revenuecatWebhook',
512
+ 'doctor.stripe.title': 'Stripe (Pagos en Web)',
513
+ 'doctor.stripe.serverSide': 'Solo en el servidor — ninguna clave Stripe va en la app (Checkout alojado).',
514
+ 'doctor.stripe.secretsFirebase': 'Define STRIPE_SECRET_KEY + STRIPE_WEBHOOK_SECRET con `kasy configure stripe`, luego `kasy deploy`.',
515
+ 'doctor.stripe.secretsSupabase': 'Secrets con `supabase secrets set` (hecho en `kasy new` si se proporcionan).',
516
+ 'doctor.stripe.secretsApi': 'Configura STRIPE_SECRET_KEY + STRIPE_WEBHOOK_SECRET en tu servidor (ver Stripe-Guia.md).',
517
+ 'doctor.stripe.webhookUrl': 'URL del webhook Stripe (agrega en Stripe → Developers → Webhooks)',
507
518
 
508
519
  'update.iosRelease.success': 'Archivos de release iOS actualizados',
509
520
  'add.iosRelease.success': 'Archivos de release iOS agregados',
@@ -548,14 +559,15 @@ module.exports = {
548
559
  'new.modules.header.feedback': '── Feedback (Firebase + Supabase) ──',
549
560
  'new.modules.header.ci': '── CI/CD ──',
550
561
  'new.modules.header.monetization': '── Monetizacion ──',
551
- 'new.firebase.module.revenuecat': '💰 RevenueCat (activa Subscriptions)',
562
+ 'new.firebase.module.revenuecat': '💰 RevenueCat (suscripciones móvil)',
563
+ 'new.firebase.module.stripe': '🌐 Stripe (suscripciones en web)',
552
564
  'new.firebase.module.sentry': '🚨 Crash Reports (Sentry)',
553
565
  'new.firebase.module.analytics': '📊 Analytics (Mixpanel)',
554
566
  'new.firebase.module.facebook': '👤 Facebook (Login + Ads)',
555
567
  'new.firebase.module.web': '🌐 Web Support (PWA)',
556
568
  'new.firebase.module.widget': '📱 Home Widget (iOS/Android)',
557
- 'new.firebase.module.llm_chat': '🤖 AI Chat (OpenAI/Gemini)',
558
- 'new.firebase.module.local_notifications': '🔔 Local Reminders (sin servidor)',
569
+ 'new.firebase.module.ai_chat': '🤖 AI Chat (OpenAI/Gemini)',
570
+ 'new.firebase.module.local_reminders': '🔔 Local Reminders (sin servidor)',
559
571
  'new.firebase.module.feedback': '💬 Feature Requests (requiere Firebase o Supabase)',
560
572
  'new.firebase.module.ci': '⚙️ CI/CD (GitHub + Codemagic)',
561
573
  'new.firebase.module.onboarding': '👋 Onboarding (flujo de bienvenida)',
@@ -579,10 +591,12 @@ module.exports = {
579
591
  'new.firebase.q.revenuecat.ios': 'Clave API RevenueCat para iOS',
580
592
  'new.firebase.q.paywall': '¿Qué estilo de paywall?',
581
593
  'new.firebase.q.paywall.hint': 'Layout de la pantalla de suscripciones — puedes cambiarlo después en RevenueCat',
582
- 'new.firebase.q.revenuecat.web': '¿Habilitar suscripciones en web (RevenueCat Web Billing)?',
583
- 'new.firebase.q.revenuecat.web.hint': 'Requiere Web Billing en dashboard RevenueCat + Stripe. Deja desmarcado si no necesitas.',
584
- 'new.firebase.q.revenuecat.webKey': 'Clave API RevenueCat Web Billing (rcb_xxx o rcb_sb_xxx, opcional — configurar después)',
585
- 'new.firebase.success.revenuecatWeb': ' RevenueCat Web: agrega RC_WEB_API_KEY (launch.json) para suscripciones en web',
594
+ 'new.firebase.q.stripe.secretKey': 'Stripe Secret Key (sk_test_… / sk_live_…) — opcional, configurar después',
595
+ 'new.firebase.q.stripe.webhookSecret': 'Stripe Webhook Signing Secret (whsec_…) opcional, configurar después',
596
+ 'new.firebase.q.stripe.webhookSecret.hint': 'En Stripe Developers Webhooks tu endpoint',
597
+ 'new.firebase.q.stripe.webhookSecret.invalid': 'El signing secret del webhook debe empezar con whsec_.',
598
+ 'new.firebase.q.stripe.productId': 'Stripe Product ID (prod_…) — opcional, limita el paywall a un producto',
599
+ 'new.firebase.q.stripe.productId.hint': 'Deja en blanco para listar todos los precios recurrentes activos',
586
600
  'new.firebase.q.sentry.dsn': 'DSN de Sentry (deja en blanco para configurar después)',
587
601
  'new.firebase.q.sentry.dsn.invalid': 'DSN inválido. Formato esperado: https://clave@host/project-id',
588
602
  'new.firebase.q.mixpanel.token': 'Token de Mixpanel (deja en blanco para configurar después)',
@@ -594,7 +608,6 @@ module.exports = {
594
608
  'new.firebase.q.revenuecat.android.required': 'Clave Android de RevenueCat es obligatoria.',
595
609
  'new.firebase.q.revenuecat.ios.required': 'Clave iOS de RevenueCat es obligatoria.',
596
610
  'new.firebase.q.revenuecat.metaDataset.invalid': 'Pixel ID debe ser numérico (ej: 1234567890).',
597
- 'new.firebase.q.revenuecat.webKey.invalid': 'La clave Web Billing debe empezar con rcb_ (ej: rcb_sb_xxx o rcb_xxx).',
598
611
 
599
612
  'new.firebase.confirm.title': 'Resumen de configuración:',
600
613
  'new.firebase.confirm.app': 'App',
@@ -707,6 +720,8 @@ module.exports = {
707
720
  'new.outdated.upgraded': '¡kasy actualizado! Ejecuta kasy new nuevamente.',
708
721
  'new.success.title': '¡Proyecto creado con exito!',
709
722
  'new.success.featuresInstalled': 'Recursos activados:',
723
+ 'new.success.bundleId': 'Identificador de la app (bundle ID)',
724
+ 'new.success.bundleId.hint': 'Identificador único de tu app en Android, iOS y Firebase (push).',
710
725
  'new.success.nextSteps': 'Proximos pasos:',
711
726
  'new.success.step.cd': 'Ve a la carpeta del proyecto:',
712
727
  'new.success.step.deploy': 'Sube el servidor a Firebase (DB + funciones):',
@@ -914,7 +929,7 @@ module.exports = {
914
929
  'notifications.error.notKasyProject': 'No se encontro kit_setup.json. Ejecuta dentro de un proyecto Kasy.',
915
930
  'notifications.error.noI18n': 'lib/i18n/*.i18n.json no encontrado en este proyecto.',
916
931
  'notifications.error.noFeatures': 'lib/core/config/features.dart no encontrado.',
917
- 'notifications.error.notEnabled': 'Notificaciones locales desactivadas. Ejecuta: kasy add local_notifications',
932
+ 'notifications.error.notEnabled': 'Notificaciones locales desactivadas. Ejecuta: kasy add local_reminders',
918
933
  'notifications.error.cancelled': 'Cancelado.',
919
934
  'notifications.prompt.intro': 'Textos de notificación local',
920
935
  'notifications.prompt.hint': 'Demo Home = prueba instantanea en Features. Recordatorio = alerta programada en Ajustes.',
@@ -957,26 +972,26 @@ module.exports = {
957
972
  // Legacy keys — kept for compatibility with old scripts.
958
973
  'add.prompt.rcAndroidKey': 'RevenueCat Android API key (deja en blanco para configurar después):',
959
974
  'add.prompt.rcIosKey': 'RevenueCat iOS API key (deja en blanco para configurar después):',
960
- 'add.note.facebook': 'Agrega tu Facebook App ID y token en .vscode/launch.json (FB_APP_ID, FB_TOKEN).',
961
- 'new.q.llm_chat.configureNow': 'Configurar el agente de Chat LLM ahora?',
962
- 'new.q.llm_chat.configureNow.hint': 'Puedes omitir y ejecutar "kasy add llm_chat" después',
963
- 'add.llm_chat.reconfigure': 'Feature ya activa — reconfigurando solo las credenciales.',
964
- 'add.prompt.llmProvider': 'Proveedor de LLM:',
965
- 'add.prompt.llmSystemPrompt': 'Instruccion del agente — system prompt (deja en blanco para ninguna):\n Ejemplo: "Eres un asistente de soporte del app Fitsync. Solo responde sobre entrenamientos."\n >',
966
- 'add.prompt.llmApiKey': 'Clave de API (OpenAI o Gemini) — se guarda en el servidor, nunca en el app (deja en blanco para configurar después):',
967
- 'add.prompt.llmEndpoint': 'URL de tu endpoint LLM (deja en blanco para configurar después):',
968
- 'add.llm_chat.settingSecret': 'Guardando clave de API como secret en el servidor...',
969
- 'add.llm_chat.secretSet': 'Clave de API guardada como secret',
970
- 'add.llm_chat.secretFailed': 'No se pudo guardar el secret automaticamente — configuralo manualmente (ver instrucciones abajo)',
971
- 'add.llm_chat.skipSecret': 'Clave de API omitida — configura antes del deploy via CLI del servidor',
972
- 'add.llm_chat.deploying': 'Desplegando funcion LLM en el servidor...',
973
- 'add.llm_chat.deployed': 'Funcion LLM desplegada con exito',
974
- 'add.llm_chat.deployFailed': 'Deploy automático fallo — despliega manualmente (ver instrucciones abajo)',
975
- 'add.llm_chat.nextSteps.firebase': '\n Proximos pasos:\n 1. El LLM_CHAT_ENDPOINT en .vscode/launch.json ya fue pre-llenado.\n 2. Corre el app: kasy run\n',
976
- 'add.llm_chat.nextSteps.firebase.deployFailed': '\n Proximos pasos:\n 1. Deploy manual: firebase deploy --only functions:llmChat\n 2. El LLM_CHAT_ENDPOINT en .vscode/launch.json ya fue pre-llenado.\n 3. Corre el app: kasy run\n',
977
- 'add.llm_chat.nextSteps.supabase': '\n Proximos pasos:\n 1. El LLM_CHAT_ENDPOINT en .vscode/launch.json ya fue pre-llenado.\n 2. Corre el app: kasy run\n',
978
- 'add.llm_chat.nextSteps.supabase.deployFailed': '\n Proximos pasos:\n 1. Deploy manual: supabase functions deploy llm-chat --no-verify-jwt\n 2. El LLM_CHAT_ENDPOINT en .vscode/launch.json ya fue pre-llenado.\n 3. Corre el app: kasy run\n',
979
- 'add.llm_chat.nextSteps.api': '\n Proximos pasos:\n 1. Crea un endpoint en tu servidor que acepte {message, history} y llame tu LLM.\n 2. Actualiza LLM_CHAT_ENDPOINT en .vscode/launch.json con la URL de tu endpoint.\n 3. Corre el app: kasy run\n',
975
+ 'add.note.facebook': 'Agrega tu Facebook App ID y token en .vscode/launch.json (FB_APP_ID, FB_CLIENT_TOKEN).',
976
+ 'new.q.ai_chat.configureNow': 'Configurar el agente de Chat IA ahora?',
977
+ 'new.q.ai_chat.configureNow.hint': 'Puedes omitir y ejecutar "kasy add ai_chat" después',
978
+ 'add.ai_chat.reconfigure': 'Feature ya activa — reconfigurando solo las credenciales.',
979
+ 'add.prompt.aiProvider': 'Proveedor de IA:',
980
+ 'add.prompt.aiSystemPrompt': 'Instruccion del agente — system prompt (deja en blanco para ninguna):\n Ejemplo: "Eres un asistente de soporte del app Fitsync. Solo responde sobre entrenamientos."\n >',
981
+ 'add.prompt.aiApiKey': 'Clave de API (OpenAI o Gemini) — se guarda en el servidor, nunca en el app (deja en blanco para configurar después):',
982
+ 'add.prompt.aiEndpoint': 'URL de tu endpoint IA (deja en blanco para configurar después):',
983
+ 'add.ai_chat.settingSecret': 'Guardando clave de API como secret en el servidor...',
984
+ 'add.ai_chat.secretSet': 'Clave de API guardada como secret',
985
+ 'add.ai_chat.secretFailed': 'No se pudo guardar el secret automaticamente — configuralo manualmente (ver instrucciones abajo)',
986
+ 'add.ai_chat.skipSecret': 'Clave de API omitida — configura antes del deploy via CLI del servidor',
987
+ 'add.ai_chat.deploying': 'Desplegando funcion IA en el servidor...',
988
+ 'add.ai_chat.deployed': 'Funcion IA desplegada con exito',
989
+ 'add.ai_chat.deployFailed': 'Deploy automático fallo — despliega manualmente (ver instrucciones abajo)',
990
+ 'add.ai_chat.nextSteps.firebase': '\n Proximos pasos:\n 1. El AI_CHAT_ENDPOINT en .vscode/launch.json ya fue pre-llenado.\n 2. Corre el app: kasy run\n',
991
+ 'add.ai_chat.nextSteps.firebase.deployFailed': '\n Proximos pasos:\n 1. Deploy manual: firebase deploy --only functions:aiChat\n 2. El AI_CHAT_ENDPOINT en .vscode/launch.json ya fue pre-llenado.\n 3. Corre el app: kasy run\n',
992
+ 'add.ai_chat.nextSteps.supabase': '\n Proximos pasos:\n 1. El AI_CHAT_ENDPOINT en .vscode/launch.json ya fue pre-llenado.\n 2. Corre el app: kasy run\n',
993
+ 'add.ai_chat.nextSteps.supabase.deployFailed': '\n Proximos pasos:\n 1. Deploy manual: supabase functions deploy ai-chat --no-verify-jwt\n 2. El AI_CHAT_ENDPOINT en .vscode/launch.json ya fue pre-llenado.\n 3. Corre el app: kasy run\n',
994
+ 'add.ai_chat.nextSteps.api': '\n Proximos pasos:\n 1. Crea un endpoint en tu servidor que acepte {message, history} y llame tu IA.\n 2. Actualiza AI_CHAT_ENDPOINT en .vscode/launch.json con la URL de tu endpoint.\n 3. Corre el app: kasy run\n',
980
995
  'cli.command.remove.description': 'Elimina algo que ya no usas (ej: kasy remove sentry)',
981
996
  'remove.error.noModule': 'Ingresa el nombre de la feature. Uso: kasy remove <feature>',
982
997
  'remove.error.notKasyProject': 'kit_setup.json no encontrado. Ejecuta este comando dentro de un proyecto Kasy.',