@cortexmemory/cli 0.27.4 → 0.28.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.
- package/dist/commands/db.d.ts.map +1 -1
- package/dist/commands/db.js +18 -6
- package/dist/commands/db.js.map +1 -1
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +74 -34
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/dev.js +3 -2
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +12 -0
- package/dist/commands/init.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/app-template-sync.d.ts.map +1 -1
- package/dist/utils/app-template-sync.js +3 -1
- package/dist/utils/app-template-sync.js.map +1 -1
- package/dist/utils/init/quickstart-setup.d.ts.map +1 -1
- package/dist/utils/init/quickstart-setup.js.map +1 -1
- package/package.json +4 -4
- package/templates/basic/.env.local.example +23 -0
- package/templates/basic/README.md +181 -56
- package/templates/basic/package-lock.json +2180 -406
- package/templates/basic/package.json +23 -5
- package/templates/basic/src/__tests__/chat.test.ts +340 -0
- package/templates/basic/src/__tests__/cortex.test.ts +260 -0
- package/templates/basic/src/__tests__/display.test.ts +455 -0
- package/templates/basic/src/__tests__/e2e/fact-extraction.test.ts +498 -0
- package/templates/basic/src/__tests__/e2e/memory-flow.test.ts +355 -0
- package/templates/basic/src/__tests__/e2e/server-e2e.test.ts +414 -0
- package/templates/basic/src/__tests__/helpers/test-utils.ts +345 -0
- package/templates/basic/src/__tests__/integration/chat-flow.test.ts +422 -0
- package/templates/basic/src/__tests__/integration/server.test.ts +441 -0
- package/templates/basic/src/__tests__/llm.test.ts +344 -0
- package/templates/basic/src/chat.ts +300 -0
- package/templates/basic/src/cortex.ts +203 -0
- package/templates/basic/src/display.ts +425 -0
- package/templates/basic/src/index.ts +194 -64
- package/templates/basic/src/llm.ts +214 -0
- package/templates/basic/src/server.ts +280 -0
- package/templates/basic/vitest.config.ts +33 -0
- package/templates/basic/vitest.e2e.config.ts +28 -0
- package/templates/basic/vitest.integration.config.ts +25 -0
- package/templates/vercel-ai-quickstart/app/api/auth/check/route.ts +1 -1
- package/templates/vercel-ai-quickstart/app/api/auth/login/route.ts +6 -9
- package/templates/vercel-ai-quickstart/app/api/auth/register/route.ts +14 -18
- package/templates/vercel-ai-quickstart/app/api/auth/setup/route.ts +4 -7
- package/templates/vercel-ai-quickstart/app/api/chat/route.ts +28 -11
- package/templates/vercel-ai-quickstart/app/api/chat-v6/route.ts +19 -13
- package/templates/vercel-ai-quickstart/app/api/conversations/route.ts +16 -16
- package/templates/vercel-ai-quickstart/app/globals.css +24 -9
- package/templates/vercel-ai-quickstart/app/page.tsx +25 -13
- package/templates/vercel-ai-quickstart/components/AdminSetup.tsx +3 -1
- package/templates/vercel-ai-quickstart/components/AuthProvider.tsx +6 -6
- package/templates/vercel-ai-quickstart/components/ChatHistorySidebar.tsx +19 -8
- package/templates/vercel-ai-quickstart/components/ChatInterface.tsx +41 -14
- package/templates/vercel-ai-quickstart/components/LoginScreen.tsx +10 -5
- package/templates/vercel-ai-quickstart/lib/agents/memory-agent.ts +3 -3
- package/templates/vercel-ai-quickstart/lib/password.ts +5 -5
- package/templates/vercel-ai-quickstart/next.config.js +10 -2
- package/templates/vercel-ai-quickstart/package.json +18 -11
- package/templates/vercel-ai-quickstart/test-api.mjs +131 -100
- package/templates/vercel-ai-quickstart/tests/e2e/chat-memory-flow.test.ts +73 -44
- package/templates/vercel-ai-quickstart/tests/helpers/mock-cortex.ts +40 -40
- package/templates/vercel-ai-quickstart/tests/integration/auth.test.ts +8 -8
- package/templates/vercel-ai-quickstart/tests/integration/conversations.test.ts +12 -8
- package/templates/vercel-ai-quickstart/tests/unit/password.test.ts +4 -1
|
@@ -48,42 +48,40 @@ export function createMockCortex() {
|
|
|
48
48
|
const ns = mutableStore.get(namespace);
|
|
49
49
|
if (!ns) return null;
|
|
50
50
|
return ns.get(key) ?? null;
|
|
51
|
-
}
|
|
51
|
+
},
|
|
52
52
|
),
|
|
53
53
|
set: jest.fn(
|
|
54
54
|
async (
|
|
55
55
|
namespace: string,
|
|
56
56
|
key: string,
|
|
57
|
-
value: unknown
|
|
57
|
+
value: unknown,
|
|
58
58
|
): Promise<void> => {
|
|
59
59
|
if (!mutableStore.has(namespace)) {
|
|
60
60
|
mutableStore.set(namespace, new Map());
|
|
61
61
|
}
|
|
62
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
|
-
}
|
|
63
|
+
},
|
|
70
64
|
),
|
|
65
|
+
delete: jest.fn(async (namespace: string, key: string): Promise<void> => {
|
|
66
|
+
const ns = mutableStore.get(namespace);
|
|
67
|
+
if (ns) ns.delete(key);
|
|
68
|
+
}),
|
|
71
69
|
},
|
|
72
70
|
users: {
|
|
73
71
|
get: jest.fn(
|
|
74
72
|
async (
|
|
75
|
-
userId: string
|
|
73
|
+
userId: string,
|
|
76
74
|
): Promise<{
|
|
77
75
|
userId: string;
|
|
78
76
|
data: Record<string, unknown>;
|
|
79
77
|
} | null> => {
|
|
80
78
|
return usersStore.get(userId) ?? null;
|
|
81
|
-
}
|
|
79
|
+
},
|
|
82
80
|
),
|
|
83
81
|
update: jest.fn(
|
|
84
82
|
async (
|
|
85
83
|
userId: string,
|
|
86
|
-
data: Record<string, unknown
|
|
84
|
+
data: Record<string, unknown>,
|
|
87
85
|
): Promise<{ userId: string; data: Record<string, unknown> }> => {
|
|
88
86
|
const existing = usersStore.get(userId);
|
|
89
87
|
const user = {
|
|
@@ -92,7 +90,7 @@ export function createMockCortex() {
|
|
|
92
90
|
};
|
|
93
91
|
usersStore.set(userId, user);
|
|
94
92
|
return user;
|
|
95
|
-
}
|
|
93
|
+
},
|
|
96
94
|
),
|
|
97
95
|
delete: jest.fn(async (userId: string): Promise<void> => {
|
|
98
96
|
usersStore.delete(userId);
|
|
@@ -115,17 +113,14 @@ export function createMockCortex() {
|
|
|
115
113
|
) {
|
|
116
114
|
return false;
|
|
117
115
|
}
|
|
118
|
-
if (
|
|
119
|
-
params.userId &&
|
|
120
|
-
conv.participants.userId !== params.userId
|
|
121
|
-
) {
|
|
116
|
+
if (params.userId && conv.participants.userId !== params.userId) {
|
|
122
117
|
return false;
|
|
123
118
|
}
|
|
124
119
|
return true;
|
|
125
|
-
}
|
|
120
|
+
},
|
|
126
121
|
);
|
|
127
122
|
return { conversations, hasMore: false };
|
|
128
|
-
}
|
|
123
|
+
},
|
|
129
124
|
),
|
|
130
125
|
create: jest.fn(
|
|
131
126
|
async (params: {
|
|
@@ -148,31 +143,36 @@ export function createMockCortex() {
|
|
|
148
143
|
};
|
|
149
144
|
conversationsStore.set(params.conversationId, conversation);
|
|
150
145
|
return conversation;
|
|
151
|
-
}
|
|
146
|
+
},
|
|
147
|
+
),
|
|
148
|
+
get: jest.fn(
|
|
149
|
+
async (
|
|
150
|
+
conversationId: string,
|
|
151
|
+
options?: { includeMessages?: boolean; messageLimit?: number },
|
|
152
|
+
) => {
|
|
153
|
+
const conv = conversationsStore.get(conversationId);
|
|
154
|
+
if (!conv) return null;
|
|
155
|
+
|
|
156
|
+
// If includeMessages is requested, return with messages
|
|
157
|
+
if (options?.includeMessages) {
|
|
158
|
+
return {
|
|
159
|
+
...conv,
|
|
160
|
+
messages: conv.messages || [],
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Otherwise return without messages
|
|
165
|
+
const { messages: _messages, ...convWithoutMessages } = conv;
|
|
166
|
+
return convWithoutMessages;
|
|
167
|
+
},
|
|
152
168
|
),
|
|
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
169
|
delete: jest.fn(async (conversationId: string): Promise<void> => {
|
|
170
170
|
conversationsStore.delete(conversationId);
|
|
171
171
|
}),
|
|
172
172
|
update: jest.fn(
|
|
173
173
|
async (
|
|
174
174
|
conversationId: string,
|
|
175
|
-
updates: { metadata?: Record<string, unknown> }
|
|
175
|
+
updates: { metadata?: Record<string, unknown> },
|
|
176
176
|
) => {
|
|
177
177
|
const conv = conversationsStore.get(conversationId);
|
|
178
178
|
if (!conv) throw new Error("Conversation not found");
|
|
@@ -183,7 +183,7 @@ export function createMockCortex() {
|
|
|
183
183
|
};
|
|
184
184
|
conversationsStore.set(conversationId, updated);
|
|
185
185
|
return updated;
|
|
186
|
-
}
|
|
186
|
+
},
|
|
187
187
|
),
|
|
188
188
|
},
|
|
189
189
|
memory: {
|
|
@@ -215,7 +215,7 @@ export type MockCortex = ReturnType<typeof createMockCortex>;
|
|
|
215
215
|
export const seedTestData = {
|
|
216
216
|
user: (
|
|
217
217
|
userId: string,
|
|
218
|
-
data: Record<string, unknown> = {}
|
|
218
|
+
data: Record<string, unknown> = {},
|
|
219
219
|
): { userId: string; data: Record<string, unknown> } => {
|
|
220
220
|
const user = { userId, data };
|
|
221
221
|
usersStore.set(userId, user);
|
|
@@ -234,7 +234,7 @@ export const seedTestData = {
|
|
|
234
234
|
userId?: string;
|
|
235
235
|
title?: string;
|
|
236
236
|
messages?: Array<{ role: string; content: string }>;
|
|
237
|
-
} = {}
|
|
237
|
+
} = {},
|
|
238
238
|
) => {
|
|
239
239
|
const now = Date.now();
|
|
240
240
|
const messages = params.messages?.map((msg, i) => ({
|
|
@@ -31,7 +31,7 @@ import { POST as loginPost } from "../../app/api/auth/login/route";
|
|
|
31
31
|
function createRequest(
|
|
32
32
|
method: string,
|
|
33
33
|
body?: Record<string, unknown>,
|
|
34
|
-
url: string = "http://localhost:3000"
|
|
34
|
+
url: string = "http://localhost:3000",
|
|
35
35
|
): Request {
|
|
36
36
|
const init: RequestInit = { method };
|
|
37
37
|
if (body) {
|
|
@@ -76,7 +76,7 @@ describe("Auth API Routes", () => {
|
|
|
76
76
|
seedTestData.mutable(
|
|
77
77
|
"quickstart-config",
|
|
78
78
|
"admin_password_hash",
|
|
79
|
-
"somehash:value"
|
|
79
|
+
"somehash:value",
|
|
80
80
|
);
|
|
81
81
|
|
|
82
82
|
const response = await checkGet();
|
|
@@ -91,7 +91,7 @@ describe("Auth API Routes", () => {
|
|
|
91
91
|
|
|
92
92
|
expect(mockCortex.mutable.get).toHaveBeenCalledWith(
|
|
93
93
|
"quickstart-config",
|
|
94
|
-
"admin_password_hash"
|
|
94
|
+
"admin_password_hash",
|
|
95
95
|
);
|
|
96
96
|
});
|
|
97
97
|
});
|
|
@@ -133,7 +133,7 @@ describe("Auth API Routes", () => {
|
|
|
133
133
|
seedTestData.mutable(
|
|
134
134
|
"quickstart-config",
|
|
135
135
|
"admin_password_hash",
|
|
136
|
-
"existing:hash"
|
|
136
|
+
"existing:hash",
|
|
137
137
|
);
|
|
138
138
|
|
|
139
139
|
const request = createRequest("POST", { password: "newpassword" });
|
|
@@ -157,7 +157,7 @@ describe("Auth API Routes", () => {
|
|
|
157
157
|
expect(mockCortex.mutable.set).toHaveBeenCalledWith(
|
|
158
158
|
"quickstart-config",
|
|
159
159
|
"admin_password_hash",
|
|
160
|
-
expect.stringContaining(":") // salt:hash format
|
|
160
|
+
expect.stringContaining(":"), // salt:hash format
|
|
161
161
|
);
|
|
162
162
|
});
|
|
163
163
|
});
|
|
@@ -262,7 +262,7 @@ describe("Auth API Routes", () => {
|
|
|
262
262
|
passwordHash: expect.stringContaining(":"),
|
|
263
263
|
createdAt: expect.any(Number),
|
|
264
264
|
lastLoginAt: expect.any(Number),
|
|
265
|
-
})
|
|
265
|
+
}),
|
|
266
266
|
);
|
|
267
267
|
});
|
|
268
268
|
|
|
@@ -288,7 +288,7 @@ describe("Auth API Routes", () => {
|
|
|
288
288
|
|
|
289
289
|
expect(status).toBe(200);
|
|
290
290
|
expect((data.user as { displayName: string }).displayName).toBe(
|
|
291
|
-
"testuser"
|
|
291
|
+
"testuser",
|
|
292
292
|
);
|
|
293
293
|
});
|
|
294
294
|
|
|
@@ -448,7 +448,7 @@ describe("Auth API Routes", () => {
|
|
|
448
448
|
|
|
449
449
|
expect(status).toBe(200);
|
|
450
450
|
expect((data.user as { displayName: string }).displayName).toBe(
|
|
451
|
-
"testuser"
|
|
451
|
+
"testuser",
|
|
452
452
|
);
|
|
453
453
|
});
|
|
454
454
|
});
|
|
@@ -33,7 +33,7 @@ function createRequest(
|
|
|
33
33
|
options: {
|
|
34
34
|
body?: Record<string, unknown>;
|
|
35
35
|
searchParams?: Record<string, string>;
|
|
36
|
-
} = {}
|
|
36
|
+
} = {},
|
|
37
37
|
): Request {
|
|
38
38
|
const url = new URL("http://localhost:3000/api/conversations");
|
|
39
39
|
|
|
@@ -102,8 +102,12 @@ describe("Conversations API Routes", () => {
|
|
|
102
102
|
|
|
103
103
|
expect(status).toBe(200);
|
|
104
104
|
expect(data.conversation).toBeDefined();
|
|
105
|
-
expect((data.conversation as { id: string }).id).toBe(
|
|
106
|
-
|
|
105
|
+
expect((data.conversation as { id: string }).id).toBe(
|
|
106
|
+
"conv-with-messages",
|
|
107
|
+
);
|
|
108
|
+
expect((data.conversation as { title: string }).title).toBe(
|
|
109
|
+
"Test Conversation",
|
|
110
|
+
);
|
|
107
111
|
expect(data.messages).toBeDefined();
|
|
108
112
|
expect((data.messages as unknown[]).length).toBe(2);
|
|
109
113
|
});
|
|
@@ -235,7 +239,7 @@ describe("Conversations API Routes", () => {
|
|
|
235
239
|
expect.objectContaining({
|
|
236
240
|
memorySpaceId: "quickstart-demo",
|
|
237
241
|
userId: "testuser",
|
|
238
|
-
})
|
|
242
|
+
}),
|
|
239
243
|
);
|
|
240
244
|
});
|
|
241
245
|
});
|
|
@@ -304,7 +308,7 @@ describe("Conversations API Routes", () => {
|
|
|
304
308
|
expect(mockCortex.conversations.create).toHaveBeenCalledWith(
|
|
305
309
|
expect.objectContaining({
|
|
306
310
|
memorySpaceId: "custom-space",
|
|
307
|
-
})
|
|
311
|
+
}),
|
|
308
312
|
);
|
|
309
313
|
});
|
|
310
314
|
|
|
@@ -317,7 +321,7 @@ describe("Conversations API Routes", () => {
|
|
|
317
321
|
expect(mockCortex.conversations.create).toHaveBeenCalledWith(
|
|
318
322
|
expect.objectContaining({
|
|
319
323
|
memorySpaceId: "quickstart-demo",
|
|
320
|
-
})
|
|
324
|
+
}),
|
|
321
325
|
);
|
|
322
326
|
});
|
|
323
327
|
|
|
@@ -330,7 +334,7 @@ describe("Conversations API Routes", () => {
|
|
|
330
334
|
expect(mockCortex.conversations.create).toHaveBeenCalledWith(
|
|
331
335
|
expect.objectContaining({
|
|
332
336
|
type: "user-agent",
|
|
333
|
-
})
|
|
337
|
+
}),
|
|
334
338
|
);
|
|
335
339
|
});
|
|
336
340
|
|
|
@@ -346,7 +350,7 @@ describe("Conversations API Routes", () => {
|
|
|
346
350
|
userId: "testuser",
|
|
347
351
|
agentId: "quickstart-assistant",
|
|
348
352
|
},
|
|
349
|
-
})
|
|
353
|
+
}),
|
|
350
354
|
);
|
|
351
355
|
});
|
|
352
356
|
|
|
@@ -137,7 +137,10 @@ describe("Password Utilities", () => {
|
|
|
137
137
|
});
|
|
138
138
|
|
|
139
139
|
it("should return false for invalid base64 in salt", async () => {
|
|
140
|
-
const result = await verifyPassword(
|
|
140
|
+
const result = await verifyPassword(
|
|
141
|
+
"password",
|
|
142
|
+
"!!!invalid!!!:validhash",
|
|
143
|
+
);
|
|
141
144
|
|
|
142
145
|
expect(result).toBe(false);
|
|
143
146
|
});
|