convex 1.34.0 → 1.34.1

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 (243) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/browser.bundle.js +6 -9
  3. package/dist/browser.bundle.js.map +2 -2
  4. package/dist/cjs/browser/sync/authentication_manager.js +4 -1
  5. package/dist/cjs/browser/sync/authentication_manager.js.map +2 -2
  6. package/dist/cjs/browser/sync/web_socket_manager.js +1 -7
  7. package/dist/cjs/browser/sync/web_socket_manager.js.map +2 -2
  8. package/dist/cjs/cli/aiFiles.js +15 -14
  9. package/dist/cjs/cli/aiFiles.js.map +2 -2
  10. package/dist/cjs/cli/configure.js +15 -10
  11. package/dist/cjs/cli/configure.js.map +2 -2
  12. package/dist/cjs/cli/lib/aiFiles/agentsmd.js +69 -0
  13. package/dist/cjs/cli/lib/aiFiles/agentsmd.js.map +7 -0
  14. package/dist/cjs/cli/lib/aiFiles/claudemd.js +69 -0
  15. package/dist/cjs/cli/lib/aiFiles/claudemd.js.map +7 -0
  16. package/dist/cjs/cli/lib/{ai → aiFiles}/config.js +73 -46
  17. package/dist/cjs/cli/lib/aiFiles/config.js.map +7 -0
  18. package/dist/cjs/cli/lib/aiFiles/cursorrules.js +48 -0
  19. package/dist/cjs/cli/lib/aiFiles/cursorrules.js.map +7 -0
  20. package/dist/cjs/cli/lib/aiFiles/guidelinesmd.js +51 -0
  21. package/dist/cjs/cli/lib/aiFiles/guidelinesmd.js.map +7 -0
  22. package/dist/cjs/cli/lib/aiFiles/index.js +231 -0
  23. package/dist/cjs/cli/lib/aiFiles/index.js.map +7 -0
  24. package/dist/cjs/cli/lib/aiFiles/paths.js.map +7 -0
  25. package/dist/cjs/cli/lib/aiFiles/skills.js +180 -0
  26. package/dist/cjs/cli/lib/aiFiles/skills.js.map +7 -0
  27. package/dist/cjs/cli/lib/aiFiles/status.js +195 -0
  28. package/dist/cjs/cli/lib/aiFiles/status.js.map +7 -0
  29. package/dist/cjs/cli/lib/aiFiles/utils.js +111 -0
  30. package/dist/cjs/cli/lib/aiFiles/utils.js.map +7 -0
  31. package/dist/cjs/cli/lib/command.js +6 -1
  32. package/dist/cjs/cli/lib/command.js.map +2 -2
  33. package/dist/cjs/cli/lib/config.js +3 -4
  34. package/dist/cjs/cli/lib/config.js.map +2 -2
  35. package/dist/cjs/cli/lib/localDeployment/anonymous.js +2 -2
  36. package/dist/cjs/cli/lib/localDeployment/anonymous.js.map +2 -2
  37. package/dist/cjs/cli/lib/updates.js +8 -8
  38. package/dist/cjs/cli/lib/updates.js.map +2 -2
  39. package/dist/cjs/cli/lib/versionApi.js +7 -4
  40. package/dist/cjs/cli/lib/versionApi.js.map +2 -2
  41. package/dist/cjs/cli/lib/workos/workos.js +4 -6
  42. package/dist/cjs/cli/lib/workos/workos.js.map +2 -2
  43. package/dist/cjs/index.js +1 -1
  44. package/dist/cjs/index.js.map +1 -1
  45. package/dist/cjs-types/browser/sync/authentication_manager.d.ts.map +1 -1
  46. package/dist/cjs-types/browser/sync/web_socket_manager.d.ts.map +1 -1
  47. package/dist/cjs-types/cli/aiFiles.d.ts.map +1 -1
  48. package/dist/cjs-types/cli/configure.d.ts.map +1 -1
  49. package/dist/cjs-types/cli/lib/aiFiles/agentsmd.d.ts +19 -0
  50. package/dist/cjs-types/cli/lib/aiFiles/agentsmd.d.ts.map +1 -0
  51. package/dist/cjs-types/cli/lib/aiFiles/agentsmd.test.d.ts +2 -0
  52. package/dist/cjs-types/cli/lib/aiFiles/agentsmd.test.d.ts.map +1 -0
  53. package/dist/cjs-types/cli/lib/aiFiles/claudemd.d.ts +19 -0
  54. package/dist/cjs-types/cli/lib/aiFiles/claudemd.d.ts.map +1 -0
  55. package/dist/cjs-types/cli/lib/aiFiles/claudemd.test.d.ts +2 -0
  56. package/dist/cjs-types/cli/lib/aiFiles/claudemd.test.d.ts.map +1 -0
  57. package/dist/cjs-types/cli/lib/aiFiles/config.d.ts +46 -0
  58. package/dist/cjs-types/cli/lib/aiFiles/config.d.ts.map +1 -0
  59. package/dist/cjs-types/cli/lib/aiFiles/config.test.d.ts.map +1 -0
  60. package/dist/cjs-types/cli/lib/aiFiles/cursorrules.d.ts +10 -0
  61. package/dist/cjs-types/cli/lib/aiFiles/cursorrules.d.ts.map +1 -0
  62. package/dist/cjs-types/cli/lib/aiFiles/guidelinesmd.d.ts +12 -0
  63. package/dist/cjs-types/cli/lib/aiFiles/guidelinesmd.d.ts.map +1 -0
  64. package/dist/cjs-types/cli/lib/aiFiles/guidelinesmd.test.d.ts +2 -0
  65. package/dist/cjs-types/cli/lib/aiFiles/guidelinesmd.test.d.ts.map +1 -0
  66. package/dist/cjs-types/cli/lib/aiFiles/index.d.ts +40 -0
  67. package/dist/cjs-types/cli/lib/aiFiles/index.d.ts.map +1 -0
  68. package/dist/cjs-types/cli/lib/aiFiles/index.test.d.ts.map +1 -0
  69. package/dist/cjs-types/cli/lib/aiFiles/integration.test.d.ts.map +1 -0
  70. package/dist/cjs-types/cli/lib/{ai → aiFiles}/paths.d.ts +4 -0
  71. package/dist/cjs-types/cli/lib/aiFiles/paths.d.ts.map +1 -0
  72. package/dist/cjs-types/cli/lib/aiFiles/prompt.test.d.ts.map +1 -0
  73. package/dist/cjs-types/cli/lib/aiFiles/skills.d.ts +18 -0
  74. package/dist/cjs-types/cli/lib/aiFiles/skills.d.ts.map +1 -0
  75. package/dist/cjs-types/cli/lib/aiFiles/status.d.ts +3 -0
  76. package/dist/cjs-types/cli/lib/aiFiles/status.d.ts.map +1 -0
  77. package/dist/cjs-types/cli/lib/aiFiles/utils.d.ts +46 -0
  78. package/dist/cjs-types/cli/lib/aiFiles/utils.d.ts.map +1 -0
  79. package/dist/cjs-types/cli/lib/config.d.ts +1 -0
  80. package/dist/cjs-types/cli/lib/config.d.ts.map +1 -1
  81. package/dist/cjs-types/cli/lib/versionApi.d.ts +7 -1
  82. package/dist/cjs-types/cli/lib/versionApi.d.ts.map +1 -1
  83. package/dist/cjs-types/cli/lib/workos/workos.d.ts.map +1 -1
  84. package/dist/cjs-types/index.d.ts +1 -1
  85. package/dist/cli.bundle.cjs +1605 -1548
  86. package/dist/cli.bundle.cjs.map +4 -4
  87. package/dist/esm/browser/sync/authentication_manager.js +4 -1
  88. package/dist/esm/browser/sync/authentication_manager.js.map +2 -2
  89. package/dist/esm/browser/sync/web_socket_manager.js +1 -7
  90. package/dist/esm/browser/sync/web_socket_manager.js.map +2 -2
  91. package/dist/esm/cli/aiFiles.js +17 -17
  92. package/dist/esm/cli/aiFiles.js.map +2 -2
  93. package/dist/esm/cli/configure.js +15 -10
  94. package/dist/esm/cli/configure.js.map +2 -2
  95. package/dist/esm/cli/lib/aiFiles/agentsmd.js +52 -0
  96. package/dist/esm/cli/lib/aiFiles/agentsmd.js.map +7 -0
  97. package/dist/esm/cli/lib/aiFiles/claudemd.js +52 -0
  98. package/dist/esm/cli/lib/aiFiles/claudemd.js.map +7 -0
  99. package/dist/esm/cli/lib/{ai → aiFiles}/config.js +71 -45
  100. package/dist/esm/cli/lib/aiFiles/config.js.map +7 -0
  101. package/dist/esm/cli/lib/aiFiles/cursorrules.js +16 -0
  102. package/dist/esm/cli/lib/aiFiles/cursorrules.js.map +7 -0
  103. package/dist/esm/cli/lib/aiFiles/guidelinesmd.js +28 -0
  104. package/dist/esm/cli/lib/aiFiles/guidelinesmd.js.map +7 -0
  105. package/dist/esm/cli/lib/aiFiles/index.js +210 -0
  106. package/dist/esm/cli/lib/aiFiles/index.js.map +7 -0
  107. package/dist/esm/cli/lib/aiFiles/paths.js.map +7 -0
  108. package/dist/esm/cli/lib/aiFiles/skills.js +147 -0
  109. package/dist/esm/cli/lib/aiFiles/skills.js.map +7 -0
  110. package/dist/esm/cli/lib/aiFiles/status.js +175 -0
  111. package/dist/esm/cli/lib/aiFiles/status.js.map +7 -0
  112. package/dist/esm/cli/lib/aiFiles/utils.js +82 -0
  113. package/dist/esm/cli/lib/aiFiles/utils.js.map +7 -0
  114. package/dist/esm/cli/lib/command.js +6 -1
  115. package/dist/esm/cli/lib/command.js.map +2 -2
  116. package/dist/esm/cli/lib/config.js +3 -4
  117. package/dist/esm/cli/lib/config.js.map +2 -2
  118. package/dist/esm/cli/lib/localDeployment/anonymous.js +2 -2
  119. package/dist/esm/cli/lib/localDeployment/anonymous.js.map +2 -2
  120. package/dist/esm/cli/lib/updates.js +8 -8
  121. package/dist/esm/cli/lib/updates.js.map +2 -2
  122. package/dist/esm/cli/lib/versionApi.js +7 -4
  123. package/dist/esm/cli/lib/versionApi.js.map +2 -2
  124. package/dist/esm/cli/lib/workos/workos.js +4 -6
  125. package/dist/esm/cli/lib/workos/workos.js.map +2 -2
  126. package/dist/esm/index.js +1 -1
  127. package/dist/esm/index.js.map +1 -1
  128. package/dist/esm-types/browser/sync/authentication_manager.d.ts.map +1 -1
  129. package/dist/esm-types/browser/sync/web_socket_manager.d.ts.map +1 -1
  130. package/dist/esm-types/cli/aiFiles.d.ts.map +1 -1
  131. package/dist/esm-types/cli/configure.d.ts.map +1 -1
  132. package/dist/esm-types/cli/lib/aiFiles/agentsmd.d.ts +19 -0
  133. package/dist/esm-types/cli/lib/aiFiles/agentsmd.d.ts.map +1 -0
  134. package/dist/esm-types/cli/lib/aiFiles/agentsmd.test.d.ts +2 -0
  135. package/dist/esm-types/cli/lib/aiFiles/agentsmd.test.d.ts.map +1 -0
  136. package/dist/esm-types/cli/lib/aiFiles/claudemd.d.ts +19 -0
  137. package/dist/esm-types/cli/lib/aiFiles/claudemd.d.ts.map +1 -0
  138. package/dist/esm-types/cli/lib/aiFiles/claudemd.test.d.ts +2 -0
  139. package/dist/esm-types/cli/lib/aiFiles/claudemd.test.d.ts.map +1 -0
  140. package/dist/esm-types/cli/lib/aiFiles/config.d.ts +46 -0
  141. package/dist/esm-types/cli/lib/aiFiles/config.d.ts.map +1 -0
  142. package/dist/esm-types/cli/lib/aiFiles/config.test.d.ts.map +1 -0
  143. package/dist/esm-types/cli/lib/aiFiles/cursorrules.d.ts +10 -0
  144. package/dist/esm-types/cli/lib/aiFiles/cursorrules.d.ts.map +1 -0
  145. package/dist/esm-types/cli/lib/aiFiles/guidelinesmd.d.ts +12 -0
  146. package/dist/esm-types/cli/lib/aiFiles/guidelinesmd.d.ts.map +1 -0
  147. package/dist/esm-types/cli/lib/aiFiles/guidelinesmd.test.d.ts +2 -0
  148. package/dist/esm-types/cli/lib/aiFiles/guidelinesmd.test.d.ts.map +1 -0
  149. package/dist/esm-types/cli/lib/aiFiles/index.d.ts +40 -0
  150. package/dist/esm-types/cli/lib/aiFiles/index.d.ts.map +1 -0
  151. package/dist/esm-types/cli/lib/aiFiles/index.test.d.ts.map +1 -0
  152. package/dist/esm-types/cli/lib/aiFiles/integration.test.d.ts.map +1 -0
  153. package/dist/esm-types/cli/lib/{ai → aiFiles}/paths.d.ts +4 -0
  154. package/dist/esm-types/cli/lib/aiFiles/paths.d.ts.map +1 -0
  155. package/dist/esm-types/cli/lib/aiFiles/prompt.test.d.ts.map +1 -0
  156. package/dist/esm-types/cli/lib/aiFiles/skills.d.ts +18 -0
  157. package/dist/esm-types/cli/lib/aiFiles/skills.d.ts.map +1 -0
  158. package/dist/esm-types/cli/lib/aiFiles/status.d.ts +3 -0
  159. package/dist/esm-types/cli/lib/aiFiles/status.d.ts.map +1 -0
  160. package/dist/esm-types/cli/lib/aiFiles/utils.d.ts +46 -0
  161. package/dist/esm-types/cli/lib/aiFiles/utils.d.ts.map +1 -0
  162. package/dist/esm-types/cli/lib/config.d.ts +1 -0
  163. package/dist/esm-types/cli/lib/config.d.ts.map +1 -1
  164. package/dist/esm-types/cli/lib/versionApi.d.ts +7 -1
  165. package/dist/esm-types/cli/lib/versionApi.d.ts.map +1 -1
  166. package/dist/esm-types/cli/lib/workos/workos.d.ts.map +1 -1
  167. package/dist/esm-types/index.d.ts +1 -1
  168. package/dist/react.bundle.js +6 -9
  169. package/dist/react.bundle.js.map +2 -2
  170. package/package.json +1 -1
  171. package/schemas/convex.schema.json +7 -1
  172. package/src/browser/sync/authentication_manager.ts +9 -4
  173. package/src/browser/sync/client_node.test.ts +125 -0
  174. package/src/browser/sync/web_socket_manager.ts +1 -7
  175. package/src/cli/aiFiles.ts +20 -27
  176. package/src/cli/configure.ts +17 -11
  177. package/src/cli/deploymentSelection.test.ts +56 -2
  178. package/src/cli/lib/{ai → aiFiles}/MANUAL_TESTING.md +6 -2
  179. package/src/cli/lib/aiFiles/agentsmd.test.ts +133 -0
  180. package/src/cli/lib/aiFiles/agentsmd.ts +77 -0
  181. package/src/cli/lib/aiFiles/claudemd.test.ts +92 -0
  182. package/src/cli/lib/aiFiles/claudemd.ts +77 -0
  183. package/src/cli/lib/{ai → aiFiles}/config.test.ts +181 -59
  184. package/src/cli/lib/{ai → aiFiles}/config.ts +92 -63
  185. package/src/cli/lib/aiFiles/cursorrules.ts +25 -0
  186. package/src/cli/lib/aiFiles/guidelinesmd.test.ts +40 -0
  187. package/src/cli/lib/aiFiles/guidelinesmd.ts +41 -0
  188. package/src/cli/lib/{ai → aiFiles}/index.test.ts +200 -339
  189. package/src/cli/lib/aiFiles/index.ts +303 -0
  190. package/src/cli/lib/{ai → aiFiles}/integration.test.ts +117 -147
  191. package/src/cli/lib/{ai → aiFiles}/paths.ts +5 -0
  192. package/src/cli/lib/{ai → aiFiles}/prompt.test.ts +78 -30
  193. package/src/cli/lib/aiFiles/skills.ts +213 -0
  194. package/src/cli/lib/aiFiles/status.ts +240 -0
  195. package/src/cli/lib/aiFiles/utils.ts +163 -0
  196. package/src/cli/lib/command.ts +6 -1
  197. package/src/cli/lib/config.test.ts +1 -1
  198. package/src/cli/lib/config.ts +6 -5
  199. package/src/cli/lib/localDeployment/anonymous.ts +2 -2
  200. package/src/cli/lib/updates.test.ts +40 -30
  201. package/src/cli/lib/updates.ts +8 -8
  202. package/src/cli/lib/versionApi.test.ts +13 -10
  203. package/src/cli/lib/versionApi.ts +13 -5
  204. package/src/cli/lib/workos/workos.ts +4 -5
  205. package/src/index.ts +1 -1
  206. package/src/values/.claude/settings.local.json +10 -0
  207. package/dist/cjs/cli/lib/ai/config.js.map +0 -7
  208. package/dist/cjs/cli/lib/ai/index.js +0 -704
  209. package/dist/cjs/cli/lib/ai/index.js.map +0 -7
  210. package/dist/cjs/cli/lib/ai/paths.js.map +0 -7
  211. package/dist/cjs-types/cli/lib/ai/config.d.ts +0 -50
  212. package/dist/cjs-types/cli/lib/ai/config.d.ts.map +0 -1
  213. package/dist/cjs-types/cli/lib/ai/config.test.d.ts.map +0 -1
  214. package/dist/cjs-types/cli/lib/ai/index.d.ts +0 -56
  215. package/dist/cjs-types/cli/lib/ai/index.d.ts.map +0 -1
  216. package/dist/cjs-types/cli/lib/ai/index.test.d.ts.map +0 -1
  217. package/dist/cjs-types/cli/lib/ai/integration.test.d.ts.map +0 -1
  218. package/dist/cjs-types/cli/lib/ai/paths.d.ts.map +0 -1
  219. package/dist/cjs-types/cli/lib/ai/prompt.test.d.ts.map +0 -1
  220. package/dist/esm/cli/lib/ai/config.js.map +0 -7
  221. package/dist/esm/cli/lib/ai/index.js +0 -684
  222. package/dist/esm/cli/lib/ai/index.js.map +0 -7
  223. package/dist/esm/cli/lib/ai/paths.js.map +0 -7
  224. package/dist/esm-types/cli/lib/ai/config.d.ts +0 -50
  225. package/dist/esm-types/cli/lib/ai/config.d.ts.map +0 -1
  226. package/dist/esm-types/cli/lib/ai/config.test.d.ts.map +0 -1
  227. package/dist/esm-types/cli/lib/ai/index.d.ts +0 -56
  228. package/dist/esm-types/cli/lib/ai/index.d.ts.map +0 -1
  229. package/dist/esm-types/cli/lib/ai/index.test.d.ts.map +0 -1
  230. package/dist/esm-types/cli/lib/ai/integration.test.d.ts.map +0 -1
  231. package/dist/esm-types/cli/lib/ai/paths.d.ts.map +0 -1
  232. package/dist/esm-types/cli/lib/ai/prompt.test.d.ts.map +0 -1
  233. package/src/cli/lib/ai/index.ts +0 -1006
  234. /package/dist/cjs/cli/lib/{ai → aiFiles}/paths.js +0 -0
  235. /package/dist/cjs-types/cli/lib/{ai → aiFiles}/config.test.d.ts +0 -0
  236. /package/dist/cjs-types/cli/lib/{ai → aiFiles}/index.test.d.ts +0 -0
  237. /package/dist/cjs-types/cli/lib/{ai → aiFiles}/integration.test.d.ts +0 -0
  238. /package/dist/cjs-types/cli/lib/{ai → aiFiles}/prompt.test.d.ts +0 -0
  239. /package/dist/esm/cli/lib/{ai → aiFiles}/paths.js +0 -0
  240. /package/dist/esm-types/cli/lib/{ai → aiFiles}/config.test.d.ts +0 -0
  241. /package/dist/esm-types/cli/lib/{ai → aiFiles}/index.test.d.ts +0 -0
  242. /package/dist/esm-types/cli/lib/{ai → aiFiles}/integration.test.d.ts +0 -0
  243. /package/dist/esm-types/cli/lib/{ai → aiFiles}/prompt.test.d.ts +0 -0
