@cortexmemory/cli 0.26.2 → 0.27.3

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 (90) 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 +771 -144
  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 +210 -36
  9. package/dist/commands/dev.js.map +1 -1
  10. package/dist/commands/init.d.ts.map +1 -1
  11. package/dist/commands/init.js +273 -43
  12. package/dist/commands/init.js.map +1 -1
  13. package/dist/commands/setup.d.ts.map +1 -1
  14. package/dist/commands/setup.js +102 -46
  15. package/dist/commands/setup.js.map +1 -1
  16. package/dist/commands/status.d.ts.map +1 -1
  17. package/dist/commands/status.js +94 -7
  18. package/dist/commands/status.js.map +1 -1
  19. package/dist/index.js +1 -1
  20. package/dist/types.d.ts +23 -0
  21. package/dist/types.d.ts.map +1 -1
  22. package/dist/utils/app-template-sync.d.ts +95 -0
  23. package/dist/utils/app-template-sync.d.ts.map +1 -0
  24. package/dist/utils/app-template-sync.js +425 -0
  25. package/dist/utils/app-template-sync.js.map +1 -0
  26. package/dist/utils/config.d.ts +11 -0
  27. package/dist/utils/config.d.ts.map +1 -1
  28. package/dist/utils/config.js +20 -0
  29. package/dist/utils/config.js.map +1 -1
  30. package/dist/utils/deployment-selector.d.ts +21 -0
  31. package/dist/utils/deployment-selector.d.ts.map +1 -1
  32. package/dist/utils/deployment-selector.js +32 -0
  33. package/dist/utils/deployment-selector.js.map +1 -1
  34. package/dist/utils/init/graph-setup.d.ts.map +1 -1
  35. package/dist/utils/init/graph-setup.js +25 -2
  36. package/dist/utils/init/graph-setup.js.map +1 -1
  37. package/dist/utils/init/quickstart-setup.d.ts +87 -0
  38. package/dist/utils/init/quickstart-setup.d.ts.map +1 -0
  39. package/dist/utils/init/quickstart-setup.js +462 -0
  40. package/dist/utils/init/quickstart-setup.js.map +1 -0
  41. package/dist/utils/schema-sync.d.ts.map +1 -1
  42. package/dist/utils/schema-sync.js +27 -21
  43. package/dist/utils/schema-sync.js.map +1 -1
  44. package/package.json +3 -2
  45. package/templates/vercel-ai-quickstart/.env.local.example +45 -0
  46. package/templates/vercel-ai-quickstart/README.md +280 -0
  47. package/templates/vercel-ai-quickstart/app/api/auth/check/route.ts +30 -0
  48. package/templates/vercel-ai-quickstart/app/api/auth/login/route.ts +83 -0
  49. package/templates/vercel-ai-quickstart/app/api/auth/register/route.ts +94 -0
  50. package/templates/vercel-ai-quickstart/app/api/auth/setup/route.ts +59 -0
  51. package/templates/vercel-ai-quickstart/app/api/chat/route.ts +277 -0
  52. package/templates/vercel-ai-quickstart/app/api/conversations/route.ts +179 -0
  53. package/templates/vercel-ai-quickstart/app/api/facts/route.ts +39 -0
  54. package/templates/vercel-ai-quickstart/app/api/health/route.ts +99 -0
  55. package/templates/vercel-ai-quickstart/app/api/memories/route.ts +37 -0
  56. package/templates/vercel-ai-quickstart/app/globals.css +275 -0
  57. package/templates/vercel-ai-quickstart/app/layout.tsx +19 -0
  58. package/templates/vercel-ai-quickstart/app/page.tsx +216 -0
  59. package/templates/vercel-ai-quickstart/components/AdminSetup.tsx +139 -0
  60. package/templates/vercel-ai-quickstart/components/AuthProvider.tsx +283 -0
  61. package/templates/vercel-ai-quickstart/components/ChatHistorySidebar.tsx +323 -0
  62. package/templates/vercel-ai-quickstart/components/ChatInterface.tsx +334 -0
  63. package/templates/vercel-ai-quickstart/components/ConvexClientProvider.tsx +21 -0
  64. package/templates/vercel-ai-quickstart/components/DataPreview.tsx +57 -0
  65. package/templates/vercel-ai-quickstart/components/HealthStatus.tsx +214 -0
  66. package/templates/vercel-ai-quickstart/components/LayerCard.tsx +263 -0
  67. package/templates/vercel-ai-quickstart/components/LayerFlowDiagram.tsx +195 -0
  68. package/templates/vercel-ai-quickstart/components/LoginScreen.tsx +202 -0
  69. package/templates/vercel-ai-quickstart/components/MemorySpaceSwitcher.tsx +93 -0
  70. package/templates/vercel-ai-quickstart/convex/conversations.ts +67 -0
  71. package/templates/vercel-ai-quickstart/convex/facts.ts +131 -0
  72. package/templates/vercel-ai-quickstart/convex/health.ts +15 -0
  73. package/templates/vercel-ai-quickstart/convex/memories.ts +104 -0
  74. package/templates/vercel-ai-quickstart/convex/schema.ts +20 -0
  75. package/templates/vercel-ai-quickstart/convex/users.ts +105 -0
  76. package/templates/vercel-ai-quickstart/jest.config.js +45 -0
  77. package/templates/vercel-ai-quickstart/lib/animations.ts +146 -0
  78. package/templates/vercel-ai-quickstart/lib/cortex.ts +27 -0
  79. package/templates/vercel-ai-quickstart/lib/layer-tracking.ts +214 -0
  80. package/templates/vercel-ai-quickstart/lib/password.ts +120 -0
  81. package/templates/vercel-ai-quickstart/next.config.js +27 -0
  82. package/templates/vercel-ai-quickstart/package.json +46 -0
  83. package/templates/vercel-ai-quickstart/postcss.config.js +5 -0
  84. package/templates/vercel-ai-quickstart/tailwind.config.js +37 -0
  85. package/templates/vercel-ai-quickstart/tests/helpers/mock-cortex.ts +263 -0
  86. package/templates/vercel-ai-quickstart/tests/helpers/setup.ts +48 -0
  87. package/templates/vercel-ai-quickstart/tests/integration/auth.test.ts +455 -0
  88. package/templates/vercel-ai-quickstart/tests/integration/conversations.test.ts +461 -0
  89. package/templates/vercel-ai-quickstart/tests/unit/password.test.ts +228 -0
  90. package/templates/vercel-ai-quickstart/tsconfig.json +33 -0
