@pantheon.ai/agents 0.0.10 → 0.0.11
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 +43 -6
- package/dist/index.js +384 -151
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,16 +1,43 @@
|
|
|
1
1
|
# `@pantheon.ai/agents`
|
|
2
2
|
|
|
3
|
-
This package
|
|
3
|
+
This package provides the `pantheon-agents` CLI for managing agent configs and tasks backed by a TiDB/MySQL task list.
|
|
4
|
+
|
|
5
|
+
It includes:
|
|
4
6
|
|
|
5
7
|
- A **runner loop** (`pantheon-agents run <agent>`) that executes queued tasks via Pantheon and persists status/output to TiDB.
|
|
6
8
|
- A **client-facing server** (`pantheon-agents server`) that exposes the same task operations over **HTTP REST** and **MCP (HTTP+SSE)**.
|
|
7
9
|
|
|
8
|
-
##
|
|
10
|
+
## Build
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm run -w @pantheon.ai/agents build
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Environment variables
|
|
17
|
+
|
|
18
|
+
- `DATABASE_URL` (required): MySQL/TiDB connection string for the task list database.
|
|
19
|
+
- `PANTHEON_API_KEY` (required for some commands): Used to query/execute Pantheon branches.
|
|
20
|
+
- `PANTHEON_AGENTS_API_TOKEN` (optional): Bearer token for API auth when running `pantheon-agents server` (defaults for `--token`).
|
|
21
|
+
|
|
22
|
+
Command requirements:
|
|
23
|
+
|
|
24
|
+
- `pantheon-agents add-task|delete-task|show-config|show-tasks`: requires `DATABASE_URL`
|
|
25
|
+
- `pantheon-agents run`: requires `DATABASE_URL` + `PANTHEON_API_KEY`
|
|
26
|
+
- `pantheon-agents config`: requires `DATABASE_URL`, and requires `PANTHEON_API_KEY` when `--bootstrap` is enabled (default) or when `--root-branch-id` is not provided
|
|
27
|
+
- `pantheon-agents reconfig`: requires `DATABASE_URL` + `PANTHEON_API_KEY`
|
|
28
|
+
- `pantheon-agents server`: requires `DATABASE_URL`; auth uses `--token` or env `PANTHEON_AGENTS_API_TOKEN` (unless `--no-auth`)
|
|
9
29
|
|
|
10
|
-
|
|
11
|
-
- `PANTHEON_API_KEY` is required for the runner loop (`pantheon-agents run`) and bootstrap config flows.
|
|
30
|
+
Notes:
|
|
12
31
|
|
|
13
|
-
|
|
32
|
+
- `PANTHEON_API_KEY` is also required for config-related server endpoints/tools that read Pantheon branch output or re-bootstrap configs.
|
|
33
|
+
|
|
34
|
+
## Show tasks output modes
|
|
35
|
+
|
|
36
|
+
- Default: concise one-line entries.
|
|
37
|
+
- Table output: use `--no-concise`.
|
|
38
|
+
- JSON output: use `--json`.
|
|
39
|
+
|
|
40
|
+
## DB schema / migrations
|
|
14
41
|
|
|
15
42
|
The schema lives in `packages/agents/src/db/schema/tidb.sql`.
|
|
16
43
|
|
|
@@ -59,6 +86,15 @@ curl -sS -H "Authorization: Bearer $TOKEN" \\
|
|
|
59
86
|
|
|
60
87
|
curl -sS -H "Authorization: Bearer $TOKEN" \\
|
|
61
88
|
-X DELETE http://127.0.0.1:8000/api/v1/agents/<agent>/tasks/<task_id>
|
|
89
|
+
|
|
90
|
+
# Get agent config (includes bootstrap branch output)
|
|
91
|
+
curl -sS -H "Authorization: Bearer $TOKEN" \\
|
|
92
|
+
http://127.0.0.1:8000/api/v1/agents/<agent>/configs/<project_id>
|
|
93
|
+
|
|
94
|
+
# Re-bootstrap agent config (like `pantheon-agents reconfig`)
|
|
95
|
+
curl -sS -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \\
|
|
96
|
+
-X POST http://127.0.0.1:8000/api/v1/agents/<agent>/configs/<project_id>/reconfig \\
|
|
97
|
+
-d '{ "role": "reviewer", "skills": ["style-reviewer"] }'
|
|
62
98
|
```
|
|
63
99
|
|
|
64
100
|
### MCP (HTTP+SSE)
|
|
@@ -73,4 +109,5 @@ Tools:
|
|
|
73
109
|
- `tasks.create`
|
|
74
110
|
- `tasks.cancel`
|
|
75
111
|
- `tasks.delete`
|
|
76
|
-
|
|
112
|
+
- `configs.get`
|
|
113
|
+
- `configs.reconfig`
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
|
-
import
|
|
4
|
-
import
|
|
3
|
+
import { Command, createCommand } from "commander";
|
|
4
|
+
import process$1 from "node:process";
|
|
5
5
|
import * as fs from "node:fs";
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import { multistream, pino, transport } from "pino";
|
|
@@ -420,7 +420,7 @@ var require_cli_options = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
420
420
|
|
|
421
421
|
//#endregion
|
|
422
422
|
//#region package.json
|
|
423
|
-
var version$1 = "0.0.
|
|
423
|
+
var version$1 = "0.0.11";
|
|
424
424
|
|
|
425
425
|
//#endregion
|
|
426
426
|
//#region src/schemas/task-list.ts
|
|
@@ -9780,38 +9780,37 @@ async function runAgent(name, options, logger) {
|
|
|
9780
9780
|
}
|
|
9781
9781
|
async function configAgent(name, options) {
|
|
9782
9782
|
const provider = new TaskListTidbProvider(name, pino());
|
|
9783
|
-
|
|
9784
|
-
|
|
9785
|
-
|
|
9786
|
-
|
|
9787
|
-
|
|
9788
|
-
|
|
9789
|
-
|
|
9790
|
-
|
|
9791
|
-
|
|
9792
|
-
|
|
9793
|
-
|
|
9794
|
-
process.exitCode = 1;
|
|
9795
|
-
return;
|
|
9796
|
-
}
|
|
9797
|
-
console.log(`Configuring agent ${name} as ${options.role} for project ${options.projectId}.`);
|
|
9798
|
-
if (!options.rootBranchId) {
|
|
9799
|
-
console.log("No root branch id specified, using project root branch.");
|
|
9800
|
-
const project = await getPantheonProjectInfo({ projectId: options.projectId });
|
|
9801
|
-
if (!project.root_branch_id) {
|
|
9802
|
-
console.error(`Project ${options.projectId} has no root branch. Project status is ${project.status}`);
|
|
9803
|
-
await provider.close();
|
|
9783
|
+
try {
|
|
9784
|
+
const previousConfig = await provider.getAgentConfig(options.projectId);
|
|
9785
|
+
if (previousConfig) {
|
|
9786
|
+
if (previousConfig.role === options.role) {
|
|
9787
|
+
console.log(`Agent ${name} already configured as ${options.role} for project ${options.projectId}.`);
|
|
9788
|
+
console.log(`Base branch id: ${previousConfig.base_branch_id}`);
|
|
9789
|
+
return;
|
|
9790
|
+
}
|
|
9791
|
+
console.error(`Agent ${name} already configured as ${previousConfig.role} for project ${options.projectId}.`);
|
|
9792
|
+
console.error(`Base branch id: ${previousConfig.base_branch_id}`);
|
|
9793
|
+
console.error(`Cannot change role to ${options.role}`);
|
|
9804
9794
|
process.exitCode = 1;
|
|
9805
9795
|
return;
|
|
9806
9796
|
}
|
|
9807
|
-
options.
|
|
9808
|
-
|
|
9809
|
-
|
|
9810
|
-
|
|
9811
|
-
|
|
9812
|
-
|
|
9813
|
-
|
|
9814
|
-
|
|
9797
|
+
console.log(`Configuring agent ${name} as ${options.role} for project ${options.projectId}.`);
|
|
9798
|
+
if (!options.rootBranchId) {
|
|
9799
|
+
console.log("No root branch id specified, using project root branch.");
|
|
9800
|
+
const project = await getPantheonProjectInfo({ projectId: options.projectId });
|
|
9801
|
+
if (!project.root_branch_id) {
|
|
9802
|
+
console.error(`Project ${options.projectId} has no root branch. Project status is ${project.status}`);
|
|
9803
|
+
process.exitCode = 1;
|
|
9804
|
+
return;
|
|
9805
|
+
}
|
|
9806
|
+
options.rootBranchId = project.root_branch_id;
|
|
9807
|
+
}
|
|
9808
|
+
if (options.bootstrap) {
|
|
9809
|
+
const branchId = await executeOnPantheon({
|
|
9810
|
+
projectId: options.projectId,
|
|
9811
|
+
branchId: options.rootBranchId,
|
|
9812
|
+
agent: "codex",
|
|
9813
|
+
prompt: `You must follow these instructions":
|
|
9815
9814
|
1. Clone the main branch from ${options.prototypeUrl} to a temporary directory (<pantheon-agents> in follow instructions references to this directory).
|
|
9816
9815
|
2. Copy the <pantheon-agents>/agents/${options.role}/AGENTS.md to \`<workspace>/AGENTS.md\`.
|
|
9817
9816
|
3. Copy the <pantheon-agents>/agents/${options.role}/skills directory to \`<workspace>/.codex/skills\` if the source directory exists.
|
|
@@ -9825,58 +9824,61 @@ Validate <workspace>: check if files and directorys exists:
|
|
|
9825
9824
|
|
|
9826
9825
|
Finally, outputs the first 5 lines of <workspace>/AGENTS.md and the skills list in <workspace>/.codex/skills
|
|
9827
9826
|
`
|
|
9828
|
-
});
|
|
9829
|
-
let retried = 0;
|
|
9830
|
-
const maxRetries = 3;
|
|
9831
|
-
let i = 0;
|
|
9832
|
-
console.log(`Bootstrap branch created: ${branchId}. Waiting for ready... [poll interval = 10s]`);
|
|
9833
|
-
while (true) {
|
|
9834
|
-
await new Promise((resolve) => {
|
|
9835
|
-
setTimeout(resolve, 1e4);
|
|
9836
9827
|
});
|
|
9837
|
-
|
|
9838
|
-
|
|
9839
|
-
|
|
9840
|
-
|
|
9841
|
-
|
|
9842
|
-
|
|
9843
|
-
|
|
9844
|
-
|
|
9845
|
-
|
|
9846
|
-
|
|
9847
|
-
|
|
9848
|
-
|
|
9828
|
+
let retried = 0;
|
|
9829
|
+
const maxRetries = 3;
|
|
9830
|
+
let i = 0;
|
|
9831
|
+
console.log(`Bootstrap branch created: ${branchId}. Waiting for ready... [poll interval = 10s]`);
|
|
9832
|
+
while (true) {
|
|
9833
|
+
await new Promise((resolve) => {
|
|
9834
|
+
setTimeout(resolve, 1e4);
|
|
9835
|
+
});
|
|
9836
|
+
const result = await getPantheonBranch({
|
|
9837
|
+
branchId,
|
|
9838
|
+
projectId: options.projectId,
|
|
9839
|
+
getOutputIfFinished: true
|
|
9840
|
+
}).then((result) => {
|
|
9841
|
+
retried = 0;
|
|
9842
|
+
return result;
|
|
9843
|
+
}).catch((reason) => {
|
|
9844
|
+
if (retried < maxRetries) {
|
|
9845
|
+
retried++;
|
|
9846
|
+
return { state: "others" };
|
|
9847
|
+
}
|
|
9848
|
+
throw new Error(`Failed to get bootstrap branch status. Retry ${retried} times. Last error: ${getErrorMessage(reason)}`);
|
|
9849
|
+
});
|
|
9850
|
+
if (result.state === "failed") {
|
|
9851
|
+
console.error("Bootstrap failed: " + result.error);
|
|
9852
|
+
process.exitCode = 1;
|
|
9853
|
+
return;
|
|
9854
|
+
}
|
|
9855
|
+
if (result.state === "succeed") {
|
|
9856
|
+
console.log("Bootstrap succeeded. Output is:");
|
|
9857
|
+
console.log(result.output);
|
|
9858
|
+
break;
|
|
9859
|
+
}
|
|
9860
|
+
console.log(`Bootstrap in progress... [${++i}]`);
|
|
9861
|
+
}
|
|
9862
|
+
await provider.setAgentConfig({
|
|
9863
|
+
project_id: options.projectId,
|
|
9864
|
+
base_branch_id: branchId,
|
|
9865
|
+
execute_agent: options.executeAgent,
|
|
9866
|
+
role: options.role,
|
|
9867
|
+
skills: options.skills,
|
|
9868
|
+
prototype_url: options.prototypeUrl
|
|
9849
9869
|
});
|
|
9850
|
-
|
|
9851
|
-
console.error("Bootstrap failed: " + result.error);
|
|
9852
|
-
await provider.close();
|
|
9853
|
-
process.exit(1);
|
|
9854
|
-
}
|
|
9855
|
-
if (result.state === "succeed") {
|
|
9856
|
-
console.log("Bootstrap succeeded. Output is:");
|
|
9857
|
-
console.log(result.output);
|
|
9858
|
-
break;
|
|
9859
|
-
}
|
|
9860
|
-
console.log(`Bootstrap in progress... [${++i}]`);
|
|
9861
|
-
}
|
|
9862
|
-
await provider.setAgentConfig({
|
|
9870
|
+
} else await provider.setAgentConfig({
|
|
9863
9871
|
project_id: options.projectId,
|
|
9864
|
-
base_branch_id:
|
|
9872
|
+
base_branch_id: options.rootBranchId,
|
|
9865
9873
|
execute_agent: options.executeAgent,
|
|
9866
9874
|
role: options.role,
|
|
9867
9875
|
skills: options.skills,
|
|
9868
9876
|
prototype_url: options.prototypeUrl
|
|
9869
9877
|
});
|
|
9870
|
-
|
|
9871
|
-
|
|
9872
|
-
|
|
9873
|
-
|
|
9874
|
-
role: options.role,
|
|
9875
|
-
skills: options.skills,
|
|
9876
|
-
prototype_url: options.prototypeUrl
|
|
9877
|
-
});
|
|
9878
|
-
console.log(`Agent ${name} configured successfully.`);
|
|
9879
|
-
await provider.close();
|
|
9878
|
+
console.log(`Agent ${name} configured successfully.`);
|
|
9879
|
+
} finally {
|
|
9880
|
+
await provider.close();
|
|
9881
|
+
}
|
|
9880
9882
|
}
|
|
9881
9883
|
async function reconfigAgentWithDeps(name, options, deps) {
|
|
9882
9884
|
const previousConfig = await deps.provider.getAgentConfig(options.projectId);
|
|
@@ -9939,15 +9941,18 @@ async function reconfigAgent(name, options) {
|
|
|
9939
9941
|
}
|
|
9940
9942
|
async function addTask(name, options) {
|
|
9941
9943
|
const provider = new TaskListTidbProvider(name, pino());
|
|
9942
|
-
|
|
9943
|
-
|
|
9944
|
-
|
|
9945
|
-
task
|
|
9946
|
-
|
|
9947
|
-
|
|
9948
|
-
|
|
9949
|
-
|
|
9950
|
-
|
|
9944
|
+
try {
|
|
9945
|
+
const config = await provider.getAgentConfig(options.projectId);
|
|
9946
|
+
if (!config) throw new Error(`Agent ${name} not configured for project ${options.projectId}`);
|
|
9947
|
+
const task = await provider.createTask({
|
|
9948
|
+
task: options.prompt,
|
|
9949
|
+
project_id: options.projectId,
|
|
9950
|
+
base_branch_id: config.base_branch_id
|
|
9951
|
+
});
|
|
9952
|
+
console.log(`Queued task ${task.id} successfully.`);
|
|
9953
|
+
} finally {
|
|
9954
|
+
await provider.close();
|
|
9955
|
+
}
|
|
9951
9956
|
}
|
|
9952
9957
|
async function deleteTask(agentName, taskId) {
|
|
9953
9958
|
const provider = new TaskListTidbProvider(agentName, pino());
|
|
@@ -10102,11 +10107,22 @@ async function assertsSingleton(logger, pidFile) {
|
|
|
10102
10107
|
}
|
|
10103
10108
|
}
|
|
10104
10109
|
|
|
10110
|
+
//#endregion
|
|
10111
|
+
//#region src/cli/utils/env.ts
|
|
10112
|
+
function ensureEnv(keys) {
|
|
10113
|
+
const missing = keys.filter((key) => !process.env[key]);
|
|
10114
|
+
if (missing.length === 0) return true;
|
|
10115
|
+
for (const key of missing) console.error(`${key} environment variable is not set.`);
|
|
10116
|
+
process.exitCode = 1;
|
|
10117
|
+
return false;
|
|
10118
|
+
}
|
|
10119
|
+
|
|
10105
10120
|
//#endregion
|
|
10106
10121
|
//#region src/cli/commands/add-task.ts
|
|
10107
10122
|
function createAddTaskCommand(version) {
|
|
10108
|
-
return createCommand("
|
|
10123
|
+
return createCommand("add-task").version(version).description("Add a task to an agent").argument("<name>", "The name of the agent.").argument("<project-id>", "The project id of the agent.").argument("<task-prompt>", "The prompt of the task.").action(async function() {
|
|
10109
10124
|
const [name, projectId, taskPrompt] = this.args;
|
|
10125
|
+
if (!ensureEnv(["DATABASE_URL"])) return;
|
|
10110
10126
|
await addTask(name, {
|
|
10111
10127
|
projectId,
|
|
10112
10128
|
prompt: taskPrompt
|
|
@@ -10117,12 +10133,16 @@ function createAddTaskCommand(version) {
|
|
|
10117
10133
|
//#endregion
|
|
10118
10134
|
//#region src/cli/commands/config.ts
|
|
10119
10135
|
function createConfigAgentCommand(version) {
|
|
10120
|
-
return createCommand("
|
|
10136
|
+
return createCommand("config").version(version).description("Configure agent for pantheon project").argument("<name>", "The name of the agent.").argument("<role>", "The role of the agent.").argument("<project-id>", "The project id of the agent.").option("--skills <skills>", "The skills of the agent. Multiple values are separated by comma.", (val) => val.split(",").map((s) => s.trim()).filter((s) => s !== ""), []).option("--execute-agent <agent>", "The execute agent of the agent.", "codex").option("--root-branch-id <branchId>", "The root branch id of the agent. Default to project root branch id.").option("--prototype-url <url>", "Role and skill definitions repo.", "https://github.com/pingcap-inc/pantheon-agents").option("--no-bootstrap", "Prevent bootstrap base branch for agent. Use the root branch as base branch.").action(async function() {
|
|
10121
10137
|
const [name, role, projectId] = this.args;
|
|
10138
|
+
const options = this.opts();
|
|
10139
|
+
const requiredEnvVars = ["DATABASE_URL"];
|
|
10140
|
+
if (options.bootstrap || !options.rootBranchId) requiredEnvVars.push("PANTHEON_API_KEY");
|
|
10141
|
+
if (!ensureEnv(requiredEnvVars)) return;
|
|
10122
10142
|
await configAgent(name, {
|
|
10123
10143
|
role,
|
|
10124
10144
|
projectId,
|
|
10125
|
-
...
|
|
10145
|
+
...options
|
|
10126
10146
|
});
|
|
10127
10147
|
});
|
|
10128
10148
|
}
|
|
@@ -10130,8 +10150,9 @@ function createConfigAgentCommand(version) {
|
|
|
10130
10150
|
//#endregion
|
|
10131
10151
|
//#region src/cli/commands/delete-task.ts
|
|
10132
10152
|
function createDeleteTaskCommand(version) {
|
|
10133
|
-
return createCommand("
|
|
10153
|
+
return createCommand("delete-task").version(version).description("Delete a task for an agent").argument("<name>", "The name of the agent.").argument("<task-id>", "The id of the task.").action(async function() {
|
|
10134
10154
|
const [name, taskId] = this.args;
|
|
10155
|
+
if (!ensureEnv(["DATABASE_URL"])) return;
|
|
10135
10156
|
const rl = readline.createInterface({
|
|
10136
10157
|
input: process$1.stdin,
|
|
10137
10158
|
output: process$1.stdout
|
|
@@ -10139,16 +10160,19 @@ function createDeleteTaskCommand(version) {
|
|
|
10139
10160
|
try {
|
|
10140
10161
|
if ((await rl.question(`Type the task id (${taskId}) to confirm deletion: `)).trim() !== taskId) {
|
|
10141
10162
|
console.error("Confirmation failed. Task id did not match.");
|
|
10142
|
-
process$1.
|
|
10163
|
+
process$1.exitCode = 1;
|
|
10164
|
+
return;
|
|
10143
10165
|
}
|
|
10144
10166
|
if ((await rl.question("Type DELETE to permanently remove this task: ")).trim() !== "DELETE") {
|
|
10145
10167
|
console.error("Confirmation failed. Aborting deletion.");
|
|
10146
|
-
process$1.
|
|
10168
|
+
process$1.exitCode = 1;
|
|
10169
|
+
return;
|
|
10147
10170
|
}
|
|
10148
10171
|
const deletedTask = await deleteTask(name, taskId);
|
|
10149
10172
|
if (!deletedTask) {
|
|
10150
10173
|
console.error(`Task ${taskId} not found for agent ${name}.`);
|
|
10151
|
-
process$1.
|
|
10174
|
+
process$1.exitCode = 1;
|
|
10175
|
+
return;
|
|
10152
10176
|
}
|
|
10153
10177
|
console.log(`Deleted task ${taskId} for agent ${name}. Status was ${deletedTask.status}.`);
|
|
10154
10178
|
} finally {
|
|
@@ -10177,33 +10201,31 @@ function parseUniqueCommaList(value) {
|
|
|
10177
10201
|
//#endregion
|
|
10178
10202
|
//#region src/cli/commands/reconfig.ts
|
|
10179
10203
|
function createReconfigAgentCommand(version) {
|
|
10180
|
-
return createCommand("
|
|
10204
|
+
return createCommand("reconfig").version(version).description("Re-bootstrap an existing agent configuration for a project").argument("<name>", "The name of the agent.").argument("<project-id>", "The project id of the agent.").option("--role <role>", "Override role for the agent.").option("--skills <skills>", "Override skills for the agent (comma-separated, replaces existing list).", parseUniqueCommaList).action(async function() {
|
|
10181
10205
|
const [name, projectId] = this.args;
|
|
10182
10206
|
const options = this.opts();
|
|
10207
|
+
if (!ensureEnv(["DATABASE_URL", "PANTHEON_API_KEY"])) return;
|
|
10183
10208
|
const resolvedRole = options.role?.trim();
|
|
10184
10209
|
if (options.role != null && !resolvedRole) {
|
|
10185
10210
|
console.error("--role must be non-empty.");
|
|
10186
|
-
process$1.
|
|
10187
|
-
|
|
10188
|
-
try {
|
|
10189
|
-
await reconfigAgent(name, {
|
|
10190
|
-
projectId,
|
|
10191
|
-
role: resolvedRole,
|
|
10192
|
-
skills: options.skills
|
|
10193
|
-
});
|
|
10194
|
-
} catch (error) {
|
|
10195
|
-
console.error(getErrorMessage(error));
|
|
10196
|
-
process$1.exit(1);
|
|
10211
|
+
process$1.exitCode = 1;
|
|
10212
|
+
return;
|
|
10197
10213
|
}
|
|
10214
|
+
await reconfigAgent(name, {
|
|
10215
|
+
projectId,
|
|
10216
|
+
role: resolvedRole,
|
|
10217
|
+
skills: options.skills
|
|
10218
|
+
});
|
|
10198
10219
|
});
|
|
10199
10220
|
}
|
|
10200
10221
|
|
|
10201
10222
|
//#endregion
|
|
10202
10223
|
//#region src/cli/commands/run.ts
|
|
10203
10224
|
function createRunAgentCommand(version) {
|
|
10204
|
-
return createCommand("
|
|
10225
|
+
return createCommand("run").version(version).description("Start a pantheon agent").argument("<name>", "The name of the agent.").option("--data-dir [dir]", "Data directory.", expandTilde("~/.pantheon-agents")).option("--loop-interval <seconds>", "The interval of the loop in seconds. Defaults to 5.", (val) => parseInt(val, 10), 5).action(async function() {
|
|
10205
10226
|
const [name] = this.args;
|
|
10206
10227
|
const options = this.opts();
|
|
10228
|
+
if (!ensureEnv(["DATABASE_URL", "PANTHEON_API_KEY"])) return;
|
|
10207
10229
|
const logFileTransport = transport({
|
|
10208
10230
|
target: "pino-roll",
|
|
10209
10231
|
options: {
|
|
@@ -21793,6 +21815,141 @@ function taskToDTO(agent, task) {
|
|
|
21793
21815
|
error: task.status === "failed" ? task.error : null
|
|
21794
21816
|
};
|
|
21795
21817
|
}
|
|
21818
|
+
function agentConfigToDTO(config) {
|
|
21819
|
+
return {
|
|
21820
|
+
agent: config.agent,
|
|
21821
|
+
project_id: config.project_id,
|
|
21822
|
+
base_branch_id: config.base_branch_id,
|
|
21823
|
+
role: config.role,
|
|
21824
|
+
skills: config.skills,
|
|
21825
|
+
prototype_url: config.prototype_url,
|
|
21826
|
+
execute_agent: config.execute_agent
|
|
21827
|
+
};
|
|
21828
|
+
}
|
|
21829
|
+
|
|
21830
|
+
//#endregion
|
|
21831
|
+
//#region src/server/agent-config.ts
|
|
21832
|
+
function assertPantheonApiKeyConfigured() {
|
|
21833
|
+
if (!process.env.PANTHEON_API_KEY?.trim()) throw new ApiError({
|
|
21834
|
+
status: 503,
|
|
21835
|
+
code: "pantheon_api_key_missing",
|
|
21836
|
+
message: "Missing PANTHEON_API_KEY. This endpoint requires Pantheon API access."
|
|
21837
|
+
});
|
|
21838
|
+
}
|
|
21839
|
+
async function getBranchOutputOrThrow(options) {
|
|
21840
|
+
let state;
|
|
21841
|
+
try {
|
|
21842
|
+
state = await options.getPantheonBranchFn({
|
|
21843
|
+
projectId: options.projectId,
|
|
21844
|
+
branchId: options.branchId,
|
|
21845
|
+
getOutputIfFinished: true,
|
|
21846
|
+
manifestingAsSucceed: true
|
|
21847
|
+
});
|
|
21848
|
+
} catch (error) {
|
|
21849
|
+
throw new ApiError({
|
|
21850
|
+
status: 502,
|
|
21851
|
+
code: "pantheon_api_error",
|
|
21852
|
+
message: `Failed to fetch Pantheon branch output for ${options.branchId}.`,
|
|
21853
|
+
details: {
|
|
21854
|
+
project_id: options.projectId,
|
|
21855
|
+
branch_id: options.branchId,
|
|
21856
|
+
error: getErrorMessage(error)
|
|
21857
|
+
}
|
|
21858
|
+
});
|
|
21859
|
+
}
|
|
21860
|
+
if (state.state === "succeed") return state.output ?? "";
|
|
21861
|
+
if (state.state === "failed") throw new ApiError({
|
|
21862
|
+
status: 502,
|
|
21863
|
+
code: "pantheon_branch_failed",
|
|
21864
|
+
message: `Pantheon branch ${options.branchId} failed.`,
|
|
21865
|
+
details: {
|
|
21866
|
+
project_id: options.projectId,
|
|
21867
|
+
branch_id: options.branchId,
|
|
21868
|
+
error: state.error
|
|
21869
|
+
}
|
|
21870
|
+
});
|
|
21871
|
+
throw new ApiError({
|
|
21872
|
+
status: 502,
|
|
21873
|
+
code: "pantheon_branch_not_ready",
|
|
21874
|
+
message: `Pantheon branch ${options.branchId} is not finished yet.`,
|
|
21875
|
+
details: {
|
|
21876
|
+
project_id: options.projectId,
|
|
21877
|
+
branch_id: options.branchId
|
|
21878
|
+
}
|
|
21879
|
+
});
|
|
21880
|
+
}
|
|
21881
|
+
async function getAgentConfigWithBootstrapOutput(options) {
|
|
21882
|
+
assertPantheonApiKeyConfigured();
|
|
21883
|
+
const config = await options.provider.getAgentConfig(options.projectId);
|
|
21884
|
+
if (!config) throw new ApiError({
|
|
21885
|
+
status: 404,
|
|
21886
|
+
code: "config_not_found",
|
|
21887
|
+
message: `No config found for agent ${options.agent} and project ${options.projectId}.`
|
|
21888
|
+
});
|
|
21889
|
+
const bootstrapOutput = await getBranchOutputOrThrow({
|
|
21890
|
+
projectId: config.project_id,
|
|
21891
|
+
branchId: config.base_branch_id,
|
|
21892
|
+
getPantheonBranchFn: options.getPantheonBranchFn ?? getPantheonBranch
|
|
21893
|
+
});
|
|
21894
|
+
return {
|
|
21895
|
+
config: agentConfigToDTO(config),
|
|
21896
|
+
bootstrap_output: bootstrapOutput
|
|
21897
|
+
};
|
|
21898
|
+
}
|
|
21899
|
+
async function reconfigAgentConfigWithBootstrapOutput(options) {
|
|
21900
|
+
assertPantheonApiKeyConfigured();
|
|
21901
|
+
const getPantheonBranchFn = options.getPantheonBranchFn ?? getPantheonBranch;
|
|
21902
|
+
const wrappedGetPantheonBranch = (args) => getPantheonBranchFn({
|
|
21903
|
+
...args,
|
|
21904
|
+
manifestingAsSucceed: true
|
|
21905
|
+
});
|
|
21906
|
+
let result;
|
|
21907
|
+
try {
|
|
21908
|
+
result = await reconfigAgentWithDeps(options.agent, options.reconfig, {
|
|
21909
|
+
provider: options.provider,
|
|
21910
|
+
executeOnPantheonFn: options.executeOnPantheonFn ?? executeOnPantheon,
|
|
21911
|
+
getPantheonBranchFn: wrappedGetPantheonBranch,
|
|
21912
|
+
sleep: options.sleep,
|
|
21913
|
+
pollIntervalMs: options.pollIntervalMs,
|
|
21914
|
+
maxRetries: options.maxRetries
|
|
21915
|
+
});
|
|
21916
|
+
} catch (error) {
|
|
21917
|
+
if (error instanceof ApiError) throw error;
|
|
21918
|
+
const message = getErrorMessage(error);
|
|
21919
|
+
if (message.startsWith("No config found for agent ")) throw new ApiError({
|
|
21920
|
+
status: 404,
|
|
21921
|
+
code: "config_not_found",
|
|
21922
|
+
message
|
|
21923
|
+
});
|
|
21924
|
+
if (message === "--role must be non-empty.") throw new ApiError({
|
|
21925
|
+
status: 400,
|
|
21926
|
+
code: "validation_error",
|
|
21927
|
+
message
|
|
21928
|
+
});
|
|
21929
|
+
if (message.startsWith("Bootstrap failed:")) throw new ApiError({
|
|
21930
|
+
status: 502,
|
|
21931
|
+
code: "bootstrap_failed",
|
|
21932
|
+
message
|
|
21933
|
+
});
|
|
21934
|
+
throw new ApiError({
|
|
21935
|
+
status: 502,
|
|
21936
|
+
code: "reconfig_failed",
|
|
21937
|
+
message,
|
|
21938
|
+
details: { error: message }
|
|
21939
|
+
});
|
|
21940
|
+
}
|
|
21941
|
+
const updated = await options.provider.getAgentConfig(result.previousConfig.project_id);
|
|
21942
|
+
if (!updated) throw new ApiError({
|
|
21943
|
+
status: 500,
|
|
21944
|
+
code: "config_update_lost",
|
|
21945
|
+
message: "Config disappeared after reconfig update."
|
|
21946
|
+
});
|
|
21947
|
+
return {
|
|
21948
|
+
previous_config: agentConfigToDTO(result.previousConfig),
|
|
21949
|
+
config: agentConfigToDTO(updated),
|
|
21950
|
+
bootstrap_output: result.bootstrapOutput
|
|
21951
|
+
};
|
|
21952
|
+
}
|
|
21796
21953
|
|
|
21797
21954
|
//#endregion
|
|
21798
21955
|
//#region src/server/api.ts
|
|
@@ -21831,6 +21988,10 @@ const createTaskBodySchema = z$1.object({
|
|
|
21831
21988
|
project_id: z$1.string().min(1),
|
|
21832
21989
|
task: z$1.string().min(1)
|
|
21833
21990
|
});
|
|
21991
|
+
const reconfigBodySchema = z$1.object({
|
|
21992
|
+
role: z$1.string().trim().min(1).optional(),
|
|
21993
|
+
skills: z$1.array(z$1.string().trim().min(1)).optional()
|
|
21994
|
+
});
|
|
21834
21995
|
function getAgentParam(value) {
|
|
21835
21996
|
if (typeof value !== "string" || value.trim().length === 0) throw new ApiError({
|
|
21836
21997
|
status: 400,
|
|
@@ -21839,6 +22000,14 @@ function getAgentParam(value) {
|
|
|
21839
22000
|
});
|
|
21840
22001
|
return value;
|
|
21841
22002
|
}
|
|
22003
|
+
function getProjectIdParam(value) {
|
|
22004
|
+
if (typeof value !== "string" || value.trim().length === 0) throw new ApiError({
|
|
22005
|
+
status: 400,
|
|
22006
|
+
code: "validation_error",
|
|
22007
|
+
message: "Invalid project_id parameter."
|
|
22008
|
+
});
|
|
22009
|
+
return value;
|
|
22010
|
+
}
|
|
21842
22011
|
function getTaskIdParam(value) {
|
|
21843
22012
|
if (typeof value !== "string" || value.trim().length === 0) throw new ApiError({
|
|
21844
22013
|
status: 400,
|
|
@@ -21854,6 +22023,31 @@ function createApiRouter(options) {
|
|
|
21854
22023
|
const agents = await new TaskListTidbProvider("server", logger, { db }).listAgentNames();
|
|
21855
22024
|
res.json({ agents });
|
|
21856
22025
|
}));
|
|
22026
|
+
router.get("/agents/:agent/configs/:project_id", asyncHandler(async (req, res) => {
|
|
22027
|
+
const agent = getAgentParam(req.params.agent);
|
|
22028
|
+
const result = await getAgentConfigWithBootstrapOutput({
|
|
22029
|
+
agent,
|
|
22030
|
+
projectId: getProjectIdParam(req.params.project_id),
|
|
22031
|
+
provider: new TaskListTidbProvider(agent, logger, { db })
|
|
22032
|
+
});
|
|
22033
|
+
res.json(result);
|
|
22034
|
+
}));
|
|
22035
|
+
router.post("/agents/:agent/configs/:project_id/reconfig", asyncHandler(async (req, res) => {
|
|
22036
|
+
const agent = getAgentParam(req.params.agent);
|
|
22037
|
+
const projectId = getProjectIdParam(req.params.project_id);
|
|
22038
|
+
const body = reconfigBodySchema.parse(req.body);
|
|
22039
|
+
const provider = new TaskListTidbProvider(agent, logger, { db });
|
|
22040
|
+
const result = await reconfigAgentConfigWithBootstrapOutput({
|
|
22041
|
+
agent,
|
|
22042
|
+
reconfig: {
|
|
22043
|
+
projectId,
|
|
22044
|
+
role: body.role,
|
|
22045
|
+
skills: body.skills
|
|
22046
|
+
},
|
|
22047
|
+
provider
|
|
22048
|
+
});
|
|
22049
|
+
res.json(result);
|
|
22050
|
+
}));
|
|
21857
22051
|
router.get("/agents/:agent/tasks", asyncHandler(async (req, res) => {
|
|
21858
22052
|
const agent = getAgentParam(req.params.agent);
|
|
21859
22053
|
const query = listTasksQuerySchema.parse(req.query);
|
|
@@ -31721,6 +31915,51 @@ function createAgentsMcpServer(options) {
|
|
|
31721
31915
|
structuredContent: { deleted: true }
|
|
31722
31916
|
};
|
|
31723
31917
|
});
|
|
31918
|
+
server.registerTool("configs.get", {
|
|
31919
|
+
description: "Get an agent's config for a project, including the bootstrap branch output.",
|
|
31920
|
+
inputSchema: {
|
|
31921
|
+
agent: z$1.string().min(1),
|
|
31922
|
+
project_id: z$1.string().min(1)
|
|
31923
|
+
}
|
|
31924
|
+
}, async ({ agent, project_id }) => {
|
|
31925
|
+
return {
|
|
31926
|
+
content: [{
|
|
31927
|
+
type: "text",
|
|
31928
|
+
text: "OK"
|
|
31929
|
+
}],
|
|
31930
|
+
structuredContent: await getAgentConfigWithBootstrapOutput({
|
|
31931
|
+
agent,
|
|
31932
|
+
projectId: project_id,
|
|
31933
|
+
provider: new TaskListTidbProvider(agent, options.logger, { db: options.db })
|
|
31934
|
+
})
|
|
31935
|
+
};
|
|
31936
|
+
});
|
|
31937
|
+
server.registerTool("configs.reconfig", {
|
|
31938
|
+
description: "Re-bootstrap an existing agent configuration for a project (like `pantheon-agents reconfig`).",
|
|
31939
|
+
inputSchema: {
|
|
31940
|
+
agent: z$1.string().min(1),
|
|
31941
|
+
project_id: z$1.string().min(1),
|
|
31942
|
+
role: z$1.string().trim().min(1).optional(),
|
|
31943
|
+
skills: z$1.array(z$1.string().trim().min(1)).optional()
|
|
31944
|
+
}
|
|
31945
|
+
}, async ({ agent, project_id, role, skills }) => {
|
|
31946
|
+
const provider = new TaskListTidbProvider(agent, options.logger, { db: options.db });
|
|
31947
|
+
return {
|
|
31948
|
+
content: [{
|
|
31949
|
+
type: "text",
|
|
31950
|
+
text: "OK"
|
|
31951
|
+
}],
|
|
31952
|
+
structuredContent: await reconfigAgentConfigWithBootstrapOutput({
|
|
31953
|
+
agent,
|
|
31954
|
+
reconfig: {
|
|
31955
|
+
projectId: project_id,
|
|
31956
|
+
role,
|
|
31957
|
+
skills
|
|
31958
|
+
},
|
|
31959
|
+
provider
|
|
31960
|
+
})
|
|
31961
|
+
};
|
|
31962
|
+
});
|
|
31724
31963
|
return server;
|
|
31725
31964
|
}
|
|
31726
31965
|
|
|
@@ -31831,11 +32070,13 @@ async function startAgentsServer(options, logger, overrides = {}) {
|
|
|
31831
32070
|
//#endregion
|
|
31832
32071
|
//#region src/cli/commands/server.ts
|
|
31833
32072
|
function createServerCommand(version) {
|
|
31834
|
-
return createCommand("
|
|
32073
|
+
return createCommand("server").version(version).description("Start the task HTTP API + MCP server").option("--host <host>", "Bind host. Defaults to 127.0.0.1.", "127.0.0.1").option("--port <port>", "Bind port. Defaults to 8000.", (v) => parseInt(v, 10), 8e3).option("--base-path <path>", "Mount base path prefix. Defaults to /.", "/").option("--token <token>", "Bearer token for API auth. Defaults to env PANTHEON_AGENTS_API_TOKEN.").option("--no-auth", "Disable auth (NOT recommended).").action(async function() {
|
|
31835
32074
|
const options = this.opts();
|
|
32075
|
+
if (!ensureEnv(["DATABASE_URL"])) return;
|
|
31836
32076
|
if (!Number.isInteger(options.port) || options.port <= 0) {
|
|
31837
32077
|
console.error("Invalid --port value. Must be a positive integer.");
|
|
31838
|
-
process$1.
|
|
32078
|
+
process$1.exitCode = 1;
|
|
32079
|
+
return;
|
|
31839
32080
|
}
|
|
31840
32081
|
const logger = pino({
|
|
31841
32082
|
timestamp: pino.stdTimeFunctions.isoTime,
|
|
@@ -31858,14 +32099,16 @@ function createServerCommand(version) {
|
|
|
31858
32099
|
//#endregion
|
|
31859
32100
|
//#region src/cli/commands/show-config.ts
|
|
31860
32101
|
function createShowConfigCommand(version) {
|
|
31861
|
-
return createCommand("
|
|
32102
|
+
return createCommand("show-config").version(version).description("Show agent config for a project").argument("<name>", "The name of the agent.").argument("[project-id]", "The project id.").option("--json", "Output config as JSON.").action(async function() {
|
|
31862
32103
|
const [name, projectId] = this.args;
|
|
31863
32104
|
const options = this.opts();
|
|
32105
|
+
if (!ensureEnv(["DATABASE_URL"])) return;
|
|
31864
32106
|
if (projectId) {
|
|
31865
32107
|
const config = await showAgentConfig(name, projectId);
|
|
31866
32108
|
if (!config) {
|
|
31867
32109
|
console.error(`No config found for agent ${name} and project ${projectId}.`);
|
|
31868
|
-
process$1.
|
|
32110
|
+
process$1.exitCode = 1;
|
|
32111
|
+
return;
|
|
31869
32112
|
}
|
|
31870
32113
|
if (options.json) {
|
|
31871
32114
|
console.log(JSON.stringify(config, null, 2));
|
|
@@ -31885,7 +32128,8 @@ function createShowConfigCommand(version) {
|
|
|
31885
32128
|
const configs = await showAgentConfigs(name);
|
|
31886
32129
|
if (!configs.length) {
|
|
31887
32130
|
console.error(`No configs found for agent ${name}.`);
|
|
31888
|
-
process$1.
|
|
32131
|
+
process$1.exitCode = 1;
|
|
32132
|
+
return;
|
|
31889
32133
|
}
|
|
31890
32134
|
if (options.json) {
|
|
31891
32135
|
console.log(JSON.stringify(configs, null, 2));
|
|
@@ -31922,46 +32166,50 @@ const orderDirections = ["asc", "desc"];
|
|
|
31922
32166
|
//#endregion
|
|
31923
32167
|
//#region src/cli/commands/show-tasks.ts
|
|
31924
32168
|
function createShowTasksCommand(version) {
|
|
31925
|
-
return createCommand("
|
|
32169
|
+
return createCommand("show-tasks").version(version).description("Show tasks for an agent").argument("[name]", "The name of the agent.").option("--agents <names>", "Comma-separated agent names to query in one call.", parseCommaList, []).option("--all", "Show tasks for all agents.").option("--status <status>", "Filter tasks by status. Multiple values are separated by comma.", parseCommaList, []).option("--order-by <field>", "Order by queued_at, started_at, or ended_at.", "queued_at").option("--order-direction <direction>", "Order direction: asc or desc.", "desc").option("--limit <number>", "Limit the number of tasks shown.", (val) => parseInt(val, 10)).option("--max-task-length <number>", "Maximum task length for table output.", (val) => parseInt(val, 10), 120).option("--full-task", "Do not truncate task text in output.").option("--no-concise", "Disable concise one-line entries.").option("--no-color", "Disable colored output.").option("--json", "Output tasks as JSON.").action(async function() {
|
|
31926
32170
|
const [name] = this.args;
|
|
31927
32171
|
const options = this.opts();
|
|
32172
|
+
if (!ensureEnv(["DATABASE_URL"])) return;
|
|
31928
32173
|
const agentNames = /* @__PURE__ */ new Set();
|
|
31929
32174
|
if (name) agentNames.add(name);
|
|
31930
32175
|
options.agents.forEach((agent) => agentNames.add(agent));
|
|
31931
32176
|
if (options.all && agentNames.size > 0) {
|
|
31932
32177
|
console.error("Use either a specific agent name or --all, not both.");
|
|
31933
|
-
process$1.
|
|
32178
|
+
process$1.exitCode = 1;
|
|
32179
|
+
return;
|
|
31934
32180
|
}
|
|
31935
32181
|
if (!options.all && agentNames.size === 0) {
|
|
31936
32182
|
console.error("Provide an agent name, --agents, or --all.");
|
|
31937
|
-
process$1.
|
|
32183
|
+
process$1.exitCode = 1;
|
|
32184
|
+
return;
|
|
31938
32185
|
}
|
|
31939
32186
|
const invalidStatuses = options.status.filter((status) => !taskStatuses.includes(status));
|
|
31940
32187
|
if (invalidStatuses.length > 0) {
|
|
31941
32188
|
console.error(`Invalid status values: ${invalidStatuses.join(", ")}. Allowed: ${taskStatuses.join(", ")}.`);
|
|
31942
|
-
process$1.
|
|
32189
|
+
process$1.exitCode = 1;
|
|
32190
|
+
return;
|
|
31943
32191
|
}
|
|
31944
32192
|
if (!orderByFields.includes(options.orderBy)) {
|
|
31945
32193
|
console.error(`Invalid order-by value: ${options.orderBy}. Allowed: ${orderByFields.join(", ")}.`);
|
|
31946
|
-
process$1.
|
|
32194
|
+
process$1.exitCode = 1;
|
|
32195
|
+
return;
|
|
31947
32196
|
}
|
|
31948
32197
|
if (!orderDirections.includes(options.orderDirection)) {
|
|
31949
32198
|
console.error(`Invalid order-direction value: ${options.orderDirection}. Allowed: ${orderDirections.join(", ")}.`);
|
|
31950
|
-
process$1.
|
|
32199
|
+
process$1.exitCode = 1;
|
|
32200
|
+
return;
|
|
31951
32201
|
}
|
|
31952
32202
|
if (options.limit != null && Number.isNaN(options.limit)) {
|
|
31953
32203
|
console.error("Invalid limit value. Must be a number.");
|
|
31954
|
-
process$1.
|
|
32204
|
+
process$1.exitCode = 1;
|
|
32205
|
+
return;
|
|
31955
32206
|
}
|
|
31956
32207
|
if (Number.isNaN(options.maxTaskLength) || options.maxTaskLength <= 0) {
|
|
31957
32208
|
console.error("Invalid max-task-length value. Must be a positive number.");
|
|
31958
|
-
process$1.
|
|
32209
|
+
process$1.exitCode = 1;
|
|
32210
|
+
return;
|
|
31959
32211
|
}
|
|
31960
32212
|
if (options.fullTask && options.maxTaskLength) options.maxTaskLength = Number.POSITIVE_INFINITY;
|
|
31961
|
-
if (options.json && options.concise) {
|
|
31962
|
-
console.error("Use either --json or --concise, not both.");
|
|
31963
|
-
process$1.exit(1);
|
|
31964
|
-
}
|
|
31965
32213
|
const limitedTasks = await showTasksForAgents({
|
|
31966
32214
|
agents: Array.from(agentNames),
|
|
31967
32215
|
allAgents: options.all,
|
|
@@ -31997,37 +32245,22 @@ function createShowTasksCommand(version) {
|
|
|
31997
32245
|
});
|
|
31998
32246
|
}
|
|
31999
32247
|
|
|
32000
|
-
//#endregion
|
|
32001
|
-
//#region src/cli/utils/env.ts
|
|
32002
|
-
function warnIfMissingEnv(keys) {
|
|
32003
|
-
for (const key of keys) if (!process.env[key]) console.error(`${key} environment variable is not set.`);
|
|
32004
|
-
}
|
|
32005
|
-
|
|
32006
32248
|
//#endregion
|
|
32007
32249
|
//#region src/cli/index.ts
|
|
32008
|
-
|
|
32009
|
-
|
|
32010
|
-
|
|
32011
|
-
|
|
32012
|
-
|
|
32013
|
-
|
|
32014
|
-
|
|
32015
|
-
|
|
32016
|
-
|
|
32017
|
-
|
|
32018
|
-
}
|
|
32019
|
-
|
|
32020
|
-
|
|
32021
|
-
|
|
32022
|
-
process$1.exit(1);
|
|
32023
|
-
}
|
|
32024
|
-
if (process$1.argv[2] === "help") {
|
|
32025
|
-
const command = process$1.argv[3];
|
|
32026
|
-
if (command in commands) commands[command].help({ error: false });
|
|
32027
|
-
else printCommandHelpAndExit(command);
|
|
32028
|
-
}
|
|
32029
|
-
if (!commands[process$1.argv[2]]) printCommandHelpAndExit(process$1.argv[2]);
|
|
32030
|
-
commands[process$1.argv[2]].parse(process$1.argv.slice(3), { from: "user" });
|
|
32250
|
+
const program = new Command().name("pantheon-agents").description("Pantheon agents CLI").version(version$1).showHelpAfterError().showSuggestionAfterError().addHelpCommand().addCommand(createAddTaskCommand(version$1)).addCommand(createConfigAgentCommand(version$1)).addCommand(createDeleteTaskCommand(version$1)).addCommand(createReconfigAgentCommand(version$1)).addCommand(createRunAgentCommand(version$1)).addCommand(createServerCommand(version$1)).addCommand(createShowConfigCommand(version$1)).addCommand(createShowTasksCommand(version$1));
|
|
32251
|
+
async function main() {
|
|
32252
|
+
if (process$1.argv.length <= 2) {
|
|
32253
|
+
program.outputHelp();
|
|
32254
|
+
return;
|
|
32255
|
+
}
|
|
32256
|
+
await program.parseAsync(process$1.argv);
|
|
32257
|
+
}
|
|
32258
|
+
try {
|
|
32259
|
+
await main();
|
|
32260
|
+
} catch (error) {
|
|
32261
|
+
console.error(getErrorMessage(error));
|
|
32262
|
+
process$1.exitCode = 1;
|
|
32263
|
+
}
|
|
32031
32264
|
|
|
32032
32265
|
//#endregion
|
|
32033
32266
|
export { };
|