-
Notifications
You must be signed in to change notification settings - Fork 41
Expand file tree
/
Copy pathcli.ts
More file actions
163 lines (142 loc) · 5.64 KB
/
cli.ts
File metadata and controls
163 lines (142 loc) · 5.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import { getOrCreateInstallationId } from '../lib/schemas/io/global-config';
import { registerABTestCommand } from './commands/abtest';
import { registerAdd } from './commands/add';
import { registerArchive } from './commands/archive';
import { registerConfigBundle } from './commands/config-bundle';
import { registerCreate } from './commands/create';
import { registerDeploy } from './commands/deploy';
import { registerDev } from './commands/dev';
import { registerEval } from './commands/eval';
import { registerFeedback } from './commands/feedback';
import { registerFetch } from './commands/fetch';
import { registerHelp } from './commands/help';
import { registerImport } from './commands/import';
import { registerInvoke } from './commands/invoke';
import { registerLogs } from './commands/logs';
import { registerPackage } from './commands/package';
import { registerPause, registerPromote } from './commands/pause';
import { registerRecommendations } from './commands/recommendations';
import { registerRemove } from './commands/remove';
import { registerResume } from './commands/resume';
import { registerRun } from './commands/run';
import { registerStatus } from './commands/status';
import { registerStop } from './commands/stop';
import { registerTelemetry } from './commands/telemetry';
import { registerTraces } from './commands/traces';
import { registerUpdate } from './commands/update';
import { registerValidate } from './commands/validate';
import { PACKAGE_VERSION } from './constants';
import { printPostCommandNotices, printTelemetryNotice } from './notices';
import { ALL_PRIMITIVES } from './primitives';
import { TelemetryClientAccessor } from './telemetry';
import { renderTUI, setupAltScreenCleanup } from './tui';
import { LayoutProvider } from './tui/context';
import { COMMAND_DESCRIPTIONS } from './tui/copy';
import { clearExitMessage, getExitMessage } from './tui/exit-message';
import { requireTTY } from './tui/guards';
import { CommandListScreen } from './tui/screens/home';
import { getCommandsForUI } from './tui/utils';
import { checkForUpdate } from './update-notifier';
import { Command } from '@commander-js/extra-typings';
import { render } from 'ink';
import React from 'react';
function renderHelp(program: Command): void {
const commands = getCommandsForUI(program);
render(React.createElement(LayoutProvider, null, React.createElement(CommandListScreen, { commands })));
}
export function createProgram(): Command {
const program = new Command();
program
.name('agentcore')
.description(COMMAND_DESCRIPTIONS.program)
.version(PACKAGE_VERSION)
.showHelpAfterError()
.showSuggestionAfterError();
// Custom help only for main program
program.addHelpCommand(false); // Disable default help subcommand
program.helpOption('-h, --help', 'Display help');
// Override help action for main program only
program.on('option:help', () => {
renderHelp(program);
process.exit(0);
});
registerCommands(program);
// Add help footer to all subcommands explaining interactive vs non-interactive
const helpFooter =
'\nRun without flags for interactive mode. Flags marked [non-interactive] trigger CLI mode.\nRun `agentcore help modes` for details.';
program.commands.forEach(cmd => {
cmd.addHelpText('after', helpFooter);
// Also add to nested subcommands (e.g., add agent, remove agent)
cmd.commands.forEach(subcmd => {
subcmd.addHelpText('after', helpFooter);
});
});
return program;
}
export function registerCommands(program: Command) {
const addCmd = registerAdd(program);
registerDev(program);
registerDeploy(program);
registerCreate(program);
registerEval(program);
registerFeedback(program);
registerFetch(program);
registerHelp(program);
registerImport(program);
registerInvoke(program);
registerLogs(program);
registerPackage(program);
registerPause(program);
registerRecommendations(program);
const removeCmd = registerRemove(program);
registerResume(program);
registerRun(program);
registerStatus(program);
registerStop(program);
registerPromote(program);
registerTelemetry(program);
registerTraces(program);
registerUpdate(program);
registerValidate(program);
registerConfigBundle(program);
registerArchive(program);
// Register primitive subcommands (add agent, remove agent, add memory, etc.)
for (const primitive of ALL_PRIMITIVES) {
primitive.registerCommands(addCmd, removeCmd);
}
// Register AB test detail command
registerABTestCommand(program);
}
export const main = async (argv: string[]) => {
// Register global cleanup handlers once at startup
setupAltScreenCleanup();
// Generate installationId on first run and show telemetry notice
const { created: isFirstRun } = await getOrCreateInstallationId();
const program = createProgram();
const args = argv.slice(2);
// Fire off non-blocking update check (skip for `update` command itself)
const isUpdateCommand = args[0] === 'update';
const updateCheck = isUpdateCommand ? Promise.resolve(null) : checkForUpdate();
// Show TUI for no arguments, commander handles --help via configureHelp()
if (args.length === 0) {
requireTTY();
await renderTUI({ updateCheck, isFirstRun });
return;
}
if (isFirstRun) {
printTelemetryNotice();
}
await TelemetryClientAccessor.init(args[0] ?? 'unknown');
try {
await program.parseAsync(argv);
} finally {
await TelemetryClientAccessor.shutdown();
}
// Telemetry notice already printed above; only run update check here.
await printPostCommandNotices(false, updateCheck);
const exitMessage = getExitMessage();
if (exitMessage) {
console.log(`\n${exitMessage}`);
clearExitMessage();
}
};