@@ -0,0 +1,163 @@
1
+ // eslint-disable-next-line no-restricted-imports
2
+ import { promises as fs } from "fs";
3
+ import { chalkStderr } from "chalk";
4
+ import { logMessage } from "../../../bundler/log.js";
5
+ import { hashSha256 } from "../utils/hash.js";
6
+
7
+ export function isInInteractiveTerminal(): boolean {
8
+ return process.stdin.isTTY === true;
9
+ }
10
+
11
+ export async function readFileSafe(filePath: string): Promise<string | null> {
12
+ try {
13
+ return await fs.readFile(filePath, "utf8");
14
+ } catch {
15
+ return null;
16
+ }
17
+ }
18
+
19
+ /**
20
+ * Attempt to delete a file. Returns `true` if the file was deleted,
21
+ * `false` if it didn't exist or the deletion failed.
22
+ */
23
+ export async function safelyDeleteFile(filePath: string): Promise<boolean> {
24
+ try {
25
+ await fs.unlink(filePath);
26
+ return true;
27
+ } catch {
28
+ return false;
29
+ }
30
+ }
31
+
32
+ // ---------------------------------------------------------------------------
33
+ // Generic managed-section helpers
34
+ //
35
+ // Several files (AGENTS.md, CLAUDE.md) contain a Convex-managed section
36
+ // delimited by start/end markers. These helpers provide the common logic
37
+ // for injecting, stripping, and detecting those sections.
38
+ // ---------------------------------------------------------------------------
39
+
40
+ export type ManagedSectionTarget = {
41
+ filePath: string;
42
+ startMarker: string;
43
+ endMarker: string;
44
+ };
45
+
46
+ export type InjectResult = {
47
+ sectionHash: string;
48
+ didWrite: boolean;
49
+ };
50
+
51
+ export const iife = <T>(fn: () => T): T => fn();
52
+
53
+ /**
54
+ * Inject a managed section into a file. If the file already contains the
55
+ * markers, the section between them is replaced. Otherwise the section is
56
+ * appended (or the file is created). Only writes when content actually
57
+ * changes.
58
+ */
59
+ export async function injectManagedSection(
60
+ opts: ManagedSectionTarget & { section: string },
61
+ ): Promise<InjectResult> {
62
+ const { filePath, startMarker, endMarker, section } = opts;
63
+
64
+ const existing = (await readFileSafe(filePath)) ?? "";
65
+
66
+ const startIdx = existing.indexOf(startMarker);
67
+ const endIdx = existing.indexOf(endMarker);
68
+
69
+ const updated = iife(() => {
70
+ if (startIdx !== -1 && endIdx !== -1)
71
+ return (
72
+ existing.slice(0, startIdx) +
73
+ section +
74
+ existing.slice(endIdx + endMarker.length)
75
+ );
76
+ if (existing.length > 0)
77
+ return existing.trimEnd() + "\n\n" + section + "\n";
78
+
79
+ return section + "\n";
80
+ });
81
+
82
+ const didWrite = updated !== existing;
83
+ if (didWrite) await fs.writeFile(filePath, updated, "utf8");
84
+
85
+ return { sectionHash: hashSha256(section), didWrite };
86
+ }
87
+
88
+ export type StripResult = "none" | "section" | "file";
89
+
90
+ /**
91
+ * Remove the managed section (between start/end markers) from a file.
92
+ * If the file is empty after removal, it is deleted.
93
+ *
94
+ * Returns `"none"` if the file doesn't exist or has no markers,
95
+ * `"section"` if the section was stripped, or `"file"` if the entire
96
+ * file was deleted.
97
+ */
98
+ export async function stripManagedSection(
99
+ opts: ManagedSectionTarget,
100
+ ): Promise<StripResult> {
101
+ const { filePath, startMarker, endMarker } = opts;
102
+
103
+ const content = await readFileSafe(filePath);
104
+ if (content === null) return "none";
105
+
106
+ const startIdx = content.indexOf(startMarker);
107
+ const endIdx = content.indexOf(endMarker);
108
+ if (startIdx === -1 || endIdx === -1) {
109
+ return "none";
110
+ }
111
+
112
+ const before = content.slice(0, startIdx).trimEnd();
113
+ const after = content.slice(endIdx + endMarker.length).trimStart();
114
+ const updated = [before, after].filter(Boolean).join("\n\n");
115
+
116
+ if (!updated.trim()) {
117
+ await safelyDeleteFile(filePath);
118
+ return "file";
119
+ }
120
+
121
+ await fs.writeFile(filePath, updated + "\n", "utf8");
122
+ return "section";
123
+ }
124
+
125
+ export async function removeMarkdownSection({
126
+ projectDir,
127
+ strip,
128
+ fileName,
129
+ }: {
130
+ projectDir: string;
131
+ strip: (dir: string) => Promise<StripResult>;
132
+ fileName: string;
133
+ }): Promise<boolean> {
134
+ const result = await strip(projectDir);
135
+
136
+ if (result === "section") {
137
+ logMessage(
138
+ `${chalkStderr.green("✔")} Removed Convex section from ${fileName}.`,
139
+ );
140
+ return true;
141
+ }
142
+
143
+ if (result === "file") {
144
+ logMessage(`${chalkStderr.green("✔")} Deleted ${fileName}.`);
145
+ return true;
146
+ }
147
+
148
+ return false;
149
+ }
150
+
151
+ /**
152
+ * Check whether a file contains a managed section (both markers present).
153
+ */
154
+ export async function hasManagedSection(
155
+ opts: ManagedSectionTarget,
156
+ ): Promise<boolean> {
157
+ const content = await readFileSafe(opts.filePath);
158
+ return (
159
+ content !== null &&
160
+ content.includes(opts.startMarker) &&
161
+ content.includes(opts.endMarker)
162
+ );
163
+ }
@@ -333,7 +333,12 @@ Command.prototype.addDeployOptions = function () {
333
333
  "--dry-run",
334
334
  "Print out the generated configuration without deploying to your Convex deployment",
335
335
  )
