convex 1.34.1 → 1.35.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 (512) hide show
  1. package/CHANGELOG.md +86 -43
  2. package/dist/browser.bundle.js +8 -2
  3. package/dist/browser.bundle.js.map +3 -3
  4. package/dist/cjs/browser/index-node.js +3 -1
  5. package/dist/cjs/browser/index.js +3 -1
  6. package/dist/cjs/browser/index.js.map +2 -2
  7. package/dist/cjs/browser/query_options.js.map +2 -2
  8. package/dist/cjs/cli/aiFiles.js +31 -13
  9. package/dist/cjs/cli/aiFiles.js.map +3 -3
  10. package/dist/cjs/cli/codegen_templates/readme.js +14 -1
  11. package/dist/cjs/cli/codegen_templates/readme.js.map +2 -2
  12. package/dist/cjs/cli/configure.js +21 -24
  13. package/dist/cjs/cli/configure.js.map +2 -2
  14. package/dist/cjs/cli/deploy.js +7 -8
  15. package/dist/cjs/cli/deploy.js.map +2 -2
  16. package/dist/cjs/cli/deploymentCreate.js +225 -40
  17. package/dist/cjs/cli/deploymentCreate.js.map +3 -3
  18. package/dist/cjs/cli/deploymentSelect.js +14 -13
  19. package/dist/cjs/cli/deploymentSelect.js.map +2 -2
  20. package/dist/cjs/cli/dev.js +30 -11
  21. package/dist/cjs/cli/dev.js.map +2 -2
  22. package/dist/cjs/cli/docs.js +1 -1
  23. package/dist/cjs/cli/docs.js.map +2 -2
  24. package/dist/cjs/cli/init.js +1 -1
  25. package/dist/cjs/cli/init.js.map +2 -2
  26. package/dist/cjs/cli/lib/aiFiles/agentsmd.js +14 -10
  27. package/dist/cjs/cli/lib/aiFiles/agentsmd.js.map +2 -2
  28. package/dist/cjs/cli/lib/aiFiles/claudemd.js +14 -10
  29. package/dist/cjs/cli/lib/aiFiles/claudemd.js.map +2 -2
  30. package/dist/cjs/cli/lib/aiFiles/guidelinesmd.js +10 -3
  31. package/dist/cjs/cli/lib/aiFiles/guidelinesmd.js.map +2 -2
  32. package/dist/cjs/cli/lib/aiFiles/index.js +70 -86
  33. package/dist/cjs/cli/lib/aiFiles/index.js.map +3 -3
  34. package/dist/cjs/cli/lib/aiFiles/skills.js +28 -12
  35. package/dist/cjs/cli/lib/aiFiles/skills.js.map +2 -2
  36. package/dist/cjs/cli/lib/aiFiles/state.js +96 -0
  37. package/dist/cjs/cli/lib/aiFiles/state.js.map +7 -0
  38. package/dist/cjs/cli/lib/aiFiles/status.js +31 -28
  39. package/dist/cjs/cli/lib/aiFiles/status.js.map +2 -2
  40. package/dist/cjs/cli/lib/aiFiles/utils.js +31 -14
  41. package/dist/cjs/cli/lib/aiFiles/utils.js.map +2 -2
  42. package/dist/cjs/cli/lib/api.js +70 -7
  43. package/dist/cjs/cli/lib/api.js.map +2 -2
  44. package/dist/cjs/cli/lib/command.js +4 -5
  45. package/dist/cjs/cli/lib/command.js.map +2 -2
  46. package/dist/cjs/cli/lib/config.js +41 -4
  47. package/dist/cjs/cli/lib/config.js.map +3 -3
  48. package/dist/cjs/cli/lib/deploy2.js +9 -26
  49. package/dist/cjs/cli/lib/deploy2.js.map +2 -2
  50. package/dist/cjs/cli/lib/deployApi/componentDefinition.js +4 -1
  51. package/dist/cjs/cli/lib/deployApi/componentDefinition.js.map +2 -2
  52. package/dist/cjs/cli/lib/deploymentSelection.js +45 -2
  53. package/dist/cjs/cli/lib/deploymentSelection.js.map +2 -2
  54. package/dist/cjs/cli/lib/deploymentSelector.js +1 -0
  55. package/dist/cjs/cli/lib/deploymentSelector.js.map +2 -2
  56. package/dist/cjs/cli/lib/dev.js +162 -117
  57. package/dist/cjs/cli/lib/dev.js.map +2 -2
  58. package/dist/cjs/cli/lib/env.js +1 -13
  59. package/dist/cjs/cli/lib/env.js.map +2 -2
  60. package/dist/cjs/cli/lib/expiration.js +104 -0
  61. package/dist/cjs/cli/lib/expiration.js.map +7 -0
  62. package/dist/cjs/cli/lib/generatedFunctionLogsApi.js.map +1 -1
  63. package/dist/cjs/cli/lib/init.js +4 -3
  64. package/dist/cjs/cli/lib/init.js.map +2 -2
  65. package/dist/cjs/cli/lib/insights.js +1 -1
  66. package/dist/cjs/cli/lib/insights.js.map +2 -2
  67. package/dist/cjs/cli/lib/localDeployment/anonymous.js +14 -7
  68. package/dist/cjs/cli/lib/localDeployment/anonymous.js.map +2 -2
  69. package/dist/cjs/cli/lib/localDeployment/localDeployment.js +8 -10
  70. package/dist/cjs/cli/lib/localDeployment/localDeployment.js.map +2 -2
  71. package/dist/cjs/cli/lib/localDeployment/run.js +1 -0
  72. package/dist/cjs/cli/lib/localDeployment/run.js.map +2 -2
  73. package/dist/cjs/cli/lib/localDeployment/upgrade.js +2 -2
  74. package/dist/cjs/cli/lib/localDeployment/upgrade.js.map +2 -2
  75. package/dist/cjs/cli/lib/localDeployment/utils.js +9 -0
  76. package/dist/cjs/cli/lib/localDeployment/utils.js.map +2 -2
  77. package/dist/cjs/cli/lib/mcp/tools/status.js +1 -1
  78. package/dist/cjs/cli/lib/mcp/tools/status.js.map +2 -2
  79. package/dist/cjs/cli/lib/updates.js +8 -9
  80. package/dist/cjs/cli/lib/updates.js.map +2 -2
  81. package/dist/cjs/cli/lib/usage.js +2 -1
  82. package/dist/cjs/cli/lib/usage.js.map +2 -2
  83. package/dist/cjs/cli/lib/utils/prompts.js +2 -1
  84. package/dist/cjs/cli/lib/utils/prompts.js.map +2 -2
  85. package/dist/cjs/cli/lib/utils/utils.js +46 -20
  86. package/dist/cjs/cli/lib/utils/utils.js.map +3 -3
  87. package/dist/cjs/index.js +1 -1
  88. package/dist/cjs/index.js.map +1 -1
  89. package/dist/cjs/react/client.js +43 -6
  90. package/dist/cjs/react/client.js.map +2 -2
  91. package/dist/cjs/react/index.js +2 -0
  92. package/dist/cjs/react/index.js.map +2 -2
  93. package/dist/cjs/react-clerk/ConvexProviderWithClerk.js.map +1 -1
  94. package/dist/cjs/server/api.js.map +2 -2
  95. package/dist/cjs/server/components/definition.js.map +1 -1
  96. package/dist/cjs/server/components/index.js +40 -4
  97. package/dist/cjs/server/components/index.js.map +2 -2
  98. package/dist/cjs/server/data_model.js.map +1 -1
  99. package/dist/cjs/server/impl/meta_impl.js +78 -0
  100. package/dist/cjs/server/impl/meta_impl.js.map +7 -0
  101. package/dist/cjs/server/impl/registration_impl.js +16 -11
  102. package/dist/cjs/server/impl/registration_impl.js.map +2 -2
  103. package/dist/cjs/server/index.js.map +2 -2
  104. package/dist/cjs/server/meta.js +17 -0
  105. package/dist/cjs/server/meta.js.map +7 -0
  106. package/dist/cjs/server/registration.js.map +1 -1
  107. package/dist/cjs-types/browser/index.d.ts +1 -0
  108. package/dist/cjs-types/browser/index.d.ts.map +1 -1
  109. package/dist/cjs-types/browser/query_options.d.ts +12 -9
  110. package/dist/cjs-types/browser/query_options.d.ts.map +1 -1
  111. package/dist/cjs-types/cli/aiFiles.d.ts.map +1 -1
  112. package/dist/cjs-types/cli/codegen_templates/readme.d.ts.map +1 -1
  113. package/dist/cjs-types/cli/configure.d.ts.map +1 -1
  114. package/dist/cjs-types/cli/configure.test.d.ts +2 -0
  115. package/dist/cjs-types/cli/configure.test.d.ts.map +1 -0
  116. package/dist/cjs-types/cli/deploy.d.ts.map +1 -1
  117. package/dist/cjs-types/cli/deploymentCreate.d.ts +1 -0
  118. package/dist/cjs-types/cli/deploymentCreate.d.ts.map +1 -1
  119. package/dist/cjs-types/cli/deploymentSelect.d.ts +2 -1
  120. package/dist/cjs-types/cli/deploymentSelect.d.ts.map +1 -1
  121. package/dist/cjs-types/cli/dev.d.ts +3 -1
  122. package/dist/cjs-types/cli/dev.d.ts.map +1 -1
  123. package/dist/cjs-types/cli/lib/aiFiles/agentsmd.d.ts +5 -5
  124. package/dist/cjs-types/cli/lib/aiFiles/agentsmd.d.ts.map +1 -1
  125. package/dist/cjs-types/cli/lib/aiFiles/claudemd.d.ts +5 -5
  126. package/dist/cjs-types/cli/lib/aiFiles/claudemd.d.ts.map +1 -1
  127. package/dist/cjs-types/cli/lib/aiFiles/guidelinesmd.d.ts +3 -3
  128. package/dist/cjs-types/cli/lib/aiFiles/guidelinesmd.d.ts.map +1 -1
  129. package/dist/cjs-types/cli/lib/aiFiles/index.d.ts +20 -18
  130. package/dist/cjs-types/cli/lib/aiFiles/index.d.ts.map +1 -1
  131. package/dist/cjs-types/cli/lib/aiFiles/skills.d.ts +6 -4
  132. package/dist/cjs-types/cli/lib/aiFiles/skills.d.ts.map +1 -1
  133. package/dist/cjs-types/cli/lib/aiFiles/state.d.ts +38 -0
  134. package/dist/cjs-types/cli/lib/aiFiles/state.d.ts.map +1 -0
  135. package/dist/cjs-types/cli/lib/aiFiles/state.test.d.ts +2 -0
  136. package/dist/cjs-types/cli/lib/aiFiles/state.test.d.ts.map +1 -0
  137. package/dist/cjs-types/cli/lib/aiFiles/status.d.ts +4 -1
  138. package/dist/cjs-types/cli/lib/aiFiles/status.d.ts.map +1 -1
  139. package/dist/cjs-types/cli/lib/aiFiles/utils.d.ts +13 -3
  140. package/dist/cjs-types/cli/lib/aiFiles/utils.d.ts.map +1 -1
  141. package/dist/cjs-types/cli/lib/aiFiles/utils.test.d.ts +2 -0
  142. package/dist/cjs-types/cli/lib/aiFiles/utils.test.d.ts.map +1 -0
  143. package/dist/cjs-types/cli/lib/api.d.ts +3 -3
  144. package/dist/cjs-types/cli/lib/api.d.ts.map +1 -1
  145. package/dist/cjs-types/cli/lib/command.d.ts +2 -1
  146. package/dist/cjs-types/cli/lib/command.d.ts.map +1 -1
  147. package/dist/cjs-types/cli/lib/config.d.ts +17 -6
  148. package/dist/cjs-types/cli/lib/config.d.ts.map +1 -1
  149. package/dist/cjs-types/cli/lib/deploy2.d.ts +5 -2
  150. package/dist/cjs-types/cli/lib/deploy2.d.ts.map +1 -1
  151. package/dist/cjs-types/cli/lib/deployApi/componentDefinition.d.ts +27 -12
  152. package/dist/cjs-types/cli/lib/deployApi/componentDefinition.d.ts.map +1 -1
  153. package/dist/cjs-types/cli/lib/deployApi/definitionConfig.d.ts +24 -24
  154. package/dist/cjs-types/cli/lib/deployApi/modules.d.ts +14 -14
  155. package/dist/cjs-types/cli/lib/deployApi/startPush.d.ts +61 -52
  156. package/dist/cjs-types/cli/lib/deployApi/startPush.d.ts.map +1 -1
  157. package/dist/cjs-types/cli/lib/deploymentSelection.d.ts.map +1 -1
  158. package/dist/cjs-types/cli/lib/deploymentSelector.d.ts +2 -0
  159. package/dist/cjs-types/cli/lib/deploymentSelector.d.ts.map +1 -1
  160. package/dist/cjs-types/cli/lib/dev.d.ts.map +1 -1
  161. package/dist/cjs-types/cli/lib/env.d.ts +0 -4
  162. package/dist/cjs-types/cli/lib/env.d.ts.map +1 -1
  163. package/dist/cjs-types/cli/lib/expiration.d.ts +35 -0
  164. package/dist/cjs-types/cli/lib/expiration.d.ts.map +1 -0
  165. package/dist/cjs-types/cli/lib/expiration.test.d.ts +2 -0
  166. package/dist/cjs-types/cli/lib/expiration.test.d.ts.map +1 -0
  167. package/dist/cjs-types/cli/lib/generatedFunctionLogsApi.d.ts +16 -1
  168. package/dist/cjs-types/cli/lib/generatedFunctionLogsApi.d.ts.map +1 -1
  169. package/dist/cjs-types/cli/lib/init.d.ts.map +1 -1
  170. package/dist/cjs-types/cli/lib/localDeployment/anonymous.d.ts.map +1 -1
  171. package/dist/cjs-types/cli/lib/localDeployment/localDeployment.d.ts.map +1 -1
  172. package/dist/cjs-types/cli/lib/localDeployment/run.d.ts +15 -0
  173. package/dist/cjs-types/cli/lib/localDeployment/run.d.ts.map +1 -1
  174. package/dist/cjs-types/cli/lib/localDeployment/upgrade.d.ts.map +1 -1
  175. package/dist/cjs-types/cli/lib/localDeployment/utils.d.ts +7 -0
  176. package/dist/cjs-types/cli/lib/localDeployment/utils.d.ts.map +1 -1
  177. package/dist/cjs-types/cli/lib/mcp/requestContext.d.ts +3 -3
  178. package/dist/cjs-types/cli/lib/mcp/tools/insights.d.ts +2 -2
  179. package/dist/cjs-types/cli/lib/updates.d.ts +4 -3
  180. package/dist/cjs-types/cli/lib/updates.d.ts.map +1 -1
  181. package/dist/cjs-types/cli/lib/usage.d.ts.map +1 -1
  182. package/dist/cjs-types/cli/lib/utils/prompts.d.ts +1 -0
  183. package/dist/cjs-types/cli/lib/utils/prompts.d.ts.map +1 -1
  184. package/dist/cjs-types/cli/lib/utils/utils.d.ts +16 -2
  185. package/dist/cjs-types/cli/lib/utils/utils.d.ts.map +1 -1
  186. package/dist/cjs-types/index.d.ts +1 -1
  187. package/dist/cjs-types/react/client.d.ts +54 -2
  188. package/dist/cjs-types/react/client.d.ts.map +1 -1
  189. package/dist/cjs-types/react/index.d.ts +7 -2
  190. package/dist/cjs-types/react/index.d.ts.map +1 -1
  191. package/dist/cjs-types/react/use_query_object_options.test.d.ts +5 -0
  192. package/dist/cjs-types/react/use_query_object_options.test.d.ts.map +1 -0
  193. package/dist/cjs-types/react/use_query_result.test.d.ts +5 -0
  194. package/dist/cjs-types/react/use_query_result.test.d.ts.map +1 -0
  195. package/dist/cjs-types/react-clerk/ConvexProviderWithClerk.d.ts +1 -1
  196. package/dist/cjs-types/server/api.d.ts +5 -1
  197. package/dist/cjs-types/server/api.d.ts.map +1 -1
  198. package/dist/cjs-types/server/components/definition.d.ts +1 -0
  199. package/dist/cjs-types/server/components/definition.d.ts.map +1 -1
  200. package/dist/cjs-types/server/components/index.d.ts +5 -1
  201. package/dist/cjs-types/server/components/index.d.ts.map +1 -1
  202. package/dist/cjs-types/server/data_model.d.ts +2 -1
  203. package/dist/cjs-types/server/data_model.d.ts.map +1 -1
  204. package/dist/cjs-types/server/impl/meta_impl.d.ts +5 -0
  205. package/dist/cjs-types/server/impl/meta_impl.d.ts.map +1 -0
  206. package/dist/cjs-types/server/impl/registration_impl.d.ts.map +1 -1
  207. package/dist/cjs-types/server/index.d.ts +1 -0
  208. package/dist/cjs-types/server/index.d.ts.map +1 -1
  209. package/dist/cjs-types/server/meta.d.ts +72 -0
  210. package/dist/cjs-types/server/meta.d.ts.map +1 -0
  211. package/dist/cjs-types/server/registration.d.ts.map +1 -1
  212. package/dist/cli.bundle.cjs +1670 -1214
  213. package/dist/cli.bundle.cjs.map +4 -4
  214. package/dist/esm/browser/index-node.js +1 -0
  215. package/dist/esm/browser/index.js +1 -0
  216. package/dist/esm/browser/index.js.map +2 -2
  217. package/dist/esm/browser/query_options.js.map +2 -2
  218. package/dist/esm/cli/aiFiles.js +33 -15
  219. package/dist/esm/cli/aiFiles.js.map +2 -2
  220. package/dist/esm/cli/codegen_templates/readme.js +14 -1
  221. package/dist/esm/cli/codegen_templates/readme.js.map +2 -2
  222. package/dist/esm/cli/configure.js +23 -26
  223. package/dist/esm/cli/configure.js.map +2 -2
  224. package/dist/esm/cli/deploy.js +11 -10
  225. package/dist/esm/cli/deploy.js.map +2 -2
  226. package/dist/esm/cli/deploymentCreate.js +238 -42
  227. package/dist/esm/cli/deploymentCreate.js.map +2 -2
  228. package/dist/esm/cli/deploymentSelect.js +13 -12
  229. package/dist/esm/cli/deploymentSelect.js.map +2 -2
  230. package/dist/esm/cli/dev.js +34 -13
  231. package/dist/esm/cli/dev.js.map +2 -2
  232. package/dist/esm/cli/docs.js +1 -1
  233. package/dist/esm/cli/docs.js.map +2 -2
  234. package/dist/esm/cli/init.js +2 -2
  235. package/dist/esm/cli/init.js.map +2 -2
  236. package/dist/esm/cli/lib/aiFiles/agentsmd.js +13 -9
  237. package/dist/esm/cli/lib/aiFiles/agentsmd.js.map +2 -2
  238. package/dist/esm/cli/lib/aiFiles/claudemd.js +13 -9
  239. package/dist/esm/cli/lib/aiFiles/claudemd.js.map +2 -2
  240. package/dist/esm/cli/lib/aiFiles/guidelinesmd.js +12 -5
  241. package/dist/esm/cli/lib/aiFiles/guidelinesmd.js.map +2 -2
  242. package/dist/esm/cli/lib/aiFiles/index.js +72 -89
  243. package/dist/esm/cli/lib/aiFiles/index.js.map +2 -2
  244. package/dist/esm/cli/lib/aiFiles/skills.js +29 -13
  245. package/dist/esm/cli/lib/aiFiles/skills.js.map +2 -2
  246. package/dist/esm/cli/lib/aiFiles/state.js +60 -0
  247. package/dist/esm/cli/lib/aiFiles/state.js.map +7 -0
  248. package/dist/esm/cli/lib/aiFiles/status.js +32 -29
  249. package/dist/esm/cli/lib/aiFiles/status.js.map +2 -2
  250. package/dist/esm/cli/lib/aiFiles/utils.js +25 -10
  251. package/dist/esm/cli/lib/aiFiles/utils.js.map +2 -2
  252. package/dist/esm/cli/lib/api.js +70 -7
  253. package/dist/esm/cli/lib/api.js.map +2 -2
  254. package/dist/esm/cli/lib/command.js +4 -5
  255. package/dist/esm/cli/lib/command.js.map +2 -2
  256. package/dist/esm/cli/lib/config.js +39 -3
  257. package/dist/esm/cli/lib/config.js.map +2 -2
  258. package/dist/esm/cli/lib/deploy2.js +13 -26
  259. package/dist/esm/cli/lib/deploy2.js.map +2 -2
  260. package/dist/esm/cli/lib/deployApi/componentDefinition.js +4 -1
  261. package/dist/esm/cli/lib/deployApi/componentDefinition.js.map +2 -2
  262. package/dist/esm/cli/lib/deploymentSelection.js +46 -2
  263. package/dist/esm/cli/lib/deploymentSelection.js.map +2 -2
  264. package/dist/esm/cli/lib/deploymentSelector.js +1 -0
  265. package/dist/esm/cli/lib/deploymentSelector.js.map +2 -2
  266. package/dist/esm/cli/lib/dev.js +162 -118
  267. package/dist/esm/cli/lib/dev.js.map +2 -2
  268. package/dist/esm/cli/lib/env.js +0 -11
  269. package/dist/esm/cli/lib/env.js.map +2 -2
  270. package/dist/esm/cli/lib/expiration.js +80 -0
  271. package/dist/esm/cli/lib/expiration.js.map +7 -0
  272. package/dist/esm/cli/lib/init.js +4 -3
  273. package/dist/esm/cli/lib/init.js.map +2 -2
  274. package/dist/esm/cli/lib/insights.js +1 -1
  275. package/dist/esm/cli/lib/insights.js.map +2 -2
  276. package/dist/esm/cli/lib/localDeployment/anonymous.js +16 -9
  277. package/dist/esm/cli/lib/localDeployment/anonymous.js.map +2 -2
  278. package/dist/esm/cli/lib/localDeployment/localDeployment.js +9 -11
  279. package/dist/esm/cli/lib/localDeployment/localDeployment.js.map +2 -2
  280. package/dist/esm/cli/lib/localDeployment/run.js +1 -1
  281. package/dist/esm/cli/lib/localDeployment/run.js.map +2 -2
  282. package/dist/esm/cli/lib/localDeployment/upgrade.js +2 -2
  283. package/dist/esm/cli/lib/localDeployment/upgrade.js.map +2 -2
  284. package/dist/esm/cli/lib/localDeployment/utils.js +8 -0
  285. package/dist/esm/cli/lib/localDeployment/utils.js.map +2 -2
  286. package/dist/esm/cli/lib/mcp/tools/status.js +1 -1
  287. package/dist/esm/cli/lib/mcp/tools/status.js.map +2 -2
  288. package/dist/esm/cli/lib/updates.js +11 -9
  289. package/dist/esm/cli/lib/updates.js.map +2 -2
  290. package/dist/esm/cli/lib/usage.js +2 -1
  291. package/dist/esm/cli/lib/usage.js.map +2 -2
  292. package/dist/esm/cli/lib/utils/prompts.js +2 -1
  293. package/dist/esm/cli/lib/utils/prompts.js.map +2 -2
  294. package/dist/esm/cli/lib/utils/utils.js +45 -20
  295. package/dist/esm/cli/lib/utils/utils.js.map +3 -3
  296. package/dist/esm/index.js +1 -1
  297. package/dist/esm/index.js.map +1 -1
  298. package/dist/esm/react/client.js +43 -6
  299. package/dist/esm/react/client.js.map +2 -2
  300. package/dist/esm/react/index.js +1 -0
  301. package/dist/esm/react/index.js.map +2 -2
  302. package/dist/esm/react-clerk/ConvexProviderWithClerk.js.map +1 -1
  303. package/dist/esm/server/api.js.map +2 -2
  304. package/dist/esm/server/components/index.js +40 -4
  305. package/dist/esm/server/components/index.js.map +2 -2
  306. package/dist/esm/server/impl/meta_impl.js +54 -0
  307. package/dist/esm/server/impl/meta_impl.js.map +7 -0
  308. package/dist/esm/server/impl/registration_impl.js +20 -11
  309. package/dist/esm/server/impl/registration_impl.js.map +2 -2
  310. package/dist/esm/server/index.js.map +2 -2
  311. package/dist/esm/server/meta.js +2 -0
  312. package/dist/esm/server/meta.js.map +7 -0
  313. package/dist/esm-types/browser/index.d.ts +1 -0
  314. package/dist/esm-types/browser/index.d.ts.map +1 -1
  315. package/dist/esm-types/browser/query_options.d.ts +12 -9
  316. package/dist/esm-types/browser/query_options.d.ts.map +1 -1
  317. package/dist/esm-types/cli/aiFiles.d.ts.map +1 -1
  318. package/dist/esm-types/cli/codegen_templates/readme.d.ts.map +1 -1
  319. package/dist/esm-types/cli/configure.d.ts.map +1 -1
  320. package/dist/esm-types/cli/configure.test.d.ts +2 -0
  321. package/dist/esm-types/cli/configure.test.d.ts.map +1 -0
  322. package/dist/esm-types/cli/deploy.d.ts.map +1 -1
  323. package/dist/esm-types/cli/deploymentCreate.d.ts +1 -0
  324. package/dist/esm-types/cli/deploymentCreate.d.ts.map +1 -1
  325. package/dist/esm-types/cli/deploymentSelect.d.ts +2 -1
  326. package/dist/esm-types/cli/deploymentSelect.d.ts.map +1 -1
  327. package/dist/esm-types/cli/dev.d.ts +3 -1
  328. package/dist/esm-types/cli/dev.d.ts.map +1 -1
  329. package/dist/esm-types/cli/lib/aiFiles/agentsmd.d.ts +5 -5
  330. package/dist/esm-types/cli/lib/aiFiles/agentsmd.d.ts.map +1 -1
  331. package/dist/esm-types/cli/lib/aiFiles/claudemd.d.ts +5 -5
  332. package/dist/esm-types/cli/lib/aiFiles/claudemd.d.ts.map +1 -1
  333. package/dist/esm-types/cli/lib/aiFiles/guidelinesmd.d.ts +3 -3
  334. package/dist/esm-types/cli/lib/aiFiles/guidelinesmd.d.ts.map +1 -1
  335. package/dist/esm-types/cli/lib/aiFiles/index.d.ts +20 -18
  336. package/dist/esm-types/cli/lib/aiFiles/index.d.ts.map +1 -1
  337. package/dist/esm-types/cli/lib/aiFiles/skills.d.ts +6 -4
  338. package/dist/esm-types/cli/lib/aiFiles/skills.d.ts.map +1 -1
  339. package/dist/esm-types/cli/lib/aiFiles/state.d.ts +38 -0
  340. package/dist/esm-types/cli/lib/aiFiles/state.d.ts.map +1 -0
  341. package/dist/esm-types/cli/lib/aiFiles/state.test.d.ts +2 -0
  342. package/dist/esm-types/cli/lib/aiFiles/state.test.d.ts.map +1 -0
  343. package/dist/esm-types/cli/lib/aiFiles/status.d.ts +4 -1
  344. package/dist/esm-types/cli/lib/aiFiles/status.d.ts.map +1 -1
  345. package/dist/esm-types/cli/lib/aiFiles/utils.d.ts +13 -3
  346. package/dist/esm-types/cli/lib/aiFiles/utils.d.ts.map +1 -1
  347. package/dist/esm-types/cli/lib/aiFiles/utils.test.d.ts +2 -0
  348. package/dist/esm-types/cli/lib/aiFiles/utils.test.d.ts.map +1 -0
  349. package/dist/esm-types/cli/lib/api.d.ts +3 -3
  350. package/dist/esm-types/cli/lib/api.d.ts.map +1 -1
  351. package/dist/esm-types/cli/lib/command.d.ts +2 -1
  352. package/dist/esm-types/cli/lib/command.d.ts.map +1 -1
  353. package/dist/esm-types/cli/lib/config.d.ts +17 -6
  354. package/dist/esm-types/cli/lib/config.d.ts.map +1 -1
  355. package/dist/esm-types/cli/lib/deploy2.d.ts +5 -2
  356. package/dist/esm-types/cli/lib/deploy2.d.ts.map +1 -1
  357. package/dist/esm-types/cli/lib/deployApi/componentDefinition.d.ts +27 -12
  358. package/dist/esm-types/cli/lib/deployApi/componentDefinition.d.ts.map +1 -1
  359. package/dist/esm-types/cli/lib/deployApi/definitionConfig.d.ts +24 -24
  360. package/dist/esm-types/cli/lib/deployApi/modules.d.ts +14 -14
  361. package/dist/esm-types/cli/lib/deployApi/startPush.d.ts +61 -52
  362. package/dist/esm-types/cli/lib/deployApi/startPush.d.ts.map +1 -1
  363. package/dist/esm-types/cli/lib/deploymentSelection.d.ts.map +1 -1
  364. package/dist/esm-types/cli/lib/deploymentSelector.d.ts +2 -0
  365. package/dist/esm-types/cli/lib/deploymentSelector.d.ts.map +1 -1
  366. package/dist/esm-types/cli/lib/dev.d.ts.map +1 -1
  367. package/dist/esm-types/cli/lib/env.d.ts +0 -4
  368. package/dist/esm-types/cli/lib/env.d.ts.map +1 -1
  369. package/dist/esm-types/cli/lib/expiration.d.ts +35 -0
  370. package/dist/esm-types/cli/lib/expiration.d.ts.map +1 -0
  371. package/dist/esm-types/cli/lib/expiration.test.d.ts +2 -0
  372. package/dist/esm-types/cli/lib/expiration.test.d.ts.map +1 -0
  373. package/dist/esm-types/cli/lib/generatedFunctionLogsApi.d.ts +16 -1
  374. package/dist/esm-types/cli/lib/generatedFunctionLogsApi.d.ts.map +1 -1
  375. package/dist/esm-types/cli/lib/init.d.ts.map +1 -1
  376. package/dist/esm-types/cli/lib/localDeployment/anonymous.d.ts.map +1 -1
  377. package/dist/esm-types/cli/lib/localDeployment/localDeployment.d.ts.map +1 -1
  378. package/dist/esm-types/cli/lib/localDeployment/run.d.ts +15 -0
  379. package/dist/esm-types/cli/lib/localDeployment/run.d.ts.map +1 -1
  380. package/dist/esm-types/cli/lib/localDeployment/upgrade.d.ts.map +1 -1
  381. package/dist/esm-types/cli/lib/localDeployment/utils.d.ts +7 -0
  382. package/dist/esm-types/cli/lib/localDeployment/utils.d.ts.map +1 -1
  383. package/dist/esm-types/cli/lib/mcp/requestContext.d.ts +3 -3
  384. package/dist/esm-types/cli/lib/mcp/tools/insights.d.ts +2 -2
  385. package/dist/esm-types/cli/lib/updates.d.ts +4 -3
  386. package/dist/esm-types/cli/lib/updates.d.ts.map +1 -1
  387. package/dist/esm-types/cli/lib/usage.d.ts.map +1 -1
  388. package/dist/esm-types/cli/lib/utils/prompts.d.ts +1 -0
  389. package/dist/esm-types/cli/lib/utils/prompts.d.ts.map +1 -1
  390. package/dist/esm-types/cli/lib/utils/utils.d.ts +16 -2
  391. package/dist/esm-types/cli/lib/utils/utils.d.ts.map +1 -1
  392. package/dist/esm-types/index.d.ts +1 -1
  393. package/dist/esm-types/react/client.d.ts +54 -2
  394. package/dist/esm-types/react/client.d.ts.map +1 -1
  395. package/dist/esm-types/react/index.d.ts +7 -2
  396. package/dist/esm-types/react/index.d.ts.map +1 -1
  397. package/dist/esm-types/react/use_query_object_options.test.d.ts +5 -0
  398. package/dist/esm-types/react/use_query_object_options.test.d.ts.map +1 -0
  399. package/dist/esm-types/react/use_query_result.test.d.ts +5 -0
  400. package/dist/esm-types/react/use_query_result.test.d.ts.map +1 -0
  401. package/dist/esm-types/react-clerk/ConvexProviderWithClerk.d.ts +1 -1
  402. package/dist/esm-types/server/api.d.ts +5 -1
  403. package/dist/esm-types/server/api.d.ts.map +1 -1
  404. package/dist/esm-types/server/components/definition.d.ts +1 -0
  405. package/dist/esm-types/server/components/definition.d.ts.map +1 -1
  406. package/dist/esm-types/server/components/index.d.ts +5 -1
  407. package/dist/esm-types/server/components/index.d.ts.map +1 -1
  408. package/dist/esm-types/server/data_model.d.ts +2 -1
  409. package/dist/esm-types/server/data_model.d.ts.map +1 -1
  410. package/dist/esm-types/server/impl/meta_impl.d.ts +5 -0
  411. package/dist/esm-types/server/impl/meta_impl.d.ts.map +1 -0
  412. package/dist/esm-types/server/impl/registration_impl.d.ts.map +1 -1
  413. package/dist/esm-types/server/index.d.ts +1 -0
  414. package/dist/esm-types/server/index.d.ts.map +1 -1
  415. package/dist/esm-types/server/meta.d.ts +72 -0
  416. package/dist/esm-types/server/meta.d.ts.map +1 -0
  417. package/dist/esm-types/server/registration.d.ts.map +1 -1
  418. package/dist/react.bundle.js +50 -7
  419. package/dist/react.bundle.js.map +3 -3
  420. package/package.json +11 -7
  421. package/schemas/convex.schema.json +15 -2
  422. package/src/browser/index.ts +3 -0
  423. package/src/browser/query_options.test.ts +0 -9
  424. package/src/browser/query_options.ts +36 -15
  425. package/src/cli/aiFiles.ts +44 -14
  426. package/src/cli/codegen_templates/readme.ts +14 -1
  427. package/src/cli/configure.test.ts +138 -0
  428. package/src/cli/configure.ts +48 -47
  429. package/src/cli/deploy.ts +12 -9
  430. package/src/cli/deploymentCreate.test.ts +349 -14
  431. package/src/cli/deploymentCreate.ts +268 -41
  432. package/src/cli/deploymentSelect.test.ts +136 -27
  433. package/src/cli/deploymentSelect.ts +50 -41
  434. package/src/cli/deploymentSelection.test.ts +343 -35
  435. package/src/cli/dev.ts +49 -14
  436. package/src/cli/docs.ts +1 -1
  437. package/src/cli/init.ts +2 -2
  438. package/src/cli/lib/aiFiles/agentsmd.ts +15 -11
  439. package/src/cli/lib/aiFiles/claudemd.ts +15 -11
  440. package/src/cli/lib/aiFiles/guidelinesmd.test.ts +12 -2
  441. package/src/cli/lib/aiFiles/guidelinesmd.ts +15 -7
  442. package/src/cli/lib/aiFiles/index.test.ts +188 -222
  443. package/src/cli/lib/aiFiles/index.ts +119 -125
  444. package/src/cli/lib/aiFiles/integration.test.ts +112 -45
  445. package/src/cli/lib/aiFiles/prompt.test.ts +6 -6
  446. package/src/cli/lib/aiFiles/skills.ts +46 -16
  447. package/src/cli/lib/aiFiles/state.test.ts +280 -0
  448. package/src/cli/lib/aiFiles/state.ts +82 -0
  449. package/src/cli/lib/aiFiles/status.ts +45 -39
  450. package/src/cli/lib/aiFiles/utils.test.ts +50 -0
  451. package/src/cli/lib/aiFiles/utils.ts +38 -10
  452. package/src/cli/lib/api.ts +88 -7
  453. package/src/cli/lib/command.ts +12 -7
  454. package/src/cli/lib/config.test.ts +184 -7
  455. package/src/cli/lib/config.ts +67 -7
  456. package/src/cli/lib/deploy2.ts +14 -27
  457. package/src/cli/lib/deployApi/componentDefinition.ts +4 -1
  458. package/src/cli/lib/deploymentSelection.ts +59 -6
  459. package/src/cli/lib/deploymentSelector.test.ts +6 -0
  460. package/src/cli/lib/deploymentSelector.ts +2 -0
  461. package/src/cli/lib/dev.ts +202 -153
  462. package/src/cli/lib/env.ts +0 -15
  463. package/src/cli/lib/expiration.test.ts +159 -0
  464. package/src/cli/lib/expiration.ts +124 -0
  465. package/src/cli/lib/generatedFunctionLogsApi.ts +16 -1
  466. package/src/cli/lib/init.ts +6 -2
  467. package/src/cli/lib/insights.ts +1 -1
  468. package/src/cli/lib/localDeployment/anonymous.ts +19 -9
  469. package/src/cli/lib/localDeployment/localDeployment.ts +9 -11
  470. package/src/cli/lib/localDeployment/run.ts +1 -1
  471. package/src/cli/lib/localDeployment/upgrade.ts +12 -10
  472. package/src/cli/lib/localDeployment/utils.ts +12 -0
  473. package/src/cli/lib/mcp/tools/status.ts +1 -1
  474. package/src/cli/lib/updates.test.ts +102 -75
  475. package/src/cli/lib/updates.ts +14 -12
  476. package/src/cli/lib/usage.ts +3 -1
  477. package/src/cli/lib/utils/prompts.ts +2 -0
  478. package/src/cli/lib/utils/utils.test.ts +6 -6
  479. package/src/cli/lib/utils/utils.ts +66 -27
  480. package/src/index.ts +1 -1
  481. package/src/react/client.test.tsx +65 -0
  482. package/src/react/client.ts +129 -13
  483. package/src/react/index.ts +9 -1
  484. package/src/react/use_query_object_options.test.ts +50 -0
  485. package/src/react/use_query_result.test.ts +41 -0
  486. package/src/react-clerk/ConvexProviderWithClerk.test.tsx +1 -1
  487. package/src/react-clerk/ConvexProviderWithClerk.tsx +1 -1
  488. package/src/server/api.ts +5 -1
  489. package/src/server/components/definition.ts +3 -0
  490. package/src/server/components/index.ts +62 -5
  491. package/src/server/data_model.ts +2 -1
  492. package/src/server/impl/meta_impl.ts +74 -0
  493. package/src/server/impl/registration_impl.ts +21 -9
  494. package/src/server/index.ts +8 -0
  495. package/src/server/meta.ts +76 -0
  496. package/src/server/registration.ts +10 -0
  497. package/src/server/schema.test.ts +78 -1
  498. package/dist/cjs/cli/lib/aiFiles/config.js +0 -171
  499. package/dist/cjs/cli/lib/aiFiles/config.js.map +0 -7
  500. package/dist/cjs-types/cli/lib/aiFiles/config.d.ts +0 -46
  501. package/dist/cjs-types/cli/lib/aiFiles/config.d.ts.map +0 -1
  502. package/dist/cjs-types/cli/lib/aiFiles/config.test.d.ts +0 -2
  503. package/dist/cjs-types/cli/lib/aiFiles/config.test.d.ts.map +0 -1
  504. package/dist/esm/cli/lib/aiFiles/config.js +0 -135
  505. package/dist/esm/cli/lib/aiFiles/config.js.map +0 -7
  506. package/dist/esm-types/cli/lib/aiFiles/config.d.ts +0 -46
  507. package/dist/esm-types/cli/lib/aiFiles/config.d.ts.map +0 -1
  508. package/dist/esm-types/cli/lib/aiFiles/config.test.d.ts +0 -2
  509. package/dist/esm-types/cli/lib/aiFiles/config.test.d.ts.map +0 -1
  510. package/src/cli/lib/aiFiles/config.test.ts +0 -460
  511. package/src/cli/lib/aiFiles/config.ts +0 -188
  512. package/src/values/.claude/settings.local.json +0 -10