@@ -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,819 @@ 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 once (shared across all targets)
236
+ let latestSdkVersion = "unknown";
237
+ let latestConvexVersion = "unknown";
238
+ let latestProviderVersion = "unknown";
239
+ let latestAiVersion = "unknown";
240
+ let sdkConvexPeerDep = "unknown";
241
+ try {
242
+ const [sdkResult, convexResult, providerResult, aiResult, peerDepResult] = await Promise.all([
243
+ execCommand("npm", ["view", "@cortexmemory/sdk", "version"], {
244
+ quiet: true,
245
+ }).catch(() => ({ stdout: "unknown" })),
246
+ execCommand("npm", ["view", "convex", "version"], {
247
+ quiet: true,
248
+ }).catch(() => ({ stdout: "unknown" })),
249
+ execCommand("npm", ["view", "@cortexmemory/vercel-ai-provider", "version"], {
250
+ quiet: true,
251
+ }).catch(() => ({ stdout: "unknown" })),
252
+ execCommand("npm", ["view", "ai", "version"], {
253
+ quiet: true,
254
+ }).catch(() => ({ stdout: "unknown" })),
255
+ execCommand("npm", ["view", "@cortexmemory/sdk", "peerDependencies", "--json"], { quiet: true }).catch(() => ({ stdout: "{}" })),
256
+ ]);
257
+ latestSdkVersion = sdkResult.stdout.trim() || "unknown";
258
+ latestConvexVersion = convexResult.stdout.trim() || "unknown";
259
+ latestProviderVersion = providerResult.stdout.trim() || "unknown";
260
+ latestAiVersion = aiResult.stdout.trim() || "unknown";
176
261
  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";
262
+ const peerDeps = JSON.parse(peerDepResult.stdout);
263
+ sdkConvexPeerDep = peerDeps?.convex ?? "unknown";
181
264
  }