336
- .option("-y, --yes", "Skip confirmation prompt when running locally")
336
+ .addOption(
337
+ new Option(
338
+ "-y, --yes",
339
+ "Skip confirmation prompt when running interactively. Warning: this deploys to PRODUCTION. To deploy to your current dev environment, run npx convex dev --once",
340
+ ).hideHelp(),
341
+ )
337
342
  .addOption(
338
343
  new Option(
339
344
  "--typecheck <mode>",
@@ -327,7 +327,7 @@ test("readProjectConfig - returns defaults when file doesn't exist", async () =>
327
327
  node: { externalPackages: [] },
328
328
  generateCommonJSApi: false,
329
329
  codegen: { staticApi: false, staticDataModel: false },
330
- aiFiles: { disableStalenessMessage: false },
330
+ aiFiles: {},
331
331
  });
332
332
  });
333
333
 
@@ -102,7 +102,9 @@ export interface ProjectConfig {
102
102
 
103
103
  // Convex AI files user preferences.
104
104
  aiFiles?: {
105
- // When true, suppresses AI files install/staleness nags.
105
+ // When false, disables all AI files prompts and staleness messages.
106
+ enabled?: boolean;
107
+ // @deprecated use `enabled` instead.
106
108
  disableStalenessMessage?: boolean;
107
109
  };
108
110
  }
