@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
@@ -3,14 +3,17 @@
3
3
  *
4
4
  * Top-level commands for deploying and updating Cortex projects:
5
5
  * - deploy: Deploy schema and functions to Convex
6
- * - update: Update @cortexmemory/sdk and convex packages
6
+ * - update: Update @cortexmemory/sdk and convex packages across deployments and apps
7
7
  */
8
8
  import ora from "ora";
9
+ import path from "path";
10
+ import fs from "fs-extra";
9
11
  import { resolveConfig, loadConfig } from "../utils/config.js";
10
- import { selectDeployment } from "../utils/deployment-selector.js";
12
+ import { selectDeployment, getEnabledDeployments, } from "../utils/deployment-selector.js";
11
13
  import { getDeploymentInfo } from "../utils/client.js";
12
14
  import { printSuccess, printError, printWarning, printInfo, printSection, } from "../utils/formatting.js";
13
15
  import { execCommand, execCommandLive } from "../utils/shell.js";
16
+ import { syncAppTemplate, checkTemplateSync, printTemplateSyncResult, } from "../utils/app-template-sync.js";
14
17
  import pc from "picocolors";
15
18
  /**
16
19
  * Build environment for Convex commands, removing inherited CONVEX_* vars
@@ -136,195 +139,890 @@ export function registerDeployCommands(program, _config) {
136
139
  // cortex update
137
140
  program
138
141
  .command("update")
139
- .description("Update @cortexmemory/sdk and convex packages")
140
- .option("-d, --deployment <name>", "Target deployment")
142
+ .description("Update @cortexmemory/sdk and convex packages across all enabled deployments and apps")
143
+ .option("-d, --deployment <name>", "Target a specific deployment only")
144
+ .option("-a, --app <name>", "Target a specific app only")
145
+ .option("--apps-only", "Only update apps (skip deployments)", false)
146
+ .option("--deployments-only", "Only update deployments (skip apps)", false)
147
+ .option("--dev", "Use dev mode (link to local SDK via CORTEX_SDK_DEV_PATH)", false)
148
+ .option("--sync-template", "Sync app template files (components, routes, etc.)", false)
141
149
  .option("--sdk-version <version>", "Specific Cortex SDK version to install")
142
150
  .option("--convex-version <version>", "Specific Convex version to install")
151
+ .option("--provider-version <version>", "Specific vercel-ai-provider version to install")
143
152
  .option("-y, --yes", "Auto-accept all updates", false)
144
153
  .action(async (options) => {
145
154
  const currentConfig = await loadConfig();
146
- const selection = await selectDeployment(currentConfig, options, "update packages");
147
- if (!selection)
155
+ // Check for dev mode
156
+ const devPath = process.env.CORTEX_SDK_DEV_PATH;
157
+ const isDevMode = options.dev || !!devPath;
158
+ if (isDevMode && !devPath) {
159
+ console.log(pc.red("\n Dev mode requires CORTEX_SDK_DEV_PATH environment variable"));
160
+ console.log(pc.dim(" Set it to the path of your local Project-Cortex repo:"));
161
+ console.log(pc.dim(" export CORTEX_SDK_DEV_PATH=/path/to/Project-Cortex\n"));
148
162
  return;
149
- const { deployment } = selection;
150
- const projectPath = deployment.projectPath || process.cwd();
151
- const spinner = ora("Checking for updates...").start();
152
- try {
153
- // Get current Cortex SDK version
154
- let currentSdkVersion = "not installed";
163
+ }
164
+ // If -a flag is provided, use single app mode
165
+ if (options.app) {
166
+ const app = currentConfig.apps?.[options.app];
167
+ if (!app) {
168
+ console.log(pc.red(`\n App "${options.app}" not found`));
169
+ const appNames = Object.keys(currentConfig.apps || {});
170
+ if (appNames.length > 0) {
171
+ console.log(pc.dim(` Available: ${appNames.join(", ")}`));
172
+ }
173
+ else {
174
+ console.log(pc.dim(" No apps configured. Run 'cortex init' to add one."));
175
+ }
176
+ return;
177
+ }
155
178
  try {
156
- const result = await execCommand("npm", ["list", "@cortexmemory/sdk", "--json"], { quiet: true, cwd: projectPath });
157
- const data = JSON.parse(result.stdout);
158
- currentSdkVersion =
159
- data.dependencies?.["@cortexmemory/sdk"]?.version ??
160
- "not installed";
179
+ await updateApp(options.app, app, {
180
+ ...options,
181
+ devPath: isDevMode ? devPath : undefined,
182
+ syncTemplate: options.syncTemplate,
183
+ });
161
184
  }
162
- catch {
163
- // Ignore errors
185
+ catch (error) {
186
+ printError(`Failed to update app "${options.app}": ${error instanceof Error ? error.message : "Unknown error"}`);
164
187
  }
165
- // Get latest Cortex SDK version from npm
166
- let latestSdkVersion = "unknown";
188
+ return;
189
+ }
190
+ // If -d flag is provided, use single deployment mode (existing behavior)
191
+ if (options.deployment) {
192
+ const selection = await selectDeployment(currentConfig, options, "update packages");
193
+ if (!selection)
194
+ return;
195
+ const { name, deployment } = selection;
167
196
  try {
168
- const result = await execCommand("npm", ["view", "@cortexmemory/sdk", "version"], { quiet: true });
169
- latestSdkVersion = result.stdout.trim();
197
+ await updateDeployment(name, deployment, options);
170
198
  }
171
- catch {
172
- // Ignore errors
199
+ catch (error) {
200
+ printError(`Failed to update deployment "${name}": ${error instanceof Error ? error.message : "Unknown error"}`);
173
201
  }
174
- // Get current Convex version
175
- let currentConvexVersion = "not installed";
202
+ return;
203
+ }
204
+ // Determine what to update based on flags
205
+ const updateDeployments = !options.appsOnly;
206
+ const updateApps = !options.deploymentsOnly;
207
+ // Get enabled deployments and apps
208
+ const { deployments: enabledDeployments } = getEnabledDeployments(currentConfig);
209
+ const enabledApps = Object.entries(currentConfig.apps || {})
210
+ .filter(([, app]) => app.enabled)
211
+ .map(([name, app]) => ({ name, app }));
212
+ const hasDeployments = enabledDeployments.length > 0;
213
+ const hasApps = enabledApps.length > 0;
214
+ if (updateDeployments && !hasDeployments && !options.appsOnly) {
215
+ console.log(pc.yellow("\n No enabled deployments found"));
216
+ }
217
+ if (updateApps && !hasApps && !options.deploymentsOnly) {
218
+ console.log(pc.yellow("\n No enabled apps found"));
219
+ }
220
+ if ((!updateDeployments || !hasDeployments) && (!updateApps || !hasApps)) {
221
+ console.log(pc.red("\n Nothing to update"));
222
+ console.log(pc.dim(" Run 'cortex init' to configure deployments and apps\n"));
223
+ return;
224
+ }
225
+ // Single deployment + no apps - proceed directly (backwards compatibility)
226
+ if (updateDeployments && enabledDeployments.length === 1 && (!updateApps || !hasApps)) {
227
+ const { name, deployment } = enabledDeployments[0];
228
+ console.log(pc.dim(` Using: ${name}`));
229
+ await updateDeployment(name, deployment, options);
230
+ return;
231
+ }
232
+ // Multiple targets or apps - show status dashboard
233
+ console.log();
234
+ const spinner = ora("Checking package versions...").start();
235
+ // Get latest versions - from local source in dev mode, from npm otherwise
236
+ let latestSdkVersion = "unknown";
237
+ let latestConvexVersion = "unknown";
238
+ let latestProviderVersion = "unknown";
239
+ let latestAiVersion = "unknown";
240
+ let sdkConvexPeerDep = "unknown";
241
+ if (isDevMode && devPath) {
242
+ // In dev mode, read versions from local source package.json files
176
243
  try {
177
- const result = await execCommand("npm", ["list", "convex", "--json"], { quiet: true, cwd: projectPath });
178
- const data = JSON.parse(result.stdout);
179
- currentConvexVersion =
180
- data.dependencies?.convex?.version ?? "not installed";
244
+ const sdkPkgPath = path.join(devPath, "package.json");
245
+ const providerPkgPath = path.join(devPath, "packages", "vercel-ai-provider", "package.json");
246
+ if (await fs.pathExists(sdkPkgPath)) {
247
+ const sdkPkg = await fs.readJson(sdkPkgPath);
248
+ latestSdkVersion = sdkPkg.version || "unknown";
249
+ // Also get peerDependencies from local source
250
+ sdkConvexPeerDep = sdkPkg.peerDependencies?.convex ?? "unknown";
251
+ }
252
+ if (await fs.pathExists(providerPkgPath)) {
253
+ const providerPkg = await fs.readJson(providerPkgPath);
254
+ latestProviderVersion = providerPkg.version || "unknown";
255
+ }
256
+ // Still fetch convex and ai versions from npm (external dependencies)
257
+ const [convexResult, aiResult] = await Promise.all([
258
+ execCommand("npm", ["view", "convex", "version"], {
259
+ quiet: true,
260
+ }).catch(() => ({ stdout: "unknown" })),
261
+ execCommand("npm", ["view", "ai", "version"], {
262
+ quiet: true,
263
+ }).catch(() => ({ stdout: "unknown" })),
264
+ ]);
265
+ latestConvexVersion = convexResult.stdout.trim() || "unknown";
266
+ latestAiVersion = aiResult.stdout.trim() || "unknown";
181
267
  }
182
268
  catch {
183
- // Ignore errors
269
+ // Ignore errors, versions will remain "unknown"
184
270
  }
185
- // Get latest Convex version from npm
186
- let latestConvexVersion = "unknown";
271
+ }
272
+ else {
273
+ // Normal mode: fetch all versions from npm
187
274
  try {
188
- const result = await execCommand("npm", ["view", "convex", "version"], { quiet: true });
189
- latestConvexVersion = result.stdout.trim();
275
+ const [sdkResult, convexResult, providerResult, aiResult, peerDepResult] = await Promise.all([
276
+ execCommand("npm", ["view", "@cortexmemory/sdk", "version"], {
277
+ quiet: true,
278
+ }).catch(() => ({ stdout: "unknown" })),
279
+ execCommand("npm", ["view", "convex", "version"], {
280
+ quiet: true,
281
+ }).catch(() => ({ stdout: "unknown" })),
282
+ execCommand("npm", ["view", "@cortexmemory/vercel-ai-provider", "version"], {
283
+ quiet: true,
284
+ }).catch(() => ({ stdout: "unknown" })),
285
+ execCommand("npm", ["view", "ai", "version"], {
286
+ quiet: true,
287
+ }).catch(() => ({ stdout: "unknown" })),
288
+ execCommand("npm", ["view", "@cortexmemory/sdk", "peerDependencies", "--json"], { quiet: true }).catch(() => ({ stdout: "{}" })),
289
+ ]);
290
+ latestSdkVersion = sdkResult.stdout.trim() || "unknown";
291
+ latestConvexVersion = convexResult.stdout.trim() || "unknown";
292
+ latestProviderVersion = providerResult.stdout.trim() || "unknown";
293
+ latestAiVersion = aiResult.stdout.trim() || "unknown";
294
+ try {
295
+ const peerDeps = JSON.parse(peerDepResult.stdout);
296
+ sdkConvexPeerDep = peerDeps?.convex ?? "unknown";
297
+ }
298
+ catch {
299
+ // Ignore parse errors
300
+ }
190
301
  }
191
302
  catch {
192
303
  // Ignore errors
193
304
  }
194
- // Get Cortex SDK's peer dependency on Convex
195
- let sdkConvexPeerDep = "unknown";
196
- try {
197
- const result = await execCommand("npm", ["view", "@cortexmemory/sdk", "peerDependencies", "--json"], { quiet: true });
198
- const peerDeps = JSON.parse(result.stdout);
199
- sdkConvexPeerDep = peerDeps?.convex ?? "unknown";
305
+ }
306
+ const deploymentInfos = [];
307
+ const appInfos = [];
308
+ // Check deployments
309
+ if (updateDeployments && hasDeployments) {
310
+ for (const { name, deployment, projectPath } of enabledDeployments) {
311
+ let currentSdkVersion = "not installed";
312
+ let currentProviderVersion = "not installed";
313
+ let currentAiVersion = "not installed";
314
+ let currentConvexVersion = "not installed";
315
+ // Check all packages in one npm list call for efficiency
316
+ try {
317
+ const result = await execCommand("npm", ["list", "@cortexmemory/sdk", "@cortexmemory/vercel-ai-provider", "convex", "ai", "--json"], { quiet: true, cwd: projectPath });
318
+ const data = JSON.parse(result.stdout);
319
+ currentSdkVersion =
320
+ data.dependencies?.["@cortexmemory/sdk"]?.version ?? "not installed";
321
+ currentProviderVersion =
322
+ data.dependencies?.["@cortexmemory/vercel-ai-provider"]?.version ?? "not installed";
323
+ currentAiVersion =
324
+ data.dependencies?.ai?.version ?? "not installed";
325
+ currentConvexVersion =
326
+ data.dependencies?.convex?.version ?? "not installed";
327
+ }
328
+ catch {
329
+ // Ignore errors
330
+ }
331
+ const targetSdkVersion = options.sdkVersion ?? latestSdkVersion;
332
+ const needsUpdate = currentSdkVersion !== targetSdkVersion ||
333
+ currentSdkVersion === "not installed";
334
+ deploymentInfos.push({
335
+ name,
336
+ deployment,
337
+ projectPath,
338
+ currentSdkVersion,
339
+ currentProviderVersion,
340
+ currentAiVersion,
341
+ currentConvexVersion,
342
+ needsUpdate,
343
+ });
200
344
  }
201
- catch {
202
- // Ignore errors
345
+ }
346
+ // Check apps
347
+ if (updateApps && hasApps) {
348
+ for (const { name, app } of enabledApps) {
349
+ const appPath = path.join(app.projectPath, app.path);
350
+ let currentSdkVersion = "not installed";
351
+ let currentProviderVersion = "not installed";
352
+ let currentConvexVersion = "not installed";
353
+ let currentAiVersion = "not installed";
354
+ let isDevLinked = false;
355
+ // Check package.json for file: references (dev linked)
356
+ try {
357
+ const packageJsonPath = path.join(appPath, "package.json");
358
+ if (await fs.pathExists(packageJsonPath)) {
359
+ const pkg = await fs.readJson(packageJsonPath);
360
+ const sdkDep = pkg.dependencies?.["@cortexmemory/sdk"];
361
+ const providerDep = pkg.dependencies?.["@cortexmemory/vercel-ai-provider"];
362
+ isDevLinked = sdkDep?.startsWith("file:") || providerDep?.startsWith("file:");
363
+ }
364
+ }
365
+ catch {
366
+ // Ignore errors
367
+ }
368
+ // Get installed versions
369
+ try {
370
+ const result = await execCommand("npm", ["list", "@cortexmemory/sdk", "@cortexmemory/vercel-ai-provider", "convex", "ai", "--json"], { quiet: true, cwd: appPath });
371
+ const data = JSON.parse(result.stdout);
372
+ currentSdkVersion =
373
+ data.dependencies?.["@cortexmemory/sdk"]?.version ?? "not installed";
374
+ currentProviderVersion =
375
+ data.dependencies?.["@cortexmemory/vercel-ai-provider"]?.version ?? "not installed";
376
+ currentConvexVersion =
377
+ data.dependencies?.convex?.version ?? "not installed";
378
+ currentAiVersion =
379
+ data.dependencies?.ai?.version ?? "not installed";
380
+ }
381
+ catch {
382
+ // Ignore errors
383
+ }
384
+ const targetSdkVersion = isDevMode ? "dev" : (options.sdkVersion ?? latestSdkVersion);
385
+ const needsUpdate = isDevMode
386
+ ? !isDevLinked // Dev mode: needs update if not already dev-linked
387
+ : (currentSdkVersion !== targetSdkVersion || currentSdkVersion === "not installed");
388
+ // Check template sync status if --sync-template is enabled
389
+ let templateFilesToUpdate = 0;
390
+ let templateFilesToAdd = 0;
391
+ let needsTemplateSync = false;
392
+ if (options.syncTemplate) {
393
+ try {
394
+ const templateStatus = await checkTemplateSync(app);
395
+ templateFilesToUpdate = templateStatus.filesOutdated.length;
396
+ templateFilesToAdd = templateStatus.filesMissing.length;
397
+ needsTemplateSync = templateStatus.needsSync;
398
+ }
399
+ catch {
400
+ // Ignore errors
401
+ }
402
+ }
403
+ appInfos.push({
404
+ name,
405
+ app,
406
+ appPath,
407
+ currentSdkVersion,
408
+ currentProviderVersion,
409
+ currentConvexVersion,
410
+ currentAiVersion,
411
+ needsUpdate,
412
+ isDevLinked,
413
+ templateFilesToUpdate,
414
+ templateFilesToAdd,
415
+ needsTemplateSync,
416
+ });
203
417
  }
204
- spinner.stop();
205
- // Display current status
418
+ }
419
+ spinner.stop();
420
+ // Display status dashboard
421
+ if (isDevMode) {
422
+ console.log(pc.magenta(" ═══ DEV MODE ═══"));
423
+ console.log(pc.dim(` SDK path: ${devPath}`));
206
424
  console.log();
207
- printSection("Package Status", {
208
- "Project Path": projectPath,
425
+ }
426
+ // Use "Source versions" in dev mode to indicate local package.json versions
427
+ const versionsLabel = isDevMode ? "Source versions" : "Latest versions";
428
+ console.log(pc.bold(` ${versionsLabel}:`));
429
+ console.log(` @cortexmemory/sdk: ${pc.cyan(latestSdkVersion)}`);
430
+ console.log(` @cortexmemory/vercel-ai-provider: ${pc.cyan(latestProviderVersion)}`);
431
+ console.log(` convex: ${pc.cyan(latestConvexVersion)}`);
432
+ console.log(` ai: ${pc.cyan(latestAiVersion)}`);
433
+ if (sdkConvexPeerDep !== "unknown") {
434
+ console.log(` SDK requires convex: ${pc.dim(sdkConvexPeerDep)}`);
435
+ }
436
+ console.log();
437
+ // Show deployment status
438
+ if (deploymentInfos.length > 0) {
439
+ printSection("Deployments", {});
440
+ console.log();
441
+ for (const info of deploymentInfos) {
442
+ const isDefault = info.name === currentConfig.default;
443
+ const defaultBadge = isDefault ? pc.cyan(" (default)") : "";
444
+ const statusIcon = info.needsUpdate
445
+ ? pc.yellow("●")
446
+ : pc.green("●");
447
+ console.log(` ${statusIcon} ${pc.bold(info.name)}${defaultBadge}`);
448
+ console.log(pc.dim(` Path: ${info.projectPath}`));
449
+ console.log(` SDK: ${info.currentSdkVersion === latestSdkVersion ? pc.green(info.currentSdkVersion) : pc.yellow(info.currentSdkVersion)}`);
450
+ // Only show provider and AI if they're installed (frontend packages)
451
+ if (info.currentProviderVersion !== "not installed") {
452
+ console.log(` Provider: ${info.currentProviderVersion === latestProviderVersion ? pc.green(info.currentProviderVersion) : pc.yellow(info.currentProviderVersion)}`);
453
+ }
454
+ if (info.currentAiVersion !== "not installed") {
455
+ console.log(` AI: ${info.currentAiVersion === latestAiVersion ? pc.green(info.currentAiVersion) : pc.yellow(info.currentAiVersion)}`);
456
+ }
457
+ console.log(` Convex: ${info.currentConvexVersion === latestConvexVersion ? pc.green(info.currentConvexVersion) : pc.yellow(info.currentConvexVersion)}`);
458
+ console.log();
459
+ }
460
+ }
461
+ // Show app status
462
+ if (appInfos.length > 0) {
463
+ printSection("Apps", {});
464
+ console.log();
465
+ for (const info of appInfos) {
466
+ const devBadge = info.isDevLinked ? pc.magenta(" [DEV]") : "";
467
+ const needsAnyUpdate = info.needsUpdate || info.needsTemplateSync;
468
+ const statusIcon = needsAnyUpdate
469
+ ? pc.yellow("●")
470
+ : pc.green("●");
471
+ console.log(` ${statusIcon} ${pc.bold(info.name)}${devBadge}`);
472
+ console.log(pc.dim(` Path: ${info.appPath}`));
473
+ console.log(` SDK: ${info.isDevLinked ? pc.magenta("file:...") : (info.currentSdkVersion === latestSdkVersion ? pc.green(info.currentSdkVersion) : pc.yellow(info.currentSdkVersion))}`);
474
+ console.log(` Provider: ${info.isDevLinked ? pc.magenta("file:...") : (info.currentProviderVersion === latestProviderVersion ? pc.green(info.currentProviderVersion) : pc.yellow(info.currentProviderVersion))}`);
475
+ console.log(` AI: ${info.currentAiVersion === latestAiVersion ? pc.green(info.currentAiVersion) : pc.yellow(info.currentAiVersion)}`);
476
+ console.log(` Convex: ${info.currentConvexVersion === latestConvexVersion ? pc.green(info.currentConvexVersion) : pc.yellow(info.currentConvexVersion)}`);
477
+ // Show template sync status if --sync-template is enabled
478
+ if (options.syncTemplate) {
479
+ const totalTemplateChanges = info.templateFilesToUpdate + info.templateFilesToAdd;
480
+ if (totalTemplateChanges > 0) {
481
+ console.log(` Template: ${pc.yellow(`${totalTemplateChanges} file(s) to sync`)}`);
482
+ }
483
+ else {
484
+ console.log(` Template: ${pc.green("up to date")}`);
485
+ }
486
+ }
487
+ console.log();
488
+ }
489
+ }
490
+ // Count updates needed
491
+ const deploymentsNeedingUpdate = deploymentInfos.filter((d) => d.needsUpdate);
492
+ const appsNeedingUpdate = appInfos.filter((a) => a.needsUpdate || (options.syncTemplate && a.needsTemplateSync));
493
+ const totalNeedingUpdate = deploymentsNeedingUpdate.length + appsNeedingUpdate.length;
494
+ // Check if any updates needed
495
+ if (totalNeedingUpdate === 0) {
496
+ printSuccess("Everything is up to date!");
497
+ return;
498
+ }
499
+ // Prompt for confirmation
500
+ const updateParts = [];
501
+ if (deploymentsNeedingUpdate.length > 0) {
502
+ updateParts.push(`${deploymentsNeedingUpdate.length} deployment(s)`);
503
+ }
504
+ if (appsNeedingUpdate.length > 0) {
505
+ updateParts.push(`${appsNeedingUpdate.length} app(s)`);
506
+ }
507
+ console.log(pc.cyan(` ${updateParts.join(" and ")} need updates`));
508
+ console.log();
509
+ let shouldProceed = options.yes;
510
+ if (!shouldProceed) {
511
+ const { default: prompts } = await import("prompts");
512
+ const response = await prompts({
513
+ type: "confirm",
514
+ name: "proceed",
515
+ message: `Update all ${totalNeedingUpdate} target(s)?`,
516
+ initial: true,
517
+ });
518
+ shouldProceed = response.proceed;
519
+ }
520
+ if (!shouldProceed) {
521
+ console.log(pc.yellow("\n Operation cancelled\n"));
522
+ console.log(pc.dim(" Tip: Use '-d <name>' for deployments or '-a <name>' for apps\n"));
523
+ return;
524
+ }
525
+ // Perform updates
526
+ console.log();
527
+ let deploymentSuccessCount = 0;
528
+ let deploymentFailCount = 0;
529
+ let appSuccessCount = 0;
530
+ let appFailCount = 0;
531
+ // Update deployments
532
+ for (const info of deploymentsNeedingUpdate) {
533
+ console.log(pc.bold(`\n━━━ Updating deployment: ${info.name} ━━━\n`));
534
+ try {
535
+ await updateDeployment(info.name, info.deployment, {
536
+ ...options,
537
+ yes: true,
538
+ });
539
+ deploymentSuccessCount++;
540
+ }
541
+ catch (error) {
542
+ printError(`Failed to update ${info.name}: ${error instanceof Error ? error.message : "Unknown error"}`);
543
+ deploymentFailCount++;
544
+ }
545
+ }
546
+ // Update apps
547
+ for (const info of appsNeedingUpdate) {
548
+ console.log(pc.bold(`\n━━━ Updating app: ${info.name} ━━━\n`));
549
+ try {
550
+ await updateApp(info.name, info.app, {
551
+ ...options,
552
+ devPath: isDevMode ? devPath : undefined,
553
+ syncTemplate: options.syncTemplate,
554
+ yes: true,
555
+ });
556
+ appSuccessCount++;
557
+ }
558
+ catch (error) {
559
+ printError(`Failed to update ${info.name}: ${error instanceof Error ? error.message : "Unknown error"}`);
560
+ appFailCount++;
561
+ }
562
+ }
563
+ // Summary
564
+ console.log();
565
+ console.log(pc.bold("━━━ Summary ━━━"));
566
+ console.log();
567
+ if (deploymentSuccessCount > 0) {
568
+ printSuccess(`${deploymentSuccessCount} deployment(s) updated successfully`);
569
+ }
570
+ if (deploymentFailCount > 0) {
571
+ printWarning(`${deploymentFailCount} deployment(s) failed to update`);
572
+ }
573
+ if (appSuccessCount > 0) {
574
+ printSuccess(`${appSuccessCount} app(s) updated successfully`);
575
+ }
576
+ if (appFailCount > 0) {
577
+ printWarning(`${appFailCount} app(s) failed to update`);
578
+ }
579
+ });
580
+ }
581
+ /**
582
+ * Update packages for a single deployment
583
+ */
584
+ async function updateDeployment(name, deployment, options) {
585
+ const projectPath = deployment.projectPath || process.cwd();
586
+ const spinner = ora("Checking for updates...").start();
587
+ try {
588
+ // Get current Cortex SDK version
589
+ let currentSdkVersion = "not installed";
590
+ try {
591
+ const result = await execCommand("npm", ["list", "@cortexmemory/sdk", "--json"], { quiet: true, cwd: projectPath });
592
+ const data = JSON.parse(result.stdout);
593
+ currentSdkVersion =
594
+ data.dependencies?.["@cortexmemory/sdk"]?.version ?? "not installed";
595
+ }
596
+ catch {
597
+ // Ignore errors
598
+ }
599
+ // Get latest Cortex SDK version from npm
600
+ let latestSdkVersion = "unknown";
601
+ try {
602
+ const result = await execCommand("npm", ["view", "@cortexmemory/sdk", "version"], { quiet: true });
603
+ latestSdkVersion = result.stdout.trim();
604
+ }
605
+ catch {
606
+ // Ignore errors
607
+ }
608
+ // Get current Convex version
609
+ let currentConvexVersion = "not installed";
610
+ try {
611
+ const result = await execCommand("npm", ["list", "convex", "--json"], {
612
+ quiet: true,
613
+ cwd: projectPath,
614
+ });
615
+ const data = JSON.parse(result.stdout);
616
+ currentConvexVersion =
617
+ data.dependencies?.convex?.version ?? "not installed";
618
+ }
619
+ catch {
620
+ // Ignore errors
621
+ }
622
+ // Get latest Convex version from npm
623
+ let latestConvexVersion = "unknown";
624
+ try {
625
+ const result = await execCommand("npm", ["view", "convex", "version"], {
626
+ quiet: true,
209
627
  });
628
+ latestConvexVersion = result.stdout.trim();
629
+ }
630
+ catch {
631
+ // Ignore errors
632
+ }
633
+ // Get Cortex SDK's peer dependency on Convex
634
+ let sdkConvexPeerDep = "unknown";
635
+ try {
636
+ const result = await execCommand("npm", ["view", "@cortexmemory/sdk", "peerDependencies", "--json"], { quiet: true });
637
+ const peerDeps = JSON.parse(result.stdout);
638
+ sdkConvexPeerDep = peerDeps?.convex ?? "unknown";
639
+ }
640
+ catch {
641
+ // Ignore errors
642
+ }
643
+ spinner.stop();
644
+ // Display current status
645
+ console.log();
646
+ printSection("Package Status", {
647
+ Deployment: name,
648
+ "Project Path": projectPath,
649
+ });
650
+ console.log();
651
+ console.log(pc.bold(" @cortexmemory/sdk"));
652
+ console.log(` Current: ${currentSdkVersion === latestSdkVersion ? pc.green(currentSdkVersion) : pc.yellow(currentSdkVersion)}`);
653
+ console.log(` Latest: ${latestSdkVersion}`);
654
+ console.log();
655
+ console.log(pc.bold(" convex"));
656
+ console.log(` Current: ${currentConvexVersion === latestConvexVersion ? pc.green(currentConvexVersion) : pc.yellow(currentConvexVersion)}`);
657
+ console.log(` Latest: ${latestConvexVersion}`);
658
+ if (sdkConvexPeerDep !== "unknown") {
659
+ console.log(` SDK requires: ${pc.dim(sdkConvexPeerDep)}`);
660
+ }
661
+ console.log();
662
+ // Determine what needs updating
663
+ const targetSdkVersion = options.sdkVersion ?? latestSdkVersion;
664
+ const sdkNeedsUpdate = currentSdkVersion !== targetSdkVersion &&
665
+ currentSdkVersion !== "not installed";
666
+ const sdkNeedsInstall = currentSdkVersion === "not installed";
667
+ // Check if Convex has a patch update available beyond what SDK requires
668
+ const parseVersion = (v) => {
669
+ const match = v.match(/^(\d+)\.(\d+)\.(\d+)/);
670
+ if (!match)
671
+ return null;
672
+ return {
673
+ major: parseInt(match[1]),
674
+ minor: parseInt(match[2]),
675
+ patch: parseInt(match[3]),
676
+ };
677
+ };
678
+ const currentConvex = parseVersion(currentConvexVersion);
679
+ const latestConvex = parseVersion(latestConvexVersion);
680
+ let convexPatchAvailable = false;
681
+ if (currentConvex && latestConvex) {
682
+ // Patch update = same major.minor, higher patch
683
+ convexPatchAvailable =
684
+ currentConvex.major === latestConvex.major &&
685
+ currentConvex.minor === latestConvex.minor &&
686
+ currentConvex.patch < latestConvex.patch;
687
+ }
688
+ const targetConvexVersion = options.convexVersion ??
689
+ (convexPatchAvailable ? latestConvexVersion : null);
690
+ const convexNeedsUpdate = targetConvexVersion && currentConvexVersion !== targetConvexVersion;
691
+ // Nothing to update
692
+ if (!sdkNeedsUpdate &&
693
+ !sdkNeedsInstall &&
694
+ !convexNeedsUpdate &&
695
+ !convexPatchAvailable) {
696
+ printSuccess("All packages are up to date!");
697
+ return;
698
+ }
699
+ // Update Cortex SDK if needed
700
+ if (sdkNeedsUpdate || sdkNeedsInstall) {
210
701
  console.log();
211
- console.log(pc.bold(" @cortexmemory/sdk"));
212
- console.log(` Current: ${currentSdkVersion === latestSdkVersion ? pc.green(currentSdkVersion) : pc.yellow(currentSdkVersion)}`);
213
- console.log(` Latest: ${latestSdkVersion}`);
702
+ printInfo(`${sdkNeedsInstall ? "Installing" : "Updating"} @cortexmemory/sdk@${targetSdkVersion}...`);
214
703
  console.log();
215
- console.log(pc.bold(" convex"));
216
- console.log(` Current: ${currentConvexVersion === latestConvexVersion ? pc.green(currentConvexVersion) : pc.yellow(currentConvexVersion)}`);
217
- console.log(` Latest: ${latestConvexVersion}`);
218
- if (sdkConvexPeerDep !== "unknown") {
219
- console.log(` SDK requires: ${pc.dim(sdkConvexPeerDep)}`);
704
+ const exitCode = await execCommandLive("npm", ["install", `@cortexmemory/sdk@${targetSdkVersion}`], { cwd: projectPath });
705
+ if (exitCode === 0) {
706
+ printSuccess(`${sdkNeedsInstall ? "Installed" : "Updated"} @cortexmemory/sdk to ${targetSdkVersion}`);
220
707
  }
708
+ else {
709
+ printError("SDK update failed");
710
+ throw new Error("SDK update failed");
711
+ }
712
+ }
713
+ else if (currentSdkVersion !== "not installed") {
714
+ printSuccess("@cortexmemory/sdk is already up to date");
715
+ }
716
+ // Check for Convex patch update
717
+ if (convexPatchAvailable && !options.convexVersion) {
221
718
  console.log();
222
- // Determine what needs updating
223
- const targetSdkVersion = options.sdkVersion ?? latestSdkVersion;
224
- const sdkNeedsUpdate = currentSdkVersion !== targetSdkVersion &&
225
- currentSdkVersion !== "not installed";
226
- const sdkNeedsInstall = currentSdkVersion === "not installed";
227
- // Check if Convex has a patch update available beyond what SDK requires
228
- const parseVersion = (v) => {
229
- const match = v.match(/^(\d+)\.(\d+)\.(\d+)/);
230
- if (!match)
231
- return null;
232
- return {
233
- major: parseInt(match[1]),
234
- minor: parseInt(match[2]),
235
- patch: parseInt(match[3]),
236
- };
237
- };
238
- const currentConvex = parseVersion(currentConvexVersion);
239
- const latestConvex = parseVersion(latestConvexVersion);
240
- let convexPatchAvailable = false;
241
- if (currentConvex && latestConvex) {
242
- // Patch update = same major.minor, higher patch
243
- convexPatchAvailable =
244
- currentConvex.major === latestConvex.major &&
245
- currentConvex.minor === latestConvex.minor &&
246
- currentConvex.patch < latestConvex.patch;
247
- }
248
- const targetConvexVersion = options.convexVersion ??
249
- (convexPatchAvailable ? latestConvexVersion : null);
250
- const convexNeedsUpdate = targetConvexVersion && currentConvexVersion !== targetConvexVersion;
251
- // Nothing to update
252
- if (!sdkNeedsUpdate &&
253
- !sdkNeedsInstall &&
254
- !convexNeedsUpdate &&
255
- !convexPatchAvailable) {
256
- printSuccess("All packages are up to date!");
257
- return;
719
+ console.log(pc.cyan(` Convex patch update available: ${currentConvexVersion} → ${latestConvexVersion}`));
720
+ let shouldUpdate = options.yes;
721
+ if (!shouldUpdate) {
722
+ const { default: prompts } = await import("prompts");
723
+ const response = await prompts({
724
+ type: "confirm",
725
+ name: "update",
726
+ message: "Update Convex to latest patch version?",
727
+ initial: true,
728
+ });
729
+ shouldUpdate = response.update;
258
730
  }
259
- // Update Cortex SDK if needed
260
- if (sdkNeedsUpdate || sdkNeedsInstall) {
731
+ if (shouldUpdate) {
261
732
  console.log();
262
- printInfo(`${sdkNeedsInstall ? "Installing" : "Updating"} @cortexmemory/sdk@${targetSdkVersion}...`);
733
+ printInfo(`Updating convex@${latestConvexVersion}...`);
263
734
  console.log();
264
- const exitCode = await execCommandLive("npm", ["install", `@cortexmemory/sdk@${targetSdkVersion}`], { cwd: projectPath });
735
+ const exitCode = await execCommandLive("npm", ["install", `convex@${latestConvexVersion}`], { cwd: projectPath });
265
736
  if (exitCode === 0) {
266
- printSuccess(`${sdkNeedsInstall ? "Installed" : "Updated"} @cortexmemory/sdk to ${targetSdkVersion}`);
737
+ printSuccess(`Updated convex to ${latestConvexVersion}`);
267
738
  }
268
739
  else {
269
- printError("SDK update failed");
270
- process.exit(1);
740
+ printWarning("Convex update failed, but SDK update was successful");
271
741
  }
272
742
  }
273
- else if (currentSdkVersion !== "not installed") {
274
- printSuccess("@cortexmemory/sdk is already up to date");
743
+ else {
744
+ console.log(pc.dim(" Skipping Convex update"));
275
745
  }
276
- // Check for Convex patch update
277
- if (convexPatchAvailable && !options.convexVersion) {
278
- console.log();
279
- console.log(pc.cyan(` Convex patch update available: ${currentConvexVersion} → ${latestConvexVersion}`));
280
- let shouldUpdate = options.yes;
281
- if (!shouldUpdate) {
282
- const { default: prompts } = await import("prompts");
283
- const response = await prompts({
284
- type: "confirm",
285
- name: "update",
286
- message: "Update Convex to latest patch version?",
287
- initial: true,
288
- });
289
- shouldUpdate = response.update;
290
- }
291
- if (shouldUpdate) {
292
- console.log();
293
- printInfo(`Updating convex@${latestConvexVersion}...`);
294
- console.log();
295
- const exitCode = await execCommandLive("npm", ["install", `convex@${latestConvexVersion}`], { cwd: projectPath });
296
- if (exitCode === 0) {
297
- printSuccess(`Updated convex to ${latestConvexVersion}`);
298
- }
299
- else {
300
- printWarning("Convex update failed, but SDK update was successful");
301
- }
746
+ }
747
+ else if (options.convexVersion) {
748
+ // Explicit version requested
749
+ console.log();
750
+ printInfo(`Updating convex@${options.convexVersion}...`);
751
+ console.log();
752
+ const exitCode = await execCommandLive("npm", ["install", `convex@${options.convexVersion}`], { cwd: projectPath });
753
+ if (exitCode === 0) {
754
+ printSuccess(`Updated convex to ${options.convexVersion}`);
755
+ }
756
+ else {
757
+ printWarning("Convex update failed");
758
+ }
759
+ }
760
+ console.log();
761
+ printSuccess("Update complete!");
762
+ }
763
+ catch (error) {
764
+ spinner.stop();
765
+ throw error;
766
+ }
767
+ }
768
+ /**
769
+ * Update packages for a single app
770
+ */
771
+ async function updateApp(name, app, options) {
772
+ const appPath = path.join(app.projectPath, app.path);
773
+ const isDevMode = !!options.devPath;
774
+ if (!await fs.pathExists(appPath)) {
775
+ printError(`App path not found: ${appPath}`);
776
+ throw new Error(`App path not found: ${appPath}`);
777
+ }
778
+ const spinner = ora("Checking for updates...").start();
779
+ try {
780
+ // Read package.json
781
+ const packageJsonPath = path.join(appPath, "package.json");
782
+ if (!await fs.pathExists(packageJsonPath)) {
783
+ spinner.stop();
784
+ printError(`No package.json found at ${appPath}`);
785
+ throw new Error(`No package.json found at ${appPath}`);
786
+ }
787
+ const pkg = await fs.readJson(packageJsonPath);
788
+ // Check current versions
789
+ let currentSdkVersion = "not installed";
790
+ let currentProviderVersion = "not installed";
791
+ let currentConvexVersion = "not installed";
792
+ let currentAiVersion = "not installed";
793
+ let isDevLinked = false;
794
+ // Check if already dev-linked
795
+ const sdkDep = pkg.dependencies?.["@cortexmemory/sdk"];
796
+ const providerDep = pkg.dependencies?.["@cortexmemory/vercel-ai-provider"];
797
+ isDevLinked = sdkDep?.startsWith("file:") || providerDep?.startsWith("file:");
798
+ // Get installed versions
799
+ try {
800
+ const result = await execCommand("npm", ["list", "@cortexmemory/sdk", "@cortexmemory/vercel-ai-provider", "convex", "ai", "--json"], { quiet: true, cwd: appPath });
801
+ const data = JSON.parse(result.stdout);
802
+ currentSdkVersion =
803
+ data.dependencies?.["@cortexmemory/sdk"]?.version ?? "not installed";
804
+ currentProviderVersion =
805
+ data.dependencies?.["@cortexmemory/vercel-ai-provider"]?.version ?? "not installed";
806
+ currentConvexVersion =
807
+ data.dependencies?.convex?.version ?? "not installed";
808
+ currentAiVersion =
809
+ data.dependencies?.ai?.version ?? "not installed";
810
+ }
811
+ catch {
812
+ // Ignore errors
813
+ }
814
+ // Get latest versions - from local source in dev mode, from npm otherwise
815
+ let latestSdkVersion = "unknown";
816
+ let latestProviderVersion = "unknown";
817
+ let latestConvexVersion = "unknown";
818
+ let latestAiVersion = "unknown";
819
+ if (isDevMode && options.devPath) {
820
+ // In dev mode, read versions from local source package.json files
821
+ try {
822
+ const sdkPkgPath = path.join(options.devPath, "package.json");
823
+ const providerPkgPath = path.join(options.devPath, "packages", "vercel-ai-provider", "package.json");
824
+ if (await fs.pathExists(sdkPkgPath)) {
825
+ const sdkPkg = await fs.readJson(sdkPkgPath);
826
+ latestSdkVersion = sdkPkg.version || "unknown";
302
827
  }
303
- else {
304
- console.log(pc.dim(" Skipping Convex update"));
828
+ if (await fs.pathExists(providerPkgPath)) {
829
+ const providerPkg = await fs.readJson(providerPkgPath);
830
+ latestProviderVersion = providerPkg.version || "unknown";
305
831
  }
832
+ // Still fetch convex and ai versions from npm (external dependencies)
833
+ const [convexResult, aiResult] = await Promise.all([
834
+ execCommand("npm", ["view", "convex", "version"], { quiet: true }).catch(() => ({ stdout: "unknown" })),
835
+ execCommand("npm", ["view", "ai", "version"], { quiet: true }).catch(() => ({ stdout: "unknown" })),
836
+ ]);
837
+ latestConvexVersion = convexResult.stdout.trim() || "unknown";
838
+ latestAiVersion = aiResult.stdout.trim() || "unknown";
839
+ }
840
+ catch {
841
+ // Ignore errors, versions will remain "unknown"
842
+ }
843
+ }
844
+ else {
845
+ // Normal mode: fetch all versions from npm
846
+ try {
847
+ const [sdkResult, providerResult, convexResult, aiResult] = await Promise.all([
848
+ execCommand("npm", ["view", "@cortexmemory/sdk", "version"], { quiet: true }).catch(() => ({ stdout: "unknown" })),
849
+ execCommand("npm", ["view", "@cortexmemory/vercel-ai-provider", "version"], { quiet: true }).catch(() => ({ stdout: "unknown" })),
850
+ execCommand("npm", ["view", "convex", "version"], { quiet: true }).catch(() => ({ stdout: "unknown" })),
851
+ execCommand("npm", ["view", "ai", "version"], { quiet: true }).catch(() => ({ stdout: "unknown" })),
852
+ ]);
853
+ latestSdkVersion = sdkResult.stdout.trim() || "unknown";
854
+ latestProviderVersion = providerResult.stdout.trim() || "unknown";
855
+ latestConvexVersion = convexResult.stdout.trim() || "unknown";
856
+ latestAiVersion = aiResult.stdout.trim() || "unknown";
857
+ }
858
+ catch {
859
+ // Ignore errors
860
+ }
861
+ }
862
+ spinner.stop();
863
+ // Display current status
864
+ console.log();
865
+ printSection("App Package Status", {
866
+ App: name,
867
+ Type: app.type,
868
+ Path: appPath,
869
+ });
870
+ if (isDevMode) {
871
+ console.log();
872
+ console.log(pc.magenta(" ═══ DEV MODE ═══"));
873
+ console.log(pc.dim(` Will link to: ${options.devPath}`));
874
+ }
875
+ // Use "Source" label in dev mode to indicate local package.json version
876
+ const cortexVersionLabel = isDevMode ? "Source" : "Latest";
877
+ console.log();
878
+ console.log(pc.bold(" @cortexmemory/sdk"));
879
+ if (isDevLinked) {
880
+ console.log(` Current: ${pc.magenta("file:... (dev linked)")}`);
881
+ }
882
+ else {
883
+ console.log(` Current: ${currentSdkVersion === latestSdkVersion ? pc.green(currentSdkVersion) : pc.yellow(currentSdkVersion)}`);
884
+ }
885
+ console.log(` ${cortexVersionLabel}: ${latestSdkVersion}`);
886
+ console.log();
887
+ console.log(pc.bold(" @cortexmemory/vercel-ai-provider"));
888
+ if (isDevLinked) {
889
+ console.log(` Current: ${pc.magenta("file:... (dev linked)")}`);
890
+ }
891
+ else {
892
+ console.log(` Current: ${currentProviderVersion === latestProviderVersion ? pc.green(currentProviderVersion) : pc.yellow(currentProviderVersion)}`);
893
+ }
894
+ console.log(` ${cortexVersionLabel}: ${latestProviderVersion}`);
895
+ console.log();
896
+ console.log(pc.bold(" convex"));
897
+ console.log(` Current: ${currentConvexVersion === latestConvexVersion ? pc.green(currentConvexVersion) : pc.yellow(currentConvexVersion)}`);
898
+ console.log(` Latest: ${latestConvexVersion}`);
899
+ console.log();
900
+ console.log(pc.bold(" ai (Vercel AI SDK)"));
901
+ console.log(` Current: ${currentAiVersion === latestAiVersion ? pc.green(currentAiVersion) : pc.yellow(currentAiVersion)}`);
902
+ console.log(` Latest: ${latestAiVersion}`);
903
+ console.log();
904
+ // Determine update strategy
905
+ if (isDevMode) {
906
+ // Dev mode: update package.json with file: references
907
+ if (isDevLinked) {
908
+ printSuccess("App is already dev-linked. Running npm install to refresh...");
909
+ }
910
+ else {
911
+ printInfo("Switching to dev mode with local SDK...");
912
+ }
913
+ // Update package.json with file: references
914
+ const devSdkPath = options.devPath;
915
+ const devProviderPath = path.join(devSdkPath, "packages", "vercel-ai-provider");
916
+ pkg.dependencies = pkg.dependencies || {};
917
+ pkg.dependencies["@cortexmemory/sdk"] = `file:${devSdkPath}`;
918
+ pkg.dependencies["@cortexmemory/vercel-ai-provider"] = `file:${devProviderPath}`;
919
+ await fs.writeJson(packageJsonPath, pkg, { spaces: 2 });
920
+ console.log(pc.cyan(" Updated package.json with file: references"));
921
+ // Run npm install
922
+ console.log();
923
+ printInfo("Running npm install...");
924
+ console.log();
925
+ const exitCode = await execCommandLive("npm", ["install", "--legacy-peer-deps"], { cwd: appPath });
926
+ if (exitCode === 0) {
927
+ console.log();
928
+ printSuccess("Dev mode linking complete!");
929
+ console.log(pc.dim(` SDK linked to: ${devSdkPath}`));
930
+ console.log(pc.dim(` Provider linked to: ${devProviderPath}`));
931
+ }
932
+ else {
933
+ printError("npm install failed");
934
+ throw new Error("npm install failed");
306
935
  }
307
- else if (options.convexVersion) {
308
- // Explicit version requested
936
+ }
937
+ else {
938
+ // Normal mode: update to latest versions from npm
939
+ const targetSdkVersion = options.sdkVersion ?? latestSdkVersion;
940
+ const targetProviderVersion = options.providerVersion ?? latestProviderVersion;
941
+ // Check if we need to remove dev links first
942
+ if (isDevLinked) {
943
+ printInfo("Removing dev links and switching to npm packages...");
944
+ pkg.dependencies["@cortexmemory/sdk"] = `^${targetSdkVersion}`;
945
+ pkg.dependencies["@cortexmemory/vercel-ai-provider"] = `^${targetProviderVersion}`;
946
+ await fs.writeJson(packageJsonPath, pkg, { spaces: 2 });
947
+ console.log(pc.cyan(" Updated package.json with npm versions"));
948
+ }
949
+ // Determine what needs updating
950
+ const sdkNeedsUpdate = currentSdkVersion !== targetSdkVersion || isDevLinked;
951
+ const providerNeedsUpdate = currentProviderVersion !== targetProviderVersion || isDevLinked;
952
+ // Nothing to update
953
+ if (!sdkNeedsUpdate && !providerNeedsUpdate) {
954
+ printSuccess("All packages are up to date!");
955
+ return;
956
+ }
957
+ // Build install command
958
+ const packagesToInstall = [];
959
+ if (sdkNeedsUpdate) {
960
+ packagesToInstall.push(`@cortexmemory/sdk@${targetSdkVersion}`);
961
+ }
962
+ if (providerNeedsUpdate) {
963
+ packagesToInstall.push(`@cortexmemory/vercel-ai-provider@${targetProviderVersion}`);
964
+ }
965
+ if (packagesToInstall.length > 0) {
309
966
  console.log();
310
- printInfo(`Updating convex@${options.convexVersion}...`);
967
+ printInfo(`Installing: ${packagesToInstall.join(", ")}...`);
311
968
  console.log();
312
- const exitCode = await execCommandLive("npm", ["install", `convex@${options.convexVersion}`], { cwd: projectPath });
969
+ const exitCode = await execCommandLive("npm", ["install", ...packagesToInstall, "--legacy-peer-deps"], { cwd: appPath });
313
970
  if (exitCode === 0) {
314
- printSuccess(`Updated convex to ${options.convexVersion}`);
971
+ printSuccess("Packages updated successfully");
315
972
  }
316
973
  else {
317
- printWarning("Convex update failed");
974
+ printError("Package update failed");
975
+ throw new Error("Package update failed");
318
976
  }
319
977
  }
320
978
  console.log();
321
- printSuccess("Update complete!");
979
+ printSuccess("Package update complete!");
322
980
  }
323
- catch (error) {
324
- spinner.stop();
325
- printError(error instanceof Error ? error.message : "Update failed");
326
- process.exit(1);
981
+ // Template sync (if enabled)
982
+ if (options.syncTemplate) {
983
+ console.log();
984
+ printSection("Template Sync", {});
985
+ console.log();
986
+ try {
987
+ const templateResult = await syncAppTemplate(app, { dryRun: false });
988
+ if (templateResult.error) {
989
+ printWarning(`Template sync skipped: ${templateResult.error}`);
990
+ }
991
+ else if (templateResult.synced) {
992
+ printTemplateSyncResult(templateResult);
993
+ // Run npm install if package.json was updated with new dependencies
994
+ if (templateResult.packageJsonUpdated) {
995
+ const totalNewDeps = templateResult.depsAdded.length + templateResult.devDepsAdded.length;
996
+ if (totalNewDeps > 0) {
997
+ console.log();
998
+ printInfo(`Installing ${totalNewDeps} new dependencies...`);
999
+ console.log(pc.dim(` Running in: ${templateResult.appPath}`));
1000
+ console.log();
1001
+ const exitCode = await execCommandLive("npm", ["install", "--legacy-peer-deps"], { cwd: templateResult.appPath });
1002
+ if (exitCode === 0) {
1003
+ printSuccess("Dependencies installed");
1004
+ }
1005
+ else {
1006
+ printWarning("npm install failed - you may need to run it manually");
1007
+ }
1008
+ }
1009
+ }
1010
+ }
1011
+ else {
1012
+ console.log(pc.dim(" Template files are up to date"));
1013
+ }
1014
+ }
1015
+ catch (error) {
1016
+ const message = error instanceof Error ? error.message : String(error);
1017
+ printWarning(`Template sync failed: ${message}`);
1018
+ }
327
1019
  }
328
- });
1020
+ console.log();
1021
+ printSuccess("Update complete!");
1022
+ }
1023
+ catch (error) {
1024
+ spinner.stop();
1025
+ throw error;
1026
+ }
329
1027
  }
330
1028
  //# sourceMappingURL=deploy.js.map