182
265
  catch {
183
- // Ignore errors
266
+ // Ignore parse errors
267
+ }
268
+ }
269
+ catch {
270
+ // Ignore errors
271
+ }
272
+ const deploymentInfos = [];
273
+ const appInfos = [];
274
+ // Check deployments
275
+ if (updateDeployments && hasDeployments) {
276
+ for (const { name, deployment, projectPath } of enabledDeployments) {
277
+ let currentSdkVersion = "not installed";
278
+ let currentConvexVersion = "not installed";
279
+ try {
280
+ const result = await execCommand("npm", ["list", "@cortexmemory/sdk", "--json"], { quiet: true, cwd: projectPath });
281
+ const data = JSON.parse(result.stdout);
282
+ currentSdkVersion =
283
+ data.dependencies?.["@cortexmemory/sdk"]?.version ??
284
+ "not installed";
285
+ }
286
+ catch {
287
+ // Ignore errors
288
+ }
289
+ try {
290
+ const result = await execCommand("npm", ["list", "convex", "--json"], {
291
+ quiet: true,
292
+ cwd: projectPath,
293
+ });
294
+ const data = JSON.parse(result.stdout);
295
+ currentConvexVersion =
296
+ data.dependencies?.convex?.version ?? "not installed";
297
+ }
298
+ catch {
299
+ // Ignore errors
300
+ }
301
+ const targetSdkVersion = options.sdkVersion ?? latestSdkVersion;
302
+ const needsUpdate = currentSdkVersion !== targetSdkVersion ||
303
+ currentSdkVersion === "not installed";
304
+ deploymentInfos.push({
305
+ name,
306
+ deployment,
307
+ projectPath,
308
+ currentSdkVersion,
309
+ currentConvexVersion,
310
+ needsUpdate,
311
+ });
312
+ }
313
+ }
314
+ // Check apps
315
+ if (updateApps && hasApps) {
316
+ for (const { name, app } of enabledApps) {
317
+ const appPath = path.join(app.projectPath, app.path);
318
+ let currentSdkVersion = "not installed";
319
+ let currentProviderVersion = "not installed";
320
+ let currentConvexVersion = "not installed";
321
+ let currentAiVersion = "not installed";
322
+ let isDevLinked = false;
323
+ // Check package.json for file: references (dev linked)
324
+ try {
325
+ const packageJsonPath = path.join(appPath, "package.json");
326
+ if (await fs.pathExists(packageJsonPath)) {
327
+ const pkg = await fs.readJson(packageJsonPath);
328
+ const sdkDep = pkg.dependencies?.["@cortexmemory/sdk"];
329
+ const providerDep = pkg.dependencies?.["@cortexmemory/vercel-ai-provider"];
330
+ isDevLinked = sdkDep?.startsWith("file:") || providerDep?.startsWith("file:");
331
+ }
332
+ }
333
+ catch {
334
+ // Ignore errors
335
+ }
336
+ // Get installed versions
337
+ try {
338
+ const result = await execCommand("npm", ["list", "@cortexmemory/sdk", "@cortexmemory/vercel-ai-provider", "convex", "ai", "--json"], { quiet: true, cwd: appPath });
339
+ const data = JSON.parse(result.stdout);
340
+ currentSdkVersion =
341
+ data.dependencies?.["@cortexmemory/sdk"]?.version ?? "not installed";
342
+ currentProviderVersion =
343
+ data.dependencies?.["@cortexmemory/vercel-ai-provider"]?.version ?? "not installed";
344
+ currentConvexVersion =
345
+ data.dependencies?.convex?.version ?? "not installed";
346
+ currentAiVersion =
347
+ data.dependencies?.ai?.version ?? "not installed";
348
+ }
349
+ catch {
350
+ // Ignore errors
351
+ }
352
+ const targetSdkVersion = isDevMode ? "dev" : (options.sdkVersion ?? latestSdkVersion);
353
+ const needsUpdate = isDevMode
354
+ ? !isDevLinked // Dev mode: needs update if not already dev-linked
355
+ : (currentSdkVersion !== targetSdkVersion || currentSdkVersion === "not installed");
356
+ // Check template sync status if --sync-template is enabled
357
+ let templateFilesToUpdate = 0;
358
+ let templateFilesToAdd = 0;
359
+ let needsTemplateSync = false;
360
+ if (options.syncTemplate) {
361
+ try {
362
+ const templateStatus = await checkTemplateSync(app);
363
+ templateFilesToUpdate = templateStatus.filesOutdated.length;
364
+ templateFilesToAdd = templateStatus.filesMissing.length;
365
+ needsTemplateSync = templateStatus.needsSync;
366
+ }
367
+ catch {
368
+ // Ignore errors
369
+ }
370
+ }
371
+ appInfos.push({
372
+ name,
373
+ app,
374
+ appPath,
375
+ currentSdkVersion,
376
+ currentProviderVersion,
377
+ currentConvexVersion,
378
+ currentAiVersion,
379
+ needsUpdate,
380
+ isDevLinked,
381
+ templateFilesToUpdate,
382
+ templateFilesToAdd,
383
+ needsTemplateSync,
384
+ });
385
+ }
386
+ }
387
+ spinner.stop();
388
+ // Display status dashboard
389
+ if (isDevMode) {
390
+ console.log(pc.magenta(" ═══ DEV MODE ═══"));
391
+ console.log(pc.dim(` SDK path: ${devPath}`));
392
+ console.log();
393
+ }
394
+ console.log(pc.bold(" Latest versions:"));
395
+ console.log(` @cortexmemory/sdk: ${pc.cyan(latestSdkVersion)}`);
396
+ console.log(` @cortexmemory/vercel-ai-provider: ${pc.cyan(latestProviderVersion)}`);
397
+ console.log(` convex: ${pc.cyan(latestConvexVersion)}`);
398
+ console.log(` ai: ${pc.cyan(latestAiVersion)}`);
399
+ if (sdkConvexPeerDep !== "unknown") {
400
+ console.log(` SDK requires convex: ${pc.dim(sdkConvexPeerDep)}`);
401
+ }
402
+ console.log();
403
+ // Show deployment status
404
+ if (deploymentInfos.length > 0) {
405
+ printSection("Deployments", {});
406
+ console.log();
407
+ for (const info of deploymentInfos) {
408
+ const isDefault = info.name === currentConfig.default;
409
+ const defaultBadge = isDefault ? pc.cyan(" (default)") : "";
410
+ const statusIcon = info.needsUpdate
411
+ ? pc.yellow("●")
412
+ : pc.green("●");
413
+ console.log(` ${statusIcon} ${pc.bold(info.name)}${defaultBadge}`);
414
+ console.log(pc.dim(` Path: ${info.projectPath}`));
415
+ console.log(` SDK: ${info.currentSdkVersion === latestSdkVersion ? pc.green(info.currentSdkVersion) : pc.yellow(info.currentSdkVersion)}`);
416
+ console.log(` Convex: ${info.currentConvexVersion === latestConvexVersion ? pc.green(info.currentConvexVersion) : pc.yellow(info.currentConvexVersion)}`);
417
+ console.log();
184
418
  }
185
- // Get latest Convex version from npm
186
- let latestConvexVersion = "unknown";
419
+ }
420
+ // Show app status
421
+ if (appInfos.length > 0) {
422
+ printSection("Apps", {});
423
+ console.log();
424
+ for (const info of appInfos) {
425
+ const devBadge = info.isDevLinked ? pc.magenta(" [DEV]") : "";
426
+ const needsAnyUpdate = info.needsUpdate || info.needsTemplateSync;
427
+ const statusIcon = needsAnyUpdate
428
+ ? pc.yellow("●")
429
+ : pc.green("●");
430
+ console.log(` ${statusIcon} ${pc.bold(info.name)}${devBadge}`);
431
+ console.log(pc.dim(` Path: ${info.appPath}`));
432
+ console.log(` SDK: ${info.isDevLinked ? pc.magenta("file:...") : (info.currentSdkVersion === latestSdkVersion ? pc.green(info.currentSdkVersion) : pc.yellow(info.currentSdkVersion))}`);
433
+ console.log(` Provider: ${info.isDevLinked ? pc.magenta("file:...") : (info.currentProviderVersion === latestProviderVersion ? pc.green(info.currentProviderVersion) : pc.yellow(info.currentProviderVersion))}`);
434
+ console.log(` AI: ${info.currentAiVersion === latestAiVersion ? pc.green(info.currentAiVersion) : pc.yellow(info.currentAiVersion)}`);
435
+ console.log(` Convex: ${info.currentConvexVersion === latestConvexVersion ? pc.green(info.currentConvexVersion) : pc.yellow(info.currentConvexVersion)}`);
436
+ // Show template sync status if --sync-template is enabled
437
+ if (options.syncTemplate) {
438
+ const totalTemplateChanges = info.templateFilesToUpdate + info.templateFilesToAdd;
439
+ if (totalTemplateChanges > 0) {
440
+ console.log(` Template: ${pc.yellow(`${totalTemplateChanges} file(s) to sync`)}`);
441
+ }
442
+ else {
443
+ console.log(` Template: ${pc.green("up to date")}`);
444
+ }
445
+ }
446
+ console.log();
447
+ }
448
+ }
449
+ // Count updates needed
450
+ const deploymentsNeedingUpdate = deploymentInfos.filter((d) => d.needsUpdate);
451
+ const appsNeedingUpdate = appInfos.filter((a) => a.needsUpdate || (options.syncTemplate && a.needsTemplateSync));
452
+ const totalNeedingUpdate = deploymentsNeedingUpdate.length + appsNeedingUpdate.length;
453
+ // Check if any updates needed
454
+ if (totalNeedingUpdate === 0) {
455
+ printSuccess("Everything is up to date!");
456
+ return;
457
+ }
458
+ // Prompt for confirmation
459
+ const updateParts = [];
460
+ if (deploymentsNeedingUpdate.length > 0) {
461
+ updateParts.push(`${deploymentsNeedingUpdate.length} deployment(s)`);
462
+ }
463
+ if (appsNeedingUpdate.length > 0) {
464
+ updateParts.push(`${appsNeedingUpdate.length} app(s)`);
465
+ }
466
+ console.log(pc.cyan(` ${updateParts.join(" and ")} need updates`));
467
+ console.log();
468
+ let shouldProceed = options.yes;
469
+ if (!shouldProceed) {
470
+ const { default: prompts } = await import("prompts");
471
+ const response = await prompts({
472
+ type: "confirm",
473
+ name: "proceed",
474
+ message: `Update all ${totalNeedingUpdate} target(s)?`,
475
+ initial: true,
476
+ });
477
+ shouldProceed = response.proceed;
478
+ }
479
+ if (!shouldProceed) {
480
+ console.log(pc.yellow("\n Operation cancelled\n"));
481
+ console.log(pc.dim(" Tip: Use '-d <name>' for deployments or '-a <name>' for apps\n"));
482
+ return;
483
+ }
484
+ // Perform updates
485
+ console.log();
486
+ let deploymentSuccessCount = 0;
487
+ let deploymentFailCount = 0;
488
+ let appSuccessCount = 0;
489
+ let appFailCount = 0;
490
+ // Update deployments
491
+ for (const info of deploymentsNeedingUpdate) {
492
+ console.log(pc.bold(`\n━━━ Updating deployment: ${info.name} ━━━\n`));
187
493
  try {
188
- const result = await execCommand("npm", ["view", "convex", "version"], { quiet: true });
189
- latestConvexVersion = result.stdout.trim();
494
+ await updateDeployment(info.name, info.deployment, {
495
+ ...options,
496
+ yes: true,
497
+ });
498
+ deploymentSuccessCount++;
190
499
  }
191
- catch {
192
- // Ignore errors
500
+ catch (error) {
501
+ printError(`Failed to update ${info.name}: ${error instanceof Error ? error.message : "Unknown error"}`);
502
+ deploymentFailCount++;
193
503
  }
194
- // Get Cortex SDK's peer dependency on Convex
195
- let sdkConvexPeerDep = "unknown";
504
+ }
505
+ // Update apps
506
+ for (const info of appsNeedingUpdate) {
507
+ console.log(pc.bold(`\n━━━ Updating app: ${info.name} ━━━\n`));
196
508
  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";
509
+ await updateApp(info.name, info.app, {
510
+ ...options,
511
+ devPath: isDevMode ? devPath : undefined,
512
+ syncTemplate: options.syncTemplate,
513
+ yes: true,
514
+ });
515
+ appSuccessCount++;
200
516
  }
201
- catch {
202
- // Ignore errors
517
+ catch (error) {
518
+ printError(`Failed to update ${info.name}: ${error instanceof Error ? error.message : "Unknown error"}`);
519
+ appFailCount++;
203
520
  }
204
- spinner.stop();
205
- // Display current status
206
- console.log();
207
- printSection("Package Status", {
208
- "Project Path": projectPath,
521
+ }
522
+ // Summary
523
+ console.log();
524
+ console.log(pc.bold("━━━ Summary ━━━"));
525
+ console.log();
526
+ if (deploymentSuccessCount > 0) {
527
+ printSuccess(`${deploymentSuccessCount} deployment(s) updated successfully`);
528
+ }
529
+ if (deploymentFailCount > 0) {
530
+ printWarning(`${deploymentFailCount} deployment(s) failed to update`);
531
+ }
532
+ if (appSuccessCount > 0) {
533
+ printSuccess(`${appSuccessCount} app(s) updated successfully`);
534
+ }
535
+ if (appFailCount > 0) {
536
+ printWarning(`${appFailCount} app(s) failed to update`);
537
+ }
538
+ });
539
+ }
540
+ /**
541
+ * Update packages for a single deployment
542
+ */
543
+ async function updateDeployment(name, deployment, options) {
544
+ const projectPath = deployment.projectPath || process.cwd();
545
+ const spinner = ora("Checking for updates...").start();
546
+ try {
547
+ // Get current Cortex SDK version
548
+ let currentSdkVersion = "not installed";
549
+ try {
550
+ const result = await execCommand("npm", ["list", "@cortexmemory/sdk", "--json"], { quiet: true, cwd: projectPath });
551
+ const data = JSON.parse(result.stdout);
552
+ currentSdkVersion =
553
+ data.dependencies?.["@cortexmemory/sdk"]?.version ?? "not installed";
554
+ }
555
+ catch {
556
+ // Ignore errors
557
+ }
558
+ // Get latest Cortex SDK version from npm
559
+ let latestSdkVersion = "unknown";
560
+ try {
561
+ const result = await execCommand("npm", ["view", "@cortexmemory/sdk", "version"], { quiet: true });
562
+ latestSdkVersion = result.stdout.trim();
563
+ }
564
+ catch {
565
+ // Ignore errors
566
+ }
567
+ // Get current Convex version
568
+ let currentConvexVersion = "not installed";
569
+ try {
570
+ const result = await execCommand("npm", ["list", "convex", "--json"], {
571
+ quiet: true,
572
+ cwd: projectPath,
573
+ });
574
+ const data = JSON.parse(result.stdout);
575
+ currentConvexVersion =
576
+ data.dependencies?.convex?.version ?? "not installed";
577
+ }
578
+ catch {
579
+ // Ignore errors
580
+ }
581
+ // Get latest Convex version from npm
582
+ let latestConvexVersion = "unknown";
583
+ try {
584
+ const result = await execCommand("npm", ["view", "convex", "version"], {
585
+ quiet: true,
209
586
  });
587
+ latestConvexVersion = result.stdout.trim();
588
+ }
589
+ catch {
590
+ // Ignore errors
591
+ }
592
+ // Get Cortex SDK's peer dependency on Convex
593
+ let sdkConvexPeerDep = "unknown";
594
+ try {
595
+ const result = await execCommand("npm", ["view", "@cortexmemory/sdk", "peerDependencies", "--json"], { quiet: true });
596
+ const peerDeps = JSON.parse(result.stdout);
597
+ sdkConvexPeerDep = peerDeps?.convex ?? "unknown";
598
+ }
599
+ catch {
600
+ // Ignore errors
601
+ }
602
+ spinner.stop();
603
+ // Display current status
604
+ console.log();
605
+ printSection("Package Status", {
606
+ Deployment: name,
607
+ "Project Path": projectPath,
608
+ });
609
+ console.log();
610
+ console.log(pc.bold(" @cortexmemory/sdk"));
611
+ console.log(` Current: ${currentSdkVersion === latestSdkVersion ? pc.green(currentSdkVersion) : pc.yellow(currentSdkVersion)}`);
612
+ console.log(` Latest: ${latestSdkVersion}`);
613
+ console.log();
614
+ console.log(pc.bold(" convex"));
615
+ console.log(` Current: ${currentConvexVersion === latestConvexVersion ? pc.green(currentConvexVersion) : pc.yellow(currentConvexVersion)}`);
616
+ console.log(` Latest: ${latestConvexVersion}`);
617
+ if (sdkConvexPeerDep !== "unknown") {
618
+ console.log(` SDK requires: ${pc.dim(sdkConvexPeerDep)}`);
619
+ }
620
+ console.log();
621
+ // Determine what needs updating
622
+ const targetSdkVersion = options.sdkVersion ?? latestSdkVersion;
623
+ const sdkNeedsUpdate = currentSdkVersion !== targetSdkVersion &&
624
+ currentSdkVersion !== "not installed";
625
+ const sdkNeedsInstall = currentSdkVersion === "not installed";
626
+ // Check if Convex has a patch update available beyond what SDK requires
627
+ const parseVersion = (v) => {
628
+ const match = v.match(/^(\d+)\.(\d+)\.(\d+)/);
629
+ if (!match)
630
+ return null;
631
+ return {
632
+ major: parseInt(match[1]),
633
+ minor: parseInt(match[2]),
634
+ patch: parseInt(match[3]),
635
+ };
636
+ };
637
+ const currentConvex = parseVersion(currentConvexVersion);
638
+ const latestConvex = parseVersion(latestConvexVersion);
639
+ let convexPatchAvailable = false;
640
+ if (currentConvex && latestConvex) {
641
+ // Patch update = same major.minor, higher patch
642
+ convexPatchAvailable =
643
+ currentConvex.major === latestConvex.major &&
644
+ currentConvex.minor === latestConvex.minor &&
645
+ currentConvex.patch < latestConvex.patch;
646
+ }
647
+ const targetConvexVersion = options.convexVersion ??
648
+ (convexPatchAvailable ? latestConvexVersion : null);
649
+ const convexNeedsUpdate = targetConvexVersion && currentConvexVersion !== targetConvexVersion;
650
+ // Nothing to update
651
+ if (!sdkNeedsUpdate &&
652
+ !sdkNeedsInstall &&
653
+ !convexNeedsUpdate &&
654
+ !convexPatchAvailable) {
655
+ printSuccess("All packages are up to date!");
656
+ return;
657
+ }
658
+ // Update Cortex SDK if needed
659
+ if (sdkNeedsUpdate || sdkNeedsInstall) {
210
660
  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}`);
661
+ printInfo(`${sdkNeedsInstall ? "Installing" : "Updating"} @cortexmemory/sdk@${targetSdkVersion}...`);
214
662
  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)}`);
663
+ const exitCode = await execCommandLive("npm", ["install", `@cortexmemory/sdk@${targetSdkVersion}`], { cwd: projectPath });
664
+ if (exitCode === 0) {
665
+ printSuccess(`${sdkNeedsInstall ? "Installed" : "Updated"} @cortexmemory/sdk to ${targetSdkVersion}`);
666
+ }
667
+ else {
668
+ printError("SDK update failed");
669
+ throw new Error("SDK update failed");
220
670
  }
671
+ }
672
+ else if (currentSdkVersion !== "not installed") {
673
+ printSuccess("@cortexmemory/sdk is already up to date");
674
+ }
675
+ // Check for Convex patch update
676
+ if (convexPatchAvailable && !options.convexVersion) {
221
677
  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;
678
+ console.log(pc.cyan(` Convex patch update available: ${currentConvexVersion} → ${latestConvexVersion}`));
679
+ let shouldUpdate = options.yes;
680
+ if (!shouldUpdate) {
681
+ const { default: prompts } = await import("prompts");
682
+ const response = await prompts({
683
+ type: "confirm",
684
+ name: "update",
685
+ message: "Update Convex to latest patch version?",
686
+ initial: true,
687
+ });
688
+ shouldUpdate = response.update;
258
689
  }
259
- // Update Cortex SDK if needed
260
- if (sdkNeedsUpdate || sdkNeedsInstall) {
690
+ if (shouldUpdate) {
261
691
  console.log();
262
- printInfo(`${sdkNeedsInstall ? "Installing" : "Updating"} @cortexmemory/sdk@${targetSdkVersion}...`);
692
+ printInfo(`Updating convex@${latestConvexVersion}...`);
263
693
  console.log();
264
- const exitCode = await execCommandLive("npm", ["install", `@cortexmemory/sdk@${targetSdkVersion}`], { cwd: projectPath });
694
+ const exitCode = await execCommandLive("npm", ["install", `convex@${latestConvexVersion}`], { cwd: projectPath });
265
695
  if (exitCode === 0) {
266
- printSuccess(`${sdkNeedsInstall ? "Installed" : "Updated"} @cortexmemory/sdk to ${targetSdkVersion}`);
696
+ printSuccess(`Updated convex to ${latestConvexVersion}`);
267
697
  }
268
698
  else {
269
- printError("SDK update failed");
270
- process.exit(1);
699
+ printWarning("Convex update failed, but SDK update was successful");
271
700
  }
272
701
  }
273
- else if (currentSdkVersion !== "not installed") {
274
- printSuccess("@cortexmemory/sdk is already up to date");
702
+ else {
703
+ console.log(pc.dim(" Skipping Convex update"));
704
+ }
705
+ }
706
+ else if (options.convexVersion) {
707
+ // Explicit version requested
708
+ console.log();
709
+ printInfo(`Updating convex@${options.convexVersion}...`);
710
+ console.log();
711
+ const exitCode = await execCommandLive("npm", ["install", `convex@${options.convexVersion}`], { cwd: projectPath });
712
+ if (exitCode === 0) {
713
+ printSuccess(`Updated convex to ${options.convexVersion}`);
714
+ }
715
+ else {
716
+ printWarning("Convex update failed");
717
+ }
718
+ }
719
+ console.log();
720
+ printSuccess("Update complete!");
721
+ }
722
+ catch (error) {
723
+ spinner.stop();
724
+ throw error;
725
+ }
726
+ }
727
+ /**
728
+ * Update packages for a single app
729
+ */
730
+ async function updateApp(name, app, options) {
731
+ const appPath = path.join(app.projectPath, app.path);
732
+ const isDevMode = !!options.devPath;
733
+ if (!await fs.pathExists(appPath)) {
734
+ printError(`App path not found: ${appPath}`);
735
+ throw new Error(`App path not found: ${appPath}`);
736
+ }
737
+ const spinner = ora("Checking for updates...").start();
738
+ try {
739
+ // Read package.json
740
+ const packageJsonPath = path.join(appPath, "package.json");
741
+ if (!await fs.pathExists(packageJsonPath)) {
742
+ spinner.stop();
743
+ printError(`No package.json found at ${appPath}`);
744
+ throw new Error(`No package.json found at ${appPath}`);
745
+ }
746
+ const pkg = await fs.readJson(packageJsonPath);
747
+ // Check current versions
748
+ let currentSdkVersion = "not installed";
749
+ let currentProviderVersion = "not installed";
750
+ let currentConvexVersion = "not installed";
751
+ let currentAiVersion = "not installed";
752
+ let isDevLinked = false;
753
+ // Check if already dev-linked
754
+ const sdkDep = pkg.dependencies?.["@cortexmemory/sdk"];
755
+ const providerDep = pkg.dependencies?.["@cortexmemory/vercel-ai-provider"];
756
+ isDevLinked = sdkDep?.startsWith("file:") || providerDep?.startsWith("file:");
757
+ // Get installed versions
758
+ try {
759
+ const result = await execCommand("npm", ["list", "@cortexmemory/sdk", "@cortexmemory/vercel-ai-provider", "convex", "ai", "--json"], { quiet: true, cwd: appPath });
760
+ const data = JSON.parse(result.stdout);
761
+ currentSdkVersion =
762
+ data.dependencies?.["@cortexmemory/sdk"]?.version ?? "not installed";
763
+ currentProviderVersion =
764
+ data.dependencies?.["@cortexmemory/vercel-ai-provider"]?.version ?? "not installed";
765
+ currentConvexVersion =
766
+ data.dependencies?.convex?.version ?? "not installed";
767
+ currentAiVersion =
768
+ data.dependencies?.ai?.version ?? "not installed";
769
+ }
770
+ catch {
771
+ // Ignore errors
772
+ }
773
+ // Get latest versions from npm
774
+ let latestSdkVersion = "unknown";
775
+ let latestProviderVersion = "unknown";
776
+ let latestConvexVersion = "unknown";
777
+ let latestAiVersion = "unknown";
778
+ try {
779
+ const [sdkResult, providerResult, convexResult, aiResult] = await Promise.all([
780
+ execCommand("npm", ["view", "@cortexmemory/sdk", "version"], { quiet: true }).catch(() => ({ stdout: "unknown" })),
781
+ execCommand("npm", ["view", "@cortexmemory/vercel-ai-provider", "version"], { quiet: true }).catch(() => ({ stdout: "unknown" })),
782
+ execCommand("npm", ["view", "convex", "version"], { quiet: true }).catch(() => ({ stdout: "unknown" })),
783
+ execCommand("npm", ["view", "ai", "version"], { quiet: true }).catch(() => ({ stdout: "unknown" })),
784
+ ]);
785
+ latestSdkVersion = sdkResult.stdout.trim() || "unknown";
786
+ latestProviderVersion = providerResult.stdout.trim() || "unknown";
787
+ latestConvexVersion = convexResult.stdout.trim() || "unknown";
788
+ latestAiVersion = aiResult.stdout.trim() || "unknown";
789
+ }
790
+ catch {
791
+ // Ignore errors
792
+ }
793
+ spinner.stop();
794
+ // Display current status
795
+ console.log();
796
+ printSection("App Package Status", {
797
+ App: name,
798
+ Type: app.type,
799
+ Path: appPath,
800
+ });
801
+ if (isDevMode) {
802
+ console.log();
803
+ console.log(pc.magenta(" ═══ DEV MODE ═══"));
804
+ console.log(pc.dim(` Will link to: ${options.devPath}`));
805
+ }
806
+ console.log();
807
+ console.log(pc.bold(" @cortexmemory/sdk"));
808
+ if (isDevLinked) {
809
+ console.log(` Current: ${pc.magenta("file:... (dev linked)")}`);
810
+ }
811
+ else {
812
+ console.log(` Current: ${currentSdkVersion === latestSdkVersion ? pc.green(currentSdkVersion) : pc.yellow(currentSdkVersion)}`);
813
+ }
814
+ console.log(` Latest: ${latestSdkVersion}`);
815
+ console.log();
816
+ console.log(pc.bold(" @cortexmemory/vercel-ai-provider"));
817
+ if (isDevLinked) {
818
+ console.log(` Current: ${pc.magenta("file:... (dev linked)")}`);
819
+ }
820
+ else {
821
+ console.log(` Current: ${currentProviderVersion === latestProviderVersion ? pc.green(currentProviderVersion) : pc.yellow(currentProviderVersion)}`);
822
+ }
823
+ console.log(` Latest: ${latestProviderVersion}`);
824
+ console.log();
825
+ console.log(pc.bold(" convex"));
826
+ console.log(` Current: ${currentConvexVersion === latestConvexVersion ? pc.green(currentConvexVersion) : pc.yellow(currentConvexVersion)}`);
827
+ console.log(` Latest: ${latestConvexVersion}`);
828
+ console.log();
829
+ console.log(pc.bold(" ai (Vercel AI SDK)"));
830
+ console.log(` Current: ${currentAiVersion === latestAiVersion ? pc.green(currentAiVersion) : pc.yellow(currentAiVersion)}`);
831
+ console.log(` Latest: ${latestAiVersion}`);
832
+ console.log();
833
+ // Determine update strategy
834
+ if (isDevMode) {
835
+ // Dev mode: update package.json with file: references
836
+ if (isDevLinked) {
837
+ printSuccess("App is already dev-linked. Running npm install to refresh...");
838
+ }
839
+ else {
840
+ printInfo("Switching to dev mode with local SDK...");
275
841
  }
276
- // Check for Convex patch update
277
- if (convexPatchAvailable && !options.convexVersion) {
842
+ // Update package.json with file: references
843
+ const devSdkPath = options.devPath;
844
+ const devProviderPath = path.join(devSdkPath, "packages", "vercel-ai-provider");
845
+ pkg.dependencies = pkg.dependencies || {};
846
+ pkg.dependencies["@cortexmemory/sdk"] = `file:${devSdkPath}`;
847
+ pkg.dependencies["@cortexmemory/vercel-ai-provider"] = `file:${devProviderPath}`;
848
+ await fs.writeJson(packageJsonPath, pkg, { spaces: 2 });
849
+ console.log(pc.cyan(" Updated package.json with file: references"));
850
+ // Run npm install
851
+ console.log();
852
+ printInfo("Running npm install...");
853
+ console.log();
854
+ const exitCode = await execCommandLive("npm", ["install", "--legacy-peer-deps"], { cwd: appPath });
855
+ if (exitCode === 0) {
278
856
  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
- }
302
- }
303
- else {
304
- console.log(pc.dim(" Skipping Convex update"));
305
- }
857
+ printSuccess("Dev mode linking complete!");
858
+ console.log(pc.dim(` SDK linked to: ${devSdkPath}`));
859
+ console.log(pc.dim(` Provider linked to: ${devProviderPath}`));
860
+ }
861
+ else {
862
+ printError("npm install failed");
863
+ throw new Error("npm install failed");
306
864
  }
307
- else if (options.convexVersion) {
308
- // Explicit version requested
865
+ }
866
+ else {
867
+ // Normal mode: update to latest versions from npm
868
+ const targetSdkVersion = options.sdkVersion ?? latestSdkVersion;
869
+ const targetProviderVersion = options.providerVersion ?? latestProviderVersion;
870
+ // Check if we need to remove dev links first
871
+ if (isDevLinked) {
872
+ printInfo("Removing dev links and switching to npm packages...");
873
+ pkg.dependencies["@cortexmemory/sdk"] = `^${targetSdkVersion}`;
874
+ pkg.dependencies["@cortexmemory/vercel-ai-provider"] = `^${targetProviderVersion}`;
875
+ await fs.writeJson(packageJsonPath, pkg, { spaces: 2 });
876
+ console.log(pc.cyan(" Updated package.json with npm versions"));
877
+ }
878
+ // Determine what needs updating
879
+ const sdkNeedsUpdate = currentSdkVersion !== targetSdkVersion || isDevLinked;
880
+ const providerNeedsUpdate = currentProviderVersion !== targetProviderVersion || isDevLinked;
881
+ // Nothing to update
882
+ if (!sdkNeedsUpdate && !providerNeedsUpdate) {
883
+ printSuccess("All packages are up to date!");
884
+ return;
885
+ }
886
+ // Build install command
887
+ const packagesToInstall = [];
888
+ if (sdkNeedsUpdate) {
889
+ packagesToInstall.push(`@cortexmemory/sdk@${targetSdkVersion}`);
890
+ }
891
+ if (providerNeedsUpdate) {
892
+ packagesToInstall.push(`@cortexmemory/vercel-ai-provider@${targetProviderVersion}`);
893
+ }
894
+ if (packagesToInstall.length > 0) {
309
895
  console.log();
310
- printInfo(`Updating convex@${options.convexVersion}...`);
896
+ printInfo(`Installing: ${packagesToInstall.join(", ")}...`);
311
897
  console.log();
312
- const exitCode = await execCommandLive("npm", ["install", `convex@${options.convexVersion}`], { cwd: projectPath });
898
+ const exitCode = await execCommandLive("npm", ["install", ...packagesToInstall, "--legacy-peer-deps"], { cwd: appPath });
313
899
  if (exitCode === 0) {
314
- printSuccess(`Updated convex to ${options.convexVersion}`);
900
+ printSuccess("Packages updated successfully");
315
901
  }
316
902
  else {
317
- printWarning("Convex update failed");
903
+ printError("Package update failed");
904
+ throw new Error("Package update failed");
318
905
  }
319
906
  }
320
907
  console.log();
321
- printSuccess("Update complete!");
908
+ printSuccess("Package update complete!");
322
909
  }
323
- catch (error) {
324
- spinner.stop();
325
- printError(error instanceof Error ? error.message : "Update failed");
326
- process.exit(1);
910
+ // Template sync (if enabled)
911
+ if (options.syncTemplate) {
912
+ console.log();
913
+ printSection("Template Sync", {});
914
+ console.log();
915
+ try {
916
+ const templateResult = await syncAppTemplate(app, { dryRun: false });
917
+ if (templateResult.error) {
918
+ printWarning(`Template sync skipped: ${templateResult.error}`);
919
+ }
920
+ else if (templateResult.synced) {
921
+ printTemplateSyncResult(templateResult);
922
+ // Run npm install if package.json was updated with new dependencies
923
+ if (templateResult.packageJsonUpdated) {
924
+ const totalNewDeps = templateResult.depsAdded.length + templateResult.devDepsAdded.length;
925
+ if (totalNewDeps > 0) {
926
+ console.log();
927
+ printInfo(`Installing ${totalNewDeps} new dependencies...`);
928
+ console.log(pc.dim(` Running in: ${templateResult.appPath}`));
929
+ console.log();
930
+ const exitCode = await execCommandLive("npm", ["install", "--legacy-peer-deps"], { cwd: templateResult.appPath });
931
+ if (exitCode === 0) {
932
+ printSuccess("Dependencies installed");
933
+ }
934
+ else {
935
+ printWarning("npm install failed - you may need to run it manually");
936
+ }
937
+ }
938
+ }
939
+ }
940
+ else {
941
+ console.log(pc.dim(" Template files are up to date"));
942
+ }
943
+ }
944
+ catch (error) {
945
+ const message = error instanceof Error ? error.message : String(error);
946
+ printWarning(`Template sync failed: ${message}`);
947
+ }
327
948
  }
328
- });
949
+ console.log();
950
+ printSuccess("Update complete!");
951
+ }
952
+ catch (error) {
953
+ spinner.stop();
954
+ throw error;
955
+ }
329
956
  }
330
957
  //# sourceMappingURL=deploy.js.map