@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.
Files changed (84) hide show
  1. package/README.md +184 -21
  2. package/dist/agents-host-supervisor.d.ts +7 -5
  3. package/dist/agents-host-supervisor.js +24 -4
  4. package/dist/agents-host.d.ts +114 -15
  5. package/dist/agents-host.js +2712 -141
  6. package/dist/chat/chat-control-plane.d.ts +13 -2
  7. package/dist/chat/sdk-chat-control-plane.d.ts +14 -3
  8. package/dist/chat/sdk-chat-control-plane.js +54 -2
  9. package/dist/cli-args.d.ts +46 -5
  10. package/dist/cli-args.js +313 -32
  11. package/dist/cli.d.ts +9 -0
  12. package/dist/cli.js +112 -5
  13. package/dist/compatibility-gates.d.ts +39 -0
  14. package/dist/compatibility-gates.js +131 -0
  15. package/dist/config.d.ts +1 -0
  16. package/dist/config.js +23 -5
  17. package/dist/connections-state-store.d.ts +81 -0
  18. package/dist/connections-state-store.js +228 -0
  19. package/dist/context/attention.d.ts +12 -0
  20. package/dist/context/attention.js +137 -0
  21. package/dist/context/collaboration-capabilities-diagnostics.d.ts +3 -0
  22. package/dist/context/collaboration-capabilities-diagnostics.js +18 -0
  23. package/dist/context/collaboration-outcome.d.ts +2 -0
  24. package/dist/context/collaboration-outcome.js +26 -0
  25. package/dist/context/injection.d.ts +134 -0
  26. package/dist/context/injection.js +355 -0
  27. package/dist/context/prompt.d.ts +4 -1
  28. package/dist/context/prompt.js +231 -1
  29. package/dist/context/task-thread-collaboration.d.ts +6 -0
  30. package/dist/context/task-thread-collaboration.js +31 -0
  31. package/dist/context/turn-preparation.d.ts +9 -0
  32. package/dist/context/turn-preparation.js +135 -0
  33. package/dist/debug.d.ts +44 -0
  34. package/dist/debug.js +135 -0
  35. package/dist/gateway/localhost-gateway.d.ts +52 -0
  36. package/dist/gateway/localhost-gateway.js +857 -0
  37. package/dist/index.js +7 -5
  38. package/dist/local-config.d.ts +4 -1
  39. package/dist/local-config.js +24 -7
  40. package/dist/managed-daemon-log.d.ts +34 -0
  41. package/dist/managed-daemon-log.js +261 -0
  42. package/dist/managed-daemon.d.ts +220 -0
  43. package/dist/managed-daemon.js +1601 -0
  44. package/dist/policy/authorization-audit.d.ts +63 -0
  45. package/dist/policy/authorization-audit.js +94 -0
  46. package/dist/policy/copilot-permission.d.ts +15 -0
  47. package/dist/policy/copilot-permission.js +193 -0
  48. package/dist/policy/gateway-authorization.d.ts +42 -0
  49. package/dist/policy/gateway-authorization.js +162 -0
  50. package/dist/providers/awaiting-user.d.ts +12 -0
  51. package/dist/providers/awaiting-user.js +192 -0
  52. package/dist/providers/claude/adapter.d.ts +3 -1
  53. package/dist/providers/claude/adapter.js +8 -12
  54. package/dist/providers/claude/cli-client.d.ts +12 -5
  55. package/dist/providers/claude/cli-client.js +184 -37
  56. package/dist/providers/claude/session-store.d.ts +1 -0
  57. package/dist/providers/codex/adapter.d.ts +11 -0
  58. package/dist/providers/codex/adapter.js +19 -0
  59. package/dist/providers/codex/cli-client.d.ts +103 -0
  60. package/dist/providers/codex/cli-client.js +1133 -0
  61. package/dist/providers/codex/project-doc.d.ts +3 -0
  62. package/dist/providers/codex/project-doc.js +90 -0
  63. package/dist/providers/codex/session-store.d.ts +38 -0
  64. package/dist/providers/codex/session-store.js +150 -0
  65. package/dist/providers/copilot/adapter.d.ts +3 -1
  66. package/dist/providers/copilot/adapter.js +8 -12
  67. package/dist/providers/copilot/cli-client.d.ts +20 -2
  68. package/dist/providers/copilot/cli-client.js +251 -71
  69. package/dist/providers/copilot/session-store.d.ts +1 -0
  70. package/dist/providers/create-provider.d.ts +11 -2
  71. package/dist/providers/create-provider.js +131 -12
  72. package/dist/run.d.ts +1 -0
  73. package/dist/run.js +5 -2
  74. package/dist/state-paths.d.ts +14 -1
  75. package/dist/state-paths.js +87 -3
  76. package/dist/task-thread-resolution.d.ts +10 -0
  77. package/dist/task-thread-resolution.js +48 -0
  78. package/dist/types.d.ts +267 -1
  79. package/dist/visible-mentions.d.ts +3 -0
  80. package/dist/visible-mentions.js +15 -0
  81. package/package.json +19 -17
  82. package/skills/borgee-agent/SKILL.md +33 -0
  83. package/skills/borgee-agent/borgee-agent.mjs +473 -0
  84. package/skills/borgee-agent/borgee-agent.py +409 -0
