@borgee/agents-host 0.2.2 → 0.2.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +184 -21
- package/dist/agents-host-supervisor.d.ts +7 -5
- package/dist/agents-host-supervisor.js +24 -4
- package/dist/agents-host.d.ts +114 -15
- package/dist/agents-host.js +2712 -141
- package/dist/chat/chat-control-plane.d.ts +13 -2
- package/dist/chat/sdk-chat-control-plane.d.ts +14 -3
- package/dist/chat/sdk-chat-control-plane.js +54 -2
- package/dist/cli-args.d.ts +46 -5
- package/dist/cli-args.js +313 -32
- package/dist/cli.d.ts +9 -0
- package/dist/cli.js +112 -5
- package/dist/compatibility-gates.d.ts +39 -0
- package/dist/compatibility-gates.js +131 -0
- package/dist/config.d.ts +1 -0
- package/dist/config.js +23 -5
- package/dist/connections-state-store.d.ts +81 -0
- package/dist/connections-state-store.js +228 -0
- package/dist/context/attention.d.ts +12 -0
- package/dist/context/attention.js +137 -0
- package/dist/context/collaboration-capabilities-diagnostics.d.ts +3 -0
- package/dist/context/collaboration-capabilities-diagnostics.js +18 -0
- package/dist/context/collaboration-outcome.d.ts +2 -0
- package/dist/context/collaboration-outcome.js +26 -0
- package/dist/context/injection.d.ts +134 -0
- package/dist/context/injection.js +355 -0
- package/dist/context/prompt.d.ts +4 -1
- package/dist/context/prompt.js +231 -1
- package/dist/context/task-thread-collaboration.d.ts +6 -0
- package/dist/context/task-thread-collaboration.js +31 -0
- package/dist/context/turn-preparation.d.ts +9 -0
- package/dist/context/turn-preparation.js +135 -0
- package/dist/debug.d.ts +44 -0
- package/dist/debug.js +135 -0
- package/dist/gateway/localhost-gateway.d.ts +52 -0
- package/dist/gateway/localhost-gateway.js +857 -0
- package/dist/index.js +7 -5
- package/dist/local-config.d.ts +4 -1
- package/dist/local-config.js +24 -7
- package/dist/managed-daemon-log.d.ts +34 -0
- package/dist/managed-daemon-log.js +261 -0
- package/dist/managed-daemon.d.ts +220 -0
- package/dist/managed-daemon.js +1601 -0
- package/dist/policy/authorization-audit.d.ts +63 -0
- package/dist/policy/authorization-audit.js +94 -0
- package/dist/policy/copilot-permission.d.ts +15 -0
- package/dist/policy/copilot-permission.js +193 -0
- package/dist/policy/gateway-authorization.d.ts +42 -0
- package/dist/policy/gateway-authorization.js +162 -0
- package/dist/providers/awaiting-user.d.ts +12 -0
- package/dist/providers/awaiting-user.js +192 -0
- package/dist/providers/claude/adapter.d.ts +3 -1
- package/dist/providers/claude/adapter.js +8 -12
- package/dist/providers/claude/cli-client.d.ts +12 -5
- package/dist/providers/claude/cli-client.js +184 -37
- package/dist/providers/claude/session-store.d.ts +1 -0
- package/dist/providers/codex/adapter.d.ts +11 -0
- package/dist/providers/codex/adapter.js +19 -0
- package/dist/providers/codex/cli-client.d.ts +103 -0
- package/dist/providers/codex/cli-client.js +1133 -0
- package/dist/providers/codex/project-doc.d.ts +3 -0
- package/dist/providers/codex/project-doc.js +90 -0
- package/dist/providers/codex/session-store.d.ts +38 -0
- package/dist/providers/codex/session-store.js +150 -0
- package/dist/providers/copilot/adapter.d.ts +3 -1
- package/dist/providers/copilot/adapter.js +8 -12
- package/dist/providers/copilot/cli-client.d.ts +20 -2
- package/dist/providers/copilot/cli-client.js +251 -71
- package/dist/providers/copilot/session-store.d.ts +1 -0
- package/dist/providers/create-provider.d.ts +11 -2
- package/dist/providers/create-provider.js +131 -12
- package/dist/run.d.ts +1 -0
- package/dist/run.js +5 -2
- package/dist/state-paths.d.ts +14 -1
- package/dist/state-paths.js +87 -3
- package/dist/task-thread-resolution.d.ts +10 -0
- package/dist/task-thread-resolution.js +48 -0
- package/dist/types.d.ts +267 -1
- package/dist/visible-mentions.d.ts +3 -0
- package/dist/visible-mentions.js +15 -0
- package/package.json +19 -17
- package/skills/borgee-agent/SKILL.md +33 -0
- package/skills/borgee-agent/borgee-agent.mjs +473 -0
- package/skills/borgee-agent/borgee-agent.py +409 -0
|
@@ -0,0 +1,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,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 {};
|