propr-cli 0.8.3
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/README.md +549 -0
- package/dist/api/agentTank.js +27 -0
- package/dist/api/agents.js +201 -0
- package/dist/api/client.js +284 -0
- package/dist/api/errors.js +145 -0
- package/dist/api/implement.js +147 -0
- package/dist/api/index.js +26 -0
- package/dist/api/logs.js +59 -0
- package/dist/api/plans.js +160 -0
- package/dist/api/relay.js +73 -0
- package/dist/api/repos.js +243 -0
- package/dist/api/settings.js +219 -0
- package/dist/api/system.js +53 -0
- package/dist/api/tasks.js +140 -0
- package/dist/api/todos.js +77 -0
- package/dist/api/types.js +6 -0
- package/dist/assets/.env.example +183 -0
- package/dist/assets/env.example.txt +198 -0
- package/dist/commands/agentCommands.js +405 -0
- package/dist/commands/checkCommands.js +384 -0
- package/dist/commands/implementCommands.js +178 -0
- package/dist/commands/index.js +22 -0
- package/dist/commands/initCommands.js +167 -0
- package/dist/commands/initStack.js +193 -0
- package/dist/commands/logCommands.js +170 -0
- package/dist/commands/planCommands.js +552 -0
- package/dist/commands/relayCommands.js +149 -0
- package/dist/commands/repoCommands.js +526 -0
- package/dist/commands/settingCommands.js +237 -0
- package/dist/commands/stackCommands.js +86 -0
- package/dist/commands/startCommand.js +36 -0
- package/dist/commands/systemCommands.js +221 -0
- package/dist/commands/tankCommands.js +55 -0
- package/dist/commands/taskCommands.js +554 -0
- package/dist/commands/todoCommands.js +620 -0
- package/dist/commands/uiDocsCommands.js +69 -0
- package/dist/config/ConfigManager.js +360 -0
- package/dist/config/index.js +8 -0
- package/dist/config/types.js +16 -0
- package/dist/index.js +276 -0
- package/dist/orchestrator/format.js +31 -0
- package/dist/orchestrator/index.js +102 -0
- package/dist/orchestrator/manifest.json +16 -0
- package/dist/orchestrator/orchestrator.mjs +798 -0
- package/dist/orchestrator/types.js +10 -0
- package/dist/tui/StartApp.js +175 -0
- package/dist/tui/app.js +9 -0
- package/dist/tui/render.js +87 -0
- package/dist/utils/envFile.js +65 -0
- package/dist/utils/index.js +8 -0
- package/dist/utils/io.js +186 -0
- package/dist/utils/parseState.js +14 -0
- package/dist/utils/resolveProject.js +50 -0
- package/dist/vendor/shared/demoMode.js +6 -0
- package/dist/vendor/shared/events.js +30 -0
- package/dist/vendor/shared/githubAuthMode.js +35 -0
- package/dist/vendor/shared/index.js +15 -0
- package/dist/vendor/shared/labelUtils.js +32 -0
- package/dist/vendor/shared/modelDefinitions.js +146 -0
- package/dist/vendor/shared/reviewPrompt.js +18 -0
- package/dist/vendor/shared/usageTypes.js +13 -0
- package/dist/vendor/shared/userWhitelist.js +30 -0
- package/dist/vendor/shared/validateRelayUrl.js +21 -0
- package/package.json +31 -0
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Management Commands
|
|
3
|
+
*
|
|
4
|
+
* CLI commands for managing AI agent configurations.
|
|
5
|
+
* Provides the `agent` command group with `list`, `add`, and `delete` subcommands.
|
|
6
|
+
*/
|
|
7
|
+
import { Command } from "commander";
|
|
8
|
+
import { listAgents, addAgent, deleteAgent, setAgentEnabled, AGENT_TYPES, } from "../api/agents.js";
|
|
9
|
+
import { ApiError, NetworkError, NotFoundError, UnauthorizedError } from "../api/errors.js";
|
|
10
|
+
import { printOutput, readJsonInput, validateJsonFields, JsonInputError, } from "../utils/index.js";
|
|
11
|
+
const AGENT_TYPE_LIST = AGENT_TYPES.join(", ");
|
|
12
|
+
/**
|
|
13
|
+
* Formats an agent type for display.
|
|
14
|
+
*/
|
|
15
|
+
function formatType(type) {
|
|
16
|
+
const typeMap = {
|
|
17
|
+
claude: "Claude",
|
|
18
|
+
codex: "Codex",
|
|
19
|
+
antigravity: "Antigravity",
|
|
20
|
+
opencode: "OpenCode",
|
|
21
|
+
vibe: "Mistral Vibe",
|
|
22
|
+
};
|
|
23
|
+
return typeMap[type?.toLowerCase()] || type;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Truncates a string to a maximum length.
|
|
27
|
+
*/
|
|
28
|
+
function truncate(str, maxLen) {
|
|
29
|
+
if (!str)
|
|
30
|
+
return "";
|
|
31
|
+
if (str.length <= maxLen)
|
|
32
|
+
return str;
|
|
33
|
+
return str.substring(0, maxLen - 3) + "...";
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Displays a table of agents with clean formatting.
|
|
37
|
+
*/
|
|
38
|
+
function displayAgentsTable(agents) {
|
|
39
|
+
const aliasWidth = Math.max("Alias".length, ...agents.map((a) => a.alias.length));
|
|
40
|
+
const typeWidth = Math.max("Type".length, ...agents.map((a) => formatType(a.type).length));
|
|
41
|
+
const enabledWidth = "Enabled".length;
|
|
42
|
+
const defaultModelWidth = Math.max("Default Model".length, ...agents.map((a) => truncate(a.defaultModel, 30).length));
|
|
43
|
+
const modelsWidth = Math.max("Supported Models".length, ...agents.map((a) => truncate(a.supportedModels.join(", "), 40).length));
|
|
44
|
+
const header = [
|
|
45
|
+
"Alias".padEnd(aliasWidth),
|
|
46
|
+
"Type".padEnd(typeWidth),
|
|
47
|
+
"Enabled".padEnd(enabledWidth),
|
|
48
|
+
"Default Model".padEnd(defaultModelWidth),
|
|
49
|
+
"Supported Models".padEnd(modelsWidth),
|
|
50
|
+
].join(" ");
|
|
51
|
+
console.log(header);
|
|
52
|
+
console.log("-".repeat(header.length));
|
|
53
|
+
for (const agent of agents) {
|
|
54
|
+
const row = [
|
|
55
|
+
agent.alias.padEnd(aliasWidth),
|
|
56
|
+
formatType(agent.type).padEnd(typeWidth),
|
|
57
|
+
(agent.enabled ? "Yes" : "No").padEnd(enabledWidth),
|
|
58
|
+
truncate(agent.defaultModel, 30).padEnd(defaultModelWidth),
|
|
59
|
+
truncate(agent.supportedModels.join(", "), 40).padEnd(modelsWidth),
|
|
60
|
+
].join(" ");
|
|
61
|
+
console.log(row);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Validates that the agent type is valid.
|
|
66
|
+
*/
|
|
67
|
+
function isValidAgentType(type) {
|
|
68
|
+
return AGENT_TYPES.includes(type.toLowerCase());
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Prompts the user for confirmation.
|
|
72
|
+
*/
|
|
73
|
+
async function confirm(message) {
|
|
74
|
+
const readline = await import("readline");
|
|
75
|
+
const rl = readline.createInterface({
|
|
76
|
+
input: process.stdin,
|
|
77
|
+
output: process.stdout,
|
|
78
|
+
});
|
|
79
|
+
return new Promise((resolve) => {
|
|
80
|
+
rl.question(`${message} (y/N): `, (answer) => {
|
|
81
|
+
rl.close();
|
|
82
|
+
resolve(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Creates the `agent` command group.
|
|
88
|
+
*/
|
|
89
|
+
export function createAgentCommand() {
|
|
90
|
+
const agent = new Command("agent")
|
|
91
|
+
.description("Manage AI agent configurations")
|
|
92
|
+
.addHelpText("after", `
|
|
93
|
+
Examples:
|
|
94
|
+
$ propr agent list # List all agents
|
|
95
|
+
$ propr agent add my-claude -t claude -m ... # Add an agent
|
|
96
|
+
$ propr agent delete my-agent # Delete an agent
|
|
97
|
+
`);
|
|
98
|
+
// agent list
|
|
99
|
+
agent
|
|
100
|
+
.command("list")
|
|
101
|
+
.description("List all configured AI agents with their models and status")
|
|
102
|
+
.option("-j, --json", "Output as JSON for programmatic use")
|
|
103
|
+
.addHelpText("after", `
|
|
104
|
+
Examples:
|
|
105
|
+
$ propr agent list
|
|
106
|
+
$ propr agent list --json
|
|
107
|
+
`)
|
|
108
|
+
.action(async (options) => {
|
|
109
|
+
try {
|
|
110
|
+
const result = await listAgents();
|
|
111
|
+
if (printOutput(result, options.json ?? false)) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
console.log("Fetching agents...");
|
|
115
|
+
if (result.agents.length === 0) {
|
|
116
|
+
console.log("");
|
|
117
|
+
console.log("No agents configured.");
|
|
118
|
+
console.log("");
|
|
119
|
+
console.log("To add an agent, use:");
|
|
120
|
+
console.log(" propr agent add <alias> --type <type> --model <models>");
|
|
121
|
+
console.log("");
|
|
122
|
+
console.log("Example:");
|
|
123
|
+
console.log(" propr agent add claude-prod --type claude --model claude-sonnet-4-20250514,claude-opus-4-20250514");
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
console.log("");
|
|
127
|
+
displayAgentsTable(result.agents);
|
|
128
|
+
console.log("");
|
|
129
|
+
console.log(`Total: ${result.agents.length} agent(s)`);
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
if (error instanceof UnauthorizedError) {
|
|
133
|
+
console.error("Error: Unauthorized. Please run 'propr login' first.");
|
|
134
|
+
}
|
|
135
|
+
else if (error instanceof NetworkError) {
|
|
136
|
+
console.error("Error: cannot reach the ProPR backend. Start the stack first: propr start");
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
console.error(`Error listing agents: ${error.message}`);
|
|
140
|
+
}
|
|
141
|
+
process.exit(1);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
// agent add
|
|
145
|
+
agent
|
|
146
|
+
.command("add [alias]")
|
|
147
|
+
.description("Add a new AI agent configuration for code implementation")
|
|
148
|
+
.option("-t, --type <type>", `Agent type (${AGENT_TYPE_LIST})`)
|
|
149
|
+
.option("-m, --model <models>", "Comma-separated list of supported models")
|
|
150
|
+
.option("-d, --default-model <model>", "Default model to use (defaults to first model)")
|
|
151
|
+
.option("--docker-image <image>", "Docker image for the agent")
|
|
152
|
+
.option("--config-path <path>", "Host path to mount for configuration")
|
|
153
|
+
.option("--disabled", "Create the agent in disabled state")
|
|
154
|
+
.option("-f, --file <path>", "Load agent configuration from JSON file (use '-' for stdin)")
|
|
155
|
+
.option("-j, --json", "Output result as JSON")
|
|
156
|
+
.addHelpText("after", `
|
|
157
|
+
Argument:
|
|
158
|
+
alias Unique identifier for the agent (required unless using --file)
|
|
159
|
+
|
|
160
|
+
Agent Types:
|
|
161
|
+
claude Anthropic Claude models
|
|
162
|
+
codex OpenAI Codex models
|
|
163
|
+
antigravity Antigravity models
|
|
164
|
+
opencode OpenCode models
|
|
165
|
+
vibe Mistral Vibe models
|
|
166
|
+
|
|
167
|
+
JSON File Format:
|
|
168
|
+
{
|
|
169
|
+
"alias": "my-agent",
|
|
170
|
+
"type": "claude",
|
|
171
|
+
"models": ["claude-sonnet-4-20250514", "claude-opus-4-20250514"],
|
|
172
|
+
"defaultModel": "claude-sonnet-4-20250514",
|
|
173
|
+
"dockerImage": "optional-image",
|
|
174
|
+
"configPath": "/optional/path",
|
|
175
|
+
"enabled": true
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
Examples:
|
|
179
|
+
$ propr agent add my-claude -t claude -m claude-sonnet-4-20250514
|
|
180
|
+
$ propr agent add opencode -t opencode -m opencode-minimax-m3-free
|
|
181
|
+
$ propr agent add prod-agent -t claude -m claude-sonnet-4-20250514,claude-opus-4-20250514 -d claude-sonnet-4-20250514
|
|
182
|
+
$ propr agent add test-agent -t antigravity -m antigravity-gemini-3-pro-preview --disabled
|
|
183
|
+
$ propr agent add --file agent-config.json
|
|
184
|
+
$ cat config.json | propr agent add --file -
|
|
185
|
+
`)
|
|
186
|
+
.action(async (aliasArg, options) => {
|
|
187
|
+
try {
|
|
188
|
+
let alias;
|
|
189
|
+
let type;
|
|
190
|
+
let models;
|
|
191
|
+
let defaultModel;
|
|
192
|
+
let dockerImage;
|
|
193
|
+
let configPath;
|
|
194
|
+
let enabled;
|
|
195
|
+
if (options.file) {
|
|
196
|
+
try {
|
|
197
|
+
const jsonConfig = await readJsonInput(options.file);
|
|
198
|
+
validateJsonFields(jsonConfig, ["alias", "type", "models"]);
|
|
199
|
+
alias = jsonConfig.alias;
|
|
200
|
+
type = jsonConfig.type.toLowerCase();
|
|
201
|
+
models = jsonConfig.models;
|
|
202
|
+
defaultModel = jsonConfig.defaultModel;
|
|
203
|
+
dockerImage = jsonConfig.dockerImage;
|
|
204
|
+
configPath = jsonConfig.configPath;
|
|
205
|
+
enabled = jsonConfig.enabled !== false;
|
|
206
|
+
}
|
|
207
|
+
catch (error) {
|
|
208
|
+
if (error instanceof JsonInputError) {
|
|
209
|
+
console.error(`Error: ${error.message}`);
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
console.error(`Error reading JSON file: ${error.message}`);
|
|
213
|
+
}
|
|
214
|
+
process.exit(1);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
if (!aliasArg) {
|
|
219
|
+
console.error("Error: Alias is required. Provide it as an argument or use --file.");
|
|
220
|
+
process.exit(1);
|
|
221
|
+
}
|
|
222
|
+
if (!options.type) {
|
|
223
|
+
console.error("Error: --type is required when not using --file");
|
|
224
|
+
process.exit(1);
|
|
225
|
+
}
|
|
226
|
+
if (!options.model) {
|
|
227
|
+
console.error("Error: --model is required when not using --file");
|
|
228
|
+
process.exit(1);
|
|
229
|
+
}
|
|
230
|
+
alias = aliasArg;
|
|
231
|
+
type = options.type.toLowerCase();
|
|
232
|
+
models = options.model
|
|
233
|
+
.split(",")
|
|
234
|
+
.map((m) => m.trim())
|
|
235
|
+
.filter((m) => m.length > 0);
|
|
236
|
+
defaultModel = options.defaultModel;
|
|
237
|
+
dockerImage = options.dockerImage;
|
|
238
|
+
configPath = options.configPath;
|
|
239
|
+
enabled = !options.disabled;
|
|
240
|
+
}
|
|
241
|
+
if (!isValidAgentType(type)) {
|
|
242
|
+
console.error(`Error: Invalid agent type '${type}'. Must be one of: ${AGENT_TYPE_LIST}`);
|
|
243
|
+
process.exit(1);
|
|
244
|
+
}
|
|
245
|
+
if (models.length === 0) {
|
|
246
|
+
console.error("Error: At least one model must be specified");
|
|
247
|
+
process.exit(1);
|
|
248
|
+
}
|
|
249
|
+
if (defaultModel && !models.includes(defaultModel)) {
|
|
250
|
+
console.error(`Error: Default model '${defaultModel}' is not in the list of supported models`);
|
|
251
|
+
process.exit(1);
|
|
252
|
+
}
|
|
253
|
+
if (!options.json) {
|
|
254
|
+
console.log(`Adding agent '${alias}'...`);
|
|
255
|
+
}
|
|
256
|
+
const result = await addAgent({
|
|
257
|
+
alias,
|
|
258
|
+
type,
|
|
259
|
+
models,
|
|
260
|
+
defaultModel,
|
|
261
|
+
dockerImage,
|
|
262
|
+
configPath,
|
|
263
|
+
enabled,
|
|
264
|
+
});
|
|
265
|
+
if (result.success) {
|
|
266
|
+
if (printOutput(result, options.json ?? false)) {
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
console.log("");
|
|
270
|
+
console.log(`Agent '${alias}' added successfully!`);
|
|
271
|
+
console.log("");
|
|
272
|
+
console.log("Configuration:");
|
|
273
|
+
console.log(` Type: ${formatType(type)}`);
|
|
274
|
+
console.log(` Enabled: ${enabled ? "Yes" : "No"}`);
|
|
275
|
+
console.log(` Models: ${models.join(", ")}`);
|
|
276
|
+
console.log(` Default Model: ${defaultModel || models[0]}`);
|
|
277
|
+
console.log("");
|
|
278
|
+
console.log(`Total agents configured: ${result.agents.length}`);
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
console.error("Failed to add agent");
|
|
282
|
+
process.exit(1);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
catch (error) {
|
|
286
|
+
if (error instanceof UnauthorizedError) {
|
|
287
|
+
console.error("Error: Unauthorized. Please run 'propr login' first.");
|
|
288
|
+
}
|
|
289
|
+
else if (error instanceof NetworkError) {
|
|
290
|
+
console.error("Error: cannot reach the ProPR backend. Start the stack first: propr start");
|
|
291
|
+
}
|
|
292
|
+
else if (error instanceof ApiError && error.message.includes("already exists")) {
|
|
293
|
+
console.error(`Error: ${error.message}`);
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
console.error(`Error adding agent: ${error.message}`);
|
|
297
|
+
}
|
|
298
|
+
process.exit(1);
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
// agent enable / disable
|
|
302
|
+
const applyEnabled = async (alias, enabled) => {
|
|
303
|
+
try {
|
|
304
|
+
const result = await setAgentEnabled(alias, enabled);
|
|
305
|
+
if (result.success) {
|
|
306
|
+
console.log(`Agent '${alias}' ${enabled ? "enabled" : "disabled"}.`);
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
console.error(`Failed to ${enabled ? "enable" : "disable"} agent '${alias}'`);
|
|
310
|
+
process.exit(1);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
catch (error) {
|
|
314
|
+
if (error instanceof NetworkError) {
|
|
315
|
+
console.error("Error: cannot reach the ProPR backend. Start the stack first: propr start");
|
|
316
|
+
}
|
|
317
|
+
else if (error instanceof NotFoundError || (error instanceof Error && error.message.includes("not found"))) {
|
|
318
|
+
console.error(`Error: Agent '${alias}' not found`);
|
|
319
|
+
}
|
|
320
|
+
else if (error instanceof UnauthorizedError) {
|
|
321
|
+
console.error("Error: Unauthorized. Please run 'propr login' first.");
|
|
322
|
+
}
|
|
323
|
+
else if (error instanceof ApiError) {
|
|
324
|
+
console.error(`Error updating agent: ${error.message}`);
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
console.error(`Error updating agent: ${error.message}`);
|
|
328
|
+
}
|
|
329
|
+
process.exit(1);
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
agent
|
|
333
|
+
.command("enable <alias>")
|
|
334
|
+
.description("Enable an agent (requires the stack to be running)")
|
|
335
|
+
.addHelpText("after", `
|
|
336
|
+
Example:
|
|
337
|
+
$ propr agent enable claude-prod
|
|
338
|
+
`)
|
|
339
|
+
.action(async (alias) => {
|
|
340
|
+
await applyEnabled(alias, true);
|
|
341
|
+
});
|
|
342
|
+
agent
|
|
343
|
+
.command("disable <alias>")
|
|
344
|
+
.description("Disable an agent (requires the stack to be running)")
|
|
345
|
+
.addHelpText("after", `
|
|
346
|
+
Example:
|
|
347
|
+
$ propr agent disable claude-prod
|
|
348
|
+
`)
|
|
349
|
+
.action(async (alias) => {
|
|
350
|
+
await applyEnabled(alias, false);
|
|
351
|
+
});
|
|
352
|
+
// agent delete
|
|
353
|
+
agent
|
|
354
|
+
.command("delete <alias>")
|
|
355
|
+
.description("Delete an AI agent configuration permanently")
|
|
356
|
+
.option("-f, --force", "Skip confirmation prompt")
|
|
357
|
+
.addHelpText("after", `
|
|
358
|
+
Argument:
|
|
359
|
+
alias The alias of the agent to delete
|
|
360
|
+
|
|
361
|
+
Examples:
|
|
362
|
+
$ propr agent delete my-agent # With confirmation
|
|
363
|
+
$ propr agent delete my-agent --force # Skip confirmation
|
|
364
|
+
`)
|
|
365
|
+
.action(async (alias, options) => {
|
|
366
|
+
try {
|
|
367
|
+
if (!options.force) {
|
|
368
|
+
console.log(`About to delete agent: ${alias}`);
|
|
369
|
+
console.log("");
|
|
370
|
+
const confirmed = await confirm("Are you sure you want to delete this agent?");
|
|
371
|
+
if (!confirmed) {
|
|
372
|
+
console.log("Deletion cancelled.");
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
console.log(`Deleting agent '${alias}'...`);
|
|
377
|
+
const result = await deleteAgent(alias);
|
|
378
|
+
if (result.success) {
|
|
379
|
+
console.log("");
|
|
380
|
+
console.log(`Agent '${alias}' deleted successfully!`);
|
|
381
|
+
console.log(`Remaining agents: ${result.agents.length}`);
|
|
382
|
+
}
|
|
383
|
+
else {
|
|
384
|
+
console.error("Failed to delete agent");
|
|
385
|
+
process.exit(1);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
catch (error) {
|
|
389
|
+
if (error instanceof UnauthorizedError) {
|
|
390
|
+
console.error("Error: Unauthorized. Please run 'propr login' first.");
|
|
391
|
+
}
|
|
392
|
+
else if (error instanceof NotFoundError) {
|
|
393
|
+
console.error(`Error: Agent '${alias}' not found`);
|
|
394
|
+
}
|
|
395
|
+
else if (error instanceof NetworkError) {
|
|
396
|
+
console.error("Error: cannot reach the ProPR backend. Start the stack first: propr start");
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
console.error(`Error deleting agent: ${error.message}`);
|
|
400
|
+
}
|
|
401
|
+
process.exit(1);
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
return agent;
|
|
405
|
+
}
|