@borgee/agents-host 0.2.35 → 0.2.44
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/dist/agents-host.d.ts +2 -0
- package/dist/agents-host.js +111 -44
- package/dist/chat/sdk-chat-control-plane.js +3 -0
- package/dist/context/injection.d.ts +5 -3
- package/dist/context/injection.js +45 -29
- package/dist/context/prompt.js +23 -35
- package/dist/context/skill-manual.d.ts +13 -0
- package/dist/context/skill-manual.js +18 -0
- package/dist/context/turn-preparation.js +13 -4
- package/dist/gateway/localhost-gateway.js +16 -8
- package/dist/hosted-turn-content.d.ts +15 -0
- package/dist/hosted-turn-content.js +50 -0
- package/dist/managed-daemon.d.ts +3 -2
- package/dist/managed-daemon.js +77 -29
- package/dist/providers/claude/adapter.d.ts +3 -1
- package/dist/providers/claude/adapter.js +10 -0
- package/dist/providers/claude/cli-client.d.ts +11 -2
- package/dist/providers/claude/cli-client.js +98 -27
- package/dist/providers/codex/adapter.d.ts +3 -1
- package/dist/providers/codex/adapter.js +10 -0
- package/dist/providers/codex/cli-client.d.ts +10 -2
- package/dist/providers/codex/cli-client.js +85 -21
- package/dist/providers/codex/project-doc.js +13 -29
- package/dist/providers/copilot/adapter.d.ts +3 -1
- package/dist/providers/copilot/adapter.js +10 -0
- package/dist/providers/copilot/cli-client.d.ts +9 -1
- package/dist/providers/copilot/cli-client.js +71 -8
- package/dist/providers/create-provider.d.ts +1 -1
- package/dist/providers/create-provider.js +16 -5
- package/dist/providers/provider-adapter.d.ts +35 -0
- package/dist/providers/provider-adapter.js +44 -1
- package/dist/state-paths.d.ts +9 -1
- package/dist/state-paths.js +22 -3
- package/dist/types.d.ts +33 -2
- package/package.json +1 -1
- package/skills/borgee-agent/SKILL.md +119 -38
- package/skills/borgee-agent/references/errors.md +38 -0
- package/skills/borgee-agent/references/task-properties.md +30 -0
- package/skills/borgee-agent/scripts/borgee-agent.mjs +553 -0
- package/skills/borgee-agent/scripts/borgee-agent.py +547 -0
- package/skills/borgee-agent/borgee-agent.mjs +0 -562
- package/skills/borgee-agent/borgee-agent.py +0 -469
|
@@ -1,562 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { readFile } from 'node:fs/promises';
|
|
4
|
-
|
|
5
|
-
const TASK_THREAD_COLLECTION_COMMAND_ERROR
|
|
6
|
-
= 'Task assignment threads only support --get-task, --update-task, --set-property and --delete-property. Create/list tasks belong to the parent channel.';
|
|
7
|
-
const TASK_THREAD_MISSING_TASK_ID_ERROR
|
|
8
|
-
= 'Task assignment thread could not resolve the current task from persisted context or local fallback. Pass --task-id explicitly.';
|
|
9
|
-
// A window value outside the IEEE-754 safe integer range does not survive this CLI: it parses
|
|
10
|
-
// the value to a number and re-stringifies it into the query string, so `1000000000000000000000`
|
|
11
|
-
// leaves as `1e+21` and the gateway's `Number.parseInt(value, 10)` reads it back as `1` — a
|
|
12
|
-
// different page, silently. Both packaged CLIs accept exactly this grammar.
|
|
13
|
-
const INTEGER_ARGUMENT_PATTERN = /^[+-]?[0-9]+$/;
|
|
14
|
-
|
|
15
|
-
function parseArgs(argv) {
|
|
16
|
-
let contextPath;
|
|
17
|
-
let authPath;
|
|
18
|
-
let turnExecutionId;
|
|
19
|
-
let action = 'print-bootstrap';
|
|
20
|
-
let limit;
|
|
21
|
-
let before;
|
|
22
|
-
let after;
|
|
23
|
-
let body;
|
|
24
|
-
let replyToId;
|
|
25
|
-
let mentionTargetId;
|
|
26
|
-
let title;
|
|
27
|
-
let description;
|
|
28
|
-
let assigneeId;
|
|
29
|
-
let taskId;
|
|
30
|
-
let status;
|
|
31
|
-
let propertyKey;
|
|
32
|
-
let propertyValue;
|
|
33
|
-
const mentions = [];
|
|
34
|
-
|
|
35
|
-
function setAction(nextAction) {
|
|
36
|
-
if (action !== 'print-bootstrap') {
|
|
37
|
-
throw new Error('Only one action flag may be used per invocation');
|
|
38
|
-
}
|
|
39
|
-
action = nextAction;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function parseIntegerOption(flag, value) {
|
|
43
|
-
if (value == null) {
|
|
44
|
-
throw new Error(`Missing value after ${flag}`);
|
|
45
|
-
}
|
|
46
|
-
if (!INTEGER_ARGUMENT_PATTERN.test(value)) {
|
|
47
|
-
throw new Error(`Invalid integer for ${flag}: ${value}`);
|
|
48
|
-
}
|
|
49
|
-
const parsed = Number(value);
|
|
50
|
-
if (!Number.isSafeInteger(parsed)) {
|
|
51
|
-
throw new Error(`Integer out of range for ${flag}: ${value}`);
|
|
52
|
-
}
|
|
53
|
-
return parsed;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
for (let index = 0; index < argv.length; index += 1) {
|
|
57
|
-
const arg = argv[index];
|
|
58
|
-
if (arg === '--context') {
|
|
59
|
-
contextPath = argv[index + 1];
|
|
60
|
-
index += 1;
|
|
61
|
-
continue;
|
|
62
|
-
}
|
|
63
|
-
if (arg === '--auth-path') {
|
|
64
|
-
authPath = argv[index + 1];
|
|
65
|
-
index += 1;
|
|
66
|
-
continue;
|
|
67
|
-
}
|
|
68
|
-
if (arg === '--turn-execution-id') {
|
|
69
|
-
turnExecutionId = argv[index + 1];
|
|
70
|
-
index += 1;
|
|
71
|
-
continue;
|
|
72
|
-
}
|
|
73
|
-
if (arg === '--print-bootstrap') {
|
|
74
|
-
action = 'print-bootstrap';
|
|
75
|
-
continue;
|
|
76
|
-
}
|
|
77
|
-
if (arg === '--health') {
|
|
78
|
-
setAction('health');
|
|
79
|
-
continue;
|
|
80
|
-
}
|
|
81
|
-
if (arg === '--read-bootstrap') {
|
|
82
|
-
setAction('read-bootstrap');
|
|
83
|
-
continue;
|
|
84
|
-
}
|
|
85
|
-
if (arg === '--get-me') {
|
|
86
|
-
setAction('get-me');
|
|
87
|
-
continue;
|
|
88
|
-
}
|
|
89
|
-
if (arg === '--read-history') {
|
|
90
|
-
setAction('read-history');
|
|
91
|
-
continue;
|
|
92
|
-
}
|
|
93
|
-
if (arg === '--read-task-history') {
|
|
94
|
-
setAction('read-task-history');
|
|
95
|
-
continue;
|
|
96
|
-
}
|
|
97
|
-
if (arg === '--read-draft') {
|
|
98
|
-
setAction('read-draft');
|
|
99
|
-
continue;
|
|
100
|
-
}
|
|
101
|
-
if (arg === '--list-users') {
|
|
102
|
-
setAction('list-users');
|
|
103
|
-
continue;
|
|
104
|
-
}
|
|
105
|
-
if (arg === '--send-message') {
|
|
106
|
-
setAction('send-message');
|
|
107
|
-
continue;
|
|
108
|
-
}
|
|
109
|
-
if (arg === '--send-mention') {
|
|
110
|
-
setAction('send-mention');
|
|
111
|
-
mentionTargetId = argv[index + 1];
|
|
112
|
-
index += 1;
|
|
113
|
-
continue;
|
|
114
|
-
}
|
|
115
|
-
if (arg === '--create-task') {
|
|
116
|
-
setAction('create-task');
|
|
117
|
-
continue;
|
|
118
|
-
}
|
|
119
|
-
if (arg === '--list-tasks') {
|
|
120
|
-
setAction('list-tasks');
|
|
121
|
-
continue;
|
|
122
|
-
}
|
|
123
|
-
if (arg === '--get-task') {
|
|
124
|
-
setAction('get-task');
|
|
125
|
-
continue;
|
|
126
|
-
}
|
|
127
|
-
if (arg === '--update-task') {
|
|
128
|
-
setAction('update-task');
|
|
129
|
-
continue;
|
|
130
|
-
}
|
|
131
|
-
if (arg === '--set-property') {
|
|
132
|
-
setAction('set-property');
|
|
133
|
-
// key=value in one token so the pair cannot be split across flags and
|
|
134
|
-
// land half-applied.
|
|
135
|
-
const pair = argv[index + 1];
|
|
136
|
-
if (pair == null || !pair.includes('=')) {
|
|
137
|
-
throw new Error('--set-property requires <key>=<value>');
|
|
138
|
-
}
|
|
139
|
-
const separator = pair.indexOf('=');
|
|
140
|
-
propertyKey = pair.slice(0, separator);
|
|
141
|
-
propertyValue = pair.slice(separator + 1);
|
|
142
|
-
if (propertyKey.trim().length === 0) {
|
|
143
|
-
throw new Error('--set-property requires a non-empty key');
|
|
144
|
-
}
|
|
145
|
-
index += 1;
|
|
146
|
-
continue;
|
|
147
|
-
}
|
|
148
|
-
if (arg === '--delete-property') {
|
|
149
|
-
setAction('delete-property');
|
|
150
|
-
propertyKey = argv[index + 1];
|
|
151
|
-
if (propertyKey == null || propertyKey.trim().length === 0) {
|
|
152
|
-
throw new Error('--delete-property requires a key');
|
|
153
|
-
}
|
|
154
|
-
index += 1;
|
|
155
|
-
continue;
|
|
156
|
-
}
|
|
157
|
-
if (arg === '--limit') {
|
|
158
|
-
limit = parseIntegerOption(arg, argv[index + 1]);
|
|
159
|
-
index += 1;
|
|
160
|
-
continue;
|
|
161
|
-
}
|
|
162
|
-
if (arg === '--before') {
|
|
163
|
-
before = parseIntegerOption(arg, argv[index + 1]);
|
|
164
|
-
index += 1;
|
|
165
|
-
continue;
|
|
166
|
-
}
|
|
167
|
-
if (arg === '--after') {
|
|
168
|
-
after = parseIntegerOption(arg, argv[index + 1]);
|
|
169
|
-
index += 1;
|
|
170
|
-
continue;
|
|
171
|
-
}
|
|
172
|
-
if (arg === '--body') {
|
|
173
|
-
body = argv[index + 1];
|
|
174
|
-
index += 1;
|
|
175
|
-
continue;
|
|
176
|
-
}
|
|
177
|
-
if (arg === '--reply-to') {
|
|
178
|
-
replyToId = argv[index + 1];
|
|
179
|
-
index += 1;
|
|
180
|
-
continue;
|
|
181
|
-
}
|
|
182
|
-
if (arg === '--mention') {
|
|
183
|
-
const mention = argv[index + 1];
|
|
184
|
-
if (mention == null || mention.trim().length === 0) {
|
|
185
|
-
throw new Error('Missing value after --mention');
|
|
186
|
-
}
|
|
187
|
-
mentions.push(mention.trim());
|
|
188
|
-
index += 1;
|
|
189
|
-
continue;
|
|
190
|
-
}
|
|
191
|
-
if (arg === '--title') {
|
|
192
|
-
title = argv[index + 1];
|
|
193
|
-
index += 1;
|
|
194
|
-
continue;
|
|
195
|
-
}
|
|
196
|
-
if (arg === '--description') {
|
|
197
|
-
description = argv[index + 1];
|
|
198
|
-
index += 1;
|
|
199
|
-
continue;
|
|
200
|
-
}
|
|
201
|
-
if (arg === '--assignee-id') {
|
|
202
|
-
assigneeId = argv[index + 1];
|
|
203
|
-
index += 1;
|
|
204
|
-
continue;
|
|
205
|
-
}
|
|
206
|
-
if (arg === '--task-id') {
|
|
207
|
-
taskId = argv[index + 1];
|
|
208
|
-
index += 1;
|
|
209
|
-
continue;
|
|
210
|
-
}
|
|
211
|
-
if (arg === '--status') {
|
|
212
|
-
status = argv[index + 1];
|
|
213
|
-
index += 1;
|
|
214
|
-
continue;
|
|
215
|
-
}
|
|
216
|
-
throw new Error(`Unknown argument: ${arg}`);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
if (!contextPath) {
|
|
220
|
-
throw new Error('Missing required --context <path> argument');
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
return {
|
|
224
|
-
contextPath,
|
|
225
|
-
authPath,
|
|
226
|
-
turnExecutionId: turnExecutionId?.trim(),
|
|
227
|
-
action,
|
|
228
|
-
limit,
|
|
229
|
-
before,
|
|
230
|
-
after,
|
|
231
|
-
body,
|
|
232
|
-
replyToId,
|
|
233
|
-
mentionTargetId: mentionTargetId?.trim(),
|
|
234
|
-
mentions,
|
|
235
|
-
title,
|
|
236
|
-
description,
|
|
237
|
-
assigneeId,
|
|
238
|
-
taskId,
|
|
239
|
-
status,
|
|
240
|
-
propertyKey: propertyKey?.trim(),
|
|
241
|
-
propertyValue,
|
|
242
|
-
};
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
function ensureVisibleMention(body, participantId) {
|
|
246
|
-
if (body.includes(`<@${participantId}>`)) {
|
|
247
|
-
return body;
|
|
248
|
-
}
|
|
249
|
-
const separator = /\s$/u.test(body) ? '' : ' ';
|
|
250
|
-
return `${body}${separator}<@${participantId}>`;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
function ensureVisibleMentions(body, participantIds) {
|
|
254
|
-
return participantIds.reduce(
|
|
255
|
-
(nextBody, participantId) => ensureVisibleMention(nextBody, participantId),
|
|
256
|
-
body,
|
|
257
|
-
);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
function explicitTaskId(options) {
|
|
261
|
-
const taskId = typeof options.taskId === 'string' ? options.taskId.trim() : '';
|
|
262
|
-
return taskId.length > 0 ? taskId : null;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
function missingTaskIdError(action) {
|
|
266
|
-
return new Error(`Missing required --task-id <value> for --${action}`);
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
function requireExplicitTaskId(action, options) {
|
|
270
|
-
const taskId = explicitTaskId(options);
|
|
271
|
-
if (taskId === null) {
|
|
272
|
-
throw missingTaskIdError(action);
|
|
273
|
-
}
|
|
274
|
-
return taskId;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
function applyHistoryWindow(url, options) {
|
|
278
|
-
if (options.limit != null) {
|
|
279
|
-
url.searchParams.set('limit', String(options.limit));
|
|
280
|
-
}
|
|
281
|
-
if (options.before != null) {
|
|
282
|
-
url.searchParams.set('before', String(options.before));
|
|
283
|
-
}
|
|
284
|
-
if (options.after != null) {
|
|
285
|
-
url.searchParams.set('after', String(options.after));
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
function resolveTaskId(payload, action, options) {
|
|
290
|
-
const taskId = explicitTaskId(options);
|
|
291
|
-
if (taskId !== null) {
|
|
292
|
-
return taskId;
|
|
293
|
-
}
|
|
294
|
-
if (payload.taskAssignmentContext?.active === true) {
|
|
295
|
-
const persistedTaskId = typeof payload.taskAssignmentContext.currentTaskId === 'string'
|
|
296
|
-
? payload.taskAssignmentContext.currentTaskId.trim()
|
|
297
|
-
: '';
|
|
298
|
-
if (persistedTaskId) {
|
|
299
|
-
return persistedTaskId;
|
|
300
|
-
}
|
|
301
|
-
return null;
|
|
302
|
-
}
|
|
303
|
-
throw missingTaskIdError(action);
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
function resolveGatewayRequest(payload, action, options) {
|
|
307
|
-
const gateway = payload.localhostGateway;
|
|
308
|
-
if (!gateway?.baseUrl) {
|
|
309
|
-
throw new Error('Missing localhostGateway bootstrap metadata in the context payload');
|
|
310
|
-
}
|
|
311
|
-
if ((action === 'create-task' || action === 'list-tasks') && payload.taskAssignmentContext?.active === true) {
|
|
312
|
-
throw new Error(TASK_THREAD_COLLECTION_COMMAND_ERROR);
|
|
313
|
-
}
|
|
314
|
-
const encodedChannelId = encodeURIComponent(String(payload.channelId ?? ''));
|
|
315
|
-
switch (action) {
|
|
316
|
-
case 'health':
|
|
317
|
-
return { url: new URL('/health', gateway.baseUrl), method: 'GET' };
|
|
318
|
-
case 'read-bootstrap':
|
|
319
|
-
return { url: new URL(`/v1/channels/${encodedChannelId}/bootstrap`, gateway.baseUrl), method: 'GET' };
|
|
320
|
-
case 'get-me':
|
|
321
|
-
return { url: new URL(`/v1/channels/${encodedChannelId}/me`, gateway.baseUrl), method: 'GET' };
|
|
322
|
-
case 'read-history': {
|
|
323
|
-
const url = new URL(`/v1/channels/${encodedChannelId}/history`, gateway.baseUrl);
|
|
324
|
-
applyHistoryWindow(url, options);
|
|
325
|
-
return { url, method: 'GET' };
|
|
326
|
-
}
|
|
327
|
-
case 'read-task-history': {
|
|
328
|
-
const taskId = requireExplicitTaskId(action, options);
|
|
329
|
-
const url = new URL(`/v1/tasks/${encodeURIComponent(taskId)}/history`, gateway.baseUrl);
|
|
330
|
-
applyHistoryWindow(url, options);
|
|
331
|
-
return { url, method: 'GET' };
|
|
332
|
-
}
|
|
333
|
-
case 'read-draft': {
|
|
334
|
-
if (!options.turnExecutionId || options.turnExecutionId.trim().length === 0) {
|
|
335
|
-
throw new Error('Missing required --turn-execution-id value for --read-draft');
|
|
336
|
-
}
|
|
337
|
-
const url = new URL(`/v1/channels/${encodedChannelId}/draft`, gateway.baseUrl);
|
|
338
|
-
url.searchParams.set('turnExecutionId', options.turnExecutionId.trim());
|
|
339
|
-
return { url, method: 'GET' };
|
|
340
|
-
}
|
|
341
|
-
case 'list-users':
|
|
342
|
-
return { url: new URL(`/v1/channels/${encodedChannelId}/users`, gateway.baseUrl), method: 'GET' };
|
|
343
|
-
case 'send-message':
|
|
344
|
-
case 'send-mention':
|
|
345
|
-
return { url: new URL(`/v1/channels/${encodedChannelId}/messages`, gateway.baseUrl), method: 'POST' };
|
|
346
|
-
case 'create-task': {
|
|
347
|
-
if (!options.title) {
|
|
348
|
-
throw new Error('Missing required --title <value> for --create-task');
|
|
349
|
-
}
|
|
350
|
-
return {
|
|
351
|
-
url: new URL(`/v1/channels/${encodedChannelId}/tasks`, gateway.baseUrl),
|
|
352
|
-
method: 'POST',
|
|
353
|
-
body: {
|
|
354
|
-
title: options.title,
|
|
355
|
-
...(options.description != null ? { description: options.description } : {}),
|
|
356
|
-
...(options.assigneeId != null ? { assigneeId: options.assigneeId } : {}),
|
|
357
|
-
},
|
|
358
|
-
};
|
|
359
|
-
}
|
|
360
|
-
case 'list-tasks':
|
|
361
|
-
return { url: new URL(`/v1/channels/${encodedChannelId}/tasks`, gateway.baseUrl), method: 'GET' };
|
|
362
|
-
case 'get-task': {
|
|
363
|
-
const taskId = resolveTaskId(payload, action, options);
|
|
364
|
-
if (payload.taskAssignmentContext?.active === true && explicitTaskId(options) === null) {
|
|
365
|
-
return {
|
|
366
|
-
url: new URL(`/v1/channels/${encodedChannelId}/current-task`, gateway.baseUrl),
|
|
367
|
-
method: 'GET',
|
|
368
|
-
usesCurrentThreadFallback: true,
|
|
369
|
-
};
|
|
370
|
-
}
|
|
371
|
-
return {
|
|
372
|
-
url: new URL(`/v1/tasks/${encodeURIComponent(taskId)}`, gateway.baseUrl),
|
|
373
|
-
method: 'GET',
|
|
374
|
-
usesCurrentThreadFallback: false,
|
|
375
|
-
};
|
|
376
|
-
}
|
|
377
|
-
case 'update-task': {
|
|
378
|
-
const taskId = resolveTaskId(payload, action, options);
|
|
379
|
-
const requestBody = {
|
|
380
|
-
...(options.status != null ? { status: options.status } : {}),
|
|
381
|
-
...(options.assigneeId != null ? { assigneeId: options.assigneeId } : {}),
|
|
382
|
-
...(options.title != null ? { title: options.title } : {}),
|
|
383
|
-
...(options.description != null ? { description: options.description } : {}),
|
|
384
|
-
};
|
|
385
|
-
if (Object.keys(requestBody).length === 0) {
|
|
386
|
-
throw new Error('At least one of --status, --assignee-id, --title, or --description is required for --update-task');
|
|
387
|
-
}
|
|
388
|
-
if (payload.taskAssignmentContext?.active === true && explicitTaskId(options) === null) {
|
|
389
|
-
return {
|
|
390
|
-
url: new URL(`/v1/channels/${encodedChannelId}/current-task`, gateway.baseUrl),
|
|
391
|
-
method: 'PATCH',
|
|
392
|
-
body: requestBody,
|
|
393
|
-
usesCurrentThreadFallback: true,
|
|
394
|
-
};
|
|
395
|
-
}
|
|
396
|
-
return {
|
|
397
|
-
url: new URL(`/v1/tasks/${encodeURIComponent(taskId)}`, gateway.baseUrl),
|
|
398
|
-
method: 'PATCH',
|
|
399
|
-
body: requestBody,
|
|
400
|
-
usesCurrentThreadFallback: false,
|
|
401
|
-
};
|
|
402
|
-
}
|
|
403
|
-
case 'set-property':
|
|
404
|
-
case 'delete-property': {
|
|
405
|
-
const taskId = resolveTaskId(payload, action, options);
|
|
406
|
-
const method = action === 'set-property' ? 'PUT' : 'DELETE';
|
|
407
|
-
const requestBody = action === 'set-property' ? { value: options.propertyValue } : undefined;
|
|
408
|
-
const encodedKey = encodeURIComponent(String(options.propertyKey ?? ''));
|
|
409
|
-
if (payload.taskAssignmentContext?.active === true && explicitTaskId(options) === null) {
|
|
410
|
-
return {
|
|
411
|
-
url: new URL(`/v1/channels/${encodedChannelId}/current-task/properties/${encodedKey}`, gateway.baseUrl),
|
|
412
|
-
method,
|
|
413
|
-
body: requestBody,
|
|
414
|
-
usesCurrentThreadFallback: true,
|
|
415
|
-
};
|
|
416
|
-
}
|
|
417
|
-
return {
|
|
418
|
-
url: new URL(`/v1/tasks/${encodeURIComponent(taskId)}/properties/${encodedKey}`, gateway.baseUrl),
|
|
419
|
-
method,
|
|
420
|
-
body: requestBody,
|
|
421
|
-
usesCurrentThreadFallback: false,
|
|
422
|
-
};
|
|
423
|
-
}
|
|
424
|
-
default:
|
|
425
|
-
throw new Error(`Unsupported gateway action: ${action}`);
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
async function readGatewayAuth(authPath, expectedChannelId) {
|
|
430
|
-
if (!authPath) {
|
|
431
|
-
throw new Error('Missing required --auth-path <path> argument for gateway access');
|
|
432
|
-
}
|
|
433
|
-
const authPayload = JSON.parse(await readFile(authPath, 'utf8'));
|
|
434
|
-
if (authPayload?.channelId !== expectedChannelId || !authPayload?.localhostGateway?.token) {
|
|
435
|
-
throw new Error('Missing localhost gateway auth payload for this channel');
|
|
436
|
-
}
|
|
437
|
-
return { token: authPayload.localhostGateway.token };
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
async function callGateway(payload, action, options) {
|
|
441
|
-
const request = resolveGatewayRequest(payload, action, options);
|
|
442
|
-
const auth = await readGatewayAuth(options.authPath, payload.channelId);
|
|
443
|
-
const httpRequest = {
|
|
444
|
-
method: request.method,
|
|
445
|
-
headers: auth.token
|
|
446
|
-
? {
|
|
447
|
-
authorization: `Bearer ${auth.token}`,
|
|
448
|
-
...(request.body || action === 'send-message' || action === 'send-mention'
|
|
449
|
-
? { 'content-type': 'application/json; charset=utf-8' }
|
|
450
|
-
: {}),
|
|
451
|
-
}
|
|
452
|
-
: undefined,
|
|
453
|
-
};
|
|
454
|
-
|
|
455
|
-
if (action === 'send-message' || action === 'send-mention') {
|
|
456
|
-
if (!options.body || options.body.trim().length === 0) {
|
|
457
|
-
throw new Error(`Missing required --body value for --${action}`);
|
|
458
|
-
}
|
|
459
|
-
if (!options.turnExecutionId || options.turnExecutionId.trim().length === 0) {
|
|
460
|
-
throw new Error(`Missing required --turn-execution-id value for --${action}`);
|
|
461
|
-
}
|
|
462
|
-
const requestMentions =
|
|
463
|
-
action === 'send-mention'
|
|
464
|
-
? [options.mentionTargetId?.trim()].filter(
|
|
465
|
-
(value) => typeof value === 'string' && value.length > 0,
|
|
466
|
-
)
|
|
467
|
-
: options.mentions;
|
|
468
|
-
if (action === 'send-mention' && requestMentions.length !== 1) {
|
|
469
|
-
throw new Error('Missing required target user id after --send-mention');
|
|
470
|
-
}
|
|
471
|
-
if (action === 'send-mention' && options.mentions.length > 0) {
|
|
472
|
-
throw new Error('Do not combine --send-mention with additional --mention flags');
|
|
473
|
-
}
|
|
474
|
-
const requestBody =
|
|
475
|
-
requestMentions.length > 0
|
|
476
|
-
? ensureVisibleMentions(options.body, requestMentions)
|
|
477
|
-
: options.body;
|
|
478
|
-
httpRequest.body = JSON.stringify({
|
|
479
|
-
body: requestBody,
|
|
480
|
-
replyToId: options.replyToId,
|
|
481
|
-
turnExecutionId: options.turnExecutionId,
|
|
482
|
-
});
|
|
483
|
-
} else if (request.body) {
|
|
484
|
-
httpRequest.body = JSON.stringify(request.body);
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
const response = await fetch(request.url, httpRequest);
|
|
488
|
-
const bodyText = await response.text();
|
|
489
|
-
const responseBody = bodyText.length > 0 ? JSON.parse(bodyText) : null;
|
|
490
|
-
if (!response.ok) {
|
|
491
|
-
if (responseBody?.error === 'not_found' && request.usesCurrentThreadFallback === true) {
|
|
492
|
-
throw new Error(TASK_THREAD_MISSING_TASK_ID_ERROR);
|
|
493
|
-
}
|
|
494
|
-
throw new Error(`Gateway request failed with ${response.status}: ${JSON.stringify(responseBody)}`);
|
|
495
|
-
}
|
|
496
|
-
return responseBody;
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
function redactBootstrap(payload, contextPath) {
|
|
500
|
-
return {
|
|
501
|
-
kind: 'borgee-agent-skill-bootstrap',
|
|
502
|
-
contextPath,
|
|
503
|
-
channelId: payload.channelId,
|
|
504
|
-
skillRuntime: payload.skillRuntime ?? null,
|
|
505
|
-
taskAssignmentContext: payload.taskAssignmentContext ?? null,
|
|
506
|
-
localhostGateway: payload.localhostGateway?.baseUrl
|
|
507
|
-
? {
|
|
508
|
-
baseUrl: payload.localhostGateway.baseUrl,
|
|
509
|
-
...(payload.localhostGateway.collaboration
|
|
510
|
-
? { collaboration: payload.localhostGateway.collaboration }
|
|
511
|
-
: {}),
|
|
512
|
-
}
|
|
513
|
-
: null,
|
|
514
|
-
};
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
const {
|
|
518
|
-
contextPath,
|
|
519
|
-
authPath,
|
|
520
|
-
turnExecutionId,
|
|
521
|
-
action,
|
|
522
|
-
limit,
|
|
523
|
-
before,
|
|
524
|
-
after,
|
|
525
|
-
body,
|
|
526
|
-
replyToId,
|
|
527
|
-
mentionTargetId,
|
|
528
|
-
mentions,
|
|
529
|
-
title,
|
|
530
|
-
description,
|
|
531
|
-
assigneeId,
|
|
532
|
-
taskId,
|
|
533
|
-
status,
|
|
534
|
-
propertyKey,
|
|
535
|
-
propertyValue,
|
|
536
|
-
} = parseArgs(process.argv.slice(2));
|
|
537
|
-
const payload = JSON.parse(await readFile(contextPath, 'utf8'));
|
|
538
|
-
|
|
539
|
-
if (action === 'print-bootstrap') {
|
|
540
|
-
console.log(JSON.stringify(redactBootstrap(payload, contextPath), null, 2));
|
|
541
|
-
} else {
|
|
542
|
-
const result = await callGateway(payload, action, {
|
|
543
|
-
contextPath,
|
|
544
|
-
authPath,
|
|
545
|
-
turnExecutionId,
|
|
546
|
-
limit,
|
|
547
|
-
before,
|
|
548
|
-
after,
|
|
549
|
-
body,
|
|
550
|
-
replyToId,
|
|
551
|
-
mentionTargetId,
|
|
552
|
-
mentions,
|
|
553
|
-
title,
|
|
554
|
-
description,
|
|
555
|
-
assigneeId,
|
|
556
|
-
taskId,
|
|
557
|
-
status,
|
|
558
|
-
propertyKey,
|
|
559
|
-
propertyValue,
|
|
560
|
-
});
|
|
561
|
-
console.log(JSON.stringify(result, null, 2));
|
|
562
|
-
}
|