@borgee/agents-host 0.2.44 → 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 +26 -5
- package/dist/agents-host.js +163 -192
- 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 +3 -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 +39 -6
- package/dist/context/injection.js +317 -26
- 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 +456 -22
- package/dist/context/resolved-workspace.d.ts +2 -0
- package/dist/context/resolved-workspace.js +64 -0
- package/dist/context/skill-manual.d.ts +1 -0
- package/dist/context/skill-manual.js +4 -1
- package/dist/context/turn-preparation.d.ts +8 -2
- package/dist/context/turn-preparation.js +56 -14
- package/dist/gateway/localhost-gateway.js +2 -0
- package/dist/managed-daemon.js +122 -9
- 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/cli-client.d.ts +1 -2
- package/dist/providers/claude/cli-client.js +190 -117
- package/dist/providers/codex/cli-client.js +3 -83
- package/dist/providers/codex/project-doc.js +12 -11
- package/dist/providers/copilot/cli-client.js +3 -83
- package/dist/providers/create-provider.d.ts +2 -0
- package/dist/providers/create-provider.js +20 -4
- package/dist/state-paths.d.ts +1 -1
- package/dist/state-paths.js +3 -3
- package/dist/task-thread-resolution.d.ts +3 -2
- package/dist/types.d.ts +130 -6
- package/package.json +2 -2
- package/skills/borgee-agent/SKILL.md +9 -1
- package/skills/borgee-agent/references/task-properties.md +5 -2
- package/dist/durable-cursor-store.d.ts +0 -5
- package/dist/durable-cursor-store.js +0 -7
|
@@ -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();
|
|
@@ -36,9 +37,6 @@ const DEFAULT_SESSION_CAPABILITIES = {
|
|
|
36
37
|
loadSession: false,
|
|
37
38
|
resumeSession: false,
|
|
38
39
|
};
|
|
39
|
-
function hasVisibleText(value) {
|
|
40
|
-
return typeof value === 'string' && value.trim().length > 0;
|
|
41
|
-
}
|
|
42
40
|
function isAbsoluteHttpUrl(value) {
|
|
43
41
|
return value.startsWith('http://') || value.startsWith('https://');
|
|
44
42
|
}
|
|
@@ -61,84 +59,6 @@ function isSameOrigin(left, right) {
|
|
|
61
59
|
function asImagePart(part) {
|
|
62
60
|
return part.type === 'image' ? part : null;
|
|
63
61
|
}
|
|
64
|
-
function formatToolProgress(title, status) {
|
|
65
|
-
const normalizedTitle = hasVisibleText(title) ? title.trim() : null;
|
|
66
|
-
switch (status) {
|
|
67
|
-
case 'completed':
|
|
68
|
-
return normalizedTitle ? `Completed ${normalizedTitle}` : 'Completed tool call';
|
|
69
|
-
case 'failed':
|
|
70
|
-
return normalizedTitle ? `Failed ${normalizedTitle}` : 'Tool call failed';
|
|
71
|
-
case 'pending':
|
|
72
|
-
case 'in_progress':
|
|
73
|
-
case undefined:
|
|
74
|
-
case null:
|
|
75
|
-
return normalizedTitle ? `Running ${normalizedTitle}…` : 'Running tool…';
|
|
76
|
-
default:
|
|
77
|
-
return normalizedTitle ? `${status} ${normalizedTitle}` : status;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
function formatPlanProgress(entries) {
|
|
81
|
-
const current = entries.find((entry) => entry.status === 'in_progress') ??
|
|
82
|
-
entries.find((entry) => entry.status === 'pending') ??
|
|
83
|
-
entries[0];
|
|
84
|
-
return hasVisibleText(current?.content) ? `Plan: ${current.content.trim()}` : null;
|
|
85
|
-
}
|
|
86
|
-
class CopilotProgressCollector {
|
|
87
|
-
onProgress;
|
|
88
|
-
publicText = '';
|
|
89
|
-
lastPublished = null;
|
|
90
|
-
toolTitles = new Map();
|
|
91
|
-
constructor(onProgress) {
|
|
92
|
-
this.onProgress = onProgress;
|
|
93
|
-
}
|
|
94
|
-
consume(update) {
|
|
95
|
-
switch (update.update.sessionUpdate) {
|
|
96
|
-
case 'agent_message_chunk':
|
|
97
|
-
if (update.update.content.type !== 'text') {
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
this.publicText += update.update.content.text;
|
|
101
|
-
this.publish(this.publicText);
|
|
102
|
-
return;
|
|
103
|
-
case 'tool_call':
|
|
104
|
-
this.toolTitles.set(update.update.toolCallId, update.update.title);
|
|
105
|
-
this.publishFallback(formatToolProgress(update.update.title, update.update.status));
|
|
106
|
-
return;
|
|
107
|
-
case 'tool_call_update': {
|
|
108
|
-
const nextTitle = update.update.title ?? this.toolTitles.get(update.update.toolCallId);
|
|
109
|
-
if (hasVisibleText(nextTitle)) {
|
|
110
|
-
this.toolTitles.set(update.update.toolCallId, nextTitle);
|
|
111
|
-
}
|
|
112
|
-
this.publishFallback(formatToolProgress(nextTitle, update.update.status));
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
case 'plan':
|
|
116
|
-
this.publishFallback(formatPlanProgress(update.update.entries.map((entry) => ({
|
|
117
|
-
content: entry.content,
|
|
118
|
-
status: entry.status,
|
|
119
|
-
}))));
|
|
120
|
-
return;
|
|
121
|
-
default:
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
getFinalText() {
|
|
126
|
-
return this.publicText.trim();
|
|
127
|
-
}
|
|
128
|
-
publishFallback(text) {
|
|
129
|
-
if (hasVisibleText(this.publicText)) {
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
this.publish(text);
|
|
133
|
-
}
|
|
134
|
-
publish(text) {
|
|
135
|
-
if (!this.onProgress || !hasVisibleText(text) || text === this.lastPublished) {
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
this.lastPublished = text;
|
|
139
|
-
this.onProgress({ text });
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
62
|
function createDeferredTurn(channelId, preparedTurn, sessionPersistence, options) {
|
|
143
63
|
let settled = false;
|
|
144
64
|
let resolvePromise;
|
|
@@ -647,7 +567,7 @@ export class CopilotCliClient {
|
|
|
647
567
|
}
|
|
648
568
|
}
|
|
649
569
|
async resolveSessionCwd(promptContext) {
|
|
650
|
-
return promptContext?.
|
|
570
|
+
return promptContext?.resolvedWorkspace?.rootPath ?? this.runtime.cwd;
|
|
651
571
|
}
|
|
652
572
|
async buildPromptInput(turn) {
|
|
653
573
|
const imageParts = turn.incomingParts.map(asImagePart).filter((part) => part !== null);
|
|
@@ -707,7 +627,7 @@ export class CopilotCliClient {
|
|
|
707
627
|
const promptFailure = new Promise((_, reject) => {
|
|
708
628
|
void promptPromise.catch((error) => reject(markSessionTainted(error)));
|
|
709
629
|
});
|
|
710
|
-
const collector = new
|
|
630
|
+
const collector = new AcpProgressCollector(options?.onProgress);
|
|
711
631
|
for (;;) {
|
|
712
632
|
let update;
|
|
713
633
|
try {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { DebugLogger } from '../debug.js';
|
|
2
2
|
import type { ProviderRuntimeConfig } from '../types.js';
|
|
3
|
+
import type { ChatControlPlane } from '../chat/chat-control-plane.js';
|
|
3
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';
|
|
@@ -7,6 +8,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';
|
|
@@ -52,7 +53,6 @@ class CliBackedProviderV2 {
|
|
|
52
53
|
}
|
|
53
54
|
class CopilotProviderV2 extends CliBackedProviderV2 {
|
|
54
55
|
}
|
|
55
|
-
const TASK_WORKSPACE_ROOT_DIR_ENV = 'AGENTS_HOST_INTERNAL_TASK_WORKSPACE_ROOT_DIR';
|
|
56
56
|
const PROVIDER_V2_COMPATIBILITY_GATES = {
|
|
57
57
|
copilot: COPILOT_PROVIDER_V2_COMPATIBILITY_GATE,
|
|
58
58
|
};
|
|
@@ -131,13 +131,29 @@ export function createProvider(config, debugLogger, options = {}) {
|
|
|
131
131
|
const channelContextStore = contextInjectionGateEnabled
|
|
132
132
|
? new FileChannelContextStore(config.stateRootDir, {
|
|
133
133
|
skillRuntimeEnabled: skillRuntimeGateEnabled,
|
|
134
|
-
taskWorkspaceRootDir: process.env[TASK_WORKSPACE_ROOT_DIR_ENV],
|
|
135
134
|
localhostGateway: skillRuntimeGateEnabled && localhostGatewayGateEnabled
|
|
136
135
|
? options.localhostGateway
|
|
137
136
|
: undefined,
|
|
137
|
+
taskReader: options.controlPlane,
|
|
138
138
|
})
|
|
139
139
|
: undefined;
|
|
140
|
-
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
|
+
});
|
|
141
157
|
switch (config.provider) {
|
|
142
158
|
case 'claude': {
|
|
143
159
|
return createClaudeProvider(config, debugLogger, connectionsStateGateEnabled, turnPreparer, idleBackendShutdownMs);
|
package/dist/state-paths.d.ts
CHANGED
|
@@ -20,11 +20,11 @@ export declare function resolveManagedDaemonLogPath(rootPath: string): string;
|
|
|
20
20
|
export declare function resolveManagedRuntimeSettingsPath(rootPath: string): string;
|
|
21
21
|
export declare function resolveManagedBootstrapLockPath(rootPath: string): string;
|
|
22
22
|
export declare function resolveLocalConfigAgentStateRoot(rootPath: string, agentKey: string): string;
|
|
23
|
-
export declare function resolveAgentCursorPath(stateRootDir: string, agentId: string): string;
|
|
24
23
|
export declare function resolveSharedProtocolKickoffDecisionPath(stateRootDir: string, channelId: string, anchorMessageId: string): string;
|
|
25
24
|
export declare function resolveSharedProtocolStatusPath(stateRootDir: string, channelId: string, anchorMessageId: string): string;
|
|
26
25
|
export declare function resolveConnectionsStatePath(stateRootDir: string): string;
|
|
27
26
|
export declare function resolveAttentionStatePath(stateRootDir: string, channelId: string): string;
|
|
27
|
+
export declare function resolveCompactionStatePath(stateRootDir: string, channelId: string): string;
|
|
28
28
|
export declare function resolveAuthorizationAuditPath(stateRootDir: string): string;
|
|
29
29
|
export declare function resolvePreviousAuthorizationAuditPath(stateRootDir: string): string;
|
|
30
30
|
export declare function resolveClaudeSessionMapPath(stateRootDir: string, agentId: string): string;
|
package/dist/state-paths.js
CHANGED
|
@@ -129,9 +129,6 @@ export function resolveManagedBootstrapLockPath(rootPath) {
|
|
|
129
129
|
export function resolveLocalConfigAgentStateRoot(rootPath, agentKey) {
|
|
130
130
|
return join(resolveManagedStateRoot(rootPath), `${sanitizeStateRootLabel(agentKey)}-${hashStateRootKey(agentKey)}`);
|
|
131
131
|
}
|
|
132
|
-
export function resolveAgentCursorPath(stateRootDir, agentId) {
|
|
133
|
-
return join(stateRootDir, `bpp-cursor-${encodeSegment(agentId)}.json`);
|
|
134
|
-
}
|
|
135
132
|
export function resolveSharedProtocolKickoffDecisionPath(stateRootDir, channelId, anchorMessageId) {
|
|
136
133
|
return join(dirname(resolve(stateRootDir)), 'protocol-kickoff-decisions', `${encodeSegment(channelId)}--${encodeSegment(anchorMessageId)}.json`);
|
|
137
134
|
}
|
|
@@ -144,6 +141,9 @@ export function resolveConnectionsStatePath(stateRootDir) {
|
|
|
144
141
|
export function resolveAttentionStatePath(stateRootDir, channelId) {
|
|
145
142
|
return join(stateRootDir, 'attention-state', `${encodeSegment(channelId)}.json`);
|
|
146
143
|
}
|
|
144
|
+
export function resolveCompactionStatePath(stateRootDir, channelId) {
|
|
145
|
+
return join(stateRootDir, 'compaction-state', `${encodeSegment(channelId)}.json`);
|
|
146
|
+
}
|
|
147
147
|
export function resolveAuthorizationAuditPath(stateRootDir) {
|
|
148
148
|
return join(stateRootDir, 'authorization-audit.jsonl');
|
|
149
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 {};
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export type ProviderKind = 'claude' | 'codex' | 'copilot';
|
|
2
|
+
export type ProjectionStrategy = 'session-brief' | 'turn-full' | 'message-only' | 'turn-thin' | 'file-brief';
|
|
2
3
|
export interface ProviderCommandConfig {
|
|
3
4
|
claudeCommand: string;
|
|
4
5
|
claudeArgs: string[];
|
|
@@ -167,7 +168,7 @@ export interface CollaborationDraftSnapshot {
|
|
|
167
168
|
}
|
|
168
169
|
export type ProviderCollaborationTurnMode = 'ordinary' | 'silent-kickoff' | 'protocol-managed';
|
|
169
170
|
export type CollaborationOutcomeResponseState = 'responded' | 'blocked' | 'superseded' | 'failed';
|
|
170
|
-
export type CollaborationOutcomeDeliveryState = 'posted' | '
|
|
171
|
+
export type CollaborationOutcomeDeliveryState = 'posted' | 'not-delivered' | 'delivery-failed';
|
|
171
172
|
export type CollaborationOutcomeWakeState = 'waiting' | 'suppressed-agent' | 'resumed-human';
|
|
172
173
|
export interface CollaborationOutcomeBlockedDetails {
|
|
173
174
|
question: string;
|
|
@@ -211,6 +212,22 @@ export interface AttentionSnapshot {
|
|
|
211
212
|
turnExecutionId?: string;
|
|
212
213
|
claimContext?: AttentionClaimContext;
|
|
213
214
|
}
|
|
215
|
+
export type ProviderCompactionStage = 'started' | 'completed' | 'failed';
|
|
216
|
+
/**
|
|
217
|
+
* Shared host-side projection only. This is the latest host-observed compaction
|
|
218
|
+
* lifecycle snapshot surfaced by a provider adapter; it is not provider- or
|
|
219
|
+
* model-authoritative truth about retained prompt content.
|
|
220
|
+
*/
|
|
221
|
+
export interface CompactionSnapshot {
|
|
222
|
+
source: 'host-observed';
|
|
223
|
+
provider: ProviderKind;
|
|
224
|
+
stage: ProviderCompactionStage;
|
|
225
|
+
observedAt: number;
|
|
226
|
+
turnExecutionId?: string;
|
|
227
|
+
usedTokens?: number;
|
|
228
|
+
contextWindowTokens?: number;
|
|
229
|
+
failureReason?: string;
|
|
230
|
+
}
|
|
214
231
|
export type TaskThreadCollaborationTurnRole = 'assignment' | 'continuation';
|
|
215
232
|
export type TaskThreadMainResultContract = 'ordinary-final-reply-in-thread';
|
|
216
233
|
export type TaskThreadAuxiliaryRouteContract = 'optional-auxiliary-send-or-escalation-only';
|
|
@@ -233,6 +250,7 @@ export interface TaskThreadCollaborationContract {
|
|
|
233
250
|
export interface CollaborationCapabilityDeclaration {
|
|
234
251
|
collaborationOutcome?: true;
|
|
235
252
|
attentionSnapshot?: true;
|
|
253
|
+
compactionSnapshot?: true;
|
|
236
254
|
taskThreadCollaborationContract?: true;
|
|
237
255
|
missedCollaborationDiagnostic?: true;
|
|
238
256
|
recoveryExplanation?: 'runtime-local-only';
|
|
@@ -264,6 +282,7 @@ export interface ProviderInput {
|
|
|
264
282
|
collaboration?: ProviderCollaborationContext;
|
|
265
283
|
collaborationOutcome?: CollaborationOutcomeSnapshot;
|
|
266
284
|
attentionSnapshot?: AttentionSnapshot;
|
|
285
|
+
compactionSnapshot?: CompactionSnapshot;
|
|
267
286
|
taskThreadCollaborationContract?: TaskThreadCollaborationContract;
|
|
268
287
|
collaborationCapabilities?: CollaborationCapabilityDeclaration;
|
|
269
288
|
missedCollaborationDiagnostic?: MissedCollaborationDiagnostic;
|
|
@@ -310,17 +329,52 @@ export interface TaskAssignmentThreadContext {
|
|
|
310
329
|
active: true;
|
|
311
330
|
currentTaskId?: string;
|
|
312
331
|
}
|
|
313
|
-
export interface
|
|
314
|
-
|
|
332
|
+
export interface ChannelResolvedWorkspaceContext {
|
|
333
|
+
authority: 'channel';
|
|
334
|
+
owningChannelId: string;
|
|
315
335
|
rootPath: string;
|
|
316
336
|
}
|
|
337
|
+
export interface TaskResolvedWorkspaceContext {
|
|
338
|
+
authority: 'task';
|
|
339
|
+
taskId: string;
|
|
340
|
+
rootPath: string;
|
|
341
|
+
}
|
|
342
|
+
export type ResolvedWorkspaceContext = ChannelResolvedWorkspaceContext | TaskResolvedWorkspaceContext;
|
|
343
|
+
export interface RuntimeSurface {
|
|
344
|
+
schemaVersion: 1;
|
|
345
|
+
turnMode: ProviderCollaborationTurnMode;
|
|
346
|
+
gateway: {
|
|
347
|
+
available: boolean;
|
|
348
|
+
readOnlyRoutesAuthorized: boolean;
|
|
349
|
+
inspectBeforeAnswer: boolean;
|
|
350
|
+
};
|
|
351
|
+
task: {
|
|
352
|
+
currentThread: 'parent-channel' | 'task-assignment-thread';
|
|
353
|
+
parentChannelTaskCollection: 'available' | 'parent-channel-only';
|
|
354
|
+
currentTaskShorthand: 'requires-task-id' | 'persisted-current-task' | 'fallback-current-task';
|
|
355
|
+
currentTaskIdPersisted: boolean;
|
|
356
|
+
currentTaskFallback: 'disallowed' | 'visible-parent-channel-thread-scan';
|
|
357
|
+
};
|
|
358
|
+
collaboration: {
|
|
359
|
+
participantLookup: 'unavailable' | 'available';
|
|
360
|
+
draftRead: 'unavailable' | 'available';
|
|
361
|
+
auxiliarySend: 'unavailable' | 'available';
|
|
362
|
+
};
|
|
363
|
+
response: {
|
|
364
|
+
mainVisibleReply: 'model-visible-reply' | 'host-visible-protocol-reply' | 'no-visible-reply';
|
|
365
|
+
auxiliaryMessageUsage: 'unavailable' | 'targeted-escalation-only';
|
|
366
|
+
};
|
|
367
|
+
}
|
|
317
368
|
export interface PreparedPromptContext {
|
|
318
369
|
channelContextPayloadPath?: string;
|
|
370
|
+
claudeProjectedBriefPath?: string;
|
|
371
|
+
claudeProjectedBriefHash?: string;
|
|
319
372
|
gatewayCredentialPath?: string;
|
|
320
373
|
collaborationTurnExecutionId?: string;
|
|
321
374
|
collaborationTurnMode?: ProviderCollaborationTurnMode;
|
|
322
375
|
collaborationOutcome?: CollaborationOutcomeSnapshot;
|
|
323
376
|
attentionSnapshot?: AttentionSnapshot;
|
|
377
|
+
compactionSnapshot?: CompactionSnapshot;
|
|
324
378
|
taskThreadCollaborationContract?: TaskThreadCollaborationContract;
|
|
325
379
|
collaborationCapabilities?: CollaborationCapabilityDeclaration;
|
|
326
380
|
missedCollaborationDiagnostic?: MissedCollaborationDiagnostic;
|
|
@@ -330,19 +384,25 @@ export interface PreparedPromptContext {
|
|
|
330
384
|
skillRuntime?: SkillRuntimeBootstrapMetadata;
|
|
331
385
|
localhostGateway?: LocalhostGatewayBootstrapMetadata;
|
|
332
386
|
taskAssignmentContext?: TaskAssignmentThreadContext;
|
|
333
|
-
|
|
387
|
+
resolvedWorkspace?: ResolvedWorkspaceContext;
|
|
388
|
+
runtimeSurface?: RuntimeSurface;
|
|
334
389
|
}
|
|
335
390
|
export interface PreparedProviderSessionRouting {
|
|
336
391
|
key: string;
|
|
337
392
|
persistence: 'persistent' | 'ephemeral';
|
|
338
393
|
}
|
|
339
394
|
export interface PreparedProviderTurnInput {
|
|
395
|
+
agentName?: string;
|
|
340
396
|
channelId: string;
|
|
341
397
|
incomingContent: string;
|
|
342
398
|
incomingParts: HostedTurnContentPart[];
|
|
343
399
|
incomingEventKind?: string;
|
|
344
400
|
incomingMessageType?: string;
|
|
345
401
|
prompt: string;
|
|
402
|
+
/** Claude-only session append content for ACP systemPrompt.append. */
|
|
403
|
+
claudeSessionPromptAppend?: string;
|
|
404
|
+
/** Shared projection-strategy selector used for provider prompt/session experiments. */
|
|
405
|
+
projectionStrategy?: ProjectionStrategy;
|
|
346
406
|
promptContext?: PreparedPromptContext;
|
|
347
407
|
providerSessionRouting?: PreparedProviderSessionRouting;
|
|
348
408
|
}
|
|
@@ -417,9 +477,73 @@ export interface UpdateTaskInput {
|
|
|
417
477
|
title?: string;
|
|
418
478
|
description?: string;
|
|
419
479
|
}
|
|
420
|
-
|
|
421
|
-
|
|
480
|
+
/** The protocol's ten tool kinds, treated as open: an unknown value is not an error. */
|
|
481
|
+
export type ProgressActivityKind = 'read' | 'edit' | 'delete' | 'move' | 'search' | 'execute' | 'think' | 'fetch' | 'switch_mode' | 'other';
|
|
482
|
+
/** The protocol's four statuses, plus the one it lacks: stopped, waiting on a human. */
|
|
483
|
+
export type ProgressActivityStatus = 'pending' | 'in_progress' | 'waiting' | 'completed' | 'failed';
|
|
484
|
+
/**
|
|
485
|
+
* One entry in an agent's timeline of work. Identity is minted by the producer:
|
|
486
|
+
* a producer that can correlate later progress to an earlier event reuses the
|
|
487
|
+
* id and the entry is patched in place; one that cannot mints a fresh id and
|
|
488
|
+
* entries accumulate. An absent field means unchanged; `paths` replaces.
|
|
489
|
+
*/
|
|
490
|
+
export interface ProgressActivity {
|
|
491
|
+
id: string;
|
|
492
|
+
/** The protocol's title. For a shell tool this is the raw command line. */
|
|
493
|
+
label?: string;
|
|
494
|
+
/** The provider's human-readable phrasing, when it offers one. */
|
|
495
|
+
description?: string;
|
|
496
|
+
kind?: ProgressActivityKind;
|
|
497
|
+
status?: ProgressActivityStatus;
|
|
498
|
+
/** Bounded one-line detail: the command, the file, the query. Never raw output. */
|
|
499
|
+
detail?: string;
|
|
500
|
+
/** Files this activity touched. Replaces the previous list. */
|
|
501
|
+
paths?: string[];
|
|
502
|
+
/** The activity that spawned this one. */
|
|
503
|
+
parentId?: string;
|
|
504
|
+
/**
|
|
505
|
+
* Whether this activity is a container for other work rather than work of its
|
|
506
|
+
* own. A reader nests under it, and cannot arrive at that by noticing it has
|
|
507
|
+
* children: a sub-agent's children can be reported before it is, and a
|
|
508
|
+
* sub-agent that has spawned nothing yet is still a sub-agent.
|
|
509
|
+
*/
|
|
510
|
+
subagent?: boolean;
|
|
511
|
+
/** Why a terminal activity ended as it did. An open set upstream, so never an enum. */
|
|
512
|
+
reason?: string;
|
|
422
513
|
}
|
|
514
|
+
/** Plan entries have no identity: the whole list is replaced on every update. */
|
|
515
|
+
export interface ProgressPlanItem {
|
|
516
|
+
label: string;
|
|
517
|
+
status: 'pending' | 'in_progress' | 'completed';
|
|
518
|
+
}
|
|
519
|
+
export interface ProviderCompactionProgress {
|
|
520
|
+
provider: ProviderKind;
|
|
521
|
+
stage: ProviderCompactionStage;
|
|
522
|
+
usedTokens?: number;
|
|
523
|
+
contextWindowTokens?: number;
|
|
524
|
+
failureReason?: string;
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* A plan, a tool call and a stream of text are three meanings with three
|
|
528
|
+
* cardinalities and three update rules, so they travel as three shapes rather
|
|
529
|
+
* than as one entry with a category field. Text is cumulative rather than a
|
|
530
|
+
* delta, so a consumer that misses one update recovers on the next.
|
|
531
|
+
*/
|
|
532
|
+
export type ProviderProgressUpdate = {
|
|
533
|
+
type: 'text';
|
|
534
|
+
stream: 'answer' | 'reasoning';
|
|
535
|
+
text: string;
|
|
536
|
+
messageId?: string;
|
|
537
|
+
} | {
|
|
538
|
+
type: 'activity';
|
|
539
|
+
activity: ProgressActivity;
|
|
540
|
+
} | {
|
|
541
|
+
type: 'plan';
|
|
542
|
+
items: ProgressPlanItem[];
|
|
543
|
+
} | {
|
|
544
|
+
type: 'compaction';
|
|
545
|
+
compaction: ProviderCompactionProgress;
|
|
546
|
+
};
|
|
423
547
|
export interface ProviderGenerateOptions {
|
|
424
548
|
onProgress?: (update: ProviderProgressUpdate) => void;
|
|
425
549
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@borgee/agents-host",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.56",
|
|
4
4
|
"private": false,
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"tsx": "^4.20.5",
|
|
36
36
|
"typescript": "^5.9.3",
|
|
37
37
|
"vitest": "^4.1.5",
|
|
38
|
-
"@borgee/plugin-sdk": "0.
|
|
38
|
+
"@borgee/plugin-sdk": "0.10.0"
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
|
41
41
|
"predev": "pnpm --filter @borgee/plugin-sdk build",
|
|
@@ -11,6 +11,14 @@ This turn is running as an agent inside a Borgee channel. The packaged CLI is th
|
|
|
11
11
|
|
|
12
12
|
Every command below is already authorized on a turn whose prompt names a gateway credential file. Run it directly. Never ask the user for permission first, and never end a turn having asked to read instead of reading.
|
|
13
13
|
|
|
14
|
+
## Session contract
|
|
15
|
+
|
|
16
|
+
This session is the coordination surface for the work that belongs to this Borgee thread: read the channel, answer the human here, break the work down, and keep task state current here.
|
|
17
|
+
|
|
18
|
+
Delegate the heavy execution to workers rather than running everything inline in this session. Research, code edits, long builds and test runs, and broad repository sweeps belong in delegated workers so a newly arriving message can still be handled promptly here.
|
|
19
|
+
|
|
20
|
+
Delegation changes who executes, not who owns. The work still belongs to this thread, and this session still reports the result here itself.
|
|
21
|
+
|
|
14
22
|
## When to use it
|
|
15
23
|
|
|
16
24
|
- You are asked what was said here, who is here, or what you are supposed to be working on: read it, do not guess.
|
|
@@ -56,7 +64,7 @@ Everything below writes that leading interpreter and script path as `borgee-agen
|
|
|
56
64
|
|
|
57
65
|
On `task get`, `task update`, `task set-property` and `task delete-property` the task id is an optional leading positional. Inside a task thread, omitting it addresses this thread's own task: the host's published binding names it, and where the host published none the gateway scans the parent channel's visible tasks for this thread instead — so pass the id explicitly when that scan cannot land on a single task. `task list` and `task create` are refused inside a task thread; they belong to the parent channel. In a parent channel every one of those ids is required, and omitting it answers `not_found`.
|
|
58
66
|
|
|
59
|
-
The keys `task set-property` and `task delete-property` accept are a closed set, and a value has a size limit: see `references/task-properties.md`.
|
|
67
|
+
The keys `task set-property` and `task delete-property` accept are a closed set, and a value has a size limit: see `references/task-properties.md`. In this slice, `workspace.mode` is the formal task-workspace switch: `inherit` keeps a task thread on its channel workspace, while `isolated` moves that task thread onto its own task workspace.
|
|
60
68
|
|
|
61
69
|
## What is available on a turn
|
|
62
70
|
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
# Task properties
|
|
2
2
|
|
|
3
|
-
A task property associates a task with something that lives outside it. Use one to record what a reader would otherwise have to hunt for in the thread — the pull request that implements the task, the issue it came from.
|
|
3
|
+
A task property associates a task with something that lives outside it, or with a closed task-level runtime choice. Use one to record what a reader would otherwise have to hunt for in the thread — the pull request that implements the task, the issue it came from, or the task workspace mode it should run with.
|
|
4
4
|
|
|
5
5
|
Read them back with `task get`: every task response carries a `properties` object, `{}` when the task has none.
|
|
6
6
|
|
|
7
7
|
```
|
|
8
8
|
borgee-agent --gateway <path> task set-property <task-id> --key link.pr --value https://github.com/org/repo/pull/12
|
|
9
9
|
borgee-agent --gateway <path> task delete-property <task-id> --key link.pr
|
|
10
|
+
borgee-agent --gateway <path> task set-property <task-id> --key workspace.mode --value isolated
|
|
11
|
+
borgee-agent --gateway <path> task delete-property <task-id> --key workspace.mode
|
|
10
12
|
```
|
|
11
13
|
|
|
12
14
|
The task id is omitted only inside that task's own thread, where the request resolves to the thread's task.
|
|
@@ -19,6 +21,7 @@ The key set is closed; writing an unregistered key is rejected with `unknown_pro
|
|
|
19
21
|
| --- | --- |
|
|
20
22
|
| `link.pr` | The pull request that implements this task. Set it as soon as the PR exists, not at the end. |
|
|
21
23
|
| `link.issue` | The issue or ticket the task originates from. |
|
|
24
|
+
| `workspace.mode` | The task workspace binding for task threads. `inherit` keeps the task on its channel workspace. `isolated` switches it to its task-isolated workspace. Deleting the key returns to the default `inherit` behavior. |
|
|
22
25
|
| `agent.session_id` | Do not write this. It is registered, so a write is accepted and lands — overwriting the host's record of which provider session worked this task. The host writes it itself after each turn. |
|
|
23
26
|
|
|
24
27
|
## One key per call
|
|
@@ -27,4 +30,4 @@ Each call writes exactly one key, and that is what makes it safe to write a prop
|
|
|
27
30
|
|
|
28
31
|
## Value
|
|
29
32
|
|
|
30
|
-
A value is a plain string of at most 8 KiB; a longer one is rejected with `property_value_too_long`. It is a reference — a URL, an identifier — never a document.
|
|
33
|
+
A value is a plain string of at most 8 KiB; a longer one is rejected with `property_value_too_long`. It is a reference — a URL, an identifier — never a document. Some registered keys are closed enums: `workspace.mode` accepts only `inherit` or `isolated`.
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { FileCursorStore } from './plugin-sdk.js';
|
|
2
|
-
import { resolveAgentCursorPath } from './state-paths.js';
|
|
3
|
-
export function createDurableCursorStore(options) {
|
|
4
|
-
return new FileCursorStore({
|
|
5
|
-
resolvePath: (agentId) => resolveAgentCursorPath(options.stateRootDir, agentId),
|
|
6
|
-
});
|
|
7
|
-
}
|