@agentuity/cli 0.0.42 → 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/bin/cli.ts +7 -5
- 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 +2 -0
- package/dist/cmd/auth/whoami.d.ts.map +1 -0
- 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/index.d.ts +1 -1
- package/dist/cmd/bundle/index.d.ts.map +1 -1
- 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 -0
- 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 -0
- 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 +2 -0
- package/dist/cmd/env/delete.d.ts.map +1 -0
- package/dist/cmd/env/get.d.ts +2 -0
- package/dist/cmd/env/get.d.ts.map +1 -0
- package/dist/cmd/env/import.d.ts +2 -0
- package/dist/cmd/env/import.d.ts.map +1 -0
- package/dist/cmd/env/index.d.ts +2 -0
- package/dist/cmd/env/index.d.ts.map +1 -0
- package/dist/cmd/env/list.d.ts.map +1 -0
- package/dist/cmd/env/pull.d.ts +2 -0
- package/dist/cmd/env/pull.d.ts.map +1 -0
- package/dist/cmd/env/push.d.ts +2 -0
- package/dist/cmd/env/push.d.ts.map +1 -0
- package/dist/cmd/env/set.d.ts +2 -0
- package/dist/cmd/env/set.d.ts.map +1 -0
- 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/download.d.ts +1 -1
- package/dist/cmd/project/download.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 +5 -1
- package/dist/cmd/project/template-flow.d.ts.map +1 -1
- package/dist/cmd/secret/delete.d.ts +2 -0
- package/dist/cmd/secret/delete.d.ts.map +1 -0
- package/dist/cmd/secret/get.d.ts +2 -0
- package/dist/cmd/secret/get.d.ts.map +1 -0
- package/dist/cmd/secret/import.d.ts +2 -0
- package/dist/cmd/secret/import.d.ts.map +1 -0
- package/dist/cmd/secret/index.d.ts +2 -0
- package/dist/cmd/secret/index.d.ts.map +1 -0
- package/dist/cmd/secret/list.d.ts +2 -0
- package/dist/cmd/secret/list.d.ts.map +1 -0
- package/dist/cmd/secret/pull.d.ts +2 -0
- package/dist/cmd/secret/pull.d.ts.map +1 -0
- package/dist/cmd/secret/push.d.ts +2 -0
- package/dist/cmd/secret/push.d.ts.map +1 -0
- package/dist/cmd/secret/set.d.ts +2 -0
- package/dist/cmd/secret/set.d.ts.map +1 -0
- package/dist/cmd/version/index.d.ts.map +1 -1
- package/dist/config.d.ts +11 -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/env-util.d.ts +67 -0
- package/dist/env-util.d.ts.map +1 -0
- package/dist/env-util.test.d.ts +2 -0
- package/dist/env-util.test.d.ts.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/schema-parser.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 +32 -2
- package/dist/tui.d.ts.map +1 -1
- package/dist/types.d.ts +250 -127
- 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 +709 -36
- package/src/cmd/auth/api.ts +10 -16
- package/src/cmd/auth/index.ts +3 -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 +69 -0
- 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 +11 -11
- package/src/cmd/bundle/patch/aisdk.ts +1 -1
- package/src/cmd/bundle/plugin.ts +373 -53
- package/src/cmd/cloud/deploy.ts +336 -0
- package/src/cmd/cloud/domain.ts +92 -0
- package/src/cmd/cloud/index.ts +11 -0
- 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 +362 -34
- package/src/cmd/dev/templates.ts +84 -0
- package/src/cmd/env/delete.ts +47 -0
- package/src/cmd/env/get.ts +53 -0
- package/src/cmd/env/import.ts +102 -0
- package/src/cmd/env/index.ts +22 -0
- package/src/cmd/env/list.ts +56 -0
- package/src/cmd/env/pull.ts +80 -0
- package/src/cmd/env/push.ts +37 -0
- package/src/cmd/env/set.ts +71 -0
- 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 +3 -3
- package/src/cmd/project/list.ts +8 -8
- package/src/cmd/project/show.ts +3 -7
- package/src/cmd/project/template-flow.ts +186 -48
- package/src/cmd/secret/delete.ts +40 -0
- package/src/cmd/secret/get.ts +54 -0
- package/src/cmd/secret/import.ts +64 -0
- package/src/cmd/secret/index.ts +22 -0
- package/src/cmd/secret/list.ts +56 -0
- package/src/cmd/secret/pull.ts +78 -0
- package/src/cmd/secret/push.ts +37 -0
- package/src/cmd/secret/set.ts +45 -0
- package/src/cmd/version/index.ts +2 -1
- package/src/config.ts +257 -27
- 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 +194 -0
- package/src/env-util.ts +290 -0
- package/src/index.ts +5 -1
- package/src/schema-parser.ts +2 -3
- package/src/steps.ts +144 -10
- package/src/terminal.ts +24 -23
- package/src/tui.ts +208 -68
- package/src/types.ts +292 -202
- 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.map +0 -1
- package/dist/cmd/example/index.d.ts.map +0 -1
- 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/dist/logger.d.ts +0 -24
- package/dist/logger.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/logger.ts +0 -235
- /package/dist/cmd/{example → cloud}/deploy.d.ts +0 -0
- /package/dist/cmd/{example → cloud}/index.d.ts +0 -0
- /package/dist/cmd/{example → env}/list.d.ts +0 -0
package/src/config.ts
CHANGED
|
@@ -1,18 +1,29 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import type { Logger } from '@agentuity/core';
|
|
4
|
+
import {
|
|
5
|
+
BuildMetadataSchema,
|
|
6
|
+
type BuildMetadata,
|
|
7
|
+
getServiceUrls,
|
|
8
|
+
APIClient as ServerAPIClient,
|
|
9
|
+
} from '@agentuity/server';
|
|
1
10
|
import { YAML } from 'bun';
|
|
2
|
-
import { join, extname, basename } from 'node:path';
|
|
11
|
+
import { join, extname, basename, resolve, normalize } from 'node:path';
|
|
3
12
|
import { homedir } from 'node:os';
|
|
4
13
|
import { mkdir, readdir, readFile, writeFile, chmod } from 'node:fs/promises';
|
|
14
|
+
import JSON5 from 'json5';
|
|
5
15
|
import type { Config, Profile, AuthData } from './types';
|
|
6
|
-
import { ConfigSchema, ProjectSchema
|
|
16
|
+
import { ConfigSchema, ProjectSchema } from './types';
|
|
7
17
|
import * as tui from './tui';
|
|
8
|
-
|
|
18
|
+
|
|
19
|
+
export const defaultProfileName = 'production';
|
|
9
20
|
|
|
10
21
|
export function getDefaultConfigDir(): string {
|
|
11
22
|
return join(homedir(), '.config', 'agentuity');
|
|
12
23
|
}
|
|
13
24
|
|
|
14
25
|
export function getDefaultConfigPath(): string {
|
|
15
|
-
return join(getDefaultConfigDir(), '
|
|
26
|
+
return join(getDefaultConfigDir(), defaultProfileName + '.yaml');
|
|
16
27
|
}
|
|
17
28
|
|
|
18
29
|
export function getProfilePath(): string {
|
|
@@ -71,7 +82,7 @@ export async function fetchProfiles(): Promise<Profile[]> {
|
|
|
71
82
|
const content = await readFile(filePath, 'utf-8');
|
|
72
83
|
const match = nameRegex.exec(content);
|
|
73
84
|
|
|
74
|
-
if (match
|
|
85
|
+
if (match?.[1]) {
|
|
75
86
|
profiles.push({
|
|
76
87
|
name: match[1],
|
|
77
88
|
filename: filePath,
|
|
@@ -103,22 +114,24 @@ export async function loadConfig(customPath?: string): Promise<Config | null> {
|
|
|
103
114
|
try {
|
|
104
115
|
const file = Bun.file(configPath);
|
|
105
116
|
const exists = await file.exists();
|
|
117
|
+
let result: ReturnType<typeof ConfigSchema.safeParse>;
|
|
106
118
|
|
|
107
|
-
if (
|
|
108
|
-
|
|
109
|
-
|
|
119
|
+
if (exists) {
|
|
120
|
+
const content = await file.text();
|
|
121
|
+
const config = YAML.parse(content);
|
|
110
122
|
|
|
111
|
-
|
|
112
|
-
|
|
123
|
+
// check to see if this is a legacy config file that might not have the required name
|
|
124
|
+
// and in this case we can just use the filename
|
|
125
|
+
const _config = config as { name?: string };
|
|
126
|
+
if (!_config.name) {
|
|
127
|
+
_config.name = basename(configPath).replace(extname(configPath), '');
|
|
128
|
+
}
|
|
113
129
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
if (!_config.name) {
|
|
118
|
-
_config.name = basename(configPath).replace(extname(configPath), '');
|
|
130
|
+
result = ConfigSchema.safeParse(config);
|
|
131
|
+
} else {
|
|
132
|
+
result = ConfigSchema.safeParse({ name: defaultProfileName });
|
|
119
133
|
}
|
|
120
134
|
|
|
121
|
-
const result = ConfigSchema.safeParse(config);
|
|
122
135
|
if (!result.success) {
|
|
123
136
|
tui.error(`Invalid config in ${configPath}:`);
|
|
124
137
|
for (const issue of result.error.issues) {
|
|
@@ -128,6 +141,36 @@ export async function loadConfig(customPath?: string): Promise<Config | null> {
|
|
|
128
141
|
process.exit(1);
|
|
129
142
|
}
|
|
130
143
|
|
|
144
|
+
// allow environment variables to override
|
|
145
|
+
const overrides = result.data.overrides ?? ConfigSchema.shape.overrides.parse({});
|
|
146
|
+
if (overrides) {
|
|
147
|
+
if (process.env.AGENTUITY_API_URL) {
|
|
148
|
+
overrides.api_url = process.env.AGENTUITY_API_URL;
|
|
149
|
+
}
|
|
150
|
+
if (process.env.AGENTUITY_APP_URL) {
|
|
151
|
+
overrides.app_url = process.env.AGENTUITY_APP_URL;
|
|
152
|
+
}
|
|
153
|
+
if (process.env.AGENTUITY_CATALYST_URL) {
|
|
154
|
+
overrides.catalyst_url = process.env.AGENTUITY_CATALYST_URL;
|
|
155
|
+
}
|
|
156
|
+
if (process.env.AGENTUITY_TRANSPORT_URL) {
|
|
157
|
+
overrides.transport_url = process.env.AGENTUITY_TRANSPORT_URL;
|
|
158
|
+
}
|
|
159
|
+
if (process.env.AGENTUITY_KEYVALUE_URL) {
|
|
160
|
+
overrides.kv_url = process.env.AGENTUITY_KEYVALUE_URL;
|
|
161
|
+
}
|
|
162
|
+
if (process.env.AGENTUITY_OBJECTSTORE_URL) {
|
|
163
|
+
overrides.object_url = process.env.AGENTUITY_OBJECTSTORE_URL;
|
|
164
|
+
}
|
|
165
|
+
if (process.env.AGENTUITY_VECTOR_URL) {
|
|
166
|
+
overrides.vector_url = process.env.AGENTUITY_VECTOR_URL;
|
|
167
|
+
}
|
|
168
|
+
if (process.env.AGENTUITY_STREAM_URL) {
|
|
169
|
+
overrides.stream_url = process.env.AGENTUITY_STREAM_URL;
|
|
170
|
+
}
|
|
171
|
+
result.data.overrides = overrides;
|
|
172
|
+
}
|
|
173
|
+
|
|
131
174
|
return result.data;
|
|
132
175
|
} catch (error) {
|
|
133
176
|
if (error instanceof Error) {
|
|
@@ -189,8 +232,18 @@ export async function saveConfig(config: Config, customPath?: string): Promise<v
|
|
|
189
232
|
await chmod(configPath, 0o600);
|
|
190
233
|
}
|
|
191
234
|
|
|
235
|
+
async function getOrInitConfig(): Promise<Config> {
|
|
236
|
+
const config = await loadConfig();
|
|
237
|
+
if (config) {
|
|
238
|
+
return config;
|
|
239
|
+
}
|
|
240
|
+
const profilePath = await getProfile();
|
|
241
|
+
const name = basename(profilePath, '.yaml');
|
|
242
|
+
return { name };
|
|
243
|
+
}
|
|
244
|
+
|
|
192
245
|
export async function saveAuth(auth: AuthData): Promise<void> {
|
|
193
|
-
const config =
|
|
246
|
+
const config = await getOrInitConfig();
|
|
194
247
|
config.auth = {
|
|
195
248
|
api_key: auth.apiKey,
|
|
196
249
|
user_id: auth.userId,
|
|
@@ -202,7 +255,7 @@ export async function saveAuth(auth: AuthData): Promise<void> {
|
|
|
202
255
|
}
|
|
203
256
|
|
|
204
257
|
export async function clearAuth(): Promise<void> {
|
|
205
|
-
const config =
|
|
258
|
+
const config = await getOrInitConfig();
|
|
206
259
|
config.auth = {
|
|
207
260
|
api_key: '',
|
|
208
261
|
user_id: '',
|
|
@@ -213,7 +266,31 @@ export async function clearAuth(): Promise<void> {
|
|
|
213
266
|
await saveConfig(config);
|
|
214
267
|
}
|
|
215
268
|
|
|
269
|
+
export async function saveProjectDir(projectDir: string): Promise<void> {
|
|
270
|
+
const config = await getOrInitConfig();
|
|
271
|
+
config.preferences = config.preferences || {};
|
|
272
|
+
const normalized = resolve(normalize(projectDir));
|
|
273
|
+
(config.preferences as Record<string, unknown>).project_dir = normalized;
|
|
274
|
+
await saveConfig(config);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
export async function saveOrgId(orgId: string): Promise<void> {
|
|
278
|
+
const config = await getOrInitConfig();
|
|
279
|
+
config.preferences = config.preferences || {};
|
|
280
|
+
(config.preferences as Record<string, unknown>).orgId = orgId;
|
|
281
|
+
await saveConfig(config);
|
|
282
|
+
}
|
|
283
|
+
|
|
216
284
|
export async function getAuth(): Promise<AuthData | null> {
|
|
285
|
+
// allow automated login from environment variables if present
|
|
286
|
+
if (process.env.AGENTUITY_CLI_API_KEY && process.env.AGENTUITY_USER_ID) {
|
|
287
|
+
return {
|
|
288
|
+
apiKey: process.env.AGENTUITY_CLI_API_KEY,
|
|
289
|
+
userId: process.env.AGENTUITY_USER_ID,
|
|
290
|
+
expires: new Date(Date.now() + 30 * 60_000),
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
|
|
217
294
|
const config = await loadConfig();
|
|
218
295
|
if (!config) return null;
|
|
219
296
|
const auth = config.auth as { api_key?: string; user_id?: string; expires?: number } | undefined;
|
|
@@ -255,6 +332,81 @@ function getPlaceholderValue(schema: z.ZodTypeAny): string {
|
|
|
255
332
|
}
|
|
256
333
|
}
|
|
257
334
|
|
|
335
|
+
function extractDefaultValue(schema: z.ZodTypeAny): unknown {
|
|
336
|
+
let unwrapped = schema;
|
|
337
|
+
|
|
338
|
+
// Unwrap optional layers
|
|
339
|
+
while (unwrapped instanceof z.ZodOptional) {
|
|
340
|
+
unwrapped = (unwrapped._def as unknown as { innerType: z.ZodTypeAny }).innerType;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Check if it's a ZodDefault (has defaultValue in def or _def)
|
|
344
|
+
const checkDef = (obj: unknown): unknown => {
|
|
345
|
+
if (typeof obj !== 'object' || obj === null) return undefined;
|
|
346
|
+
const anyObj = obj as Record<string, unknown>;
|
|
347
|
+
|
|
348
|
+
// Check `def` property first (used in some Zod versions)
|
|
349
|
+
if ('def' in anyObj && typeof anyObj.def === 'object' && anyObj.def !== null) {
|
|
350
|
+
const def = anyObj.def as Record<string, unknown>;
|
|
351
|
+
if (def.type === 'default' && 'defaultValue' in def) {
|
|
352
|
+
const val = def.defaultValue;
|
|
353
|
+
return typeof val === 'function' ? (val as () => unknown)() : val;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// Check `_def` property (standard Zod property)
|
|
358
|
+
if ('_def' in anyObj && typeof anyObj._def === 'object' && anyObj._def !== null) {
|
|
359
|
+
const def = anyObj._def as Record<string, unknown>;
|
|
360
|
+
if (def.type === 'default' && 'defaultValue' in def) {
|
|
361
|
+
const val = def.defaultValue;
|
|
362
|
+
return typeof val === 'function' ? (val as () => unknown)() : val;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
return undefined;
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
return checkDef(unwrapped);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
function getValueWithDefaults(schema: z.ZodTypeAny, providedValue: unknown): unknown {
|
|
373
|
+
// If value is explicitly provided, use it
|
|
374
|
+
if (providedValue !== undefined) {
|
|
375
|
+
return providedValue;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// Try to extract default value
|
|
379
|
+
const defaultValue = extractDefaultValue(schema);
|
|
380
|
+
if (defaultValue !== undefined) {
|
|
381
|
+
return defaultValue;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// For optional fields without defaults, check if it's an object
|
|
385
|
+
let unwrapped = schema;
|
|
386
|
+
if (schema instanceof z.ZodOptional) {
|
|
387
|
+
unwrapped = (schema._def as unknown as { innerType: z.ZodTypeAny }).innerType;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// If it's an object schema, recursively populate defaults
|
|
391
|
+
if (unwrapped instanceof z.ZodObject) {
|
|
392
|
+
const shape = unwrapped.shape;
|
|
393
|
+
const result: Record<string, unknown> = {};
|
|
394
|
+
let hasAnyDefaults = false;
|
|
395
|
+
|
|
396
|
+
for (const [key, fieldSchema] of Object.entries(shape)) {
|
|
397
|
+
const fieldValue = getValueWithDefaults(fieldSchema as z.ZodTypeAny, undefined);
|
|
398
|
+
if (fieldValue !== undefined) {
|
|
399
|
+
result[key] = fieldValue;
|
|
400
|
+
hasAnyDefaults = true;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
return hasAnyDefaults ? result : undefined;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
return undefined;
|
|
408
|
+
}
|
|
409
|
+
|
|
258
410
|
export function generateYAMLTemplate(name: string): string {
|
|
259
411
|
const lines: string[] = [];
|
|
260
412
|
|
|
@@ -325,15 +477,61 @@ class ProjectConfigNotFoundExpection extends Error {
|
|
|
325
477
|
|
|
326
478
|
type ProjectConfig = z.infer<typeof ProjectSchema>;
|
|
327
479
|
|
|
328
|
-
|
|
329
|
-
|
|
480
|
+
function generateJSON5WithComments(
|
|
481
|
+
schema: z.ZodObject<z.ZodRawShape>,
|
|
482
|
+
data: Record<string, unknown>
|
|
483
|
+
): string {
|
|
484
|
+
const lines: string[] = ['{'];
|
|
485
|
+
const shape = schema.shape;
|
|
486
|
+
const keys = Object.keys(shape);
|
|
487
|
+
|
|
488
|
+
for (let i = 0; i < keys.length; i++) {
|
|
489
|
+
const key = keys[i];
|
|
490
|
+
const fieldSchema = shape[key] as z.ZodTypeAny;
|
|
491
|
+
const description = getSchemaDescription(fieldSchema);
|
|
492
|
+
const providedValue = data[key];
|
|
493
|
+
|
|
494
|
+
if (description) {
|
|
495
|
+
lines.push(` // ${description}`);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// Get value with defaults applied
|
|
499
|
+
const valueWithDefaults = getValueWithDefaults(fieldSchema, providedValue);
|
|
500
|
+
const safeValue = valueWithDefaults === undefined ? null : valueWithDefaults;
|
|
501
|
+
const jsonValue = JSON.stringify(safeValue, null, 2).replace(/\n/g, '\n ');
|
|
502
|
+
const comma = i < keys.length - 1 ? ',' : '';
|
|
503
|
+
lines.push(` ${JSON.stringify(key)}: ${jsonValue}${comma}`);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
lines.push('}');
|
|
507
|
+
return lines.join('\n');
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
export async function loadProjectConfig(
|
|
511
|
+
dir: string,
|
|
512
|
+
config?: Config | null
|
|
513
|
+
): Promise<ProjectConfig> {
|
|
514
|
+
let configPath = join(dir, 'agentuity.json');
|
|
515
|
+
|
|
516
|
+
// Check for profile-specific override if config is provided
|
|
517
|
+
if (config?.name) {
|
|
518
|
+
const profileConfigPath = join(dir, `agentuity.${config.name}.json`);
|
|
519
|
+
if (await Bun.file(profileConfigPath).exists()) {
|
|
520
|
+
configPath = profileConfigPath;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
|
|
330
524
|
const file = Bun.file(configPath);
|
|
331
525
|
if (!(await file.exists())) {
|
|
526
|
+
// TODO: check to see if a valid project that was created unauthenticated
|
|
527
|
+
// and then if so:
|
|
528
|
+
// 1. if authentication, offer to import the project
|
|
529
|
+
// 2. tell them that they need to login to use the command and import the project
|
|
332
530
|
throw new ProjectConfigNotFoundExpection();
|
|
333
531
|
}
|
|
334
532
|
const text = await file.text();
|
|
335
|
-
const
|
|
336
|
-
const result = ProjectSchema.safeParse(
|
|
533
|
+
const parsedConfig = JSON5.parse(text);
|
|
534
|
+
const result = ProjectSchema.safeParse(parsedConfig);
|
|
337
535
|
if (!result.success) {
|
|
338
536
|
tui.error(`Invalid project config at ${configPath}:`);
|
|
339
537
|
for (const issue of result.error.issues) {
|
|
@@ -350,16 +548,18 @@ type InitialProjectConfig = ProjectConfig & {
|
|
|
350
548
|
};
|
|
351
549
|
|
|
352
550
|
export async function createProjectConfig(dir: string, config: InitialProjectConfig) {
|
|
353
|
-
// Create a sanitized config without the apiKey for agentuity.json
|
|
354
551
|
const { apiKey, ...sanitizedConfig } = config;
|
|
355
552
|
|
|
356
553
|
const configPath = join(dir, 'agentuity.json');
|
|
357
|
-
const
|
|
358
|
-
await
|
|
554
|
+
const json5Content = generateJSON5WithComments(ProjectSchema, sanitizedConfig);
|
|
555
|
+
await Bun.write(configPath, json5Content + '\n');
|
|
359
556
|
|
|
360
557
|
const envPath = join(dir, '.env');
|
|
361
|
-
const
|
|
362
|
-
|
|
558
|
+
const comment =
|
|
559
|
+
'# AGENTUITY_SDK_KEY is a sensitive value and should not be committed to version control.';
|
|
560
|
+
const content = `${comment}\nAGENTUITY_SDK_KEY=${apiKey}\n`;
|
|
561
|
+
await Bun.write(envPath, content);
|
|
562
|
+
await chmod(envPath, 0o600);
|
|
363
563
|
}
|
|
364
564
|
|
|
365
565
|
export async function loadBuildMetadata(dir: string): Promise<BuildMetadata> {
|
|
@@ -381,3 +581,33 @@ export async function loadBuildMetadata(dir: string): Promise<BuildMetadata> {
|
|
|
381
581
|
}
|
|
382
582
|
return result.data;
|
|
383
583
|
}
|
|
584
|
+
|
|
585
|
+
export async function loadDevelopmentProjectSDKKey(
|
|
586
|
+
projectDir: string
|
|
587
|
+
): Promise<string | undefined> {
|
|
588
|
+
const files: string[] = ['.env.development', '.env.local', '.env'];
|
|
589
|
+
for (const filename of files) {
|
|
590
|
+
const fn = join(projectDir, filename);
|
|
591
|
+
if (existsSync(fn)) {
|
|
592
|
+
const buf = await Bun.file(fn).text();
|
|
593
|
+
const tok = buf.split(/\n/);
|
|
594
|
+
for (const t of tok) {
|
|
595
|
+
if (t.charAt(0) !== '#' && t.startsWith('AGENTUITY_SDK_KEY=')) {
|
|
596
|
+
const i = t.indexOf('=');
|
|
597
|
+
return t.substring(i + 1).trim();
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
export function getCatalystAPIClient(config: Config | null, logger: Logger, auth: AuthData) {
|
|
605
|
+
const serviceUrls = getServiceUrls();
|
|
606
|
+
const catalystUrl = config?.overrides?.catalyst_url ?? serviceUrls.catalyst;
|
|
607
|
+
return new ServerAPIClient(catalystUrl, logger, auth.apiKey);
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
export function getIONHost(config: Config | null) {
|
|
611
|
+
const url = new URL(config?.overrides?.ion_url ?? 'https://ion.agentuity.cloud');
|
|
612
|
+
return url.hostname;
|
|
613
|
+
}
|