@agentuity/cli 0.0.43 → 0.0.44
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/AGENTS.md +1 -1
- package/README.md +1 -1
- package/dist/api.d.ts +3 -3
- package/dist/api.d.ts.map +1 -1
- package/dist/auth.d.ts +10 -2
- package/dist/auth.d.ts.map +1 -1
- package/dist/banner.d.ts.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cmd/auth/api.d.ts +4 -4
- package/dist/cmd/auth/api.d.ts.map +1 -1
- package/dist/cmd/auth/index.d.ts.map +1 -1
- package/dist/cmd/auth/login.d.ts.map +1 -1
- package/dist/cmd/auth/signup.d.ts.map +1 -1
- package/dist/cmd/auth/ssh/add.d.ts +2 -0
- package/dist/cmd/auth/ssh/add.d.ts.map +1 -0
- package/dist/cmd/auth/ssh/api.d.ts +16 -0
- package/dist/cmd/auth/ssh/api.d.ts.map +1 -0
- package/dist/cmd/auth/ssh/delete.d.ts +2 -0
- package/dist/cmd/auth/ssh/delete.d.ts.map +1 -0
- package/dist/cmd/auth/ssh/index.d.ts +3 -0
- package/dist/cmd/auth/ssh/index.d.ts.map +1 -0
- package/dist/cmd/auth/ssh/list.d.ts +2 -0
- package/dist/cmd/auth/ssh/list.d.ts.map +1 -0
- package/dist/cmd/auth/whoami.d.ts.map +1 -1
- package/dist/cmd/bundle/ast.d.ts +14 -3
- package/dist/cmd/bundle/ast.d.ts.map +1 -1
- package/dist/cmd/bundle/ast.test.d.ts +2 -0
- package/dist/cmd/bundle/ast.test.d.ts.map +1 -0
- package/dist/cmd/bundle/bundler.d.ts +6 -1
- package/dist/cmd/bundle/bundler.d.ts.map +1 -1
- package/dist/cmd/bundle/file.d.ts.map +1 -1
- package/dist/cmd/bundle/fix-duplicate-exports.d.ts +2 -0
- package/dist/cmd/bundle/fix-duplicate-exports.d.ts.map +1 -0
- package/dist/cmd/bundle/fix-duplicate-exports.test.d.ts +2 -0
- package/dist/cmd/bundle/fix-duplicate-exports.test.d.ts.map +1 -0
- package/dist/cmd/bundle/plugin.d.ts +2 -0
- package/dist/cmd/bundle/plugin.d.ts.map +1 -1
- package/dist/cmd/cloud/deploy.d.ts.map +1 -1
- package/dist/cmd/cloud/domain.d.ts +17 -0
- package/dist/cmd/cloud/domain.d.ts.map +1 -0
- package/dist/cmd/cloud/index.d.ts.map +1 -1
- package/dist/cmd/cloud/resource/add.d.ts +2 -0
- package/dist/cmd/cloud/resource/add.d.ts.map +1 -0
- package/dist/cmd/cloud/resource/delete.d.ts +2 -0
- package/dist/cmd/cloud/resource/delete.d.ts.map +1 -0
- package/dist/cmd/cloud/resource/index.d.ts +3 -0
- package/dist/cmd/cloud/resource/index.d.ts.map +1 -0
- package/dist/cmd/cloud/resource/list.d.ts +2 -0
- package/dist/cmd/cloud/resource/list.d.ts.map +1 -0
- package/dist/cmd/cloud/scp/download.d.ts +2 -0
- package/dist/cmd/cloud/scp/download.d.ts.map +1 -0
- package/dist/cmd/cloud/scp/index.d.ts +3 -0
- package/dist/cmd/cloud/scp/index.d.ts.map +1 -0
- package/dist/cmd/cloud/scp/upload.d.ts +2 -0
- package/dist/cmd/cloud/scp/upload.d.ts.map +1 -0
- package/dist/cmd/cloud/ssh.d.ts +2 -0
- package/dist/cmd/cloud/ssh.d.ts.map +1 -0
- package/dist/cmd/dev/api.d.ts +18 -0
- package/dist/cmd/dev/api.d.ts.map +1 -0
- package/dist/cmd/dev/download.d.ts +11 -0
- package/dist/cmd/dev/download.d.ts.map +1 -0
- package/dist/cmd/dev/index.d.ts.map +1 -1
- package/dist/cmd/dev/templates.d.ts +3 -0
- package/dist/cmd/dev/templates.d.ts.map +1 -0
- package/dist/cmd/env/delete.d.ts.map +1 -1
- package/dist/cmd/env/get.d.ts.map +1 -1
- package/dist/cmd/env/import.d.ts.map +1 -1
- package/dist/cmd/env/list.d.ts.map +1 -1
- package/dist/cmd/env/pull.d.ts.map +1 -1
- package/dist/cmd/env/push.d.ts.map +1 -1
- package/dist/cmd/env/set.d.ts.map +1 -1
- package/dist/cmd/profile/show.d.ts.map +1 -1
- package/dist/cmd/project/create.d.ts.map +1 -1
- package/dist/cmd/project/delete.d.ts.map +1 -1
- package/dist/cmd/project/list.d.ts.map +1 -1
- package/dist/cmd/project/show.d.ts.map +1 -1
- package/dist/cmd/project/template-flow.d.ts +4 -0
- package/dist/cmd/project/template-flow.d.ts.map +1 -1
- package/dist/cmd/secret/delete.d.ts.map +1 -1
- package/dist/cmd/secret/get.d.ts.map +1 -1
- package/dist/cmd/secret/import.d.ts.map +1 -1
- package/dist/cmd/secret/list.d.ts.map +1 -1
- package/dist/cmd/secret/pull.d.ts.map +1 -1
- package/dist/cmd/secret/push.d.ts.map +1 -1
- package/dist/cmd/secret/set.d.ts.map +1 -1
- package/dist/config.d.ts +9 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/crypto/box.d.ts +65 -0
- package/dist/crypto/box.d.ts.map +1 -0
- package/dist/crypto/box.test.d.ts +2 -0
- package/dist/crypto/box.test.d.ts.map +1 -0
- package/dist/download.d.ts.map +1 -1
- package/dist/steps.d.ts +4 -1
- package/dist/steps.d.ts.map +1 -1
- package/dist/terminal.d.ts.map +1 -1
- package/dist/tui.d.ts +31 -1
- package/dist/tui.d.ts.map +1 -1
- package/dist/types.d.ts +249 -126
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/detectSubagent.d.ts +15 -0
- package/dist/utils/detectSubagent.d.ts.map +1 -0
- package/dist/utils/zip.d.ts +7 -0
- package/dist/utils/zip.d.ts.map +1 -0
- package/package.json +11 -3
- package/src/api-errors.md +2 -2
- package/src/api.ts +12 -7
- package/src/auth.ts +116 -7
- package/src/banner.ts +13 -6
- package/src/cli.ts +695 -63
- package/src/cmd/auth/api.ts +10 -16
- package/src/cmd/auth/index.ts +2 -1
- package/src/cmd/auth/login.ts +24 -8
- package/src/cmd/auth/signup.ts +15 -11
- package/src/cmd/auth/ssh/add.ts +263 -0
- package/src/cmd/auth/ssh/api.ts +94 -0
- package/src/cmd/auth/ssh/delete.ts +102 -0
- package/src/cmd/auth/ssh/index.ts +10 -0
- package/src/cmd/auth/ssh/list.ts +74 -0
- package/src/cmd/auth/whoami.ts +13 -13
- package/src/cmd/bundle/ast.test.ts +565 -0
- package/src/cmd/bundle/ast.ts +457 -44
- package/src/cmd/bundle/bundler.ts +255 -57
- package/src/cmd/bundle/file.ts +6 -12
- package/src/cmd/bundle/fix-duplicate-exports.test.ts +387 -0
- package/src/cmd/bundle/fix-duplicate-exports.ts +204 -0
- package/src/cmd/bundle/index.ts +9 -9
- package/src/cmd/bundle/patch/aisdk.ts +1 -1
- package/src/cmd/bundle/plugin.ts +373 -53
- package/src/cmd/cloud/deploy.ts +300 -93
- package/src/cmd/cloud/domain.ts +92 -0
- package/src/cmd/cloud/index.ts +4 -1
- package/src/cmd/cloud/resource/add.ts +56 -0
- package/src/cmd/cloud/resource/delete.ts +120 -0
- package/src/cmd/cloud/resource/index.ts +11 -0
- package/src/cmd/cloud/resource/list.ts +69 -0
- package/src/cmd/cloud/scp/download.ts +59 -0
- package/src/cmd/cloud/scp/index.ts +9 -0
- package/src/cmd/cloud/scp/upload.ts +62 -0
- package/src/cmd/cloud/ssh.ts +68 -0
- package/src/cmd/dev/api.ts +46 -0
- package/src/cmd/dev/download.ts +111 -0
- package/src/cmd/dev/index.ts +360 -34
- package/src/cmd/dev/templates.ts +84 -0
- package/src/cmd/env/delete.ts +5 -20
- package/src/cmd/env/get.ts +5 -18
- package/src/cmd/env/import.ts +5 -20
- package/src/cmd/env/list.ts +5 -18
- package/src/cmd/env/pull.ts +10 -23
- package/src/cmd/env/push.ts +5 -23
- package/src/cmd/env/set.ts +5 -20
- package/src/cmd/index.ts +2 -2
- package/src/cmd/profile/show.ts +15 -6
- package/src/cmd/project/create.ts +7 -2
- package/src/cmd/project/delete.ts +75 -18
- package/src/cmd/project/download.ts +2 -2
- package/src/cmd/project/list.ts +8 -8
- package/src/cmd/project/show.ts +3 -7
- package/src/cmd/project/template-flow.ts +170 -72
- package/src/cmd/secret/delete.ts +5 -20
- package/src/cmd/secret/get.ts +5 -18
- package/src/cmd/secret/import.ts +5 -20
- package/src/cmd/secret/list.ts +5 -18
- package/src/cmd/secret/pull.ts +10 -23
- package/src/cmd/secret/push.ts +5 -23
- package/src/cmd/secret/set.ts +5 -20
- package/src/config.ts +224 -24
- package/src/crypto/box.test.ts +431 -0
- package/src/crypto/box.ts +477 -0
- package/src/download.ts +1 -0
- package/src/env-util.test.ts +1 -1
- package/src/steps.ts +65 -6
- package/src/terminal.ts +24 -23
- package/src/tui.ts +192 -61
- package/src/types.ts +291 -201
- package/src/utils/detectSubagent.ts +31 -0
- package/src/utils/zip.ts +38 -0
- package/dist/cmd/example/create-user.d.ts +0 -2
- package/dist/cmd/example/create-user.d.ts.map +0 -1
- package/dist/cmd/example/create.d.ts +0 -2
- package/dist/cmd/example/create.d.ts.map +0 -1
- package/dist/cmd/example/deploy.d.ts +0 -2
- package/dist/cmd/example/deploy.d.ts.map +0 -1
- package/dist/cmd/example/index.d.ts +0 -2
- package/dist/cmd/example/index.d.ts.map +0 -1
- package/dist/cmd/example/list.d.ts +0 -2
- package/dist/cmd/example/list.d.ts.map +0 -1
- package/dist/cmd/example/optional-auth.d.ts +0 -3
- package/dist/cmd/example/optional-auth.d.ts.map +0 -1
- package/dist/cmd/example/run-command.d.ts +0 -2
- package/dist/cmd/example/run-command.d.ts.map +0 -1
- package/dist/cmd/example/sound.d.ts +0 -3
- package/dist/cmd/example/sound.d.ts.map +0 -1
- package/dist/cmd/example/spinner.d.ts +0 -2
- package/dist/cmd/example/spinner.d.ts.map +0 -1
- package/dist/cmd/example/steps.d.ts +0 -2
- package/dist/cmd/example/steps.d.ts.map +0 -1
- package/dist/cmd/example/version.d.ts +0 -2
- package/dist/cmd/example/version.d.ts.map +0 -1
- package/src/cmd/example/create-user.ts +0 -38
- package/src/cmd/example/create.ts +0 -31
- package/src/cmd/example/deploy.ts +0 -36
- package/src/cmd/example/index.ts +0 -29
- package/src/cmd/example/list.ts +0 -32
- package/src/cmd/example/optional-auth.ts +0 -38
- package/src/cmd/example/run-command.ts +0 -45
- package/src/cmd/example/sound.ts +0 -14
- package/src/cmd/example/spinner.ts +0 -44
- package/src/cmd/example/steps.ts +0 -66
- package/src/cmd/example/version.ts +0 -13
package/src/cmd/project/list.ts
CHANGED
|
@@ -2,13 +2,12 @@ import { z } from 'zod';
|
|
|
2
2
|
import { createSubcommand } from '../../types';
|
|
3
3
|
import * as tui from '../../tui';
|
|
4
4
|
import { projectList } from '@agentuity/server';
|
|
5
|
-
import { getAPIBaseURL, APIClient } from '../../api';
|
|
6
5
|
|
|
7
6
|
export const listSubcommand = createSubcommand({
|
|
8
7
|
name: 'list',
|
|
9
8
|
description: 'List all projects',
|
|
10
9
|
aliases: ['ls'],
|
|
11
|
-
|
|
10
|
+
requires: { auth: true, apiClient: true },
|
|
12
11
|
schema: {
|
|
13
12
|
options: z.object({
|
|
14
13
|
format: z
|
|
@@ -19,13 +18,14 @@ export const listSubcommand = createSubcommand({
|
|
|
19
18
|
},
|
|
20
19
|
|
|
21
20
|
async handler(ctx) {
|
|
22
|
-
const {
|
|
21
|
+
const { apiClient, opts } = ctx;
|
|
23
22
|
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
const projects = await tui.spinner({
|
|
24
|
+
message: 'Fetching projects',
|
|
25
|
+
clearOnSuccess: true,
|
|
26
|
+
callback: () => {
|
|
27
|
+
return projectList(apiClient);
|
|
28
|
+
},
|
|
29
29
|
});
|
|
30
30
|
|
|
31
31
|
// TODO: might want to sort by the last org_id we used
|
package/src/cmd/project/show.ts
CHANGED
|
@@ -2,13 +2,12 @@ import { z } from 'zod';
|
|
|
2
2
|
import { createSubcommand } from '../../types';
|
|
3
3
|
import * as tui from '../../tui';
|
|
4
4
|
import { projectGet } from '@agentuity/server';
|
|
5
|
-
import { getAPIBaseURL, APIClient } from '../../api';
|
|
6
5
|
|
|
7
6
|
export const showSubcommand = createSubcommand({
|
|
8
7
|
name: 'show',
|
|
9
8
|
aliases: ['get'],
|
|
10
9
|
description: 'Show project detail',
|
|
11
|
-
|
|
10
|
+
requires: { auth: true, apiClient: true },
|
|
12
11
|
schema: {
|
|
13
12
|
args: z.object({
|
|
14
13
|
id: z.string().describe('the project id'),
|
|
@@ -22,13 +21,10 @@ export const showSubcommand = createSubcommand({
|
|
|
22
21
|
},
|
|
23
22
|
|
|
24
23
|
async handler(ctx) {
|
|
25
|
-
const { opts, args,
|
|
26
|
-
|
|
27
|
-
const apiUrl = getAPIBaseURL(config);
|
|
28
|
-
const client = new APIClient(apiUrl, config);
|
|
24
|
+
const { opts, args, apiClient } = ctx;
|
|
29
25
|
|
|
30
26
|
const project = await tui.spinner('Fetching project', () => {
|
|
31
|
-
return projectGet(
|
|
27
|
+
return projectGet(apiClient, { id: args.id, mask: true });
|
|
32
28
|
});
|
|
33
29
|
|
|
34
30
|
if (!project) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { basename, resolve } from 'node:path';
|
|
2
|
+
import { z } from 'zod';
|
|
2
3
|
import { existsSync, readdirSync, rmSync, statSync } from 'node:fs';
|
|
3
4
|
import { cwd } from 'node:process';
|
|
4
5
|
import { homedir } from 'node:os';
|
|
@@ -6,19 +7,21 @@ import enquirer from 'enquirer';
|
|
|
6
7
|
import {
|
|
7
8
|
projectCreate,
|
|
8
9
|
projectExists,
|
|
9
|
-
|
|
10
|
+
listResources,
|
|
10
11
|
projectEnvUpdate,
|
|
11
|
-
|
|
12
|
+
getServiceUrls,
|
|
13
|
+
APIClient as ServerAPIClient,
|
|
14
|
+
Resources,
|
|
15
|
+
createResources,
|
|
12
16
|
} from '@agentuity/server';
|
|
13
17
|
import type { Logger } from '@agentuity/core';
|
|
14
18
|
import * as tui from '../../tui';
|
|
15
19
|
import { playSound } from '../../sound';
|
|
16
20
|
import { fetchTemplates, type TemplateInfo } from './templates';
|
|
17
21
|
import { downloadTemplate, setupProject } from './download';
|
|
18
|
-
import { showBanner } from '../../banner';
|
|
19
22
|
import type { AuthData, Config } from '../../types';
|
|
20
|
-
import {
|
|
21
|
-
import { createProjectConfig
|
|
23
|
+
import type { APIClient } from '../../api';
|
|
24
|
+
import { createProjectConfig } from '../../config';
|
|
22
25
|
import {
|
|
23
26
|
findEnvFile,
|
|
24
27
|
readEnvFile,
|
|
@@ -26,6 +29,8 @@ import {
|
|
|
26
29
|
splitEnvAndSecrets,
|
|
27
30
|
} from '../../env-util';
|
|
28
31
|
|
|
32
|
+
type ResourcesTypes = z.infer<typeof Resources>;
|
|
33
|
+
|
|
29
34
|
interface CreateFlowOptions {
|
|
30
35
|
projectName?: string;
|
|
31
36
|
dir?: string;
|
|
@@ -38,6 +43,9 @@ interface CreateFlowOptions {
|
|
|
38
43
|
logger: Logger;
|
|
39
44
|
auth?: AuthData;
|
|
40
45
|
config?: Config;
|
|
46
|
+
orgId?: string;
|
|
47
|
+
region?: string;
|
|
48
|
+
apiClient?: APIClient;
|
|
41
49
|
}
|
|
42
50
|
|
|
43
51
|
export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
|
|
@@ -51,47 +59,39 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
|
|
|
51
59
|
logger,
|
|
52
60
|
auth,
|
|
53
61
|
config,
|
|
62
|
+
orgId: selectedOrgId,
|
|
63
|
+
region,
|
|
64
|
+
apiClient,
|
|
54
65
|
} = options;
|
|
55
66
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
// Step 1: Fetch available templates
|
|
67
|
+
// Fetch available templates
|
|
59
68
|
if (templateDir) {
|
|
60
69
|
tui.info(`📋 Loading templates from local directory: ${templateDir}...\n`);
|
|
61
70
|
}
|
|
62
71
|
|
|
63
|
-
const templates = await tui.spinner(
|
|
64
|
-
|
|
72
|
+
const templates = await tui.spinner({
|
|
73
|
+
message: 'Fetching templates',
|
|
74
|
+
clearOnSuccess: true,
|
|
75
|
+
callback: async () => {
|
|
76
|
+
return fetchTemplates(templateDir, templateBranch);
|
|
77
|
+
},
|
|
65
78
|
});
|
|
66
79
|
|
|
67
80
|
if (templates.length === 0) {
|
|
68
81
|
logger.fatal('No templates available');
|
|
69
82
|
}
|
|
70
83
|
|
|
71
|
-
//
|
|
84
|
+
// Get project name
|
|
72
85
|
let projectName = initialProjectName;
|
|
73
86
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
let
|
|
87
|
+
// Organization is now automatically selected by the CLI framework via optional: { org: true }
|
|
88
|
+
const orgId = selectedOrgId;
|
|
89
|
+
let catalystClient: ServerAPIClient | undefined;
|
|
77
90
|
|
|
78
91
|
if (auth) {
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const resp = await listOrganizations(client!);
|
|
83
|
-
if (resp.data) {
|
|
84
|
-
return resp.data;
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
if (!orgs) {
|
|
88
|
-
tui.fatal('no organizations could be found for your login');
|
|
89
|
-
}
|
|
90
|
-
orgId = await tui.selectOrganization(orgs, config?.preferences?.orgId);
|
|
91
|
-
|
|
92
|
-
if (orgId && orgId !== config?.preferences?.orgId) {
|
|
93
|
-
await saveOrgId(orgId);
|
|
94
|
-
}
|
|
92
|
+
const serviceUrls = getServiceUrls();
|
|
93
|
+
const catalystUrl = config?.overrides?.catalyst_url ?? serviceUrls.catalyst;
|
|
94
|
+
catalystClient = new ServerAPIClient(catalystUrl, logger, auth.apiKey);
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
if (!projectName && !skipPrompts) {
|
|
@@ -104,8 +104,11 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
|
|
|
104
104
|
if (!value || value.trim().length === 0) {
|
|
105
105
|
return 'Project name is required';
|
|
106
106
|
}
|
|
107
|
-
if (
|
|
108
|
-
const exists = await projectExists(
|
|
107
|
+
if (apiClient && auth && orgId) {
|
|
108
|
+
const exists = await projectExists(apiClient, {
|
|
109
|
+
name: value,
|
|
110
|
+
organization_id: orgId,
|
|
111
|
+
});
|
|
109
112
|
if (exists) {
|
|
110
113
|
return `Project with name '${value}' already exists in this organization`;
|
|
111
114
|
}
|
|
@@ -117,13 +120,13 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
|
|
|
117
120
|
}
|
|
118
121
|
projectName = projectName || 'My First Agent';
|
|
119
122
|
|
|
120
|
-
//
|
|
123
|
+
// Generate disk-friendly directory name
|
|
121
124
|
const dirName = projectName === '.' ? '.' : sanitizeDirectoryName(projectName);
|
|
122
125
|
|
|
123
|
-
//
|
|
126
|
+
// Determine destination directory
|
|
124
127
|
// Expand ~ to home directory
|
|
125
128
|
let expandedTargetDir = targetDir;
|
|
126
|
-
if (expandedTargetDir
|
|
129
|
+
if (expandedTargetDir?.startsWith('~')) {
|
|
127
130
|
expandedTargetDir = expandedTargetDir.replace(/^~/, homedir());
|
|
128
131
|
}
|
|
129
132
|
const baseDir = expandedTargetDir ? resolve(expandedTargetDir) : process.cwd();
|
|
@@ -155,7 +158,7 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
|
|
|
155
158
|
return;
|
|
156
159
|
}
|
|
157
160
|
rmSync(dest, { recursive: true, force: true });
|
|
158
|
-
tui.success(`Deleted ${dest}
|
|
161
|
+
tui.success(`Deleted ${dest}`);
|
|
159
162
|
} else {
|
|
160
163
|
logger.fatal(`Directory ${dest} already exists and is not empty.`, true);
|
|
161
164
|
}
|
|
@@ -192,7 +195,7 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
|
|
|
192
195
|
|
|
193
196
|
tui.info(`✨ Using template: ${tui.bold(selectedTemplate.name)}`);
|
|
194
197
|
|
|
195
|
-
//
|
|
198
|
+
// Download template
|
|
196
199
|
await downloadTemplate({
|
|
197
200
|
dest,
|
|
198
201
|
template: selectedTemplate,
|
|
@@ -201,7 +204,7 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
|
|
|
201
204
|
logger,
|
|
202
205
|
});
|
|
203
206
|
|
|
204
|
-
//
|
|
207
|
+
// Setup project (replace placeholders, install deps, build)
|
|
205
208
|
await setupProject({
|
|
206
209
|
dest,
|
|
207
210
|
projectName: projectName === '.' ? basename(dest) : projectName,
|
|
@@ -211,58 +214,153 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
|
|
|
211
214
|
logger,
|
|
212
215
|
});
|
|
213
216
|
|
|
214
|
-
|
|
217
|
+
const resourceConfig: ResourcesTypes = Resources.parse({});
|
|
218
|
+
|
|
219
|
+
if (auth && apiClient && catalystClient && orgId && region) {
|
|
220
|
+
// Fetch resources for selected org and region using Catalyst API
|
|
221
|
+
const resources = await tui.spinner({
|
|
222
|
+
message: 'Fetching resources',
|
|
223
|
+
clearOnSuccess: true,
|
|
224
|
+
callback: async () => {
|
|
225
|
+
return listResources(catalystClient, orgId, region);
|
|
226
|
+
},
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
logger.debug(`Resources for org ${orgId} in region ${region}:`, resources);
|
|
230
|
+
|
|
231
|
+
const choices = await enquirer.prompt<{
|
|
232
|
+
db_action: string;
|
|
233
|
+
s3_action: string;
|
|
234
|
+
}>([
|
|
235
|
+
{
|
|
236
|
+
type: 'select',
|
|
237
|
+
name: 'db_action',
|
|
238
|
+
message: 'Create SQL Database?',
|
|
239
|
+
choices: [
|
|
240
|
+
{ name: 'Create New', message: 'Create a new (free)' },
|
|
241
|
+
{ name: 'Skip', message: 'Skip or Setup later' },
|
|
242
|
+
...resources.db.map((db) => ({
|
|
243
|
+
name: db.name,
|
|
244
|
+
message: `Use database: ${db.name}`,
|
|
245
|
+
})),
|
|
246
|
+
],
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
type: 'select',
|
|
250
|
+
name: 's3_action',
|
|
251
|
+
message: 'Create Storage Bucket?',
|
|
252
|
+
choices: [
|
|
253
|
+
{ name: 'Create New', message: 'Create a new (free)' },
|
|
254
|
+
{ name: 'Skip', message: 'Skip or Setup later' },
|
|
255
|
+
...resources.s3.map((db) => ({
|
|
256
|
+
name: db.bucket_name,
|
|
257
|
+
message: `Use bucket: ${db.bucket_name}`,
|
|
258
|
+
})),
|
|
259
|
+
],
|
|
260
|
+
},
|
|
261
|
+
]);
|
|
262
|
+
switch (choices.s3_action) {
|
|
263
|
+
case 'Create New': {
|
|
264
|
+
const created = await tui.spinner({
|
|
265
|
+
message: 'Provisioning New Bucket',
|
|
266
|
+
clearOnSuccess: true,
|
|
267
|
+
callback: async () => {
|
|
268
|
+
return createResources(catalystClient, orgId, region!, [{ type: 's3' }]);
|
|
269
|
+
},
|
|
270
|
+
});
|
|
271
|
+
resourceConfig.storage = created[0].name;
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
case 'Skip': {
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
default: {
|
|
278
|
+
resourceConfig.storage = choices.s3_action;
|
|
279
|
+
break;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
switch (choices.db_action) {
|
|
283
|
+
case 'Create New': {
|
|
284
|
+
const created = await tui.spinner({
|
|
285
|
+
message: 'Provisioning New SQL Database',
|
|
286
|
+
clearOnSuccess: true,
|
|
287
|
+
callback: async () => {
|
|
288
|
+
return createResources(catalystClient, orgId, region!, [{ type: 'db' }]);
|
|
289
|
+
},
|
|
290
|
+
});
|
|
291
|
+
resourceConfig.db = created[0].name;
|
|
292
|
+
break;
|
|
293
|
+
}
|
|
294
|
+
case 'Skip': {
|
|
295
|
+
break;
|
|
296
|
+
}
|
|
297
|
+
default: {
|
|
298
|
+
resourceConfig.db = choices.db_action;
|
|
299
|
+
break;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
if (auth && apiClient && orgId) {
|
|
215
305
|
let projectId: string | undefined;
|
|
216
306
|
|
|
217
|
-
await tui.spinner(
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
307
|
+
await tui.spinner({
|
|
308
|
+
message: 'Registering your project',
|
|
309
|
+
clearOnSuccess: true,
|
|
310
|
+
callback: async () => {
|
|
311
|
+
const project = await projectCreate(apiClient, {
|
|
312
|
+
name: projectName,
|
|
313
|
+
organization_id: orgId,
|
|
314
|
+
provider: 'bunjs',
|
|
315
|
+
});
|
|
316
|
+
projectId = project.id;
|
|
225
317
|
return createProjectConfig(dest, {
|
|
226
|
-
projectId:
|
|
318
|
+
projectId: project.id,
|
|
227
319
|
orgId,
|
|
228
|
-
apiKey:
|
|
320
|
+
apiKey: project.api_key,
|
|
321
|
+
deployment: {
|
|
322
|
+
resources: resourceConfig,
|
|
323
|
+
},
|
|
229
324
|
});
|
|
230
|
-
}
|
|
231
|
-
tui.fatal(res.message ?? 'failed to register project');
|
|
325
|
+
},
|
|
232
326
|
});
|
|
233
327
|
|
|
234
328
|
// After registration, push any existing env/secrets from .env.production
|
|
235
329
|
if (projectId) {
|
|
236
|
-
await tui.spinner(
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
330
|
+
await tui.spinner({
|
|
331
|
+
message: 'Syncing environment variables',
|
|
332
|
+
clearOnSuccess: true,
|
|
333
|
+
callback: async () => {
|
|
334
|
+
try {
|
|
335
|
+
const envFilePath = await findEnvFile(dest);
|
|
336
|
+
const localEnv = await readEnvFile(envFilePath);
|
|
337
|
+
const filteredEnv = filterAgentuitySdkKeys(localEnv);
|
|
241
338
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
339
|
+
if (Object.keys(filteredEnv).length > 0) {
|
|
340
|
+
const { env, secrets } = splitEnvAndSecrets(filteredEnv);
|
|
341
|
+
await projectEnvUpdate(apiClient, {
|
|
342
|
+
id: projectId as string,
|
|
343
|
+
env,
|
|
344
|
+
secrets,
|
|
345
|
+
});
|
|
346
|
+
logger.debug(
|
|
347
|
+
`Synced ${Object.keys(filteredEnv).length} environment variables to cloud`
|
|
348
|
+
);
|
|
349
|
+
}
|
|
350
|
+
} catch (error) {
|
|
351
|
+
// Non-fatal: just log the error
|
|
352
|
+
logger.debug('Failed to sync environment variables:', error);
|
|
252
353
|
}
|
|
253
|
-
}
|
|
254
|
-
// Non-fatal: just log the error
|
|
255
|
-
logger.debug('Failed to sync environment variables:', error);
|
|
256
|
-
}
|
|
354
|
+
},
|
|
257
355
|
});
|
|
258
356
|
}
|
|
259
357
|
}
|
|
260
358
|
|
|
261
|
-
//
|
|
359
|
+
// Show completion message
|
|
262
360
|
tui.success('✨ Project created successfully!\n');
|
|
263
361
|
tui.info('Next steps:');
|
|
264
362
|
if (dirName !== '.') {
|
|
265
|
-
const dirDisplay = cwd()
|
|
363
|
+
const dirDisplay = cwd() === targetDir ? basename(dirName) : dest;
|
|
266
364
|
tui.newline();
|
|
267
365
|
console.log(` 1. ${tui.bold(`cd ${dirDisplay}`)}`);
|
|
268
366
|
console.log(` 2. ${tui.bold('bun run dev')}`);
|
package/src/cmd/secret/delete.ts
CHANGED
|
@@ -2,47 +2,32 @@ import { z } from 'zod';
|
|
|
2
2
|
import { createSubcommand } from '../../types';
|
|
3
3
|
import * as tui from '../../tui';
|
|
4
4
|
import { projectEnvDelete } from '@agentuity/server';
|
|
5
|
-
import { getAPIBaseURL, APIClient } from '../../api';
|
|
6
|
-
import { loadProjectConfig } from '../../config';
|
|
7
5
|
import { findEnvFile, readEnvFile, writeEnvFile, filterAgentuitySdkKeys } from '../../env-util';
|
|
8
6
|
|
|
9
7
|
export const deleteSubcommand = createSubcommand({
|
|
10
8
|
name: 'delete',
|
|
11
9
|
aliases: ['del', 'remove', 'rm'],
|
|
12
10
|
description: 'Delete a secret',
|
|
13
|
-
|
|
11
|
+
requires: { auth: true, project: true, apiClient: true },
|
|
14
12
|
schema: {
|
|
15
13
|
args: z.object({
|
|
16
14
|
key: z.string().describe('the secret key to delete'),
|
|
17
15
|
}),
|
|
18
|
-
options: z.object({
|
|
19
|
-
dir: z.string().optional().describe('project directory (default: current directory)'),
|
|
20
|
-
}),
|
|
21
16
|
},
|
|
22
17
|
|
|
23
18
|
async handler(ctx) {
|
|
24
|
-
const { args,
|
|
25
|
-
const dir = opts?.dir ?? process.cwd();
|
|
26
|
-
|
|
27
|
-
// Load project config to get project ID
|
|
28
|
-
const projectConfig = await loadProjectConfig(dir);
|
|
29
|
-
if (!projectConfig) {
|
|
30
|
-
tui.fatal(`No Agentuity project found in ${dir}. Missing agentuity.json`);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const apiUrl = getAPIBaseURL(config);
|
|
34
|
-
const client = new APIClient(apiUrl, config);
|
|
19
|
+
const { args, apiClient, project, projectDir } = ctx;
|
|
35
20
|
|
|
36
21
|
// Delete from cloud (using secrets field)
|
|
37
22
|
await tui.spinner('Deleting secret from cloud', () => {
|
|
38
|
-
return projectEnvDelete(
|
|
39
|
-
id:
|
|
23
|
+
return projectEnvDelete(apiClient, {
|
|
24
|
+
id: project.projectId,
|
|
40
25
|
secrets: [args.key],
|
|
41
26
|
});
|
|
42
27
|
});
|
|
43
28
|
|
|
44
29
|
// Update local .env.production file
|
|
45
|
-
const envFilePath = await findEnvFile(
|
|
30
|
+
const envFilePath = await findEnvFile(projectDir);
|
|
46
31
|
const currentEnv = await readEnvFile(envFilePath);
|
|
47
32
|
delete currentEnv[args.key];
|
|
48
33
|
|
package/src/cmd/secret/get.ts
CHANGED
|
@@ -2,20 +2,17 @@ import { z } from 'zod';
|
|
|
2
2
|
import { createSubcommand } from '../../types';
|
|
3
3
|
import * as tui from '../../tui';
|
|
4
4
|
import { projectGet } from '@agentuity/server';
|
|
5
|
-
import { getAPIBaseURL, APIClient } from '../../api';
|
|
6
|
-
import { loadProjectConfig } from '../../config';
|
|
7
5
|
import { maskSecret } from '../../env-util';
|
|
8
6
|
|
|
9
7
|
export const getSubcommand = createSubcommand({
|
|
10
8
|
name: 'get',
|
|
11
9
|
description: 'Get a secret value',
|
|
12
|
-
|
|
10
|
+
requires: { auth: true, project: true, apiClient: true },
|
|
13
11
|
schema: {
|
|
14
12
|
args: z.object({
|
|
15
13
|
key: z.string().describe('the secret key'),
|
|
16
14
|
}),
|
|
17
15
|
options: z.object({
|
|
18
|
-
dir: z.string().optional().describe('project directory (default: current directory)'),
|
|
19
16
|
mask: z
|
|
20
17
|
.boolean()
|
|
21
18
|
.default(!!process.stdout.isTTY)
|
|
@@ -24,25 +21,15 @@ export const getSubcommand = createSubcommand({
|
|
|
24
21
|
},
|
|
25
22
|
|
|
26
23
|
async handler(ctx) {
|
|
27
|
-
const { args, opts,
|
|
28
|
-
const dir = opts?.dir ?? process.cwd();
|
|
29
|
-
|
|
30
|
-
// Load project config to get project ID
|
|
31
|
-
const projectConfig = await loadProjectConfig(dir);
|
|
32
|
-
if (!projectConfig) {
|
|
33
|
-
tui.fatal(`No Agentuity project found in ${dir}. Missing agentuity.json`);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const apiUrl = getAPIBaseURL(config);
|
|
37
|
-
const client = new APIClient(apiUrl, config);
|
|
24
|
+
const { args, opts, apiClient, project } = ctx;
|
|
38
25
|
|
|
39
26
|
// Fetch project with unmasked secrets
|
|
40
|
-
const
|
|
41
|
-
return projectGet(
|
|
27
|
+
const projectData = await tui.spinner('Fetching secrets', () => {
|
|
28
|
+
return projectGet(apiClient, { id: project.projectId, mask: false });
|
|
42
29
|
});
|
|
43
30
|
|
|
44
31
|
// Look for the key in secrets
|
|
45
|
-
const value =
|
|
32
|
+
const value = projectData.secrets?.[args.key];
|
|
46
33
|
|
|
47
34
|
if (value === undefined) {
|
|
48
35
|
tui.fatal(`Secret '${args.key}' not found`);
|
package/src/cmd/secret/import.ts
CHANGED
|
@@ -2,8 +2,6 @@ import { z } from 'zod';
|
|
|
2
2
|
import { createSubcommand } from '../../types';
|
|
3
3
|
import * as tui from '../../tui';
|
|
4
4
|
import { projectEnvUpdate } from '@agentuity/server';
|
|
5
|
-
import { getAPIBaseURL, APIClient } from '../../api';
|
|
6
|
-
import { loadProjectConfig } from '../../config';
|
|
7
5
|
import {
|
|
8
6
|
findEnvFile,
|
|
9
7
|
readEnvFile,
|
|
@@ -15,25 +13,15 @@ import {
|
|
|
15
13
|
export const importSubcommand = createSubcommand({
|
|
16
14
|
name: 'import',
|
|
17
15
|
description: 'Import secrets from a file to cloud and local .env.production',
|
|
18
|
-
|
|
16
|
+
requires: { auth: true, project: true, apiClient: true },
|
|
19
17
|
schema: {
|
|
20
18
|
args: z.object({
|
|
21
19
|
file: z.string().describe('path to the .env file to import'),
|
|
22
20
|
}),
|
|
23
|
-
options: z.object({
|
|
24
|
-
dir: z.string().optional().describe('project directory (default: current directory)'),
|
|
25
|
-
}),
|
|
26
21
|
},
|
|
27
22
|
|
|
28
23
|
async handler(ctx) {
|
|
29
|
-
const { args,
|
|
30
|
-
const dir = opts?.dir ?? process.cwd();
|
|
31
|
-
|
|
32
|
-
// Load project config to get project ID
|
|
33
|
-
const projectConfig = await loadProjectConfig(dir);
|
|
34
|
-
if (!projectConfig) {
|
|
35
|
-
tui.fatal(`No Agentuity project found in ${dir}. Missing agentuity.json`);
|
|
36
|
-
}
|
|
24
|
+
const { args, apiClient, project, projectDir } = ctx;
|
|
37
25
|
|
|
38
26
|
// Read the import file
|
|
39
27
|
const importedSecrets = await readEnvFile(args.file);
|
|
@@ -51,19 +39,16 @@ export const importSubcommand = createSubcommand({
|
|
|
51
39
|
return;
|
|
52
40
|
}
|
|
53
41
|
|
|
54
|
-
const apiUrl = getAPIBaseURL(config);
|
|
55
|
-
const client = new APIClient(apiUrl, config);
|
|
56
|
-
|
|
57
42
|
// Push to cloud (using secrets field)
|
|
58
43
|
await tui.spinner('Importing secrets to cloud', () => {
|
|
59
|
-
return projectEnvUpdate(
|
|
60
|
-
id:
|
|
44
|
+
return projectEnvUpdate(apiClient, {
|
|
45
|
+
id: project.projectId,
|
|
61
46
|
secrets: filteredSecrets,
|
|
62
47
|
});
|
|
63
48
|
});
|
|
64
49
|
|
|
65
50
|
// Merge with local .env.production file
|
|
66
|
-
const localEnvPath = await findEnvFile(
|
|
51
|
+
const localEnvPath = await findEnvFile(projectDir);
|
|
67
52
|
const localEnv = await readEnvFile(localEnvPath);
|
|
68
53
|
const mergedEnv = mergeEnvVars(localEnv, filteredSecrets);
|
|
69
54
|
|
package/src/cmd/secret/list.ts
CHANGED
|
@@ -2,18 +2,15 @@ import { z } from 'zod';
|
|
|
2
2
|
import { createSubcommand } from '../../types';
|
|
3
3
|
import * as tui from '../../tui';
|
|
4
4
|
import { projectGet } from '@agentuity/server';
|
|
5
|
-
import { getAPIBaseURL, APIClient } from '../../api';
|
|
6
|
-
import { loadProjectConfig } from '../../config';
|
|
7
5
|
import { maskSecret } from '../../env-util';
|
|
8
6
|
|
|
9
7
|
export const listSubcommand = createSubcommand({
|
|
10
8
|
name: 'list',
|
|
11
9
|
aliases: ['ls'],
|
|
12
10
|
description: 'List all secrets',
|
|
13
|
-
|
|
11
|
+
requires: { auth: true, project: true, apiClient: true },
|
|
14
12
|
schema: {
|
|
15
13
|
options: z.object({
|
|
16
|
-
dir: z.string().optional().describe('project directory (default: current directory)'),
|
|
17
14
|
mask: z
|
|
18
15
|
.boolean()
|
|
19
16
|
.default(!!process.stdout.isTTY)
|
|
@@ -22,24 +19,14 @@ export const listSubcommand = createSubcommand({
|
|
|
22
19
|
},
|
|
23
20
|
|
|
24
21
|
async handler(ctx) {
|
|
25
|
-
const { opts,
|
|
26
|
-
const dir = opts?.dir ?? process.cwd();
|
|
27
|
-
|
|
28
|
-
// Load project config to get project ID
|
|
29
|
-
const projectConfig = await loadProjectConfig(dir);
|
|
30
|
-
if (!projectConfig) {
|
|
31
|
-
tui.fatal(`No Agentuity project found in ${dir}. Missing agentuity.json`);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const apiUrl = getAPIBaseURL(config);
|
|
35
|
-
const client = new APIClient(apiUrl, config);
|
|
22
|
+
const { opts, apiClient, project } = ctx;
|
|
36
23
|
|
|
37
24
|
// Fetch project with unmasked secrets
|
|
38
|
-
const
|
|
39
|
-
return projectGet(
|
|
25
|
+
const projectData = await tui.spinner('Fetching secrets', () => {
|
|
26
|
+
return projectGet(apiClient, { id: project.projectId, mask: false });
|
|
40
27
|
});
|
|
41
28
|
|
|
42
|
-
const secrets =
|
|
29
|
+
const secrets = projectData.secrets || {};
|
|
43
30
|
|
|
44
31
|
if (Object.keys(secrets).length === 0) {
|
|
45
32
|
tui.info('No secrets found');
|