@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.
- package/dist/commands/convex.js +1 -1
- package/dist/commands/convex.js.map +1 -1
- package/dist/commands/deploy.d.ts +1 -1
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +839 -141
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +89 -26
- package/dist/commands/dev.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/utils/app-template-sync.d.ts +95 -0
- package/dist/utils/app-template-sync.d.ts.map +1 -0
- package/dist/utils/app-template-sync.js +445 -0
- package/dist/utils/app-template-sync.js.map +1 -0
- package/dist/utils/deployment-selector.d.ts +21 -0
- package/dist/utils/deployment-selector.d.ts.map +1 -1
- package/dist/utils/deployment-selector.js +32 -0
- package/dist/utils/deployment-selector.js.map +1 -1
- package/dist/utils/init/graph-setup.d.ts.map +1 -1
- package/dist/utils/init/graph-setup.js +13 -2
- package/dist/utils/init/graph-setup.js.map +1 -1
- package/package.json +1 -1
- package/templates/vercel-ai-quickstart/app/api/auth/check/route.ts +30 -0
- package/templates/vercel-ai-quickstart/app/api/auth/login/route.ts +128 -0
- package/templates/vercel-ai-quickstart/app/api/auth/register/route.ts +94 -0
- package/templates/vercel-ai-quickstart/app/api/auth/setup/route.ts +59 -0
- package/templates/vercel-ai-quickstart/app/api/chat/route.ts +139 -3
- package/templates/vercel-ai-quickstart/app/api/chat-v6/route.ts +333 -0
- package/templates/vercel-ai-quickstart/app/api/conversations/route.ts +179 -0
- package/templates/vercel-ai-quickstart/app/globals.css +161 -0
- package/templates/vercel-ai-quickstart/app/page.tsx +110 -11
- package/templates/vercel-ai-quickstart/components/AdminSetup.tsx +139 -0
- package/templates/vercel-ai-quickstart/components/AuthProvider.tsx +283 -0
- package/templates/vercel-ai-quickstart/components/ChatHistorySidebar.tsx +323 -0
- package/templates/vercel-ai-quickstart/components/ChatInterface.tsx +117 -17
- package/templates/vercel-ai-quickstart/components/LoginScreen.tsx +202 -0
- package/templates/vercel-ai-quickstart/jest.config.js +52 -0
- package/templates/vercel-ai-quickstart/lib/agents/memory-agent.ts +165 -0
- package/templates/vercel-ai-quickstart/lib/cortex.ts +27 -0
- package/templates/vercel-ai-quickstart/lib/password.ts +120 -0
- package/templates/vercel-ai-quickstart/lib/versions.ts +60 -0
- package/templates/vercel-ai-quickstart/next.config.js +20 -0
- package/templates/vercel-ai-quickstart/package.json +11 -2
- package/templates/vercel-ai-quickstart/test-api.mjs +272 -0
- package/templates/vercel-ai-quickstart/tests/e2e/chat-memory-flow.test.ts +454 -0
- package/templates/vercel-ai-quickstart/tests/helpers/mock-cortex.ts +263 -0
- package/templates/vercel-ai-quickstart/tests/helpers/setup.ts +48 -0
- package/templates/vercel-ai-quickstart/tests/integration/auth.test.ts +455 -0
- package/templates/vercel-ai-quickstart/tests/integration/conversations.test.ts +461 -0
- package/templates/vercel-ai-quickstart/tests/unit/password.test.ts +228 -0
- package/templates/vercel-ai-quickstart/tsconfig.json +1 -1
package/dist/commands/deploy.js
CHANGED
|
@@ -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
|
-
|
|
147
|
-
|
|
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
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
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
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
179
|
+
await updateApp(options.app, app, {
|
|
180
|
+
...options,
|
|
181
|
+
devPath: isDevMode ? devPath : undefined,
|
|
182
|
+
syncTemplate: options.syncTemplate,
|
|
183
|
+
});
|
|
161
184
|
}
|
|
162
|
-
catch {
|
|
163
|
-
|
|
185
|
+
catch (error) {
|
|
186
|
+
printError(`Failed to update app "${options.app}": ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
164
187
|
}
|
|
165
|
-
|
|
166
|
-
|
|
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
|
-
|
|
169
|
-
latestSdkVersion = result.stdout.trim();
|
|
197
|
+
await updateDeployment(name, deployment, options);
|
|
170
198
|
}
|
|
171
|
-
catch {
|
|
172
|
-
|
|
199
|
+
catch (error) {
|
|
200
|
+
printError(`Failed to update deployment "${name}": ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
173
201
|
}
|
|
174
|
-
|
|
175
|
-
|
|
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
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
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
|
-
|
|
186
|
-
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
// Normal mode: fetch all versions from npm
|
|
187
274
|
try {
|
|
188
|
-
const
|
|
189
|
-
|
|
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
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
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
|
-
|
|
202
|
-
|
|
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
|
-
|
|
205
|
-
|
|
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
|
-
|
|
208
|
-
|
|
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
|
-
|
|
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
|
-
|
|
216
|
-
|
|
217
|
-
|
|
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
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
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
|
-
|
|
260
|
-
if (sdkNeedsUpdate || sdkNeedsInstall) {
|
|
731
|
+
if (shouldUpdate) {
|
|
261
732
|
console.log();
|
|
262
|
-
printInfo(
|
|
733
|
+
printInfo(`Updating convex@${latestConvexVersion}...`);
|
|
263
734
|
console.log();
|
|
264
|
-
const exitCode = await execCommandLive("npm", ["install",
|
|
735
|
+
const exitCode = await execCommandLive("npm", ["install", `convex@${latestConvexVersion}`], { cwd: projectPath });
|
|
265
736
|
if (exitCode === 0) {
|
|
266
|
-
printSuccess(
|
|
737
|
+
printSuccess(`Updated convex to ${latestConvexVersion}`);
|
|
267
738
|
}
|
|
268
739
|
else {
|
|
269
|
-
|
|
270
|
-
process.exit(1);
|
|
740
|
+
printWarning("Convex update failed, but SDK update was successful");
|
|
271
741
|
}
|
|
272
742
|
}
|
|
273
|
-
else
|
|
274
|
-
|
|
743
|
+
else {
|
|
744
|
+
console.log(pc.dim(" Skipping Convex update"));
|
|
275
745
|
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
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
|
-
|
|
304
|
-
|
|
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
|
-
|
|
308
|
-
|
|
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(`
|
|
967
|
+
printInfo(`Installing: ${packagesToInstall.join(", ")}...`);
|
|
311
968
|
console.log();
|
|
312
|
-
const exitCode = await execCommandLive("npm", ["install",
|
|
969
|
+
const exitCode = await execCommandLive("npm", ["install", ...packagesToInstall, "--legacy-peer-deps"], { cwd: appPath });
|
|
313
970
|
if (exitCode === 0) {
|
|
314
|
-
printSuccess(
|
|
971
|
+
printSuccess("Packages updated successfully");
|
|
315
972
|
}
|
|
316
973
|
else {
|
|
317
|
-
|
|
974
|
+
printError("Package update failed");
|
|
975
|
+
throw new Error("Package update failed");
|
|
318
976
|
}
|
|
319
977
|
}
|
|
320
978
|
console.log();
|
|
321
|
-
printSuccess("
|
|
979
|
+
printSuccess("Package update complete!");
|
|
322
980
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
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
|