@@ -289,7 +291,8 @@ const BundlerSchema = z.object({
289
291
  });
290
292
 
291
293
  const AiFilesSchema = z.object({
292
- disableStalenessMessage: z.boolean().default(false),
294
+ enabled: z.boolean().optional(),
295
+ disableStalenessMessage: z.boolean().optional(),
293
296
  });
294
297
 
295
298
  const refineToObject = <T extends z.ZodTypeAny>(schema: T) =>
@@ -553,9 +556,7 @@ export async function readProjectConfig(ctx: Context): Promise<{
553
556
  staticApi: false,
554
557
  staticDataModel: false,
555
558
  },
556
- aiFiles: {
557
- disableStalenessMessage: false,
558
- },
559
+ aiFiles: {},
559
560
  },
560
561
  configPath: configName(),
561
562
  };
@@ -48,7 +48,7 @@ import { nodeFs } from "../../../bundler/fs.js";
48
48
  import { doInitConvexFolder } from "../codegen.js";
49
49
  import { readProjectConfig } from "../config.js";
50
50
  import { functionsDir } from "../utils/utils.js";
51
- import { maybeSetupAiFiles } from "../ai/index.js";
51
+ import { maybeSetupAiFiles } from "../aiFiles/index.js";
52
52
 
53
53
  export async function handleAnonymousDeployment(
54
54
  ctx: Context,
@@ -187,7 +187,7 @@ export async function handleAnonymousDeployment(
187
187
  const { configPath, projectConfig } = await readProjectConfig(ctx);
188
188
  const convexDir = path.resolve(functionsDir(configPath, projectConfig));
189
189
  const projectDir = path.resolve(path.dirname(configPath));
190
- await maybeSetupAiFiles(ctx, convexDir, projectDir);
190
+ await maybeSetupAiFiles({ ctx, convexDir, projectDir });
191
191
  }
192
192
  return {
193
193
  adminKey,
@@ -2,7 +2,7 @@ import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
2
2
  import { checkVersion } from "./updates.js";
3
3
  import { getVersion } from "./versionApi.js";
4
4
  import { logMessage } from "../../bundler/log.js";
5
- import { checkAiFilesStaleness } from "./ai/index.js";
5
+ import { checkAiFilesStaleness } from "./aiFiles/index.js";
6
6
  import { readProjectConfig } from "./config.js";
7
7
  import type { Context } from "../../bundler/context.js";
8
8
 
@@ -10,7 +10,7 @@ vi.mock("./versionApi.js", () => ({
10
10
  getVersion: vi.fn(),
11
11
  }));
12
12
 
13
- vi.mock("./ai/index.js", () => ({
13
+ vi.mock("./aiFiles/index.js", () => ({
14
14
  checkAiFilesStaleness: vi.fn(),
15
15
  }));
16
16
 
@@ -52,11 +52,14 @@ describe("updates", () => {
52
52
  it("logs message and passes both hashes to staleness check", async () => {
53
53
  const sha = "abc123def456abc123def456abc123def456abc1";
54
54
  mockGetVersion.mockResolvedValue({
55
- message: "New version available: 1.2.3",
56
- guidelinesHash:
57
- "02e43fc1ff0ee48db8da468f5c7525877d8056fcd56c77d78a166ac447efb91c",
58
- agentSkillsSha: sha,
59
- disableSkillsCli: false,
55
+ kind: "ok",
56
+ data: {
57
+ message: "New version available: 1.2.3",
58
+ guidelinesHash:
59
+ "02e43fc1ff0ee48db8da468f5c7525877d8056fcd56c77d78a166ac447efb91c",
60
+ agentSkillsSha: sha,
61
+ disableSkillsCli: false,
62
+ },
60
63
  });
61
64
 
62
65
  await checkVersion(fakeCtx);
@@ -65,21 +68,25 @@ describe("updates", () => {
65
68
  expect(mockLogMessage).toHaveBeenCalledWith(
66
69
  "New version available: 1.2.3",
67
70
  );
68
- expect(mockCheckAiFilesStaleness).toHaveBeenCalledWith(
69
- "02e43fc1ff0ee48db8da468f5c7525877d8056fcd56c77d78a166ac447efb91c",
70
- sha,
71
- expect.any(String),
72
- expect.any(String),
73
- );
71
+ expect(mockCheckAiFilesStaleness).toHaveBeenCalledWith({
72
+ canonicalGuidelinesHash:
73
+ "02e43fc1ff0ee48db8da468f5c7525877d8056fcd56c77d78a166ac447efb91c",
74
+ canonicalAgentSkillsSha: sha,
75
+ projectDir: expect.any(String),
76
+ convexDir: expect.any(String),
77
+ });
74
78
  });
75
79
 
76
80
  it("does not log when version has no message", async () => {
77
81
  mockGetVersion.mockResolvedValue({
78
- message: null,
79
- guidelinesHash:
80
- "02e43fc1ff0ee48db8da468f5c7525877d8056fcd56c77d78a166ac447efb91c",
81
- agentSkillsSha: null,
82
- disableSkillsCli: false,
82
+ kind: "ok",
83
+ data: {
84
+ message: null,
85
+ guidelinesHash:
86
+ "02e43fc1ff0ee48db8da468f5c7525877d8056fcd56c77d78a166ac447efb91c",
87
+ agentSkillsSha: null,
88
+ disableSkillsCli: false,
89
+ },
83
90
  });
84
91
 
85
92
  await checkVersion(fakeCtx);
@@ -88,8 +95,8 @@ describe("updates", () => {
88
95
  expect(mockLogMessage).not.toHaveBeenCalled();
89
96
  });
90
97
 
91
- it("doesn't do anything when getVersion returns null", async () => {
92
- mockGetVersion.mockResolvedValue(null);
98
+ it("doesn't do anything when getVersion returns error", async () => {
99
+ mockGetVersion.mockResolvedValue({ kind: "error" });
93
100
 
94
101
  await checkVersion(fakeCtx);
95
102
 
@@ -100,20 +107,23 @@ describe("updates", () => {
100
107
 
101
108
  it("passes null hashes to staleness check when version has none", async () => {
102
109
  mockGetVersion.mockResolvedValue({
103
- message: "New version available: 1.2.3",
104
- guidelinesHash: null,
105
- agentSkillsSha: null,
106
- disableSkillsCli: false,
110
+ kind: "ok",
111
+ data: {
112
+ message: "New version available: 1.2.3",
113
+ guidelinesHash: null,
114
+ agentSkillsSha: null,
115
+ disableSkillsCli: false,
116
+ },
107
117
  });
108
118
 
109
119
  await checkVersion(fakeCtx);
110
120
 
111
- expect(mockCheckAiFilesStaleness).toHaveBeenCalledWith(
112
- null,
113
- null,
114
- expect.any(String),
115
- expect.any(String),
116
- );
121
+ expect(mockCheckAiFilesStaleness).toHaveBeenCalledWith({
122
+ canonicalGuidelinesHash: null,
123
+ canonicalAgentSkillsSha: null,
124
+ projectDir: expect.any(String),
125
+ convexDir: expect.any(String),
126
+ });
117
127
  });
118
128
  });
119
129
  });
@@ -3,7 +3,7 @@ import { logMessage } from "../../bundler/log.js";
3
3
  import type { Context } from "../../bundler/context.js";
4
4
  import { readProjectConfig } from "./config.js";
5
5
  import { functionsDir } from "./utils/utils.js";
6
- import { checkAiFilesStaleness } from "./ai/index.js";
6
+ import { checkAiFilesStaleness } from "./aiFiles/index.js";
7
7
  import { getVersion } from "./versionApi.js";
8
8
 
9
9
  /**
@@ -13,24 +13,24 @@ import { getVersion } from "./versionApi.js";
13
13
  export async function checkVersion(ctx: Context) {
14
14
  const version = await getVersion();
15
15
 
16
- if (version === null) {
16
+ if (version.kind === "error") {
17
17
  return;
18
18
  }
19
19
 
20
- if (version.message) {
21
- logMessage(version.message);
20
+ if (version.data.message) {
21
+ logMessage(version.data.message);
22
22
  }
23
23
 
24
24
  try {
25
25
  const { configPath, projectConfig } = await readProjectConfig(ctx);
26
26
  const convexDir = path.resolve(functionsDir(configPath, projectConfig));
27
27
  const projectDir = path.resolve(path.dirname(configPath));
28
- await checkAiFilesStaleness(
29
- version.guidelinesHash,
30
- version.agentSkillsSha,
28
+ await checkAiFilesStaleness({
29
+ canonicalGuidelinesHash: version.data.guidelinesHash,
30
+ canonicalAgentSkillsSha: version.data.agentSkillsSha,
31
31
  projectDir,
32
32
  convexDir,
33
- );
33
+ });
34
34
  } catch {
35
35
  // Non-fatal: skip staleness check if project config can't be resolved.
36
36
  }
@@ -40,10 +40,13 @@ describe("versionApi", () => {
40
40
  const result = await getVersion();
41
41
 
42
42
  expect(result).toEqual({
43
- message: "New version available",
44
- guidelinesHash: null,
45
- agentSkillsSha: sha,
46
- disableSkillsCli: false,
43
+ kind: "ok",
44
+ data: {
45
+ message: "New version available",
46
+ guidelinesHash: null,
47
+ agentSkillsSha: sha,
48
+ disableSkillsCli: false,
49
+ },
47
50
  });
48
51
  expect(mockFetch).toHaveBeenCalledWith(
49
52
  "https://version.convex.dev/v1/version",
@@ -59,15 +62,15 @@ describe("versionApi", () => {
59
62
  );
60
63
  });
61
64
 
62
- it("returns null on network error", async () => {
65
+ it("returns error on network error", async () => {
63
66
  mockFetch.mockRejectedValue(new Error("Network error"));
64
67
 
65
68
  const result = await getVersion();
66
69
 
67
- expect(result).toBeNull();
70
+ expect(result).toEqual({ kind: "error" });
68
71
  });
69
72
 
70
- it("returns null on non-ok response", async () => {
73
+ it("returns error on non-ok response", async () => {
71
74
  const mockResponse = {
72
75
  ok: false,
73
76
  status: 500,
@@ -76,10 +79,10 @@ describe("versionApi", () => {
76
79
 
77
80
  const result = await getVersion();
78
81
 
79
- expect(result).toBeNull();
82
+ expect(result).toEqual({ kind: "error" });
80
83
  });
81
84
 
82
- it("returns null on invalid JSON response", async () => {
85
+ it("returns error on invalid JSON response", async () => {
83
86
  const mockResponse = {
84
87
  ok: true,
85
88
  json: vi.fn().mockResolvedValue("invalid json"),
@@ -88,7 +91,7 @@ describe("versionApi", () => {
88
91
 
89
92
  const result = await getVersion();
90
93
 
91
- expect(result).toBeNull();
94
+ expect(result).toEqual({ kind: "error" });
92
95
  });
93
96
  });
94
97
 
@@ -20,7 +20,11 @@ export type VersionResult = {
20
20
  disableSkillsCli: boolean;
21
21
  };
22
22
 
23
- export async function getVersion(): Promise<VersionResult | null> {
23
+ export type VersionFetchResult =
24
+ | { kind: "ok"; data: VersionResult }
25
+ | { kind: "error" };
26
+
27
+ export async function getVersion(): Promise<VersionFetchResult> {
24
28
  try {
25
29
  const req = await fetch(VERSION_ENDPOINT, {
26
30
  headers: HEADERS,
@@ -30,14 +34,17 @@ export async function getVersion(): Promise<VersionResult | null> {
30
34
  Sentry.captureException(
31
35
  new Error(`Failed to fetch version: status = ${req.status}`),
32
36
  );
33
- return null;
37
+ return { kind: "error" };
34
38
  }
35
39
 
36
40
  const json = await req.json();
37
- return validateVersionResult(json);
41
+ const result = validateVersionResult(json);
42
+
43
+ if (result === null) return { kind: "error" };
44
+ return { kind: "ok", data: result };
38
45
  } catch (error) {
39
46
  Sentry.captureException(error);
40
- return null;
47
+ return { kind: "error" };
41
48
  }
42
49
  }
43
50
 
@@ -71,7 +78,8 @@ export function validateVersionResult(json: any): VersionResult | null {
71
78
  /** Fetch the latest agent skills SHA from version.convex.dev. */
72
79
  export async function fetchAgentSkillsSha(): Promise<string | null> {
73
80
  const versionData = await getVersion();
74
- return versionData?.agentSkillsSha ?? null;
81
+ if (versionData.kind === "error") return null;
82
+ return versionData.data.agentSkillsSha;
75
83
  }
76
84
 
77
85
  export async function downloadGuidelines(): Promise<string | null> {
@@ -618,12 +618,11 @@ export async function tryToCreateAssociatedWorkosTeam(
618
618
  );
619
619
 
620
620
  if (!result.success) {
621
- const dashboardUrl = deploymentDashboardUrlPage(
622
- deploymentName,
623
- `/settings/environment-variables?var=WORKOS_CLIENT_ID`,
624
- );
625
621
  logMessage(
626
- `To provide your own WorkOS environment credentials instead, set environment variables manually on the dashboard:\n ${dashboardUrl}`,
622
+ `To provide your own WorkOS environment credentials instead, set environment variables manually:
623
+
624
+ npx convex env set WORKOS_CLIENT_ID $YOUR_CLIENT_ID_HERE
625
+ npx convex env set WORKOS_API_KEY $YOUR_API_KEY_HERE`,
627
626
  );
628
627
  return "choseNotToAssociatedTeam";
629
628
  }
package/src/index.ts CHANGED
@@ -1 +1 @@
1
- export const version = "1.34.0";
1
+ export const version = "1.34.1";
@@ -0,0 +1,10 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Read(//Users/ianmacartney/src/convex-core/npm-packages/convex/**)",
5
+ "Bash(npx vitest:*)"
6
+ ],
7
+ "deny": [],
8
+ "ask": []
9
+ }
10
+ }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../../src/cli/lib/ai/config.ts"],
4
- "sourcesContent": ["import * as Sentry from \"@sentry/node\";\n// Use raw fs (not ctx.fs) so these operations run asynchronously and don't\n// interfere with the file-watcher used by `convex dev`.\n// eslint-disable-next-line no-restricted-imports\nimport { promises as fs } from \"fs\";\nimport path from \"path\";\nimport { z } from \"zod\";\nimport { aiFilesStatePathForConvexDir } from \"./paths.js\";\n\nconst aiFilesStateSchema = z.object({\n guidelinesHash: z.string().nullable(),\n agentsMdSectionHash: z.string().nullable(),\n claudeMdHash: z.string().nullable(),\n // Commit SHA from get-convex/agent-skills that was current when skills were\n // last installed. Used to detect when newer skills are available.\n agentSkillsSha: z.string().nullable(),\n // Names of skills installed by `npx skills add`, used by `remove` to\n // only remove Convex-managed skills.\n installedSkillNames: z.array(z.string()).default([]),\n});\n\nconst aiFilesProjectConfigSchema = z\n .object({\n aiFiles: z\n .object({\n disableStalenessMessage: z.boolean().default(false),\n })\n .default({ disableStalenessMessage: false }),\n })\n .passthrough();\n\nexport const aiFilesSchema = aiFilesStateSchema;\n\ntype AiFilesState = z.infer<typeof aiFilesStateSchema>;\nexport type AiFilesConfig = AiFilesState & {\n disableStalenessMessage: boolean;\n};\n\nconst EMPTY_AI_STATE: AiFilesState = {\n guidelinesHash: null,\n agentsMdSectionHash: null,\n claudeMdHash: null,\n agentSkillsSha: null,\n installedSkillNames: [],\n};\n\nasync function readAiDisabledFromProjectConfig(\n projectDir: string,\n): Promise<boolean> {\n let raw: string;\n try {\n raw = await fs.readFile(path.join(projectDir, \"convex.json\"), \"utf8\");\n } catch {\n return false;\n }\n try {\n const parsed = aiFilesProjectConfigSchema.parse(JSON.parse(raw));\n return parsed.aiFiles.disableStalenessMessage;\n } catch (err) {\n Sentry.captureException(err);\n return false;\n }\n}\n\nexport async function writeAiDisabledToProjectConfig(\n disableStalenessMessage: boolean,\n projectDir: string,\n): Promise<void> {\n const filePath = path.join(projectDir, \"convex.json\");\n let existing: unknown = {};\n try {\n existing = JSON.parse(await fs.readFile(filePath, \"utf8\"));\n } catch {\n // Use a minimal object when convex.json doesn't exist yet or is unreadable.\n }\n const base =\n existing !== null &&\n typeof existing === \"object\" &&\n !Array.isArray(existing)\n ? (existing as Record<string, unknown>)\n : {};\n const aiFilesValue =\n base.aiFiles !== null &&\n typeof base.aiFiles === \"object\" &&\n !Array.isArray(base.aiFiles)\n ? (base.aiFiles as Record<string, unknown>)\n : {};\n const { $schema, ...rest } = base;\n const next: Record<string, unknown> = {\n $schema: $schema ?? \"node_modules/convex/schemas/convex.schema.json\",\n ...rest,\n aiFiles: {\n ...aiFilesValue,\n disableStalenessMessage,\n },\n };\n await fs.writeFile(filePath, JSON.stringify(next, null, 2) + \"\\n\", \"utf8\");\n}\n\nexport async function readAiConfig(\n projectDir: string,\n convexDir: string,\n): Promise<AiFilesConfig | null> {\n const disableStalenessMessage =\n await readAiDisabledFromProjectConfig(projectDir);\n let rawState: string;\n try {\n rawState = await fs.readFile(\n aiFilesStatePathForConvexDir(convexDir),\n \"utf8\",\n );\n } catch {\n // No state file means AI files are not installed, unless the user has\n // explicitly disabled install/staleness messages in convex.json.\n return disableStalenessMessage\n ? { ...EMPTY_AI_STATE, disableStalenessMessage }\n : null;\n }\n try {\n const state = aiFilesStateSchema.parse(JSON.parse(rawState));\n return {\n ...state,\n disableStalenessMessage,\n };\n } catch (err) {\n Sentry.captureException(err);\n return null;\n }\n}\n\nexport async function writeAiConfig(\n config: AiFilesConfig,\n projectDir: string,\n convexDir: string,\n options?: { persistDisabledPreference?: \"ifTrue\" | \"always\" | \"never\" },\n): Promise<void> {\n const state = aiFilesStateSchema.parse({\n guidelinesHash: config.guidelinesHash,\n agentsMdSectionHash: config.agentsMdSectionHash,\n claudeMdHash: config.claudeMdHash,\n agentSkillsSha: config.agentSkillsSha,\n installedSkillNames: config.installedSkillNames,\n });\n await fs.writeFile(\n aiFilesStatePathForConvexDir(convexDir),\n JSON.stringify(state, null, 2) + \"\\n\",\n \"utf8\",\n );\n const persistMode = options?.persistDisabledPreference ?? \"ifTrue\";\n if (\n persistMode === \"always\" ||\n (persistMode === \"ifTrue\" && config.disableStalenessMessage)\n ) {\n await writeAiDisabledToProjectConfig(\n config.disableStalenessMessage,\n projectDir,\n );\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["fs", "path"]
7
- }