@borgee/agents-host 0.2.2 → 0.2.26
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 +184 -21
- package/dist/agents-host-supervisor.d.ts +7 -5
- package/dist/agents-host-supervisor.js +24 -4
- package/dist/agents-host.d.ts +89 -15
- package/dist/agents-host.js +2099 -141
- package/dist/chat/chat-control-plane.d.ts +13 -2
- package/dist/chat/sdk-chat-control-plane.d.ts +14 -3
- package/dist/chat/sdk-chat-control-plane.js +54 -2
- package/dist/cli-args.d.ts +46 -5
- package/dist/cli-args.js +313 -32
- package/dist/cli.d.ts +9 -0
- package/dist/cli.js +112 -5
- package/dist/compatibility-gates.d.ts +35 -0
- package/dist/compatibility-gates.js +127 -0
- package/dist/config.d.ts +1 -0
- package/dist/config.js +23 -5
- package/dist/connections-state-store.d.ts +81 -0
- package/dist/connections-state-store.js +228 -0
- package/dist/context/injection.d.ts +109 -0
- package/dist/context/injection.js +350 -0
- package/dist/context/prompt.d.ts +4 -1
- package/dist/context/prompt.js +170 -1
- package/dist/context/turn-preparation.d.ts +9 -0
- package/dist/context/turn-preparation.js +106 -0
- package/dist/debug.d.ts +44 -0
- package/dist/debug.js +135 -0
- package/dist/gateway/localhost-gateway.d.ts +52 -0
- package/dist/gateway/localhost-gateway.js +857 -0
- package/dist/index.js +7 -5
- package/dist/local-config.d.ts +4 -1
- package/dist/local-config.js +24 -7
- package/dist/managed-daemon-log.d.ts +34 -0
- package/dist/managed-daemon-log.js +261 -0
- package/dist/managed-daemon.d.ts +220 -0
- package/dist/managed-daemon.js +1601 -0
- package/dist/policy/authorization-audit.d.ts +63 -0
- package/dist/policy/authorization-audit.js +94 -0
- package/dist/policy/copilot-permission.d.ts +15 -0
- package/dist/policy/copilot-permission.js +193 -0
- package/dist/policy/gateway-authorization.d.ts +42 -0
- package/dist/policy/gateway-authorization.js +162 -0
- package/dist/providers/awaiting-user.d.ts +12 -0
- package/dist/providers/awaiting-user.js +151 -0
- package/dist/providers/claude/adapter.d.ts +3 -1
- package/dist/providers/claude/adapter.js +8 -12
- package/dist/providers/claude/cli-client.d.ts +12 -5
- package/dist/providers/claude/cli-client.js +184 -37
- package/dist/providers/claude/session-store.d.ts +1 -0
- package/dist/providers/codex/adapter.d.ts +11 -0
- package/dist/providers/codex/adapter.js +19 -0
- package/dist/providers/codex/cli-client.d.ts +103 -0
- package/dist/providers/codex/cli-client.js +1133 -0
- package/dist/providers/codex/project-doc.d.ts +3 -0
- package/dist/providers/codex/project-doc.js +66 -0
- package/dist/providers/codex/session-store.d.ts +38 -0
- package/dist/providers/codex/session-store.js +150 -0
- package/dist/providers/copilot/adapter.d.ts +3 -1
- package/dist/providers/copilot/adapter.js +8 -12
- package/dist/providers/copilot/cli-client.d.ts +20 -2
- package/dist/providers/copilot/cli-client.js +251 -71
- package/dist/providers/copilot/session-store.d.ts +1 -0
- package/dist/providers/create-provider.d.ts +11 -2
- package/dist/providers/create-provider.js +131 -12
- package/dist/run.d.ts +1 -0
- package/dist/run.js +5 -2
- package/dist/state-paths.d.ts +13 -1
- package/dist/state-paths.js +84 -3
- package/dist/task-thread-resolution.d.ts +10 -0
- package/dist/task-thread-resolution.js +48 -0
- package/dist/types.d.ts +174 -1
- package/dist/visible-mentions.d.ts +3 -0
- package/dist/visible-mentions.js +15 -0
- package/package.json +19 -17
- package/skills/borgee-agent/SKILL.md +33 -0
- package/skills/borgee-agent/borgee-agent.mjs +473 -0
- package/skills/borgee-agent/borgee-agent.py +409 -0
|
@@ -1,10 +1,21 @@
|
|
|
1
|
-
import type { ChannelMessageEvent, MeResponseUser, PostedMessage } from '../types.js';
|
|
1
|
+
import type { ChannelSummary, ChannelHistoryEntry, ChannelMessageEvent, CreateTaskInput, DirectoryUser, MeResponseUser, PostMessageInput, PostedMessage, ReadChannelHistoryInput, Task, UpdateTaskInput } from '../types.js';
|
|
2
2
|
export interface ChatControlPlane {
|
|
3
3
|
connect(onMessage: (message: ChannelMessageEvent) => void): Promise<void>;
|
|
4
4
|
close(): Promise<void>;
|
|
5
|
-
postMessage(
|
|
5
|
+
postMessage(input: PostMessageInput): Promise<PostedMessage>;
|
|
6
6
|
editMessage(messageId: string, content: string): Promise<void>;
|
|
7
7
|
deleteMessage(messageId: string): Promise<void>;
|
|
8
8
|
startTyping(channelId: string): () => void;
|
|
9
9
|
getMe(): Promise<MeResponseUser>;
|
|
10
|
+
listUsers(): Promise<DirectoryUser[]>;
|
|
11
|
+
listChannels(): Promise<ChannelSummary[]>;
|
|
12
|
+
readChannelHistory(input: ReadChannelHistoryInput): Promise<ChannelHistoryEntry[]>;
|
|
13
|
+
createTask(input: CreateTaskInput): Promise<Task>;
|
|
14
|
+
listTasks(input: {
|
|
15
|
+
channelId: string;
|
|
16
|
+
}): Promise<Task[]>;
|
|
17
|
+
getTask(input: {
|
|
18
|
+
taskId: string;
|
|
19
|
+
}): Promise<Task>;
|
|
20
|
+
updateTask(input: UpdateTaskInput): Promise<Task>;
|
|
10
21
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type BorgeePluginClient, type BorgeePluginOptions, type InboundMessageEvent } from '@borgee/plugin-sdk';
|
|
2
|
-
import type { ChannelMessageEvent, MeResponseUser, PostedMessage } from '../types.js';
|
|
2
|
+
import type { ChannelSummary, ChannelHistoryEntry, ChannelMessageEvent, CreateTaskInput, DirectoryUser, MeResponseUser, PostMessageInput, PostedMessage, ReadChannelHistoryInput, Task, UpdateTaskInput } from '../types.js';
|
|
3
3
|
import type { ChatControlPlane } from './chat-control-plane.js';
|
|
4
|
-
type PluginClientLike = Pick<BorgeePluginClient, 'agentId' | 'close' | 'connect' | 'deleteMessage' | 'editMessage' | 'getMe' | 'on' | 'sendMessage' | 'startTyping'>;
|
|
4
|
+
type PluginClientLike = Pick<BorgeePluginClient, 'agentId' | 'close' | 'connect' | 'createTask' | 'deleteMessage' | 'editMessage' | 'getMe' | 'getTask' | 'listChannels' | 'listTasks' | 'listUsers' | 'on' | 'readHistory' | 'sendMessage' | 'startTyping' | 'updateTask'>;
|
|
5
5
|
type PluginClientFactory = (options: BorgeePluginOptions) => PluginClientLike;
|
|
6
6
|
type SdkChatControlPlaneOptions = Pick<BorgeePluginOptions, 'cursorStore' | 'pluginId'>;
|
|
7
7
|
/**
|
|
@@ -18,11 +18,22 @@ export declare class SdkChatControlPlane implements ChatControlPlane {
|
|
|
18
18
|
constructor(baseUrl: string, apiKey: string, createClient?: PluginClientFactory, options?: SdkChatControlPlaneOptions);
|
|
19
19
|
connect(onMessage: (message: ChannelMessageEvent) => void): Promise<void>;
|
|
20
20
|
close(): Promise<void>;
|
|
21
|
-
postMessage(
|
|
21
|
+
postMessage(input: PostMessageInput): Promise<PostedMessage>;
|
|
22
22
|
editMessage(messageId: string, content: string): Promise<void>;
|
|
23
23
|
deleteMessage(messageId: string): Promise<void>;
|
|
24
24
|
startTyping(channelId: string): () => void;
|
|
25
25
|
getMe(): Promise<MeResponseUser>;
|
|
26
|
+
listUsers(): Promise<DirectoryUser[]>;
|
|
27
|
+
readChannelHistory(input: ReadChannelHistoryInput): Promise<ChannelHistoryEntry[]>;
|
|
28
|
+
listChannels(): Promise<ChannelSummary[]>;
|
|
29
|
+
createTask(input: CreateTaskInput): Promise<Task>;
|
|
30
|
+
listTasks(input: {
|
|
31
|
+
channelId: string;
|
|
32
|
+
}): Promise<Task[]>;
|
|
33
|
+
getTask(input: {
|
|
34
|
+
taskId: string;
|
|
35
|
+
}): Promise<Task>;
|
|
36
|
+
updateTask(input: UpdateTaskInput): Promise<Task>;
|
|
26
37
|
}
|
|
27
38
|
export declare function mapInboundToChannelMessage(event: InboundMessageEvent): ChannelMessageEvent;
|
|
28
39
|
export {};
|
|
@@ -47,8 +47,12 @@ export class SdkChatControlPlane {
|
|
|
47
47
|
this.unsubscribe = null;
|
|
48
48
|
await this.client.close();
|
|
49
49
|
}
|
|
50
|
-
async postMessage(
|
|
51
|
-
const sent = await this.client.sendMessage({
|
|
50
|
+
async postMessage(input) {
|
|
51
|
+
const sent = await this.client.sendMessage({
|
|
52
|
+
channelId: input.channelId,
|
|
53
|
+
body: input.body,
|
|
54
|
+
replyToId: input.replyToId,
|
|
55
|
+
});
|
|
52
56
|
return { messageId: sent.messageId };
|
|
53
57
|
}
|
|
54
58
|
async editMessage(messageId, content) {
|
|
@@ -72,10 +76,58 @@ export class SdkChatControlPlane {
|
|
|
72
76
|
};
|
|
73
77
|
return this.me;
|
|
74
78
|
}
|
|
79
|
+
async listUsers() {
|
|
80
|
+
const users = await this.client.listUsers();
|
|
81
|
+
return users.map((user) => ({
|
|
82
|
+
id: user.id,
|
|
83
|
+
display_name: user.displayName,
|
|
84
|
+
kind: user.kind,
|
|
85
|
+
}));
|
|
86
|
+
}
|
|
87
|
+
async readChannelHistory(input) {
|
|
88
|
+
const messages = await this.client.readHistory({
|
|
89
|
+
channelId: input.channelId,
|
|
90
|
+
before: input.before,
|
|
91
|
+
after: input.after,
|
|
92
|
+
limit: input.limit,
|
|
93
|
+
});
|
|
94
|
+
return messages.map((message) => ({
|
|
95
|
+
id: message.id,
|
|
96
|
+
channelId: message.channelId,
|
|
97
|
+
authorId: message.authorId,
|
|
98
|
+
body: message.body,
|
|
99
|
+
contentType: message.contentType,
|
|
100
|
+
type: message.type,
|
|
101
|
+
replyToId: message.replyToId,
|
|
102
|
+
createdAt: message.createdAt,
|
|
103
|
+
editedAt: message.editedAt,
|
|
104
|
+
}));
|
|
105
|
+
}
|
|
106
|
+
async listChannels() {
|
|
107
|
+
const channels = await this.client.listChannels();
|
|
108
|
+
return channels.map((channel) => ({
|
|
109
|
+
id: channel.id,
|
|
110
|
+
name: channel.name,
|
|
111
|
+
kind: channel.kind,
|
|
112
|
+
}));
|
|
113
|
+
}
|
|
114
|
+
async createTask(input) {
|
|
115
|
+
return this.client.createTask(input);
|
|
116
|
+
}
|
|
117
|
+
async listTasks(input) {
|
|
118
|
+
return this.client.listTasks(input);
|
|
119
|
+
}
|
|
120
|
+
async getTask(input) {
|
|
121
|
+
return this.client.getTask(input);
|
|
122
|
+
}
|
|
123
|
+
async updateTask(input) {
|
|
124
|
+
return this.client.updateTask(input);
|
|
125
|
+
}
|
|
75
126
|
}
|
|
76
127
|
export function mapInboundToChannelMessage(event) {
|
|
77
128
|
return {
|
|
78
129
|
type: event.kind,
|
|
130
|
+
...(event.message?.type != null ? { message_type: event.message.type } : {}),
|
|
79
131
|
channel_id: event.channelId,
|
|
80
132
|
channel_type: event.channelType,
|
|
81
133
|
message_id: event.message?.id ?? event.messageId,
|
package/dist/cli-args.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Maps
|
|
3
|
-
* reads. Keeping this as a plain lookup table (rather than
|
|
4
|
-
* `loadConfigFromEnv`'s parsing logic) means the CLI and the
|
|
5
|
-
* point (`index.ts`) always agree on
|
|
2
|
+
* Maps `agents-host start` / `agents-host start-managed` agent flags to the env
|
|
3
|
+
* vars `config.ts` reads. Keeping this as a plain lookup table (rather than
|
|
4
|
+
* duplicating `loadConfigFromEnv`'s parsing logic) means the CLI and the
|
|
5
|
+
* standalone env-var entry point (`index.ts`) always agree on
|
|
6
|
+
* defaults/validation.
|
|
6
7
|
*/
|
|
7
8
|
export declare const CLI_FLAG_TO_ENV: Record<string, string>;
|
|
8
9
|
export type ParsedStartArgs = ParsedSingleAgentStartArgs | ParsedLocalConfigStartArgs;
|
|
@@ -10,11 +11,18 @@ export interface ParsedSingleAgentStartArgs {
|
|
|
10
11
|
mode: 'single-agent';
|
|
11
12
|
serverUrl: string;
|
|
12
13
|
apiKey: string;
|
|
14
|
+
debug: boolean;
|
|
15
|
+
env: Record<string, string>;
|
|
16
|
+
}
|
|
17
|
+
export interface ParsedManagedStartArgs {
|
|
18
|
+
serverUrl: string;
|
|
19
|
+
apiKey?: string;
|
|
13
20
|
env: Record<string, string>;
|
|
14
21
|
}
|
|
15
22
|
export interface ParsedLocalConfigStartArgs {
|
|
16
23
|
mode: 'local-config';
|
|
17
24
|
configPath: string;
|
|
25
|
+
debug: boolean;
|
|
18
26
|
}
|
|
19
27
|
export interface ParsedValidateArgs {
|
|
20
28
|
configPath: string;
|
|
@@ -35,11 +43,44 @@ export interface ParsedGenerateConfigFromStdinArgs {
|
|
|
35
43
|
input: 'stdin';
|
|
36
44
|
}
|
|
37
45
|
export type ParsedGenerateConfigArgs = ParsedGenerateConfigFromArgvArgs | ParsedGenerateConfigFromStdinArgs;
|
|
46
|
+
export interface ParsedDaemonArgs {
|
|
47
|
+
rootPath: string;
|
|
48
|
+
debug: boolean;
|
|
49
|
+
}
|
|
50
|
+
export interface ParsedLogArgs {
|
|
51
|
+
serverUrl: string;
|
|
52
|
+
lines: number;
|
|
53
|
+
follow: boolean;
|
|
54
|
+
pathOnly: boolean;
|
|
55
|
+
}
|
|
56
|
+
export interface ParsedDescribeManagedArgs {
|
|
57
|
+
serverUrl: string;
|
|
58
|
+
}
|
|
59
|
+
export interface ParsedCleanupManagedArgs {
|
|
60
|
+
serverUrl: string;
|
|
61
|
+
purge: boolean;
|
|
62
|
+
}
|
|
63
|
+
export interface ParsedApplyManagedFromArgvArgs {
|
|
64
|
+
serverUrl: string;
|
|
65
|
+
input: 'argv';
|
|
66
|
+
specJson: string;
|
|
67
|
+
}
|
|
68
|
+
export interface ParsedApplyManagedFromStdinArgs {
|
|
69
|
+
serverUrl: string;
|
|
70
|
+
input: 'stdin';
|
|
71
|
+
}
|
|
72
|
+
export type ParsedApplyManagedArgs = ParsedApplyManagedFromArgvArgs | ParsedApplyManagedFromStdinArgs;
|
|
38
73
|
export declare class CliUsageError extends Error {
|
|
39
74
|
}
|
|
40
75
|
export declare function parseStartArgs(argv: string[]): ParsedStartArgs;
|
|
76
|
+
export declare function parseManagedStartArgs(argv: string[]): ParsedManagedStartArgs;
|
|
41
77
|
export declare function parseValidateArgs(argv: string[]): ParsedValidateArgs;
|
|
42
78
|
export declare function parseDescribeArgs(argv: string[]): ParsedDescribeArgs;
|
|
43
79
|
export declare function parsePrintLayoutArgs(argv: string[]): ParsedPrintLayoutArgs;
|
|
44
80
|
export declare function parseGenerateConfigArgs(argv: string[]): ParsedGenerateConfigArgs;
|
|
45
|
-
export declare
|
|
81
|
+
export declare function parseDaemonArgs(argv: string[]): ParsedDaemonArgs;
|
|
82
|
+
export declare function parseLogArgs(argv: string[]): ParsedLogArgs;
|
|
83
|
+
export declare function parseDescribeManagedArgs(argv: string[]): ParsedDescribeManagedArgs;
|
|
84
|
+
export declare function parseCleanupManagedArgs(argv: string[]): ParsedCleanupManagedArgs;
|
|
85
|
+
export declare function parseApplyManagedArgs(argv: string[]): ParsedApplyManagedArgs;
|
|
86
|
+
export declare const USAGE = "Usage:\n agents-host start <serverUrl> <apiKey> [options]\n agents-host start-managed <serverUrl>\n agents-host start-managed <serverUrl> <apiKey> [agent-options]\n agents-host describe-managed <serverUrl>\n agents-host cleanup-managed <serverUrl> [--purge]\n agents-host apply-managed <serverUrl> --stdin\n agents-host apply-managed <serverUrl> --spec-json <json>\n agents-host log <serverUrl> [--lines <n>] [--follow]\n agents-host log <serverUrl> --path\n agents-host start --config <path-to-host-config> [--debug]\n agents-host validate --config <path-to-host-config>\n agents-host describe --config <path-to-host-config>\n agents-host print-layout --root <dir>\n agents-host generate-config --root <dir> --stdin\n agents-host generate-config --root <dir> --spec-json <json>\n\nForeground start options:\n --debug Enable host/provider debug logs (or set AGENTS_HOST_DEBUG=1)\n\nSingle-agent agent options:\n --name <name> Display name (default: Assistant)\n --provider <claude|codex|copilot>\n Runtime provider (default: claude)\n --claude-command <cmd> Local Claude CLI command (default: claude)\n --claude-args <args> Local Claude CLI args (default: --print --permission-mode bypassPermissions)\n --codex-command <cmd> Local Codex ACP adapter command (default: codex-acp)\n --codex-args <args> Local Codex ACP adapter args\n --copilot-command <cmd> Local Copilot CLI command (default: copilot)\n --copilot-args <args> Ignored by the Copilot ACP prototype\n --copilot-session-ttl-minutes <minutes>\n Idle session TTL for Copilot ACP sessions (default: 2880)\n\nCommand summary:\n start <serverUrl> <apiKey> Start one foreground hosted agent (legacy-compatible behavior)\n start --config <path> Start agents + supervisor + watchers from a host config file\n start-managed <serverUrl> Restart or resume an existing per-serverUrl managed daemon\n start-managed <serverUrl> <apiKey>\n Upsert one agent into the per-serverUrl local daemon and exit after reconcile\n describe-managed <serverUrl> Print managed-runtime spec JSON for machine callers\n cleanup-managed <serverUrl> Stop one managed-runtime daemon locally; --purge also removes its runtime root\n apply-managed <serverUrl> Apply one managed-runtime full-set spec for machine callers\n log <serverUrl> Print the managed daemon log tail for one server runtime\n validate --config <path> Validate local-config files without starting agents or watchers\n describe --config <path> Print the current managed full-set spec as JSON\n print-layout --root <dir> Print the canonical default local-config layout as JSON\n generate-config --root <dir> --stdin Materialize canonical local-config files from stdin\n generate-config --root <dir> --spec-json <json>\n Compatibility input; JSON is exposed in process arguments\n\nExamples:\n agents-host start https://borgee.example.com bgr_xxxxxxxx --provider copilot --debug\n agents-host start-managed https://borgee.example.com\n agents-host start-managed https://borgee.example.com bgr_xxxxxxxx --provider copilot\n agents-host describe-managed https://borgee.example.com\n agents-host cleanup-managed https://borgee.example.com --purge\n printf '%s' '{\"host\":{\"borgeeBaseUrl\":\"https://borgee.example.com\"},\"agents\":[{\"key\":\"cp1\",\"name\":\"Copilot\",\"apiKey\":\"bgr_xxx\",\"provider\":\"copilot\"}]}' | agents-host apply-managed https://borgee.example.com --stdin\n agents-host log https://borgee.example.com --lines 200 --follow\n agents-host log https://borgee.example.com --path\n agents-host start --config ./agents-host.yaml --debug\n agents-host validate --config ./agents-host.yaml\n agents-host describe --config ./agents-host.yaml\n agents-host print-layout --root ./runtime-root\n printf '%s' '{\"host\":{\"borgeeBaseUrl\":\"https://borgee.example.com\"},\"agents\":[{\"key\":\"cp1\",\"name\":\"Copilot\",\"apiKey\":\"bgr_xxx\",\"provider\":\"copilot\"}]}' | agents-host generate-config --root ./runtime-root --stdin\n";
|
package/dist/cli-args.js
CHANGED
|
@@ -1,26 +1,72 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Maps
|
|
3
|
-
* reads. Keeping this as a plain lookup table (rather than
|
|
4
|
-
* `loadConfigFromEnv`'s parsing logic) means the CLI and the
|
|
5
|
-
* point (`index.ts`) always agree on
|
|
2
|
+
* Maps `agents-host start` / `agents-host start-managed` agent flags to the env
|
|
3
|
+
* vars `config.ts` reads. Keeping this as a plain lookup table (rather than
|
|
4
|
+
* duplicating `loadConfigFromEnv`'s parsing logic) means the CLI and the
|
|
5
|
+
* standalone env-var entry point (`index.ts`) always agree on
|
|
6
|
+
* defaults/validation.
|
|
6
7
|
*/
|
|
7
8
|
export const CLI_FLAG_TO_ENV = {
|
|
8
9
|
name: 'BORGEE_AGENT_NAME',
|
|
9
10
|
provider: 'RUNTIME_PROVIDER',
|
|
10
11
|
'claude-command': 'CLAUDE_COMMAND',
|
|
11
12
|
'claude-args': 'CLAUDE_ARGS',
|
|
13
|
+
'codex-command': 'CODEX_COMMAND',
|
|
14
|
+
'codex-args': 'CODEX_ARGS',
|
|
12
15
|
'copilot-command': 'COPILOT_COMMAND',
|
|
13
16
|
'copilot-args': 'COPILOT_ARGS',
|
|
14
17
|
'copilot-session-ttl-minutes': 'COPILOT_SESSION_TTL_MINUTES',
|
|
15
18
|
};
|
|
16
19
|
const SINGLE_AGENT_FLAG_NAMES = new Set(Object.keys(CLI_FLAG_TO_ENV));
|
|
20
|
+
const FLAGS_ALLOWING_DASH_PREFIX_VALUE = new Set(['claude-args', 'codex-args', 'copilot-args']);
|
|
17
21
|
export class CliUsageError extends Error {
|
|
18
22
|
}
|
|
23
|
+
function parseSingleAgentPositionals(positionals) {
|
|
24
|
+
const [serverUrl, apiKey, ...extra] = positionals;
|
|
25
|
+
if (!serverUrl) {
|
|
26
|
+
throw new CliUsageError('Missing <serverUrl>');
|
|
27
|
+
}
|
|
28
|
+
if (!apiKey) {
|
|
29
|
+
throw new CliUsageError('Missing <apiKey>');
|
|
30
|
+
}
|
|
31
|
+
if (extra.length > 0) {
|
|
32
|
+
throw new CliUsageError(`Unexpected argument: ${extra[0]}`);
|
|
33
|
+
}
|
|
34
|
+
return { serverUrl, apiKey };
|
|
35
|
+
}
|
|
36
|
+
function readSingleAgentFlagValue(argv, index, flag) {
|
|
37
|
+
const value = argv[index + 1];
|
|
38
|
+
if (value === undefined ||
|
|
39
|
+
(value.startsWith('--') && !FLAGS_ALLOWING_DASH_PREFIX_VALUE.has(flag))) {
|
|
40
|
+
throw new CliUsageError(`Missing value for --${flag}`);
|
|
41
|
+
}
|
|
42
|
+
return value;
|
|
43
|
+
}
|
|
44
|
+
function applySingleAgentFlag(argv, index, env, seenSingleAgentFlags) {
|
|
45
|
+
const flag = argv[index]?.slice(2) ?? '';
|
|
46
|
+
const envKey = CLI_FLAG_TO_ENV[flag];
|
|
47
|
+
if (!envKey) {
|
|
48
|
+
throw new CliUsageError(`Unknown option: --${flag}`);
|
|
49
|
+
}
|
|
50
|
+
env[envKey] = readSingleAgentFlagValue(argv, index, flag);
|
|
51
|
+
seenSingleAgentFlags.add(flag);
|
|
52
|
+
return index + 1;
|
|
53
|
+
}
|
|
54
|
+
function parseNonNegativeInteger(value, flag) {
|
|
55
|
+
if (!/^\d+$/u.test(value)) {
|
|
56
|
+
throw new CliUsageError(`--${flag} must be a non-negative integer`);
|
|
57
|
+
}
|
|
58
|
+
const parsed = Number.parseInt(value, 10);
|
|
59
|
+
if (!Number.isSafeInteger(parsed)) {
|
|
60
|
+
throw new CliUsageError(`--${flag} must be a non-negative integer`);
|
|
61
|
+
}
|
|
62
|
+
return parsed;
|
|
63
|
+
}
|
|
19
64
|
export function parseStartArgs(argv) {
|
|
20
65
|
const positionals = [];
|
|
21
66
|
const env = {};
|
|
22
67
|
const seenSingleAgentFlags = new Set();
|
|
23
68
|
let configPath;
|
|
69
|
+
let debug = false;
|
|
24
70
|
for (let i = 0; i < argv.length; i++) {
|
|
25
71
|
const arg = argv[i];
|
|
26
72
|
if (!arg.startsWith('--')) {
|
|
@@ -28,25 +74,22 @@ export function parseStartArgs(argv) {
|
|
|
28
74
|
continue;
|
|
29
75
|
}
|
|
30
76
|
const flag = arg.slice(2);
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
77
|
+
if (flag === 'debug') {
|
|
78
|
+
if (debug) {
|
|
79
|
+
throw new CliUsageError('--debug may only be specified once');
|
|
80
|
+
}
|
|
81
|
+
debug = true;
|
|
82
|
+
continue;
|
|
34
83
|
}
|
|
35
84
|
if (flag === 'config') {
|
|
36
85
|
if (configPath !== undefined) {
|
|
37
86
|
throw new CliUsageError('--config may only be specified once');
|
|
38
87
|
}
|
|
39
|
-
configPath =
|
|
88
|
+
configPath = readSingleAgentFlagValue(argv, i, flag);
|
|
40
89
|
i++;
|
|
41
90
|
continue;
|
|
42
91
|
}
|
|
43
|
-
|
|
44
|
-
if (!envKey) {
|
|
45
|
-
throw new CliUsageError(`Unknown option: --${flag}`);
|
|
46
|
-
}
|
|
47
|
-
env[envKey] = value;
|
|
48
|
-
seenSingleAgentFlags.add(flag);
|
|
49
|
-
i++;
|
|
92
|
+
i = applySingleAgentFlag(argv, i, env, seenSingleAgentFlags);
|
|
50
93
|
}
|
|
51
94
|
if (configPath !== undefined) {
|
|
52
95
|
if (positionals.length > 0) {
|
|
@@ -58,25 +101,49 @@ export function parseStartArgs(argv) {
|
|
|
58
101
|
return {
|
|
59
102
|
mode: 'local-config',
|
|
60
103
|
configPath,
|
|
104
|
+
debug,
|
|
61
105
|
};
|
|
62
106
|
}
|
|
63
|
-
const
|
|
64
|
-
if (!serverUrl) {
|
|
65
|
-
throw new CliUsageError('Missing <serverUrl>');
|
|
66
|
-
}
|
|
67
|
-
if (!apiKey) {
|
|
68
|
-
throw new CliUsageError('Missing <apiKey>');
|
|
69
|
-
}
|
|
70
|
-
if (extra.length > 0) {
|
|
71
|
-
throw new CliUsageError(`Unexpected argument: ${extra[0]}`);
|
|
72
|
-
}
|
|
107
|
+
const { serverUrl, apiKey } = parseSingleAgentPositionals(positionals);
|
|
73
108
|
return {
|
|
74
109
|
mode: 'single-agent',
|
|
75
110
|
serverUrl,
|
|
76
111
|
apiKey,
|
|
112
|
+
debug,
|
|
77
113
|
env,
|
|
78
114
|
};
|
|
79
115
|
}
|
|
116
|
+
export function parseManagedStartArgs(argv) {
|
|
117
|
+
const positionals = [];
|
|
118
|
+
const env = {};
|
|
119
|
+
const seenSingleAgentFlags = new Set();
|
|
120
|
+
for (let i = 0; i < argv.length; i++) {
|
|
121
|
+
const arg = argv[i];
|
|
122
|
+
if (!arg.startsWith('--')) {
|
|
123
|
+
positionals.push(arg);
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
const flag = arg.slice(2);
|
|
127
|
+
if (flag === 'debug') {
|
|
128
|
+
throw new CliUsageError('start-managed does not support --debug; use foreground start for debug logging');
|
|
129
|
+
}
|
|
130
|
+
if (flag === 'config') {
|
|
131
|
+
throw new CliUsageError('start-managed does not support --config');
|
|
132
|
+
}
|
|
133
|
+
i = applySingleAgentFlag(argv, i, env, seenSingleAgentFlags);
|
|
134
|
+
}
|
|
135
|
+
if (positionals.length === 1) {
|
|
136
|
+
if (seenSingleAgentFlags.size > 0) {
|
|
137
|
+
throw new CliUsageError(`Cannot combine bare start-managed <serverUrl> resume with agent option --${[...seenSingleAgentFlags][0]}; provide <apiKey> to bootstrap or update an agent`);
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
serverUrl: positionals[0],
|
|
141
|
+
env,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
const { serverUrl, apiKey } = parseSingleAgentPositionals(positionals);
|
|
145
|
+
return { serverUrl, apiKey, env };
|
|
146
|
+
}
|
|
80
147
|
export function parseValidateArgs(argv) {
|
|
81
148
|
const positionals = [];
|
|
82
149
|
let configPath;
|
|
@@ -218,27 +285,234 @@ export function parseGenerateConfigArgs(argv) {
|
|
|
218
285
|
}
|
|
219
286
|
return { rootPath, input: 'argv', specJson };
|
|
220
287
|
}
|
|
288
|
+
export function parseDaemonArgs(argv) {
|
|
289
|
+
const positionals = [];
|
|
290
|
+
let rootPath;
|
|
291
|
+
let debug = false;
|
|
292
|
+
for (let i = 0; i < argv.length; i++) {
|
|
293
|
+
const arg = argv[i];
|
|
294
|
+
if (!arg.startsWith('--')) {
|
|
295
|
+
positionals.push(arg);
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
const flag = arg.slice(2);
|
|
299
|
+
if (flag === 'debug') {
|
|
300
|
+
if (debug) {
|
|
301
|
+
throw new CliUsageError('--debug may only be specified once');
|
|
302
|
+
}
|
|
303
|
+
debug = true;
|
|
304
|
+
continue;
|
|
305
|
+
}
|
|
306
|
+
if (flag === 'root') {
|
|
307
|
+
const value = argv[i + 1];
|
|
308
|
+
if (value === undefined || value.startsWith('--')) {
|
|
309
|
+
throw new CliUsageError('Missing value for --root');
|
|
310
|
+
}
|
|
311
|
+
if (rootPath !== undefined) {
|
|
312
|
+
throw new CliUsageError('--root may only be specified once');
|
|
313
|
+
}
|
|
314
|
+
rootPath = value;
|
|
315
|
+
i++;
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
throw new CliUsageError(`Unknown option: --${flag}`);
|
|
319
|
+
}
|
|
320
|
+
if (positionals.length > 0) {
|
|
321
|
+
throw new CliUsageError(`Unexpected argument: ${positionals[0]}`);
|
|
322
|
+
}
|
|
323
|
+
if (!rootPath) {
|
|
324
|
+
throw new CliUsageError('Missing required --root <dir>');
|
|
325
|
+
}
|
|
326
|
+
return { rootPath, debug };
|
|
327
|
+
}
|
|
328
|
+
export function parseLogArgs(argv) {
|
|
329
|
+
const positionals = [];
|
|
330
|
+
let lines = 100;
|
|
331
|
+
let follow = false;
|
|
332
|
+
let pathOnly = false;
|
|
333
|
+
let linesSpecified = false;
|
|
334
|
+
for (let i = 0; i < argv.length; i++) {
|
|
335
|
+
const arg = argv[i];
|
|
336
|
+
if (!arg.startsWith('--')) {
|
|
337
|
+
positionals.push(arg);
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
const flag = arg.slice(2);
|
|
341
|
+
if (flag === 'follow') {
|
|
342
|
+
if (follow) {
|
|
343
|
+
throw new CliUsageError('--follow may only be specified once');
|
|
344
|
+
}
|
|
345
|
+
follow = true;
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
if (flag === 'path') {
|
|
349
|
+
if (pathOnly) {
|
|
350
|
+
throw new CliUsageError('--path may only be specified once');
|
|
351
|
+
}
|
|
352
|
+
pathOnly = true;
|
|
353
|
+
continue;
|
|
354
|
+
}
|
|
355
|
+
if (flag === 'lines') {
|
|
356
|
+
if (linesSpecified) {
|
|
357
|
+
throw new CliUsageError('--lines may only be specified once');
|
|
358
|
+
}
|
|
359
|
+
const value = argv[i + 1];
|
|
360
|
+
if (value === undefined || value.startsWith('--')) {
|
|
361
|
+
throw new CliUsageError('Missing value for --lines');
|
|
362
|
+
}
|
|
363
|
+
lines = parseNonNegativeInteger(value, 'lines');
|
|
364
|
+
linesSpecified = true;
|
|
365
|
+
i++;
|
|
366
|
+
continue;
|
|
367
|
+
}
|
|
368
|
+
throw new CliUsageError(`Unknown option: --${flag}`);
|
|
369
|
+
}
|
|
370
|
+
const [serverUrl, ...extra] = positionals;
|
|
371
|
+
if (!serverUrl) {
|
|
372
|
+
throw new CliUsageError('Missing <serverUrl>');
|
|
373
|
+
}
|
|
374
|
+
if (extra.length > 0) {
|
|
375
|
+
throw new CliUsageError(`Unexpected argument: ${extra[0]}`);
|
|
376
|
+
}
|
|
377
|
+
if (pathOnly && (follow || linesSpecified)) {
|
|
378
|
+
throw new CliUsageError('--path cannot be combined with --follow or --lines');
|
|
379
|
+
}
|
|
380
|
+
return { serverUrl, lines, follow, pathOnly };
|
|
381
|
+
}
|
|
382
|
+
export function parseDescribeManagedArgs(argv) {
|
|
383
|
+
const [serverUrl, ...extra] = argv;
|
|
384
|
+
if (!serverUrl) {
|
|
385
|
+
throw new CliUsageError('Missing <serverUrl>');
|
|
386
|
+
}
|
|
387
|
+
if (serverUrl.startsWith('--')) {
|
|
388
|
+
throw new CliUsageError(`Unknown option: ${serverUrl}`);
|
|
389
|
+
}
|
|
390
|
+
if (extra.length > 0) {
|
|
391
|
+
throw new CliUsageError(`Unexpected argument: ${extra[0]}`);
|
|
392
|
+
}
|
|
393
|
+
return { serverUrl };
|
|
394
|
+
}
|
|
395
|
+
export function parseCleanupManagedArgs(argv) {
|
|
396
|
+
const positionals = [];
|
|
397
|
+
let purge = false;
|
|
398
|
+
for (let i = 0; i < argv.length; i++) {
|
|
399
|
+
const arg = argv[i];
|
|
400
|
+
if (!arg.startsWith('--')) {
|
|
401
|
+
positionals.push(arg);
|
|
402
|
+
continue;
|
|
403
|
+
}
|
|
404
|
+
const flag = arg.slice(2);
|
|
405
|
+
if (flag === 'purge') {
|
|
406
|
+
if (purge) {
|
|
407
|
+
throw new CliUsageError('--purge may only be specified once');
|
|
408
|
+
}
|
|
409
|
+
purge = true;
|
|
410
|
+
continue;
|
|
411
|
+
}
|
|
412
|
+
throw new CliUsageError(`Unknown option: --${flag}`);
|
|
413
|
+
}
|
|
414
|
+
const [serverUrl, ...extra] = positionals;
|
|
415
|
+
if (!serverUrl) {
|
|
416
|
+
throw new CliUsageError('Missing <serverUrl>');
|
|
417
|
+
}
|
|
418
|
+
if (extra.length > 0) {
|
|
419
|
+
throw new CliUsageError(`Unexpected argument: ${extra[0]}`);
|
|
420
|
+
}
|
|
421
|
+
return { serverUrl, purge };
|
|
422
|
+
}
|
|
423
|
+
export function parseApplyManagedArgs(argv) {
|
|
424
|
+
const positionals = [];
|
|
425
|
+
let specJson;
|
|
426
|
+
let stdin = false;
|
|
427
|
+
for (let i = 0; i < argv.length; i++) {
|
|
428
|
+
const arg = argv[i];
|
|
429
|
+
if (!arg.startsWith('--')) {
|
|
430
|
+
positionals.push(arg);
|
|
431
|
+
continue;
|
|
432
|
+
}
|
|
433
|
+
const flag = arg.slice(2);
|
|
434
|
+
if (flag === 'stdin') {
|
|
435
|
+
if (stdin) {
|
|
436
|
+
throw new CliUsageError('--stdin may only be specified once');
|
|
437
|
+
}
|
|
438
|
+
stdin = true;
|
|
439
|
+
continue;
|
|
440
|
+
}
|
|
441
|
+
if (flag === 'spec-json') {
|
|
442
|
+
const value = argv[i + 1];
|
|
443
|
+
if (value === undefined || value.startsWith('--')) {
|
|
444
|
+
throw new CliUsageError('Missing value for --spec-json');
|
|
445
|
+
}
|
|
446
|
+
if (specJson !== undefined) {
|
|
447
|
+
throw new CliUsageError('--spec-json may only be specified once');
|
|
448
|
+
}
|
|
449
|
+
specJson = value;
|
|
450
|
+
i++;
|
|
451
|
+
continue;
|
|
452
|
+
}
|
|
453
|
+
throw new CliUsageError(`Unknown option: --${flag}`);
|
|
454
|
+
}
|
|
455
|
+
const [serverUrl, ...extra] = positionals;
|
|
456
|
+
if (!serverUrl) {
|
|
457
|
+
throw new CliUsageError('Missing <serverUrl>');
|
|
458
|
+
}
|
|
459
|
+
if (extra.length > 0) {
|
|
460
|
+
throw new CliUsageError(`Unexpected argument: ${extra[0]}`);
|
|
461
|
+
}
|
|
462
|
+
if (stdin && specJson !== undefined) {
|
|
463
|
+
throw new CliUsageError('apply-managed accepts exactly one input source: --stdin or --spec-json');
|
|
464
|
+
}
|
|
465
|
+
if (stdin) {
|
|
466
|
+
return { serverUrl, input: 'stdin' };
|
|
467
|
+
}
|
|
468
|
+
if (!specJson) {
|
|
469
|
+
throw new CliUsageError('Missing required input: use --stdin or --spec-json <json>');
|
|
470
|
+
}
|
|
471
|
+
return { serverUrl, input: 'argv', specJson };
|
|
472
|
+
}
|
|
221
473
|
export const USAGE = `Usage:
|
|
222
474
|
agents-host start <serverUrl> <apiKey> [options]
|
|
223
|
-
agents-host start
|
|
475
|
+
agents-host start-managed <serverUrl>
|
|
476
|
+
agents-host start-managed <serverUrl> <apiKey> [agent-options]
|
|
477
|
+
agents-host describe-managed <serverUrl>
|
|
478
|
+
agents-host cleanup-managed <serverUrl> [--purge]
|
|
479
|
+
agents-host apply-managed <serverUrl> --stdin
|
|
480
|
+
agents-host apply-managed <serverUrl> --spec-json <json>
|
|
481
|
+
agents-host log <serverUrl> [--lines <n>] [--follow]
|
|
482
|
+
agents-host log <serverUrl> --path
|
|
483
|
+
agents-host start --config <path-to-host-config> [--debug]
|
|
224
484
|
agents-host validate --config <path-to-host-config>
|
|
225
485
|
agents-host describe --config <path-to-host-config>
|
|
226
486
|
agents-host print-layout --root <dir>
|
|
227
487
|
agents-host generate-config --root <dir> --stdin
|
|
228
488
|
agents-host generate-config --root <dir> --spec-json <json>
|
|
229
489
|
|
|
230
|
-
|
|
490
|
+
Foreground start options:
|
|
491
|
+
--debug Enable host/provider debug logs (or set AGENTS_HOST_DEBUG=1)
|
|
492
|
+
|
|
493
|
+
Single-agent agent options:
|
|
231
494
|
--name <name> Display name (default: Assistant)
|
|
232
|
-
--provider <claude|copilot>
|
|
495
|
+
--provider <claude|codex|copilot>
|
|
496
|
+
Runtime provider (default: claude)
|
|
233
497
|
--claude-command <cmd> Local Claude CLI command (default: claude)
|
|
234
|
-
--claude-args <args> Local Claude CLI args (default: --print)
|
|
498
|
+
--claude-args <args> Local Claude CLI args (default: --print --permission-mode bypassPermissions)
|
|
499
|
+
--codex-command <cmd> Local Codex ACP adapter command (default: codex-acp)
|
|
500
|
+
--codex-args <args> Local Codex ACP adapter args
|
|
235
501
|
--copilot-command <cmd> Local Copilot CLI command (default: copilot)
|
|
236
502
|
--copilot-args <args> Ignored by the Copilot ACP prototype
|
|
237
503
|
--copilot-session-ttl-minutes <minutes>
|
|
238
504
|
Idle session TTL for Copilot ACP sessions (default: 2880)
|
|
239
505
|
|
|
240
|
-
|
|
506
|
+
Command summary:
|
|
507
|
+
start <serverUrl> <apiKey> Start one foreground hosted agent (legacy-compatible behavior)
|
|
241
508
|
start --config <path> Start agents + supervisor + watchers from a host config file
|
|
509
|
+
start-managed <serverUrl> Restart or resume an existing per-serverUrl managed daemon
|
|
510
|
+
start-managed <serverUrl> <apiKey>
|
|
511
|
+
Upsert one agent into the per-serverUrl local daemon and exit after reconcile
|
|
512
|
+
describe-managed <serverUrl> Print managed-runtime spec JSON for machine callers
|
|
513
|
+
cleanup-managed <serverUrl> Stop one managed-runtime daemon locally; --purge also removes its runtime root
|
|
514
|
+
apply-managed <serverUrl> Apply one managed-runtime full-set spec for machine callers
|
|
515
|
+
log <serverUrl> Print the managed daemon log tail for one server runtime
|
|
242
516
|
validate --config <path> Validate local-config files without starting agents or watchers
|
|
243
517
|
describe --config <path> Print the current managed full-set spec as JSON
|
|
244
518
|
print-layout --root <dir> Print the canonical default local-config layout as JSON
|
|
@@ -247,8 +521,15 @@ Local-config mode:
|
|
|
247
521
|
Compatibility input; JSON is exposed in process arguments
|
|
248
522
|
|
|
249
523
|
Examples:
|
|
250
|
-
agents-host start https://borgee.example.com bgr_xxxxxxxx --provider copilot
|
|
251
|
-
agents-host start
|
|
524
|
+
agents-host start https://borgee.example.com bgr_xxxxxxxx --provider copilot --debug
|
|
525
|
+
agents-host start-managed https://borgee.example.com
|
|
526
|
+
agents-host start-managed https://borgee.example.com bgr_xxxxxxxx --provider copilot
|
|
527
|
+
agents-host describe-managed https://borgee.example.com
|
|
528
|
+
agents-host cleanup-managed https://borgee.example.com --purge
|
|
529
|
+
printf '%s' '{"host":{"borgeeBaseUrl":"https://borgee.example.com"},"agents":[{"key":"cp1","name":"Copilot","apiKey":"bgr_xxx","provider":"copilot"}]}' | agents-host apply-managed https://borgee.example.com --stdin
|
|
530
|
+
agents-host log https://borgee.example.com --lines 200 --follow
|
|
531
|
+
agents-host log https://borgee.example.com --path
|
|
532
|
+
agents-host start --config ./agents-host.yaml --debug
|
|
252
533
|
agents-host validate --config ./agents-host.yaml
|
|
253
534
|
agents-host describe --config ./agents-host.yaml
|
|
254
535
|
agents-host print-layout --root ./runtime-root
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { applyManagedSpec, bootstrapManagedDaemonStart, cleanupManagedRuntime, describeManagedSpec } from './managed-daemon.js';
|
|
3
|
+
import { runManagedDaemonLogCommand } from './managed-daemon-log.js';
|
|
2
4
|
import { describeLocalConfig, generateLocalConfig, printLocalConfigLayout, runMain, validateLocalConfig } from './run.js';
|
|
3
5
|
export interface CliDeps {
|
|
4
6
|
env?: NodeJS.ProcessEnv;
|
|
5
7
|
logger?: Pick<Console, 'error'>;
|
|
6
8
|
runMain?: typeof runMain;
|
|
9
|
+
bootstrapManagedDaemonStart?: typeof bootstrapManagedDaemonStart;
|
|
10
|
+
startManagedDaemon?: (rootPath: string, debug: boolean) => Promise<void>;
|
|
7
11
|
validateLocalConfig?: typeof validateLocalConfig;
|
|
8
12
|
describeLocalConfig?: typeof describeLocalConfig;
|
|
9
13
|
printLocalConfigLayout?: typeof printLocalConfigLayout;
|
|
10
14
|
generateLocalConfig?: typeof generateLocalConfig;
|
|
11
15
|
readStdin?: () => Promise<string>;
|
|
16
|
+
runManagedDaemonLogCommand?: typeof runManagedDaemonLogCommand;
|
|
17
|
+
describeManagedSpec?: typeof describeManagedSpec;
|
|
18
|
+
cleanupManagedRuntime?: typeof cleanupManagedRuntime;
|
|
19
|
+
applyManagedSpec?: typeof applyManagedSpec;
|
|
20
|
+
stdout?: Pick<Console, 'log'>;
|
|
12
21
|
}
|
|
13
22
|
interface CliEntrypointDeps {
|
|
14
23
|
realpath?: (path: string) => string;
|