@borgee/agents-host 0.2.35 → 0.2.56
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 +23 -27
- package/dist/agents-host.d.ts +28 -5
- package/dist/agents-host.js +274 -236
- package/dist/chat/chat-control-plane.d.ts +3 -0
- package/dist/chat/sdk-chat-control-plane.d.ts +4 -3
- package/dist/chat/sdk-chat-control-plane.js +6 -0
- package/dist/cli.js +1 -5
- package/dist/compatibility-gates.d.ts +4 -0
- package/dist/compatibility-gates.js +18 -1
- package/dist/context/claude-file-brief.d.ts +2 -0
- package/dist/context/claude-file-brief.js +83 -0
- package/dist/context/compaction.d.ts +20 -0
- package/dist/context/compaction.js +59 -0
- package/dist/context/injection.d.ts +44 -9
- package/dist/context/injection.js +360 -53
- package/dist/context/main-session-delegation.d.ts +1 -1
- package/dist/context/projection-strategy.d.ts +24 -0
- package/dist/context/projection-strategy.js +90 -0
- package/dist/context/prompt.d.ts +16 -1
- package/dist/context/prompt.js +475 -53
- package/dist/context/resolved-workspace.d.ts +2 -0
- package/dist/context/resolved-workspace.js +64 -0
- package/dist/context/skill-manual.d.ts +14 -0
- package/dist/context/skill-manual.js +21 -0
- package/dist/context/turn-preparation.d.ts +8 -2
- package/dist/context/turn-preparation.js +68 -17
- package/dist/gateway/localhost-gateway.js +18 -8
- package/dist/hosted-turn-content.d.ts +15 -0
- package/dist/hosted-turn-content.js +50 -0
- package/dist/managed-daemon.d.ts +3 -2
- package/dist/managed-daemon.js +198 -37
- package/dist/plugin-sdk.js +276 -359
- package/dist/plugin-sdk.js.map +4 -4
- package/dist/progress-to-activity.d.ts +16 -0
- package/dist/progress-to-activity.js +24 -0
- package/dist/projection-strategy-values.d.ts +4 -0
- package/dist/projection-strategy-values.js +28 -0
- package/dist/providers/acp-progress-collector.d.ts +44 -0
- package/dist/providers/acp-progress-collector.js +130 -0
- package/dist/providers/awaiting-user.d.ts +2 -3
- package/dist/providers/awaiting-user.js +5 -7
- package/dist/providers/claude/activity-metadata.d.ts +14 -0
- package/dist/providers/claude/activity-metadata.js +81 -0
- package/dist/providers/claude/adapter.d.ts +3 -1
- package/dist/providers/claude/adapter.js +10 -0
- package/dist/providers/claude/cli-client.d.ts +9 -1
- package/dist/providers/claude/cli-client.js +270 -126
- package/dist/providers/codex/adapter.d.ts +3 -1
- package/dist/providers/codex/adapter.js +10 -0
- package/dist/providers/codex/cli-client.d.ts +10 -2
- package/dist/providers/codex/cli-client.js +88 -104
- package/dist/providers/codex/project-doc.js +22 -37
- package/dist/providers/copilot/adapter.d.ts +3 -1
- package/dist/providers/copilot/adapter.js +10 -0
- package/dist/providers/copilot/cli-client.d.ts +9 -1
- package/dist/providers/copilot/cli-client.js +68 -85
- package/dist/providers/create-provider.d.ts +3 -1
- package/dist/providers/create-provider.js +36 -9
- package/dist/providers/provider-adapter.d.ts +35 -0
- package/dist/providers/provider-adapter.js +44 -1
- package/dist/state-paths.d.ts +10 -2
- package/dist/state-paths.js +25 -6
- package/dist/task-thread-resolution.d.ts +3 -2
- package/dist/types.d.ts +163 -8
- package/package.json +2 -2
- package/skills/borgee-agent/SKILL.md +127 -38
- package/skills/borgee-agent/references/errors.md +38 -0
- package/skills/borgee-agent/references/task-properties.md +33 -0
- package/skills/borgee-agent/scripts/borgee-agent.mjs +553 -0
- package/skills/borgee-agent/scripts/borgee-agent.py +547 -0
- package/dist/durable-cursor-store.d.ts +0 -5
- package/dist/durable-cursor-store.js +0 -7
- package/skills/borgee-agent/borgee-agent.mjs +0 -562
- package/skills/borgee-agent/borgee-agent.py +0 -469
|
@@ -2,6 +2,7 @@ import { Readable, Writable } from 'node:stream';
|
|
|
2
2
|
import spawn from 'cross-spawn';
|
|
3
3
|
import { PROTOCOL_VERSION, client, methods, ndJsonStream, } from '@agentclientprotocol/sdk';
|
|
4
4
|
import { HostLogger, summarizeChildStderr, summarizeError } from '../../debug.js';
|
|
5
|
+
import { AcpProgressCollector } from '../acp-progress-collector.js';
|
|
5
6
|
import { resolveCopilotPermissionResponse } from '../../policy/copilot-permission.js';
|
|
6
7
|
import { IDLE_BACKEND_SHUTDOWN_DISABLED_MS, IdleBackendShutdownScheduler, } from '../idle-backend-shutdown.js';
|
|
7
8
|
const SESSION_TAINTED_ERRORS = new WeakSet();
|
|
@@ -30,93 +31,35 @@ const DEFAULT_RUNTIME = {
|
|
|
30
31
|
idleShutdownGracePeriodMs: DEFAULT_IDLE_SHUTDOWN_GRACE_PERIOD_MS,
|
|
31
32
|
shutdownGracePeriodMs: DEFAULT_SHUTDOWN_GRACE_PERIOD_MS,
|
|
32
33
|
shutdownForceKillWaitMs: DEFAULT_SHUTDOWN_FORCE_KILL_WAIT_MS,
|
|
34
|
+
fetch: async (input, init) => fetch(input, init),
|
|
33
35
|
};
|
|
34
36
|
const DEFAULT_SESSION_CAPABILITIES = {
|
|
35
37
|
loadSession: false,
|
|
36
38
|
resumeSession: false,
|
|
37
39
|
};
|
|
38
|
-
function
|
|
39
|
-
return
|
|
40
|
+
function isAbsoluteHttpUrl(value) {
|
|
41
|
+
return value.startsWith('http://') || value.startsWith('https://');
|
|
40
42
|
}
|
|
41
|
-
function
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
case 'completed':
|
|
45
|
-
return normalizedTitle ? `Completed ${normalizedTitle}` : 'Completed tool call';
|
|
46
|
-
case 'failed':
|
|
47
|
-
return normalizedTitle ? `Failed ${normalizedTitle}` : 'Tool call failed';
|
|
48
|
-
case 'pending':
|
|
49
|
-
case 'in_progress':
|
|
50
|
-
case undefined:
|
|
51
|
-
case null:
|
|
52
|
-
return normalizedTitle ? `Running ${normalizedTitle}…` : 'Running tool…';
|
|
53
|
-
default:
|
|
54
|
-
return normalizedTitle ? `${status} ${normalizedTitle}` : status;
|
|
43
|
+
function resolveHostedAttachmentUrl(rawUrl, borgeeBaseUrl) {
|
|
44
|
+
if (isAbsoluteHttpUrl(rawUrl)) {
|
|
45
|
+
return rawUrl;
|
|
55
46
|
}
|
|
47
|
+
const base = borgeeBaseUrl.replace(/\/$/, '');
|
|
48
|
+
const path = rawUrl.startsWith('/') ? rawUrl : `/${rawUrl}`;
|
|
49
|
+
return `${base}${path}`;
|
|
56
50
|
}
|
|
57
|
-
function
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
entries[0];
|
|
61
|
-
return hasVisibleText(current?.content) ? `Plan: ${current.content.trim()}` : null;
|
|
62
|
-
}
|
|
63
|
-
class CopilotProgressCollector {
|
|
64
|
-
onProgress;
|
|
65
|
-
publicText = '';
|
|
66
|
-
lastPublished = null;
|
|
67
|
-
toolTitles = new Map();
|
|
68
|
-
constructor(onProgress) {
|
|
69
|
-
this.onProgress = onProgress;
|
|
70
|
-
}
|
|
71
|
-
consume(update) {
|
|
72
|
-
switch (update.update.sessionUpdate) {
|
|
73
|
-
case 'agent_message_chunk':
|
|
74
|
-
if (update.update.content.type !== 'text') {
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
this.publicText += update.update.content.text;
|
|
78
|
-
this.publish(this.publicText);
|
|
79
|
-
return;
|
|
80
|
-
case 'tool_call':
|
|
81
|
-
this.toolTitles.set(update.update.toolCallId, update.update.title);
|
|
82
|
-
this.publishFallback(formatToolProgress(update.update.title, update.update.status));
|
|
83
|
-
return;
|
|
84
|
-
case 'tool_call_update': {
|
|
85
|
-
const nextTitle = update.update.title ?? this.toolTitles.get(update.update.toolCallId);
|
|
86
|
-
if (hasVisibleText(nextTitle)) {
|
|
87
|
-
this.toolTitles.set(update.update.toolCallId, nextTitle);
|
|
88
|
-
}
|
|
89
|
-
this.publishFallback(formatToolProgress(nextTitle, update.update.status));
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
case 'plan':
|
|
93
|
-
this.publishFallback(formatPlanProgress(update.update.entries.map((entry) => ({
|
|
94
|
-
content: entry.content,
|
|
95
|
-
status: entry.status,
|
|
96
|
-
}))));
|
|
97
|
-
return;
|
|
98
|
-
default:
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
51
|
+
function isSameOrigin(left, right) {
|
|
52
|
+
try {
|
|
53
|
+
return new URL(left).origin === new URL(right).origin;
|
|
101
54
|
}
|
|
102
|
-
|
|
103
|
-
return
|
|
104
|
-
}
|
|
105
|
-
publishFallback(text) {
|
|
106
|
-
if (hasVisibleText(this.publicText)) {
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
this.publish(text);
|
|
110
|
-
}
|
|
111
|
-
publish(text) {
|
|
112
|
-
if (!this.onProgress || !hasVisibleText(text) || text === this.lastPublished) {
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
this.lastPublished = text;
|
|
116
|
-
this.onProgress({ text });
|
|
55
|
+
catch {
|
|
56
|
+
return false;
|
|
117
57
|
}
|
|
118
58
|
}
|
|
119
|
-
function
|
|
59
|
+
function asImagePart(part) {
|
|
60
|
+
return part.type === 'image' ? part : null;
|
|
61
|
+
}
|
|
62
|
+
function createDeferredTurn(channelId, preparedTurn, sessionPersistence, options) {
|
|
120
63
|
let settled = false;
|
|
121
64
|
let resolvePromise;
|
|
122
65
|
let rejectPromise;
|
|
@@ -126,9 +69,8 @@ function createDeferredTurn(channelId, prompt, sessionPersistence, promptContext
|
|
|
126
69
|
});
|
|
127
70
|
return {
|
|
128
71
|
channelId,
|
|
129
|
-
|
|
72
|
+
preparedTurn,
|
|
130
73
|
sessionPersistence,
|
|
131
|
-
promptContext,
|
|
132
74
|
options,
|
|
133
75
|
promise,
|
|
134
76
|
resolve(value) {
|
|
@@ -216,6 +158,7 @@ export class CopilotCliClient {
|
|
|
216
158
|
resolveSessionStoreAgentId;
|
|
217
159
|
logger;
|
|
218
160
|
permissionPolicy;
|
|
161
|
+
imageInputConfig;
|
|
219
162
|
runtime;
|
|
220
163
|
channels = new Map();
|
|
221
164
|
/**
|
|
@@ -253,12 +196,13 @@ export class CopilotCliClient {
|
|
|
253
196
|
sessionStoreWriteQueue = Promise.resolve();
|
|
254
197
|
sessionCapabilities = DEFAULT_SESSION_CAPABILITIES;
|
|
255
198
|
idleBackendShutdown;
|
|
256
|
-
constructor(command, _ignoredArgs = [], runtimeOverrides = {}, sessionStore, resolveSessionStoreAgentId = () => undefined, logger = new HostLogger(), permissionPolicy = {}) {
|
|
199
|
+
constructor(command, _ignoredArgs = [], runtimeOverrides = {}, sessionStore, resolveSessionStoreAgentId = () => undefined, logger = new HostLogger(), permissionPolicy = {}, imageInputConfig = {}) {
|
|
257
200
|
this.command = command;
|
|
258
201
|
this.sessionStore = sessionStore;
|
|
259
202
|
this.resolveSessionStoreAgentId = resolveSessionStoreAgentId;
|
|
260
203
|
this.logger = logger;
|
|
261
204
|
this.permissionPolicy = permissionPolicy;
|
|
205
|
+
this.imageInputConfig = imageInputConfig;
|
|
262
206
|
this.runtime = { ...DEFAULT_RUNTIME, ...runtimeOverrides };
|
|
263
207
|
this.idleBackendShutdown = new IdleBackendShutdownScheduler({
|
|
264
208
|
idleShutdownMs: this.runtime.idleBackendShutdownMs,
|
|
@@ -279,12 +223,19 @@ export class CopilotCliClient {
|
|
|
279
223
|
if (this.fatalError) {
|
|
280
224
|
throw this.fatalError;
|
|
281
225
|
}
|
|
282
|
-
const
|
|
226
|
+
const preparedTurnBase = typeof channelIdOrTurn === 'string'
|
|
283
227
|
? {
|
|
284
228
|
channelId: channelIdOrTurn,
|
|
229
|
+
incomingContent: '',
|
|
230
|
+
incomingParts: [],
|
|
285
231
|
prompt: typeof promptOrOptions === 'string' ? promptOrOptions : '',
|
|
286
232
|
}
|
|
287
233
|
: channelIdOrTurn;
|
|
234
|
+
const preparedTurn = {
|
|
235
|
+
...preparedTurnBase,
|
|
236
|
+
incomingContent: preparedTurnBase.incomingContent ?? '',
|
|
237
|
+
incomingParts: preparedTurnBase.incomingParts ?? [],
|
|
238
|
+
};
|
|
288
239
|
const options = typeof channelIdOrTurn === 'string'
|
|
289
240
|
? maybeOptions
|
|
290
241
|
: promptOrOptions;
|
|
@@ -292,7 +243,7 @@ export class CopilotCliClient {
|
|
|
292
243
|
const state = this.getOrCreateChannelState(sessionRouting.key, preparedTurn.channelId, sessionRouting.persistence);
|
|
293
244
|
this.clearIdleTimer(state);
|
|
294
245
|
this.idleBackendShutdown.cancel();
|
|
295
|
-
const turn = createDeferredTurn(preparedTurn.channelId, preparedTurn
|
|
246
|
+
const turn = createDeferredTurn(preparedTurn.channelId, preparedTurn, sessionRouting.persistence, options);
|
|
296
247
|
state.queue.push(turn);
|
|
297
248
|
this.processChannelQueue(sessionRouting.key, state);
|
|
298
249
|
return turn.promise;
|
|
@@ -455,13 +406,14 @@ export class CopilotCliClient {
|
|
|
455
406
|
}
|
|
456
407
|
state.activeTurn = turn;
|
|
457
408
|
try {
|
|
458
|
-
state.cwd = await this.resolveSessionCwd(turn.promptContext);
|
|
409
|
+
state.cwd = await this.resolveSessionCwd(turn.preparedTurn.promptContext);
|
|
459
410
|
await this.ensureStarted();
|
|
460
411
|
await this.recycleSessionIfCwdChanged(channelId, state);
|
|
461
412
|
const session = await this.getOrCreateSession(channelId, state);
|
|
462
413
|
let reply;
|
|
463
414
|
try {
|
|
464
|
-
|
|
415
|
+
const promptInput = await this.buildPromptInput(turn.preparedTurn);
|
|
416
|
+
reply = await this.runTurn(session, promptInput, turn.options);
|
|
465
417
|
}
|
|
466
418
|
catch (error) {
|
|
467
419
|
if (isSessionTainted(error)) {
|
|
@@ -615,7 +567,38 @@ export class CopilotCliClient {
|
|
|
615
567
|
}
|
|
616
568
|
}
|
|
617
569
|
async resolveSessionCwd(promptContext) {
|
|
618
|
-
return promptContext?.
|
|
570
|
+
return promptContext?.resolvedWorkspace?.rootPath ?? this.runtime.cwd;
|
|
571
|
+
}
|
|
572
|
+
async buildPromptInput(turn) {
|
|
573
|
+
const imageParts = turn.incomingParts.map(asImagePart).filter((part) => part !== null);
|
|
574
|
+
if (imageParts.length === 0) {
|
|
575
|
+
return turn.prompt;
|
|
576
|
+
}
|
|
577
|
+
const imageBlocks = await Promise.all(imageParts.map(async (part) => this.fetchImageBlock(part.attachment.url, part.attachment.contentType)));
|
|
578
|
+
return [{ type: 'text', text: turn.prompt }, ...imageBlocks];
|
|
579
|
+
}
|
|
580
|
+
async fetchImageBlock(rawUrl, contentType) {
|
|
581
|
+
const baseUrl = this.imageInputConfig.borgeeBaseUrl?.trim();
|
|
582
|
+
const agentApiKey = this.imageInputConfig.agentApiKey?.trim();
|
|
583
|
+
if (!baseUrl || !agentApiKey) {
|
|
584
|
+
throw new Error('Copilot image input requires Borgee base URL and agent API key');
|
|
585
|
+
}
|
|
586
|
+
const resolvedUrl = resolveHostedAttachmentUrl(rawUrl, baseUrl);
|
|
587
|
+
if (!isSameOrigin(resolvedUrl, baseUrl)) {
|
|
588
|
+
throw new Error(`Copilot image input only supports Borgee-origin attachments: ${resolvedUrl}`);
|
|
589
|
+
}
|
|
590
|
+
const response = await this.runtime.fetch(resolvedUrl, {
|
|
591
|
+
headers: { Authorization: `Bearer ${agentApiKey}` },
|
|
592
|
+
});
|
|
593
|
+
if (!response.ok) {
|
|
594
|
+
throw new Error(`Copilot image fetch failed with ${response.status} ${response.statusText}`.trim());
|
|
595
|
+
}
|
|
596
|
+
return {
|
|
597
|
+
type: 'image',
|
|
598
|
+
mimeType: contentType,
|
|
599
|
+
data: Buffer.from(await response.arrayBuffer()).toString('base64'),
|
|
600
|
+
uri: response.url || resolvedUrl,
|
|
601
|
+
};
|
|
619
602
|
}
|
|
620
603
|
async recycleSessionIfCwdChanged(channelId, state) {
|
|
621
604
|
const session = state.session;
|
|
@@ -644,7 +627,7 @@ export class CopilotCliClient {
|
|
|
644
627
|
const promptFailure = new Promise((_, reject) => {
|
|
645
628
|
void promptPromise.catch((error) => reject(markSessionTainted(error)));
|
|
646
629
|
});
|
|
647
|
-
const collector = new
|
|
630
|
+
const collector = new AcpProgressCollector(options?.onProgress);
|
|
648
631
|
for (;;) {
|
|
649
632
|
let update;
|
|
650
633
|
try {
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import type { DebugLogger } from '../debug.js';
|
|
2
2
|
import type { ProviderRuntimeConfig } from '../types.js';
|
|
3
|
-
import type {
|
|
3
|
+
import type { ChatControlPlane } from '../chat/chat-control-plane.js';
|
|
4
|
+
import { type ProviderAdapter } from './provider-adapter.js';
|
|
4
5
|
import type { LocalhostGatewayContextPublisher } from '../context/injection.js';
|
|
5
6
|
import type { AuthorizationAuditSinkLike } from '../policy/authorization-audit.js';
|
|
6
7
|
interface CreateProviderOptions {
|
|
7
8
|
compatibilityGates?: ReadonlySet<string>;
|
|
8
9
|
localhostGateway?: LocalhostGatewayContextPublisher;
|
|
9
10
|
authorizationAuditSink?: AuthorizationAuditSinkLike;
|
|
11
|
+
controlPlane?: Pick<ChatControlPlane, 'getTask' | 'listChannels' | 'listTasks'>;
|
|
10
12
|
}
|
|
11
13
|
export declare function createProvider(config: ProviderRuntimeConfig, debugLogger?: DebugLogger, options?: CreateProviderOptions): ProviderAdapter;
|
|
12
14
|
export {};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { FileChannelContextStore } from '../context/injection.js';
|
|
2
|
+
import { ServerProjectionStrategyResolver } from '../context/projection-strategy.js';
|
|
2
3
|
import { createProviderConnectionsSessionStore } from '../connections-state-store.js';
|
|
3
4
|
import { ProviderTurnPreparer } from '../context/turn-preparation.js';
|
|
4
|
-
import { CONNECTIONS_STATE_LAYER_COMPATIBILITY_GATE, CONTEXT_INJECTION_COMPATIBILITY_GATE, CODEX_PROVIDER_COMPATIBILITY_GATE, COPILOT_PROVIDER_V2_COMPATIBILITY_GATE, INTERNAL_PROVIDER_IMPLEMENTATIONS_ENV, LOCALHOST_GATEWAY_COMPATIBILITY_GATE, parseInternalProviderImplementationOverrides, POLICY_AUDIT_ENFORCEMENT_COMPATIBILITY_GATE, resolveInternalPolicyMode, resolveInternalCompatibilityGates, SKILL_RUNTIME_COMPATIBILITY_GATE, } from '../compatibility-gates.js';
|
|
5
|
+
import { CONNECTIONS_STATE_LAYER_COMPATIBILITY_GATE, CONTEXT_INJECTION_COMPATIBILITY_GATE, CODEX_PROVIDER_COMPATIBILITY_GATE, COPILOT_PROVIDER_V2_COMPATIBILITY_GATE, INTERNAL_PROVIDER_IMPLEMENTATIONS_ENV, LOCALHOST_GATEWAY_COMPATIBILITY_GATE, parseInternalProviderImplementationOverrides, POLICY_AUDIT_ENFORCEMENT_COMPATIBILITY_GATE, resolveInternalPolicyMode, resolveInternalCompatibilityGates, resolveInternalProjectionStrategy, SKILL_RUNTIME_COMPATIBILITY_GATE, } from '../compatibility-gates.js';
|
|
5
6
|
import { resolveIdleBackendShutdownMs } from './idle-backend-shutdown.js';
|
|
6
7
|
import { ClaudeCliClient } from './claude/cli-client.js';
|
|
7
8
|
import { ClaudeProviderAdapter } from './claude/adapter.js';
|
|
@@ -10,16 +11,18 @@ import { CodexCliClient } from './codex/cli-client.js';
|
|
|
10
11
|
import { CodexProviderAdapter } from './codex/adapter.js';
|
|
11
12
|
import { FileCodexChannelSessionStore } from './codex/session-store.js';
|
|
12
13
|
import { CopilotCliClient } from './copilot/cli-client.js';
|
|
13
|
-
import { CopilotProviderAdapter } from './copilot/adapter.js';
|
|
14
|
+
import { COPILOT_HOSTED_PROVIDER_CAPABILITIES, CopilotProviderAdapter } from './copilot/adapter.js';
|
|
14
15
|
import { FileCopilotChannelSessionStore } from './copilot/session-store.js';
|
|
15
16
|
import { resolveClaudeSessionMapPath, resolveCodexSessionMapPath, resolveCopilotSessionMapPath, } from '../state-paths.js';
|
|
16
17
|
import { createAwaitingUserProgressHandler, parseProviderReply } from './awaiting-user.js';
|
|
17
18
|
class ProviderV2CompatibilityAdapter {
|
|
18
19
|
provider;
|
|
19
20
|
turnPreparer;
|
|
20
|
-
|
|
21
|
+
capabilities;
|
|
22
|
+
constructor(provider, turnPreparer, capabilities) {
|
|
21
23
|
this.provider = provider;
|
|
22
24
|
this.turnPreparer = turnPreparer;
|
|
25
|
+
this.capabilities = capabilities;
|
|
23
26
|
}
|
|
24
27
|
async generateReply(input, options) {
|
|
25
28
|
const preparedTurn = await this.turnPreparer.prepare(input);
|
|
@@ -50,7 +53,6 @@ class CliBackedProviderV2 {
|
|
|
50
53
|
}
|
|
51
54
|
class CopilotProviderV2 extends CliBackedProviderV2 {
|
|
52
55
|
}
|
|
53
|
-
const TASK_WORKSPACE_ROOT_DIR_ENV = 'AGENTS_HOST_INTERNAL_TASK_WORKSPACE_ROOT_DIR';
|
|
54
56
|
const PROVIDER_V2_COMPATIBILITY_GATES = {
|
|
55
57
|
copilot: COPILOT_PROVIDER_V2_COMPATIBILITY_GATE,
|
|
56
58
|
};
|
|
@@ -69,7 +71,10 @@ function createClaudeProvider(config, debugLogger, connectionsStateGateEnabled,
|
|
|
69
71
|
stateRootDir: config.stateRootDir,
|
|
70
72
|
gateEnabled: connectionsStateGateEnabled,
|
|
71
73
|
logger: debugLogger,
|
|
72
|
-
}), config.resolveStableAgentId, debugLogger
|
|
74
|
+
}), config.resolveStableAgentId, debugLogger, {
|
|
75
|
+
borgeeBaseUrl: config.borgeeBaseUrl,
|
|
76
|
+
agentApiKey: config.agentApiKey,
|
|
77
|
+
});
|
|
73
78
|
return new ClaudeProviderAdapter(cli, turnPreparer);
|
|
74
79
|
}
|
|
75
80
|
function createCopilotProvider(config, debugLogger, connectionsStateGateEnabled, implementation, turnPreparer, policyAuditGateEnabled, authorizationAuditSink, idleBackendShutdownMs) {
|
|
@@ -89,9 +94,12 @@ function createCopilotProvider(config, debugLogger, connectionsStateGateEnabled,
|
|
|
89
94
|
gateEnabled: policyAuditGateEnabled,
|
|
90
95
|
policyMode,
|
|
91
96
|
auditSink: authorizationAuditSink,
|
|
97
|
+
}, {
|
|
98
|
+
borgeeBaseUrl: config.borgeeBaseUrl,
|
|
99
|
+
agentApiKey: config.agentApiKey,
|
|
92
100
|
});
|
|
93
101
|
return implementation === 'v2'
|
|
94
|
-
? new ProviderV2CompatibilityAdapter(new CopilotProviderV2(cli), turnPreparer)
|
|
102
|
+
? new ProviderV2CompatibilityAdapter(new CopilotProviderV2(cli), turnPreparer, COPILOT_HOSTED_PROVIDER_CAPABILITIES)
|
|
95
103
|
: new CopilotProviderAdapter(cli, turnPreparer);
|
|
96
104
|
}
|
|
97
105
|
function createCodexProvider(config, debugLogger, connectionsStateGateEnabled, turnPreparer, idleBackendShutdownMs) {
|
|
@@ -103,7 +111,10 @@ function createCodexProvider(config, debugLogger, connectionsStateGateEnabled, t
|
|
|
103
111
|
stateRootDir: config.stateRootDir,
|
|
104
112
|
gateEnabled: connectionsStateGateEnabled,
|
|
105
113
|
logger: debugLogger,
|
|
106
|
-
}), config.resolveStableAgentId, debugLogger
|
|
114
|
+
}), config.resolveStableAgentId, debugLogger, {
|
|
115
|
+
borgeeBaseUrl: config.borgeeBaseUrl,
|
|
116
|
+
agentApiKey: config.agentApiKey,
|
|
117
|
+
});
|
|
107
118
|
return new CodexProviderAdapter(cli, turnPreparer);
|
|
108
119
|
}
|
|
109
120
|
export function createProvider(config, debugLogger, options = {}) {
|
|
@@ -120,13 +131,29 @@ export function createProvider(config, debugLogger, options = {}) {
|
|
|
120
131
|
const channelContextStore = contextInjectionGateEnabled
|
|
121
132
|
? new FileChannelContextStore(config.stateRootDir, {
|
|
122
133
|
skillRuntimeEnabled: skillRuntimeGateEnabled,
|
|
123
|
-
taskWorkspaceRootDir: process.env[TASK_WORKSPACE_ROOT_DIR_ENV],
|
|
124
134
|
localhostGateway: skillRuntimeGateEnabled && localhostGatewayGateEnabled
|
|
125
135
|
? options.localhostGateway
|
|
126
136
|
: undefined,
|
|
137
|
+
taskReader: options.controlPlane,
|
|
127
138
|
})
|
|
128
139
|
: undefined;
|
|
129
|
-
const
|
|
140
|
+
const resolveInternalProjection = () => resolveInternalProjectionStrategy();
|
|
141
|
+
const projectionStrategyResolver = new ServerProjectionStrategyResolver({
|
|
142
|
+
baseUrl: config.borgeeBaseUrl,
|
|
143
|
+
agentApiKey: config.agentApiKey,
|
|
144
|
+
resolveStableAgentId: config.resolveStableAgentId,
|
|
145
|
+
fallback: resolveInternalProjection,
|
|
146
|
+
logger: debugLogger,
|
|
147
|
+
taskReader: options.controlPlane,
|
|
148
|
+
});
|
|
149
|
+
const turnPreparer = new ProviderTurnPreparer(channelContextStore, debugLogger, {
|
|
150
|
+
resolveProjectionStrategy: async (input) => {
|
|
151
|
+
if (input.provider !== 'claude') {
|
|
152
|
+
return resolveInternalProjection();
|
|
153
|
+
}
|
|
154
|
+
return projectionStrategyResolver.resolve(input.channelId);
|
|
155
|
+
},
|
|
156
|
+
});
|
|
130
157
|
switch (config.provider) {
|
|
131
158
|
case 'claude': {
|
|
132
159
|
return createClaudeProvider(config, debugLogger, connectionsStateGateEnabled, turnPreparer, idleBackendShutdownMs);
|
|
@@ -1,5 +1,40 @@
|
|
|
1
1
|
import type { ProviderGenerateOptions, ProviderInput, ProviderReply } from '../types.js';
|
|
2
|
+
export type ProviderImageInputSupport = 'supported' | 'metadata-only' | 'not-supported';
|
|
3
|
+
export type ProviderImageTransportSupport = 'supported' | 'not-supported';
|
|
4
|
+
export type ProviderImageTransportSource = 'transport-derived' | 'runtime-derived';
|
|
5
|
+
export type ProviderImageTransportDelivery = 'host-materialized-local-path' | 'blob';
|
|
6
|
+
export type ProviderImageInputReason = 'real-media-delivered' | 'shared-host-attachment-metadata-fallback' | 'host-policy-blocked';
|
|
7
|
+
export type ProviderImageTransportReason = 'real-media-delivered' | 'transport-does-not-deliver-real-media' | 'runtime-capability-not-yet-resolved' | 'host-policy-blocked';
|
|
8
|
+
export interface SharedHostAttachmentMetadataFallbackCapability {
|
|
9
|
+
support: 'metadata-only';
|
|
10
|
+
delivery: 'prompt-text-attachment-metadata';
|
|
11
|
+
}
|
|
12
|
+
export interface ProviderImageTransportCapability {
|
|
13
|
+
source: ProviderImageTransportSource;
|
|
14
|
+
support: ProviderImageTransportSupport;
|
|
15
|
+
reason: ProviderImageTransportReason;
|
|
16
|
+
delivery: readonly ProviderImageTransportDelivery[];
|
|
17
|
+
maxImageCount?: number;
|
|
18
|
+
maxBytesPerImage?: number;
|
|
19
|
+
maxTotalBytes?: number;
|
|
20
|
+
}
|
|
21
|
+
export interface ProviderImageCapability {
|
|
22
|
+
support: ProviderImageInputSupport;
|
|
23
|
+
reason: ProviderImageInputReason;
|
|
24
|
+
sharedHostFallback: SharedHostAttachmentMetadataFallbackCapability;
|
|
25
|
+
transport: ProviderImageTransportCapability;
|
|
26
|
+
}
|
|
27
|
+
export interface ProviderCapabilities {
|
|
28
|
+
imageInput: ProviderImageCapability;
|
|
29
|
+
}
|
|
30
|
+
export declare const SHARED_HOST_ATTACHMENT_METADATA_FALLBACK: SharedHostAttachmentMetadataFallbackCapability;
|
|
31
|
+
export declare function createHostedProviderCapabilities(params: {
|
|
32
|
+
imageInputTransport: ProviderImageTransportCapability;
|
|
33
|
+
sharedHostFallback?: SharedHostAttachmentMetadataFallbackCapability;
|
|
34
|
+
}): ProviderCapabilities;
|
|
35
|
+
export declare const TEXT_ONLY_HOSTED_PROVIDER_CAPABILITIES: ProviderCapabilities;
|
|
2
36
|
export interface ProviderAdapter {
|
|
37
|
+
readonly capabilities: ProviderCapabilities;
|
|
3
38
|
generateReply(input: ProviderInput, options?: ProviderGenerateOptions): Promise<ProviderReply>;
|
|
4
39
|
dispose?(): Promise<void>;
|
|
5
40
|
}
|
|
@@ -1 +1,44 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export const SHARED_HOST_ATTACHMENT_METADATA_FALLBACK = Object.freeze({
|
|
2
|
+
support: 'metadata-only',
|
|
3
|
+
delivery: 'prompt-text-attachment-metadata',
|
|
4
|
+
});
|
|
5
|
+
function resolveImageInputSupport(transport, sharedHostFallback) {
|
|
6
|
+
if (transport.support === 'supported') {
|
|
7
|
+
return {
|
|
8
|
+
support: 'supported',
|
|
9
|
+
reason: 'real-media-delivered',
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
if (transport.reason === 'host-policy-blocked') {
|
|
13
|
+
return {
|
|
14
|
+
support: 'not-supported',
|
|
15
|
+
reason: 'host-policy-blocked',
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
return {
|
|
19
|
+
support: sharedHostFallback.support,
|
|
20
|
+
reason: 'shared-host-attachment-metadata-fallback',
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export function createHostedProviderCapabilities(params) {
|
|
24
|
+
const sharedHostFallback = params.sharedHostFallback ?? SHARED_HOST_ATTACHMENT_METADATA_FALLBACK;
|
|
25
|
+
const transport = Object.freeze({
|
|
26
|
+
...params.imageInputTransport,
|
|
27
|
+
delivery: Object.freeze([...params.imageInputTransport.delivery]),
|
|
28
|
+
});
|
|
29
|
+
return Object.freeze({
|
|
30
|
+
imageInput: Object.freeze({
|
|
31
|
+
...resolveImageInputSupport(transport, sharedHostFallback),
|
|
32
|
+
sharedHostFallback,
|
|
33
|
+
transport,
|
|
34
|
+
}),
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
export const TEXT_ONLY_HOSTED_PROVIDER_CAPABILITIES = createHostedProviderCapabilities({
|
|
38
|
+
imageInputTransport: {
|
|
39
|
+
source: 'transport-derived',
|
|
40
|
+
support: 'not-supported',
|
|
41
|
+
reason: 'transport-does-not-deliver-real-media',
|
|
42
|
+
delivery: [],
|
|
43
|
+
},
|
|
44
|
+
});
|
package/dist/state-paths.d.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
export declare function normalizeManagedRuntimeKey(serverUrl: string): string;
|
|
2
|
+
export type ManagedDaemonEndpoint = {
|
|
3
|
+
kind: 'named-pipe';
|
|
4
|
+
address: string;
|
|
5
|
+
} | {
|
|
6
|
+
kind: 'unix-socket';
|
|
7
|
+
address: string;
|
|
8
|
+
};
|
|
2
9
|
export declare function resolveSingleAgentStateRoot(env?: NodeJS.ProcessEnv, resolvedHomeDir?: string, agentKey?: string): string;
|
|
3
10
|
export declare function resolveManagedRuntimeRoot(serverUrl: string, env?: NodeJS.ProcessEnv, resolvedHomeDir?: string): string;
|
|
4
11
|
/**
|
|
@@ -7,16 +14,17 @@ export declare function resolveManagedRuntimeRoot(serverUrl: string, env?: NodeJ
|
|
|
7
14
|
*/
|
|
8
15
|
export declare function resolveUpdateCheckCachePath(env?: NodeJS.ProcessEnv, resolvedHomeDir?: string): string;
|
|
9
16
|
export declare function resolveManagedStateRoot(rootPath: string): string;
|
|
10
|
-
export declare function
|
|
17
|
+
export declare function resolveManagedDaemonEndpoint(rootPath: string, platform?: NodeJS.Platform): ManagedDaemonEndpoint;
|
|
18
|
+
export declare function resolveManagedDaemonSocketPath(rootPath: string, platform?: NodeJS.Platform): string;
|
|
11
19
|
export declare function resolveManagedDaemonLogPath(rootPath: string): string;
|
|
12
20
|
export declare function resolveManagedRuntimeSettingsPath(rootPath: string): string;
|
|
13
21
|
export declare function resolveManagedBootstrapLockPath(rootPath: string): string;
|
|
14
22
|
export declare function resolveLocalConfigAgentStateRoot(rootPath: string, agentKey: string): string;
|
|
15
|
-
export declare function resolveAgentCursorPath(stateRootDir: string, agentId: string): string;
|
|
16
23
|
export declare function resolveSharedProtocolKickoffDecisionPath(stateRootDir: string, channelId: string, anchorMessageId: string): string;
|
|
17
24
|
export declare function resolveSharedProtocolStatusPath(stateRootDir: string, channelId: string, anchorMessageId: string): string;
|
|
18
25
|
export declare function resolveConnectionsStatePath(stateRootDir: string): string;
|
|
19
26
|
export declare function resolveAttentionStatePath(stateRootDir: string, channelId: string): string;
|
|
27
|
+
export declare function resolveCompactionStatePath(stateRootDir: string, channelId: string): string;
|
|
20
28
|
export declare function resolveAuthorizationAuditPath(stateRootDir: string): string;
|
|
21
29
|
export declare function resolvePreviousAuthorizationAuditPath(stateRootDir: string): string;
|
|
22
30
|
export declare function resolveClaudeSessionMapPath(stateRootDir: string, agentId: string): string;
|
package/dist/state-paths.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
import { homedir } from 'node:os';
|
|
3
|
-
import { dirname, join, resolve } from 'node:path';
|
|
3
|
+
import { dirname, join, posix, resolve, win32 } from 'node:path';
|
|
4
4
|
const SINGLE_AGENT_HOME_ROOT = '.borgee';
|
|
5
5
|
const AGENTS_HOST_ROOT = 'agents-host';
|
|
6
6
|
const SINGLE_AGENT_NAMESPACE = 'single-agent';
|
|
7
7
|
const MANAGED_RUNTIME_NAMESPACE = 'managed';
|
|
8
8
|
const MANAGED_STATE_DIRNAME = '.state';
|
|
9
9
|
const MANAGED_DAEMON_SOCKET_FILENAME = 'ctl.sock';
|
|
10
|
+
const MANAGED_DAEMON_PIPE_PREFIX = '\\\\.\\pipe\\borgee-agents-host-managed-';
|
|
10
11
|
const MANAGED_DAEMON_LOG_FILENAME = 'daemon.log';
|
|
11
12
|
const MANAGED_RUNTIME_SETTINGS_FILENAME = 'managed-runtime-settings.json';
|
|
12
13
|
const MANAGED_BOOTSTRAP_LOCK_DIRNAME = '.bootstrap.lock';
|
|
@@ -95,8 +96,26 @@ export function resolveUpdateCheckCachePath(env = process.env, resolvedHomeDir =
|
|
|
95
96
|
export function resolveManagedStateRoot(rootPath) {
|
|
96
97
|
return join(resolve(rootPath), MANAGED_STATE_DIRNAME);
|
|
97
98
|
}
|
|
98
|
-
export function
|
|
99
|
-
|
|
99
|
+
export function resolveManagedDaemonEndpoint(rootPath, platform = process.platform) {
|
|
100
|
+
const pathApi = platform === 'win32' ? win32 : posix;
|
|
101
|
+
const resolvedRoot = pathApi.resolve(rootPath);
|
|
102
|
+
if (platform === 'win32') {
|
|
103
|
+
const rootHash = createHash('sha256')
|
|
104
|
+
.update(resolvedRoot.toLowerCase())
|
|
105
|
+
.digest('hex')
|
|
106
|
+
.slice(0, 24);
|
|
107
|
+
return {
|
|
108
|
+
kind: 'named-pipe',
|
|
109
|
+
address: `${MANAGED_DAEMON_PIPE_PREFIX}${rootHash}`,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
kind: 'unix-socket',
|
|
114
|
+
address: posix.join(resolvedRoot, MANAGED_DAEMON_SOCKET_FILENAME),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
export function resolveManagedDaemonSocketPath(rootPath, platform = process.platform) {
|
|
118
|
+
return resolveManagedDaemonEndpoint(rootPath, platform).address;
|
|
100
119
|
}
|
|
101
120
|
export function resolveManagedDaemonLogPath(rootPath) {
|
|
102
121
|
return join(resolve(rootPath), MANAGED_DAEMON_LOG_FILENAME);
|
|
@@ -110,9 +129,6 @@ export function resolveManagedBootstrapLockPath(rootPath) {
|
|
|
110
129
|
export function resolveLocalConfigAgentStateRoot(rootPath, agentKey) {
|
|
111
130
|
return join(resolveManagedStateRoot(rootPath), `${sanitizeStateRootLabel(agentKey)}-${hashStateRootKey(agentKey)}`);
|
|
112
131
|
}
|
|
113
|
-
export function resolveAgentCursorPath(stateRootDir, agentId) {
|
|
114
|
-
return join(stateRootDir, `bpp-cursor-${encodeSegment(agentId)}.json`);
|
|
115
|
-
}
|
|
116
132
|
export function resolveSharedProtocolKickoffDecisionPath(stateRootDir, channelId, anchorMessageId) {
|
|
117
133
|
return join(dirname(resolve(stateRootDir)), 'protocol-kickoff-decisions', `${encodeSegment(channelId)}--${encodeSegment(anchorMessageId)}.json`);
|
|
118
134
|
}
|
|
@@ -125,6 +141,9 @@ export function resolveConnectionsStatePath(stateRootDir) {
|
|
|
125
141
|
export function resolveAttentionStatePath(stateRootDir, channelId) {
|
|
126
142
|
return join(stateRootDir, 'attention-state', `${encodeSegment(channelId)}.json`);
|
|
127
143
|
}
|
|
144
|
+
export function resolveCompactionStatePath(stateRootDir, channelId) {
|
|
145
|
+
return join(stateRootDir, 'compaction-state', `${encodeSegment(channelId)}.json`);
|
|
146
|
+
}
|
|
128
147
|
export function resolveAuthorizationAuditPath(stateRootDir) {
|
|
129
148
|
return join(stateRootDir, 'authorization-audit.jsonl');
|
|
130
149
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { ChatControlPlane } from './chat/chat-control-plane.js';
|
|
2
2
|
import type { Task } from './types.js';
|
|
3
|
+
type TaskThreadResolutionControlPlane = Pick<ChatControlPlane, 'getTask' | 'listChannels' | 'listTasks'>;
|
|
3
4
|
interface WaitForTaskForThreadOptions {
|
|
4
5
|
preferredTaskId?: string;
|
|
5
6
|
attempts?: number;
|
|
6
7
|
delayMs?: number;
|
|
7
8
|
}
|
|
8
|
-
export declare function findTaskForThread(controlPlane:
|
|
9
|
-
export declare function waitForTaskForThread(controlPlane:
|
|
9
|
+
export declare function findTaskForThread(controlPlane: TaskThreadResolutionControlPlane, threadId: string, preferredTaskId?: string): Promise<Task | null>;
|
|
10
|
+
export declare function waitForTaskForThread(controlPlane: TaskThreadResolutionControlPlane, threadId: string, options?: WaitForTaskForThreadOptions): Promise<Task | null>;
|
|
10
11
|
export {};
|