@cortexmemory/cli 0.27.1 → 0.27.4

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 (51) hide show
  1. package/dist/commands/convex.js +1 -1
  2. package/dist/commands/convex.js.map +1 -1
  3. package/dist/commands/deploy.d.ts +1 -1
  4. package/dist/commands/deploy.d.ts.map +1 -1
  5. package/dist/commands/deploy.js +839 -141
  6. package/dist/commands/deploy.js.map +1 -1
  7. package/dist/commands/dev.d.ts.map +1 -1
  8. package/dist/commands/dev.js +89 -26
  9. package/dist/commands/dev.js.map +1 -1
  10. package/dist/index.js +1 -1
  11. package/dist/utils/app-template-sync.d.ts +95 -0
  12. package/dist/utils/app-template-sync.d.ts.map +1 -0
  13. package/dist/utils/app-template-sync.js +445 -0
  14. package/dist/utils/app-template-sync.js.map +1 -0
  15. package/dist/utils/deployment-selector.d.ts +21 -0
  16. package/dist/utils/deployment-selector.d.ts.map +1 -1
  17. package/dist/utils/deployment-selector.js +32 -0
  18. package/dist/utils/deployment-selector.js.map +1 -1
  19. package/dist/utils/init/graph-setup.d.ts.map +1 -1
  20. package/dist/utils/init/graph-setup.js +13 -2
  21. package/dist/utils/init/graph-setup.js.map +1 -1
  22. package/package.json +1 -1
  23. package/templates/vercel-ai-quickstart/app/api/auth/check/route.ts +30 -0
  24. package/templates/vercel-ai-quickstart/app/api/auth/login/route.ts +128 -0
  25. package/templates/vercel-ai-quickstart/app/api/auth/register/route.ts +94 -0
  26. package/templates/vercel-ai-quickstart/app/api/auth/setup/route.ts +59 -0
  27. package/templates/vercel-ai-quickstart/app/api/chat/route.ts +139 -3
  28. package/templates/vercel-ai-quickstart/app/api/chat-v6/route.ts +333 -0
  29. package/templates/vercel-ai-quickstart/app/api/conversations/route.ts +179 -0
  30. package/templates/vercel-ai-quickstart/app/globals.css +161 -0
  31. package/templates/vercel-ai-quickstart/app/page.tsx +110 -11
  32. package/templates/vercel-ai-quickstart/components/AdminSetup.tsx +139 -0
  33. package/templates/vercel-ai-quickstart/components/AuthProvider.tsx +283 -0
  34. package/templates/vercel-ai-quickstart/components/ChatHistorySidebar.tsx +323 -0
  35. package/templates/vercel-ai-quickstart/components/ChatInterface.tsx +117 -17
  36. package/templates/vercel-ai-quickstart/components/LoginScreen.tsx +202 -0
  37. package/templates/vercel-ai-quickstart/jest.config.js +52 -0
  38. package/templates/vercel-ai-quickstart/lib/agents/memory-agent.ts +165 -0
  39. package/templates/vercel-ai-quickstart/lib/cortex.ts +27 -0
  40. package/templates/vercel-ai-quickstart/lib/password.ts +120 -0
  41. package/templates/vercel-ai-quickstart/lib/versions.ts +60 -0
  42. package/templates/vercel-ai-quickstart/next.config.js +20 -0
  43. package/templates/vercel-ai-quickstart/package.json +11 -2
  44. package/templates/vercel-ai-quickstart/test-api.mjs +272 -0
  45. package/templates/vercel-ai-quickstart/tests/e2e/chat-memory-flow.test.ts +454 -0
  46. package/templates/vercel-ai-quickstart/tests/helpers/mock-cortex.ts +263 -0
  47. package/templates/vercel-ai-quickstart/tests/helpers/setup.ts +48 -0
  48. package/templates/vercel-ai-quickstart/tests/integration/auth.test.ts +455 -0
  49. package/templates/vercel-ai-quickstart/tests/integration/conversations.test.ts +461 -0
  50. package/templates/vercel-ai-quickstart/tests/unit/password.test.ts +228 -0
  51. package/templates/vercel-ai-quickstart/tsconfig.json +1 -1
