@borgee/agents-host 0.2.2 → 0.2.28
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 +114 -15
- package/dist/agents-host.js +2712 -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 +39 -0
- package/dist/compatibility-gates.js +131 -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/attention.d.ts +12 -0
- package/dist/context/attention.js +137 -0
- package/dist/context/collaboration-capabilities-diagnostics.d.ts +3 -0
- package/dist/context/collaboration-capabilities-diagnostics.js +18 -0
- package/dist/context/collaboration-outcome.d.ts +2 -0
- package/dist/context/collaboration-outcome.js +26 -0
- package/dist/context/injection.d.ts +134 -0
- package/dist/context/injection.js +355 -0
- package/dist/context/prompt.d.ts +4 -1
- package/dist/context/prompt.js +231 -1
- package/dist/context/task-thread-collaboration.d.ts +6 -0
- package/dist/context/task-thread-collaboration.js +31 -0
- package/dist/context/turn-preparation.d.ts +9 -0
- package/dist/context/turn-preparation.js +135 -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 +192 -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 +90 -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 +14 -1
- package/dist/state-paths.js +87 -3
- package/dist/task-thread-resolution.d.ts +10 -0
- package/dist/task-thread-resolution.js +48 -0
- package/dist/types.d.ts +267 -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
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
export const HOST_CONTROL_PREFIX = '[[BORGEE_CONTROL]] ';
|
|
2
|
+
export const AWAITING_USER_CONTROL_PREFIX = HOST_CONTROL_PREFIX;
|
|
3
|
+
const VALID_ATTENTION_UPDATES = new Set([
|
|
4
|
+
'follow-channel',
|
|
5
|
+
'unfollow-channel',
|
|
6
|
+
'mute-channel',
|
|
7
|
+
'claim-channel',
|
|
8
|
+
'claim-task-thread',
|
|
9
|
+
'unclaim-channel',
|
|
10
|
+
'unclaim-task-thread',
|
|
11
|
+
]);
|
|
12
|
+
function isProviderAttentionUpdate(value) {
|
|
13
|
+
return typeof value === 'string' && VALID_ATTENTION_UPDATES.has(value);
|
|
14
|
+
}
|
|
15
|
+
function hasVisibleText(value) {
|
|
16
|
+
return value.trim().length > 0;
|
|
17
|
+
}
|
|
18
|
+
function stripTrailingCarriageReturn(value) {
|
|
19
|
+
return value.endsWith('\r') ? value.slice(0, -1) : value;
|
|
20
|
+
}
|
|
21
|
+
function matchControlLine(sourceText, trimTrailingWhitespace) {
|
|
22
|
+
const analyzedText = trimTrailingWhitespace
|
|
23
|
+
? sourceText.replace(/[ \t\r\n]+$/u, '')
|
|
24
|
+
: sourceText;
|
|
25
|
+
const lastNewline = analyzedText.lastIndexOf('\n');
|
|
26
|
+
const lineStart = lastNewline === -1 ? 0 : lastNewline + 1;
|
|
27
|
+
const line = stripTrailingCarriageReturn(analyzedText.slice(lineStart));
|
|
28
|
+
const removalStart = lastNewline === -1 ? 0 : lastNewline;
|
|
29
|
+
if (line.startsWith(HOST_CONTROL_PREFIX)) {
|
|
30
|
+
return {
|
|
31
|
+
kind: 'footer',
|
|
32
|
+
analyzedText,
|
|
33
|
+
removalStart,
|
|
34
|
+
payload: line.slice(HOST_CONTROL_PREFIX.length),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
if (line.length > 0 && HOST_CONTROL_PREFIX.startsWith(line)) {
|
|
38
|
+
return {
|
|
39
|
+
kind: 'plausible-prefix',
|
|
40
|
+
analyzedText,
|
|
41
|
+
removalStart,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
kind: 'none',
|
|
46
|
+
analyzedText,
|
|
47
|
+
removalStart,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function parseControlPayload(payload) {
|
|
51
|
+
let parsed;
|
|
52
|
+
try {
|
|
53
|
+
parsed = JSON.parse(payload);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
const record = parsed;
|
|
62
|
+
if (typeof record.kind !== 'string') {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
const attentionUpdate = (() => {
|
|
66
|
+
if (record.attentionUpdate === undefined) {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
return isProviderAttentionUpdate(record.attentionUpdate) ? record.attentionUpdate : null;
|
|
70
|
+
})();
|
|
71
|
+
if (attentionUpdate === null) {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
if (record.kind === 'continue-to-peer' || record.kind === 'conclude-locally') {
|
|
75
|
+
return Object.keys(record).every((key) => key === 'kind' || key === 'attentionUpdate')
|
|
76
|
+
? {
|
|
77
|
+
kind: record.kind,
|
|
78
|
+
...(attentionUpdate ? { attentionUpdate } : {}),
|
|
79
|
+
}
|
|
80
|
+
: null;
|
|
81
|
+
}
|
|
82
|
+
if (record.kind === 'start-protocol') {
|
|
83
|
+
return attentionUpdate === undefined
|
|
84
|
+
&& Object.keys(record).length === 2
|
|
85
|
+
&& typeof record.rounds === 'number'
|
|
86
|
+
&& Number.isInteger(record.rounds)
|
|
87
|
+
&& record.rounds > 0
|
|
88
|
+
? {
|
|
89
|
+
kind: 'start-protocol',
|
|
90
|
+
rounds: record.rounds,
|
|
91
|
+
}
|
|
92
|
+
: null;
|
|
93
|
+
}
|
|
94
|
+
if (record.kind === 'awaiting-user') {
|
|
95
|
+
const keys = Object.keys(record);
|
|
96
|
+
if (keys.some((key) => key !== 'kind' && key !== 'question' && key !== 'reason' && key !== 'attentionUpdate')) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
if (typeof record.question !== 'string' || record.question.trim().length === 0) {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
if (record.reason !== undefined
|
|
103
|
+
&& (typeof record.reason !== 'string' || record.reason.trim().length === 0)) {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
kind: 'awaiting-user',
|
|
108
|
+
question: record.question.trim(),
|
|
109
|
+
...(typeof record.reason === 'string' ? { reason: record.reason.trim() } : {}),
|
|
110
|
+
...(attentionUpdate ? { attentionUpdate } : {}),
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
if (record.kind === 'attention-only') {
|
|
114
|
+
return Object.keys(record).length === 2 && attentionUpdate
|
|
115
|
+
? {
|
|
116
|
+
kind: 'attention-only',
|
|
117
|
+
attentionUpdate,
|
|
118
|
+
}
|
|
119
|
+
: null;
|
|
120
|
+
}
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
export function parseProviderReply(text) {
|
|
124
|
+
const match = matchControlLine(text, true);
|
|
125
|
+
if (match.kind !== 'footer' || match.payload === undefined) {
|
|
126
|
+
return { text };
|
|
127
|
+
}
|
|
128
|
+
const control = parseControlPayload(match.payload);
|
|
129
|
+
if (!control) {
|
|
130
|
+
return {
|
|
131
|
+
text: stripTrailingCarriageReturn(match.analyzedText.slice(0, match.removalStart)),
|
|
132
|
+
controlMalformed: true,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
const textWithoutFooter = stripTrailingCarriageReturn(match.analyzedText.slice(0, match.removalStart));
|
|
136
|
+
if (control.kind === 'attention-only' && !hasVisibleText(textWithoutFooter)) {
|
|
137
|
+
return {
|
|
138
|
+
text: textWithoutFooter,
|
|
139
|
+
controlMalformed: true,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
text: textWithoutFooter,
|
|
144
|
+
control,
|
|
145
|
+
...(control.kind === 'awaiting-user'
|
|
146
|
+
? {
|
|
147
|
+
awaitingUser: {
|
|
148
|
+
question: control.question,
|
|
149
|
+
...(control.reason ? { reason: control.reason } : {}),
|
|
150
|
+
},
|
|
151
|
+
}
|
|
152
|
+
: {}),
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
export function sanitizeAwaitingUserProgressText(text) {
|
|
156
|
+
const match = matchControlLine(text, true);
|
|
157
|
+
if (match.kind !== 'none') {
|
|
158
|
+
return stripTrailingCarriageReturn(match.analyzedText.slice(0, match.removalStart));
|
|
159
|
+
}
|
|
160
|
+
const rawMatch = matchControlLine(text, false);
|
|
161
|
+
if (rawMatch.kind === 'none') {
|
|
162
|
+
return text;
|
|
163
|
+
}
|
|
164
|
+
return stripTrailingCarriageReturn(rawMatch.analyzedText.slice(0, rawMatch.removalStart));
|
|
165
|
+
}
|
|
166
|
+
export class AwaitingUserProgressSanitizer {
|
|
167
|
+
onProgress;
|
|
168
|
+
lastPublished = null;
|
|
169
|
+
constructor(onProgress) {
|
|
170
|
+
this.onProgress = onProgress;
|
|
171
|
+
}
|
|
172
|
+
publish(text) {
|
|
173
|
+
if (!this.onProgress) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
const sanitizedText = sanitizeAwaitingUserProgressText(text);
|
|
177
|
+
if (!hasVisibleText(sanitizedText) || sanitizedText === this.lastPublished) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
this.lastPublished = sanitizedText;
|
|
181
|
+
this.onProgress({ text: sanitizedText });
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
export function createAwaitingUserProgressHandler(onProgress) {
|
|
185
|
+
if (!onProgress) {
|
|
186
|
+
return undefined;
|
|
187
|
+
}
|
|
188
|
+
const sanitizer = new AwaitingUserProgressSanitizer(onProgress);
|
|
189
|
+
return (update) => {
|
|
190
|
+
sanitizer.publish(update.text);
|
|
191
|
+
};
|
|
192
|
+
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { ProviderAdapter } from '../provider-adapter.js';
|
|
2
2
|
import type { ProviderGenerateOptions, ProviderInput, ProviderReply } from '../../types.js';
|
|
3
|
+
import { ProviderTurnPreparer } from '../../context/turn-preparation.js';
|
|
3
4
|
import { ClaudeCliClient } from './cli-client.js';
|
|
4
5
|
export declare class ClaudeProviderAdapter implements ProviderAdapter {
|
|
5
6
|
private readonly cli;
|
|
6
|
-
|
|
7
|
+
private readonly turnPreparer;
|
|
8
|
+
constructor(cli: ClaudeCliClient, turnPreparer: ProviderTurnPreparer);
|
|
7
9
|
generateReply(input: ProviderInput, options?: ProviderGenerateOptions): Promise<ProviderReply>;
|
|
8
10
|
dispose(): Promise<void>;
|
|
9
11
|
}
|
|
@@ -1,21 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createAwaitingUserProgressHandler, parseProviderReply } from '../awaiting-user.js';
|
|
2
2
|
export class ClaudeProviderAdapter {
|
|
3
3
|
cli;
|
|
4
|
-
|
|
4
|
+
turnPreparer;
|
|
5
|
+
constructor(cli, turnPreparer) {
|
|
5
6
|
this.cli = cli;
|
|
7
|
+
this.turnPreparer = turnPreparer;
|
|
6
8
|
}
|
|
7
9
|
async generateReply(input, options) {
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
channelId: input.channelId,
|
|
12
|
-
incomingAuthorId: input.incomingAuthorId,
|
|
13
|
-
incomingContent: input.incomingContent,
|
|
10
|
+
const preparedTurn = await this.turnPreparer.prepare(input);
|
|
11
|
+
const text = await this.cli.generateReply(preparedTurn, {
|
|
12
|
+
onProgress: createAwaitingUserProgressHandler(options?.onProgress),
|
|
14
13
|
});
|
|
15
|
-
|
|
16
|
-
onProgress: options?.onProgress,
|
|
17
|
-
});
|
|
18
|
-
return { text };
|
|
14
|
+
return parseProviderReply(text);
|
|
19
15
|
}
|
|
20
16
|
async dispose() {
|
|
21
17
|
await this.cli.dispose();
|
|
@@ -1,22 +1,26 @@
|
|
|
1
1
|
import spawn from 'cross-spawn';
|
|
2
|
-
import type
|
|
2
|
+
import { type DebugLogger } from '../../debug.js';
|
|
3
|
+
import type { PreparedProviderTurnInput, ProviderGenerateOptions } from '../../types.js';
|
|
3
4
|
import type { ClaudeChannelSessionStore } from './session-store.js';
|
|
4
5
|
interface ClaudeCliRuntime {
|
|
5
6
|
spawn: typeof spawn;
|
|
7
|
+
cwd: string;
|
|
6
8
|
}
|
|
7
9
|
/**
|
|
8
10
|
* CLI client for the Claude Code CLI (`claude`) non-interactive mode, with
|
|
9
|
-
* native
|
|
11
|
+
* native provider-session continuity.
|
|
10
12
|
*
|
|
11
13
|
* Claude session memory remains entirely inside the Claude CLI. This client
|
|
12
|
-
* only pins one native session id per
|
|
13
|
-
*
|
|
14
|
+
* only pins one native session id per routed provider session and serializes
|
|
15
|
+
* turns per route so `--resume` is never called concurrently for the same
|
|
16
|
+
* native session.
|
|
14
17
|
*/
|
|
15
18
|
export declare class ClaudeCliClient {
|
|
16
19
|
private readonly command;
|
|
17
20
|
private readonly args;
|
|
18
21
|
private readonly sessionStore?;
|
|
19
22
|
private readonly resolveSessionStoreAgentId;
|
|
23
|
+
private readonly logger;
|
|
20
24
|
private readonly runtime;
|
|
21
25
|
private readonly channels;
|
|
22
26
|
private readonly persistedSessions;
|
|
@@ -24,7 +28,8 @@ export declare class ClaudeCliClient {
|
|
|
24
28
|
private stopped;
|
|
25
29
|
private sessionStoreLoadPromise;
|
|
26
30
|
private sessionStoreWriteQueue;
|
|
27
|
-
constructor(command: string, args: string[], runtimeOverrides?: Partial<ClaudeCliRuntime>, sessionStore?: ClaudeChannelSessionStore | undefined, resolveSessionStoreAgentId?: () => string | undefined);
|
|
31
|
+
constructor(command: string, args: string[], runtimeOverrides?: Partial<ClaudeCliRuntime>, sessionStore?: ClaudeChannelSessionStore | undefined, resolveSessionStoreAgentId?: () => string | undefined, logger?: DebugLogger);
|
|
32
|
+
generateReply(turn: PreparedProviderTurnInput, options?: ProviderGenerateOptions): Promise<string>;
|
|
28
33
|
generateReply(channelId: string, prompt: string, options?: ProviderGenerateOptions): Promise<string>;
|
|
29
34
|
dispose(): Promise<void>;
|
|
30
35
|
private getOrCreateChannelState;
|
|
@@ -37,6 +42,8 @@ export declare class ClaudeCliClient {
|
|
|
37
42
|
private persistSession;
|
|
38
43
|
private persistSessionBestEffort;
|
|
39
44
|
private resetPersistedSession;
|
|
45
|
+
private resolveTurnCwd;
|
|
46
|
+
private resetSessionIfCwdChanged;
|
|
40
47
|
private resetPersistedSessionBestEffort;
|
|
41
48
|
private enqueueSessionStoreWrite;
|
|
42
49
|
private run;
|