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.
- package/CHANGELOG.md +12 -0
- package/dist/browser.bundle.js +6 -9
- package/dist/browser.bundle.js.map +2 -2
- package/dist/cjs/browser/sync/authentication_manager.js +4 -1
- package/dist/cjs/browser/sync/authentication_manager.js.map +2 -2
- package/dist/cjs/browser/sync/web_socket_manager.js +1 -7
- package/dist/cjs/browser/sync/web_socket_manager.js.map +2 -2
- package/dist/cjs/cli/aiFiles.js +15 -14
- package/dist/cjs/cli/aiFiles.js.map +2 -2
- package/dist/cjs/cli/configure.js +15 -10
- package/dist/cjs/cli/configure.js.map +2 -2
- package/dist/cjs/cli/lib/aiFiles/agentsmd.js +69 -0
- package/dist/cjs/cli/lib/aiFiles/agentsmd.js.map +7 -0
- package/dist/cjs/cli/lib/aiFiles/claudemd.js +69 -0
- package/dist/cjs/cli/lib/aiFiles/claudemd.js.map +7 -0
- package/dist/cjs/cli/lib/{ai → aiFiles}/config.js +73 -46
- package/dist/cjs/cli/lib/aiFiles/config.js.map +7 -0
- package/dist/cjs/cli/lib/aiFiles/cursorrules.js +48 -0
- package/dist/cjs/cli/lib/aiFiles/cursorrules.js.map +7 -0
- package/dist/cjs/cli/lib/aiFiles/guidelinesmd.js +51 -0
- package/dist/cjs/cli/lib/aiFiles/guidelinesmd.js.map +7 -0
- package/dist/cjs/cli/lib/aiFiles/index.js +231 -0
- package/dist/cjs/cli/lib/aiFiles/index.js.map +7 -0
- package/dist/cjs/cli/lib/aiFiles/paths.js.map +7 -0
- package/dist/cjs/cli/lib/aiFiles/skills.js +180 -0
- package/dist/cjs/cli/lib/aiFiles/skills.js.map +7 -0
- package/dist/cjs/cli/lib/aiFiles/status.js +195 -0
- package/dist/cjs/cli/lib/aiFiles/status.js.map +7 -0
- package/dist/cjs/cli/lib/aiFiles/utils.js +111 -0
- package/dist/cjs/cli/lib/aiFiles/utils.js.map +7 -0
- package/dist/cjs/cli/lib/command.js +6 -1
- package/dist/cjs/cli/lib/command.js.map +2 -2
- package/dist/cjs/cli/lib/config.js +3 -4
- package/dist/cjs/cli/lib/config.js.map +2 -2
- package/dist/cjs/cli/lib/localDeployment/anonymous.js +2 -2
- package/dist/cjs/cli/lib/localDeployment/anonymous.js.map +2 -2
- package/dist/cjs/cli/lib/updates.js +8 -8
- package/dist/cjs/cli/lib/updates.js.map +2 -2
- package/dist/cjs/cli/lib/versionApi.js +7 -4
- package/dist/cjs/cli/lib/versionApi.js.map +2 -2
- package/dist/cjs/cli/lib/workos/workos.js +4 -6
- package/dist/cjs/cli/lib/workos/workos.js.map +2 -2
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs-types/browser/sync/authentication_manager.d.ts.map +1 -1
- package/dist/cjs-types/browser/sync/web_socket_manager.d.ts.map +1 -1
- package/dist/cjs-types/cli/aiFiles.d.ts.map +1 -1
- package/dist/cjs-types/cli/configure.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/aiFiles/agentsmd.d.ts +19 -0
- package/dist/cjs-types/cli/lib/aiFiles/agentsmd.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/aiFiles/agentsmd.test.d.ts +2 -0
- package/dist/cjs-types/cli/lib/aiFiles/agentsmd.test.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/aiFiles/claudemd.d.ts +19 -0
- package/dist/cjs-types/cli/lib/aiFiles/claudemd.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/aiFiles/claudemd.test.d.ts +2 -0
- package/dist/cjs-types/cli/lib/aiFiles/claudemd.test.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/aiFiles/config.d.ts +46 -0
- package/dist/cjs-types/cli/lib/aiFiles/config.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/aiFiles/config.test.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/aiFiles/cursorrules.d.ts +10 -0
- package/dist/cjs-types/cli/lib/aiFiles/cursorrules.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/aiFiles/guidelinesmd.d.ts +12 -0
- package/dist/cjs-types/cli/lib/aiFiles/guidelinesmd.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/aiFiles/guidelinesmd.test.d.ts +2 -0
- package/dist/cjs-types/cli/lib/aiFiles/guidelinesmd.test.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/aiFiles/index.d.ts +40 -0
- package/dist/cjs-types/cli/lib/aiFiles/index.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/aiFiles/index.test.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/aiFiles/integration.test.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/{ai → aiFiles}/paths.d.ts +4 -0
- package/dist/cjs-types/cli/lib/aiFiles/paths.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/aiFiles/prompt.test.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/aiFiles/skills.d.ts +18 -0
- package/dist/cjs-types/cli/lib/aiFiles/skills.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/aiFiles/status.d.ts +3 -0
- package/dist/cjs-types/cli/lib/aiFiles/status.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/aiFiles/utils.d.ts +46 -0
- package/dist/cjs-types/cli/lib/aiFiles/utils.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/config.d.ts +1 -0
- package/dist/cjs-types/cli/lib/config.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/versionApi.d.ts +7 -1
- package/dist/cjs-types/cli/lib/versionApi.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/workos/workos.d.ts.map +1 -1
- package/dist/cjs-types/index.d.ts +1 -1
- package/dist/cli.bundle.cjs +1605 -1548
- package/dist/cli.bundle.cjs.map +4 -4
- package/dist/esm/browser/sync/authentication_manager.js +4 -1
- package/dist/esm/browser/sync/authentication_manager.js.map +2 -2
- package/dist/esm/browser/sync/web_socket_manager.js +1 -7
- package/dist/esm/browser/sync/web_socket_manager.js.map +2 -2
- package/dist/esm/cli/aiFiles.js +17 -17
- package/dist/esm/cli/aiFiles.js.map +2 -2
- package/dist/esm/cli/configure.js +15 -10
- package/dist/esm/cli/configure.js.map +2 -2
- package/dist/esm/cli/lib/aiFiles/agentsmd.js +52 -0
- package/dist/esm/cli/lib/aiFiles/agentsmd.js.map +7 -0
- package/dist/esm/cli/lib/aiFiles/claudemd.js +52 -0
- package/dist/esm/cli/lib/aiFiles/claudemd.js.map +7 -0
- package/dist/esm/cli/lib/{ai → aiFiles}/config.js +71 -45
- package/dist/esm/cli/lib/aiFiles/config.js.map +7 -0
- package/dist/esm/cli/lib/aiFiles/cursorrules.js +16 -0
- package/dist/esm/cli/lib/aiFiles/cursorrules.js.map +7 -0
- package/dist/esm/cli/lib/aiFiles/guidelinesmd.js +28 -0
- package/dist/esm/cli/lib/aiFiles/guidelinesmd.js.map +7 -0
- package/dist/esm/cli/lib/aiFiles/index.js +210 -0
- package/dist/esm/cli/lib/aiFiles/index.js.map +7 -0
- package/dist/esm/cli/lib/aiFiles/paths.js.map +7 -0
- package/dist/esm/cli/lib/aiFiles/skills.js +147 -0
- package/dist/esm/cli/lib/aiFiles/skills.js.map +7 -0
- package/dist/esm/cli/lib/aiFiles/status.js +175 -0
- package/dist/esm/cli/lib/aiFiles/status.js.map +7 -0
- package/dist/esm/cli/lib/aiFiles/utils.js +82 -0
- package/dist/esm/cli/lib/aiFiles/utils.js.map +7 -0
- package/dist/esm/cli/lib/command.js +6 -1
- package/dist/esm/cli/lib/command.js.map +2 -2
- package/dist/esm/cli/lib/config.js +3 -4
- package/dist/esm/cli/lib/config.js.map +2 -2
- package/dist/esm/cli/lib/localDeployment/anonymous.js +2 -2
- package/dist/esm/cli/lib/localDeployment/anonymous.js.map +2 -2
- package/dist/esm/cli/lib/updates.js +8 -8
- package/dist/esm/cli/lib/updates.js.map +2 -2
- package/dist/esm/cli/lib/versionApi.js +7 -4
- package/dist/esm/cli/lib/versionApi.js.map +2 -2
- package/dist/esm/cli/lib/workos/workos.js +4 -6
- package/dist/esm/cli/lib/workos/workos.js.map +2 -2
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm-types/browser/sync/authentication_manager.d.ts.map +1 -1
- package/dist/esm-types/browser/sync/web_socket_manager.d.ts.map +1 -1
- package/dist/esm-types/cli/aiFiles.d.ts.map +1 -1
- package/dist/esm-types/cli/configure.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/aiFiles/agentsmd.d.ts +19 -0
- package/dist/esm-types/cli/lib/aiFiles/agentsmd.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/aiFiles/agentsmd.test.d.ts +2 -0
- package/dist/esm-types/cli/lib/aiFiles/agentsmd.test.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/aiFiles/claudemd.d.ts +19 -0
- package/dist/esm-types/cli/lib/aiFiles/claudemd.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/aiFiles/claudemd.test.d.ts +2 -0
- package/dist/esm-types/cli/lib/aiFiles/claudemd.test.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/aiFiles/config.d.ts +46 -0
- package/dist/esm-types/cli/lib/aiFiles/config.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/aiFiles/config.test.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/aiFiles/cursorrules.d.ts +10 -0
- package/dist/esm-types/cli/lib/aiFiles/cursorrules.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/aiFiles/guidelinesmd.d.ts +12 -0
- package/dist/esm-types/cli/lib/aiFiles/guidelinesmd.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/aiFiles/guidelinesmd.test.d.ts +2 -0
- package/dist/esm-types/cli/lib/aiFiles/guidelinesmd.test.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/aiFiles/index.d.ts +40 -0
- package/dist/esm-types/cli/lib/aiFiles/index.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/aiFiles/index.test.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/aiFiles/integration.test.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/{ai → aiFiles}/paths.d.ts +4 -0
- package/dist/esm-types/cli/lib/aiFiles/paths.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/aiFiles/prompt.test.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/aiFiles/skills.d.ts +18 -0
- package/dist/esm-types/cli/lib/aiFiles/skills.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/aiFiles/status.d.ts +3 -0
- package/dist/esm-types/cli/lib/aiFiles/status.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/aiFiles/utils.d.ts +46 -0
- package/dist/esm-types/cli/lib/aiFiles/utils.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/config.d.ts +1 -0
- package/dist/esm-types/cli/lib/config.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/versionApi.d.ts +7 -1
- package/dist/esm-types/cli/lib/versionApi.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/workos/workos.d.ts.map +1 -1
- package/dist/esm-types/index.d.ts +1 -1
- package/dist/react.bundle.js +6 -9
- package/dist/react.bundle.js.map +2 -2
- package/package.json +1 -1
- package/schemas/convex.schema.json +7 -1
- package/src/browser/sync/authentication_manager.ts +9 -4
- package/src/browser/sync/client_node.test.ts +125 -0
- package/src/browser/sync/web_socket_manager.ts +1 -7
- package/src/cli/aiFiles.ts +20 -27
- package/src/cli/configure.ts +17 -11
- package/src/cli/deploymentSelection.test.ts +56 -2
- package/src/cli/lib/{ai → aiFiles}/MANUAL_TESTING.md +6 -2
- package/src/cli/lib/aiFiles/agentsmd.test.ts +133 -0
- package/src/cli/lib/aiFiles/agentsmd.ts +77 -0
- package/src/cli/lib/aiFiles/claudemd.test.ts +92 -0
- package/src/cli/lib/aiFiles/claudemd.ts +77 -0
- package/src/cli/lib/{ai → aiFiles}/config.test.ts +181 -59
- package/src/cli/lib/{ai → aiFiles}/config.ts +92 -63
- package/src/cli/lib/aiFiles/cursorrules.ts +25 -0
- package/src/cli/lib/aiFiles/guidelinesmd.test.ts +40 -0
- package/src/cli/lib/aiFiles/guidelinesmd.ts +41 -0
- package/src/cli/lib/{ai → aiFiles}/index.test.ts +200 -339
- package/src/cli/lib/aiFiles/index.ts +303 -0
- package/src/cli/lib/{ai → aiFiles}/integration.test.ts +117 -147
- package/src/cli/lib/{ai → aiFiles}/paths.ts +5 -0
- package/src/cli/lib/{ai → aiFiles}/prompt.test.ts +78 -30
- package/src/cli/lib/aiFiles/skills.ts +213 -0
- package/src/cli/lib/aiFiles/status.ts +240 -0
- package/src/cli/lib/aiFiles/utils.ts +163 -0
- package/src/cli/lib/command.ts +6 -1
- package/src/cli/lib/config.test.ts +1 -1
- package/src/cli/lib/config.ts +6 -5
- package/src/cli/lib/localDeployment/anonymous.ts +2 -2
- package/src/cli/lib/updates.test.ts +40 -30
- package/src/cli/lib/updates.ts +8 -8
- package/src/cli/lib/versionApi.test.ts +13 -10
- package/src/cli/lib/versionApi.ts +13 -5
- package/src/cli/lib/workos/workos.ts +4 -5
- package/src/index.ts +1 -1
- package/src/values/.claude/settings.local.json +10 -0
- package/dist/cjs/cli/lib/ai/config.js.map +0 -7
- package/dist/cjs/cli/lib/ai/index.js +0 -704
- package/dist/cjs/cli/lib/ai/index.js.map +0 -7
- package/dist/cjs/cli/lib/ai/paths.js.map +0 -7
- package/dist/cjs-types/cli/lib/ai/config.d.ts +0 -50
- package/dist/cjs-types/cli/lib/ai/config.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/ai/config.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/ai/index.d.ts +0 -56
- package/dist/cjs-types/cli/lib/ai/index.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/ai/index.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/ai/integration.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/ai/paths.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/ai/prompt.test.d.ts.map +0 -1
- package/dist/esm/cli/lib/ai/config.js.map +0 -7
- package/dist/esm/cli/lib/ai/index.js +0 -684
- package/dist/esm/cli/lib/ai/index.js.map +0 -7
- package/dist/esm/cli/lib/ai/paths.js.map +0 -7
- package/dist/esm-types/cli/lib/ai/config.d.ts +0 -50
- package/dist/esm-types/cli/lib/ai/config.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/ai/config.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/ai/index.d.ts +0 -56
- package/dist/esm-types/cli/lib/ai/index.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/ai/index.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/ai/integration.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/ai/paths.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/ai/prompt.test.d.ts.map +0 -1
- package/src/cli/lib/ai/index.ts +0 -1006
- /package/dist/cjs/cli/lib/{ai → aiFiles}/paths.js +0 -0
- /package/dist/cjs-types/cli/lib/{ai → aiFiles}/config.test.d.ts +0 -0
- /package/dist/cjs-types/cli/lib/{ai → aiFiles}/index.test.d.ts +0 -0
- /package/dist/cjs-types/cli/lib/{ai → aiFiles}/integration.test.d.ts +0 -0
- /package/dist/cjs-types/cli/lib/{ai → aiFiles}/prompt.test.d.ts +0 -0
- /package/dist/esm/cli/lib/{ai → aiFiles}/paths.js +0 -0
- /package/dist/esm-types/cli/lib/{ai → aiFiles}/config.test.d.ts +0 -0
- /package/dist/esm-types/cli/lib/{ai → aiFiles}/index.test.d.ts +0 -0
- /package/dist/esm-types/cli/lib/{ai → aiFiles}/integration.test.d.ts +0 -0
- /package/dist/esm-types/cli/lib/{ai → aiFiles}/prompt.test.d.ts +0 -0
|
@@ -4,12 +4,12 @@ import os from "os";
|
|
|
4
4
|
import path from "path";
|
|
5
5
|
import {
|
|
6
6
|
checkAiFilesStaleness,
|
|
7
|
-
|
|
7
|
+
safelyAttemptToDisableAiFiles,
|
|
8
8
|
enableAiFiles,
|
|
9
9
|
removeAiFiles,
|
|
10
|
-
|
|
11
|
-
updateAiFiles,
|
|
10
|
+
installAiFiles,
|
|
12
11
|
} from "./index.js";
|
|
12
|
+
import { statusAiFiles } from "./status.js";
|
|
13
13
|
import { logMessage } from "../../../bundler/log.js";
|
|
14
14
|
import { AGENTS_MD_START_MARKER } from "../../codegen_templates/agentsmd.js";
|
|
15
15
|
import { CLAUDE_MD_START_MARKER } from "../../codegen_templates/claudemd.js";
|
|
@@ -22,10 +22,13 @@ vi.mock("../versionApi.js", () => ({
|
|
|
22
22
|
downloadGuidelines: vi.fn(async () => "integration guidelines content"),
|
|
23
23
|
fetchAgentSkillsSha: vi.fn(async () => "integration-sha"),
|
|
24
24
|
getVersion: vi.fn(async () => ({
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
kind: "ok",
|
|
26
|
+
data: {
|
|
27
|
+
message: null,
|
|
28
|
+
guidelinesHash: "integration-guidelines-hash",
|
|
29
|
+
agentSkillsSha: "integration-agent-skills-sha",
|
|
30
|
+
disableSkillsCli: false,
|
|
31
|
+
},
|
|
29
32
|
})),
|
|
30
33
|
}));
|
|
31
34
|
|
|
@@ -80,7 +83,7 @@ describe("ai-files integration with default convex/ directory", () => {
|
|
|
80
83
|
});
|
|
81
84
|
|
|
82
85
|
test("install creates guidelines, state, AGENTS.md, and CLAUDE.md", async () => {
|
|
83
|
-
await
|
|
86
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
84
87
|
|
|
85
88
|
expect(fs.existsSync(guidelinesPath())).toBe(true);
|
|
86
89
|
expect(fs.existsSync(statePath())).toBe(true);
|
|
@@ -96,7 +99,7 @@ describe("ai-files integration with default convex/ directory", () => {
|
|
|
96
99
|
path.join(tmpDir, "AGENTS.md"),
|
|
97
100
|
"# My Project\n\nImportant team guidelines here.\n",
|
|
98
101
|
);
|
|
99
|
-
await
|
|
102
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
100
103
|
const content = fs.readFileSync(path.join(tmpDir, "AGENTS.md"), "utf8");
|
|
101
104
|
expect(content).toContain("# My Project");
|
|
102
105
|
expect(content).toContain("Important team guidelines here.");
|
|
@@ -111,17 +114,17 @@ describe("ai-files integration with default convex/ directory", () => {
|
|
|
111
114
|
path.join(tmpDir, "CLAUDE.md"),
|
|
112
115
|
"My custom CLAUDE.md content\n",
|
|
113
116
|
);
|
|
114
|
-
await
|
|
117
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
115
118
|
const content = fs.readFileSync(path.join(tmpDir, "CLAUDE.md"), "utf8");
|
|
116
119
|
expect(content).toContain("My custom CLAUDE.md content");
|
|
117
120
|
});
|
|
118
121
|
|
|
119
122
|
test("second update is idempotent", async () => {
|
|
120
|
-
await
|
|
123
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
121
124
|
const firstGuidelines = fs.readFileSync(guidelinesPath(), "utf8");
|
|
122
125
|
const firstState = fs.readFileSync(statePath(), "utf8");
|
|
123
126
|
|
|
124
|
-
await
|
|
127
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
125
128
|
|
|
126
129
|
expect(fs.readFileSync(guidelinesPath(), "utf8")).toBe(firstGuidelines);
|
|
127
130
|
expect(fs.readFileSync(statePath(), "utf8")).toBe(firstState);
|
|
@@ -133,36 +136,24 @@ describe("ai-files integration with default convex/ directory", () => {
|
|
|
133
136
|
path.join(tmpDir, ".cursor", "rules", "convex_rules.mdc"),
|
|
134
137
|
"legacy",
|
|
135
138
|
);
|
|
136
|
-
await
|
|
139
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
137
140
|
expect(
|
|
138
141
|
fs.existsSync(path.join(tmpDir, ".cursor", "rules", "convex_rules.mdc")),
|
|
139
142
|
).toBe(false);
|
|
140
143
|
});
|
|
141
144
|
|
|
142
|
-
test("skips locally modified guidelines", async () => {
|
|
143
|
-
await updateAiFiles(tmpDir, convexDir);
|
|
144
|
-
fs.appendFileSync(guidelinesPath(), "\n## My custom note\n");
|
|
145
|
-
const state = readJson(statePath());
|
|
146
|
-
state.guidelinesHash = "deliberately-stale-hash";
|
|
147
|
-
fs.writeFileSync(statePath(), JSON.stringify(state, null, 2) + "\n");
|
|
148
|
-
|
|
149
|
-
await updateAiFiles(tmpDir, convexDir);
|
|
150
|
-
|
|
151
|
-
expect(fs.readFileSync(guidelinesPath(), "utf8")).toContain(
|
|
152
|
-
"My custom note",
|
|
153
|
-
);
|
|
154
|
-
expect(vi.mocked(logMessage)).toHaveBeenCalledWith(
|
|
155
|
-
expect.stringContaining("modified locally"),
|
|
156
|
-
);
|
|
157
|
-
});
|
|
158
|
-
|
|
159
145
|
test("staleness check nags when stored hash is stale", async () => {
|
|
160
|
-
await
|
|
146
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
161
147
|
const state = readJson(statePath());
|
|
162
148
|
state.guidelinesHash = "deliberately-stale-hash";
|
|
163
149
|
fs.writeFileSync(statePath(), JSON.stringify(state, null, 2) + "\n");
|
|
164
150
|
|
|
165
|
-
await checkAiFilesStaleness(
|
|
151
|
+
await checkAiFilesStaleness({
|
|
152
|
+
canonicalGuidelinesHash: "canonical-hash",
|
|
153
|
+
canonicalAgentSkillsSha: null,
|
|
154
|
+
projectDir: tmpDir,
|
|
155
|
+
convexDir,
|
|
156
|
+
});
|
|
166
157
|
|
|
167
158
|
expect(vi.mocked(logMessage)).toHaveBeenCalledWith(
|
|
168
159
|
expect.stringContaining("out of date"),
|
|
@@ -170,14 +161,19 @@ describe("ai-files integration with default convex/ directory", () => {
|
|
|
170
161
|
});
|
|
171
162
|
|
|
172
163
|
test("staleness check is silent when disabled in convex.json", async () => {
|
|
173
|
-
await
|
|
174
|
-
await
|
|
164
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
165
|
+
await safelyAttemptToDisableAiFiles(tmpDir);
|
|
175
166
|
const state = readJson(statePath());
|
|
176
167
|
state.guidelinesHash = "deliberately-stale-hash";
|
|
177
168
|
fs.writeFileSync(statePath(), JSON.stringify(state, null, 2) + "\n");
|
|
178
169
|
vi.mocked(logMessage).mockClear();
|
|
179
170
|
|
|
180
|
-
await checkAiFilesStaleness(
|
|
171
|
+
await checkAiFilesStaleness({
|
|
172
|
+
canonicalGuidelinesHash: "canonical-hash",
|
|
173
|
+
canonicalAgentSkillsSha: null,
|
|
174
|
+
projectDir: tmpDir,
|
|
175
|
+
convexDir,
|
|
176
|
+
});
|
|
181
177
|
|
|
182
178
|
const calls = vi.mocked(logMessage).mock.calls.map((c) => c[0]);
|
|
183
179
|
expect(
|
|
@@ -186,40 +182,36 @@ describe("ai-files integration with default convex/ directory", () => {
|
|
|
186
182
|
});
|
|
187
183
|
|
|
188
184
|
test("disable keeps files but sets convex.json preference", async () => {
|
|
189
|
-
await
|
|
190
|
-
await
|
|
185
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
186
|
+
await safelyAttemptToDisableAiFiles(tmpDir);
|
|
191
187
|
|
|
192
|
-
expect(readJson(projectConfigPath()).aiFiles.
|
|
193
|
-
true,
|
|
194
|
-
);
|
|
188
|
+
expect(readJson(projectConfigPath()).aiFiles.enabled).toBe(false);
|
|
195
189
|
expect(fs.existsSync(guidelinesPath())).toBe(true);
|
|
196
190
|
expect(fs.existsSync(path.join(tmpDir, "AGENTS.md"))).toBe(true);
|
|
197
191
|
expect(fs.existsSync(path.join(tmpDir, "CLAUDE.md"))).toBe(true);
|
|
198
192
|
});
|
|
199
193
|
|
|
200
194
|
test("disable before install writes only convex.json and no AI state file", async () => {
|
|
201
|
-
await
|
|
195
|
+
await safelyAttemptToDisableAiFiles(tmpDir);
|
|
202
196
|
|
|
203
|
-
expect(readJson(projectConfigPath()).aiFiles.
|
|
204
|
-
true,
|
|
205
|
-
);
|
|
197
|
+
expect(readJson(projectConfigPath()).aiFiles.enabled).toBe(false);
|
|
206
198
|
expect(fs.existsSync(statePath())).toBe(false);
|
|
207
199
|
expect(fs.existsSync(guidelinesPath())).toBe(false);
|
|
208
200
|
});
|
|
209
201
|
|
|
210
202
|
test("remove deletes ai directory and AGENTS.md managed section", async () => {
|
|
211
|
-
await
|
|
212
|
-
await removeAiFiles(tmpDir, convexDir);
|
|
203
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
204
|
+
await removeAiFiles({ projectDir: tmpDir, convexDir });
|
|
213
205
|
|
|
214
206
|
expect(fs.existsSync(aiDir())).toBe(false);
|
|
215
207
|
});
|
|
216
208
|
|
|
217
209
|
test("status reports not installed after remove", async () => {
|
|
218
|
-
await
|
|
219
|
-
await removeAiFiles(tmpDir, convexDir);
|
|
210
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
211
|
+
await removeAiFiles({ projectDir: tmpDir, convexDir });
|
|
220
212
|
vi.mocked(logMessage).mockClear();
|
|
221
213
|
|
|
222
|
-
await statusAiFiles(tmpDir, convexDir);
|
|
214
|
+
await statusAiFiles({ projectDir: tmpDir, convexDir });
|
|
223
215
|
|
|
224
216
|
expect(vi.mocked(logMessage)).toHaveBeenCalledWith(
|
|
225
217
|
expect.stringContaining("not installed"),
|
|
@@ -227,10 +219,10 @@ describe("ai-files integration with default convex/ directory", () => {
|
|
|
227
219
|
});
|
|
228
220
|
|
|
229
221
|
test("status reports installed and enabled after install", async () => {
|
|
230
|
-
await
|
|
222
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
231
223
|
vi.mocked(logMessage).mockClear();
|
|
232
224
|
|
|
233
|
-
await statusAiFiles(tmpDir, convexDir);
|
|
225
|
+
await statusAiFiles({ projectDir: tmpDir, convexDir });
|
|
234
226
|
|
|
235
227
|
expect(vi.mocked(logMessage)).toHaveBeenCalledWith(
|
|
236
228
|
expect.stringContaining("enabled"),
|
|
@@ -238,52 +230,46 @@ describe("ai-files integration with default convex/ directory", () => {
|
|
|
238
230
|
});
|
|
239
231
|
|
|
240
232
|
test("disable after CLAUDE.md user edits preserves the file", async () => {
|
|
241
|
-
await
|
|
233
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
242
234
|
fs.appendFileSync(path.join(tmpDir, "CLAUDE.md"), "My custom note\n");
|
|
243
|
-
await
|
|
235
|
+
await safelyAttemptToDisableAiFiles(tmpDir);
|
|
244
236
|
expect(fs.readFileSync(path.join(tmpDir, "CLAUDE.md"), "utf8")).toContain(
|
|
245
237
|
"My custom note",
|
|
246
238
|
);
|
|
247
239
|
});
|
|
248
240
|
|
|
249
241
|
test("update recreates missing CLAUDE.md", async () => {
|
|
250
|
-
await
|
|
242
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
251
243
|
fs.rmSync(path.join(tmpDir, "CLAUDE.md"), { force: true });
|
|
252
244
|
|
|
253
|
-
await
|
|
245
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
254
246
|
|
|
255
247
|
expect(fs.readFileSync(path.join(tmpDir, "CLAUDE.md"), "utf8")).toContain(
|
|
256
248
|
"convex/_generated/ai/guidelines.md",
|
|
257
249
|
);
|
|
258
250
|
});
|
|
259
251
|
|
|
260
|
-
test("enable
|
|
261
|
-
await
|
|
262
|
-
await
|
|
263
|
-
expect(readJson(projectConfigPath()).aiFiles.
|
|
264
|
-
true,
|
|
265
|
-
);
|
|
252
|
+
test("enable sets enabled flag to true", async () => {
|
|
253
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
254
|
+
await safelyAttemptToDisableAiFiles(tmpDir);
|
|
255
|
+
expect(readJson(projectConfigPath()).aiFiles.enabled).toBe(false);
|
|
266
256
|
|
|
267
|
-
await enableAiFiles(tmpDir, convexDir);
|
|
257
|
+
await enableAiFiles({ projectDir: tmpDir, convexDir });
|
|
268
258
|
|
|
269
|
-
expect(readJson(projectConfigPath()).aiFiles.
|
|
270
|
-
false,
|
|
271
|
-
);
|
|
259
|
+
expect(readJson(projectConfigPath()).aiFiles.enabled).toBe(true);
|
|
272
260
|
});
|
|
273
261
|
|
|
274
262
|
test("full cycle: disable -> remove -> enable reinstalls everything", async () => {
|
|
275
|
-
await
|
|
276
|
-
await
|
|
277
|
-
await removeAiFiles(tmpDir, convexDir);
|
|
263
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
264
|
+
await safelyAttemptToDisableAiFiles(tmpDir);
|
|
265
|
+
await removeAiFiles({ projectDir: tmpDir, convexDir });
|
|
278
266
|
expect(fs.existsSync(aiDir())).toBe(false);
|
|
279
267
|
|
|
280
|
-
await enableAiFiles(tmpDir, convexDir);
|
|
268
|
+
await enableAiFiles({ projectDir: tmpDir, convexDir });
|
|
281
269
|
|
|
282
270
|
expect(fs.existsSync(guidelinesPath())).toBe(true);
|
|
283
271
|
expect(fs.existsSync(path.join(tmpDir, "AGENTS.md"))).toBe(true);
|
|
284
|
-
expect(readJson(projectConfigPath()).aiFiles.
|
|
285
|
-
false,
|
|
286
|
-
);
|
|
272
|
+
expect(readJson(projectConfigPath()).aiFiles.enabled).toBe(true);
|
|
287
273
|
});
|
|
288
274
|
|
|
289
275
|
test("remove strips managed section from AGENTS.md but preserves user content", async () => {
|
|
@@ -291,11 +277,11 @@ describe("ai-files integration with default convex/ directory", () => {
|
|
|
291
277
|
path.join(tmpDir, "AGENTS.md"),
|
|
292
278
|
"# My Project\n\nTeam guidelines here.\n",
|
|
293
279
|
);
|
|
294
|
-
await
|
|
280
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
295
281
|
const before = fs.readFileSync(path.join(tmpDir, "AGENTS.md"), "utf8");
|
|
296
282
|
expect(before).toContain(AGENTS_MD_START_MARKER);
|
|
297
283
|
|
|
298
|
-
await removeAiFiles(tmpDir, convexDir);
|
|
284
|
+
await removeAiFiles({ projectDir: tmpDir, convexDir });
|
|
299
285
|
|
|
300
286
|
const after = fs.readFileSync(path.join(tmpDir, "AGENTS.md"), "utf8");
|
|
301
287
|
expect(after).toContain("# My Project");
|
|
@@ -304,19 +290,19 @@ describe("ai-files integration with default convex/ directory", () => {
|
|
|
304
290
|
});
|
|
305
291
|
|
|
306
292
|
test("remove on AGENTS.md with only Convex content deletes the file", async () => {
|
|
307
|
-
await
|
|
293
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
308
294
|
expect(fs.existsSync(path.join(tmpDir, "AGENTS.md"))).toBe(true);
|
|
309
295
|
|
|
310
|
-
await removeAiFiles(tmpDir, convexDir);
|
|
296
|
+
await removeAiFiles({ projectDir: tmpDir, convexDir });
|
|
311
297
|
|
|
312
298
|
expect(fs.existsSync(path.join(tmpDir, "AGENTS.md"))).toBe(false);
|
|
313
299
|
});
|
|
314
300
|
|
|
315
301
|
test("remove deletes CLAUDE.md when empty after stripping managed section", async () => {
|
|
316
|
-
await
|
|
302
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
317
303
|
expect(fs.existsSync(path.join(tmpDir, "CLAUDE.md"))).toBe(true);
|
|
318
304
|
|
|
319
|
-
await removeAiFiles(tmpDir, convexDir);
|
|
305
|
+
await removeAiFiles({ projectDir: tmpDir, convexDir });
|
|
320
306
|
|
|
321
307
|
expect(fs.existsSync(path.join(tmpDir, "CLAUDE.md"))).toBe(false);
|
|
322
308
|
});
|
|
@@ -326,11 +312,11 @@ describe("ai-files integration with default convex/ directory", () => {
|
|
|
326
312
|
path.join(tmpDir, "CLAUDE.md"),
|
|
327
313
|
"My project-specific Claude instructions\n",
|
|
328
314
|
);
|
|
329
|
-
await
|
|
315
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
330
316
|
const before = fs.readFileSync(path.join(tmpDir, "CLAUDE.md"), "utf8");
|
|
331
317
|
expect(before).toContain(CLAUDE_MD_START_MARKER);
|
|
332
318
|
|
|
333
|
-
await removeAiFiles(tmpDir, convexDir);
|
|
319
|
+
await removeAiFiles({ projectDir: tmpDir, convexDir });
|
|
334
320
|
|
|
335
321
|
const after = fs.readFileSync(path.join(tmpDir, "CLAUDE.md"), "utf8");
|
|
336
322
|
expect(after).toContain("My project-specific Claude instructions");
|
|
@@ -340,7 +326,12 @@ describe("ai-files integration with default convex/ directory", () => {
|
|
|
340
326
|
test("checkAiFilesStaleness nags when no state file exists", async () => {
|
|
341
327
|
vi.mocked(logMessage).mockClear();
|
|
342
328
|
|
|
343
|
-
await checkAiFilesStaleness(
|
|
329
|
+
await checkAiFilesStaleness({
|
|
330
|
+
canonicalGuidelinesHash: null,
|
|
331
|
+
canonicalAgentSkillsSha: null,
|
|
332
|
+
projectDir: tmpDir,
|
|
333
|
+
convexDir,
|
|
334
|
+
});
|
|
344
335
|
|
|
345
336
|
expect(vi.mocked(logMessage)).toHaveBeenCalledWith(
|
|
346
337
|
expect.stringContaining("not installed"),
|
|
@@ -348,16 +339,16 @@ describe("ai-files integration with default convex/ directory", () => {
|
|
|
348
339
|
});
|
|
349
340
|
|
|
350
341
|
test("checkAiFilesStaleness is silent when hashes match", async () => {
|
|
351
|
-
await
|
|
342
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
352
343
|
const state = readJson(statePath());
|
|
353
344
|
vi.mocked(logMessage).mockClear();
|
|
354
345
|
|
|
355
|
-
await checkAiFilesStaleness(
|
|
356
|
-
state.guidelinesHash,
|
|
357
|
-
state.agentSkillsSha,
|
|
358
|
-
tmpDir,
|
|
346
|
+
await checkAiFilesStaleness({
|
|
347
|
+
canonicalGuidelinesHash: state.guidelinesHash,
|
|
348
|
+
canonicalAgentSkillsSha: state.agentSkillsSha,
|
|
349
|
+
projectDir: tmpDir,
|
|
359
350
|
convexDir,
|
|
360
|
-
);
|
|
351
|
+
});
|
|
361
352
|
|
|
362
353
|
const calls = vi.mocked(logMessage).mock.calls.map((c) => c[0]);
|
|
363
354
|
expect(
|
|
@@ -369,9 +360,9 @@ describe("ai-files integration with default convex/ directory", () => {
|
|
|
369
360
|
});
|
|
370
361
|
|
|
371
362
|
test("AGENTS.md managed section is replaced not duplicated on repeated updates", async () => {
|
|
372
|
-
await
|
|
373
|
-
await
|
|
374
|
-
await
|
|
363
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
364
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
365
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
375
366
|
|
|
376
367
|
const content = fs.readFileSync(path.join(tmpDir, "AGENTS.md"), "utf8");
|
|
377
368
|
const markerCount = content.split(AGENTS_MD_START_MARKER).length - 1;
|
|
@@ -379,11 +370,11 @@ describe("ai-files integration with default convex/ directory", () => {
|
|
|
379
370
|
});
|
|
380
371
|
|
|
381
372
|
test("status reports disabled state after disable", async () => {
|
|
382
|
-
await
|
|
383
|
-
await
|
|
373
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
374
|
+
await safelyAttemptToDisableAiFiles(tmpDir);
|
|
384
375
|
vi.mocked(logMessage).mockClear();
|
|
385
376
|
|
|
386
|
-
await statusAiFiles(tmpDir, convexDir);
|
|
377
|
+
await statusAiFiles({ projectDir: tmpDir, convexDir });
|
|
387
378
|
|
|
388
379
|
expect(vi.mocked(logMessage)).toHaveBeenCalledWith(
|
|
389
380
|
expect.stringContaining("disabled"),
|
|
@@ -421,7 +412,7 @@ describe("ai-files integration with functions directory override", () => {
|
|
|
421
412
|
});
|
|
422
413
|
|
|
423
414
|
test("installs into overridden functions directory, not default convex/", async () => {
|
|
424
|
-
await
|
|
415
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
425
416
|
|
|
426
417
|
expect(fs.existsSync(guidelinesPath())).toBe(true);
|
|
427
418
|
expect(fs.existsSync(statePath())).toBe(true);
|
|
@@ -440,7 +431,7 @@ describe("ai-files integration with functions directory override", () => {
|
|
|
440
431
|
path.join(tmpDir, "AGENTS.md"),
|
|
441
432
|
"# Existing\n\nUser content.\n",
|
|
442
433
|
);
|
|
443
|
-
await
|
|
434
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
444
435
|
const content = fs.readFileSync(path.join(tmpDir, "AGENTS.md"), "utf8");
|
|
445
436
|
expect(content).toContain("# Existing");
|
|
446
437
|
expect(content).toContain("User content.");
|
|
@@ -456,17 +447,17 @@ describe("ai-files integration with functions directory override", () => {
|
|
|
456
447
|
"My custom CLAUDE.md content\n",
|
|
457
448
|
"utf8",
|
|
458
449
|
);
|
|
459
|
-
await
|
|
450
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
460
451
|
const content = fs.readFileSync(path.join(tmpDir, "CLAUDE.md"), "utf8");
|
|
461
452
|
expect(content).toContain("My custom CLAUDE.md content");
|
|
462
453
|
});
|
|
463
454
|
|
|
464
455
|
test("second update is idempotent", async () => {
|
|
465
|
-
await
|
|
456
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
466
457
|
const firstGuidelines = fs.readFileSync(guidelinesPath(), "utf8");
|
|
467
458
|
const firstState = fs.readFileSync(statePath(), "utf8");
|
|
468
459
|
|
|
469
|
-
await
|
|
460
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
470
461
|
|
|
471
462
|
expect(fs.readFileSync(guidelinesPath(), "utf8")).toBe(firstGuidelines);
|
|
472
463
|
expect(fs.readFileSync(statePath(), "utf8")).toBe(firstState);
|
|
@@ -479,36 +470,14 @@ describe("ai-files integration with functions directory override", () => {
|
|
|
479
470
|
"legacy",
|
|
480
471
|
"utf8",
|
|
481
472
|
);
|
|
482
|
-
await
|
|
473
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
483
474
|
expect(
|
|
484
475
|
fs.existsSync(path.join(tmpDir, ".cursor", "rules", "convex_rules.mdc")),
|
|
485
476
|
).toBe(false);
|
|
486
477
|
});
|
|
487
478
|
|
|
488
|
-
test("skips locally modified guidelines when stored hash is stale", async () => {
|
|
489
|
-
await updateAiFiles(tmpDir, convexDir);
|
|
490
|
-
const localNote = "\n## My custom note\n";
|
|
491
|
-
fs.appendFileSync(guidelinesPath(), localNote, "utf8");
|
|
492
|
-
const state = readJson(statePath());
|
|
493
|
-
state.guidelinesHash = "deliberately-stale-hash";
|
|
494
|
-
fs.writeFileSync(
|
|
495
|
-
statePath(),
|
|
496
|
-
JSON.stringify(state, null, 2) + "\n",
|
|
497
|
-
"utf8",
|
|
498
|
-
);
|
|
499
|
-
|
|
500
|
-
await updateAiFiles(tmpDir, convexDir);
|
|
501
|
-
|
|
502
|
-
expect(fs.readFileSync(guidelinesPath(), "utf8")).toContain(
|
|
503
|
-
localNote.trim(),
|
|
504
|
-
);
|
|
505
|
-
expect(vi.mocked(logMessage)).toHaveBeenCalledWith(
|
|
506
|
-
expect.stringContaining("modified locally"),
|
|
507
|
-
);
|
|
508
|
-
});
|
|
509
|
-
|
|
510
479
|
test("staleness check logs update nag for stale stored hash", async () => {
|
|
511
|
-
await
|
|
480
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
512
481
|
const state = readJson(statePath());
|
|
513
482
|
state.guidelinesHash = "deliberately-stale-hash";
|
|
514
483
|
fs.writeFileSync(
|
|
@@ -517,7 +486,12 @@ describe("ai-files integration with functions directory override", () => {
|
|
|
517
486
|
"utf8",
|
|
518
487
|
);
|
|
519
488
|
|
|
520
|
-
await checkAiFilesStaleness(
|
|
489
|
+
await checkAiFilesStaleness({
|
|
490
|
+
canonicalGuidelinesHash: "canonical-hash",
|
|
491
|
+
canonicalAgentSkillsSha: null,
|
|
492
|
+
projectDir: tmpDir,
|
|
493
|
+
convexDir,
|
|
494
|
+
});
|
|
521
495
|
|
|
522
496
|
expect(vi.mocked(logMessage)).toHaveBeenCalledWith(
|
|
523
497
|
expect.stringContaining("out of date"),
|
|
@@ -525,21 +499,19 @@ describe("ai-files integration with functions directory override", () => {
|
|
|
525
499
|
});
|
|
526
500
|
|
|
527
501
|
test("disable sets convex.json preference and keeps files", async () => {
|
|
528
|
-
await
|
|
529
|
-
await
|
|
502
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
503
|
+
await safelyAttemptToDisableAiFiles(tmpDir);
|
|
530
504
|
|
|
531
|
-
expect(readJson(projectConfigPath()).aiFiles.
|
|
532
|
-
true,
|
|
533
|
-
);
|
|
505
|
+
expect(readJson(projectConfigPath()).aiFiles.enabled).toBe(false);
|
|
534
506
|
expect(fs.existsSync(guidelinesPath())).toBe(true);
|
|
535
507
|
expect(fs.existsSync(path.join(tmpDir, "AGENTS.md"))).toBe(true);
|
|
536
508
|
expect(fs.existsSync(path.join(tmpDir, "CLAUDE.md"))).toBe(true);
|
|
537
509
|
});
|
|
538
510
|
|
|
539
511
|
test("remove deletes files and status reports not installed", async () => {
|
|
540
|
-
await
|
|
541
|
-
await removeAiFiles(tmpDir, convexDir);
|
|
542
|
-
await statusAiFiles(tmpDir, convexDir);
|
|
512
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
513
|
+
await removeAiFiles({ projectDir: tmpDir, convexDir });
|
|
514
|
+
await statusAiFiles({ projectDir: tmpDir, convexDir });
|
|
543
515
|
|
|
544
516
|
expect(fs.existsSync(aiDir())).toBe(false);
|
|
545
517
|
expect(vi.mocked(logMessage)).toHaveBeenCalledWith(
|
|
@@ -548,23 +520,23 @@ describe("ai-files integration with functions directory override", () => {
|
|
|
548
520
|
});
|
|
549
521
|
|
|
550
522
|
test("disable after CLAUDE.md user edits preserves file", async () => {
|
|
551
|
-
await
|
|
523
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
552
524
|
fs.appendFileSync(
|
|
553
525
|
path.join(tmpDir, "CLAUDE.md"),
|
|
554
526
|
"My custom note\n",
|
|
555
527
|
"utf8",
|
|
556
528
|
);
|
|
557
|
-
await
|
|
529
|
+
await safelyAttemptToDisableAiFiles(tmpDir);
|
|
558
530
|
expect(fs.readFileSync(path.join(tmpDir, "CLAUDE.md"), "utf8")).toContain(
|
|
559
531
|
"My custom note",
|
|
560
532
|
);
|
|
561
533
|
});
|
|
562
534
|
|
|
563
535
|
test("update recreates missing CLAUDE.md", async () => {
|
|
564
|
-
await
|
|
536
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
565
537
|
fs.rmSync(path.join(tmpDir, "CLAUDE.md"), { force: true });
|
|
566
538
|
|
|
567
|
-
await
|
|
539
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
568
540
|
|
|
569
541
|
const content = fs.readFileSync(path.join(tmpDir, "CLAUDE.md"), "utf8");
|
|
570
542
|
expect(content).toMatch(
|
|
@@ -572,30 +544,28 @@ describe("ai-files integration with functions directory override", () => {
|
|
|
572
544
|
);
|
|
573
545
|
});
|
|
574
546
|
|
|
575
|
-
test("enable
|
|
576
|
-
await
|
|
577
|
-
await
|
|
578
|
-
await enableAiFiles(tmpDir, convexDir);
|
|
579
|
-
await statusAiFiles(tmpDir, convexDir);
|
|
547
|
+
test("enable sets enabled flag to true and re-enables status", async () => {
|
|
548
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
549
|
+
await safelyAttemptToDisableAiFiles(tmpDir);
|
|
550
|
+
await enableAiFiles({ projectDir: tmpDir, convexDir });
|
|
551
|
+
await statusAiFiles({ projectDir: tmpDir, convexDir });
|
|
580
552
|
|
|
581
|
-
expect(readJson(projectConfigPath()).aiFiles.
|
|
582
|
-
false,
|
|
583
|
-
);
|
|
553
|
+
expect(readJson(projectConfigPath()).aiFiles.enabled).toBe(true);
|
|
584
554
|
expect(vi.mocked(logMessage)).toHaveBeenCalledWith(
|
|
585
555
|
expect.stringContaining("enabled"),
|
|
586
556
|
);
|
|
587
557
|
});
|
|
588
558
|
|
|
589
559
|
test("disable + remove + enable works with overridden functions directory", async () => {
|
|
590
|
-
await
|
|
591
|
-
await
|
|
592
|
-
await removeAiFiles(tmpDir, convexDir);
|
|
560
|
+
await installAiFiles({ projectDir: tmpDir, convexDir });
|
|
561
|
+
await safelyAttemptToDisableAiFiles(tmpDir);
|
|
562
|
+
await removeAiFiles({ projectDir: tmpDir, convexDir });
|
|
593
563
|
|
|
594
564
|
expect(
|
|
595
565
|
fs.existsSync(path.join(tmpDir, "src", "convex", "_generated", "ai")),
|
|
596
566
|
).toBe(false);
|
|
597
567
|
|
|
598
|
-
await enableAiFiles(tmpDir, convexDir);
|
|
568
|
+
await enableAiFiles({ projectDir: tmpDir, convexDir });
|
|
599
569
|
|
|
600
570
|
expect(fs.existsSync(guidelinesPath())).toBe(true);
|
|
601
571
|
});
|