@@ -0,0 +1,263 @@
1
+ /**
2
+ * Mock Cortex SDK
3
+ *
4
+ * Provides a mock implementation of the Cortex SDK for testing.
5
+ * Simulates the SDK behavior without requiring a real Convex backend.
6
+ */
7
+
8
+ // In-memory stores for test state
9
+ let mutableStore: Map<string, Map<string, unknown>> = new Map();
10
+ let usersStore: Map<string, { userId: string; data: Record<string, unknown> }> =
11
+ new Map();
12
+ interface StoredConversation {
13
+ conversationId: string;
14
+ memorySpaceId: string;
15
+ type: string;
16
+ participants: { userId?: string; agentId?: string };
17
+ metadata: Record<string, unknown>;
18
+ createdAt: number;
19
+ updatedAt: number;
20
+ messageCount: number;
21
+ messages?: Array<{
22
+ id: string;
23
+ role: string;
24
+ content: string;
25
+ timestamp: number;
26
+ }>;
27
+ }
28
+
29
+ let conversationsStore: Map<string, StoredConversation> = new Map();
30
+
31
+ /**
32
+ * Reset all mock stores (call in beforeEach)
33
+ */
34
+ export function resetMockStores(): void {
35
+ mutableStore = new Map();
36
+ usersStore = new Map();
37
+ conversationsStore = new Map();
38
+ }
39
+
40
+ /**
41
+ * Create a mock Cortex SDK instance
42
+ */
43
+ export function createMockCortex() {
44
+ return {
45
+ mutable: {
46
+ get: jest.fn(
47
+ async (namespace: string, key: string): Promise<unknown | null> => {
48
+ const ns = mutableStore.get(namespace);
49
+ if (!ns) return null;
50
+ return ns.get(key) ?? null;
51
+ }
52
+ ),
53
+ set: jest.fn(
54
+ async (
55
+ namespace: string,
56
+ key: string,
57
+ value: unknown
58
+ ): Promise<void> => {
59
+ if (!mutableStore.has(namespace)) {
60
+ mutableStore.set(namespace, new Map());
61
+ }
62
+ mutableStore.get(namespace)!.set(key, value);
63
+ }
64
+ ),
65
+ delete: jest.fn(
66
+ async (namespace: string, key: string): Promise<void> => {
67
+ const ns = mutableStore.get(namespace);
68
+ if (ns) ns.delete(key);
69
+ }
70
+ ),
71
+ },
72
+ users: {
73
+ get: jest.fn(
74
+ async (
75
+ userId: string
76
+ ): Promise<{
77
+ userId: string;
78
+ data: Record<string, unknown>;
79
+ } | null> => {
80
+ return usersStore.get(userId) ?? null;
81
+ }
82
+ ),
83
+ update: jest.fn(
84
+ async (
85
+ userId: string,
86
+ data: Record<string, unknown>
87
+ ): Promise<{ userId: string; data: Record<string, unknown> }> => {
88
+ const existing = usersStore.get(userId);
89
+ const user = {
90
+ userId,
91
+ data: { ...(existing?.data || {}), ...data },
92
+ };
93
+ usersStore.set(userId, user);
94
+ return user;
95
+ }
96
+ ),
97
+ delete: jest.fn(async (userId: string): Promise<void> => {
98
+ usersStore.delete(userId);
99
+ }),
100
+ list: jest.fn(async () => {
101
+ return {
102
+ users: Array.from(usersStore.values()),
103
+ hasMore: false,
104
+ };
105
+ }),
106
+ },
107
+ conversations: {
108
+ list: jest.fn(
109
+ async (params: { memorySpaceId?: string; userId?: string }) => {
110
+ const conversations = Array.from(conversationsStore.values()).filter(
111
+ (conv) => {
112
+ if (
113
+ params.memorySpaceId &&
114
+ conv.memorySpaceId !== params.memorySpaceId
115
+ ) {
116
+ return false;
117
+ }
118
+ if (
119
+ params.userId &&
120
+ conv.participants.userId !== params.userId
121
+ ) {
122
+ return false;
123
+ }
124
+ return true;
125
+ }
126
+ );
127
+ return { conversations, hasMore: false };
128
+ }
129
+ ),
130
+ create: jest.fn(
131
+ async (params: {
132
+ memorySpaceId: string;
133
+ conversationId: string;
134
+ type: string;
135
+ participants: { userId?: string; agentId?: string };
136
+ metadata?: Record<string, unknown>;
137
+ }) => {
138
+ const now = Date.now();
139
+ const conversation = {
140
+ conversationId: params.conversationId,
141
+ memorySpaceId: params.memorySpaceId,
142
+ type: params.type,
143
+ participants: params.participants,
144
+ metadata: params.metadata || {},
145
+ createdAt: now,
146
+ updatedAt: now,
147
+ messageCount: 0,
148
+ };
149
+ conversationsStore.set(params.conversationId, conversation);
150
+ return conversation;
151
+ }
152
+ ),
153
+ get: jest.fn(async (conversationId: string, options?: { includeMessages?: boolean; messageLimit?: number }) => {
154
+ const conv = conversationsStore.get(conversationId);
155
+ if (!conv) return null;
156
+
157
+ // If includeMessages is requested, return with messages
158
+ if (options?.includeMessages) {
159
+ return {
160
+ ...conv,
161
+ messages: conv.messages || [],
162
+ };
163
+ }
164
+
165
+ // Otherwise return without messages
166
+ const { messages: _messages, ...convWithoutMessages } = conv;
167
+ return convWithoutMessages;
168
+ }),
169
+ delete: jest.fn(async (conversationId: string): Promise<void> => {
170
+ conversationsStore.delete(conversationId);
171
+ }),
172
+ update: jest.fn(
173
+ async (
174
+ conversationId: string,
175
+ updates: { metadata?: Record<string, unknown> }
176
+ ) => {
177
+ const conv = conversationsStore.get(conversationId);
178
+ if (!conv) throw new Error("Conversation not found");
179
+ const updated = {
180
+ ...conv,
181
+ metadata: { ...conv.metadata, ...updates.metadata },
182
+ updatedAt: Date.now(),
183
+ };
184
+ conversationsStore.set(conversationId, updated);
185
+ return updated;
186
+ }
187
+ ),
188
+ },
189
+ memory: {
190
+ search: jest.fn().mockResolvedValue([]),
191
+ remember: jest.fn().mockResolvedValue({
192
+ conversation: { conversationId: "conv-1", messageIds: [] },
193
+ memories: [],
194
+ facts: [],
195
+ }),
196
+ recall: jest.fn().mockResolvedValue({
197
+ context: "",
198
+ totalResults: 0,
199
+ queryTimeMs: 10,
200
+ sources: { vector: { count: 0, items: [] } },
201
+ }),
202
+ },
203
+ close: jest.fn(),
204
+ };
205
+ }
206
+
207
+ /**
208
+ * Type for the mock Cortex instance
209
+ */
210
+ export type MockCortex = ReturnType<typeof createMockCortex>;
211
+
212
+ /**
213
+ * Helper to seed test data into stores
214
+ */
215
+ export const seedTestData = {
216
+ user: (
217
+ userId: string,
218
+ data: Record<string, unknown> = {}
219
+ ): { userId: string; data: Record<string, unknown> } => {
220
+ const user = { userId, data };
221
+ usersStore.set(userId, user);
222
+ return user;
223
+ },
224
+ mutable: (namespace: string, key: string, value: unknown): void => {
225
+ if (!mutableStore.has(namespace)) {
226
+ mutableStore.set(namespace, new Map());
227
+ }
228
+ mutableStore.get(namespace)!.set(key, value);
229
+ },
230
+ conversation: (
231
+ conversationId: string,
232
+ params: {
233
+ memorySpaceId?: string;
234
+ userId?: string;
235
+ title?: string;
236
+ messages?: Array<{ role: string; content: string }>;
237
+ } = {}
238
+ ) => {
239
+ const now = Date.now();
240
+ const messages = params.messages?.map((msg, i) => ({
241
+ id: `msg-${i}`,
242
+ role: msg.role,
243
+ content: msg.content,
244
+ timestamp: now + i,
245
+ }));
246
+ const conversation: StoredConversation = {
247
+ conversationId,
248
+ memorySpaceId: params.memorySpaceId || "quickstart-demo",
249
+ type: "user-agent",
250
+ participants: {
251
+ userId: params.userId || "test-user",
252
+ agentId: "quickstart-assistant",
253
+ },
254
+ metadata: { title: params.title || "Test Chat" },
255
+ createdAt: now,
256
+ updatedAt: now,
257
+ messageCount: messages?.length || 0,
258
+ messages,
259
+ };
260
+ conversationsStore.set(conversationId, conversation);
261
+ return conversation;
262
+ },
263
+ };
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Jest Test Setup
3
+ *
4
+ * Configures global test environment for quickstart tests.
5
+ */
6
+
7
+ import { TextEncoder, TextDecoder } from "util";
8
+
9
+ // Polyfill TextEncoder/TextDecoder for Node.js environment
10
+ global.TextEncoder = TextEncoder;
11
+ global.TextDecoder = TextDecoder as typeof global.TextDecoder;
12
+
13
+ // Polyfill crypto for Node.js environment (required for password utilities)
14
+ if (typeof global.crypto === "undefined") {
15
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
16
+ const { webcrypto } = require("crypto");
17
+ global.crypto = webcrypto;
18
+ }
19
+
20
+ // Polyfill btoa/atob for Node.js environment
21
+ if (typeof global.btoa === "undefined") {
22
+ global.btoa = (str: string) => Buffer.from(str, "binary").toString("base64");
23
+ }
24
+
25
+ if (typeof global.atob === "undefined") {
26
+ global.atob = (str: string) => Buffer.from(str, "base64").toString("binary");
27
+ }
28
+
29
+ // Set test environment variables
30
+ process.env.NODE_ENV = "test";
31
+ process.env.CONVEX_URL = "https://test.convex.cloud";
32
+
33
+ // Suppress console output during tests (optional - comment out for debugging)
34
+ // global.console = {
35
+ // ...console,
36
+ // log: jest.fn(),
37
+ // debug: jest.fn(),
38
+ // info: jest.fn(),
39
+ // warn: jest.fn(),
40
+ // };
41
+
42
+ // Increase test timeout for async operations
43
+ jest.setTimeout(10000);
44
+
45
+ // Reset mocks between tests
46
+ beforeEach(() => {
47
+ jest.clearAllMocks();
48
+ });