@@ -0,0 +1,228 @@
1
+ import { chmodSync, mkdirSync } from 'node:fs';
2
+ import { createRequire } from 'node:module';
3
+ import { dirname } from 'node:path';
4
+ import { HostLogger, summarizeError } from './debug.js';
5
+ import { resolveConnectionsStatePath } from './state-paths.js';
6
+ const DEFAULT_BUSY_TIMEOUT_MS = 5_000;
7
+ const PRIVATE_STATE_FILE_MODE = 0o600;
8
+ const require = createRequire(import.meta.url);
9
+ function loadDatabaseSync() {
10
+ const sqliteModule = require('node:sqlite');
11
+ if (typeof sqliteModule.DatabaseSync !== 'function') {
12
+ throw new Error('node:sqlite DatabaseSync is unavailable');
13
+ }
14
+ return sqliteModule.DatabaseSync;
15
+ }
16
+ export class SqliteConnectionsStateStore {
17
+ options;
18
+ database = null;
19
+ closed = false;
20
+ constructor(options) {
21
+ this.options = options;
22
+ }
23
+ loadProviderSessions(provider, agentId) {
24
+ const rows = this.ensureDatabase().prepare(`SELECT channel_id, session_id
25
+ FROM provider_channel_sessions
26
+ WHERE provider = ? AND agent_id = ?
27
+ ORDER BY channel_id ASC`).all(provider, agentId);
28
+ return Object.fromEntries(rows.map((row) => [row.channel_id, row.session_id]));
29
+ }
30
+ saveProviderSessions(provider, agentId, sessions) {
31
+ const database = this.ensureDatabase();
32
+ const entries = Object.entries(sessions).sort(([left], [right]) => left.localeCompare(right));
33
+ database.exec('BEGIN IMMEDIATE');
34
+ try {
35
+ database.prepare(`DELETE FROM provider_channel_sessions
36
+ WHERE provider = ? AND agent_id = ?`).run(provider, agentId);
37
+ if (entries.length > 0) {
38
+ const insert = database.prepare(`INSERT INTO provider_channel_sessions (provider, agent_id, channel_id, session_id)
39
+ VALUES (?, ?, ?, ?)`);
40
+ for (const [channelId, sessionId] of entries) {
41
+ insert.run(provider, agentId, channelId, sessionId);
42
+ }
43
+ }
44
+ database.exec('COMMIT');
45
+ }
46
+ catch (error) {
47
+ database.exec('ROLLBACK');
48
+ throw error;
49
+ }
50
+ }
51
+ hasTokenBinding(token) {
52
+ const row = this.ensureDatabase().prepare(`SELECT 1
53
+ FROM channel_token_bindings
54
+ WHERE token = ?
55
+ LIMIT 1`).get(token);
56
+ return row != null;
57
+ }
58
+ loadTokenBinding(token) {
59
+ const row = this.ensureDatabase().prepare(`SELECT token, agent_id, channel_id
60
+ FROM channel_token_bindings
61
+ WHERE token = ? AND revoked_at IS NULL`).get(token);
62
+ if (!row) {
63
+ return null;
64
+ }
65
+ return {
66
+ token: row.token,
67
+ agentId: row.agent_id,
68
+ channelId: row.channel_id,
69
+ };
70
+ }
71
+ loadTokenBindingForChannel(agentId, channelId) {
72
+ const row = this.ensureDatabase().prepare(`SELECT token, agent_id, channel_id
73
+ FROM channel_token_bindings
74
+ WHERE agent_id = ? AND channel_id = ? AND revoked_at IS NULL
75
+ ORDER BY rowid DESC
76
+ LIMIT 1`).get(agentId, channelId);
77
+ if (!row) {
78
+ return null;
79
+ }
80
+ return {
81
+ token: row.token,
82
+ agentId: row.agent_id,
83
+ channelId: row.channel_id,
84
+ };
85
+ }
86
+ replaceTokenBinding(binding) {
87
+ const database = this.ensureDatabase();
88
+ database.exec('BEGIN IMMEDIATE');
89
+ try {
90
+ const bindingByToken = this.loadStoredTokenBinding(binding.token);
91
+ if (bindingByToken) {
92
+ if (bindingByToken.revokedAt != null) {
93
+ throw new Error(`channel token ${binding.token} was revoked and cannot be reused`);
94
+ }
95
+ if (bindingByToken.agentId !== binding.agentId || bindingByToken.channelId !== binding.channelId) {
96
+ throw new Error(`channel token is already bound to ${bindingByToken.agentId}/${bindingByToken.channelId}`);
97
+ }
98
+ }
99
+ database.prepare(`UPDATE channel_token_bindings
100
+ SET revoked_at = unixepoch()
101
+ WHERE agent_id = ? AND channel_id = ? AND token <> ? AND revoked_at IS NULL`).run(binding.agentId, binding.channelId, binding.token);
102
+ database.prepare(`INSERT INTO channel_token_bindings (token, agent_id, channel_id, revoked_at)
103
+ VALUES (?, ?, ?, NULL)
104
+ ON CONFLICT(token) DO UPDATE SET
105
+ agent_id = excluded.agent_id,
106
+ channel_id = excluded.channel_id,
107
+ revoked_at = NULL`).run(binding.token, binding.agentId, binding.channelId);
108
+ database.exec('COMMIT');
109
+ }
110
+ catch (error) {
111
+ database.exec('ROLLBACK');
112
+ throw error;
113
+ }
114
+ }
115
+ deleteTokenBinding(token) {
116
+ this.ensureDatabase().prepare(`DELETE FROM channel_token_bindings
117
+ WHERE token = ?`).run(token);
118
+ }
119
+ revokeTokenBinding(token) {
120
+ this.ensureDatabase().prepare(`UPDATE channel_token_bindings
121
+ SET revoked_at = unixepoch()
122
+ WHERE token = ? AND revoked_at IS NULL`).run(token);
123
+ }
124
+ revokeAllTokenBindings() {
125
+ this.ensureDatabase().exec('UPDATE channel_token_bindings SET revoked_at = unixepoch() WHERE revoked_at IS NULL');
126
+ }
127
+ close() {
128
+ this.database?.close();
129
+ this.database = null;
130
+ this.closed = true;
131
+ }
132
+ ensureDatabase() {
133
+ if (this.closed) {
134
+ throw new Error('connections state store is closed');
135
+ }
136
+ if (this.database) {
137
+ return this.database;
138
+ }
139
+ const path = (this.options.resolveDatabasePath ?? resolveConnectionsStatePath)(this.options.stateRootDir);
140
+ mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
141
+ const database = (this.options.openDatabase ?? ((databasePath) => new (loadDatabaseSync())(databasePath)))(path);
142
+ try {
143
+ chmodSync(path, PRIVATE_STATE_FILE_MODE);
144
+ database.exec(`PRAGMA busy_timeout = ${this.options.busyTimeoutMs ?? DEFAULT_BUSY_TIMEOUT_MS}`);
145
+ database.exec('PRAGMA journal_mode = DELETE');
146
+ database.exec(`CREATE TABLE IF NOT EXISTS provider_channel_sessions (
147
+ provider TEXT NOT NULL,
148
+ agent_id TEXT NOT NULL,
149
+ channel_id TEXT NOT NULL,
150
+ session_id TEXT NOT NULL,
151
+ PRIMARY KEY (provider, agent_id, channel_id)
152
+ )`);
153
+ database.exec(`CREATE TABLE IF NOT EXISTS channel_token_bindings (
154
+ token TEXT PRIMARY KEY,
155
+ agent_id TEXT NOT NULL,
156
+ channel_id TEXT NOT NULL,
157
+ revoked_at INTEGER
158
+ )`);
159
+ const columns = database.prepare(`SELECT name
160
+ FROM pragma_table_info('channel_token_bindings')
161
+ WHERE name = 'revoked_at'
162
+ LIMIT 1`).all();
163
+ if (columns.length === 0) {
164
+ database.exec('ALTER TABLE channel_token_bindings ADD COLUMN revoked_at INTEGER');
165
+ }
166
+ }
167
+ catch (error) {
168
+ database.close();
169
+ throw error;
170
+ }
171
+ this.database = database;
172
+ return database;
173
+ }
174
+ loadStoredTokenBinding(token) {
175
+ const row = this.ensureDatabase().prepare(`SELECT token, agent_id, channel_id, revoked_at
176
+ FROM channel_token_bindings
177
+ WHERE token = ?`).get(token);
178
+ if (!row) {
179
+ return null;
180
+ }
181
+ return {
182
+ token: row.token,
183
+ agentId: row.agent_id,
184
+ channelId: row.channel_id,
185
+ revokedAt: row.revoked_at,
186
+ };
187
+ }
188
+ }
189
+ export class ConnectionsStateBackedChannelSessionStore {
190
+ options;
191
+ logger;
192
+ constructor(options) {
193
+ this.options = options;
194
+ this.logger = options.logger ?? new HostLogger();
195
+ }
196
+ async load(agentId) {
197
+ return this.options.legacyStore.load(agentId);
198
+ }
199
+ async save(agentId, sessions) {
200
+ await this.options.legacyStore.save(agentId, sessions);
201
+ if (!this.options.sqliteStateStore) {
202
+ return;
203
+ }
204
+ try {
205
+ this.options.sqliteStateStore.saveProviderSessions(this.options.provider, agentId, sessions);
206
+ }
207
+ catch (error) {
208
+ this.logger.error(`failed to mirror ${this.options.provider} session map into connections state`, {
209
+ provider: this.options.provider,
210
+ error: summarizeError(error),
211
+ });
212
+ }
213
+ }
214
+ close() {
215
+ this.options.sqliteStateStore?.close();
216
+ this.options.legacyStore.close?.();
217
+ }
218
+ }
219
+ export function createProviderConnectionsSessionStore(options) {
220
+ return new ConnectionsStateBackedChannelSessionStore({
221
+ provider: options.provider,
222
+ legacyStore: options.legacyStore,
223
+ sqliteStateStore: options.gateEnabled
224
+ ? new SqliteConnectionsStateStore({ stateRootDir: options.stateRootDir })
225
+ : undefined,
226
+ logger: options.logger,
227
+ });
228
+ }
@@ -0,0 +1,12 @@
1
+ import type { AttentionClaimActivation, AttentionClaimContext, AttentionClaimState, AttentionDeliveryMode, AttentionSnapshot, AttentionWakeMode } from '../types.js';
2
+ export declare function deriveAttentionWakeMode(snapshot: Pick<AttentionSnapshot, 'deliveryMode' | 'claimState' | 'claimActivation'>): AttentionWakeMode;
3
+ export declare function buildNormalizedAttentionSnapshot(params?: {
4
+ deliveryMode?: AttentionDeliveryMode;
5
+ claimState?: AttentionClaimState;
6
+ claimActivation?: AttentionClaimActivation;
7
+ observedAt?: number;
8
+ turnExecutionId?: string;
9
+ claimContext?: AttentionClaimContext;
10
+ }): AttentionSnapshot;
11
+ export declare function parsePersistedAttentionSnapshot(raw: unknown): AttentionSnapshot;
12
+ export declare function buildAttentionSummaryLines(snapshot: AttentionSnapshot | undefined): string[];
@@ -0,0 +1,137 @@
1
+ function isRecord(value) {
2
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
3
+ }
4
+ function isDeliveryMode(value) {
5
+ return value === 'default' || value === 'follow' || value === 'muted';
6
+ }
7
+ function isClaimState(value) {
8
+ return value === 'unclaimed' || value === 'claimed';
9
+ }
10
+ function isClaimActivation(value) {
11
+ return value === 'inactive' || value === 'active' || value === 'dormant';
12
+ }
13
+ function isUsableTaskId(value) {
14
+ return value.length > 0 && !/[\u0000-\u001f\u007f\s]/u.test(value);
15
+ }
16
+ function normalizeClaimContext(value) {
17
+ if (!isRecord(value) || typeof value.scope !== 'string' || typeof value.taskId !== 'string') {
18
+ return undefined;
19
+ }
20
+ const taskId = value.taskId.trim();
21
+ if (value.scope === 'task-thread') {
22
+ return isUsableTaskId(taskId) ? { scope: 'task-thread', taskId } : undefined;
23
+ }
24
+ if (value.scope === 'channel') {
25
+ return isUsableTaskId(taskId) ? { scope: 'channel', taskId } : undefined;
26
+ }
27
+ return undefined;
28
+ }
29
+ export function deriveAttentionWakeMode(snapshot) {
30
+ if (snapshot.deliveryMode === 'muted') {
31
+ return 'mute-non-mention';
32
+ }
33
+ if (snapshot.deliveryMode === 'follow') {
34
+ return 'follow-visible-human';
35
+ }
36
+ if (snapshot.claimState === 'claimed' && snapshot.claimActivation === 'active') {
37
+ return 'follow-visible-human';
38
+ }
39
+ return 'current-policy';
40
+ }
41
+ export function buildNormalizedAttentionSnapshot(params) {
42
+ let deliveryMode = params?.deliveryMode ?? 'default';
43
+ let claimState = params?.claimState ?? 'unclaimed';
44
+ let claimActivation = params?.claimActivation ?? 'inactive';
45
+ let claimContext = params?.claimContext;
46
+ if (claimState === 'unclaimed') {
47
+ claimActivation = 'inactive';
48
+ claimContext = undefined;
49
+ }
50
+ else if (claimActivation === 'inactive') {
51
+ claimState = 'unclaimed';
52
+ claimContext = undefined;
53
+ }
54
+ if (claimActivation === 'dormant') {
55
+ deliveryMode = 'default';
56
+ }
57
+ if (claimContext?.scope === 'task-thread' && !isUsableTaskId(claimContext.taskId)) {
58
+ claimState = 'unclaimed';
59
+ claimActivation = 'inactive';
60
+ claimContext = undefined;
61
+ deliveryMode = 'default';
62
+ }
63
+ const snapshot = {
64
+ source: 'host-observed',
65
+ deliveryMode,
66
+ claimState,
67
+ claimActivation,
68
+ wakeMode: deriveAttentionWakeMode({
69
+ deliveryMode,
70
+ claimState,
71
+ claimActivation,
72
+ }),
73
+ observedAt: params?.observedAt ?? Date.now(),
74
+ ...(params?.turnExecutionId ? { turnExecutionId: params.turnExecutionId } : {}),
75
+ ...(claimContext ? { claimContext } : {}),
76
+ };
77
+ return snapshot;
78
+ }
79
+ export function parsePersistedAttentionSnapshot(raw) {
80
+ if (!isRecord(raw)) {
81
+ return buildNormalizedAttentionSnapshot();
82
+ }
83
+ const deliveryMode = isDeliveryMode(raw.deliveryMode) ? raw.deliveryMode : 'default';
84
+ const claimState = isClaimState(raw.claimState) ? raw.claimState : 'unclaimed';
85
+ const claimActivation = isClaimActivation(raw.claimActivation) ? raw.claimActivation : 'inactive';
86
+ const observedAt = typeof raw.observedAt === 'number' && Number.isFinite(raw.observedAt)
87
+ ? raw.observedAt
88
+ : Date.now();
89
+ const turnExecutionId = typeof raw.turnExecutionId === 'string' && raw.turnExecutionId.trim().length > 0
90
+ ? raw.turnExecutionId
91
+ : undefined;
92
+ const claimContext = normalizeClaimContext(raw.claimContext);
93
+ const normalized = buildNormalizedAttentionSnapshot({
94
+ deliveryMode,
95
+ claimState,
96
+ claimActivation,
97
+ observedAt,
98
+ turnExecutionId,
99
+ claimContext,
100
+ });
101
+ if (normalized.claimContext?.scope === 'task-thread') {
102
+ return buildNormalizedAttentionSnapshot({
103
+ deliveryMode: 'default',
104
+ claimState: normalized.claimState,
105
+ claimActivation: 'dormant',
106
+ observedAt: normalized.observedAt,
107
+ turnExecutionId: normalized.turnExecutionId,
108
+ claimContext: normalized.claimContext,
109
+ });
110
+ }
111
+ return normalized;
112
+ }
113
+ function formatObservedAt(observedAt) {
114
+ return new Date(observedAt).toISOString();
115
+ }
116
+ export function buildAttentionSummaryLines(snapshot) {
117
+ if (!snapshot) {
118
+ return [];
119
+ }
120
+ return [
121
+ 'Host-observed attention snapshot for this channel (projection only; not server-authoritative truth).',
122
+ `Delivery mode: ${snapshot.deliveryMode}`,
123
+ `Claim state: ${snapshot.claimState}`,
124
+ `Claim activation: ${snapshot.claimActivation}`,
125
+ `Wake mode: ${snapshot.wakeMode}`,
126
+ ...(snapshot.claimContext
127
+ ? [
128
+ `Claim scope: ${snapshot.claimContext.scope}`,
129
+ `Claim task id: ${snapshot.claimContext.taskId}`,
130
+ ]
131
+ : []),
132
+ `Observed at: ${formatObservedAt(snapshot.observedAt)}`,
133
+ ...(snapshot.turnExecutionId
134
+ ? [`Observed turn execution id: ${snapshot.turnExecutionId}`]
135
+ : []),
136
+ ];
137
+ }
@@ -0,0 +1,3 @@
1
+ import type { CollaborationCapabilityDeclaration, MissedCollaborationDiagnostic } from '../types.js';
2
+ export declare function buildCollaborationCapabilityDeclarationSummaryLines(declaration: CollaborationCapabilityDeclaration | undefined): string[];
3
+ export declare function buildMissedCollaborationDiagnosticSummaryLines(diagnostic: MissedCollaborationDiagnostic | undefined): string[];
@@ -0,0 +1,18 @@
1
+ export function buildCollaborationCapabilityDeclarationSummaryLines(declaration) {
2
+ if (!declaration) {
3
+ return [];
4
+ }
5
+ return [
6
+ 'Shared hosted collaboration capability declaration (projection only; hosted-path vocabulary only, not authorization, action availability, thread-binding authority, or standalone-runtime parity).',
7
+ `Capability declaration: ${JSON.stringify(declaration)}`,
8
+ ];
9
+ }
10
+ export function buildMissedCollaborationDiagnosticSummaryLines(diagnostic) {
11
+ if (!diagnostic) {
12
+ return [];
13
+ }
14
+ return [
15
+ 'Latest hosted missed-collaboration diagnostic (projection only; delivery, wake, or response explanation only).',
16
+ `Missed-collaboration diagnostic: ${JSON.stringify(diagnostic)}`,
17
+ ];
18
+ }
@@ -0,0 +1,2 @@
1
+ import type { CollaborationOutcomeSnapshot } from '../types.js';
2
+ export declare function buildCollaborationOutcomeSummaryLines(snapshot: CollaborationOutcomeSnapshot | undefined): string[];
@@ -0,0 +1,26 @@
1
+ function formatObservedAt(observedAt) {
2
+ return new Date(observedAt).toISOString();
3
+ }
4
+ export function buildCollaborationOutcomeSummaryLines(snapshot) {
5
+ if (!snapshot) {
6
+ return [];
7
+ }
8
+ return [
9
+ 'Host-observed collaboration outcome snapshot for this channel (projection only; not provider-authoritative truth).',
10
+ `Response state: ${snapshot.responseState}`,
11
+ `Delivery state: ${snapshot.deliveryState}`,
12
+ ...(snapshot.wakeState ? [`Wake state: ${snapshot.wakeState}`] : []),
13
+ ...(snapshot.blockedDetails
14
+ ? [
15
+ `Blocked question: ${snapshot.blockedDetails.question}`,
16
+ ...(snapshot.blockedDetails.reason
17
+ ? [`Blocked reason: ${snapshot.blockedDetails.reason}`]
18
+ : []),
19
+ ]
20
+ : []),
21
+ `Observed at: ${formatObservedAt(snapshot.observedAt)}`,
22
+ ...(snapshot.turnExecutionId
23
+ ? [`Observed turn execution id: ${snapshot.turnExecutionId}`]
24
+ : []),
25
+ ];
26
+ }
@@ -0,0 +1,134 @@
1
+ import type { AttentionSnapshot, CollaborationCapabilityDeclaration, CollaborationOutcomeSnapshot, LocalhostGatewayBootstrapMetadata, MissedCollaborationDiagnostic, ProviderCollaborationContext, SkillRuntimeBootstrapMetadata, TaskThreadCollaborationContract, TaskAssignmentThreadContext, TaskWorkspaceContext } from '../types.js';
2
+ export interface SkillRuntimeBootstrapPayload {
3
+ skillDirectoryPath: string;
4
+ nodeCliPath: string;
5
+ pythonCliPath: string;
6
+ }
7
+ export interface ChannelContextPayload {
8
+ schemaVersion: 1;
9
+ channelId: string;
10
+ collaborationOutcome?: CollaborationOutcomeSnapshot;
11
+ attentionSnapshot?: AttentionSnapshot;
12
+ taskThreadCollaborationContract?: TaskThreadCollaborationContract;
13
+ collaborationCapabilities?: CollaborationCapabilityDeclaration;
14
+ missedCollaborationDiagnostic?: MissedCollaborationDiagnostic;
15
+ skillRuntime?: SkillRuntimeBootstrapPayload;
16
+ localhostGateway?: LocalhostGatewayBootstrapMetadata;
17
+ taskAssignmentContext?: TaskAssignmentThreadContext;
18
+ taskWorkspace?: TaskWorkspaceContext;
19
+ }
20
+ export interface PreparedChannelContext {
21
+ directoryPath: string;
22
+ payload: ChannelContextPayload;
23
+ payloadPath?: string;
24
+ gatewayAuthPath?: string;
25
+ skillRuntime?: SkillRuntimeBootstrapMetadata;
26
+ localhostGateway?: LocalhostGatewayBootstrapMetadata;
27
+ taskWorkspace?: TaskWorkspaceContext;
28
+ }
29
+ export declare class ChannelContextPreparationError extends Error {
30
+ readonly partialContext: PreparedChannelContext;
31
+ constructor(message: string, partialContext: PreparedChannelContext, options?: ErrorOptions);
32
+ }
33
+ export interface ChannelContextStore {
34
+ prepare(input: {
35
+ channelId: string;
36
+ collaboration?: ProviderCollaborationContext;
37
+ collaborationOutcome?: CollaborationOutcomeSnapshot;
38
+ attentionSnapshot?: AttentionSnapshot;
39
+ taskThreadCollaborationContract?: TaskThreadCollaborationContract;
40
+ collaborationCapabilities?: CollaborationCapabilityDeclaration;
41
+ missedCollaborationDiagnostic?: MissedCollaborationDiagnostic;
42
+ incomingMessageType?: string;
43
+ incomingContent?: string;
44
+ }): Promise<PreparedChannelContext>;
45
+ prepare(channelId: string, options?: {
46
+ collaboration?: ProviderCollaborationContext;
47
+ collaborationOutcome?: CollaborationOutcomeSnapshot;
48
+ attentionSnapshot?: AttentionSnapshot;
49
+ taskThreadCollaborationContract?: TaskThreadCollaborationContract;
50
+ collaborationCapabilities?: CollaborationCapabilityDeclaration;
51
+ missedCollaborationDiagnostic?: MissedCollaborationDiagnostic;
52
+ incomingMessageType?: string;
53
+ incomingContent?: string;
54
+ }): Promise<PreparedChannelContext>;
55
+ }
56
+ export interface SkillAssetResolver {
57
+ resolve(): Promise<SkillRuntimeBootstrapMetadata>;
58
+ }
59
+ export interface LocalhostGatewayContextPublisher {
60
+ resolveBootstrap(channelId: string, options?: {
61
+ collaboration?: {
62
+ enabled: boolean;
63
+ turnExecutionId: string;
64
+ };
65
+ }): LocalhostGatewayBootstrapMetadata & {
66
+ token: string;
67
+ turnExecutionId?: string;
68
+ };
69
+ publishPayload(channelId: string, payloadPath: string, payload: ChannelContextPayload): void;
70
+ clearChannel(channelId: string): void;
71
+ }
72
+ interface ContextFileSystem {
73
+ mkdir(path: string, options?: {
74
+ mode?: number;
75
+ recursive?: boolean;
76
+ }): Promise<void>;
77
+ readdir(path: string): Promise<string[]>;
78
+ readFile(path: string, options: {
79
+ encoding: BufferEncoding;
80
+ } | BufferEncoding): Promise<string>;
81
+ writeFile(path: string, data: string, options?: {
82
+ encoding?: BufferEncoding;
83
+ mode?: number;
84
+ }): Promise<void>;
85
+ unlink(path: string): Promise<void>;
86
+ access(path: string): Promise<void>;
87
+ }
88
+ interface FileChannelContextStoreOptions {
89
+ fileSystem?: ContextFileSystem;
90
+ skillRuntimeEnabled?: boolean;
91
+ skillAssetResolver?: SkillAssetResolver;
92
+ localhostGateway?: LocalhostGatewayContextPublisher;
93
+ taskWorkspaceRootDir?: string;
94
+ }
95
+ export declare function extractTaskIdFromTaskAssignmentContent(incomingContent: string | undefined): string | undefined;
96
+ export declare function encodeChannelPathSegment(channelId: string): string;
97
+ export declare function resolveChannelContextDirectory(stateRootDir: string, channelId: string): string;
98
+ export declare function resolveChannelContextPayloadPath(stateRootDir: string, channelId: string): string;
99
+ export declare function resolveTaskWorkspaceRootDirectory(startupWorkspaceRootDir: string): string;
100
+ export declare function resolveTaskWorkspaceDirectory(startupWorkspaceRootDir: string, channelId: string, taskId: string): string;
101
+ export declare function resolveChannelContextGatewayAuthPath(stateRootDir: string, channelId: string, turnExecutionId?: string): string;
102
+ export declare function resolveGatewayAuthPathFromPayloadPath(payloadPath: string): string;
103
+ export declare function resolveBorgeeAgentSkillRuntimeAssets(moduleUrl: string, fileSystem?: Pick<ContextFileSystem, 'access'>): Promise<SkillRuntimeBootstrapMetadata>;
104
+ export declare class FileChannelContextStore implements ChannelContextStore {
105
+ private readonly stateRootDir;
106
+ private readonly fileSystem;
107
+ private readonly skillRuntimeEnabled;
108
+ private readonly skillAssetResolver;
109
+ private readonly localhostGateway?;
110
+ private readonly startupWorkspaceRootDir;
111
+ constructor(stateRootDir: string, options?: FileChannelContextStoreOptions);
112
+ prepare(inputOrChannelId: {
113
+ channelId: string;
114
+ collaboration?: ProviderCollaborationContext;
115
+ collaborationOutcome?: CollaborationOutcomeSnapshot;
116
+ attentionSnapshot?: AttentionSnapshot;
117
+ taskThreadCollaborationContract?: TaskThreadCollaborationContract;
118
+ collaborationCapabilities?: CollaborationCapabilityDeclaration;
119
+ missedCollaborationDiagnostic?: MissedCollaborationDiagnostic;
120
+ incomingMessageType?: string;
121
+ incomingContent?: string;
122
+ } | string, options?: {
123
+ collaboration?: ProviderCollaborationContext;
124
+ collaborationOutcome?: CollaborationOutcomeSnapshot;
125
+ attentionSnapshot?: AttentionSnapshot;
126
+ taskThreadCollaborationContract?: TaskThreadCollaborationContract;
127
+ collaborationCapabilities?: CollaborationCapabilityDeclaration;
128
+ missedCollaborationDiagnostic?: MissedCollaborationDiagnostic;
129
+ incomingMessageType?: string;
130
+ incomingContent?: string;
131
+ }): Promise<PreparedChannelContext>;
132
+ private resolveSkillRuntimeBestEffort;
133
+ }
134
+ export {};