@agentuity/cli 0.1.15 → 0.1.16
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 +15 -1
- package/dist/cli.js.map +1 -1
- package/dist/cmd/ai/opencode/install.js +1 -1
- package/dist/cmd/ai/opencode/install.js.map +1 -1
- package/dist/cmd/cloud/env/delete.d.ts.map +1 -1
- package/dist/cmd/cloud/env/delete.js +87 -34
- package/dist/cmd/cloud/env/delete.js.map +1 -1
- package/dist/cmd/cloud/env/get.d.ts.map +1 -1
- package/dist/cmd/cloud/env/get.js +50 -16
- package/dist/cmd/cloud/env/get.js.map +1 -1
- package/dist/cmd/cloud/env/import.d.ts.map +1 -1
- package/dist/cmd/cloud/env/import.js +76 -32
- package/dist/cmd/cloud/env/import.js.map +1 -1
- package/dist/cmd/cloud/env/index.d.ts.map +1 -1
- package/dist/cmd/cloud/env/index.js +6 -2
- package/dist/cmd/cloud/env/index.js.map +1 -1
- package/dist/cmd/cloud/env/list.d.ts.map +1 -1
- package/dist/cmd/cloud/env/list.js +94 -23
- package/dist/cmd/cloud/env/list.js.map +1 -1
- package/dist/cmd/cloud/env/org-util.d.ts +16 -0
- package/dist/cmd/cloud/env/org-util.d.ts.map +1 -0
- package/dist/cmd/cloud/env/org-util.js +28 -0
- package/dist/cmd/cloud/env/org-util.js.map +1 -0
- package/dist/cmd/cloud/env/pull.d.ts.map +1 -1
- package/dist/cmd/cloud/env/pull.js +61 -29
- package/dist/cmd/cloud/env/pull.js.map +1 -1
- package/dist/cmd/cloud/env/push.d.ts.map +1 -1
- package/dist/cmd/cloud/env/push.js +69 -23
- package/dist/cmd/cloud/env/push.js.map +1 -1
- package/dist/cmd/cloud/env/set.d.ts.map +1 -1
- package/dist/cmd/cloud/env/set.js +69 -26
- package/dist/cmd/cloud/env/set.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/create-namespace.js +1 -1
- package/dist/cmd/cloud/keyvalue/create-namespace.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/delete-namespace.js +2 -2
- package/dist/cmd/cloud/keyvalue/delete-namespace.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/delete.js +1 -1
- package/dist/cmd/cloud/keyvalue/delete.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/get.js +1 -1
- package/dist/cmd/cloud/keyvalue/get.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/index.js +1 -1
- package/dist/cmd/cloud/keyvalue/index.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/keys.js +1 -1
- package/dist/cmd/cloud/keyvalue/keys.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/list-namespaces.js +1 -1
- package/dist/cmd/cloud/keyvalue/list-namespaces.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/repl.d.ts.map +1 -1
- package/dist/cmd/cloud/keyvalue/repl.js +8 -5
- package/dist/cmd/cloud/keyvalue/repl.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/search.js +1 -1
- package/dist/cmd/cloud/keyvalue/search.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/set.js +1 -1
- package/dist/cmd/cloud/keyvalue/set.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/stats.js +1 -1
- package/dist/cmd/cloud/keyvalue/stats.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/util.d.ts +4 -4
- package/dist/cmd/cloud/keyvalue/util.d.ts.map +1 -1
- package/dist/cmd/cloud/keyvalue/util.js +4 -9
- package/dist/cmd/cloud/keyvalue/util.js.map +1 -1
- package/dist/cmd/project/create.d.ts.map +1 -1
- package/dist/cmd/project/create.js +12 -0
- package/dist/cmd/project/create.js.map +1 -1
- package/dist/cmd/project/template-flow.d.ts +3 -0
- package/dist/cmd/project/template-flow.d.ts.map +1 -1
- package/dist/cmd/project/template-flow.js +157 -68
- package/dist/cmd/project/template-flow.js.map +1 -1
- package/dist/cmd/setup/index.d.ts.map +1 -1
- package/dist/cmd/setup/index.js +2 -1
- package/dist/cmd/setup/index.js.map +1 -1
- package/dist/onboarding/agentPrompt.d.ts +8 -0
- package/dist/onboarding/agentPrompt.d.ts.map +1 -0
- package/dist/onboarding/agentPrompt.js +263 -0
- package/dist/onboarding/agentPrompt.js.map +1 -0
- package/dist/schema-generator.d.ts +1 -1
- package/dist/schema-generator.d.ts.map +1 -1
- package/dist/schema-parser.d.ts +1 -1
- package/dist/schema-parser.d.ts.map +1 -1
- package/dist/schema-parser.js +36 -1
- package/dist/schema-parser.js.map +1 -1
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +17 -7
- package/dist/tui.js.map +1 -1
- package/package.json +6 -6
- package/src/cli.ts +14 -1
- package/src/cmd/ai/opencode/install.ts +1 -1
- package/src/cmd/cloud/env/delete.ts +100 -41
- package/src/cmd/cloud/env/get.ts +53 -16
- package/src/cmd/cloud/env/import.ts +86 -37
- package/src/cmd/cloud/env/index.ts +6 -2
- package/src/cmd/cloud/env/list.ts +102 -27
- package/src/cmd/cloud/env/org-util.ts +37 -0
- package/src/cmd/cloud/env/pull.ts +67 -31
- package/src/cmd/cloud/env/push.ts +81 -28
- package/src/cmd/cloud/env/set.ts +82 -33
- package/src/cmd/cloud/keyvalue/create-namespace.ts +1 -1
- package/src/cmd/cloud/keyvalue/delete-namespace.ts +2 -2
- package/src/cmd/cloud/keyvalue/delete.ts +1 -1
- package/src/cmd/cloud/keyvalue/get.ts +1 -1
- package/src/cmd/cloud/keyvalue/index.ts +1 -1
- package/src/cmd/cloud/keyvalue/keys.ts +1 -1
- package/src/cmd/cloud/keyvalue/list-namespaces.ts +1 -1
- package/src/cmd/cloud/keyvalue/repl.ts +8 -5
- package/src/cmd/cloud/keyvalue/search.ts +1 -1
- package/src/cmd/cloud/keyvalue/set.ts +1 -1
- package/src/cmd/cloud/keyvalue/stats.ts +1 -1
- package/src/cmd/cloud/keyvalue/util.ts +8 -17
- package/src/cmd/project/create.ts +12 -0
- package/src/cmd/project/template-flow.ts +183 -69
- package/src/cmd/setup/index.ts +2 -1
- package/src/onboarding/agentPrompt.ts +263 -0
- package/src/schema-generator.ts +1 -1
- package/src/schema-parser.ts +42 -3
- package/src/tui.ts +19 -9
|
@@ -55,6 +55,9 @@ interface CreateFlowOptions {
|
|
|
55
55
|
orgId?: string;
|
|
56
56
|
region?: string;
|
|
57
57
|
apiClient?: APIClient;
|
|
58
|
+
database?: string;
|
|
59
|
+
storage?: string;
|
|
60
|
+
enableAuth?: boolean;
|
|
58
61
|
}
|
|
59
62
|
|
|
60
63
|
export interface CreateFlowResult {
|
|
@@ -85,8 +88,14 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<CreateF
|
|
|
85
88
|
region,
|
|
86
89
|
apiClient,
|
|
87
90
|
domains,
|
|
91
|
+
database: databaseOption,
|
|
92
|
+
storage: storageOption,
|
|
93
|
+
enableAuth: enableAuthOption,
|
|
88
94
|
} = options;
|
|
89
95
|
|
|
96
|
+
const isHeadless = !process.stdin.isTTY || !process.stdout.isTTY;
|
|
97
|
+
const isInteractive = !skipPrompts && !isHeadless;
|
|
98
|
+
|
|
90
99
|
// Fetch available templates
|
|
91
100
|
if (templateDir) {
|
|
92
101
|
tui.info(`📋 Loading templates from local directory: ${templateDir}...\n`);
|
|
@@ -120,11 +129,11 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<CreateF
|
|
|
120
129
|
// Create prompt flow
|
|
121
130
|
const prompt = createPrompt();
|
|
122
131
|
|
|
123
|
-
if (
|
|
132
|
+
if (isInteractive) {
|
|
124
133
|
prompt.intro('Create Agentuity Project');
|
|
125
134
|
}
|
|
126
135
|
|
|
127
|
-
if (!projectName &&
|
|
136
|
+
if (!projectName && isInteractive) {
|
|
128
137
|
projectName = await prompt.text({
|
|
129
138
|
message: 'What is the name of your project?',
|
|
130
139
|
hint: 'The name must be unique for your organization',
|
|
@@ -164,8 +173,8 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<CreateF
|
|
|
164
173
|
const destEmpty = destIsDir ? readdirSync(dest).length === 0 : !destExists;
|
|
165
174
|
|
|
166
175
|
if (destExists && !destEmpty && dirName !== '.') {
|
|
167
|
-
// In
|
|
168
|
-
if (
|
|
176
|
+
// In interactive mode, ask if they want to overwrite
|
|
177
|
+
if (isInteractive) {
|
|
169
178
|
tui.warning(`Directory ${dest} already exists and is not empty.`, true);
|
|
170
179
|
console.log(tui.tuiColors.secondary('│'));
|
|
171
180
|
const overwrite = await prompt.confirm({
|
|
@@ -210,7 +219,7 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<CreateF
|
|
|
210
219
|
return undefined as never;
|
|
211
220
|
}
|
|
212
221
|
selectedTemplate = found;
|
|
213
|
-
} else if (
|
|
222
|
+
} else if (!isInteractive || templates.length === 1) {
|
|
214
223
|
selectedTemplate = templates[0];
|
|
215
224
|
} else {
|
|
216
225
|
let maxLength = 15;
|
|
@@ -275,7 +284,13 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<CreateF
|
|
|
275
284
|
}
|
|
276
285
|
|
|
277
286
|
// Add separator bar if we're going to show resource prompts
|
|
278
|
-
|
|
287
|
+
const canProvision = auth && apiClient && catalystClient && orgId && region;
|
|
288
|
+
// Only count as resource flags if actually requesting provisioning (not explicit skip)
|
|
289
|
+
const hasResourceFlags =
|
|
290
|
+
(databaseOption !== undefined && databaseOption.toLowerCase() !== 'skip') ||
|
|
291
|
+
(storageOption !== undefined && storageOption.toLowerCase() !== 'skip');
|
|
292
|
+
|
|
293
|
+
if (isInteractive && canProvision) {
|
|
279
294
|
const { symbols, tuiColors } = tui;
|
|
280
295
|
console.log(tuiColors.secondary(symbols.bar));
|
|
281
296
|
}
|
|
@@ -283,43 +298,127 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<CreateF
|
|
|
283
298
|
let _domains = domains;
|
|
284
299
|
const resourceEnvVars: EnvVars = {};
|
|
285
300
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
});
|
|
301
|
+
// Validate that resource flags require authentication and registration
|
|
302
|
+
if (hasResourceFlags && !canProvision) {
|
|
303
|
+
logger.fatal(
|
|
304
|
+
'Cannot provision database/storage without being authenticated and registering the project.\n' +
|
|
305
|
+
'Remove --no-register or omit --database/--storage flags.',
|
|
306
|
+
ErrorCode.VALIDATION_FAILED
|
|
307
|
+
);
|
|
308
|
+
}
|
|
295
309
|
|
|
296
|
-
|
|
310
|
+
// Validate that --enable-auth requires authentication and registration
|
|
311
|
+
if (enableAuthOption && !canProvision) {
|
|
312
|
+
logger.fatal(
|
|
313
|
+
'Cannot enable Agentuity Auth without being authenticated and registering the project.\n' +
|
|
314
|
+
'Remove --no-register or omit --enable-auth flag.',
|
|
315
|
+
ErrorCode.VALIDATION_FAILED
|
|
316
|
+
);
|
|
317
|
+
}
|
|
297
318
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
{ value: 'Skip', label: 'Skip or Setup later' },
|
|
302
|
-
{ value: 'Create New', label: 'Create a new database' },
|
|
303
|
-
...resources.db.map((db) => ({
|
|
304
|
-
value: db.name,
|
|
305
|
-
label: `Use database: ${tui.tuiColors.primary(db.name)}`,
|
|
306
|
-
})),
|
|
307
|
-
],
|
|
308
|
-
});
|
|
319
|
+
if (canProvision) {
|
|
320
|
+
// Fetch resources for selected org and region using Catalyst API (needed for both interactive and CLI flags)
|
|
321
|
+
let resources: Awaited<ReturnType<typeof listResources>> | undefined;
|
|
309
322
|
|
|
310
|
-
const
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
323
|
+
const needResources =
|
|
324
|
+
isInteractive ||
|
|
325
|
+
(databaseOption && databaseOption !== 'skip' && databaseOption !== 'new') ||
|
|
326
|
+
(storageOption && storageOption !== 'skip' && storageOption !== 'new');
|
|
327
|
+
|
|
328
|
+
if (needResources) {
|
|
329
|
+
resources = await tui.spinner({
|
|
330
|
+
message: 'Fetching resources',
|
|
331
|
+
clearOnSuccess: true,
|
|
332
|
+
callback: async () => {
|
|
333
|
+
return listResources(catalystClient!, orgId!, region!);
|
|
334
|
+
},
|
|
335
|
+
});
|
|
336
|
+
// Log sanitized summary (avoid exposing DATABASE_URL, tokens, secrets)
|
|
337
|
+
logger.debug(
|
|
338
|
+
`Resources for org ${orgId} in region ${region}: ${resources.db.length} databases, ${resources.s3.length} storage buckets`
|
|
339
|
+
);
|
|
340
|
+
logger.debug(
|
|
341
|
+
`Database names: ${resources.db.map((d) => d.name).join(', ') || '(none)'}`
|
|
342
|
+
);
|
|
343
|
+
logger.debug(
|
|
344
|
+
`Storage buckets: ${resources.s3.map((b) => b.bucket_name).join(', ') || '(none)'}`
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// Determine database action: CLI flag > interactive prompt > skip (headless)
|
|
349
|
+
let db_action: string;
|
|
350
|
+
if (databaseOption !== undefined) {
|
|
351
|
+
// CLI flag provided - normalize to expected values
|
|
352
|
+
if (databaseOption.toLowerCase() === 'new') {
|
|
353
|
+
db_action = 'Create New';
|
|
354
|
+
} else if (databaseOption.toLowerCase() === 'skip') {
|
|
355
|
+
db_action = 'Skip';
|
|
356
|
+
} else {
|
|
357
|
+
// Existing database name - validate it exists
|
|
358
|
+
const existingDb = resources?.db.find((d) => d.name === databaseOption);
|
|
359
|
+
if (!existingDb) {
|
|
360
|
+
logger.fatal(
|
|
361
|
+
`Database '${databaseOption}' not found. Use 'new' to create a new database or 'skip' to skip.`,
|
|
362
|
+
ErrorCode.RESOURCE_NOT_FOUND
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
db_action = databaseOption;
|
|
366
|
+
}
|
|
367
|
+
} else if (isInteractive) {
|
|
368
|
+
db_action = await prompt.select({
|
|
369
|
+
message: 'Create SQL Database?',
|
|
370
|
+
options: [
|
|
371
|
+
{ value: 'Skip', label: 'Skip or Setup later' },
|
|
372
|
+
{ value: 'Create New', label: 'Create a new database' },
|
|
373
|
+
...resources!.db.map((db) => ({
|
|
374
|
+
value: db.name,
|
|
375
|
+
label: `Use database: ${tui.tuiColors.primary(db.name)}`,
|
|
376
|
+
})),
|
|
377
|
+
],
|
|
378
|
+
});
|
|
379
|
+
} else {
|
|
380
|
+
// Headless without flag - skip
|
|
381
|
+
db_action = 'Skip';
|
|
382
|
+
}
|
|
321
383
|
|
|
322
|
-
|
|
384
|
+
// Determine storage action: CLI flag > interactive prompt > skip (headless)
|
|
385
|
+
let s3_action: string;
|
|
386
|
+
if (storageOption !== undefined) {
|
|
387
|
+
// CLI flag provided - normalize to expected values
|
|
388
|
+
if (storageOption.toLowerCase() === 'new') {
|
|
389
|
+
s3_action = 'Create New';
|
|
390
|
+
} else if (storageOption.toLowerCase() === 'skip') {
|
|
391
|
+
s3_action = 'Skip';
|
|
392
|
+
} else {
|
|
393
|
+
// Existing bucket name - validate it exists
|
|
394
|
+
const existingBucket = resources?.s3.find((b) => b.bucket_name === storageOption);
|
|
395
|
+
if (!existingBucket) {
|
|
396
|
+
logger.fatal(
|
|
397
|
+
`Storage bucket '${storageOption}' not found. Use 'new' to create a new bucket or 'skip' to skip.`,
|
|
398
|
+
ErrorCode.RESOURCE_NOT_FOUND
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
s3_action = storageOption;
|
|
402
|
+
}
|
|
403
|
+
} else if (isInteractive) {
|
|
404
|
+
s3_action = await prompt.select({
|
|
405
|
+
message: 'Create Storage Bucket?',
|
|
406
|
+
options: [
|
|
407
|
+
{ value: 'Skip', label: 'Skip or Setup later' },
|
|
408
|
+
{ value: 'Create New', label: 'Create a new bucket' },
|
|
409
|
+
...resources!.s3.map((bucket) => ({
|
|
410
|
+
value: bucket.bucket_name,
|
|
411
|
+
label: `Use bucket: ${tui.tuiColors.primary(bucket.bucket_name)}`,
|
|
412
|
+
})),
|
|
413
|
+
],
|
|
414
|
+
});
|
|
415
|
+
} else {
|
|
416
|
+
// Headless without flag - skip
|
|
417
|
+
s3_action = 'Skip';
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// Custom DNS: only prompt in interactive mode if not already provided
|
|
421
|
+
if (!domains?.length && isInteractive) {
|
|
323
422
|
const customDns = await prompt.text({
|
|
324
423
|
message: 'Setup custom DNS?',
|
|
325
424
|
hint: 'Enter a domain name or press Enter to skip',
|
|
@@ -335,14 +434,14 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<CreateF
|
|
|
335
434
|
}
|
|
336
435
|
}
|
|
337
436
|
|
|
338
|
-
|
|
339
|
-
switch (
|
|
437
|
+
// Process storage action
|
|
438
|
+
switch (s3_action) {
|
|
340
439
|
case 'Create New': {
|
|
341
440
|
const created = await tui.spinner({
|
|
342
441
|
message: 'Provisioning New Bucket',
|
|
343
442
|
clearOnSuccess: true,
|
|
344
443
|
callback: async () => {
|
|
345
|
-
return createResources(catalystClient
|
|
444
|
+
return createResources(catalystClient!, orgId!, region!, [{ type: 's3' }]);
|
|
346
445
|
},
|
|
347
446
|
});
|
|
348
447
|
// Collect env vars from newly created resource
|
|
@@ -356,39 +455,49 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<CreateF
|
|
|
356
455
|
}
|
|
357
456
|
default: {
|
|
358
457
|
// User selected an existing bucket - get env vars from the resources list
|
|
359
|
-
const selectedBucket = resources
|
|
458
|
+
const selectedBucket = resources?.s3.find((b) => b.bucket_name === s3_action);
|
|
360
459
|
if (selectedBucket?.env) {
|
|
361
460
|
Object.assign(resourceEnvVars, selectedBucket.env);
|
|
362
461
|
}
|
|
363
462
|
break;
|
|
364
463
|
}
|
|
365
464
|
}
|
|
366
|
-
|
|
465
|
+
|
|
466
|
+
// Process database action
|
|
467
|
+
switch (db_action) {
|
|
367
468
|
case 'Create New': {
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
469
|
+
let dbName: string | undefined;
|
|
470
|
+
let dbDescription: string | undefined;
|
|
471
|
+
|
|
472
|
+
// Only prompt for name/description in interactive mode
|
|
473
|
+
if (isInteractive) {
|
|
474
|
+
const dbNameInput = await prompt.text({
|
|
475
|
+
message: 'Database name',
|
|
476
|
+
hint: 'Optional - lowercase letters, digits, underscores only',
|
|
477
|
+
validate: (value: string) => {
|
|
478
|
+
const trimmed = value.trim();
|
|
479
|
+
if (trimmed === '') return true;
|
|
480
|
+
const result = validateDatabaseName(trimmed);
|
|
481
|
+
return result.valid ? true : result.error!;
|
|
482
|
+
},
|
|
483
|
+
});
|
|
484
|
+
dbName = dbNameInput.trim() || undefined;
|
|
485
|
+
dbDescription =
|
|
486
|
+
(await prompt.text({
|
|
487
|
+
message: 'Database description',
|
|
488
|
+
hint: 'Optional - press Enter to skip',
|
|
489
|
+
})) || undefined;
|
|
490
|
+
}
|
|
491
|
+
|
|
383
492
|
const created = await tui.spinner({
|
|
384
493
|
message: 'Provisioning New SQL Database',
|
|
385
494
|
clearOnSuccess: true,
|
|
386
495
|
callback: async () => {
|
|
387
|
-
return createResources(catalystClient
|
|
496
|
+
return createResources(catalystClient!, orgId!, region!, [
|
|
388
497
|
{
|
|
389
498
|
type: 'db',
|
|
390
499
|
name: dbName,
|
|
391
|
-
description: dbDescription
|
|
500
|
+
description: dbDescription,
|
|
392
501
|
},
|
|
393
502
|
]);
|
|
394
503
|
},
|
|
@@ -404,7 +513,7 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<CreateF
|
|
|
404
513
|
}
|
|
405
514
|
default: {
|
|
406
515
|
// User selected an existing database - get env vars from the resources list
|
|
407
|
-
const selectedDb = resources
|
|
516
|
+
const selectedDb = resources?.db.find((d) => d.name === db_action);
|
|
408
517
|
if (selectedDb?.env) {
|
|
409
518
|
Object.assign(resourceEnvVars, selectedDb.env);
|
|
410
519
|
}
|
|
@@ -413,15 +522,19 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<CreateF
|
|
|
413
522
|
}
|
|
414
523
|
}
|
|
415
524
|
|
|
416
|
-
// Auth setup - either from template or user choice
|
|
525
|
+
// Auth setup - either from template, CLI flag, or user choice
|
|
417
526
|
const templateHasAuth = selectedTemplate.id === 'agentuity-auth';
|
|
418
527
|
|
|
419
528
|
let authEnabled = templateHasAuth; // Auth templates have auth enabled by default
|
|
420
529
|
let authDatabaseName: string | undefined;
|
|
421
530
|
let authDatabaseUrl: string | undefined;
|
|
422
531
|
|
|
423
|
-
//
|
|
424
|
-
if (
|
|
532
|
+
// Handle auth enablement: CLI flag > interactive prompt > disabled (headless)
|
|
533
|
+
if (enableAuthOption !== undefined) {
|
|
534
|
+
// CLI flag provided
|
|
535
|
+
authEnabled = enableAuthOption;
|
|
536
|
+
} else if (canProvision && isInteractive && !templateHasAuth) {
|
|
537
|
+
// For non-auth templates in interactive mode, ask if they want to enable auth
|
|
425
538
|
const enableAuth = await prompt.select({
|
|
426
539
|
message: 'Enable Agentuity Authentication?',
|
|
427
540
|
options: [
|
|
@@ -434,9 +547,10 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<CreateF
|
|
|
434
547
|
authEnabled = true;
|
|
435
548
|
}
|
|
436
549
|
}
|
|
550
|
+
// In headless mode without --enable-auth flag, authEnabled stays false (unless template has auth)
|
|
437
551
|
|
|
438
552
|
// Set up database and secret for any auth-enabled project
|
|
439
|
-
if (authEnabled &&
|
|
553
|
+
if (authEnabled && canProvision) {
|
|
440
554
|
// If a database was already selected/created above, use it for auth
|
|
441
555
|
if (resourceEnvVars.DATABASE_URL) {
|
|
442
556
|
authDatabaseUrl = resourceEnvVars.DATABASE_URL;
|
|
@@ -457,7 +571,7 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<CreateF
|
|
|
457
571
|
message: 'Provisioning database for auth',
|
|
458
572
|
clearOnSuccess: true,
|
|
459
573
|
callback: async () => {
|
|
460
|
-
return createResources(catalystClient
|
|
574
|
+
return createResources(catalystClient!, orgId!, region!, [{ type: 'db' }]);
|
|
461
575
|
},
|
|
462
576
|
});
|
|
463
577
|
authDatabaseName = created[0].name;
|
|
@@ -607,7 +721,7 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<CreateF
|
|
|
607
721
|
await initGitRepo(dest);
|
|
608
722
|
|
|
609
723
|
// Show completion message
|
|
610
|
-
if (
|
|
724
|
+
if (isInteractive) {
|
|
611
725
|
if (setupResult.success) {
|
|
612
726
|
tui.success('✨ Project created successfully!\n');
|
|
613
727
|
} else {
|
|
@@ -641,7 +755,7 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<CreateF
|
|
|
641
755
|
|
|
642
756
|
playSound();
|
|
643
757
|
|
|
644
|
-
if (
|
|
758
|
+
if (isInteractive && _domains?.length && projectId) {
|
|
645
759
|
tui.newline();
|
|
646
760
|
const ok = await tui.confirm('Would you like to configure DNS now?', true);
|
|
647
761
|
if (ok) {
|
package/src/cmd/setup/index.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { hasLoggedInBefore } from '../../auth';
|
|
|
4
4
|
import { showBanner } from '../../banner';
|
|
5
5
|
import * as tui from '../../tui';
|
|
6
6
|
import { getCommand } from '../../command-prefix';
|
|
7
|
+
import { getAgentPromptMarkdown } from '../../onboarding/agentPrompt';
|
|
7
8
|
|
|
8
9
|
const validateToken = /[\d]{7,}\.[\w-_.]{22}/;
|
|
9
10
|
|
|
@@ -53,7 +54,7 @@ export const command = createCommand({
|
|
|
53
54
|
},
|
|
54
55
|
});
|
|
55
56
|
if (ok) {
|
|
56
|
-
|
|
57
|
+
process.stdout.write(getAgentPromptMarkdown());
|
|
57
58
|
return;
|
|
58
59
|
}
|
|
59
60
|
}
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Onboarding Prompt
|
|
3
|
+
*
|
|
4
|
+
* This generates the markdown prompt that coding agents use to guide developers
|
|
5
|
+
* through Agentuity setup after the CLI has been installed.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export function getAgentPromptMarkdown(): string {
|
|
9
|
+
return `
|
|
10
|
+
**Your goal:** Guide the user from zero to a deployed Agentuity project, then help them understand what they have and what to do next.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## What is Agentuity?
|
|
15
|
+
|
|
16
|
+
Agentuity is the full-stack platform for AI agents. Briefly explain to the user:
|
|
17
|
+
|
|
18
|
+
- **Full-stack agents**: Build agents, APIs, and front-end integrations with end-to-end type safety
|
|
19
|
+
- **Bun/TypeScript SDKs**: First-class developer experience with the fastest JavaScript runtime
|
|
20
|
+
- **AI Gateway**: Unified access to LLMs (OpenAI-compatible SDK) with single billing—no separate API keys needed
|
|
21
|
+
- **Observability**: Logs, tracing, and evals built-in so you can debug and improve agents
|
|
22
|
+
- **Production services**: Sandboxes, storage (S3-compatible), Postgres, KV, and enterprise features available as you grow
|
|
23
|
+
|
|
24
|
+
We're going to be setting up the default template quickly.
|
|
25
|
+
|
|
26
|
+
The default template includes AI Gateway integration, thread state persistence, structured logging, Tailwind CSS, and a local Workbench at \`/workbench\` for testing agents.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## How to Guide the User
|
|
31
|
+
|
|
32
|
+
**Your job is to make onboarding as smooth as possible with minimal user interaction.**
|
|
33
|
+
|
|
34
|
+
1. **Start by briefly explaining** what Agentuity is and what you'll help them accomplish
|
|
35
|
+
2. **Run commands automatically** when you have terminal access—don't ask permission for each step
|
|
36
|
+
3. **Only pause for human action** when absolutely required
|
|
37
|
+
4. **At each step**: Briefly explain what it does and why, then execute
|
|
38
|
+
5. **Celebrate success**: When deployment completes, make sure the user knows they earned free credits and show them what to explore next
|
|
39
|
+
|
|
40
|
+
Assume the user is technical but new to Agentuity. Be warm, efficient, and action-oriented. The goal is a successful deployment with as few interruptions as possible.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Onboarding Steps
|
|
45
|
+
|
|
46
|
+
### Step 1: You're Already Logged In!
|
|
47
|
+
|
|
48
|
+
**The install command automatically authenticated you.** No manual login needed.
|
|
49
|
+
|
|
50
|
+
Verify with:
|
|
51
|
+
\`\`\`bash
|
|
52
|
+
agentuity auth whoami
|
|
53
|
+
\`\`\`
|
|
54
|
+
|
|
55
|
+
This outputs your user info including your \`org_id\`. You'll need this for the create command.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
### Step 2: Create a New Project
|
|
60
|
+
|
|
61
|
+
**Why:** This scaffolds a full-stack agent app with AI Gateway, persistence, logging, and a testing UI.
|
|
62
|
+
|
|
63
|
+
**First, get the user's organization ID:**
|
|
64
|
+
\`\`\`bash
|
|
65
|
+
agentuity auth whoami
|
|
66
|
+
\`\`\`
|
|
67
|
+
|
|
68
|
+
This outputs the user's info including their \`org_id\`. You'll need this for the create command.
|
|
69
|
+
|
|
70
|
+
**Then create the project (non-interactive):**
|
|
71
|
+
\`\`\`bash
|
|
72
|
+
agentuity create --name "my-first-agent" --org-id <ORG_ID> --region usc --confirm
|
|
73
|
+
\`\`\`
|
|
74
|
+
|
|
75
|
+
**Required flags for non-interactive mode:**
|
|
76
|
+
- \`--name\`: Project name (use \`my-first-agent\` as default)
|
|
77
|
+
- \`--org-id\`: The organization ID from \`agentuity auth whoami\` (required in non-interactive mode)
|
|
78
|
+
- \`--region\`: Cloud region (use \`usc\` for US Central, or \`use\` for US East)
|
|
79
|
+
- \`--confirm\`: Skips interactive prompts
|
|
80
|
+
|
|
81
|
+
**Example with real org ID:**
|
|
82
|
+
\`\`\`bash
|
|
83
|
+
agentuity create --name "my-first-agent" --org-id ..... --region usc --confirm
|
|
84
|
+
\`\`\`
|
|
85
|
+
|
|
86
|
+
If the user wants a different location, add \`--dir\`:
|
|
87
|
+
\`\`\`bash
|
|
88
|
+
agentuity create --name "my-first-agent" --org-id <ORG_ID> --region usc --dir ~/projects/my-first-agent --confirm
|
|
89
|
+
\`\`\`
|
|
90
|
+
|
|
91
|
+
After creation, \`cd\` into the project directory.
|
|
92
|
+
|
|
93
|
+
**Docs:** https://agentuity.dev/Get-Started/quickstart
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
### Step 3: Run Locally
|
|
98
|
+
|
|
99
|
+
**Why:** Start the development server to test the project locally before deploying.
|
|
100
|
+
|
|
101
|
+
**Command:**
|
|
102
|
+
\`\`\`bash
|
|
103
|
+
agentuity dev
|
|
104
|
+
\`\`\`
|
|
105
|
+
|
|
106
|
+
**⚠️ This is a long-running process!** The dev server runs continuously until killed. Before or after starting it, **immediately tell the user what to do** — don't just wait silently.
|
|
107
|
+
|
|
108
|
+
**What happens:**
|
|
109
|
+
- **Local server** starts at \`http://localhost:3500\` — this is where your APIs and agents are served
|
|
110
|
+
- **Workbench** available at \`http://localhost:3500/workbench\` — a built-in UI for testing and interacting with your agents directly, without needing a frontend
|
|
111
|
+
- **Public tunnel URL** is automatically created — the CLI will display a public URL that tunnels to your local server, useful for testing webhooks or sharing with others
|
|
112
|
+
- **Hot reload** enabled — code changes reflect immediately
|
|
113
|
+
|
|
114
|
+
**Immediately after starting the dev server, tell the user:**
|
|
115
|
+
|
|
116
|
+
> "The dev server is now running! Here's what to try:
|
|
117
|
+
>
|
|
118
|
+
> 1. Open **http://localhost:3500** to see the app
|
|
119
|
+
> 2. Open **http://localhost:3500/workbench** to interact with your agents (this is a key feature!)
|
|
120
|
+
> 3. The public tunnel URL shown in the terminal can be shared with others
|
|
121
|
+
>
|
|
122
|
+
> Take a few minutes to explore. When you're ready to deploy to production, let me know!"
|
|
123
|
+
|
|
124
|
+
**Wait for the user to confirm** they're ready to deploy before proceeding to Step 4.
|
|
125
|
+
|
|
126
|
+
**Keyboard shortcuts** while dev server runs: \`h\` for help, \`r\` to restart, \`q\` to quit.
|
|
127
|
+
|
|
128
|
+
**Docs:** https://agentuity.dev/Reference/CLI/development
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
### Step 4: Deploy to Production
|
|
133
|
+
|
|
134
|
+
**Why:** Make the project live with observability, logs, and analytics.
|
|
135
|
+
|
|
136
|
+
**Important:** Deploying their first project earns the user **free credits** to continue experimenting with the platform. Make sure they know this is a reward for completing onboarding!
|
|
137
|
+
|
|
138
|
+
**First, stop the dev server:**
|
|
139
|
+
Before deploying, you must stop the dev server that's still running from Step 3. Send \`Ctrl+C\` or \`q\` to the terminal running \`agentuity dev\` to gracefully shut it down. Don't leave it running or you'll have an orphaned process on port 3500.
|
|
140
|
+
|
|
141
|
+
**Then deploy:**
|
|
142
|
+
\`\`\`bash
|
|
143
|
+
agentuity deploy
|
|
144
|
+
\`\`\`
|
|
145
|
+
|
|
146
|
+
**What happens:**
|
|
147
|
+
- Project builds and deploys to Agentuity's global edge network
|
|
148
|
+
- The CLI will output the production URL when deployment succeeds
|
|
149
|
+
- Observability (logs, tracing, analytics) is now live
|
|
150
|
+
- **Free credits are awarded** for their first deployment
|
|
151
|
+
|
|
152
|
+
**⚠️ CRITICAL: Do not hallucinate URLs!**
|
|
153
|
+
- **Only show the user URLs that the CLI actually outputs**
|
|
154
|
+
- Do not make up or guess production URLs (e.g., don't invent \`https://project-name.agentuity.app\`)
|
|
155
|
+
- If the deploy command fails or doesn't show a URL, tell the user to check the dashboard instead
|
|
156
|
+
- If there's an error, report the actual error message from the CLI
|
|
157
|
+
|
|
158
|
+
**After successful deployment:**
|
|
159
|
+
1. Show the user the **exact production URL from the CLI output**
|
|
160
|
+
2. Direct them to the Agentuity dashboard at https://app.agentuity.com to:
|
|
161
|
+
- View their deployed project
|
|
162
|
+
- Explore logs and traces
|
|
163
|
+
- See their credit balance
|
|
164
|
+
- Monitor analytics
|
|
165
|
+
|
|
166
|
+
**If deployment fails or shows errors:**
|
|
167
|
+
- Report the actual error message
|
|
168
|
+
- Don't claim success if the CLI didn't confirm it
|
|
169
|
+
- Suggest checking the dashboard for deployment status
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## What the Template Provides
|
|
174
|
+
|
|
175
|
+
After deployment, explain what they now have:
|
|
176
|
+
|
|
177
|
+
| Feature | What It Does |
|
|
178
|
+
|---------|--------------|
|
|
179
|
+
| **AI Gateway** | OpenAI-compatible SDK routed through Agentuity—unified billing, no separate API keys |
|
|
180
|
+
| **Thread State** | Conversations and agent state persist automatically for multi-turn flows |
|
|
181
|
+
| **Structured Logging** | Logs and traces captured for debugging and analytics |
|
|
182
|
+
| **Workbench** | Local UI at \`/workbench\` for testing agents without a frontend |
|
|
183
|
+
| **Tailwind CSS** | Pre-configured styling for the frontend |
|
|
184
|
+
| **Type Safety** | End-to-end types from agent schemas to API routes to frontend |
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Next Steps
|
|
189
|
+
|
|
190
|
+
After successful deployment, guide the user through these recommendations:
|
|
191
|
+
|
|
192
|
+
### 1. Celebrate the Free Credits!
|
|
193
|
+
- Remind the user: their first deployment earned them **free credits** to keep experimenting
|
|
194
|
+
- They can view their credit balance in the Agentuity dashboard
|
|
195
|
+
- These credits let them continue building and testing without upfront cost
|
|
196
|
+
|
|
197
|
+
### 2. Join the Community
|
|
198
|
+
- **Discord**: https://discord.gg/agentuity
|
|
199
|
+
- Get help, see examples, share what you're building
|
|
200
|
+
|
|
201
|
+
### 3. Explore the Dashboard
|
|
202
|
+
- **Observability**: View logs, traces, and evals for your deployment
|
|
203
|
+
- **Deployments**: See version history with rollback options
|
|
204
|
+
- **Analytics**: Monitor usage and performance
|
|
205
|
+
|
|
206
|
+
### 4. Connect GitHub
|
|
207
|
+
- Enable GitHub integration in project settings for:
|
|
208
|
+
- Automatic deployments from branches
|
|
209
|
+
- CI/CD workflows
|
|
210
|
+
- Team collaboration
|
|
211
|
+
|
|
212
|
+
### 5. Explore Additional Services
|
|
213
|
+
As your project grows, Agentuity provides:
|
|
214
|
+
- **Postgres**: Relational database
|
|
215
|
+
- **KV**: Fast key-value storage
|
|
216
|
+
- **Storage**: S3-compatible file storage
|
|
217
|
+
- **Sandboxes**: Isolated execution environments
|
|
218
|
+
|
|
219
|
+
### 6. Customize Your Agents
|
|
220
|
+
The SDK makes it easy to:
|
|
221
|
+
- Add new agents in \`src/agent/\` (just add a folder with \`agent.ts\`)
|
|
222
|
+
- Create API routes in \`src/api/\`
|
|
223
|
+
- Build type-safe frontend integrations
|
|
224
|
+
|
|
225
|
+
**Docs:** https://agentuity.dev/Get-Started/project-structure
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## Handling Common Issues
|
|
230
|
+
|
|
231
|
+
- **Bun not installed**: The CLI will prompt to install it, or run: \`curl -fsSL https://bun.sh/install | bash\`
|
|
232
|
+
- **Login fails/times out**: Rerun \`agentuity login\` and check browser
|
|
233
|
+
- **Port 3500 in use**: Kill the existing process or use \`agentuity dev --port 8080\`
|
|
234
|
+
- **Deploy fails**: Check build errors in CLI output, ensure you're in the project directory
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Success Criteria
|
|
239
|
+
|
|
240
|
+
**Onboarding is successful when the user has:**
|
|
241
|
+
|
|
242
|
+
1. ✅ **CLI installed** and authenticated
|
|
243
|
+
2. ✅ **Local dev environment running** — they've seen \`localhost:3500\` and tried the Workbench
|
|
244
|
+
3. ✅ **First deployment complete** — they have a live production URL
|
|
245
|
+
4. ✅ **Free credits earned** — they know they've been rewarded and can keep building
|
|
246
|
+
5. ✅ **Clear next steps** — they know about Discord, the dashboard, and how to extend their project
|
|
247
|
+
|
|
248
|
+
**Make them feel accomplished!** They just went from zero to a deployed AI agent platform in minutes.
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## Style Guidelines
|
|
253
|
+
|
|
254
|
+
- Keep explanations short and practical
|
|
255
|
+
- Explain what & why at each step
|
|
256
|
+
- Give exact commands
|
|
257
|
+
- Handle errors calmly with concrete suggestions
|
|
258
|
+
- Be explicit when human action is required
|
|
259
|
+
- Use non-interactive CLI flags (\`--confirm\`, \`--name\`, \`--org-id\`, \`--region usc\`, \`--dir\`) for smooth automation
|
|
260
|
+
- **Never hallucinate or make up information** — only report URLs, IDs, and status from actual CLI output
|
|
261
|
+
- If something fails or you're unsure, say so honestly and direct the user to the dashboard
|
|
262
|
+
`;
|
|
263
|
+
}
|
package/src/schema-generator.ts
CHANGED
|
@@ -13,7 +13,7 @@ export interface SchemaArgument {
|
|
|
13
13
|
|
|
14
14
|
export interface SchemaOption {
|
|
15
15
|
name: string;
|
|
16
|
-
type: 'string' | 'number' | 'boolean' | 'array';
|
|
16
|
+
type: 'string' | 'number' | 'boolean' | 'array' | 'optionalString';
|
|
17
17
|
required: boolean;
|
|
18
18
|
default?: unknown;
|
|
19
19
|
description?: string;
|