@agentuity/cli 0.0.71 → 0.0.73
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/bin/cli.ts +19 -5
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +77 -19
- package/dist/cli.js.map +1 -1
- package/dist/cmd/auth/api.d.ts +2 -2
- package/dist/cmd/auth/api.d.ts.map +1 -1
- package/dist/cmd/auth/api.js +15 -14
- package/dist/cmd/auth/api.js.map +1 -1
- package/dist/cmd/auth/login.d.ts.map +1 -1
- package/dist/cmd/auth/login.js +37 -16
- package/dist/cmd/auth/login.js.map +1 -1
- package/dist/cmd/auth/ssh/api.d.ts.map +1 -1
- package/dist/cmd/auth/ssh/api.js +3 -2
- package/dist/cmd/auth/ssh/api.js.map +1 -1
- package/dist/cmd/build/ast.d.ts.map +1 -1
- package/dist/cmd/build/ast.js +56 -8
- package/dist/cmd/build/ast.js.map +1 -1
- package/dist/cmd/build/bundler.d.ts +1 -2
- package/dist/cmd/build/bundler.d.ts.map +1 -1
- package/dist/cmd/build/bundler.js +30 -8
- package/dist/cmd/build/bundler.js.map +1 -1
- package/dist/cmd/build/format-schema.d.ts +6 -0
- package/dist/cmd/build/format-schema.d.ts.map +1 -0
- package/dist/cmd/build/format-schema.js +60 -0
- package/dist/cmd/build/format-schema.js.map +1 -0
- package/dist/cmd/build/index.d.ts.map +1 -1
- package/dist/cmd/build/index.js +13 -0
- package/dist/cmd/build/index.js.map +1 -1
- package/dist/cmd/build/plugin.d.ts.map +1 -1
- package/dist/cmd/build/plugin.js +72 -2
- package/dist/cmd/build/plugin.js.map +1 -1
- package/dist/cmd/cloud/db/create.js +2 -2
- package/dist/cmd/cloud/db/create.js.map +1 -1
- package/dist/cmd/cloud/db/delete.js +2 -2
- package/dist/cmd/cloud/db/delete.js.map +1 -1
- package/dist/cmd/cloud/db/get.js +2 -2
- package/dist/cmd/cloud/db/get.js.map +1 -1
- package/dist/cmd/cloud/db/list.js +2 -2
- package/dist/cmd/cloud/db/list.js.map +1 -1
- package/dist/cmd/cloud/db/logs.js +2 -2
- package/dist/cmd/cloud/db/logs.js.map +1 -1
- package/dist/cmd/cloud/db/sql.js +2 -2
- package/dist/cmd/cloud/db/sql.js.map +1 -1
- package/dist/cmd/cloud/deploy.d.ts.map +1 -1
- package/dist/cmd/cloud/deploy.js +163 -24
- package/dist/cmd/cloud/deploy.js.map +1 -1
- package/dist/cmd/cloud/deployment/show.d.ts.map +1 -1
- package/dist/cmd/cloud/deployment/show.js +34 -10
- package/dist/cmd/cloud/deployment/show.js.map +1 -1
- package/dist/cmd/cloud/session/get.js +2 -2
- package/dist/cmd/cloud/session/get.js.map +1 -1
- package/dist/cmd/cloud/session/list.js +2 -2
- package/dist/cmd/cloud/session/list.js.map +1 -1
- package/dist/cmd/cloud/storage/create.js +2 -2
- package/dist/cmd/cloud/storage/create.js.map +1 -1
- package/dist/cmd/cloud/storage/delete.js +2 -2
- package/dist/cmd/cloud/storage/delete.js.map +1 -1
- package/dist/cmd/cloud/storage/download.js +2 -2
- package/dist/cmd/cloud/storage/download.js.map +1 -1
- package/dist/cmd/cloud/storage/get.js +2 -2
- package/dist/cmd/cloud/storage/get.js.map +1 -1
- package/dist/cmd/cloud/storage/list.js +2 -2
- package/dist/cmd/cloud/storage/list.js.map +1 -1
- package/dist/cmd/cloud/storage/upload.js +2 -2
- package/dist/cmd/cloud/storage/upload.js.map +1 -1
- package/dist/cmd/cloud/thread/delete.js +2 -2
- package/dist/cmd/cloud/thread/delete.js.map +1 -1
- package/dist/cmd/cloud/thread/get.js +2 -2
- package/dist/cmd/cloud/thread/get.js.map +1 -1
- package/dist/cmd/cloud/thread/list.js +2 -2
- package/dist/cmd/cloud/thread/list.js.map +1 -1
- package/dist/cmd/dev/agents.d.ts.map +1 -1
- package/dist/cmd/dev/agents.js +2 -2
- package/dist/cmd/dev/agents.js.map +1 -1
- package/dist/cmd/dev/sync.d.ts.map +1 -1
- package/dist/cmd/dev/sync.js +2 -2
- package/dist/cmd/dev/sync.js.map +1 -1
- package/dist/cmd/project/show.d.ts.map +1 -1
- package/dist/cmd/project/show.js +8 -7
- package/dist/cmd/project/show.js.map +1 -1
- package/dist/cmd/project/template-flow.d.ts.map +1 -1
- package/dist/cmd/project/template-flow.js +14 -2
- package/dist/cmd/project/template-flow.js.map +1 -1
- package/dist/config.d.ts +2 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +17 -1
- package/dist/config.js.map +1 -1
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +5 -1
- package/dist/output.js.map +1 -1
- package/dist/tui.d.ts +46 -1
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +217 -39
- package/dist/tui.js.map +1 -1
- package/dist/types.d.ts +10 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/cli.ts +85 -25
- package/src/cmd/auth/api.ts +20 -26
- package/src/cmd/auth/login.ts +36 -17
- package/src/cmd/auth/ssh/api.ts +5 -6
- package/src/cmd/build/ast.ts +67 -8
- package/src/cmd/build/bundler.ts +37 -9
- package/src/cmd/build/format-schema.ts +66 -0
- package/src/cmd/build/index.ts +14 -0
- package/src/cmd/build/plugin.ts +86 -2
- package/src/cmd/cloud/db/create.ts +2 -2
- package/src/cmd/cloud/db/delete.ts +2 -2
- package/src/cmd/cloud/db/get.ts +2 -2
- package/src/cmd/cloud/db/list.ts +2 -2
- package/src/cmd/cloud/db/logs.ts +2 -2
- package/src/cmd/cloud/db/sql.ts +2 -2
- package/src/cmd/cloud/deploy.ts +187 -24
- package/src/cmd/cloud/deployment/show.ts +42 -10
- package/src/cmd/cloud/session/get.ts +2 -2
- package/src/cmd/cloud/session/list.ts +2 -2
- package/src/cmd/cloud/storage/create.ts +2 -2
- package/src/cmd/cloud/storage/delete.ts +2 -2
- package/src/cmd/cloud/storage/download.ts +2 -2
- package/src/cmd/cloud/storage/get.ts +2 -2
- package/src/cmd/cloud/storage/list.ts +2 -2
- package/src/cmd/cloud/storage/upload.ts +2 -2
- package/src/cmd/cloud/thread/delete.ts +2 -2
- package/src/cmd/cloud/thread/get.ts +2 -2
- package/src/cmd/cloud/thread/list.ts +2 -2
- package/src/cmd/dev/agents.ts +2 -4
- package/src/cmd/dev/sync.ts +6 -8
- package/src/cmd/project/show.ts +8 -6
- package/src/cmd/project/template-flow.ts +21 -2
- package/src/config.ts +19 -6
- package/src/output.ts +7 -1
- package/src/tui.ts +302 -41
package/src/cmd/cloud/deploy.ts
CHANGED
|
@@ -1,23 +1,25 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { join, resolve } from 'node:path';
|
|
3
3
|
import { createPublicKey } from 'node:crypto';
|
|
4
|
-
import { createReadStream, createWriteStream } from 'node:fs';
|
|
4
|
+
import { createReadStream, createWriteStream, existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
5
5
|
import { tmpdir } from 'node:os';
|
|
6
6
|
import { createSubcommand } from '../../types';
|
|
7
7
|
import * as tui from '../../tui';
|
|
8
|
-
import { saveProjectDir } from '../../config';
|
|
8
|
+
import { saveProjectDir, getDefaultConfigDir } from '../../config';
|
|
9
9
|
import { runSteps, stepSuccess, stepSkipped, stepError, Step, ProgressCallback } from '../../steps';
|
|
10
10
|
import { bundle } from '../build/bundler';
|
|
11
|
-
import { loadBuildMetadata } from '../../config';
|
|
11
|
+
import { loadBuildMetadata, getStreamURL } from '../../config';
|
|
12
12
|
import {
|
|
13
13
|
projectEnvUpdate,
|
|
14
14
|
projectDeploymentCreate,
|
|
15
15
|
projectDeploymentUpdate,
|
|
16
16
|
projectDeploymentComplete,
|
|
17
|
+
projectDeploymentStatus,
|
|
17
18
|
type Deployment,
|
|
18
19
|
type BuildMetadata,
|
|
19
20
|
type DeploymentInstructions,
|
|
20
21
|
type DeploymentComplete,
|
|
22
|
+
type DeploymentStatusResult,
|
|
21
23
|
} from '@agentuity/server';
|
|
22
24
|
import {
|
|
23
25
|
findEnvFile,
|
|
@@ -30,11 +32,13 @@ import { encryptFIPSKEMDEMStream } from '../../crypto/box';
|
|
|
30
32
|
import { getCommand } from '../../command-prefix';
|
|
31
33
|
import { checkCustomDomainForDNS } from './domain';
|
|
32
34
|
import { DeployOptionsSchema } from '../../schemas/deploy';
|
|
35
|
+
import { ErrorCode } from '../../errors';
|
|
33
36
|
|
|
34
37
|
const DeployResponseSchema = z.object({
|
|
35
38
|
success: z.boolean().describe('Whether deployment succeeded'),
|
|
36
39
|
deploymentId: z.string().describe('Deployment ID'),
|
|
37
40
|
projectId: z.string().describe('Project ID'),
|
|
41
|
+
logs: z.array(z.string()).optional().describe('The deployment startup logs'),
|
|
38
42
|
urls: z
|
|
39
43
|
.object({
|
|
40
44
|
deployment: z.string().describe('Deployment-specific URL'),
|
|
@@ -77,12 +81,14 @@ export const deploySubcommand = createSubcommand({
|
|
|
77
81
|
},
|
|
78
82
|
|
|
79
83
|
async handler(ctx) {
|
|
80
|
-
const { project, apiClient, projectDir, config, options, opts } = ctx;
|
|
84
|
+
const { project, apiClient, projectDir, config, options, opts, logger } = ctx;
|
|
81
85
|
|
|
82
86
|
let deployment: Deployment | undefined;
|
|
83
87
|
let build: BuildMetadata | undefined;
|
|
84
88
|
let instructions: DeploymentInstructions | undefined;
|
|
85
89
|
let complete: DeploymentComplete | undefined;
|
|
90
|
+
let statusResult: DeploymentStatusResult | undefined;
|
|
91
|
+
const logs: string[] = [];
|
|
86
92
|
|
|
87
93
|
try {
|
|
88
94
|
await saveProjectDir(projectDir);
|
|
@@ -237,7 +243,6 @@ export const deploySubcommand = createSubcommand({
|
|
|
237
243
|
if (relative.startsWith('.env')) return false;
|
|
238
244
|
if (relative.startsWith('.git/')) return false;
|
|
239
245
|
if (relative.startsWith('.ssh/')) return false;
|
|
240
|
-
if (relative.startsWith('node_modules/')) return false;
|
|
241
246
|
if (relative === '.DS_Store') return false;
|
|
242
247
|
return true;
|
|
243
248
|
},
|
|
@@ -367,9 +372,174 @@ export const deploySubcommand = createSubcommand({
|
|
|
367
372
|
].filter(Boolean) as Step[],
|
|
368
373
|
options.logLevel
|
|
369
374
|
);
|
|
370
|
-
tui.success('Your project was deployed!');
|
|
371
375
|
|
|
372
|
-
if (
|
|
376
|
+
if (!deployment) {
|
|
377
|
+
return {
|
|
378
|
+
success: false,
|
|
379
|
+
deploymentId: '',
|
|
380
|
+
projectId: project.projectId,
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
const streamId = complete?.streamId;
|
|
385
|
+
|
|
386
|
+
// Poll for deployment status with optional log streaming
|
|
387
|
+
const pollInterval = 500;
|
|
388
|
+
const maxAttempts = 600;
|
|
389
|
+
let attempts = 0;
|
|
390
|
+
|
|
391
|
+
if (streamId) {
|
|
392
|
+
// Use progress logger to stream logs while polling
|
|
393
|
+
const streamsUrl = getStreamURL(project.region, config);
|
|
394
|
+
|
|
395
|
+
await tui
|
|
396
|
+
.progress({
|
|
397
|
+
message: 'Deploying project...',
|
|
398
|
+
type: 'logger',
|
|
399
|
+
maxLines: 2,
|
|
400
|
+
clearOnSuccess: true,
|
|
401
|
+
callback: async (log) => {
|
|
402
|
+
// Start log streaming
|
|
403
|
+
const logStreamController = new AbortController();
|
|
404
|
+
const logStreamPromise = (async () => {
|
|
405
|
+
try {
|
|
406
|
+
logger.debug('fetching stream: %s/%s', streamsUrl, streamId);
|
|
407
|
+
const resp = await fetch(`${streamsUrl}/${streamId}`, {
|
|
408
|
+
signal: logStreamController.signal,
|
|
409
|
+
});
|
|
410
|
+
if (!resp.ok || !resp.body) {
|
|
411
|
+
ctx.logger.trace(
|
|
412
|
+
`Failed to connect to warmup log stream: ${resp.status}`
|
|
413
|
+
);
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
const reader = resp.body.getReader();
|
|
417
|
+
const decoder = new TextDecoder();
|
|
418
|
+
let buffer = '';
|
|
419
|
+
while (true) {
|
|
420
|
+
const { done, value } = await reader.read();
|
|
421
|
+
if (done) break;
|
|
422
|
+
buffer += decoder.decode(value, { stream: true });
|
|
423
|
+
const lines = buffer.split('\n');
|
|
424
|
+
buffer = lines.pop() || ''; // Keep incomplete line in buffer
|
|
425
|
+
for (const line of lines) {
|
|
426
|
+
// Strip ISO 8601 timestamp prefix if present
|
|
427
|
+
const message = line.replace(
|
|
428
|
+
/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+Z\s?/,
|
|
429
|
+
''
|
|
430
|
+
);
|
|
431
|
+
if (message) {
|
|
432
|
+
logs.push(message);
|
|
433
|
+
log(message);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
} catch (err) {
|
|
438
|
+
if (err instanceof Error && err.name === 'AbortError') {
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
ctx.logger.trace(`Warmup log stream error: ${err}`);
|
|
442
|
+
}
|
|
443
|
+
})();
|
|
444
|
+
|
|
445
|
+
// Poll for deployment status
|
|
446
|
+
while (attempts < maxAttempts) {
|
|
447
|
+
attempts++;
|
|
448
|
+
try {
|
|
449
|
+
statusResult = await projectDeploymentStatus(
|
|
450
|
+
apiClient,
|
|
451
|
+
deployment?.id ?? ''
|
|
452
|
+
);
|
|
453
|
+
|
|
454
|
+
logger.trace('status result: %s', statusResult);
|
|
455
|
+
|
|
456
|
+
if (statusResult.state === 'completed') {
|
|
457
|
+
logStreamController.abort();
|
|
458
|
+
break;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
if (statusResult.state === 'failed') {
|
|
462
|
+
throw new Error('Deployment failed');
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
await Bun.sleep(pollInterval);
|
|
466
|
+
} catch (err) {
|
|
467
|
+
logStreamController.abort();
|
|
468
|
+
throw err;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// Wait for log stream to finish
|
|
473
|
+
await logStreamPromise;
|
|
474
|
+
|
|
475
|
+
if (attempts >= maxAttempts) {
|
|
476
|
+
throw new Error('Deployment timed out');
|
|
477
|
+
}
|
|
478
|
+
},
|
|
479
|
+
})
|
|
480
|
+
.then(() => {
|
|
481
|
+
tui.success('Your project was deployed!');
|
|
482
|
+
})
|
|
483
|
+
.catch((ex) => {
|
|
484
|
+
const exwithmessage = ex as { message: string };
|
|
485
|
+
const msg =
|
|
486
|
+
exwithmessage.message === 'Deployment failed' ? '' : exwithmessage.toString();
|
|
487
|
+
tui.error(`Your deployment failed to start${msg ? `: ${msg}` : ''}`);
|
|
488
|
+
if (logs.length) {
|
|
489
|
+
const logsDir = join(getDefaultConfigDir(), 'logs');
|
|
490
|
+
if (!existsSync(logsDir)) {
|
|
491
|
+
mkdirSync(logsDir, { recursive: true });
|
|
492
|
+
}
|
|
493
|
+
const errorFile = join(logsDir, `${deployment?.id ?? Date.now()}.txt`);
|
|
494
|
+
writeFileSync(errorFile, logs.join('\n'));
|
|
495
|
+
const count = Math.min(logs.length, 10);
|
|
496
|
+
const last = logs.length - count;
|
|
497
|
+
tui.newline();
|
|
498
|
+
tui.warning(`The last ${count} lines of the log:`);
|
|
499
|
+
let offset = last + 1; // we want to show the offset from inside the log starting at 1
|
|
500
|
+
const max = String(logs.length).length;
|
|
501
|
+
for (const _log of logs.slice(last)) {
|
|
502
|
+
console.log(tui.muted(`${offset.toFixed().padEnd(max)} | ${_log}`));
|
|
503
|
+
offset++;
|
|
504
|
+
}
|
|
505
|
+
tui.newline();
|
|
506
|
+
tui.fatal(`The logs were written to ${errorFile}`, ErrorCode.BUILD_FAILED);
|
|
507
|
+
}
|
|
508
|
+
tui.fatal('Deployment failed', ErrorCode.BUILD_FAILED);
|
|
509
|
+
});
|
|
510
|
+
} else {
|
|
511
|
+
// No stream ID - poll without log streaming
|
|
512
|
+
await tui.spinner({
|
|
513
|
+
message: 'Deploying project...',
|
|
514
|
+
type: 'simple',
|
|
515
|
+
clearOnSuccess: true,
|
|
516
|
+
callback: async () => {
|
|
517
|
+
while (attempts < maxAttempts) {
|
|
518
|
+
attempts++;
|
|
519
|
+
statusResult = await projectDeploymentStatus(apiClient, deployment?.id ?? '');
|
|
520
|
+
|
|
521
|
+
if (statusResult.state === 'completed') {
|
|
522
|
+
break;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
if (statusResult.state === 'failed') {
|
|
526
|
+
throw new Error('Deployment failed');
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
await Bun.sleep(pollInterval);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
if (attempts >= maxAttempts) {
|
|
533
|
+
throw new Error('Deployment timed out');
|
|
534
|
+
}
|
|
535
|
+
},
|
|
536
|
+
});
|
|
537
|
+
|
|
538
|
+
tui.success('Your project was deployed!');
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// Show deployment URLs
|
|
542
|
+
if (complete?.publicUrls) {
|
|
373
543
|
tui.arrow(tui.bold(tui.padRight('Deployment ID:', 17)) + tui.link(deployment.id));
|
|
374
544
|
if (complete.publicUrls.custom?.length) {
|
|
375
545
|
for (const url of complete.publicUrls.custom) {
|
|
@@ -386,25 +556,18 @@ export const deploySubcommand = createSubcommand({
|
|
|
386
556
|
}
|
|
387
557
|
}
|
|
388
558
|
|
|
389
|
-
// Return deployment result (if available)
|
|
390
|
-
if (deployment && complete?.publicUrls) {
|
|
391
|
-
return {
|
|
392
|
-
success: true,
|
|
393
|
-
deploymentId: deployment.id,
|
|
394
|
-
projectId: project.projectId,
|
|
395
|
-
urls: {
|
|
396
|
-
deployment: complete.publicUrls.deployment,
|
|
397
|
-
latest: complete.publicUrls.latest,
|
|
398
|
-
custom: complete.publicUrls.custom,
|
|
399
|
-
},
|
|
400
|
-
};
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
// Fallback response
|
|
404
559
|
return {
|
|
405
|
-
success:
|
|
406
|
-
deploymentId:
|
|
560
|
+
success: true,
|
|
561
|
+
deploymentId: deployment.id,
|
|
407
562
|
projectId: project.projectId,
|
|
563
|
+
logs,
|
|
564
|
+
urls: complete?.publicUrls
|
|
565
|
+
? {
|
|
566
|
+
deployment: complete.publicUrls.deployment,
|
|
567
|
+
latest: complete.publicUrls.latest,
|
|
568
|
+
custom: complete.publicUrls.custom,
|
|
569
|
+
}
|
|
570
|
+
: undefined,
|
|
408
571
|
};
|
|
409
572
|
} catch (ex) {
|
|
410
573
|
tui.fatal(`unexpected error trying to deploy project. ${ex}`);
|
|
@@ -15,6 +15,10 @@ const DeploymentShowResponseSchema = z.object({
|
|
|
15
15
|
tags: z.array(z.string()).describe('Deployment tags'),
|
|
16
16
|
customDomains: z.array(z.string()).optional().describe('Custom domains'),
|
|
17
17
|
cloudRegion: z.string().optional().describe('Cloud region'),
|
|
18
|
+
resourceDb: z.string().nullable().optional().describe('the database name'),
|
|
19
|
+
resourceStorage: z.string().nullable().optional().describe('the storage name'),
|
|
20
|
+
deploymentLogsURL: z.string().nullable().optional().describe('the url to the deployment logs'),
|
|
21
|
+
buildLogsURL: z.string().nullable().optional().describe('the url to the build logs'),
|
|
18
22
|
metadata: z
|
|
19
23
|
.object({
|
|
20
24
|
git: z
|
|
@@ -87,27 +91,51 @@ export const showSubcommand = createSubcommand({
|
|
|
87
91
|
|
|
88
92
|
// Skip TUI output in JSON mode
|
|
89
93
|
if (!options.json) {
|
|
90
|
-
|
|
91
|
-
console.log(tui.bold('
|
|
92
|
-
console.log(tui.bold('
|
|
93
|
-
console.log(tui.bold('
|
|
94
|
-
console.log(tui.bold('
|
|
94
|
+
const maxWidth = 18;
|
|
95
|
+
console.log(tui.bold('ID:'.padEnd(maxWidth)) + deployment.id);
|
|
96
|
+
console.log(tui.bold('Project:'.padEnd(maxWidth)) + projectId);
|
|
97
|
+
console.log(tui.bold('State:'.padEnd(maxWidth)) + (deployment.state || 'unknown'));
|
|
98
|
+
console.log(tui.bold('Active:'.padEnd(maxWidth)) + (deployment.active ? 'Yes' : 'No'));
|
|
99
|
+
console.log(
|
|
100
|
+
tui.bold('Created:'.padEnd(maxWidth)) +
|
|
101
|
+
new Date(deployment.createdAt).toLocaleString()
|
|
102
|
+
);
|
|
95
103
|
if (deployment.updatedAt) {
|
|
96
104
|
console.log(
|
|
97
|
-
tui.bold('Updated:
|
|
105
|
+
tui.bold('Updated:'.padEnd(maxWidth)) +
|
|
106
|
+
new Date(deployment.updatedAt).toLocaleString()
|
|
98
107
|
);
|
|
99
108
|
}
|
|
100
109
|
if (deployment.message) {
|
|
101
|
-
console.log(tui.bold('Message:
|
|
110
|
+
console.log(tui.bold('Message:'.padEnd(maxWidth)) + deployment.message);
|
|
102
111
|
}
|
|
103
112
|
if (deployment.tags.length > 0) {
|
|
104
|
-
console.log(tui.bold('Tags:
|
|
113
|
+
console.log(tui.bold('Tags:'.padEnd(maxWidth)) + deployment.tags.join(', '));
|
|
105
114
|
}
|
|
106
115
|
if (deployment.customDomains && deployment.customDomains.length > 0) {
|
|
107
|
-
console.log(
|
|
116
|
+
console.log(
|
|
117
|
+
tui.bold('Domains:'.padEnd(maxWidth)) + deployment.customDomains.join(', ')
|
|
118
|
+
);
|
|
108
119
|
}
|
|
109
120
|
if (deployment.cloudRegion) {
|
|
110
|
-
console.log(tui.bold('Region:
|
|
121
|
+
console.log(tui.bold('Region:'.padEnd(maxWidth)) + deployment.cloudRegion);
|
|
122
|
+
}
|
|
123
|
+
if (deployment.resourceDb) {
|
|
124
|
+
console.log(tui.bold('Database:'.padEnd(maxWidth)) + deployment.resourceDb);
|
|
125
|
+
}
|
|
126
|
+
if (deployment.resourceStorage) {
|
|
127
|
+
console.log(tui.bold('Storage:'.padEnd(maxWidth)) + deployment.resourceStorage);
|
|
128
|
+
}
|
|
129
|
+
if (deployment.deploymentLogsURL) {
|
|
130
|
+
console.log(
|
|
131
|
+
tui.bold('Deployment Logs:'.padEnd(maxWidth)) +
|
|
132
|
+
tui.link(deployment.deploymentLogsURL)
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
if (deployment.buildLogsURL) {
|
|
136
|
+
console.log(
|
|
137
|
+
tui.bold('Build Logs:'.padEnd(maxWidth)) + tui.link(deployment.buildLogsURL)
|
|
138
|
+
);
|
|
111
139
|
}
|
|
112
140
|
|
|
113
141
|
// Git metadata
|
|
@@ -153,6 +181,10 @@ export const showSubcommand = createSubcommand({
|
|
|
153
181
|
customDomains: deployment.customDomains ?? undefined,
|
|
154
182
|
cloudRegion: deployment.cloudRegion ?? undefined,
|
|
155
183
|
metadata: deployment.metadata ?? undefined,
|
|
184
|
+
resourceDb: deployment.resourceDb ?? undefined,
|
|
185
|
+
resourceStorage: deployment.resourceStorage ?? undefined,
|
|
186
|
+
deploymentLogsURL: deployment.deploymentLogsURL ?? undefined,
|
|
187
|
+
buildLogsURL: deployment.buildLogsURL ?? undefined,
|
|
156
188
|
};
|
|
157
189
|
} catch (ex) {
|
|
158
190
|
tui.fatal(`Failed to show deployment: ${ex}`);
|
|
@@ -125,8 +125,8 @@ export const getSubcommand = createSubcommand({
|
|
|
125
125
|
response: SessionGetResponseSchema,
|
|
126
126
|
},
|
|
127
127
|
async handler(ctx) {
|
|
128
|
-
const {
|
|
129
|
-
const catalystClient = getCatalystAPIClient(
|
|
128
|
+
const { logger, auth, args, options, region } = ctx;
|
|
129
|
+
const catalystClient = getCatalystAPIClient(logger, auth, region);
|
|
130
130
|
|
|
131
131
|
try {
|
|
132
132
|
const enriched = await sessionGet(catalystClient, { id: args.session_id });
|
|
@@ -89,8 +89,8 @@ export const listSubcommand = createSubcommand({
|
|
|
89
89
|
response: SessionListResponseSchema,
|
|
90
90
|
},
|
|
91
91
|
async handler(ctx) {
|
|
92
|
-
const {
|
|
93
|
-
const catalystClient = getCatalystAPIClient(
|
|
92
|
+
const { logger, auth, project, opts, options, region } = ctx;
|
|
93
|
+
const catalystClient = getCatalystAPIClient(logger, auth, region);
|
|
94
94
|
|
|
95
95
|
const projectId = opts.projectId || project?.projectId;
|
|
96
96
|
|
|
@@ -35,7 +35,7 @@ export const createSubcommand = defineSubcommand({
|
|
|
35
35
|
},
|
|
36
36
|
|
|
37
37
|
async handler(ctx) {
|
|
38
|
-
const { logger, orgId, region,
|
|
38
|
+
const { logger, orgId, region, auth, options } = ctx;
|
|
39
39
|
|
|
40
40
|
// Handle dry-run mode
|
|
41
41
|
if (isDryRunMode(options)) {
|
|
@@ -51,7 +51,7 @@ export const createSubcommand = defineSubcommand({
|
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
const catalystClient = getCatalystAPIClient(
|
|
54
|
+
const catalystClient = getCatalystAPIClient(logger, auth, region);
|
|
55
55
|
|
|
56
56
|
const created = await tui.spinner({
|
|
57
57
|
message: `Creating storage in ${region}`,
|
|
@@ -49,9 +49,9 @@ export const deleteSubcommand = createSubcommand({
|
|
|
49
49
|
},
|
|
50
50
|
|
|
51
51
|
async handler(ctx) {
|
|
52
|
-
const { logger, args, opts,
|
|
52
|
+
const { logger, args, opts, orgId, region, auth, options } = ctx;
|
|
53
53
|
|
|
54
|
-
const catalystClient = getCatalystAPIClient(
|
|
54
|
+
const catalystClient = getCatalystAPIClient(logger, auth, region);
|
|
55
55
|
|
|
56
56
|
const resources = await tui.spinner({
|
|
57
57
|
message: `Fetching storage for ${orgId} in ${region}`,
|
|
@@ -51,9 +51,9 @@ export const downloadSubcommand = createSubcommand({
|
|
|
51
51
|
},
|
|
52
52
|
|
|
53
53
|
async handler(ctx) {
|
|
54
|
-
const { logger, args, opts, options, orgId, region,
|
|
54
|
+
const { logger, args, opts, options, orgId, region, auth } = ctx;
|
|
55
55
|
|
|
56
|
-
const catalystClient = getCatalystAPIClient(
|
|
56
|
+
const catalystClient = getCatalystAPIClient(logger, auth, region);
|
|
57
57
|
|
|
58
58
|
// Fetch bucket credentials
|
|
59
59
|
const resources = await tui.spinner({
|
|
@@ -51,9 +51,9 @@ export const getSubcommand = createSubcommand({
|
|
|
51
51
|
},
|
|
52
52
|
|
|
53
53
|
async handler(ctx) {
|
|
54
|
-
const { logger, args, opts, options, orgId, region,
|
|
54
|
+
const { logger, args, opts, options, orgId, region, auth } = ctx;
|
|
55
55
|
|
|
56
|
-
const catalystClient = getCatalystAPIClient(
|
|
56
|
+
const catalystClient = getCatalystAPIClient(logger, auth, region);
|
|
57
57
|
|
|
58
58
|
const resources = await tui.spinner({
|
|
59
59
|
message: `Fetching storage bucket ${args.name}`,
|
|
@@ -74,9 +74,9 @@ export const listSubcommand = createSubcommand({
|
|
|
74
74
|
},
|
|
75
75
|
|
|
76
76
|
async handler(ctx) {
|
|
77
|
-
const { logger, args, opts, options, orgId, region,
|
|
77
|
+
const { logger, args, opts, options, orgId, region, auth } = ctx;
|
|
78
78
|
|
|
79
|
-
const catalystClient = getCatalystAPIClient(
|
|
79
|
+
const catalystClient = getCatalystAPIClient(logger, auth, region);
|
|
80
80
|
|
|
81
81
|
const resources = await tui.spinner({
|
|
82
82
|
message: `Fetching storage for ${orgId} in ${region}`,
|
|
@@ -49,9 +49,9 @@ export const uploadSubcommand = createSubcommand({
|
|
|
49
49
|
},
|
|
50
50
|
|
|
51
51
|
async handler(ctx) {
|
|
52
|
-
const { logger, args, opts, options, orgId, region,
|
|
52
|
+
const { logger, args, opts, options, orgId, region, auth } = ctx;
|
|
53
53
|
|
|
54
|
-
const catalystClient = getCatalystAPIClient(
|
|
54
|
+
const catalystClient = getCatalystAPIClient(logger, auth, region);
|
|
55
55
|
|
|
56
56
|
// Fetch bucket credentials
|
|
57
57
|
const resources = await tui.spinner({
|
|
@@ -24,8 +24,8 @@ export const deleteSubcommand = createSubcommand({
|
|
|
24
24
|
}),
|
|
25
25
|
},
|
|
26
26
|
async handler(ctx) {
|
|
27
|
-
const {
|
|
28
|
-
const catalystClient = getCatalystAPIClient(
|
|
27
|
+
const { logger, auth, args, region } = ctx;
|
|
28
|
+
const catalystClient = getCatalystAPIClient(logger, auth, region);
|
|
29
29
|
|
|
30
30
|
try {
|
|
31
31
|
await threadDelete(catalystClient, { id: args.thread_id });
|
|
@@ -37,8 +37,8 @@ export const getSubcommand = createSubcommand({
|
|
|
37
37
|
response: ThreadGetResponseSchema,
|
|
38
38
|
},
|
|
39
39
|
async handler(ctx) {
|
|
40
|
-
const {
|
|
41
|
-
const catalystClient = getCatalystAPIClient(
|
|
40
|
+
const { logger, auth, args, options, region } = ctx;
|
|
41
|
+
const catalystClient = getCatalystAPIClient(logger, auth, region);
|
|
42
42
|
|
|
43
43
|
try {
|
|
44
44
|
const thread = await threadGet(catalystClient, { id: args.thread_id });
|
|
@@ -62,8 +62,8 @@ export const listSubcommand = createSubcommand({
|
|
|
62
62
|
response: ThreadListResponseSchema,
|
|
63
63
|
},
|
|
64
64
|
async handler(ctx) {
|
|
65
|
-
const {
|
|
66
|
-
const catalystClient = getCatalystAPIClient(
|
|
65
|
+
const { logger, auth, project, opts, options, region } = ctx;
|
|
66
|
+
const catalystClient = getCatalystAPIClient(logger, auth, region);
|
|
67
67
|
|
|
68
68
|
const projectId = opts.projectId || project?.projectId;
|
|
69
69
|
const orgId = opts.orgId;
|
package/src/cmd/dev/agents.ts
CHANGED
|
@@ -63,14 +63,12 @@ export const agentsSubcommand = createSubcommand({
|
|
|
63
63
|
const queryParams = deploymentId ? `?deploymentId=${deploymentId}` : '';
|
|
64
64
|
|
|
65
65
|
const response = options.json
|
|
66
|
-
? await apiClient.
|
|
67
|
-
'GET',
|
|
66
|
+
? await apiClient.get(
|
|
68
67
|
`/cli/agent/${projectId}${queryParams}`,
|
|
69
68
|
AgentsResponseSchema
|
|
70
69
|
)
|
|
71
70
|
: await tui.spinner('Fetching agents', async () => {
|
|
72
|
-
return apiClient.
|
|
73
|
-
'GET',
|
|
71
|
+
return apiClient.get(
|
|
74
72
|
`/cli/agent/${projectId}${queryParams}`,
|
|
75
73
|
AgentsResponseSchema
|
|
76
74
|
);
|
package/src/cmd/dev/sync.ts
CHANGED
|
@@ -253,11 +253,10 @@ class DevmodeSyncService implements IDevmodeSyncService {
|
|
|
253
253
|
JSON.stringify(payload, null, 2)
|
|
254
254
|
);
|
|
255
255
|
|
|
256
|
-
await this.apiClient.
|
|
257
|
-
'POST',
|
|
256
|
+
await this.apiClient.post(
|
|
258
257
|
'/cli/devmode/agent',
|
|
259
|
-
|
|
260
|
-
|
|
258
|
+
payload,
|
|
259
|
+
z.object({ success: z.boolean() })
|
|
261
260
|
);
|
|
262
261
|
}
|
|
263
262
|
|
|
@@ -280,11 +279,10 @@ class DevmodeSyncService implements IDevmodeSyncService {
|
|
|
280
279
|
JSON.stringify(payload, null, 2)
|
|
281
280
|
);
|
|
282
281
|
|
|
283
|
-
await this.apiClient.
|
|
284
|
-
'POST',
|
|
282
|
+
await this.apiClient.post(
|
|
285
283
|
'/cli/devmode/eval',
|
|
286
|
-
|
|
287
|
-
|
|
284
|
+
payload,
|
|
285
|
+
z.object({ success: z.boolean() })
|
|
288
286
|
);
|
|
289
287
|
}
|
|
290
288
|
}
|
package/src/cmd/project/show.ts
CHANGED
|
@@ -6,8 +6,10 @@ import { getCommand } from '../../command-prefix';
|
|
|
6
6
|
|
|
7
7
|
const ProjectShowResponseSchema = z.object({
|
|
8
8
|
id: z.string().describe('Project ID'),
|
|
9
|
+
name: z.string().describe('Project name'),
|
|
10
|
+
description: z.string().nullable().optional().describe('Project description'),
|
|
11
|
+
tags: z.array(z.string()).nullable().optional().describe('Project tags'),
|
|
9
12
|
orgId: z.string().describe('Organization ID'),
|
|
10
|
-
name: z.string().optional().describe('Project name'),
|
|
11
13
|
secrets: z.record(z.string(), z.string()).optional().describe('Project secrets (masked)'),
|
|
12
14
|
env: z.record(z.string(), z.string()).optional().describe('Environment variables'),
|
|
13
15
|
});
|
|
@@ -45,16 +47,16 @@ export const showSubcommand = createSubcommand({
|
|
|
45
47
|
tui.fatal('Project not found');
|
|
46
48
|
}
|
|
47
49
|
|
|
48
|
-
if (options.json) {
|
|
49
|
-
|
|
50
|
-
} else {
|
|
51
|
-
tui.table([project], ['id', 'orgId']);
|
|
50
|
+
if (!options.json) {
|
|
51
|
+
tui.table([project], ['id', 'name', 'description', 'tags', 'orgId']);
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
return {
|
|
55
55
|
id: project.id,
|
|
56
|
+
name: project.name,
|
|
57
|
+
description: project.description,
|
|
58
|
+
tags: project.tags,
|
|
56
59
|
orgId: project.orgId,
|
|
57
|
-
name: undefined,
|
|
58
60
|
secrets: project.secrets,
|
|
59
61
|
env: project.env,
|
|
60
62
|
};
|
|
@@ -177,7 +177,13 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
|
|
|
177
177
|
if (initialTemplate) {
|
|
178
178
|
const found = templates.find((t) => t.id === initialTemplate);
|
|
179
179
|
if (!found) {
|
|
180
|
-
|
|
180
|
+
const availableTemplates = templates
|
|
181
|
+
.map((t) => ` - ${t.id.padEnd(20)} ${t.description}`)
|
|
182
|
+
.join('\n');
|
|
183
|
+
logger.fatal(
|
|
184
|
+
`Template "${initialTemplate}" not found\n\nAvailable templates:\n${availableTemplates}`,
|
|
185
|
+
ErrorCode.RESOURCE_NOT_FOUND
|
|
186
|
+
);
|
|
181
187
|
return;
|
|
182
188
|
}
|
|
183
189
|
selectedTemplate = found;
|
|
@@ -232,7 +238,7 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
|
|
|
232
238
|
|
|
233
239
|
const resourceConfig: ResourcesTypes = Resources.parse({});
|
|
234
240
|
|
|
235
|
-
if (auth && apiClient && catalystClient && orgId && region) {
|
|
241
|
+
if (auth && apiClient && catalystClient && orgId && region && !skipPrompts) {
|
|
236
242
|
// Fetch resources for selected org and region using Catalyst API
|
|
237
243
|
const resources = await tui.spinner({
|
|
238
244
|
message: 'Fetching resources',
|
|
@@ -316,12 +322,25 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
|
|
|
316
322
|
|
|
317
323
|
const cloudRegion = region ?? process.env.AGENTUITY_REGION ?? 'usc';
|
|
318
324
|
|
|
325
|
+
const pkgJsonPath = resolve(dest, 'package.json');
|
|
326
|
+
let pkgJson: { description?: string; keywords?: string[] } = {};
|
|
327
|
+
if (existsSync(pkgJsonPath)) {
|
|
328
|
+
pkgJson = await Bun.file(pkgJsonPath).json();
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const keywords = Array.isArray(pkgJson.keywords) ? pkgJson.keywords : [];
|
|
332
|
+
const tags = keywords.filter(
|
|
333
|
+
(tag) => tag.toLowerCase() !== 'agentuity' && !tag.toLowerCase().startsWith('agentuity')
|
|
334
|
+
);
|
|
335
|
+
|
|
319
336
|
await tui.spinner({
|
|
320
337
|
message: 'Registering your project',
|
|
321
338
|
clearOnSuccess: true,
|
|
322
339
|
callback: async () => {
|
|
323
340
|
const project = await projectCreate(apiClient, {
|
|
324
341
|
name: projectName,
|
|
342
|
+
description: pkgJson.description,
|
|
343
|
+
tags: tags.length > 0 ? tags : undefined,
|
|
325
344
|
orgId,
|
|
326
345
|
cloudRegion,
|
|
327
346
|
});
|