@@ -12,25 +12,26 @@ import {
12
12
  hasGuidelinesInstalled,
13
13
  } from "./guidelinesmd.js";
14
14
  import {
15
- type AiFilesConfig,
16
- hasAiFilesConfig,
17
- readAiConfig,
18
- writeAiConfig,
19
- writeAiEnabledToProjectConfig,
20
- } from "./config.js";
21
- import { isInInteractiveTerminal } from "./utils.js";
15
+ attemptReadAiState,
16
+ readAiStateOrDefault,
17
+ writeAiState,
18
+ hasAiState,
19
+ } from "./state.js";
20
+ import { type AiFilesProjectConfig } from "../config.js";
21
+ import { exhaustiveCheck, isInInteractiveTerminal } from "./utils.js";
22
22
  import {
23
23
  hasAgentsMdInstalled,
24
24
  applyAgentsMdSection,
25
- removeAgentsMdSection,
25
+ attemptToRemoveAgentsMdSection,
26
26
  } from "./agentsmd.js";
27
27
  import {
28
28
  hasClaudeMdInstalled,
29
29
  applyClaudeMdSection,
30
- removeClaudeMdSection,
30
+ attemptToRemoveClaudeMdSection,
31
31
  } from "./claudemd.js";
32
32
  import { installSkills, removeInstalledSkills } from "./skills.js";
