@agentuity/cli 0.1.23 → 0.1.25
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/cli.d.ts.map +1 -1
- package/dist/cli.js +36 -5
- package/dist/cli.js.map +1 -1
- package/dist/cmd/ai/cadence/index.d.ts +3 -0
- package/dist/cmd/ai/cadence/index.d.ts.map +1 -0
- package/dist/cmd/ai/cadence/index.js +35 -0
- package/dist/cmd/ai/cadence/index.js.map +1 -0
- package/dist/cmd/ai/cadence/list.d.ts +3 -0
- package/dist/cmd/ai/cadence/list.d.ts.map +1 -0
- package/dist/cmd/ai/cadence/list.js +167 -0
- package/dist/cmd/ai/cadence/list.js.map +1 -0
- package/dist/cmd/ai/cadence/pause.d.ts +3 -0
- package/dist/cmd/ai/cadence/pause.d.ts.map +1 -0
- package/dist/cmd/ai/cadence/pause.js +103 -0
- package/dist/cmd/ai/cadence/pause.js.map +1 -0
- package/dist/cmd/ai/cadence/resume.d.ts +3 -0
- package/dist/cmd/ai/cadence/resume.d.ts.map +1 -0
- package/dist/cmd/ai/cadence/resume.js +106 -0
- package/dist/cmd/ai/cadence/resume.js.map +1 -0
- package/dist/cmd/ai/cadence/status.d.ts +3 -0
- package/dist/cmd/ai/cadence/status.d.ts.map +1 -0
- package/dist/cmd/ai/cadence/status.js +129 -0
- package/dist/cmd/ai/cadence/status.js.map +1 -0
- package/dist/cmd/ai/cadence/stop.d.ts +3 -0
- package/dist/cmd/ai/cadence/stop.d.ts.map +1 -0
- package/dist/cmd/ai/cadence/stop.js +107 -0
- package/dist/cmd/ai/cadence/stop.js.map +1 -0
- package/dist/cmd/ai/cadence/util.d.ts +44 -0
- package/dist/cmd/ai/cadence/util.d.ts.map +1 -0
- package/dist/cmd/ai/cadence/util.js +52 -0
- package/dist/cmd/ai/cadence/util.js.map +1 -0
- package/dist/cmd/ai/index.d.ts.map +1 -1
- package/dist/cmd/ai/index.js +9 -1
- package/dist/cmd/ai/index.js.map +1 -1
- package/dist/cmd/auth/machine/setup.js +1 -1
- package/dist/cmd/auth/machine/setup.js.map +1 -1
- package/dist/cmd/auth/ssh/add.js +1 -1
- package/dist/cmd/auth/ssh/add.js.map +1 -1
- package/dist/cmd/build/patch/index.d.ts.map +1 -1
- package/dist/cmd/build/patch/index.js +4 -0
- package/dist/cmd/build/patch/index.js.map +1 -1
- package/dist/cmd/build/patch/otel-llm.d.ts +10 -0
- package/dist/cmd/build/patch/otel-llm.d.ts.map +1 -0
- package/dist/cmd/build/patch/otel-llm.js +374 -0
- package/dist/cmd/build/patch/otel-llm.js.map +1 -0
- package/dist/cmd/cloud/db/create.js +3 -3
- package/dist/cmd/cloud/db/create.js.map +1 -1
- package/dist/cmd/cloud/deploy.d.ts.map +1 -1
- package/dist/cmd/cloud/deploy.js +55 -2
- package/dist/cmd/cloud/deploy.js.map +1 -1
- package/dist/cmd/cloud/env/pull.d.ts.map +1 -1
- package/dist/cmd/cloud/env/pull.js +26 -17
- package/dist/cmd/cloud/env/pull.js.map +1 -1
- package/dist/cmd/cloud/eval/get.d.ts +2 -0
- package/dist/cmd/cloud/eval/get.d.ts.map +1 -0
- package/dist/cmd/cloud/eval/get.js +79 -0
- package/dist/cmd/cloud/eval/get.js.map +1 -0
- package/dist/cmd/cloud/eval/index.d.ts +2 -0
- package/dist/cmd/cloud/eval/index.d.ts.map +1 -0
- package/dist/cmd/cloud/eval/index.js +15 -0
- package/dist/cmd/cloud/eval/index.js.map +1 -0
- package/dist/cmd/cloud/eval/list.d.ts +2 -0
- package/dist/cmd/cloud/eval/list.d.ts.map +1 -0
- package/dist/cmd/cloud/eval/list.js +119 -0
- package/dist/cmd/cloud/eval/list.js.map +1 -0
- package/dist/cmd/cloud/eval-run/get.d.ts +2 -0
- package/dist/cmd/cloud/eval-run/get.d.ts.map +1 -0
- package/dist/cmd/cloud/eval-run/get.js +106 -0
- package/dist/cmd/cloud/eval-run/get.js.map +1 -0
- package/dist/cmd/cloud/eval-run/index.d.ts +2 -0
- package/dist/cmd/cloud/eval-run/index.d.ts.map +1 -0
- package/dist/cmd/cloud/eval-run/index.js +15 -0
- package/dist/cmd/cloud/eval-run/index.js.map +1 -0
- package/dist/cmd/cloud/eval-run/list.d.ts +2 -0
- package/dist/cmd/cloud/eval-run/list.d.ts.map +1 -0
- package/dist/cmd/cloud/eval-run/list.js +144 -0
- package/dist/cmd/cloud/eval-run/list.js.map +1 -0
- package/dist/cmd/cloud/index.d.ts.map +1 -1
- package/dist/cmd/cloud/index.js +4 -0
- package/dist/cmd/cloud/index.js.map +1 -1
- package/dist/cmd/cloud/machine/list.d.ts.map +1 -1
- package/dist/cmd/cloud/machine/list.js +16 -0
- package/dist/cmd/cloud/machine/list.js.map +1 -1
- package/dist/cmd/cloud/queue/dlq.d.ts.map +1 -1
- package/dist/cmd/cloud/queue/dlq.js +15 -10
- package/dist/cmd/cloud/queue/dlq.js.map +1 -1
- package/dist/cmd/cloud/sandbox/download.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/download.js +8 -3
- package/dist/cmd/cloud/sandbox/download.js.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/build.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/build.js +43 -36
- package/dist/cmd/cloud/sandbox/snapshot/build.js.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/create.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/create.js +5 -1
- package/dist/cmd/cloud/sandbox/snapshot/create.js.map +1 -1
- package/dist/cmd/cloud/sandbox/upload.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/upload.js +8 -1
- package/dist/cmd/cloud/sandbox/upload.js.map +1 -1
- package/dist/cmd/cloud/storage/upload.js +1 -1
- package/dist/cmd/cloud/storage/upload.js.map +1 -1
- package/dist/cmd/cloud/vector/stats.d.ts.map +1 -1
- package/dist/cmd/cloud/vector/stats.js +3 -1
- package/dist/cmd/cloud/vector/stats.js.map +1 -1
- package/dist/cmd/cloud/vector/upsert.js +1 -1
- package/dist/cmd/cloud/vector/upsert.js.map +1 -1
- package/dist/cmd/profile/create.js +2 -2
- package/dist/cmd/profile/create.js.map +1 -1
- package/dist/cmd/project/create.d.ts.map +1 -1
- package/dist/cmd/project/create.js +6 -3
- package/dist/cmd/project/create.js.map +1 -1
- package/dist/cmd/project/delete.d.ts.map +1 -1
- package/dist/cmd/project/delete.js +46 -10
- package/dist/cmd/project/delete.js.map +1 -1
- package/dist/cmd/setup/index.d.ts.map +1 -1
- package/dist/cmd/setup/index.js +4 -1
- package/dist/cmd/setup/index.js.map +1 -1
- package/dist/env-util.d.ts.map +1 -1
- package/dist/env-util.js +4 -1
- package/dist/env-util.js.map +1 -1
- package/dist/schema-parser.d.ts +17 -1
- package/dist/schema-parser.d.ts.map +1 -1
- package/dist/schema-parser.js +131 -2
- package/dist/schema-parser.js.map +1 -1
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +4 -0
- package/dist/tui.js.map +1 -1
- package/dist/utils/deps.d.ts +8 -0
- package/dist/utils/deps.d.ts.map +1 -0
- package/dist/utils/deps.js +36 -0
- package/dist/utils/deps.js.map +1 -0
- package/package.json +6 -6
- package/src/cli.ts +36 -5
- package/src/cmd/ai/cadence/index.ts +36 -0
- package/src/cmd/ai/cadence/list.ts +183 -0
- package/src/cmd/ai/cadence/pause.ts +119 -0
- package/src/cmd/ai/cadence/resume.ts +124 -0
- package/src/cmd/ai/cadence/status.ts +141 -0
- package/src/cmd/ai/cadence/stop.ts +124 -0
- package/src/cmd/ai/cadence/util.ts +86 -0
- package/src/cmd/ai/index.ts +9 -1
- package/src/cmd/auth/machine/setup.ts +1 -1
- package/src/cmd/auth/ssh/add.ts +1 -1
- package/src/cmd/build/patch/index.ts +4 -0
- package/src/cmd/build/patch/otel-llm.ts +421 -0
- package/src/cmd/cloud/db/create.ts +3 -3
- package/src/cmd/cloud/deploy.ts +77 -1
- package/src/cmd/cloud/env/pull.ts +29 -19
- package/src/cmd/cloud/eval/get.ts +85 -0
- package/src/cmd/cloud/eval/index.ts +15 -0
- package/src/cmd/cloud/eval/list.ts +129 -0
- package/src/cmd/cloud/eval-run/get.ts +113 -0
- package/src/cmd/cloud/eval-run/index.ts +15 -0
- package/src/cmd/cloud/eval-run/list.ts +154 -0
- package/src/cmd/cloud/index.ts +4 -0
- package/src/cmd/cloud/machine/list.ts +16 -0
- package/src/cmd/cloud/queue/dlq.ts +16 -10
- package/src/cmd/cloud/sandbox/download.ts +9 -3
- package/src/cmd/cloud/sandbox/snapshot/build.ts +64 -45
- package/src/cmd/cloud/sandbox/snapshot/create.ts +5 -1
- package/src/cmd/cloud/sandbox/upload.ts +9 -1
- package/src/cmd/cloud/storage/upload.ts +1 -1
- package/src/cmd/cloud/vector/stats.ts +3 -1
- package/src/cmd/cloud/vector/upsert.ts +1 -1
- package/src/cmd/profile/create.ts +2 -2
- package/src/cmd/project/create.ts +6 -3
- package/src/cmd/project/delete.ts +55 -10
- package/src/cmd/setup/index.ts +4 -1
- package/src/env-util.ts +4 -1
- package/src/schema-parser.ts +150 -2
- package/src/tui.ts +5 -0
- package/src/utils/deps.ts +54 -0
|
@@ -138,7 +138,8 @@ function parseKeyValueArgs(args: string[] | undefined): Record<string, string> {
|
|
|
138
138
|
|
|
139
139
|
function substituteVariables(
|
|
140
140
|
values: Record<string, string>,
|
|
141
|
-
variables: Record<string, string
|
|
141
|
+
variables: Record<string, string>,
|
|
142
|
+
flagName: 'env' | 'metadata'
|
|
142
143
|
): Record<string, string> {
|
|
143
144
|
const result: Record<string, string> = {};
|
|
144
145
|
const varPattern = /\$\{([^}]+)\}/g;
|
|
@@ -152,7 +153,7 @@ function substituteVariables(
|
|
|
152
153
|
const varName = match[1];
|
|
153
154
|
if (!(varName in variables)) {
|
|
154
155
|
throw new Error(
|
|
155
|
-
`Variable "\${${varName}}" in "${key}" is not defined. Use
|
|
156
|
+
`Variable "\${${varName}}" in "${key}" is not defined. Use --${flagName} ${varName}=value to provide it.`
|
|
156
157
|
);
|
|
157
158
|
}
|
|
158
159
|
substituted = substituted.replace(match[0], variables[varName]);
|
|
@@ -163,12 +164,15 @@ function substituteVariables(
|
|
|
163
164
|
return result;
|
|
164
165
|
}
|
|
165
166
|
|
|
167
|
+
// Default patterns that are always excluded from snapshot builds
|
|
168
|
+
const DEFAULT_EXCLUSIONS = ['.git/**', 'node_modules/**', '.agentuity/**', '.env*'];
|
|
169
|
+
|
|
166
170
|
async function resolveFileGlobs(
|
|
167
171
|
directory: string,
|
|
168
172
|
patterns: string[]
|
|
169
173
|
): Promise<Map<string, FileEntry>> {
|
|
170
174
|
const files = new Map<string, FileEntry>();
|
|
171
|
-
const exclusions: string[] = [];
|
|
175
|
+
const exclusions: string[] = [...DEFAULT_EXCLUSIONS];
|
|
172
176
|
const inclusions: string[] = [];
|
|
173
177
|
|
|
174
178
|
for (const pattern of patterns) {
|
|
@@ -200,15 +204,19 @@ async function resolveFileGlobs(
|
|
|
200
204
|
}
|
|
201
205
|
|
|
202
206
|
for (let pattern of exclusions) {
|
|
203
|
-
// If
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
207
|
+
// If pattern already contains glob wildcards, use it as-is
|
|
208
|
+
// Otherwise, check if it refers to a directory and auto-append /** to exclude all contents
|
|
209
|
+
const hasGlobChars = /[*?[\]]/.test(pattern);
|
|
210
|
+
if (!hasGlobChars) {
|
|
211
|
+
const patternPath = join(directory, pattern);
|
|
212
|
+
try {
|
|
213
|
+
const stat = statSync(patternPath);
|
|
214
|
+
if (stat.isDirectory()) {
|
|
215
|
+
pattern = pattern.endsWith('/') ? `${pattern}**` : `${pattern}/**`;
|
|
216
|
+
}
|
|
217
|
+
} catch {
|
|
218
|
+
// Path doesn't exist or can't be stat'd, use pattern as-is
|
|
209
219
|
}
|
|
210
|
-
} catch {
|
|
211
|
-
// Path doesn't exist or can't be stat'd, use pattern as-is
|
|
212
220
|
}
|
|
213
221
|
|
|
214
222
|
const glob = new Bun.Glob(pattern);
|
|
@@ -379,37 +387,6 @@ export const buildSubcommand = createCommand({
|
|
|
379
387
|
const { args, opts, options, auth, region, config, logger, orgId } = ctx;
|
|
380
388
|
|
|
381
389
|
const dryRun = options.dryRun === true;
|
|
382
|
-
const isPublic = opts.public === true;
|
|
383
|
-
|
|
384
|
-
if (isPublic && !dryRun) {
|
|
385
|
-
if (!opts.confirm) {
|
|
386
|
-
if (!tui.isTTYLike()) {
|
|
387
|
-
logger.fatal(
|
|
388
|
-
`Publishing a public snapshot requires confirmation.\n\n` +
|
|
389
|
-
`Public snapshots make all environment variables and files publicly accessible.\n\n` +
|
|
390
|
-
`To proceed, add the --confirm flag:\n` +
|
|
391
|
-
` ${getCommand('cloud sandbox snapshot build . --public --confirm')}\n\n` +
|
|
392
|
-
`To preview what will be published, use --dry-run first:\n` +
|
|
393
|
-
` ${getCommand('cloud sandbox snapshot build . --public --dry-run')}`
|
|
394
|
-
);
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
tui.warningBox(
|
|
398
|
-
'Public Snapshot',
|
|
399
|
-
`You are publishing a public snapshot.\n\n` +
|
|
400
|
-
`This will make all environment variables and\n` +
|
|
401
|
-
`files in the snapshot publicly accessible.\n\n` +
|
|
402
|
-
`Run with --dry-run to preview the contents.`
|
|
403
|
-
);
|
|
404
|
-
console.log('');
|
|
405
|
-
|
|
406
|
-
const confirmed = await tui.confirm('Proceed with public snapshot?', false);
|
|
407
|
-
|
|
408
|
-
if (!confirmed) {
|
|
409
|
-
logger.fatal('Aborted');
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
390
|
|
|
414
391
|
const directory = resolve(args.directory);
|
|
415
392
|
if (!existsSync(directory)) {
|
|
@@ -470,6 +447,40 @@ export const buildSubcommand = createCommand({
|
|
|
470
447
|
|
|
471
448
|
const buildConfig = validationResult.data;
|
|
472
449
|
|
|
450
|
+
// Determine if snapshot is public: CLI flag takes precedence, otherwise use build file
|
|
451
|
+
const isPublic =
|
|
452
|
+
opts.public === true || (opts.public === undefined && buildConfig.public === true);
|
|
453
|
+
|
|
454
|
+
if (isPublic && !dryRun) {
|
|
455
|
+
if (!opts.confirm) {
|
|
456
|
+
if (!tui.isTTYLike()) {
|
|
457
|
+
logger.fatal(
|
|
458
|
+
`Publishing a public snapshot requires confirmation.\n\n` +
|
|
459
|
+
`Public snapshots make all environment variables and files publicly accessible.\n\n` +
|
|
460
|
+
`To proceed, add the --confirm flag:\n` +
|
|
461
|
+
` ${getCommand('cloud sandbox snapshot build . --public --confirm')}\n\n` +
|
|
462
|
+
`To preview what will be published, use --dry-run first:\n` +
|
|
463
|
+
` ${getCommand('cloud sandbox snapshot build . --public --dry-run')}`
|
|
464
|
+
);
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
tui.warningBox(
|
|
468
|
+
'Public Snapshot',
|
|
469
|
+
`You are publishing a public snapshot.\n\n` +
|
|
470
|
+
`This will make all environment variables and\n` +
|
|
471
|
+
`files in the snapshot publicly accessible.\n\n` +
|
|
472
|
+
`Run with --dry-run to preview the contents.`
|
|
473
|
+
);
|
|
474
|
+
console.log('');
|
|
475
|
+
|
|
476
|
+
const confirmed = await tui.confirm('Proceed with public snapshot?', false);
|
|
477
|
+
|
|
478
|
+
if (!confirmed) {
|
|
479
|
+
logger.fatal('Aborted');
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
473
484
|
if (opts.tag) {
|
|
474
485
|
if (opts.tag.length > MAX_SNAPSHOT_TAG_LENGTH) {
|
|
475
486
|
logger.fatal(
|
|
@@ -502,10 +513,14 @@ export const buildSubcommand = createCommand({
|
|
|
502
513
|
|
|
503
514
|
try {
|
|
504
515
|
if (buildConfig.env) {
|
|
505
|
-
finalEnv = substituteVariables(buildConfig.env, envSubstitutions);
|
|
516
|
+
finalEnv = substituteVariables(buildConfig.env, envSubstitutions, 'env');
|
|
506
517
|
}
|
|
507
518
|
if (buildConfig.metadata) {
|
|
508
|
-
finalMetadata = substituteVariables(
|
|
519
|
+
finalMetadata = substituteVariables(
|
|
520
|
+
buildConfig.metadata,
|
|
521
|
+
metadataSubstitutions,
|
|
522
|
+
'metadata'
|
|
523
|
+
);
|
|
509
524
|
}
|
|
510
525
|
} catch (err) {
|
|
511
526
|
logger.fatal(err instanceof Error ? err.message : String(err));
|
|
@@ -811,7 +826,11 @@ export const buildSubcommand = createCommand({
|
|
|
811
826
|
clearOnError: true,
|
|
812
827
|
callback: async (updateProgress) => {
|
|
813
828
|
const uploadFile = Bun.file(uploadPath);
|
|
814
|
-
const progressStream = createProgressStream(
|
|
829
|
+
const progressStream = createProgressStream(
|
|
830
|
+
uploadFile,
|
|
831
|
+
uploadSize,
|
|
832
|
+
updateProgress
|
|
833
|
+
);
|
|
815
834
|
await snapshotUpload(client, {
|
|
816
835
|
snapshotId: initResult.snapshotId!,
|
|
817
836
|
body: progressStream,
|
|
@@ -55,7 +55,11 @@ export const createSubcommand = createCommand({
|
|
|
55
55
|
.describe('Display name for the snapshot (letters, numbers, underscores, dashes only)'),
|
|
56
56
|
description: z.string().optional().describe('Description of the snapshot'),
|
|
57
57
|
tag: z.string().optional().describe('Tag for the snapshot (defaults to "latest")'),
|
|
58
|
-
public: z
|
|
58
|
+
public: z
|
|
59
|
+
.boolean()
|
|
60
|
+
.optional()
|
|
61
|
+
.default(false)
|
|
62
|
+
.describe('Make the snapshot publicly accessible'),
|
|
59
63
|
}),
|
|
60
64
|
response: SnapshotCreateResponseSchema,
|
|
61
65
|
},
|
|
@@ -58,11 +58,13 @@ export const uploadSubcommand = createCommand({
|
|
|
58
58
|
const content = readFileSync(args.archive);
|
|
59
59
|
const bytes = content.length;
|
|
60
60
|
|
|
61
|
+
const format = opts.format ?? detectFormat(args.archive);
|
|
62
|
+
|
|
61
63
|
await sandboxUploadArchive(client, {
|
|
62
64
|
sandboxId: args.sandboxId,
|
|
63
65
|
archive: content,
|
|
64
66
|
path: opts.path || '.',
|
|
65
|
-
format
|
|
67
|
+
format,
|
|
66
68
|
orgId,
|
|
67
69
|
});
|
|
68
70
|
|
|
@@ -81,4 +83,10 @@ function formatSize(bytes: number): string {
|
|
|
81
83
|
return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
|
|
82
84
|
}
|
|
83
85
|
|
|
86
|
+
function detectFormat(filename: string): 'zip' | 'tar.gz' {
|
|
87
|
+
const lower = filename.toLowerCase();
|
|
88
|
+
if (lower.endsWith('.zip')) return 'zip';
|
|
89
|
+
return 'tar.gz';
|
|
90
|
+
}
|
|
91
|
+
|
|
84
92
|
export default uploadSubcommand;
|
|
@@ -13,7 +13,7 @@ export const uploadSubcommand = createSubcommand({
|
|
|
13
13
|
name: 'upload',
|
|
14
14
|
aliases: ['put'],
|
|
15
15
|
description: 'Upload a file to storage bucket',
|
|
16
|
-
tags: ['write', 'requires-auth'],
|
|
16
|
+
tags: ['write', 'requires-auth', 'uses-stdin'],
|
|
17
17
|
requires: { auth: true },
|
|
18
18
|
optional: { org: true },
|
|
19
19
|
idempotent: false,
|
|
@@ -22,7 +22,9 @@ const VectorNamespaceStatsSchema = z.object({
|
|
|
22
22
|
});
|
|
23
23
|
|
|
24
24
|
const VectorStatsPaginatedSchema = z.object({
|
|
25
|
-
namespaces: z
|
|
25
|
+
namespaces: z
|
|
26
|
+
.record(z.string(), VectorNamespaceStatsSchema)
|
|
27
|
+
.describe('Map of namespace names to their statistics'),
|
|
26
28
|
total: z.number().describe('Total number of namespaces across all pages'),
|
|
27
29
|
limit: z.number().describe('Number of namespaces requested per page'),
|
|
28
30
|
offset: z.number().describe('Number of namespaces skipped'),
|
|
@@ -24,7 +24,7 @@ export const upsertSubcommand = createCommand({
|
|
|
24
24
|
name: 'upsert',
|
|
25
25
|
aliases: ['put', 'add'],
|
|
26
26
|
description: 'Add or update vectors in the vector storage',
|
|
27
|
-
tags: ['mutating', 'updates-resource', 'slow', 'requires-auth'],
|
|
27
|
+
tags: ['mutating', 'updates-resource', 'slow', 'requires-auth', 'uses-stdin'],
|
|
28
28
|
idempotent: true,
|
|
29
29
|
requires: { auth: true, region: true },
|
|
30
30
|
optional: { project: true },
|
|
@@ -24,9 +24,9 @@ export const createCommand = createSubcommand({
|
|
|
24
24
|
aliases: ['new'],
|
|
25
25
|
idempotent: false,
|
|
26
26
|
examples: [
|
|
27
|
-
{ command: getCommand('profile create production'), description: 'Create new
|
|
27
|
+
{ command: getCommand('profile create production'), description: 'Create new profile' },
|
|
28
28
|
{ command: getCommand('profile create staging --switch'), description: 'Use switch option' },
|
|
29
|
-
{ command: getCommand('profile create development'), description: 'Create new
|
|
29
|
+
{ command: getCommand('profile create development'), description: 'Create new profile' },
|
|
30
30
|
],
|
|
31
31
|
schema: {
|
|
32
32
|
args: z
|
|
@@ -27,11 +27,14 @@ export const createProjectSubcommand = createSubcommand({
|
|
|
27
27
|
idempotent: false,
|
|
28
28
|
optional: { auth: true, region: true, apiClient: true },
|
|
29
29
|
examples: [
|
|
30
|
-
{ command: getCommand('project create'), description: 'Create new
|
|
31
|
-
{
|
|
30
|
+
{ command: getCommand('project create'), description: 'Create new project' },
|
|
31
|
+
{
|
|
32
|
+
command: getCommand('project create --name my-ai-agent'),
|
|
33
|
+
description: 'Create new project',
|
|
34
|
+
},
|
|
32
35
|
{
|
|
33
36
|
command: getCommand('project create --name customer-service-bot --dir ~/projects/agent'),
|
|
34
|
-
description: 'Create new
|
|
37
|
+
description: 'Create new project',
|
|
35
38
|
},
|
|
36
39
|
{
|
|
37
40
|
command: getCommand('project create --template basic --no-install'),
|
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { createSubcommand } from '../../types';
|
|
3
3
|
import * as tui from '../../tui';
|
|
4
|
-
import { projectDelete, projectList } from '@agentuity/server';
|
|
4
|
+
import { projectDelete, projectList, projectGet } from '@agentuity/server';
|
|
5
5
|
import enquirer from 'enquirer';
|
|
6
6
|
import { getCommand } from '../../command-prefix';
|
|
7
7
|
|
|
8
|
+
interface ProjectDisplayInfo {
|
|
9
|
+
id: string;
|
|
10
|
+
name: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function formatProjectDisplay(project: ProjectDisplayInfo): string {
|
|
14
|
+
return `${project.name} (${project.id})`;
|
|
15
|
+
}
|
|
16
|
+
|
|
8
17
|
export const deleteSubcommand = createSubcommand({
|
|
9
18
|
name: 'delete',
|
|
10
19
|
description: 'Delete a project',
|
|
@@ -46,11 +55,37 @@ export const deleteSubcommand = createSubcommand({
|
|
|
46
55
|
async handler(ctx) {
|
|
47
56
|
const { args, opts, apiClient } = ctx;
|
|
48
57
|
|
|
49
|
-
let
|
|
58
|
+
let projectsToDelete: ProjectDisplayInfo[] = [];
|
|
50
59
|
|
|
51
60
|
if (args.id) {
|
|
52
|
-
// Command line argument provided
|
|
53
|
-
|
|
61
|
+
// Command line argument provided - validate and fetch project details
|
|
62
|
+
const projectInfo = await tui.spinner({
|
|
63
|
+
message: 'Fetching project details',
|
|
64
|
+
clearOnSuccess: true,
|
|
65
|
+
callback: async () => {
|
|
66
|
+
try {
|
|
67
|
+
const project = await projectGet(apiClient, {
|
|
68
|
+
id: args.id!,
|
|
69
|
+
mask: true,
|
|
70
|
+
keys: false,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
id: project.id,
|
|
75
|
+
name: project.name,
|
|
76
|
+
};
|
|
77
|
+
} catch {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
if (!projectInfo) {
|
|
84
|
+
tui.error(`Project not found: ${args.id}`);
|
|
85
|
+
return { success: false, projectIds: [], count: 0 };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
projectsToDelete = [projectInfo];
|
|
54
89
|
} else {
|
|
55
90
|
// Check TTY before attempting to prompt
|
|
56
91
|
if (!process.stdin.isTTY) {
|
|
@@ -87,10 +122,16 @@ export const deleteSubcommand = createSubcommand({
|
|
|
87
122
|
choices,
|
|
88
123
|
});
|
|
89
124
|
|
|
90
|
-
|
|
125
|
+
// Map selected IDs to full project info
|
|
126
|
+
projectsToDelete = response.projects
|
|
127
|
+
.map((id) => {
|
|
128
|
+
const project = projects.find((p) => p.id === id);
|
|
129
|
+
return project ? { id: project.id, name: project.name } : null;
|
|
130
|
+
})
|
|
131
|
+
.filter((p): p is ProjectDisplayInfo => p !== null);
|
|
91
132
|
}
|
|
92
133
|
|
|
93
|
-
if (
|
|
134
|
+
if (projectsToDelete.length === 0) {
|
|
94
135
|
tui.info('No projects selected for deletion');
|
|
95
136
|
return { success: false, projectIds: [], count: 0 };
|
|
96
137
|
}
|
|
@@ -103,13 +144,16 @@ export const deleteSubcommand = createSubcommand({
|
|
|
103
144
|
|
|
104
145
|
// Confirm deletion
|
|
105
146
|
if (!skipConfirm) {
|
|
106
|
-
const
|
|
107
|
-
|
|
147
|
+
const projectDisplay =
|
|
148
|
+
projectsToDelete.length === 1
|
|
149
|
+
? formatProjectDisplay(projectsToDelete[0])
|
|
150
|
+
: projectsToDelete.map((p) => `\n • ${formatProjectDisplay(p)}`).join('');
|
|
151
|
+
tui.warning(`You are about to delete: ${tui.bold(projectDisplay)}`);
|
|
108
152
|
|
|
109
153
|
const confirm = await enquirer.prompt<{ confirm: boolean }>({
|
|
110
154
|
type: 'confirm',
|
|
111
155
|
name: 'confirm',
|
|
112
|
-
message: `Are you sure you want to delete ${
|
|
156
|
+
message: `Are you sure you want to delete ${projectsToDelete.length > 1 ? 'these projects' : 'this project'}?`,
|
|
113
157
|
initial: false,
|
|
114
158
|
});
|
|
115
159
|
|
|
@@ -119,8 +163,9 @@ export const deleteSubcommand = createSubcommand({
|
|
|
119
163
|
}
|
|
120
164
|
}
|
|
121
165
|
|
|
166
|
+
const projectIds = projectsToDelete.map((p) => p.id);
|
|
122
167
|
const deleted = await tui.spinner({
|
|
123
|
-
message: `Deleting ${
|
|
168
|
+
message: `Deleting ${projectsToDelete.length} project(s)`,
|
|
124
169
|
clearOnSuccess: true,
|
|
125
170
|
callback: async () => {
|
|
126
171
|
return projectDelete(apiClient, ...projectIds);
|
package/src/cmd/setup/index.ts
CHANGED
|
@@ -41,7 +41,10 @@ export const command = createCommand({
|
|
|
41
41
|
// Use process.execPath which has the actual binary path
|
|
42
42
|
const isCompiledBinary = process.argv[1]?.startsWith('/$bunfs/');
|
|
43
43
|
const cmd = isCompiledBinary
|
|
44
|
-
? [
|
|
44
|
+
? [
|
|
45
|
+
process.execPath,
|
|
46
|
+
...process.argv.slice(2).map((x) => (x === 'setup' ? 'login' : x)),
|
|
47
|
+
]
|
|
45
48
|
: process.argv.map((x) => (x === 'setup' ? 'login' : x));
|
|
46
49
|
const r = Bun.spawn({
|
|
47
50
|
cmd: cmd.concat('--json'),
|
package/src/env-util.ts
CHANGED
|
@@ -17,7 +17,10 @@ export const PUBLIC_VAR_PREFIXES = ['VITE_', 'AGENTUITY_PUBLIC_', 'PUBLIC_'] as
|
|
|
17
17
|
* Specific AGENTUITY_ keys that are allowed to be set by users.
|
|
18
18
|
* Note: There is also a whitelist in the API that must be kept in sync.
|
|
19
19
|
*/
|
|
20
|
-
export const AGENTUITY_ALLOWED_KEYS = [
|
|
20
|
+
export const AGENTUITY_ALLOWED_KEYS = [
|
|
21
|
+
'AGENTUITY_AUTH_SECRET',
|
|
22
|
+
'AGENTUITY_CLOUD_BASE_URL',
|
|
23
|
+
] as const;
|
|
21
24
|
|
|
22
25
|
/**
|
|
23
26
|
* Check if a key is a public variable (exposed to frontend)
|
package/src/schema-parser.ts
CHANGED
|
@@ -254,10 +254,119 @@ export function parseOptionsSchema(schema: ZodType): ParsedOption[] {
|
|
|
254
254
|
return options;
|
|
255
255
|
}
|
|
256
256
|
|
|
257
|
+
// Cache for stdin confirmation detection
|
|
258
|
+
let stdinConfirmationChecked = false;
|
|
259
|
+
let stdinConfirmation: boolean | null = null;
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Check if stdin contains a piped "yes" confirmation.
|
|
263
|
+
* This allows commands to be run with `echo "yes" | agentuity <command>` pattern.
|
|
264
|
+
* Only works when stdin is not a TTY (piped input) and command doesn't use stdin.
|
|
265
|
+
*/
|
|
266
|
+
async function checkStdinConfirmation(): Promise<boolean> {
|
|
267
|
+
if (stdinConfirmationChecked) {
|
|
268
|
+
return stdinConfirmation === true;
|
|
269
|
+
}
|
|
270
|
+
stdinConfirmationChecked = true;
|
|
271
|
+
|
|
272
|
+
// Only check if stdin is not a TTY (meaning input is piped)
|
|
273
|
+
if (process.stdin.isTTY) {
|
|
274
|
+
stdinConfirmation = null;
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
try {
|
|
279
|
+
// Read stdin with a short timeout to avoid blocking
|
|
280
|
+
const reader = process.stdin;
|
|
281
|
+
let timeoutId: ReturnType<typeof setTimeout> | null = null;
|
|
282
|
+
let resolved = false;
|
|
283
|
+
const MAX_BYTES = 4096;
|
|
284
|
+
|
|
285
|
+
// Define handlers outside so we can remove them in all paths
|
|
286
|
+
let data = '';
|
|
287
|
+
const onData = (chunk: Buffer) => {
|
|
288
|
+
data += chunk.toString();
|
|
289
|
+
if (data.length >= MAX_BYTES) {
|
|
290
|
+
data = data.slice(0, MAX_BYTES);
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
let onEnd: (() => void) | null = null;
|
|
295
|
+
let onError: ((err: Error) => void) | null = null;
|
|
296
|
+
|
|
297
|
+
const cleanup = () => {
|
|
298
|
+
reader.removeListener('data', onData);
|
|
299
|
+
if (onEnd) {
|
|
300
|
+
reader.removeListener('end', onEnd);
|
|
301
|
+
}
|
|
302
|
+
if (onError) {
|
|
303
|
+
reader.removeListener('error', onError);
|
|
304
|
+
}
|
|
305
|
+
reader.pause();
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
const readPromise = new Promise<string>((resolve) => {
|
|
309
|
+
onEnd = () => {
|
|
310
|
+
if (resolved) return;
|
|
311
|
+
resolved = true;
|
|
312
|
+
if (timeoutId !== null) {
|
|
313
|
+
clearTimeout(timeoutId);
|
|
314
|
+
timeoutId = null;
|
|
315
|
+
}
|
|
316
|
+
cleanup();
|
|
317
|
+
resolve(data.trim().toLowerCase());
|
|
318
|
+
};
|
|
319
|
+
onError = (_err: Error) => {
|
|
320
|
+
if (resolved) return;
|
|
321
|
+
resolved = true;
|
|
322
|
+
stdinConfirmation = null;
|
|
323
|
+
if (timeoutId !== null) {
|
|
324
|
+
clearTimeout(timeoutId);
|
|
325
|
+
timeoutId = null;
|
|
326
|
+
}
|
|
327
|
+
cleanup();
|
|
328
|
+
resolve('');
|
|
329
|
+
};
|
|
330
|
+
reader.on('data', onData);
|
|
331
|
+
reader.on('end', onEnd);
|
|
332
|
+
reader.on('error', onError);
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
// Use a short timeout to avoid blocking
|
|
336
|
+
const timeoutPromise = new Promise<string>((resolve) => {
|
|
337
|
+
timeoutId = setTimeout(() => {
|
|
338
|
+
if (resolved) return;
|
|
339
|
+
resolved = true;
|
|
340
|
+
// Clean up listeners and pause stdin when timeout wins
|
|
341
|
+
cleanup();
|
|
342
|
+
resolve('');
|
|
343
|
+
}, 100);
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
const input = await Promise.race([readPromise, timeoutPromise]);
|
|
347
|
+
// Take first token/line to handle inputs like "yes\nanything"
|
|
348
|
+
const firstToken = input.split(/\s+/)[0] ?? '';
|
|
349
|
+
stdinConfirmation = firstToken === 'yes' || firstToken === 'y';
|
|
350
|
+
return stdinConfirmation;
|
|
351
|
+
} catch {
|
|
352
|
+
stdinConfirmation = null;
|
|
353
|
+
return false;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Reset stdin confirmation cache (for testing)
|
|
359
|
+
*/
|
|
360
|
+
export function resetStdinConfirmationCache(): void {
|
|
361
|
+
stdinConfirmationChecked = false;
|
|
362
|
+
stdinConfirmation = null;
|
|
363
|
+
}
|
|
364
|
+
|
|
257
365
|
export function buildValidationInput(
|
|
258
366
|
schemas: CommandSchemas,
|
|
259
367
|
rawArgs: unknown[],
|
|
260
|
-
rawOptions: Record<string, unknown
|
|
368
|
+
rawOptions: Record<string, unknown>,
|
|
369
|
+
_options?: { usesStdin?: boolean }
|
|
261
370
|
): { args: Record<string, unknown>; options: Record<string, unknown> } {
|
|
262
371
|
const result = { args: {} as Record<string, unknown>, options: {} as Record<string, unknown> };
|
|
263
372
|
|
|
@@ -274,7 +383,13 @@ export function buildValidationInput(
|
|
|
274
383
|
// Only include the option if it has a value - omitting undefined allows Zod to apply defaults
|
|
275
384
|
// Commander.js converts kebab-case to camelCase, so we need to check both
|
|
276
385
|
const camelCaseName = opt.name.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
277
|
-
|
|
386
|
+
let value = rawOptions[opt.name] ?? rawOptions[camelCaseName];
|
|
387
|
+
|
|
388
|
+
// Handle --yes alias for --confirm: if confirm is not set but yes is, use yes value
|
|
389
|
+
if (opt.name === 'confirm' && value === undefined && rawOptions.yes === true) {
|
|
390
|
+
value = true;
|
|
391
|
+
}
|
|
392
|
+
|
|
278
393
|
if (value !== undefined) {
|
|
279
394
|
result.options[opt.name] = value;
|
|
280
395
|
}
|
|
@@ -283,3 +398,36 @@ export function buildValidationInput(
|
|
|
283
398
|
|
|
284
399
|
return result;
|
|
285
400
|
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Async version of buildValidationInput that also checks stdin for "yes" confirmation.
|
|
404
|
+
* Use this when the command has a confirm option and doesn't use stdin for other purposes.
|
|
405
|
+
*/
|
|
406
|
+
export async function buildValidationInputAsync(
|
|
407
|
+
schemas: CommandSchemas,
|
|
408
|
+
rawArgs: unknown[],
|
|
409
|
+
rawOptions: Record<string, unknown>,
|
|
410
|
+
options?: { usesStdin?: boolean }
|
|
411
|
+
): Promise<{ args: Record<string, unknown>; options: Record<string, unknown> }> {
|
|
412
|
+
const result = buildValidationInput(schemas, rawArgs, rawOptions, options);
|
|
413
|
+
|
|
414
|
+
// Check for stdin confirmation if:
|
|
415
|
+
// 1. Command has a confirm option in schema
|
|
416
|
+
// 2. Command doesn't use stdin for other purposes
|
|
417
|
+
// 3. confirm is not already set via flags
|
|
418
|
+
if (schemas.options && !options?.usesStdin) {
|
|
419
|
+
// Use getShape() instead of parseOptionsSchema() to avoid re-evaluating function defaults
|
|
420
|
+
const shape = getShape(schemas.options);
|
|
421
|
+
const hasConfirmOption = Object.prototype.hasOwnProperty.call(shape, 'confirm');
|
|
422
|
+
const confirmValue = result.options.confirm;
|
|
423
|
+
|
|
424
|
+
if (hasConfirmOption && confirmValue === undefined) {
|
|
425
|
+
const stdinConfirmed = await checkStdinConfirmation();
|
|
426
|
+
if (stdinConfirmed) {
|
|
427
|
+
result.options.confirm = true;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
return result;
|
|
433
|
+
}
|
package/src/tui.ts
CHANGED
|
@@ -1172,6 +1172,11 @@ export async function spinner<T>(
|
|
|
1172
1172
|
options = messageOrOptions;
|
|
1173
1173
|
}
|
|
1174
1174
|
|
|
1175
|
+
// assume true by default
|
|
1176
|
+
if (options.clearOnSuccess === undefined) {
|
|
1177
|
+
options.clearOnSuccess = true;
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1175
1180
|
const message = options.message;
|
|
1176
1181
|
const reset = getColor('reset');
|
|
1177
1182
|
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { $ } from 'bun';
|
|
2
|
+
import type { Logger } from '../types';
|
|
3
|
+
|
|
4
|
+
export interface PackageRef {
|
|
5
|
+
name: string;
|
|
6
|
+
version: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export async function extractDependencies(
|
|
10
|
+
projectDir: string,
|
|
11
|
+
logger: Logger
|
|
12
|
+
): Promise<PackageRef[]> {
|
|
13
|
+
try {
|
|
14
|
+
logger.debug('Extracting dependencies using bun pm ls --all');
|
|
15
|
+
|
|
16
|
+
const result = await $`bun pm ls --all`.cwd(projectDir).quiet().nothrow();
|
|
17
|
+
|
|
18
|
+
if (result.exitCode !== 0) {
|
|
19
|
+
logger.warn(
|
|
20
|
+
'Failed to extract dependencies: bun pm ls exited with code %d',
|
|
21
|
+
result.exitCode
|
|
22
|
+
);
|
|
23
|
+
return [];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const output = result.stdout.toString();
|
|
27
|
+
const packages = parseBunPmLsOutput(output);
|
|
28
|
+
|
|
29
|
+
logger.debug('Extracted %d unique packages', packages.length);
|
|
30
|
+
return packages;
|
|
31
|
+
} catch (error) {
|
|
32
|
+
logger.warn('Failed to extract dependencies: %s', error);
|
|
33
|
+
return [];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function parseBunPmLsOutput(output: string): PackageRef[] {
|
|
38
|
+
const packages = new Map<string, PackageRef>();
|
|
39
|
+
const lines = output.split('\n');
|
|
40
|
+
|
|
41
|
+
for (const line of lines) {
|
|
42
|
+
const match = line.match(/([^\s]+)@(\d+\.\d+\.\d+[^\s]*)/);
|
|
43
|
+
if (match) {
|
|
44
|
+
const name = match[1];
|
|
45
|
+
const version = match[2];
|
|
46
|
+
const key = `${name}@${version}`;
|
|
47
|
+
if (!packages.has(key)) {
|
|
48
|
+
packages.set(key, { name, version });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return Array.from(packages.values());
|
|
54
|
+
}
|