@agentlang/cli 0.11.10 → 0.12.1
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/out/main.js +224 -278
- package/out/main.js.map +1 -1
- package/out/repl.js +86 -100
- package/out/repl.js.map +1 -1
- package/out/studio/services/AppManagementService.js +7 -19
- package/out/studio/services/AppManagementService.js.map +1 -1
- package/out/studio/services/AppRuntimeService.js +14 -15
- package/out/studio/services/AppRuntimeService.js.map +1 -1
- package/out/studio/services/GitHubService.js +16 -16
- package/out/studio/services/GitHubService.js.map +1 -1
- package/out/studio.js +36 -41
- package/out/studio.js.map +1 -1
- package/out/ui/components/Help.js +25 -0
- package/out/ui/components/Help.js.map +1 -0
- package/out/ui/index.js +2 -0
- package/out/ui/index.js.map +1 -0
- package/out/ui/print.js +61 -0
- package/out/ui/print.js.map +1 -0
- package/out/ui-generator/specFinder.js +4 -7
- package/out/ui-generator/specFinder.js.map +1 -1
- package/out/ui-generator/specLoader.js +2 -3
- package/out/ui-generator/specLoader.js.map +1 -1
- package/out/ui-generator/uiGenerator.js +56 -57
- package/out/ui-generator/uiGenerator.js.map +1 -1
- package/out/utils/projectInitializer.js +21 -58
- package/out/utils/projectInitializer.js.map +1 -1
- package/package.json +5 -3
package/out/main.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
1
|
import { Command } from 'commander';
|
|
3
2
|
import { NodeFileSystem } from 'langium/node';
|
|
4
3
|
import * as path from 'node:path';
|
|
@@ -9,8 +8,30 @@ import { initializeProject } from './utils/projectInitializer.js';
|
|
|
9
8
|
import { existsSync, readFileSync } from 'node:fs';
|
|
10
9
|
import { fileURLToPath } from 'node:url';
|
|
11
10
|
import { dirname, join } from 'node:path';
|
|
11
|
+
import { renderToString } from 'ink';
|
|
12
|
+
import React from 'react';
|
|
13
|
+
import Help from './ui/components/Help.js';
|
|
14
|
+
import { ui, ansi } from './ui/index.js';
|
|
12
15
|
const __filename = fileURLToPath(import.meta.url);
|
|
13
16
|
const __dirname = dirname(__filename);
|
|
17
|
+
// Read version before heavy imports so --version works without agentlang loaded
|
|
18
|
+
let packageVersion = '0.0.0';
|
|
19
|
+
try {
|
|
20
|
+
const packagePath = join(__dirname, '..', 'package.json');
|
|
21
|
+
const packageJson = JSON.parse(readFileSync(packagePath, 'utf-8'));
|
|
22
|
+
packageVersion = packageJson.version || '0.0.0';
|
|
23
|
+
}
|
|
24
|
+
catch (_a) {
|
|
25
|
+
// Fallback to default version
|
|
26
|
+
}
|
|
27
|
+
// Early exit for --version/-V — intercepts before heavy agentlang imports
|
|
28
|
+
if (process.argv.includes('--version') || process.argv.includes('-V')) {
|
|
29
|
+
ui.row([
|
|
30
|
+
{ text: 'agent', bold: true, color: 'cyan' },
|
|
31
|
+
{ text: ` v${packageVersion}`, color: 'white' },
|
|
32
|
+
]);
|
|
33
|
+
process.exit(0);
|
|
34
|
+
}
|
|
14
35
|
let agPath = 'agentlang';
|
|
15
36
|
// Check if ./node_modules/agentlang exists in the current directory, add to agPath
|
|
16
37
|
const nodeModulesPath = path.resolve(process.cwd(), 'node_modules/agentlang');
|
|
@@ -41,16 +62,6 @@ import { findSpecFile } from './ui-generator/specFinder.js';
|
|
|
41
62
|
import { startStudio } from './studio.js';
|
|
42
63
|
import { OpenAPIClientAxios } from 'openapi-client-axios';
|
|
43
64
|
import { forkApp } from './utils/forkApp.js';
|
|
44
|
-
// Read package.json for version
|
|
45
|
-
let packageVersion = '0.0.0';
|
|
46
|
-
try {
|
|
47
|
-
const packagePath = join(__dirname, '..', 'package.json');
|
|
48
|
-
const packageJson = JSON.parse(readFileSync(packagePath, 'utf-8'));
|
|
49
|
-
packageVersion = packageJson.version || '0.0.0';
|
|
50
|
-
}
|
|
51
|
-
catch (_a) {
|
|
52
|
-
// Fallback to a default version
|
|
53
|
-
}
|
|
54
65
|
function getDefaultRepoUrl(appName) {
|
|
55
66
|
const username = os.userInfo().username || 'username';
|
|
56
67
|
const repoName = appName.replace(/\s+/g, '');
|
|
@@ -58,8 +69,7 @@ function getDefaultRepoUrl(appName) {
|
|
|
58
69
|
}
|
|
59
70
|
async function promptAndPushRepository(git, appName) {
|
|
60
71
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
61
|
-
|
|
62
|
-
console.log(chalk.dim('Skipping git push prompt (non-interactive terminal).'));
|
|
72
|
+
ui.dim('Skipping git push prompt (non-interactive terminal).');
|
|
63
73
|
return;
|
|
64
74
|
}
|
|
65
75
|
const rl = createInterface({
|
|
@@ -67,14 +77,14 @@ async function promptAndPushRepository(git, appName) {
|
|
|
67
77
|
output: process.stdout,
|
|
68
78
|
});
|
|
69
79
|
try {
|
|
70
|
-
const pushAnswer = (await rl.question(
|
|
80
|
+
const pushAnswer = (await rl.question(ansi.cyan('Would you like to push this repo now? (y/N) ')))
|
|
71
81
|
.trim()
|
|
72
82
|
.toLowerCase();
|
|
73
83
|
if (pushAnswer !== 'y' && pushAnswer !== 'yes') {
|
|
74
84
|
return;
|
|
75
85
|
}
|
|
76
86
|
const defaultRepoUrl = getDefaultRepoUrl(appName);
|
|
77
|
-
const repoUrlInputPromise = rl.question(
|
|
87
|
+
const repoUrlInputPromise = rl.question(ansi.cyan('Repository URL: '));
|
|
78
88
|
rl.write(defaultRepoUrl);
|
|
79
89
|
const repoUrlInput = await repoUrlInputPromise;
|
|
80
90
|
const repoUrl = repoUrlInput.trim() || defaultRepoUrl;
|
|
@@ -88,12 +98,10 @@ async function promptAndPushRepository(git, appName) {
|
|
|
88
98
|
}
|
|
89
99
|
const currentBranch = (await git.branch()).current || 'main';
|
|
90
100
|
await git.push(['-u', 'origin', currentBranch]);
|
|
91
|
-
|
|
92
|
-
console.log(`${chalk.green('✓')} Pushed to ${chalk.cyan(repoUrl)}`);
|
|
101
|
+
ui.step('✓', 'Pushed to', repoUrl);
|
|
93
102
|
}
|
|
94
103
|
catch (error) {
|
|
95
|
-
|
|
96
|
-
console.log(chalk.yellow(`⚠️ Skipped pushing repository: ${error instanceof Error ? error.message : String(error)}`));
|
|
104
|
+
ui.warn(`Skipped pushing repository: ${error instanceof Error ? error.message : String(error)}`);
|
|
97
105
|
}
|
|
98
106
|
finally {
|
|
99
107
|
rl.close();
|
|
@@ -103,33 +111,41 @@ async function promptAndPushRepository(git, appName) {
|
|
|
103
111
|
export const initCommand = async (appName, options) => {
|
|
104
112
|
const currentDir = process.cwd();
|
|
105
113
|
const targetDir = join(currentDir, appName);
|
|
114
|
+
ui.blank();
|
|
115
|
+
ui.banner('Initialize App');
|
|
116
|
+
ui.blank();
|
|
117
|
+
ui.label('App', appName, 'cyan');
|
|
118
|
+
ui.label('Location', targetDir);
|
|
119
|
+
ui.blank();
|
|
106
120
|
try {
|
|
107
121
|
await initializeProject(targetDir, appName, {
|
|
108
122
|
prompt: options === null || options === void 0 ? void 0 : options.prompt,
|
|
109
|
-
silent: false,
|
|
123
|
+
silent: false,
|
|
110
124
|
});
|
|
111
|
-
// Change to the app directory (for CLI context)
|
|
112
125
|
try {
|
|
113
126
|
process.chdir(targetDir);
|
|
114
|
-
// eslint-disable-next-line no-console
|
|
115
|
-
console.log(chalk.cyan(`\n📂 Changed directory to ${chalk.bold(appName)}`));
|
|
116
127
|
}
|
|
117
128
|
catch (_a) {
|
|
118
129
|
// Ignore if can't change directory
|
|
119
130
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
131
|
+
ui.blank();
|
|
132
|
+
ui.divider(50);
|
|
133
|
+
ui.success(`${appName} initialized successfully!`);
|
|
134
|
+
ui.blank();
|
|
135
|
+
ui.dim('Next steps:');
|
|
136
|
+
ui.dim(' 1. Add your application logic to src/core.al');
|
|
137
|
+
ui.row([
|
|
138
|
+
{ text: ' 2. Run your app with: ', dimColor: true },
|
|
139
|
+
{ text: 'agent run', color: 'cyan' },
|
|
140
|
+
]);
|
|
141
|
+
ui.row([
|
|
142
|
+
{ text: ' 3. Or start Studio UI with: ', dimColor: true },
|
|
143
|
+
{ text: 'agent studio', color: 'cyan' },
|
|
144
|
+
]);
|
|
145
|
+
ui.divider(50);
|
|
146
|
+
ui.blank();
|
|
130
147
|
// Handle interactive git push
|
|
131
148
|
const git = simpleGit(targetDir);
|
|
132
|
-
// Check if git is initialized (initializeProject does it, but let's be safe)
|
|
133
149
|
if (await git.checkIsRepo()) {
|
|
134
150
|
await promptAndPushRepository(git, appName);
|
|
135
151
|
}
|
|
@@ -138,121 +154,36 @@ export const initCommand = async (appName, options) => {
|
|
|
138
154
|
}
|
|
139
155
|
}
|
|
140
156
|
catch (error) {
|
|
141
|
-
|
|
142
|
-
console.error(chalk.red('❌ Error initializing application:'), error instanceof Error ? error.message : error);
|
|
157
|
+
ui.error(`Error initializing application: ${error instanceof Error ? error.message : String(error)}`);
|
|
143
158
|
process.exit(1);
|
|
144
159
|
}
|
|
145
160
|
};
|
|
146
|
-
// Custom help formatter
|
|
147
|
-
function customHelp() {
|
|
148
|
-
const gradient = [chalk.hex('#00D9FF'), chalk.hex('#00C4E6'), chalk.hex('#00AFCC'), chalk.hex('#009AB3')];
|
|
149
|
-
const header = `
|
|
150
|
-
${gradient[0]('█████╗')} ${gradient[1](' ██████╗')} ${gradient[2]('███████╗')}${gradient[3]('███╗ ██╗')}${gradient[0]('████████╗')}
|
|
151
|
-
${gradient[0]('██╔══██╗')}${gradient[1]('██╔════╝')} ${gradient[2]('██╔════╝')}${gradient[3]('████╗ ██║')}${gradient[0]('╚══██╔══╝')}
|
|
152
|
-
${gradient[0]('███████║')}${gradient[1]('██║ ███╗')}${gradient[2]('█████╗')} ${gradient[3]('██╔██╗ ██║')}${gradient[0](' ██║')}
|
|
153
|
-
${gradient[0]('██╔══██║')}${gradient[1]('██║ ██║')}${gradient[2]('██╔══╝')} ${gradient[3]('██║╚██╗██║')}${gradient[0](' ██║')}
|
|
154
|
-
${gradient[0]('██║ ██║')}${gradient[1]('╚██████╔╝')}${gradient[2]('███████╗')}${gradient[3]('██║ ╚████║')}${gradient[0](' ██║')}
|
|
155
|
-
${gradient[0]('╚═╝ ╚═╝')} ${gradient[1]('╚═════╝')} ${gradient[2]('╚══════╝')}${gradient[3]('╚═╝ ╚═══╝')}${gradient[0](' ╚═╝')}
|
|
156
|
-
|
|
157
|
-
${chalk.bold.white('Agentlang CLI')} ${chalk.dim(`v${packageVersion}`)}
|
|
158
|
-
${chalk.dim('CLI for all things Agentlang')}
|
|
159
|
-
`;
|
|
160
|
-
const usage = `
|
|
161
|
-
${chalk.bold.white('USAGE')}
|
|
162
|
-
${chalk.dim('$')} ${chalk.cyan('agent')} ${chalk.yellow('<command>')} ${chalk.dim('[options]')}
|
|
163
|
-
|
|
164
|
-
${chalk.bold.white('COMMANDS')}
|
|
165
|
-
|
|
166
|
-
${chalk.cyan.bold('init')} ${chalk.dim('<appname>')}
|
|
167
|
-
${chalk.white('▸')} Initialize a new Agentlang application
|
|
168
|
-
${chalk.dim('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')}
|
|
169
|
-
${chalk.yellow('OPTIONS')}
|
|
170
|
-
${chalk.cyan('-p, --prompt')} ${chalk.dim('<description>')} Description or prompt for the application
|
|
171
|
-
|
|
172
|
-
${chalk.cyan.bold('run')} ${chalk.dim('[file]')}
|
|
173
|
-
${chalk.white('▸')} Load and execute an Agentlang module
|
|
174
|
-
${chalk.dim('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')}
|
|
175
|
-
${chalk.yellow('OPTIONS')}
|
|
176
|
-
${chalk.cyan('-c, --config')} ${chalk.dim('<file>')} Configuration file path
|
|
177
|
-
|
|
178
|
-
${chalk.cyan.bold('repl')} ${chalk.dim('[directory]')}
|
|
179
|
-
${chalk.white('▸')} Start interactive REPL environment
|
|
180
|
-
${chalk.dim('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')}
|
|
181
|
-
${chalk.yellow('OPTIONS')}
|
|
182
|
-
${chalk.cyan('-w, --watch')} Watch files and reload automatically
|
|
183
|
-
${chalk.cyan('-q, --quiet')} Suppress startup messages
|
|
184
|
-
|
|
185
|
-
${chalk.cyan.bold('doc')} ${chalk.dim('[file]')}
|
|
186
|
-
${chalk.white('▸')} Generate API documentation (Swagger/OpenAPI)
|
|
187
|
-
${chalk.dim('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')}
|
|
188
|
-
${chalk.yellow('OPTIONS')}
|
|
189
|
-
${chalk.cyan('-h, --outputHtml')} ${chalk.dim('<file>')} Generate HTML documentation
|
|
190
|
-
${chalk.cyan('-p, --outputPostman')} ${chalk.dim('<file>')} Generate Postman collection
|
|
191
|
-
|
|
192
|
-
${chalk.cyan.bold('parseAndValidate')} ${chalk.dim('<file>')}
|
|
193
|
-
${chalk.white('▸')} Parse and validate Agentlang source code
|
|
194
|
-
${chalk.dim('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')}
|
|
195
|
-
${chalk.yellow('OPTIONS')}
|
|
196
|
-
${chalk.cyan('-d, --destination')} ${chalk.dim('<dir>')} Output directory
|
|
197
|
-
|
|
198
|
-
${chalk.cyan.bold('ui-gen')} ${chalk.dim('[spec-file]')}
|
|
199
|
-
${chalk.white('▸')} Generate UI from specification ${chalk.dim('(requires Anthropic API key)')}
|
|
200
|
-
${chalk.dim('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')}
|
|
201
|
-
${chalk.yellow('OPTIONS')}
|
|
202
|
-
${chalk.cyan('-d, --directory')} ${chalk.dim('<dir>')} Target directory
|
|
203
|
-
${chalk.cyan('-k, --api-key')} ${chalk.dim('<key>')} Anthropic API key
|
|
204
|
-
${chalk.cyan('-p, --push')} Commit and push to git
|
|
205
|
-
${chalk.cyan('-m, --message')} ${chalk.dim('<text>')} Update instructions
|
|
206
|
-
|
|
207
|
-
${chalk.cyan.bold('fork')} ${chalk.dim('<source> [name]')}
|
|
208
|
-
${chalk.white('▸')} Fork an app from a local directory or git repository
|
|
209
|
-
${chalk.dim('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')}
|
|
210
|
-
${chalk.yellow('OPTIONS')}
|
|
211
|
-
${chalk.cyan('-b, --branch')} ${chalk.dim('<branch>')} Git branch to clone (for git URLs)
|
|
212
|
-
${chalk.cyan('-u, --username')} ${chalk.dim('<username>')} GitHub username for authenticated access
|
|
213
|
-
${chalk.cyan('-t, --token')} ${chalk.dim('<token>')} GitHub token for authenticated access
|
|
214
|
-
|
|
215
|
-
${chalk.cyan.bold('import')} ${chalk.dim('<source> [name]')}
|
|
216
|
-
${chalk.white('▸')} Import an app (alias for fork)
|
|
217
|
-
${chalk.dim('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')}
|
|
218
|
-
${chalk.yellow('OPTIONS')}
|
|
219
|
-
${chalk.cyan('-b, --branch')} ${chalk.dim('<branch>')} Git branch to clone (for git URLs)
|
|
220
|
-
${chalk.cyan('-u, --username')} ${chalk.dim('<username>')} GitHub username for authenticated access
|
|
221
|
-
${chalk.cyan('-t, --token')} ${chalk.dim('<token>')} GitHub token for authenticated access
|
|
222
|
-
|
|
223
|
-
${chalk.cyan.bold('studio')} ${chalk.dim('[path]')}
|
|
224
|
-
${chalk.white('▸')} Start Agentlang Studio with local server
|
|
225
|
-
${chalk.dim('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')}
|
|
226
|
-
${chalk.yellow('OPTIONS')}
|
|
227
|
-
${chalk.cyan('-p, --port')} ${chalk.dim('<port>')} Port to run Studio server on (default: 4000)
|
|
228
|
-
|
|
229
|
-
${chalk.bold.white('GLOBAL OPTIONS')}
|
|
230
|
-
${chalk.cyan('-h, --help')} Display help information
|
|
231
|
-
${chalk.cyan('-V, --version')} Display version number
|
|
232
|
-
|
|
233
|
-
${chalk.bold.white('LEARN MORE')}
|
|
234
|
-
${chalk.white('Docs')} ${chalk.cyan('https://github.com/agentlang/agentlang-cli')}
|
|
235
|
-
${chalk.white('Issues')} ${chalk.cyan('https://github.com/agentlang/agentlang-cli/issues')}
|
|
236
|
-
|
|
237
|
-
${chalk.dim('Run')} ${chalk.cyan('agent <command> --help')} ${chalk.dim('for detailed command information')}
|
|
238
|
-
`;
|
|
239
|
-
return header + usage;
|
|
240
|
-
}
|
|
241
161
|
export default function () {
|
|
242
162
|
const program = new Command();
|
|
243
163
|
// Configure program
|
|
244
164
|
program
|
|
245
165
|
.name('agent')
|
|
246
|
-
.description(
|
|
166
|
+
.description('CLI for all things Agentlang')
|
|
247
167
|
.version(packageVersion, '-V, --version', 'Display version number')
|
|
248
|
-
.helpOption(
|
|
168
|
+
.helpOption(false)
|
|
249
169
|
.helpCommand(false)
|
|
250
170
|
.configureHelp({
|
|
251
171
|
sortSubcommands: true,
|
|
252
172
|
sortOptions: true,
|
|
253
173
|
});
|
|
254
|
-
//
|
|
255
|
-
program.helpInformation =
|
|
174
|
+
// Use ink-rendered help via renderToString
|
|
175
|
+
program.helpInformation = () => {
|
|
176
|
+
return renderToString(React.createElement(Help, { version: packageVersion }), {
|
|
177
|
+
columns: process.stdout.columns || 80,
|
|
178
|
+
});
|
|
179
|
+
};
|
|
180
|
+
// Add explicit help flag since we disabled the built-in one
|
|
181
|
+
program.option('-h, --help', 'Show help information');
|
|
182
|
+
program.on('option:help', () => {
|
|
183
|
+
// eslint-disable-next-line no-console
|
|
184
|
+
console.log(program.helpInformation());
|
|
185
|
+
process.exit(0);
|
|
186
|
+
});
|
|
256
187
|
const fileExtensions = AgentlangLanguageMetaData.fileExtensions.join(', ');
|
|
257
188
|
program
|
|
258
189
|
.command('init')
|
|
@@ -260,7 +191,7 @@ export default function () {
|
|
|
260
191
|
.option('-p, --prompt <description>', 'Description or prompt for the application')
|
|
261
192
|
.description('Initialize a new Agentlang application')
|
|
262
193
|
.addHelpText('after', `
|
|
263
|
-
${
|
|
194
|
+
${ui.format.boldWhite('DESCRIPTION')}
|
|
264
195
|
Creates a new Agentlang application with the necessary project structure.
|
|
265
196
|
This command will create:
|
|
266
197
|
• package.json with your app name and version
|
|
@@ -270,18 +201,18 @@ ${chalk.bold.white('DESCRIPTION')}
|
|
|
270
201
|
The command checks if the directory is already initialized by looking for
|
|
271
202
|
existing package.json or .al files (excluding config.al).
|
|
272
203
|
|
|
273
|
-
${
|
|
274
|
-
${
|
|
275
|
-
${
|
|
204
|
+
${ui.format.boldWhite('EXAMPLES')}
|
|
205
|
+
${ui.format.dim('Initialize a new app called CarDealership')}
|
|
206
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent init CarDealership')}
|
|
276
207
|
|
|
277
|
-
${
|
|
278
|
-
${
|
|
208
|
+
${ui.format.dim('Initialize a new e-commerce app')}
|
|
209
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent init MyShop')}
|
|
279
210
|
|
|
280
|
-
${
|
|
281
|
-
${
|
|
211
|
+
${ui.format.dim('Initialize with multiple words (use PascalCase)')}
|
|
212
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent init InventoryManagement')}
|
|
282
213
|
|
|
283
|
-
${
|
|
284
|
-
${
|
|
214
|
+
${ui.format.dim('Initialize with a description/prompt')}
|
|
215
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent init ShowroomApp --prompt "a showroom app"')}
|
|
285
216
|
`)
|
|
286
217
|
.action(initCommand);
|
|
287
218
|
program
|
|
@@ -290,22 +221,22 @@ ${chalk.bold.white('EXAMPLES')}
|
|
|
290
221
|
.option('-c, --config <config>', 'Path to configuration file')
|
|
291
222
|
.description('Load and execute an Agentlang module')
|
|
292
223
|
.addHelpText('after', `
|
|
293
|
-
${
|
|
224
|
+
${ui.format.boldWhite('DESCRIPTION')}
|
|
294
225
|
Loads and executes an Agentlang module, starting the runtime environment
|
|
295
226
|
and initializing all configured services, databases, and integrations.
|
|
296
227
|
|
|
297
|
-
${
|
|
298
|
-
${
|
|
299
|
-
${
|
|
228
|
+
${ui.format.boldWhite('EXAMPLES')}
|
|
229
|
+
${ui.format.dim('Run module in current directory')}
|
|
230
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent run')}
|
|
300
231
|
|
|
301
|
-
${
|
|
302
|
-
${
|
|
232
|
+
${ui.format.dim('Run specific module file')}
|
|
233
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent run ./my-app/main.al')}
|
|
303
234
|
|
|
304
|
-
${
|
|
305
|
-
${
|
|
235
|
+
${ui.format.dim('Run with custom configuration')}
|
|
236
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent run ./my-app -c config.json')}
|
|
306
237
|
|
|
307
|
-
${
|
|
308
|
-
${
|
|
238
|
+
${ui.format.dim('Run module from specific directory')}
|
|
239
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent run ~/projects/erp-system')}
|
|
309
240
|
`)
|
|
310
241
|
.action(runModule);
|
|
311
242
|
program
|
|
@@ -315,26 +246,26 @@ ${chalk.bold.white('EXAMPLES')}
|
|
|
315
246
|
.option('-q, --quiet', 'Suppress startup messages')
|
|
316
247
|
.description('Start interactive REPL environment')
|
|
317
248
|
.addHelpText('after', `
|
|
318
|
-
${
|
|
249
|
+
${ui.format.boldWhite('DESCRIPTION')}
|
|
319
250
|
Starts an interactive Read-Eval-Print Loop (REPL) environment for
|
|
320
251
|
Agentlang, allowing you to execute code interactively, test functions,
|
|
321
252
|
and explore your application in real-time.
|
|
322
253
|
|
|
323
|
-
${
|
|
324
|
-
${
|
|
325
|
-
${
|
|
254
|
+
${ui.format.boldWhite('EXAMPLES')}
|
|
255
|
+
${ui.format.dim('Start REPL in current directory')}
|
|
256
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent repl')}
|
|
326
257
|
|
|
327
|
-
${
|
|
328
|
-
${
|
|
258
|
+
${ui.format.dim('Start REPL in specific directory')}
|
|
259
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent repl ./my-app')}
|
|
329
260
|
|
|
330
|
-
${
|
|
331
|
-
${
|
|
261
|
+
${ui.format.dim('Start with file watching enabled')}
|
|
262
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent repl --watch')}
|
|
332
263
|
|
|
333
|
-
${
|
|
334
|
-
${
|
|
264
|
+
${ui.format.dim('Start in quiet mode (no startup messages)')}
|
|
265
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent repl --quiet')}
|
|
335
266
|
|
|
336
|
-
${
|
|
337
|
-
${
|
|
267
|
+
${ui.format.dim('Combine options for development workflow')}
|
|
268
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent repl . --watch')}
|
|
338
269
|
`)
|
|
339
270
|
.action(replCommand);
|
|
340
271
|
program
|
|
@@ -344,26 +275,26 @@ ${chalk.bold.white('EXAMPLES')}
|
|
|
344
275
|
.option('-p, --outputPostman <outputPostman>', 'Generate Postman collection')
|
|
345
276
|
.description('Generate API documentation (Swagger/OpenAPI)')
|
|
346
277
|
.addHelpText('after', `
|
|
347
|
-
${
|
|
278
|
+
${ui.format.boldWhite('DESCRIPTION')}
|
|
348
279
|
Generates comprehensive API documentation from your Agentlang module
|
|
349
280
|
in Swagger/OpenAPI format. Supports both HTML and Postman collection
|
|
350
281
|
output formats for easy API exploration and testing.
|
|
351
282
|
|
|
352
|
-
${
|
|
353
|
-
${
|
|
354
|
-
${
|
|
283
|
+
${ui.format.boldWhite('EXAMPLES')}
|
|
284
|
+
${ui.format.dim('Generate OpenAPI spec (outputs to console)')}
|
|
285
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent doc')}
|
|
355
286
|
|
|
356
|
-
${
|
|
357
|
-
${
|
|
287
|
+
${ui.format.dim('Generate HTML documentation')}
|
|
288
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent doc --outputHtml api-docs.html')}
|
|
358
289
|
|
|
359
|
-
${
|
|
360
|
-
${
|
|
290
|
+
${ui.format.dim('Generate Postman collection')}
|
|
291
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent doc --outputPostman collection.json')}
|
|
361
292
|
|
|
362
|
-
${
|
|
363
|
-
${
|
|
293
|
+
${ui.format.dim('Generate both HTML and Postman')}
|
|
294
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent doc -h docs.html -p collection.json')}
|
|
364
295
|
|
|
365
|
-
${
|
|
366
|
-
${
|
|
296
|
+
${ui.format.dim('Generate docs for specific module')}
|
|
297
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent doc ./my-api -h api.html')}
|
|
367
298
|
`)
|
|
368
299
|
.action(generateDoc);
|
|
369
300
|
program
|
|
@@ -372,20 +303,20 @@ ${chalk.bold.white('EXAMPLES')}
|
|
|
372
303
|
.option('-d, --destination <dir>', 'Output directory for generated files')
|
|
373
304
|
.description('Parse and validate Agentlang source code')
|
|
374
305
|
.addHelpText('after', `
|
|
375
|
-
${
|
|
306
|
+
${ui.format.boldWhite('DESCRIPTION')}
|
|
376
307
|
Parses and validates an Agentlang source file, checking for syntax
|
|
377
308
|
errors, lexer issues, and semantic validation problems. Useful for
|
|
378
309
|
CI/CD pipelines and pre-deployment validation.
|
|
379
310
|
|
|
380
|
-
${
|
|
381
|
-
${
|
|
382
|
-
${
|
|
311
|
+
${ui.format.boldWhite('EXAMPLES')}
|
|
312
|
+
${ui.format.dim('Validate a source file')}
|
|
313
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent parseAndValidate ./src/main.al')}
|
|
383
314
|
|
|
384
|
-
${
|
|
385
|
-
${
|
|
315
|
+
${ui.format.dim('Parse and validate with output directory')}
|
|
316
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent parseAndValidate main.al -d ./out')}
|
|
386
317
|
|
|
387
|
-
${
|
|
388
|
-
${
|
|
318
|
+
${ui.format.dim('Validate in CI/CD pipeline')}
|
|
319
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent parseAndValidate app.al && npm run deploy')}
|
|
389
320
|
`)
|
|
390
321
|
.action(parseAndValidate);
|
|
391
322
|
program
|
|
@@ -397,36 +328,36 @@ ${chalk.bold.white('EXAMPLES')}
|
|
|
397
328
|
.option('-m, --message <message>', 'User message for incremental updates')
|
|
398
329
|
.description('Generate UI from specification (requires Anthropic API key)')
|
|
399
330
|
.addHelpText('after', `
|
|
400
|
-
${
|
|
331
|
+
${ui.format.boldWhite('DESCRIPTION')}
|
|
401
332
|
Generates a complete UI application from a ui-spec.json specification
|
|
402
333
|
using AI. Supports incremental updates, allowing you to evolve your UI
|
|
403
334
|
over time with natural language instructions.
|
|
404
335
|
|
|
405
|
-
${
|
|
406
|
-
Set ${
|
|
407
|
-
${
|
|
336
|
+
${ui.format.row([{ text: 'API KEY REQUIRED', color: 'yellow', bold: true }])}
|
|
337
|
+
Set ${ui.format.cyan('ANTHROPIC_API_KEY')} environment variable or use ${ui.format.cyan('--api-key')} flag
|
|
338
|
+
${ui.format.dim('Get your key at: https://console.anthropic.com')}
|
|
408
339
|
|
|
409
|
-
${
|
|
410
|
-
${
|
|
411
|
-
${
|
|
340
|
+
${ui.format.boldWhite('EXAMPLES')}
|
|
341
|
+
${ui.format.dim('Generate UI with auto-detected spec')}
|
|
342
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent ui-gen')}
|
|
412
343
|
|
|
413
|
-
${
|
|
414
|
-
${
|
|
344
|
+
${ui.format.dim('Generate from specific spec file')}
|
|
345
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent ui-gen ui-spec.json')}
|
|
415
346
|
|
|
416
|
-
${
|
|
417
|
-
${
|
|
347
|
+
${ui.format.dim('Generate and commit to git')}
|
|
348
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent ui-gen --push')}
|
|
418
349
|
|
|
419
|
-
${
|
|
420
|
-
${
|
|
350
|
+
${ui.format.dim('Generate in specific directory')}
|
|
351
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent ui-gen -d ./frontend')}
|
|
421
352
|
|
|
422
|
-
${
|
|
423
|
-
${
|
|
353
|
+
${ui.format.dim('Update existing UI with changes')}
|
|
354
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent ui-gen -m "Add dark mode toggle"')}
|
|
424
355
|
|
|
425
|
-
${
|
|
426
|
-
${
|
|
356
|
+
${ui.format.dim('Incremental update with git push')}
|
|
357
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent ui-gen -m "Fix login validation" -p')}
|
|
427
358
|
|
|
428
|
-
${
|
|
429
|
-
${
|
|
359
|
+
${ui.format.dim('Use custom API key')}
|
|
360
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent ui-gen --api-key sk-ant-...')}
|
|
430
361
|
`)
|
|
431
362
|
.action(generateUICommand);
|
|
432
363
|
program
|
|
@@ -438,26 +369,26 @@ ${chalk.bold.white('EXAMPLES')}
|
|
|
438
369
|
.option('-t, --token <token>', 'GitHub token for authenticated access')
|
|
439
370
|
.description('Fork an app from a local directory or git repository')
|
|
440
371
|
.addHelpText('after', `
|
|
441
|
-
${
|
|
372
|
+
${ui.format.boldWhite('DESCRIPTION')}
|
|
442
373
|
Forks an Agentlang application from a source path (local directory or git URL)
|
|
443
374
|
into the current workspace. The forked app will be initialized with dependencies
|
|
444
375
|
installed and a fresh git repository.
|
|
445
376
|
|
|
446
|
-
${
|
|
447
|
-
${
|
|
448
|
-
${
|
|
377
|
+
${ui.format.boldWhite('EXAMPLES')}
|
|
378
|
+
${ui.format.dim('Fork from local directory')}
|
|
379
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent fork ./my-app MyForkedApp')}
|
|
449
380
|
|
|
450
|
-
${
|
|
451
|
-
${
|
|
381
|
+
${ui.format.dim('Fork from GitHub repository')}
|
|
382
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent fork https://github.com/user/repo.git MyApp')}
|
|
452
383
|
|
|
453
|
-
${
|
|
454
|
-
${
|
|
384
|
+
${ui.format.dim('Fork from GitHub with specific branch')}
|
|
385
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent fork https://github.com/user/repo.git MyApp --branch develop')}
|
|
455
386
|
|
|
456
|
-
${
|
|
457
|
-
${
|
|
387
|
+
${ui.format.dim('Fork private repository with authentication')}
|
|
388
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent fork https://github.com/user/repo.git MyApp -u username -t token')}
|
|
458
389
|
|
|
459
|
-
${
|
|
460
|
-
${
|
|
390
|
+
${ui.format.dim('Fork using git@ URL')}
|
|
391
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent fork git@github.com:user/repo.git MyApp')}
|
|
461
392
|
`)
|
|
462
393
|
.action(forkCommand);
|
|
463
394
|
program
|
|
@@ -469,16 +400,16 @@ ${chalk.bold.white('EXAMPLES')}
|
|
|
469
400
|
.option('-t, --token <token>', 'GitHub token for authenticated access')
|
|
470
401
|
.description('Import an app from a local directory or git repository (alias for fork)')
|
|
471
402
|
.addHelpText('after', `
|
|
472
|
-
${
|
|
403
|
+
${ui.format.boldWhite('DESCRIPTION')}
|
|
473
404
|
Imports an Agentlang application from a source path. This is an alias for the
|
|
474
405
|
'fork' command and uses the same functionality.
|
|
475
406
|
|
|
476
|
-
${
|
|
477
|
-
${
|
|
478
|
-
${
|
|
407
|
+
${ui.format.boldWhite('EXAMPLES')}
|
|
408
|
+
${ui.format.dim('Import from local directory')}
|
|
409
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent import ./my-app MyImportedApp')}
|
|
479
410
|
|
|
480
|
-
${
|
|
481
|
-
${
|
|
411
|
+
${ui.format.dim('Import from GitHub repository')}
|
|
412
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent import https://github.com/user/repo.git MyApp')}
|
|
482
413
|
`)
|
|
483
414
|
.action(forkCommand);
|
|
484
415
|
program
|
|
@@ -488,7 +419,7 @@ ${chalk.bold.white('EXAMPLES')}
|
|
|
488
419
|
.option('--server-only', 'Start only the backend server without opening the UI')
|
|
489
420
|
.description('Start Agentlang Studio with local server')
|
|
490
421
|
.addHelpText('after', `
|
|
491
|
-
${
|
|
422
|
+
${ui.format.boldWhite('DESCRIPTION')}
|
|
492
423
|
Starts the Agentlang Design Studio locally for your project. This command:
|
|
493
424
|
• Starts the Agentlang server (via 'agent run')
|
|
494
425
|
• Serves the Studio UI on a local web server
|
|
@@ -497,21 +428,21 @@ ${chalk.bold.white('DESCRIPTION')}
|
|
|
497
428
|
The Studio UI allows you to visually edit Agents, Data Models, and Workflows,
|
|
498
429
|
with changes saved directly to your project files (.al files, package.json, etc.).
|
|
499
430
|
|
|
500
|
-
${
|
|
501
|
-
${
|
|
502
|
-
${
|
|
431
|
+
${ui.format.boldWhite('EXAMPLES')}
|
|
432
|
+
${ui.format.dim('Start Studio in current directory')}
|
|
433
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent studio')}
|
|
503
434
|
|
|
504
|
-
${
|
|
505
|
-
${
|
|
435
|
+
${ui.format.dim('Start Studio for specific project')}
|
|
436
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent studio ./my-project')}
|
|
506
437
|
|
|
507
|
-
${
|
|
508
|
-
${
|
|
438
|
+
${ui.format.dim('Start Studio on custom port')}
|
|
439
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent studio --port 5000')}
|
|
509
440
|
|
|
510
|
-
${
|
|
511
|
-
${
|
|
441
|
+
${ui.format.dim('Start Studio with path and custom port')}
|
|
442
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent studio ./monitoring -p 5000')}
|
|
512
443
|
|
|
513
|
-
${
|
|
514
|
-
${
|
|
444
|
+
${ui.format.dim('Start only the backend server (for development)')}
|
|
445
|
+
${ui.format.dim('$')} ${ui.format.cyan('agent studio --server-only')}
|
|
515
446
|
`)
|
|
516
447
|
.action(studioCommand);
|
|
517
448
|
program.parse(process.argv);
|
|
@@ -532,12 +463,10 @@ export const parseAndValidate = async (fileName) => {
|
|
|
532
463
|
const parseResult = document.parseResult;
|
|
533
464
|
// verify no lexer, parser, or general diagnostic errors show up
|
|
534
465
|
if (parseResult.lexerErrors.length === 0 && parseResult.parserErrors.length === 0) {
|
|
535
|
-
|
|
536
|
-
console.log(chalk.green(`Parsed and validated ${fileName} successfully!`));
|
|
466
|
+
ui.success(`Parsed and validated ${fileName} successfully!`);
|
|
537
467
|
}
|
|
538
468
|
else {
|
|
539
|
-
|
|
540
|
-
console.log(chalk.red(`Failed to parse and validate ${fileName}!`));
|
|
469
|
+
ui.error(`Failed to parse and validate ${fileName}!`);
|
|
541
470
|
}
|
|
542
471
|
};
|
|
543
472
|
export const runModule = async (fileName) => {
|
|
@@ -559,9 +488,8 @@ export const runModule = async (fileName) => {
|
|
|
559
488
|
});
|
|
560
489
|
}
|
|
561
490
|
catch (err) {
|
|
562
|
-
if (isNodeEnv
|
|
563
|
-
|
|
564
|
-
console.error(chalk.red(String(err)));
|
|
491
|
+
if (isNodeEnv) {
|
|
492
|
+
ui.error(String(err));
|
|
565
493
|
}
|
|
566
494
|
else {
|
|
567
495
|
// eslint-disable-next-line no-console
|
|
@@ -587,8 +515,7 @@ export const replCommand = async (directory, options) => {
|
|
|
587
515
|
});
|
|
588
516
|
}
|
|
589
517
|
catch (error) {
|
|
590
|
-
|
|
591
|
-
console.log(chalk.red(`Failed to start REPL: ${error instanceof Error ? error.message : String(error)}`));
|
|
518
|
+
ui.error(`Failed to start REPL: ${error instanceof Error ? error.message : String(error)}`);
|
|
592
519
|
process.exit(1);
|
|
593
520
|
}
|
|
594
521
|
};
|
|
@@ -601,20 +528,23 @@ export async function internAndRunModule(module, appSpec) {
|
|
|
601
528
|
await runPostInitTasks(appSpec);
|
|
602
529
|
return rm;
|
|
603
530
|
}
|
|
604
|
-
/* eslint-disable no-console */
|
|
605
531
|
export const generateUICommand = async (specFile, options) => {
|
|
606
532
|
try {
|
|
607
|
-
|
|
533
|
+
ui.blank();
|
|
534
|
+
ui.banner('UI Generator');
|
|
535
|
+
ui.blank();
|
|
608
536
|
// Get API key from options or environment
|
|
609
537
|
const apiKey = (options === null || options === void 0 ? void 0 : options.apiKey) || process.env.ANTHROPIC_API_KEY;
|
|
610
538
|
if (!apiKey) {
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
539
|
+
ui.error('Anthropic API key is required.');
|
|
540
|
+
ui.warn('Set ANTHROPIC_API_KEY environment variable or use --api-key flag.');
|
|
541
|
+
ui.blank();
|
|
542
|
+
ui.gray(' Example:');
|
|
543
|
+
ui.gray(' $ export ANTHROPIC_API_KEY=sk-ant-...');
|
|
544
|
+
ui.gray(' $ agent ui-gen');
|
|
545
|
+
ui.blank();
|
|
546
|
+
ui.gray(' Or:');
|
|
547
|
+
ui.gray(' $ agent ui-gen --api-key sk-ant-...');
|
|
618
548
|
process.exit(1);
|
|
619
549
|
}
|
|
620
550
|
// Set target directory
|
|
@@ -623,52 +553,51 @@ export const generateUICommand = async (specFile, options) => {
|
|
|
623
553
|
// Auto-detect spec file if not provided
|
|
624
554
|
let specFilePath;
|
|
625
555
|
if (!specFile) {
|
|
626
|
-
|
|
556
|
+
ui.dim('Searching for UI spec file...');
|
|
627
557
|
specFilePath = await findSpecFile(absoluteTargetDir);
|
|
628
558
|
}
|
|
629
559
|
else {
|
|
630
560
|
specFilePath = path.resolve(process.cwd(), specFile);
|
|
631
561
|
}
|
|
632
562
|
// Load the UI spec
|
|
633
|
-
console.log(chalk.cyan(`📄 Loading UI spec from: ${specFilePath}`));
|
|
634
563
|
const uiSpec = await loadUISpec(specFilePath);
|
|
635
|
-
|
|
636
|
-
|
|
564
|
+
ui.label('Spec', specFilePath, 'cyan');
|
|
565
|
+
ui.label('Target', absoluteTargetDir);
|
|
566
|
+
ui.label('Output', path.join(absoluteTargetDir, 'ui'));
|
|
567
|
+
ui.blank();
|
|
637
568
|
// Generate or update the UI
|
|
638
569
|
await generateUI(uiSpec, absoluteTargetDir, apiKey, (options === null || options === void 0 ? void 0 : options.push) || false, options === null || options === void 0 ? void 0 : options.message);
|
|
639
|
-
|
|
570
|
+
ui.blank();
|
|
571
|
+
ui.divider(50);
|
|
572
|
+
ui.success('UI generation completed!');
|
|
573
|
+
ui.divider(50);
|
|
574
|
+
ui.blank();
|
|
640
575
|
}
|
|
641
576
|
catch (error) {
|
|
642
|
-
|
|
577
|
+
ui.error(error instanceof Error ? error.message : String(error));
|
|
643
578
|
process.exit(1);
|
|
644
579
|
}
|
|
645
580
|
};
|
|
646
|
-
/* eslint-enable no-console */
|
|
647
|
-
/* eslint-disable no-console */
|
|
648
581
|
export const studioCommand = async (projectPath, options) => {
|
|
649
582
|
try {
|
|
650
583
|
const port = parseInt((options === null || options === void 0 ? void 0 : options.port) || '4000', 10);
|
|
651
584
|
if (isNaN(port) || port < 1 || port > 65535) {
|
|
652
|
-
|
|
585
|
+
ui.error('Invalid port number. Port must be between 1 and 65535.');
|
|
653
586
|
process.exit(1);
|
|
654
587
|
}
|
|
655
588
|
await startStudio(projectPath || '.', port, options === null || options === void 0 ? void 0 : options.serverOnly);
|
|
656
589
|
}
|
|
657
590
|
catch (error) {
|
|
658
|
-
|
|
591
|
+
ui.error(`Failed to start Studio: ${error instanceof Error ? error.message : String(error)}`);
|
|
659
592
|
process.exit(1);
|
|
660
593
|
}
|
|
661
594
|
};
|
|
662
|
-
/* eslint-enable no-console */
|
|
663
|
-
/* eslint-disable no-console */
|
|
664
595
|
export const forkCommand = async (source, name, options) => {
|
|
665
596
|
try {
|
|
666
|
-
console.log(chalk.blue('🚀 Forking Agentlang application...\n'));
|
|
667
597
|
// Determine destination name
|
|
668
598
|
let appName = name;
|
|
669
599
|
if (!appName) {
|
|
670
600
|
if (source.startsWith('http') || source.startsWith('git@')) {
|
|
671
|
-
// Try to infer from URL
|
|
672
601
|
const parts = source.split('/');
|
|
673
602
|
const lastPart = parts[parts.length - 1].replace('.git', '');
|
|
674
603
|
appName = lastPart;
|
|
@@ -690,24 +619,41 @@ export const forkCommand = async (source, name, options) => {
|
|
|
690
619
|
token: options.token,
|
|
691
620
|
};
|
|
692
621
|
}
|
|
693
|
-
|
|
694
|
-
|
|
622
|
+
ui.blank();
|
|
623
|
+
ui.banner('Fork App');
|
|
624
|
+
ui.blank();
|
|
625
|
+
ui.label('Source', source, 'cyan');
|
|
626
|
+
ui.label('Destination', destPath);
|
|
695
627
|
if (options === null || options === void 0 ? void 0 : options.branch) {
|
|
696
|
-
|
|
628
|
+
ui.label('Branch', options.branch, 'cyan');
|
|
697
629
|
}
|
|
698
630
|
if (forkOptions.credentials) {
|
|
699
|
-
|
|
631
|
+
ui.label('Auth', forkOptions.credentials.username, 'cyan');
|
|
700
632
|
}
|
|
633
|
+
ui.blank();
|
|
701
634
|
// Perform the fork
|
|
702
635
|
const result = await forkApp(source, destPath, forkOptions);
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
636
|
+
ui.divider(50);
|
|
637
|
+
ui.success(`Forked "${result.name}" successfully!`);
|
|
638
|
+
ui.blank();
|
|
639
|
+
ui.dim('Next steps:');
|
|
640
|
+
ui.row([
|
|
641
|
+
{ text: ' 1. Change directory: ', dimColor: true },
|
|
642
|
+
{ text: `cd ${result.name}`, color: 'cyan' },
|
|
643
|
+
]);
|
|
644
|
+
ui.row([
|
|
645
|
+
{ text: ' 2. Run your app: ', dimColor: true },
|
|
646
|
+
{ text: 'agent run', color: 'cyan' },
|
|
647
|
+
]);
|
|
648
|
+
ui.row([
|
|
649
|
+
{ text: ' 3. Or start Studio: ', dimColor: true },
|
|
650
|
+
{ text: 'agent studio', color: 'cyan' },
|
|
651
|
+
]);
|
|
652
|
+
ui.divider(50);
|
|
653
|
+
ui.blank();
|
|
708
654
|
}
|
|
709
655
|
catch (error) {
|
|
710
|
-
|
|
656
|
+
ui.error(error instanceof Error ? error.message : String(error));
|
|
711
657
|
process.exit(1);
|
|
712
658
|
}
|
|
713
659
|
};
|