33
33
  import { removeLegacyCursorRulesFile as removeLegacyCursorRules } from "./cursorrules.js";
34
+
34
35
  async function hasExistingAiFilesArtifacts({
35
36
  projectDir,
36
37
  convexDir,
@@ -45,53 +46,25 @@ async function hasExistingAiFilesArtifacts({
45
46
  /**
46
47
  * Install or refresh all Convex AI files.
47
48
  *
48
- * Reads the existing config if present, or starts from a blank one for a
49
- * fresh install. Each component can be individually skipped via the optional
50
- * flags (all default to true).
49
+ * Reads the existing state if present, or starts from a blank one for a
50
+ * fresh install.
51
51
  */
52
52
  export async function installAiFiles({
53
53
  projectDir,
54
54
  convexDir,
55
- shouldWriteGuidelines = true,
56
- shouldWriteAgentsMd = true,
57
- shouldWriteClaudeMd = true,
58
- shouldWriteSkills = true,
55
+ aiFilesConfig,
59
56
  }: AiFilesPaths & {
60
- shouldWriteGuidelines?: boolean;
61
- shouldWriteAgentsMd?: boolean;
62
- shouldWriteClaudeMd?: boolean;
63
- shouldWriteSkills?: boolean;
57
+ aiFilesConfig?: AiFilesProjectConfig | undefined;
64
58
  }): Promise<void> {
65
- await fs.mkdir(aiDirForConvexDir(convexDir), { recursive: true });
66
-
67
- const config: AiFilesConfig = (await readAiConfig({
68
- projectDir,
69
- convexDir,
70
- })) ?? {
71
- enabled: true,
72
- guidelinesHash: null,
73
- agentsMdSectionHash: null,
74
- claudeMdHash: null,
75
- agentSkillsSha: null,
76
- installedSkillNames: [],
77
- };
78
-
79
- if (shouldWriteGuidelines) await installGuidelinesFile({ convexDir, config });
80
-
81
59
  const convexDirName = path.relative(projectDir, convexDir);
60
+ const state = await readAiStateOrDefault(convexDir);
82
61
 
83
- if (shouldWriteAgentsMd)
84
- await applyAgentsMdSection({ projectDir, config, convexDirName });
85
-
86
- if (shouldWriteClaudeMd)
87
- await applyClaudeMdSection({ projectDir, config, convexDirName });
88
-
89
- if (shouldWriteSkills) await installSkills({ projectDir, config });
90
-
62
+ await installGuidelinesFile({ convexDir, state });
63
+ await applyAgentsMdSection({ projectDir, state, convexDirName });
64
+ await applyClaudeMdSection({ projectDir, state, convexDirName });
65
+ await installSkills({ projectDir, state, aiFilesConfig });
91
66
  await removeLegacyCursorRules(projectDir);
92
- await writeAiConfig({ config, projectDir, convexDir });
93
-
94
- logMessage(`${chalkStderr.green("✔")} Convex AI files installed.`);
67
+ await writeAiState({ state, convexDir });
95
68
  }
96
69
 
97
70
  async function attemptToInstallAiFiles(
@@ -104,58 +77,70 @@ async function attemptToInstallAiFiles(
104
77
  }
105
78
  }
106
79
 
107
- type AiFilesStalenessStatus =
108
- | "not-installed" // no config AND no artifacts — show install nag
109
- | "has-artifacts" // no config but files exist on disk (e.g. fresh checkout) — stay quiet
110
- | "disabled" // user opted out of nag messages
111
- | "stale" // one or more files are out of date
112
- | "up-to-date"; // everything looks fine
80
+ type AiFilesStalenessStatus = "not-installed" | "stale" | "silent";
81
+
82
+ export function isAiFilesDisabled(
83
+ aiFilesConfig: AiFilesProjectConfig | undefined,
84
+ ): boolean {
85
+ if (aiFilesConfig?.enabled !== undefined)
86
+ return aiFilesConfig.enabled === false;
87
+ return aiFilesConfig?.disableStalenessMessage === true;
88
+ }
113
89
 
114
90
  async function determineAiFilesStaleness({
115
91
  canonicalGuidelinesHash,
116
92
  canonicalAgentSkillsSha,
93
+ aiFilesConfig,
117
94
  projectDir,
118
95
  convexDir,
119
96
  }: {
120
97
  canonicalGuidelinesHash: string | null;
121
98
  canonicalAgentSkillsSha: string | null;
99
+ aiFilesConfig?: AiFilesProjectConfig | undefined;
122
100
  } & AiFilesPaths): Promise<AiFilesStalenessStatus> {
123
- const config = await readAiConfig({ projectDir, convexDir });
101
+ if (isAiFilesDisabled(aiFilesConfig)) return "silent";
102
+
103
+ const result = await attemptReadAiState(convexDir);
124
104
 
125
- if (config === null) {
105
+ if (result.kind === "no-file" || result.kind === "parse-error") {
126
106
  const hasArtifacts = await hasExistingAiFilesArtifacts({
127
107
  projectDir,
128
108
  convexDir,
129
109
  });
130
- return hasArtifacts ? "has-artifacts" : "not-installed";
110
+ return hasArtifacts ? "silent" : "not-installed";
131
111
  }
132
112
 
133
- if (!config.enabled) return "disabled";
113
+ if (result.kind === "ok") {
114
+ const { state } = result;
115
+
116
+ if (canonicalGuidelinesHash === null && canonicalAgentSkillsSha === null)
117
+ return "silent";
134
118
 
135
- if (canonicalGuidelinesHash === null && canonicalAgentSkillsSha === null)
136
- return "up-to-date";
119
+ const guidelinesStale =
120
+ canonicalGuidelinesHash !== null &&
121
+ state.guidelinesHash !== null &&
122
+ state.guidelinesHash !== canonicalGuidelinesHash;
137
123
 
138
- const guidelinesStale =
139
- canonicalGuidelinesHash !== null &&
140
- config.guidelinesHash !== null &&
141
- config.guidelinesHash !== canonicalGuidelinesHash;
124
+ const skillsStale =
125
+ canonicalAgentSkillsSha !== null &&
126
+ state.agentSkillsSha !== null &&
127
+ state.agentSkillsSha !== canonicalAgentSkillsSha;
142
128
 
143
- const skillsStale =
144
- canonicalAgentSkillsSha !== null &&
145
- config.agentSkillsSha !== null &&
146
- config.agentSkillsSha !== canonicalAgentSkillsSha;
129
+ return guidelinesStale || skillsStale ? "stale" : "silent";
130
+ }
147
131
 
148
- return guidelinesStale || skillsStale ? "stale" : "up-to-date";
132
+ return exhaustiveCheck(result);
149
133
  }
150
134
 
151
135
  /**
152
136
  * Check whether the Convex AI files are out of date and log a nag message
153
137
  * if so.
154
138
  */
155
- export async function checkAiFilesStaleness(
139
+ export async function checkAiFilesStalenessAndLog(
156
140
  opts: {
157
141
  canonicalGuidelinesHash: string | null;
158
142
  canonicalAgentSkillsSha: string | null;
143
+ aiFilesConfig?: AiFilesProjectConfig | undefined;
159
144
  } & AiFilesPaths,
160
145
  ): Promise<void> {
161
146
  const status = await determineAiFilesStaleness(opts);
@@ -166,6 +151,7 @@ export async function checkAiFilesStaleness(
166
151
  `Convex AI files are not installed. Run ${chalkStderr.bold(`npx convex ai-files install`)} to get started or ${chalkStderr.bold(`npx convex ai-files disable`)} to hide this message.`,
167
152
  ),
168
153
  );
154
+ return;
169
155
  }
170
156
 
171
157
  if (status === "stale") {
@@ -174,23 +160,39 @@ export async function checkAiFilesStaleness(
174
160
  `Your Convex AI files are out of date. Run ${chalkStderr.bold(`npx convex ai-files update`)} to get the latest.`,
175
161
  ),
176
162
  );
163
+ return;
177
164
  }
165
+
166
+ if (status === "silent") return;
167
+
168
+ exhaustiveCheck(status);
178
169
  }
179
170
 
171
+ /**
172
+ * Installs AI files and returns the aiFiles config to write.
173
+ */
180
174
  export async function enableAiFiles({
181
175
  projectDir,
182
176
  convexDir,
183
- }: AiFilesPaths): Promise<void> {
184
- await installAiFiles({ projectDir, convexDir });
185
- const config = await readAiConfig({ projectDir, convexDir });
186
- if (config === null) return;
187
- config.enabled = true;
188
- await writeAiConfig({
189
- config,
190
- projectDir,
191
- convexDir,
192
- options: { persistEnabledPreference: "always" },
193
- });
177
+ aiFilesConfig,
178
+ }: AiFilesPaths & {
179
+ aiFilesConfig?: AiFilesProjectConfig | undefined;
180
+ }): Promise<AiFilesProjectConfig> {
181
+ await installAiFiles({ projectDir, convexDir, aiFilesConfig });
182
+ // Deleting the deprecated disableStalenessMessage key
183
+ const { disableStalenessMessage: _, ...rest } = aiFilesConfig ?? {};
184
+ return { ...rest, enabled: true };
185
+ }
186
+
187
+ /**
188
+ * Returns the aiFiles config to write when disabling AI files.
189
+ */
190
+ export function disableAiFiles(
191
+ aiFilesConfig?: AiFilesProjectConfig | undefined,
192
+ ): AiFilesProjectConfig {
193
+ // Deleting the deprecated disableStalenessMessage key
194
+ const { disableStalenessMessage: _, ...rest } = aiFilesConfig ?? {};
195
+ return { ...rest, enabled: false };
194
196
  }
195
197
 
196
198
  /**
@@ -201,51 +203,31 @@ export async function removeAiFiles({
201
203
  projectDir,
202
204
  convexDir,
203
205
  }: AiFilesPaths): Promise<void> {
204
- const config = await readAiConfig({ projectDir, convexDir });
205
- if (config === null) {
206
- logMessage("No Convex AI files found nothing to remove.");
207
- return;
208
- }
206
+ const result = await attemptReadAiState(convexDir);
207
+
208
+ // Skill names are only known when the state file exists and parses.
209
+ // All other artifacts (AGENTS.md, CLAUDE.md sections, ai dir) can exist
210
+ // independently, so we always attempt their removal.
211
+ const installedSkillNames =
212
+ result.kind === "ok"
213
+ ? result.state.installedSkillNames
214
+ : result.kind === "no-file" || result.kind === "parse-error"
215
+ ? []
216
+ : exhaustiveCheck(result);
209
217
 
210
218
  const removals = [
211
- await removeAgentsMdSection(projectDir),
212
- await removeClaudeMdSection(projectDir),
219
+ await attemptToRemoveAgentsMdSection(projectDir),
220
+ await attemptToRemoveClaudeMdSection(projectDir),
213
221
  await removeInstalledSkills({
214
222
  projectDir,
215
- skillNames: config.installedSkillNames,
223
+ skillNames: installedSkillNames,
216
224
  }),
217
225
  await removeLegacyCursorRules(projectDir),
218
226
  await attemptToDeleteAiDir({ projectDir, convexDir }),
219
227
  ];
220
228
 
221
229
  if (removals.some(Boolean)) logMessage("Convex AI files removed.");
222
- }
223
-
224
- /**
225
- * Called by `npx convex ai-files disable`.
226
- *
227
- * Writes a suppression flag into `convex.json` so `npx convex dev` stops
228
- * showing AI files install/staleness messages. Files are left in place.
229
- */
230
- export async function safelyAttemptToDisableAiFiles(
231
- projectDir: string,
232
- ): Promise<void> {
233
- try {
234
- await writeAiEnabledToProjectConfig({
235
- projectDir,
236
- enabled: false,
237
- });
238
- logMessage(
239
- `${chalkStderr.green(`✔`)} Convex AI files disabled. Run ${chalkStderr.bold(`npx convex ai-files enable`)} to re-enable.`,
240
- );
241
- } catch (error) {
242
- Sentry.captureException(error);
243
- logMessage(
244
- chalkStderr.yellow(
245
- "Could not write AI message suppression config. Message may reappear.",
246
- ),
247
- );
248
- }
230
+ else logMessage("No Convex AI files found — nothing to remove.");
249
231
  }
250
232
 
251
233
  async function attemptToDeleteAiDir({
@@ -255,10 +237,11 @@ async function attemptToDeleteAiDir({
255
237
  const aiDir = aiDirForConvexDir(convexDir);
256
238
  const relPath = path.relative(projectDir, aiDir);
257
239
  try {
258
- await fs.rm(aiDir, { recursive: true, force: true });
240
+ await fs.rm(aiDir, { recursive: true });
259
241
  logMessage(`${chalkStderr.green("✔")} Deleted ${relPath}/`);
260
242
  return true;
261
243
  } catch (error) {
244
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") return false;
262
245
  Sentry.captureException(error);
263
246
  logMessage(
264
247
  chalkStderr.yellow(`Could not delete ${relPath}/. Remove it manually.`),
@@ -270,27 +253,37 @@ async function attemptToDeleteAiDir({
270
253
  async function hasAiFilesBeenInstalledBefore({
271
254
  projectDir,
272
255
  convexDir,
273
- }: AiFilesPaths): Promise<boolean> {
256
+ aiFilesConfig,
257
+ }: AiFilesPaths & {
258
+ aiFilesConfig?: AiFilesProjectConfig | undefined;
259
+ }): Promise<boolean> {
260
+ if (isAiFilesDisabled(aiFilesConfig)) return false;
274
261
  return (
275
- (await hasAiFilesConfig({ projectDir, convexDir })) ||
262
+ (await hasAiState(convexDir)) ||
276
263
  (await hasExistingAiFilesArtifacts({ projectDir, convexDir }))
277
264
  );
278
265
  }
279
266
 
280
- export async function maybeSetupAiFiles({
267
+ export async function attemptSetupAiFiles({
281
268
  ctx,
282
269
  convexDir,
283
270
  projectDir,
271
+ aiFilesConfig,
284
272
  }: {
285
273
  ctx: Context;
274
+ aiFilesConfig?: AiFilesProjectConfig | undefined;
286
275
  } & AiFilesPaths): Promise<void> {
287
276
  if (!isInInteractiveTerminal()) return;
277
+ if (isAiFilesDisabled(aiFilesConfig)) return;
288
278
 
289
- const config = await readAiConfig({ projectDir, convexDir });
290
- if (config !== null && !config.enabled) return;
291
-
292
- if (await hasAiFilesBeenInstalledBefore({ projectDir, convexDir })) {
293
- await attemptToInstallAiFiles({ projectDir, convexDir });
279
+ if (
280
+ await hasAiFilesBeenInstalledBefore({
281
+ projectDir,
282
+ convexDir,
283
+ aiFilesConfig,
284
+ })
285
+ ) {
286
+ await attemptToInstallAiFiles({ projectDir, convexDir, aiFilesConfig });
294
287
  return;
295
288
  }
296
289
 
@@ -299,5 +292,6 @@ export async function maybeSetupAiFiles({
299
292
  default: true,
300
293
  });
301
294
 
302
- if (shouldInstall) await attemptToInstallAiFiles({ projectDir, convexDir });
295
+ if (shouldInstall)
296
+ await attemptToInstallAiFiles({ projectDir, convexDir, aiFilesConfig });
303
297
  }
@@ -3,8 +3,7 @@ import fs from "fs";
3
3
  import os from "os";
4
4
  import path from "path";
5
5
  import {
6
- checkAiFilesStaleness,
7
- safelyAttemptToDisableAiFiles,
6
+ checkAiFilesStalenessAndLog,
8
7
  enableAiFiles,
9
8
  removeAiFiles,
10
9
  installAiFiles,
@@ -46,6 +45,8 @@ vi.mock("child_process", () => ({
46
45
  },
47
46
  }));
48
47
 
48
+ import child_process from "child_process";
49
+
49
50
  // ---------------------------------------------------------------------------
50
51
  // Shared helpers
51
52
  // ---------------------------------------------------------------------------
@@ -54,6 +55,16 @@ function readJson(filePath: string): any {
54
55
  return JSON.parse(fs.readFileSync(filePath, "utf8"));
55
56
  }
56
57
 
58
+ function patchConvexJson(projectDir: string, patch: object) {
59
+ const filePath = path.join(projectDir, "convex.json");
60
+ const existing = fs.existsSync(filePath) ? readJson(filePath) : {};
61
+ fs.writeFileSync(
62
+ filePath,
63
+ JSON.stringify({ ...existing, ...patch }, null, 2) + "\n",
64
+ "utf8",
65
+ );
66
+ }
67
+
57
68
  function makeTmpDir(): string {
58
69
  return fs.mkdtempSync(`${os.tmpdir()}${path.sep}`);
59
70
  }
@@ -92,6 +103,55 @@ describe("ai-files integration with default convex/ directory", () => {
92
103
  expect(fs.readFileSync(guidelinesPath(), "utf8")).toBe(
93
104
  "integration guidelines content",
94
105
  );
106
+
107
+ // Default agents
108
+ expect(vi.mocked(child_process.spawn)).toHaveBeenCalledWith(
109
+ "npx",
110
+ expect.arrayContaining([
111
+ "add",
112
+ "get-convex/agent-skills",
113
+ "--yes",
114
+ "--agent",
115
+ "claude-code",
116
+ "--agent",
117
+ "codex",
118
+ ]),
119
+ expect.any(Object),
120
+ );
121
+ });
122
+
123
+ test("install respects explicit agent configuration", async () => {
124
+ await installAiFiles({
125
+ projectDir: tmpDir,
126
+ convexDir,
127
+ aiFilesConfig: { skills: { agents: ["cursor", "windsurf"] } },
128
+ });
129
+
130
+ expect(vi.mocked(child_process.spawn)).toHaveBeenCalledWith(
131
+ "npx",
132
+ expect.arrayContaining([
133
+ "add",
134
+ "get-convex/agent-skills",
135
+ "--yes",
136
+ "--agent",
137
+ "cursor",
138
+ "--agent",
139
+ "windsurf",
140
+ ]),
141
+ expect.any(Object),
142
+ );
143
+ });
144
+
145
+ test("install skips skills CLI when configured agents are empty", async () => {
146
+ await installAiFiles({
147
+ projectDir: tmpDir,
148
+ convexDir,
149
+ aiFilesConfig: { skills: { agents: [] } },
150
+ });
151
+
152
+ expect(fs.existsSync(guidelinesPath())).toBe(true);
153
+ expect(fs.existsSync(statePath())).toBe(true);
154
+ expect(vi.mocked(child_process.spawn)).not.toHaveBeenCalled();
95
155
  });
96
156
 
97
157
  test("preserves existing AGENTS.md content and injects managed section", async () => {
@@ -148,7 +208,7 @@ describe("ai-files integration with default convex/ directory", () => {
148
208
  state.guidelinesHash = "deliberately-stale-hash";
149
209
  fs.writeFileSync(statePath(), JSON.stringify(state, null, 2) + "\n");
150
210
 
151
- await checkAiFilesStaleness({
211
+ await checkAiFilesStalenessAndLog({
152
212
  canonicalGuidelinesHash: "canonical-hash",
153
213
  canonicalAgentSkillsSha: null,
154
214
  projectDir: tmpDir,
@@ -160,30 +220,9 @@ describe("ai-files integration with default convex/ directory", () => {
160
220
  );
161
221
  });
162
222
 
163
- test("staleness check is silent when disabled in convex.json", async () => {
164
- await installAiFiles({ projectDir: tmpDir, convexDir });
165
- await safelyAttemptToDisableAiFiles(tmpDir);
166
- const state = readJson(statePath());
167
- state.guidelinesHash = "deliberately-stale-hash";
168
- fs.writeFileSync(statePath(), JSON.stringify(state, null, 2) + "\n");
169
- vi.mocked(logMessage).mockClear();
170
-
171
- await checkAiFilesStaleness({
172
- canonicalGuidelinesHash: "canonical-hash",
173
- canonicalAgentSkillsSha: null,
174
- projectDir: tmpDir,
175
- convexDir,
176
- });
177
-
178
- const calls = vi.mocked(logMessage).mock.calls.map((c) => c[0]);
179
- expect(
180
- calls.find((m) => typeof m === "string" && m.includes("out of date")),
181
- ).toBeUndefined();
182
- });
183
-
184
223
  test("disable keeps files but sets convex.json preference", async () => {
185
224
  await installAiFiles({ projectDir: tmpDir, convexDir });
186
- await safelyAttemptToDisableAiFiles(tmpDir);
225
+ patchConvexJson(tmpDir, { aiFiles: { enabled: false } });
187
226
 
188
227
  expect(readJson(projectConfigPath()).aiFiles.enabled).toBe(false);
189
228
  expect(fs.existsSync(guidelinesPath())).toBe(true);
@@ -192,7 +231,7 @@ describe("ai-files integration with default convex/ directory", () => {
192
231
  });
193
232
 
194
233
  test("disable before install writes only convex.json and no AI state file", async () => {
195
- await safelyAttemptToDisableAiFiles(tmpDir);
234
+ patchConvexJson(tmpDir, { aiFiles: { enabled: false } });
196
235
 
197
236
  expect(readJson(projectConfigPath()).aiFiles.enabled).toBe(false);
198
237
  expect(fs.existsSync(statePath())).toBe(false);
@@ -232,7 +271,7 @@ describe("ai-files integration with default convex/ directory", () => {
232
271
  test("disable after CLAUDE.md user edits preserves the file", async () => {
233
272
  await installAiFiles({ projectDir: tmpDir, convexDir });
234
273
  fs.appendFileSync(path.join(tmpDir, "CLAUDE.md"), "My custom note\n");
235
- await safelyAttemptToDisableAiFiles(tmpDir);
274
+ patchConvexJson(tmpDir, { aiFiles: { enabled: false } });
236
275
  expect(fs.readFileSync(path.join(tmpDir, "CLAUDE.md"), "utf8")).toContain(
237
276
  "My custom note",
238
277
  );
@@ -249,23 +288,37 @@ describe("ai-files integration with default convex/ directory", () => {
249
288
  );
250
289
  });
251
290
 
252
- test("enable sets enabled flag to true", async () => {
291
+ test("enable sets enabled flag to true and strips deprecated disableStalenessMessage", async () => {
253
292
  await installAiFiles({ projectDir: tmpDir, convexDir });
254
- await safelyAttemptToDisableAiFiles(tmpDir);
255
- expect(readJson(projectConfigPath()).aiFiles.enabled).toBe(false);
293
+ patchConvexJson(tmpDir, { aiFiles: { disableStalenessMessage: true } });
294
+ expect(readJson(projectConfigPath()).aiFiles.disableStalenessMessage).toBe(
295
+ true,
296
+ );
256
297
 
257
- await enableAiFiles({ projectDir: tmpDir, convexDir });
298
+ const newAiFiles = await enableAiFiles({
299
+ projectDir: tmpDir,
300
+ convexDir,
301
+ aiFilesConfig: readJson(projectConfigPath()).aiFiles,
302
+ });
303
+ patchConvexJson(tmpDir, { aiFiles: newAiFiles });
258
304
 
259
- expect(readJson(projectConfigPath()).aiFiles.enabled).toBe(true);
305
+ const updatedConfig = readJson(projectConfigPath());
306
+ expect(updatedConfig.aiFiles.enabled).toBe(true);
307
+ expect(updatedConfig.aiFiles.disableStalenessMessage).toBeUndefined();
260
308
  });
261
309
 
262
310
  test("full cycle: disable -> remove -> enable reinstalls everything", async () => {
263
311
  await installAiFiles({ projectDir: tmpDir, convexDir });
264
- await safelyAttemptToDisableAiFiles(tmpDir);
312
+ patchConvexJson(tmpDir, { aiFiles: { enabled: false } });
265
313
  await removeAiFiles({ projectDir: tmpDir, convexDir });
266
314
  expect(fs.existsSync(aiDir())).toBe(false);
267
315
 
268
- await enableAiFiles({ projectDir: tmpDir, convexDir });
316
+ const newAiFiles = await enableAiFiles({
317
+ projectDir: tmpDir,
318
+ convexDir,
319
+ aiFilesConfig: readJson(projectConfigPath()).aiFiles,
320
+ });
321
+ patchConvexJson(tmpDir, { aiFiles: newAiFiles });
269
322
 
270
323
  expect(fs.existsSync(guidelinesPath())).toBe(true);
271
324
  expect(fs.existsSync(path.join(tmpDir, "AGENTS.md"))).toBe(true);
@@ -326,7 +379,7 @@ describe("ai-files integration with default convex/ directory", () => {
326
379
  test("checkAiFilesStaleness nags when no state file exists", async () => {
327
380
  vi.mocked(logMessage).mockClear();
328
381
 
329
- await checkAiFilesStaleness({
382
+ await checkAiFilesStalenessAndLog({
330
383
  canonicalGuidelinesHash: null,
331
384
  canonicalAgentSkillsSha: null,
332
385
  projectDir: tmpDir,
@@ -343,7 +396,7 @@ describe("ai-files integration with default convex/ directory", () => {
343
396
  const state = readJson(statePath());
344
397
  vi.mocked(logMessage).mockClear();
345
398
 
346
- await checkAiFilesStaleness({
399
+ await checkAiFilesStalenessAndLog({
347
400
  canonicalGuidelinesHash: state.guidelinesHash,
348
401
  canonicalAgentSkillsSha: state.agentSkillsSha,
349
402
  projectDir: tmpDir,
@@ -371,10 +424,14 @@ describe("ai-files integration with default convex/ directory", () => {
371
424
 
372
425
  test("status reports disabled state after disable", async () => {
373
426
  await installAiFiles({ projectDir: tmpDir, convexDir });
374
- await safelyAttemptToDisableAiFiles(tmpDir);
427
+ patchConvexJson(tmpDir, { aiFiles: { enabled: false } });
375
428
  vi.mocked(logMessage).mockClear();
376
429
 
377
- await statusAiFiles({ projectDir: tmpDir, convexDir });
430
+ await statusAiFiles({
431
+ projectDir: tmpDir,
432
+ convexDir,
433
+ aiFilesConfig: readJson(projectConfigPath()).aiFiles,
434
+ });
378
435
 
379
436
  expect(vi.mocked(logMessage)).toHaveBeenCalledWith(
380
437
  expect.stringContaining("disabled"),
@@ -486,7 +543,7 @@ describe("ai-files integration with functions directory override", () => {
486
543
  "utf8",
487
544
  );
488
545
 
489
- await checkAiFilesStaleness({
546
+ await checkAiFilesStalenessAndLog({
490
547
  canonicalGuidelinesHash: "canonical-hash",
491
548
  canonicalAgentSkillsSha: null,
492
549
  projectDir: tmpDir,
@@ -500,7 +557,7 @@ describe("ai-files integration with functions directory override", () => {
500
557
 
501
558
  test("disable sets convex.json preference and keeps files", async () => {
502
559
  await installAiFiles({ projectDir: tmpDir, convexDir });
503
- await safelyAttemptToDisableAiFiles(tmpDir);
560
+ patchConvexJson(tmpDir, { aiFiles: { enabled: false } });
504
561
 
505
562
  expect(readJson(projectConfigPath()).aiFiles.enabled).toBe(false);
506
563
  expect(fs.existsSync(guidelinesPath())).toBe(true);
@@ -526,7 +583,7 @@ describe("ai-files integration with functions directory override", () => {
526
583
  "My custom note\n",
527
584
  "utf8",
528
585
  );
529
- await safelyAttemptToDisableAiFiles(tmpDir);
586
+ patchConvexJson(tmpDir, { aiFiles: { enabled: false } });
530
587
  expect(fs.readFileSync(path.join(tmpDir, "CLAUDE.md"), "utf8")).toContain(
531
588
  "My custom note",
532
589
  );
@@ -546,8 +603,13 @@ describe("ai-files integration with functions directory override", () => {
546
603
 
547
604
  test("enable sets enabled flag to true and re-enables status", async () => {
548
605
  await installAiFiles({ projectDir: tmpDir, convexDir });
549
- await safelyAttemptToDisableAiFiles(tmpDir);
550
- await enableAiFiles({ projectDir: tmpDir, convexDir });
606
+ patchConvexJson(tmpDir, { aiFiles: { enabled: false } });
607
+ const newAiFiles = await enableAiFiles({
608
+ projectDir: tmpDir,
609
+ convexDir,
610
+ aiFilesConfig: readJson(projectConfigPath()).aiFiles,
611
+ });
612
+ patchConvexJson(tmpDir, { aiFiles: newAiFiles });
551
613
  await statusAiFiles({ projectDir: tmpDir, convexDir });
552
614
 
553
615
  expect(readJson(projectConfigPath()).aiFiles.enabled).toBe(true);
@@ -558,14 +620,19 @@ describe("ai-files integration with functions directory override", () => {
558
620
 
559
621
  test("disable + remove + enable works with overridden functions directory", async () => {
560
622
  await installAiFiles({ projectDir: tmpDir, convexDir });
561
- await safelyAttemptToDisableAiFiles(tmpDir);
623
+ patchConvexJson(tmpDir, { aiFiles: { enabled: false } });
562
624
  await removeAiFiles({ projectDir: tmpDir, convexDir });
563
625
 
564
626
  expect(
565
627
  fs.existsSync(path.join(tmpDir, "src", "convex", "_generated", "ai")),
566
628
  ).toBe(false);
567
629
 
568
- await enableAiFiles({ projectDir: tmpDir, convexDir });
630
+ const newAiFiles = await enableAiFiles({
631
+ projectDir: tmpDir,
632
+ convexDir,
633
+ aiFilesConfig: readJson(projectConfigPath()).aiFiles,
634
+ });
635
+ patchConvexJson(tmpDir, { aiFiles: newAiFiles });
569
636
 
570
637
  expect(fs.existsSync(guidelinesPath())).toBe(true);
571
638
  });