@agentuity/cli 0.0.51 → 0.0.52
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/api.js +68 -0
- package/dist/api.js.map +1 -0
- package/dist/auth.js +225 -0
- package/dist/auth.js.map +1 -0
- package/dist/banner.js +35 -0
- package/dist/banner.js.map +1 -0
- package/dist/cli-logger.js +72 -0
- package/dist/cli-logger.js.map +1 -0
- package/dist/cli.js +822 -0
- package/dist/cli.js.map +1 -0
- package/dist/cmd/ai/capabilities/index.js +10 -0
- package/dist/cmd/ai/capabilities/index.js.map +1 -0
- package/dist/cmd/ai/capabilities/show.js +221 -0
- package/dist/cmd/ai/capabilities/show.js.map +1 -0
- package/dist/cmd/ai/index.js +11 -0
- package/dist/cmd/ai/index.js.map +1 -0
- package/dist/cmd/ai/prompt/index.js +10 -0
- package/dist/cmd/ai/prompt/index.js.map +1 -0
- package/dist/cmd/ai/prompt/llm.js +365 -0
- package/dist/cmd/ai/prompt/llm.js.map +1 -0
- package/dist/cmd/ai/schema/index.js +10 -0
- package/dist/cmd/ai/schema/index.js.map +1 -0
- package/dist/cmd/ai/schema/show.js +23 -0
- package/dist/cmd/ai/schema/show.js.map +1 -0
- package/dist/cmd/auth/api.js +85 -0
- package/dist/cmd/auth/api.js.map +1 -0
- package/dist/cmd/auth/index.js +13 -0
- package/dist/cmd/auth/index.js.map +1 -0
- package/dist/cmd/auth/login.js +84 -0
- package/dist/cmd/auth/login.js.map +1 -0
- package/dist/cmd/auth/logout.js +17 -0
- package/dist/cmd/auth/logout.js.map +1 -0
- package/dist/cmd/auth/signup.js +55 -0
- package/dist/cmd/auth/signup.js.map +1 -0
- package/dist/cmd/auth/ssh/add.js +239 -0
- package/dist/cmd/auth/ssh/add.js.map +1 -0
- package/dist/cmd/auth/ssh/api.js +53 -0
- package/dist/cmd/auth/ssh/api.js.map +1 -0
- package/dist/cmd/auth/ssh/delete.js +126 -0
- package/dist/cmd/auth/ssh/delete.js.map +1 -0
- package/dist/cmd/auth/ssh/index.js +11 -0
- package/dist/cmd/auth/ssh/index.js.map +1 -0
- package/dist/cmd/auth/ssh/list.js +70 -0
- package/dist/cmd/auth/ssh/list.js.map +1 -0
- package/dist/cmd/auth/whoami.js +68 -0
- package/dist/cmd/auth/whoami.js.map +1 -0
- package/dist/cmd/build/ast.js +608 -0
- package/dist/cmd/build/ast.js.map +1 -0
- package/dist/cmd/build/ast.test.js +389 -0
- package/dist/cmd/build/ast.test.js.map +1 -0
- package/dist/cmd/build/bundler.js +304 -0
- package/dist/cmd/build/bundler.js.map +1 -0
- package/dist/cmd/build/file.js +10 -0
- package/dist/cmd/build/file.js.map +1 -0
- package/dist/cmd/build/fix-duplicate-exports.js +167 -0
- package/dist/cmd/build/fix-duplicate-exports.js.map +1 -0
- package/dist/cmd/build/fix-duplicate-exports.test.js +300 -0
- package/dist/cmd/build/fix-duplicate-exports.test.js.map +1 -0
- package/dist/cmd/build/index.d.ts.map +1 -1
- package/dist/cmd/build/index.js +79 -0
- package/dist/cmd/build/index.js.map +1 -0
- package/dist/cmd/build/patch/_util.js +42 -0
- package/dist/cmd/build/patch/_util.js.map +1 -0
- package/dist/cmd/build/patch/aisdk.js +65 -0
- package/dist/cmd/build/patch/aisdk.js.map +1 -0
- package/dist/cmd/build/patch/index.js +97 -0
- package/dist/cmd/build/patch/index.js.map +1 -0
- package/dist/cmd/build/patch/llm.js +18 -0
- package/dist/cmd/build/patch/llm.js.map +1 -0
- package/dist/cmd/build/plugin.d.ts.map +1 -1
- package/dist/cmd/build/plugin.js +556 -0
- package/dist/cmd/build/plugin.js.map +1 -0
- package/dist/cmd/cloud/agents/index.js +133 -0
- package/dist/cmd/cloud/agents/index.js.map +1 -0
- package/dist/cmd/cloud/deploy.js +341 -0
- package/dist/cmd/cloud/deploy.js.map +1 -0
- package/dist/cmd/cloud/deployment/index.js +20 -0
- package/dist/cmd/cloud/deployment/index.js.map +1 -0
- package/dist/cmd/cloud/deployment/list.js +89 -0
- package/dist/cmd/cloud/deployment/list.js.map +1 -0
- package/dist/cmd/cloud/deployment/remove.js +60 -0
- package/dist/cmd/cloud/deployment/remove.js.map +1 -0
- package/dist/cmd/cloud/deployment/rollback.js +80 -0
- package/dist/cmd/cloud/deployment/rollback.js.map +1 -0
- package/dist/cmd/cloud/deployment/show.js +106 -0
- package/dist/cmd/cloud/deployment/show.js.map +1 -0
- package/dist/cmd/cloud/deployment/undeploy.js +45 -0
- package/dist/cmd/cloud/deployment/undeploy.js.map +1 -0
- package/dist/cmd/cloud/deployment/utils.js +10 -0
- package/dist/cmd/cloud/deployment/utils.js.map +1 -0
- package/dist/cmd/cloud/domain.js +77 -0
- package/dist/cmd/cloud/domain.js.map +1 -0
- package/dist/cmd/cloud/env/delete.js +50 -0
- package/dist/cmd/cloud/env/delete.js.map +1 -0
- package/dist/cmd/cloud/env/get.js +65 -0
- package/dist/cmd/cloud/env/get.js.map +1 -0
- package/dist/cmd/cloud/env/import.js +113 -0
- package/dist/cmd/cloud/env/import.js.map +1 -0
- package/dist/cmd/cloud/env/index.js +24 -0
- package/dist/cmd/cloud/env/index.js.map +1 -0
- package/dist/cmd/cloud/env/list.js +58 -0
- package/dist/cmd/cloud/env/list.js.map +1 -0
- package/dist/cmd/cloud/env/pull.js +81 -0
- package/dist/cmd/cloud/env/pull.js.map +1 -0
- package/dist/cmd/cloud/env/push.js +61 -0
- package/dist/cmd/cloud/env/push.js.map +1 -0
- package/dist/cmd/cloud/env/set.js +73 -0
- package/dist/cmd/cloud/env/set.js.map +1 -0
- package/dist/cmd/cloud/index.js +31 -0
- package/dist/cmd/cloud/index.js.map +1 -0
- package/dist/cmd/cloud/keyvalue/create-namespace.js +41 -0
- package/dist/cmd/cloud/keyvalue/create-namespace.js.map +1 -0
- package/dist/cmd/cloud/keyvalue/delete-namespace.js +64 -0
- package/dist/cmd/cloud/keyvalue/delete-namespace.js.map +1 -0
- package/dist/cmd/cloud/keyvalue/delete.js +47 -0
- package/dist/cmd/cloud/keyvalue/delete.js.map +1 -0
- package/dist/cmd/cloud/keyvalue/get.js +65 -0
- package/dist/cmd/cloud/keyvalue/get.js.map +1 -0
- package/dist/cmd/cloud/keyvalue/index.js +32 -0
- package/dist/cmd/cloud/keyvalue/index.js.map +1 -0
- package/dist/cmd/cloud/keyvalue/keys.js +50 -0
- package/dist/cmd/cloud/keyvalue/keys.js.map +1 -0
- package/dist/cmd/cloud/keyvalue/list-namespaces.js +37 -0
- package/dist/cmd/cloud/keyvalue/list-namespaces.js.map +1 -0
- package/dist/cmd/cloud/keyvalue/repl.js +277 -0
- package/dist/cmd/cloud/keyvalue/repl.js.map +1 -0
- package/dist/cmd/cloud/keyvalue/search.js +72 -0
- package/dist/cmd/cloud/keyvalue/search.js.map +1 -0
- package/dist/cmd/cloud/keyvalue/set.js +59 -0
- package/dist/cmd/cloud/keyvalue/set.js.map +1 -0
- package/dist/cmd/cloud/keyvalue/stats.js +82 -0
- package/dist/cmd/cloud/keyvalue/stats.js.map +1 -0
- package/dist/cmd/cloud/keyvalue/util.js +19 -0
- package/dist/cmd/cloud/keyvalue/util.js.map +1 -0
- package/dist/cmd/cloud/objectstore/delete-bucket.js +66 -0
- package/dist/cmd/cloud/objectstore/delete-bucket.js.map +1 -0
- package/dist/cmd/cloud/objectstore/delete.js +56 -0
- package/dist/cmd/cloud/objectstore/delete.js.map +1 -0
- package/dist/cmd/cloud/objectstore/get.js +64 -0
- package/dist/cmd/cloud/objectstore/get.js.map +1 -0
- package/dist/cmd/cloud/objectstore/index.js +28 -0
- package/dist/cmd/cloud/objectstore/index.js.map +1 -0
- package/dist/cmd/cloud/objectstore/list-buckets.js +37 -0
- package/dist/cmd/cloud/objectstore/list-buckets.js.map +1 -0
- package/dist/cmd/cloud/objectstore/list-keys.js +52 -0
- package/dist/cmd/cloud/objectstore/list-keys.js.map +1 -0
- package/dist/cmd/cloud/objectstore/put.js +57 -0
- package/dist/cmd/cloud/objectstore/put.js.map +1 -0
- package/dist/cmd/cloud/objectstore/repl.js +219 -0
- package/dist/cmd/cloud/objectstore/repl.js.map +1 -0
- package/dist/cmd/cloud/objectstore/url.js +55 -0
- package/dist/cmd/cloud/objectstore/url.js.map +1 -0
- package/dist/cmd/cloud/objectstore/util.js +18 -0
- package/dist/cmd/cloud/objectstore/util.js.map +1 -0
- package/dist/cmd/cloud/resource/add.js +70 -0
- package/dist/cmd/cloud/resource/add.js.map +1 -0
- package/dist/cmd/cloud/resource/delete.js +126 -0
- package/dist/cmd/cloud/resource/delete.js.map +1 -0
- package/dist/cmd/cloud/resource/index.js +12 -0
- package/dist/cmd/cloud/resource/index.js.map +1 -0
- package/dist/cmd/cloud/resource/list.js +89 -0
- package/dist/cmd/cloud/resource/list.js.map +1 -0
- package/dist/cmd/cloud/scp/download.js +72 -0
- package/dist/cmd/cloud/scp/download.js.map +1 -0
- package/dist/cmd/cloud/scp/index.js +10 -0
- package/dist/cmd/cloud/scp/index.js.map +1 -0
- package/dist/cmd/cloud/scp/upload.js +75 -0
- package/dist/cmd/cloud/scp/upload.js.map +1 -0
- package/dist/cmd/cloud/secret/delete.js +50 -0
- package/dist/cmd/cloud/secret/delete.js.map +1 -0
- package/dist/cmd/cloud/secret/get.js +69 -0
- package/dist/cmd/cloud/secret/get.js.map +1 -0
- package/dist/cmd/cloud/secret/import.js +88 -0
- package/dist/cmd/cloud/secret/import.js.map +1 -0
- package/dist/cmd/cloud/secret/index.js +24 -0
- package/dist/cmd/cloud/secret/index.js.map +1 -0
- package/dist/cmd/cloud/secret/list.js +58 -0
- package/dist/cmd/cloud/secret/list.js.map +1 -0
- package/dist/cmd/cloud/secret/pull.js +81 -0
- package/dist/cmd/cloud/secret/pull.js.map +1 -0
- package/dist/cmd/cloud/secret/push.js +61 -0
- package/dist/cmd/cloud/secret/push.js.map +1 -0
- package/dist/cmd/cloud/secret/set.js +57 -0
- package/dist/cmd/cloud/secret/set.js.map +1 -0
- package/dist/cmd/cloud/session/get.d.ts.map +1 -1
- package/dist/cmd/cloud/session/get.js +155 -0
- package/dist/cmd/cloud/session/get.js.map +1 -0
- package/dist/cmd/cloud/session/index.js +11 -0
- package/dist/cmd/cloud/session/index.js.map +1 -0
- package/dist/cmd/cloud/session/list.js +132 -0
- package/dist/cmd/cloud/session/list.js.map +1 -0
- package/dist/cmd/cloud/session/logs.js +56 -0
- package/dist/cmd/cloud/session/logs.js.map +1 -0
- package/dist/cmd/cloud/ssh.js +67 -0
- package/dist/cmd/cloud/ssh.js.map +1 -0
- package/dist/cmd/dev/agents.js +103 -0
- package/dist/cmd/dev/agents.js.map +1 -0
- package/dist/cmd/dev/api.js +26 -0
- package/dist/cmd/dev/api.js.map +1 -0
- package/dist/cmd/dev/download.js +77 -0
- package/dist/cmd/dev/download.js.map +1 -0
- package/dist/cmd/dev/index.js +745 -0
- package/dist/cmd/dev/index.js.map +1 -0
- package/dist/cmd/dev/sync.js +229 -0
- package/dist/cmd/dev/sync.js.map +1 -0
- package/dist/cmd/dev/templates.js +75 -0
- package/dist/cmd/dev/templates.js.map +1 -0
- package/dist/cmd/index.js +49 -0
- package/dist/cmd/index.js.map +1 -0
- package/dist/cmd/profile/create.js +89 -0
- package/dist/cmd/profile/create.js.map +1 -0
- package/dist/cmd/profile/delete.js +63 -0
- package/dist/cmd/profile/delete.js.map +1 -0
- package/dist/cmd/profile/index.js +14 -0
- package/dist/cmd/profile/index.js.map +1 -0
- package/dist/cmd/profile/list.js +28 -0
- package/dist/cmd/profile/list.js.map +1 -0
- package/dist/cmd/profile/show.js +68 -0
- package/dist/cmd/profile/show.js.map +1 -0
- package/dist/cmd/profile/use.js +37 -0
- package/dist/cmd/profile/use.js.map +1 -0
- package/dist/cmd/project/create.js +92 -0
- package/dist/cmd/project/create.js.map +1 -0
- package/dist/cmd/project/delete.js +117 -0
- package/dist/cmd/project/delete.js.map +1 -0
- package/dist/cmd/project/download.js +217 -0
- package/dist/cmd/project/download.js.map +1 -0
- package/dist/cmd/project/index.js +12 -0
- package/dist/cmd/project/index.js.map +1 -0
- package/dist/cmd/project/list.js +51 -0
- package/dist/cmd/project/list.js.map +1 -0
- package/dist/cmd/project/show.js +54 -0
- package/dist/cmd/project/show.js.map +1 -0
- package/dist/cmd/project/template-flow.js +315 -0
- package/dist/cmd/project/template-flow.js.map +1 -0
- package/dist/cmd/project/templates.js +31 -0
- package/dist/cmd/project/templates.js.map +1 -0
- package/dist/cmd/repl/index.js +444 -0
- package/dist/cmd/repl/index.js.map +1 -0
- package/dist/cmd/version/index.js +29 -0
- package/dist/cmd/version/index.js.map +1 -0
- package/dist/command-prefix.js +37 -0
- package/dist/command-prefix.js.map +1 -0
- package/dist/config.js +536 -0
- package/dist/config.js.map +1 -0
- package/dist/crypto/box.js +382 -0
- package/dist/crypto/box.js.map +1 -0
- package/dist/crypto/box.test.js +317 -0
- package/dist/crypto/box.test.js.map +1 -0
- package/dist/download.js +64 -0
- package/dist/download.js.map +1 -0
- package/dist/env-util.js +219 -0
- package/dist/env-util.js.map +1 -0
- package/dist/env-util.test.js +146 -0
- package/dist/env-util.test.js.map +1 -0
- package/dist/errors.js +177 -0
- package/dist/errors.js.map +1 -0
- package/dist/explain.js +90 -0
- package/dist/explain.js.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/json.js +29 -0
- package/dist/json.js.map +1 -0
- package/dist/legacy-check.js +104 -0
- package/dist/legacy-check.js.map +1 -0
- package/dist/output.js +207 -0
- package/dist/output.js.map +1 -0
- package/dist/repl.js +1176 -0
- package/dist/repl.js.map +1 -0
- package/dist/runtime.js +19 -0
- package/dist/runtime.js.map +1 -0
- package/dist/schema-generator.js +289 -0
- package/dist/schema-generator.js.map +1 -0
- package/dist/schema-parser.js +145 -0
- package/dist/schema-parser.js.map +1 -0
- package/dist/sound.js +44 -0
- package/dist/sound.js.map +1 -0
- package/dist/steps.js +293 -0
- package/dist/steps.js.map +1 -0
- package/dist/terminal.js +130 -0
- package/dist/terminal.js.map +1 -0
- package/dist/tui.js +1124 -0
- package/dist/tui.js.map +1 -0
- package/dist/types.js +163 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/detectSubagent.js +25 -0
- package/dist/utils/detectSubagent.js.map +1 -0
- package/dist/utils/format.js +21 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/utils/zip.js +33 -0
- package/dist/utils/zip.js.map +1 -0
- package/dist/version.js +24 -0
- package/dist/version.js.map +1 -0
- package/package.json +6 -6
- package/src/banner.ts +1 -1
- package/src/cmd/build/index.ts +15 -21
- package/src/cmd/build/plugin.ts +2 -1
- package/src/cmd/cloud/session/get.ts +20 -14
- package/src/cmd/cloud/session/list.ts +1 -1
package/dist/cli.js
ADDED
|
@@ -0,0 +1,822 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { showBanner } from './banner';
|
|
3
|
+
import { requireAuth, optionalAuth, requireOrg, optionalOrg as selectOptionalOrg } from './auth';
|
|
4
|
+
import { listRegions } from '@agentuity/server';
|
|
5
|
+
import enquirer from 'enquirer';
|
|
6
|
+
import * as tui from './tui';
|
|
7
|
+
import { parseArgsSchema, parseOptionsSchema, buildValidationInput } from './schema-parser';
|
|
8
|
+
import { defaultProfileName, loadProjectConfig } from './config';
|
|
9
|
+
import { APIClient, getAPIBaseURL } from './api';
|
|
10
|
+
import { ErrorCode, ExitCode, createError, exitWithError } from './errors';
|
|
11
|
+
import { getCommand } from './command-prefix';
|
|
12
|
+
import { isValidateMode, outputValidation } from './output';
|
|
13
|
+
function createAPIClient(baseCtx, config) {
|
|
14
|
+
try {
|
|
15
|
+
const apiUrl = getAPIBaseURL(config);
|
|
16
|
+
const apiClient = new APIClient(apiUrl, baseCtx.logger, config);
|
|
17
|
+
if (!apiClient) {
|
|
18
|
+
throw new Error('APIClient constructor returned null/undefined');
|
|
19
|
+
}
|
|
20
|
+
if (typeof apiClient.request !== 'function') {
|
|
21
|
+
throw new Error('APIClient instance is missing request method');
|
|
22
|
+
}
|
|
23
|
+
return apiClient;
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
baseCtx.logger.error('Failed to create API client:', error);
|
|
27
|
+
throw new Error(`API client initialization failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Execute handler or output validation result based on mode
|
|
32
|
+
*/
|
|
33
|
+
async function executeOrValidate(ctx, commandName, handler) {
|
|
34
|
+
if (isValidateMode(ctx.options)) {
|
|
35
|
+
// In validate mode, just output success (validation already passed via Zod)
|
|
36
|
+
const result = {
|
|
37
|
+
valid: true,
|
|
38
|
+
command: commandName,
|
|
39
|
+
};
|
|
40
|
+
outputValidation(result, ctx.options);
|
|
41
|
+
}
|
|
42
|
+
else if (handler) {
|
|
43
|
+
// Normal execution
|
|
44
|
+
await handler(ctx);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Handle validation error - output structured result in validate mode, otherwise log and exit
|
|
49
|
+
*/
|
|
50
|
+
function handleValidationError(error, commandName, baseCtx) {
|
|
51
|
+
if (error && typeof error === 'object' && 'issues' in error) {
|
|
52
|
+
const issues = error.issues;
|
|
53
|
+
if (isValidateMode(baseCtx.options)) {
|
|
54
|
+
// In validate mode, output structured validation result
|
|
55
|
+
const result = {
|
|
56
|
+
valid: false,
|
|
57
|
+
command: commandName,
|
|
58
|
+
errors: issues.map((issue) => ({
|
|
59
|
+
field: issue.path?.length ? issue.path.join('.') : 'unknown',
|
|
60
|
+
message: issue.message,
|
|
61
|
+
})),
|
|
62
|
+
};
|
|
63
|
+
outputValidation(result, baseCtx.options);
|
|
64
|
+
process.exit(ExitCode.VALIDATION_ERROR);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
// Use centralized error handling
|
|
68
|
+
exitWithError({
|
|
69
|
+
code: ErrorCode.VALIDATION_FAILED,
|
|
70
|
+
message: 'Validation error',
|
|
71
|
+
details: {
|
|
72
|
+
issues: issues.map((issue) => ({
|
|
73
|
+
field: issue.path?.length ? issue.path.join('.') : 'unknown',
|
|
74
|
+
message: issue.message,
|
|
75
|
+
})),
|
|
76
|
+
},
|
|
77
|
+
}, baseCtx.logger, baseCtx.options.errorFormat ?? 'text');
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
throw error;
|
|
81
|
+
}
|
|
82
|
+
function normalizeReqs(def) {
|
|
83
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
84
|
+
const d = def;
|
|
85
|
+
const requires = d.requires;
|
|
86
|
+
const optional = d.optional;
|
|
87
|
+
const requiresAuth = requires?.auth === true;
|
|
88
|
+
const optionalAuthValue = optional?.auth;
|
|
89
|
+
const optionalAuth = optionalAuthValue === true ? 'Continue without authentication' : optionalAuthValue || false;
|
|
90
|
+
const requiresProject = requires?.project === true;
|
|
91
|
+
const optionalProject = optional?.project === true;
|
|
92
|
+
const requiresOrg = requires?.org === true;
|
|
93
|
+
const optionalOrg = optional?.org === true;
|
|
94
|
+
const requiresRegions = requires?.regions === true;
|
|
95
|
+
const requiresRegion = requires?.region === true;
|
|
96
|
+
const optionalRegion = optional?.region === true;
|
|
97
|
+
// Implicitly require apiClient if org or region is required or optional
|
|
98
|
+
const requiresAPIClient = requires?.apiClient === true ||
|
|
99
|
+
requiresOrg ||
|
|
100
|
+
optionalOrg ||
|
|
101
|
+
requiresRegion ||
|
|
102
|
+
optionalRegion ||
|
|
103
|
+
requiresRegions;
|
|
104
|
+
return {
|
|
105
|
+
requiresAuth,
|
|
106
|
+
optionalAuth,
|
|
107
|
+
requiresProject,
|
|
108
|
+
optionalProject,
|
|
109
|
+
requiresAPIClient,
|
|
110
|
+
requiresOrg,
|
|
111
|
+
optionalOrg,
|
|
112
|
+
requiresRegions,
|
|
113
|
+
requiresRegion,
|
|
114
|
+
optionalRegion,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
function handleProjectConfigError(error, requiresProject, logger, errorFormat) {
|
|
118
|
+
if (requiresProject &&
|
|
119
|
+
error &&
|
|
120
|
+
typeof error === 'object' &&
|
|
121
|
+
'name' in error &&
|
|
122
|
+
error.name === 'ProjectConfigNotFoundExpection') {
|
|
123
|
+
exitWithError(createError(ErrorCode.PROJECT_NOT_FOUND, 'Invalid project folder', undefined, [
|
|
124
|
+
'Use --dir to specify a different directory',
|
|
125
|
+
'Change to a directory containing agentuity.json',
|
|
126
|
+
`Run "${getCommand('project create')}" to create a new project`,
|
|
127
|
+
]), logger, errorFormat ?? 'text');
|
|
128
|
+
}
|
|
129
|
+
throw error;
|
|
130
|
+
}
|
|
131
|
+
export async function createCLI(version) {
|
|
132
|
+
const program = new Command();
|
|
133
|
+
program
|
|
134
|
+
.name('agentuity')
|
|
135
|
+
.version(version, '-V, --version', 'Display version')
|
|
136
|
+
.helpOption('-h, --help=[json]', 'Display help (with optional JSON output)')
|
|
137
|
+
.allowUnknownOption(false)
|
|
138
|
+
.allowExcessArguments(false)
|
|
139
|
+
.showHelpAfterError(true);
|
|
140
|
+
program
|
|
141
|
+
.option('--config <path>', 'Config file path')
|
|
142
|
+
.option('--log-level <level>', 'Log level', process.env.AGENTUITY_LOG_LEVEL ?? 'info')
|
|
143
|
+
.option('--log-timestamp', 'Show timestamps in log output', false)
|
|
144
|
+
.option('--no-log-prefix', 'Hide log level prefixes', true)
|
|
145
|
+
.option('--org-id <id>', 'Use a specific organization when performing operations', process.env.AGENTUITY_CLOUD_ORG_ID)
|
|
146
|
+
.option('--color-scheme <scheme>', 'Color scheme: light or dark')
|
|
147
|
+
.option('--color <mode>', 'Color output: auto, always, never', 'auto')
|
|
148
|
+
.option('--error-format <format>', 'Error output format: json or text', 'text')
|
|
149
|
+
.option('--json', 'Output in JSON format (machine-readable)', false)
|
|
150
|
+
.option('--quiet', 'Suppress non-essential output', false)
|
|
151
|
+
.option('--no-progress', 'Disable progress indicators', false)
|
|
152
|
+
.option('--explain', 'Show what the command would do without executing', false)
|
|
153
|
+
.option('--dry-run', 'Execute command without making changes', false)
|
|
154
|
+
.option('--validate', 'Validate arguments and options without executing', false);
|
|
155
|
+
const skipVersionCheckOption = program.createOption('--skip-version-check', 'Skip version compatibility check (dev only)');
|
|
156
|
+
skipVersionCheckOption.hideHelp();
|
|
157
|
+
program.addOption(skipVersionCheckOption);
|
|
158
|
+
program.action(() => {
|
|
159
|
+
showBanner(version);
|
|
160
|
+
program.help();
|
|
161
|
+
});
|
|
162
|
+
// Handle unknown commands
|
|
163
|
+
program.on('command:*', (operands) => {
|
|
164
|
+
const unknownCommand = operands[0];
|
|
165
|
+
console.error(`error: unknown command '${unknownCommand}'`);
|
|
166
|
+
console.error();
|
|
167
|
+
const availableCommands = program.commands.map((cmd) => cmd.name());
|
|
168
|
+
if (availableCommands.length > 0) {
|
|
169
|
+
console.error('Available commands:');
|
|
170
|
+
availableCommands.forEach((name) => {
|
|
171
|
+
console.error(` ${name}`);
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
console.error();
|
|
175
|
+
console.error(`Run '${getCommand('--help')}' for usage information.`);
|
|
176
|
+
process.exit(1);
|
|
177
|
+
});
|
|
178
|
+
// Custom error handling for argument/command parsing errors
|
|
179
|
+
program.configureOutput({
|
|
180
|
+
outputError: (str, write) => {
|
|
181
|
+
// Intercept commander.js error messages
|
|
182
|
+
if (str.includes('too many arguments') || str.includes('unknown command')) {
|
|
183
|
+
// Extract potential command name from error context
|
|
184
|
+
const match = str.match(/got (\d+)/);
|
|
185
|
+
if (match) {
|
|
186
|
+
write(`error: unknown command or subcommand\n`);
|
|
187
|
+
write(`\nRun '${getCommand('--help')}' for available commands.\n`);
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
write(str);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
write(str);
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
});
|
|
198
|
+
// Configure help to show only main command names, not aliases
|
|
199
|
+
program.configureHelp({
|
|
200
|
+
subcommandTerm: (cmd) => cmd.name(),
|
|
201
|
+
});
|
|
202
|
+
return program;
|
|
203
|
+
}
|
|
204
|
+
async function getRegion(regions) {
|
|
205
|
+
if (regions.length === 1) {
|
|
206
|
+
return regions[0].region;
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
const response = await enquirer.prompt({
|
|
210
|
+
type: 'select',
|
|
211
|
+
name: 'region',
|
|
212
|
+
message: 'Select a cloud region:',
|
|
213
|
+
choices: regions.map((r) => ({
|
|
214
|
+
name: r.region,
|
|
215
|
+
message: `${r.description.padEnd(15, ' ')} ${tui.muted(r.region)}`,
|
|
216
|
+
})),
|
|
217
|
+
});
|
|
218
|
+
return response.region;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
async function resolveRegion(opts) {
|
|
222
|
+
const { options, apiClient, logger, required } = opts;
|
|
223
|
+
// Fetch regions
|
|
224
|
+
const regions = await listRegions(apiClient);
|
|
225
|
+
// No regions available
|
|
226
|
+
if (regions.length === 0) {
|
|
227
|
+
if (required) {
|
|
228
|
+
const errorFormat = options.errorFormat;
|
|
229
|
+
exitWithError(createError(ErrorCode.NO_REGIONS_AVAILABLE, 'No cloud regions available', undefined, [
|
|
230
|
+
'Contact support if you need access to cloud regions',
|
|
231
|
+
]), logger, errorFormat ?? 'text');
|
|
232
|
+
}
|
|
233
|
+
return undefined;
|
|
234
|
+
}
|
|
235
|
+
// Check if region was provided via flag
|
|
236
|
+
let region = options.region;
|
|
237
|
+
// Validate --region flag if provided
|
|
238
|
+
if (region) {
|
|
239
|
+
const found = regions.find((r) => r.region === region);
|
|
240
|
+
if (!found) {
|
|
241
|
+
const errorFormat = options.errorFormat;
|
|
242
|
+
exitWithError(createError(ErrorCode.REGION_NOT_FOUND, `Invalid region '${region}'`, { region, availableRegions: regions.map((r) => r.region) }, [`Use one of: ${regions.map((r) => r.region).join(', ')}`]), logger, errorFormat ?? 'text');
|
|
243
|
+
}
|
|
244
|
+
return region;
|
|
245
|
+
}
|
|
246
|
+
// Auto-select if only one region available
|
|
247
|
+
if (regions.length === 1) {
|
|
248
|
+
region = regions[0].region;
|
|
249
|
+
if (!process.stdin.isTTY) {
|
|
250
|
+
logger.trace('auto-selected region (non-TTY): %s', region);
|
|
251
|
+
}
|
|
252
|
+
return region;
|
|
253
|
+
}
|
|
254
|
+
// No flag provided - handle TTY vs non-TTY
|
|
255
|
+
if (required && !process.stdin.isTTY) {
|
|
256
|
+
const errorFormat = options.errorFormat;
|
|
257
|
+
exitWithError(createError(ErrorCode.REGION_REQUIRED, '--region flag is required in non-interactive mode', { availableRegions: regions.map((r) => r.region) }, [`Use --region with one of: ${regions.map((r) => r.region).join(', ')}`]), logger, errorFormat ?? 'text');
|
|
258
|
+
}
|
|
259
|
+
if (process.stdin.isTTY) {
|
|
260
|
+
// Interactive mode - prompt user
|
|
261
|
+
region = await getRegion(regions);
|
|
262
|
+
return region;
|
|
263
|
+
}
|
|
264
|
+
// Non-interactive, optional region - return undefined
|
|
265
|
+
return undefined;
|
|
266
|
+
}
|
|
267
|
+
async function registerSubcommand(parent, subcommand, baseCtx, hidden) {
|
|
268
|
+
const cmd = parent.command(subcommand.name, { hidden }).description(subcommand.description);
|
|
269
|
+
if (subcommand.aliases) {
|
|
270
|
+
cmd.aliases(subcommand.aliases);
|
|
271
|
+
}
|
|
272
|
+
// Add examples to help text
|
|
273
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
274
|
+
const examples = subcommand.examples;
|
|
275
|
+
if (examples && examples.length > 0) {
|
|
276
|
+
cmd.addHelpText('after', '\nExamples:\n' + examples.map((ex) => ` ${ex}`).join('\n'));
|
|
277
|
+
}
|
|
278
|
+
// Check if this subcommand has its own subcommands (nested subcommands)
|
|
279
|
+
const subDef = subcommand;
|
|
280
|
+
if (subDef.subcommands && subDef.subcommands.length > 0) {
|
|
281
|
+
// Register nested subcommands recursively
|
|
282
|
+
for (const nestedSub of subDef.subcommands) {
|
|
283
|
+
await registerSubcommand(cmd, nestedSub, baseCtx);
|
|
284
|
+
}
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
const { requiresProject, optionalProject, requiresOrg, optionalOrg, requiresRegion, optionalRegion, } = normalizeReqs(subcommand);
|
|
288
|
+
if (requiresProject || optionalProject) {
|
|
289
|
+
cmd.option('--dir <path>', 'project directory (default: current directory)');
|
|
290
|
+
}
|
|
291
|
+
if (requiresOrg || optionalOrg) {
|
|
292
|
+
cmd.option('--org-id <id>', 'organization ID');
|
|
293
|
+
}
|
|
294
|
+
if (requiresRegion || optionalRegion) {
|
|
295
|
+
cmd.option('--region <region>', 'cloud region');
|
|
296
|
+
}
|
|
297
|
+
if (subcommand.schema?.args) {
|
|
298
|
+
const parsed = parseArgsSchema(subcommand.schema.args);
|
|
299
|
+
for (const argMeta of parsed.metadata) {
|
|
300
|
+
let argSyntax;
|
|
301
|
+
if (argMeta.variadic) {
|
|
302
|
+
argSyntax = argMeta.optional ? `[${argMeta.name}...]` : `<${argMeta.name}...>`;
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
argSyntax = argMeta.optional ? `[${argMeta.name}]` : `<${argMeta.name}>`;
|
|
306
|
+
}
|
|
307
|
+
cmd.argument(argSyntax);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
if (subcommand.schema?.options) {
|
|
311
|
+
const parsed = parseOptionsSchema(subcommand.schema.options);
|
|
312
|
+
for (const opt of parsed) {
|
|
313
|
+
const flag = opt.name.replace(/([A-Z])/g, '-$1').toLowerCase();
|
|
314
|
+
const desc = opt.description || '';
|
|
315
|
+
// Add short flag alias for verbose
|
|
316
|
+
const flagSpec = flag === 'verbose' ? `-v, --${flag}` : `--${flag}`;
|
|
317
|
+
if (opt.type === 'boolean') {
|
|
318
|
+
if (opt.hasDefault) {
|
|
319
|
+
const defaultValue = typeof opt.defaultValue === 'function' ? opt.defaultValue() : opt.defaultValue;
|
|
320
|
+
cmd.option(`--no-${flag}`, desc);
|
|
321
|
+
cmd.option(flagSpec, desc, defaultValue);
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
cmd.option(flagSpec, desc);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
else if (opt.type === 'number') {
|
|
328
|
+
cmd.option(`${flagSpec} <${opt.name}>`, desc, parseFloat);
|
|
329
|
+
}
|
|
330
|
+
else {
|
|
331
|
+
cmd.option(`${flagSpec} <${opt.name}>`, desc);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
cmd.action(async (...rawArgs) => {
|
|
336
|
+
const cmdObj = rawArgs[rawArgs.length - 1];
|
|
337
|
+
const options = cmdObj.opts();
|
|
338
|
+
const args = rawArgs.slice(0, -1);
|
|
339
|
+
if (subcommand.banner) {
|
|
340
|
+
showBanner();
|
|
341
|
+
}
|
|
342
|
+
const normalized = normalizeReqs(subcommand);
|
|
343
|
+
let project;
|
|
344
|
+
let projectDir;
|
|
345
|
+
const dirNeeded = normalized.requiresProject || normalized.optionalProject;
|
|
346
|
+
if (dirNeeded) {
|
|
347
|
+
const dir = options.dir ?? process.cwd();
|
|
348
|
+
projectDir = dir;
|
|
349
|
+
try {
|
|
350
|
+
project = await loadProjectConfig(dir, baseCtx.config);
|
|
351
|
+
}
|
|
352
|
+
catch (error) {
|
|
353
|
+
if (normalized.requiresProject) {
|
|
354
|
+
if (error &&
|
|
355
|
+
typeof error === 'object' &&
|
|
356
|
+
'name' in error &&
|
|
357
|
+
error.name === 'ProjectConfigNotFoundExpection') {
|
|
358
|
+
exitWithError(createError(ErrorCode.PROJECT_NOT_FOUND, 'Invalid project folder', undefined, [
|
|
359
|
+
'Use --dir to specify a different directory',
|
|
360
|
+
'Change to a directory containing agentuity.json',
|
|
361
|
+
`Run "${getCommand('project create')}" to create a new project`,
|
|
362
|
+
]), baseCtx.logger, baseCtx.options.errorFormat);
|
|
363
|
+
}
|
|
364
|
+
throw error;
|
|
365
|
+
}
|
|
366
|
+
// For optional projects, silently continue without project config
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
if (normalized.requiresAuth) {
|
|
370
|
+
// Create apiClient before requireAuth since login command needs it
|
|
371
|
+
if (normalized.requiresAPIClient) {
|
|
372
|
+
baseCtx.apiClient = createAPIClient(baseCtx, baseCtx.config ?? null);
|
|
373
|
+
}
|
|
374
|
+
const auth = await requireAuth(baseCtx);
|
|
375
|
+
if (subcommand.schema) {
|
|
376
|
+
try {
|
|
377
|
+
const input = buildValidationInput(subcommand.schema, args, options);
|
|
378
|
+
const ctx = {
|
|
379
|
+
...baseCtx,
|
|
380
|
+
config: {
|
|
381
|
+
...(baseCtx.config ?? {}),
|
|
382
|
+
auth: {
|
|
383
|
+
api_key: auth.apiKey,
|
|
384
|
+
user_id: auth.userId,
|
|
385
|
+
expires: auth.expires.getTime(),
|
|
386
|
+
},
|
|
387
|
+
},
|
|
388
|
+
auth,
|
|
389
|
+
};
|
|
390
|
+
if (project || projectDir) {
|
|
391
|
+
if (project) {
|
|
392
|
+
ctx.project = project;
|
|
393
|
+
}
|
|
394
|
+
ctx.projectDir = projectDir;
|
|
395
|
+
}
|
|
396
|
+
if (subcommand.schema.args) {
|
|
397
|
+
ctx.args = subcommand.schema.args.parse(input.args);
|
|
398
|
+
}
|
|
399
|
+
if (subcommand.schema.options) {
|
|
400
|
+
ctx.opts = subcommand.schema.options.parse(input.options);
|
|
401
|
+
}
|
|
402
|
+
if (normalized.requiresAPIClient) {
|
|
403
|
+
// Recreate apiClient with auth credentials
|
|
404
|
+
ctx.apiClient = createAPIClient(baseCtx, ctx.config);
|
|
405
|
+
}
|
|
406
|
+
if (normalized.requiresOrg) {
|
|
407
|
+
ctx.orgId = await requireOrg(ctx);
|
|
408
|
+
}
|
|
409
|
+
if (normalized.optionalOrg && ctx.auth) {
|
|
410
|
+
ctx.orgId = await requireOrg(ctx);
|
|
411
|
+
}
|
|
412
|
+
if ((normalized.requiresRegion || normalized.optionalRegion) && ctx.apiClient) {
|
|
413
|
+
const apiClient = ctx.apiClient;
|
|
414
|
+
const region = await tui.spinner({
|
|
415
|
+
message: 'Fetching cloud regions',
|
|
416
|
+
clearOnSuccess: true,
|
|
417
|
+
callback: async () => {
|
|
418
|
+
return resolveRegion({
|
|
419
|
+
options: options,
|
|
420
|
+
apiClient,
|
|
421
|
+
logger: baseCtx.logger,
|
|
422
|
+
required: !!normalized.requiresRegion,
|
|
423
|
+
});
|
|
424
|
+
},
|
|
425
|
+
});
|
|
426
|
+
if (region) {
|
|
427
|
+
ctx.region = region;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
await executeOrValidate(ctx, `${parent.name()} ${subcommand.name}`, subcommand.handler);
|
|
431
|
+
}
|
|
432
|
+
catch (error) {
|
|
433
|
+
if (error && typeof error === 'object' && 'issues' in error) {
|
|
434
|
+
handleValidationError(error, `${parent.name()} ${subcommand.name}`, baseCtx);
|
|
435
|
+
}
|
|
436
|
+
handleProjectConfigError(error, normalized.requiresProject, baseCtx.logger, baseCtx.options.errorFormat);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
else {
|
|
440
|
+
const ctx = {
|
|
441
|
+
...baseCtx,
|
|
442
|
+
config: baseCtx.config
|
|
443
|
+
? {
|
|
444
|
+
...baseCtx.config,
|
|
445
|
+
name: baseCtx.config.name ?? defaultProfileName,
|
|
446
|
+
auth: {
|
|
447
|
+
api_key: auth.apiKey,
|
|
448
|
+
user_id: auth.userId,
|
|
449
|
+
expires: auth.expires.getTime(),
|
|
450
|
+
},
|
|
451
|
+
}
|
|
452
|
+
: null,
|
|
453
|
+
auth,
|
|
454
|
+
};
|
|
455
|
+
if (project || projectDir) {
|
|
456
|
+
if (project) {
|
|
457
|
+
ctx.project = project;
|
|
458
|
+
}
|
|
459
|
+
ctx.projectDir = projectDir;
|
|
460
|
+
}
|
|
461
|
+
if (normalized.requiresAPIClient) {
|
|
462
|
+
// Recreate apiClient with auth credentials
|
|
463
|
+
ctx.apiClient = createAPIClient(baseCtx, ctx.config);
|
|
464
|
+
}
|
|
465
|
+
if (normalized.requiresOrg) {
|
|
466
|
+
ctx.orgId = await requireOrg(ctx);
|
|
467
|
+
}
|
|
468
|
+
if (normalized.optionalOrg && ctx.auth) {
|
|
469
|
+
ctx.orgId = await requireOrg(ctx);
|
|
470
|
+
}
|
|
471
|
+
if ((normalized.requiresRegion || normalized.optionalRegion) && ctx.apiClient) {
|
|
472
|
+
const apiClient = ctx.apiClient;
|
|
473
|
+
const region = await tui.spinner('Fetching cloud regions', async () => {
|
|
474
|
+
return resolveRegion({
|
|
475
|
+
options: options,
|
|
476
|
+
apiClient,
|
|
477
|
+
logger: baseCtx.logger,
|
|
478
|
+
required: !!normalized.requiresRegion,
|
|
479
|
+
});
|
|
480
|
+
});
|
|
481
|
+
if (region) {
|
|
482
|
+
ctx.region = region;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
if (subcommand.handler) {
|
|
486
|
+
await subcommand.handler(ctx);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
else if (normalized.optionalAuth) {
|
|
491
|
+
const continueText = typeof normalized.optionalAuth === 'string' ? normalized.optionalAuth : undefined;
|
|
492
|
+
// Create apiClient before optionalAuth since login command needs it
|
|
493
|
+
if (normalized.requiresAPIClient) {
|
|
494
|
+
baseCtx.apiClient = createAPIClient(baseCtx, baseCtx.config ?? null);
|
|
495
|
+
}
|
|
496
|
+
const auth = await optionalAuth(baseCtx, continueText);
|
|
497
|
+
if (subcommand.schema) {
|
|
498
|
+
try {
|
|
499
|
+
const input = buildValidationInput(subcommand.schema, args, options);
|
|
500
|
+
const ctx = {
|
|
501
|
+
...baseCtx,
|
|
502
|
+
config: auth
|
|
503
|
+
? {
|
|
504
|
+
...(baseCtx.config ?? {}),
|
|
505
|
+
auth: {
|
|
506
|
+
api_key: auth.apiKey,
|
|
507
|
+
user_id: auth.userId,
|
|
508
|
+
expires: auth.expires.getTime(),
|
|
509
|
+
},
|
|
510
|
+
}
|
|
511
|
+
: baseCtx.config,
|
|
512
|
+
auth,
|
|
513
|
+
};
|
|
514
|
+
if (project || projectDir) {
|
|
515
|
+
if (project) {
|
|
516
|
+
ctx.project = project;
|
|
517
|
+
}
|
|
518
|
+
ctx.projectDir = projectDir;
|
|
519
|
+
}
|
|
520
|
+
if (subcommand.schema.args) {
|
|
521
|
+
ctx.args = subcommand.schema.args.parse(input.args);
|
|
522
|
+
}
|
|
523
|
+
if (subcommand.schema.options) {
|
|
524
|
+
ctx.opts = subcommand.schema.options.parse(input.options);
|
|
525
|
+
}
|
|
526
|
+
if (normalized.requiresAPIClient) {
|
|
527
|
+
// Recreate apiClient with auth credentials
|
|
528
|
+
ctx.apiClient = createAPIClient(baseCtx, ctx.config);
|
|
529
|
+
}
|
|
530
|
+
baseCtx.logger.trace('optionalAuth path: org=%s, region=%s, hasApiClient=%s, hasAuth=%s', normalized.optionalOrg, normalized.optionalRegion, !!ctx.apiClient, !!auth);
|
|
531
|
+
if (normalized.requiresOrg && ctx.apiClient) {
|
|
532
|
+
ctx.orgId = await requireOrg(ctx);
|
|
533
|
+
}
|
|
534
|
+
if (normalized.optionalOrg && ctx.apiClient && auth) {
|
|
535
|
+
ctx.orgId = await selectOptionalOrg(ctx);
|
|
536
|
+
baseCtx.logger.trace('selected orgId: %s', ctx.orgId);
|
|
537
|
+
}
|
|
538
|
+
if ((normalized.requiresRegion || normalized.optionalRegion) &&
|
|
539
|
+
ctx.apiClient &&
|
|
540
|
+
auth) {
|
|
541
|
+
const apiClient = ctx.apiClient;
|
|
542
|
+
const region = await resolveRegion({
|
|
543
|
+
options: options,
|
|
544
|
+
apiClient,
|
|
545
|
+
logger: baseCtx.logger,
|
|
546
|
+
required: !!normalized.requiresRegion,
|
|
547
|
+
});
|
|
548
|
+
if (region) {
|
|
549
|
+
ctx.region = region;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
await executeOrValidate(ctx, `${parent.name()} ${subcommand.name}`, subcommand.handler);
|
|
553
|
+
}
|
|
554
|
+
catch (error) {
|
|
555
|
+
if (error && typeof error === 'object' && 'issues' in error) {
|
|
556
|
+
handleValidationError(error, `${parent.name()} ${subcommand.name}`, baseCtx);
|
|
557
|
+
}
|
|
558
|
+
handleProjectConfigError(error, normalized.requiresProject, baseCtx.logger, baseCtx.options.errorFormat);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
else {
|
|
562
|
+
const ctx = {
|
|
563
|
+
...baseCtx,
|
|
564
|
+
config: auth
|
|
565
|
+
? {
|
|
566
|
+
...(baseCtx.config ?? {}),
|
|
567
|
+
auth: {
|
|
568
|
+
api_key: auth.apiKey,
|
|
569
|
+
user_id: auth.userId,
|
|
570
|
+
expires: auth.expires.getTime(),
|
|
571
|
+
},
|
|
572
|
+
}
|
|
573
|
+
: baseCtx.config,
|
|
574
|
+
auth,
|
|
575
|
+
};
|
|
576
|
+
if (project || projectDir) {
|
|
577
|
+
if (project) {
|
|
578
|
+
ctx.project = project;
|
|
579
|
+
}
|
|
580
|
+
ctx.projectDir = projectDir;
|
|
581
|
+
}
|
|
582
|
+
if (normalized.requiresAPIClient) {
|
|
583
|
+
// Recreate apiClient with auth credentials if auth was provided
|
|
584
|
+
ctx.apiClient = createAPIClient(baseCtx, ctx.config);
|
|
585
|
+
}
|
|
586
|
+
if (normalized.requiresOrg && ctx.apiClient) {
|
|
587
|
+
ctx.orgId = await requireOrg(ctx);
|
|
588
|
+
}
|
|
589
|
+
if (normalized.optionalOrg && ctx.apiClient) {
|
|
590
|
+
ctx.orgId = await selectOptionalOrg(ctx);
|
|
591
|
+
}
|
|
592
|
+
if ((normalized.requiresRegion || normalized.optionalRegion) && ctx.apiClient) {
|
|
593
|
+
const apiClient = ctx.apiClient;
|
|
594
|
+
const region = await resolveRegion({
|
|
595
|
+
options: options,
|
|
596
|
+
apiClient,
|
|
597
|
+
logger: baseCtx.logger,
|
|
598
|
+
required: !!normalized.requiresRegion,
|
|
599
|
+
});
|
|
600
|
+
if (region) {
|
|
601
|
+
ctx.region = region;
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
if (subcommand.handler) {
|
|
605
|
+
await subcommand.handler(ctx);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
else {
|
|
610
|
+
if (subcommand.schema) {
|
|
611
|
+
try {
|
|
612
|
+
const input = buildValidationInput(subcommand.schema, args, options);
|
|
613
|
+
const ctx = {
|
|
614
|
+
...baseCtx,
|
|
615
|
+
};
|
|
616
|
+
if (project || projectDir) {
|
|
617
|
+
if (project) {
|
|
618
|
+
ctx.project = project;
|
|
619
|
+
}
|
|
620
|
+
ctx.projectDir = projectDir;
|
|
621
|
+
}
|
|
622
|
+
if (subcommand.schema.args) {
|
|
623
|
+
ctx.args = subcommand.schema.args.parse(input.args);
|
|
624
|
+
}
|
|
625
|
+
if (subcommand.schema.options) {
|
|
626
|
+
ctx.opts = subcommand.schema.options.parse(input.options);
|
|
627
|
+
}
|
|
628
|
+
if (normalized.requiresAPIClient && !ctx.apiClient) {
|
|
629
|
+
ctx.apiClient = createAPIClient(baseCtx, ctx.config);
|
|
630
|
+
}
|
|
631
|
+
if (normalized.requiresOrg && ctx.apiClient) {
|
|
632
|
+
ctx.orgId = await requireOrg(ctx);
|
|
633
|
+
}
|
|
634
|
+
if (normalized.optionalOrg && ctx.apiClient && ctx.auth) {
|
|
635
|
+
ctx.orgId = await requireOrg(ctx);
|
|
636
|
+
}
|
|
637
|
+
await executeOrValidate(ctx, `${parent.name()} ${subcommand.name}`, subcommand.handler);
|
|
638
|
+
}
|
|
639
|
+
catch (error) {
|
|
640
|
+
if (error && typeof error === 'object' && 'issues' in error) {
|
|
641
|
+
handleValidationError(error, `${parent.name()} ${subcommand.name}`, baseCtx);
|
|
642
|
+
}
|
|
643
|
+
handleProjectConfigError(error, normalized.requiresProject, baseCtx.logger, baseCtx.options.errorFormat);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
else {
|
|
647
|
+
const ctx = {
|
|
648
|
+
...baseCtx,
|
|
649
|
+
};
|
|
650
|
+
if (project || projectDir) {
|
|
651
|
+
if (project) {
|
|
652
|
+
ctx.project = project;
|
|
653
|
+
}
|
|
654
|
+
ctx.projectDir = projectDir;
|
|
655
|
+
}
|
|
656
|
+
if (normalized.requiresAPIClient && !ctx.apiClient) {
|
|
657
|
+
ctx.apiClient = createAPIClient(baseCtx, ctx.config);
|
|
658
|
+
}
|
|
659
|
+
if (normalized.requiresOrg && ctx.apiClient) {
|
|
660
|
+
ctx.orgId = await requireOrg(ctx);
|
|
661
|
+
}
|
|
662
|
+
if (normalized.optionalOrg && ctx.apiClient && ctx.auth) {
|
|
663
|
+
ctx.orgId = await requireOrg(ctx);
|
|
664
|
+
}
|
|
665
|
+
if ((normalized.requiresRegion || normalized.optionalRegion) && ctx.apiClient) {
|
|
666
|
+
const apiClient = ctx.apiClient;
|
|
667
|
+
const region = await resolveRegion({
|
|
668
|
+
options: options,
|
|
669
|
+
apiClient,
|
|
670
|
+
logger: baseCtx.logger,
|
|
671
|
+
required: !!normalized.requiresRegion,
|
|
672
|
+
});
|
|
673
|
+
if (region) {
|
|
674
|
+
ctx.region = region;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
if (subcommand.handler) {
|
|
678
|
+
await subcommand.handler(ctx);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
export async function registerCommands(program, commands, baseCtx) {
|
|
685
|
+
for (const cmdDef of commands) {
|
|
686
|
+
if (cmdDef.subcommands) {
|
|
687
|
+
const cmd = program
|
|
688
|
+
.command(cmdDef.name, { hidden: cmdDef.hidden })
|
|
689
|
+
.description(cmdDef.description);
|
|
690
|
+
if (cmdDef.aliases) {
|
|
691
|
+
cmd.aliases(cmdDef.aliases);
|
|
692
|
+
}
|
|
693
|
+
if (cmdDef.handler) {
|
|
694
|
+
cmd.action(async () => {
|
|
695
|
+
if (cmdDef.banner) {
|
|
696
|
+
showBanner();
|
|
697
|
+
}
|
|
698
|
+
const normalized = normalizeReqs(cmdDef);
|
|
699
|
+
if (normalized.requiresAuth) {
|
|
700
|
+
// Create apiClient before requireAuth since login command needs it
|
|
701
|
+
if (normalized.requiresAPIClient) {
|
|
702
|
+
baseCtx.apiClient = createAPIClient(baseCtx, baseCtx.config ?? null);
|
|
703
|
+
}
|
|
704
|
+
const auth = await requireAuth(baseCtx);
|
|
705
|
+
const ctx = {
|
|
706
|
+
...baseCtx,
|
|
707
|
+
config: baseCtx.config
|
|
708
|
+
? {
|
|
709
|
+
...baseCtx.config,
|
|
710
|
+
name: baseCtx.config.name ?? defaultProfileName,
|
|
711
|
+
auth: {
|
|
712
|
+
api_key: auth.apiKey,
|
|
713
|
+
user_id: auth.userId,
|
|
714
|
+
expires: auth.expires.getTime(),
|
|
715
|
+
},
|
|
716
|
+
}
|
|
717
|
+
: null,
|
|
718
|
+
auth,
|
|
719
|
+
};
|
|
720
|
+
if (normalized.requiresAPIClient) {
|
|
721
|
+
// Recreate apiClient with auth credentials
|
|
722
|
+
ctx.apiClient = createAPIClient(baseCtx, ctx.config);
|
|
723
|
+
}
|
|
724
|
+
if ((normalized.requiresRegion || normalized.optionalRegion) && ctx.apiClient) {
|
|
725
|
+
const apiClient = ctx.apiClient;
|
|
726
|
+
const region = await resolveRegion({
|
|
727
|
+
options: baseCtx.options,
|
|
728
|
+
apiClient,
|
|
729
|
+
logger: baseCtx.logger,
|
|
730
|
+
required: !!normalized.requiresRegion,
|
|
731
|
+
});
|
|
732
|
+
if (region) {
|
|
733
|
+
ctx.region = region;
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
await cmdDef.handler(ctx);
|
|
737
|
+
}
|
|
738
|
+
else if (normalized.optionalAuth) {
|
|
739
|
+
const continueText = typeof normalized.optionalAuth === 'string'
|
|
740
|
+
? normalized.optionalAuth
|
|
741
|
+
: undefined;
|
|
742
|
+
// Create apiClient before optionalAuth since login command needs it
|
|
743
|
+
if (normalized.requiresAPIClient) {
|
|
744
|
+
baseCtx.apiClient = createAPIClient(baseCtx, baseCtx.config ?? null);
|
|
745
|
+
}
|
|
746
|
+
const auth = await optionalAuth(baseCtx, continueText);
|
|
747
|
+
const ctx = {
|
|
748
|
+
...baseCtx,
|
|
749
|
+
config: auth
|
|
750
|
+
? baseCtx.config
|
|
751
|
+
? {
|
|
752
|
+
...baseCtx.config,
|
|
753
|
+
auth: {
|
|
754
|
+
api_key: auth.apiKey,
|
|
755
|
+
user_id: auth.userId,
|
|
756
|
+
expires: auth.expires.getTime(),
|
|
757
|
+
},
|
|
758
|
+
}
|
|
759
|
+
: {
|
|
760
|
+
auth: {
|
|
761
|
+
api_key: auth.apiKey,
|
|
762
|
+
user_id: auth.userId,
|
|
763
|
+
expires: auth.expires.getTime(),
|
|
764
|
+
},
|
|
765
|
+
}
|
|
766
|
+
: baseCtx.config,
|
|
767
|
+
auth,
|
|
768
|
+
};
|
|
769
|
+
if (normalized.requiresAPIClient) {
|
|
770
|
+
// Recreate apiClient with auth credentials if auth was provided
|
|
771
|
+
ctx.apiClient = createAPIClient(baseCtx, ctx.config);
|
|
772
|
+
}
|
|
773
|
+
if ((normalized.requiresRegion || normalized.optionalRegion) && ctx.apiClient) {
|
|
774
|
+
const apiClient = ctx.apiClient;
|
|
775
|
+
const region = await resolveRegion({
|
|
776
|
+
options: baseCtx.options,
|
|
777
|
+
apiClient,
|
|
778
|
+
logger: baseCtx.logger,
|
|
779
|
+
required: !!normalized.requiresRegion,
|
|
780
|
+
});
|
|
781
|
+
if (region) {
|
|
782
|
+
ctx.region = region;
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
await cmdDef.handler(ctx);
|
|
786
|
+
}
|
|
787
|
+
else {
|
|
788
|
+
const ctx = {
|
|
789
|
+
...baseCtx,
|
|
790
|
+
};
|
|
791
|
+
if (normalized.requiresAPIClient && !ctx.apiClient) {
|
|
792
|
+
ctx.apiClient = createAPIClient(baseCtx, baseCtx.config);
|
|
793
|
+
}
|
|
794
|
+
if ((normalized.requiresRegion || normalized.optionalRegion) && ctx.apiClient) {
|
|
795
|
+
const apiClient = ctx.apiClient;
|
|
796
|
+
const region = await resolveRegion({
|
|
797
|
+
options: baseCtx.options,
|
|
798
|
+
apiClient,
|
|
799
|
+
logger: baseCtx.logger,
|
|
800
|
+
required: !!normalized.requiresRegion,
|
|
801
|
+
});
|
|
802
|
+
if (region) {
|
|
803
|
+
ctx.region = region;
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
await cmdDef.handler(ctx);
|
|
807
|
+
}
|
|
808
|
+
});
|
|
809
|
+
}
|
|
810
|
+
else {
|
|
811
|
+
cmd.action(() => cmd.help());
|
|
812
|
+
}
|
|
813
|
+
for (const sub of cmdDef.subcommands) {
|
|
814
|
+
await registerSubcommand(cmd, sub, baseCtx);
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
else {
|
|
818
|
+
await registerSubcommand(program, cmdDef, baseCtx, cmdDef.hidden);
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
//# sourceMappingURL=cli.js.map
|