skydive-cli 0.1.0 → 0.2.0-beta.421
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/CHANGELOG.md +68 -0
- package/README.md +271 -28
- package/dist/js/api-CDTKq_5Q.mjs +145 -0
- package/dist/js/bin.mjs +1752 -1359
- package/dist/js/boot-CQLDUeZ9.mjs +9827 -0
- package/dist/js/client-B3ZhhF7e.mjs +366 -0
- package/dist/js/client-CpEvH2Pq.mjs +169 -0
- package/dist/js/client-D6NAkL9e.mjs +6 -0
- package/dist/js/output-B4cW10Ph.mjs +27 -0
- package/dist/js/print-B6AO13SA.mjs +5 -0
- package/dist/js/print-DausK_KZ.mjs +484 -0
- package/dist/js/print-share-D7OSxvE2.mjs +41 -0
- package/dist/js/raw-pty-2_VA1kw_.mjs +5 -0
- package/dist/js/raw-pty-GAvxm2ol.mjs +99 -0
- package/dist/js/rest-COkLEZOB.mjs +4 -0
- package/dist/js/{print-BHbFMxQv.mjs → rest-CamHVOce.mjs} +173 -158
- package/dist/js/theme-CuQhvqzN.mjs +990 -0
- package/dist/js/util-CeisaZVY.mjs +15 -0
- package/package.json +20 -9
- package/dist/js/boot-ChlVx-ts.mjs +0 -5525
|
@@ -2,23 +2,6 @@
|
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { createParser } from "eventsource-parser";
|
|
4
4
|
|
|
5
|
-
//#region \0rolldown/runtime.js
|
|
6
|
-
var __defProp = Object.defineProperty;
|
|
7
|
-
var __exportAll = (all, no_symbols) => {
|
|
8
|
-
let target = {};
|
|
9
|
-
for (var name in all) {
|
|
10
|
-
__defProp(target, name, {
|
|
11
|
-
get: all[name],
|
|
12
|
-
enumerable: true
|
|
13
|
-
});
|
|
14
|
-
}
|
|
15
|
-
if (!no_symbols) {
|
|
16
|
-
__defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
17
|
-
}
|
|
18
|
-
return target;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
//#endregion
|
|
22
5
|
//#region src/chat/api/rest.ts
|
|
23
6
|
var HttpError = class extends Error {
|
|
24
7
|
constructor(status, body) {
|
|
@@ -28,6 +11,20 @@ var HttpError = class extends Error {
|
|
|
28
11
|
this.name = "HttpError";
|
|
29
12
|
}
|
|
30
13
|
};
|
|
14
|
+
const ERROR_DETAIL_MAX_BODY = 2e3;
|
|
15
|
+
/**
|
|
16
|
+
* Fullest renderable text for a thrown value. `HttpError.message` clips the
|
|
17
|
+
* response body to 200 chars (it flows into logs and one-line UIs); the
|
|
18
|
+
* transcript renders errors collapsed to a single line, so it can afford the
|
|
19
|
+
* whole body — capped with an explicit marker, never cut silently.
|
|
20
|
+
*/
|
|
21
|
+
function errorDetail(err) {
|
|
22
|
+
if (err instanceof HttpError) {
|
|
23
|
+
const body = err.body.length > ERROR_DETAIL_MAX_BODY ? `${err.body.slice(0, ERROR_DETAIL_MAX_BODY)}… (+${err.body.length - ERROR_DETAIL_MAX_BODY} chars)` : err.body;
|
|
24
|
+
return body ? `HTTP ${err.status}: ${body}` : `HTTP ${err.status}`;
|
|
25
|
+
}
|
|
26
|
+
return err instanceof Error ? err.message : String(err);
|
|
27
|
+
}
|
|
31
28
|
const MAX_STREAM_RECONNECTS = 5;
|
|
32
29
|
function createRestClient({ appUrl, sessionToken }) {
|
|
33
30
|
const baseHeaders = {
|
|
@@ -58,6 +55,65 @@ function createRestClient({ appUrl, sessionToken }) {
|
|
|
58
55
|
});
|
|
59
56
|
if (!res.ok) throw new HttpError(res.status, await res.text().catch(() => ""));
|
|
60
57
|
}
|
|
58
|
+
const streamEvents = async ({ path, label, signal, onEvent }) => {
|
|
59
|
+
let lastEventId = null;
|
|
60
|
+
let finished = false;
|
|
61
|
+
let reconnects = 0;
|
|
62
|
+
for (;;) {
|
|
63
|
+
if (signal.aborted) return;
|
|
64
|
+
try {
|
|
65
|
+
const headers = {
|
|
66
|
+
authorization: `Bearer ${sessionToken}`,
|
|
67
|
+
accept: "text/event-stream"
|
|
68
|
+
};
|
|
69
|
+
if (lastEventId) headers["last-event-id"] = lastEventId;
|
|
70
|
+
const res = await fetch(`${appUrl}${path}`, {
|
|
71
|
+
headers,
|
|
72
|
+
signal
|
|
73
|
+
});
|
|
74
|
+
if (!res.ok || !res.body) throw new HttpError(res.status, await res.text().catch(() => ""));
|
|
75
|
+
reconnects = 0;
|
|
76
|
+
const parser = createParser({ onEvent: (message) => {
|
|
77
|
+
if (message.id) lastEventId = message.id;
|
|
78
|
+
if (message.event === "error") {
|
|
79
|
+
const { error } = streamErrorSchema.parse(JSON.parse(message.data));
|
|
80
|
+
throw new Error(error);
|
|
81
|
+
}
|
|
82
|
+
const event = runStreamEventSchema.parse(JSON.parse(message.data));
|
|
83
|
+
if (event.kind === "finished") finished = true;
|
|
84
|
+
onEvent(event.kind === "finished" ? {
|
|
85
|
+
...event,
|
|
86
|
+
error: event.error ?? null
|
|
87
|
+
} : event);
|
|
88
|
+
} });
|
|
89
|
+
const decoder = new TextDecoder();
|
|
90
|
+
const reader = res.body.getReader();
|
|
91
|
+
try {
|
|
92
|
+
for (;;) {
|
|
93
|
+
const { done, value } = await reader.read();
|
|
94
|
+
if (done) break;
|
|
95
|
+
parser.feed(decoder.decode(value, { stream: true }));
|
|
96
|
+
if (finished) return;
|
|
97
|
+
}
|
|
98
|
+
} finally {
|
|
99
|
+
try {
|
|
100
|
+
await reader.cancel();
|
|
101
|
+
} catch (_error) {}
|
|
102
|
+
}
|
|
103
|
+
} catch (err) {
|
|
104
|
+
if (signal.aborted) return;
|
|
105
|
+
if (err instanceof HttpError && err.status >= 400 && err.status < 500) throw err;
|
|
106
|
+
reconnects += 1;
|
|
107
|
+
if (reconnects > MAX_STREAM_RECONNECTS) throw err;
|
|
108
|
+
await sleep(Math.min(500 * 2 ** reconnects, 5e3));
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
if (finished) return;
|
|
112
|
+
reconnects += 1;
|
|
113
|
+
if (reconnects > MAX_STREAM_RECONNECTS) throw new Error(`${label} stream ended unexpectedly`);
|
|
114
|
+
await sleep(Math.min(500 * 2 ** reconnects, 5e3));
|
|
115
|
+
}
|
|
116
|
+
};
|
|
61
117
|
return {
|
|
62
118
|
listAgents: async ({ scope, onPage }) => {
|
|
63
119
|
const all = [];
|
|
@@ -94,19 +150,51 @@ function createRestClient({ appUrl, sessionToken }) {
|
|
|
94
150
|
const { agent } = await post(`/api/v1/agents/${encodeURIComponent(agentId)}`, { model }, updateAgentResponseSchema, "PATCH");
|
|
95
151
|
return { model: agent.model ?? null };
|
|
96
152
|
},
|
|
97
|
-
listConversations: async ({ agentId, limit }) => {
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
153
|
+
listConversations: async ({ agentId, limit, channels, onPage }) => {
|
|
154
|
+
const all = [];
|
|
155
|
+
const maxConversations = limit ?? 5e3;
|
|
156
|
+
let cursor;
|
|
157
|
+
do {
|
|
158
|
+
const remaining = maxConversations - all.length;
|
|
159
|
+
const params = new URLSearchParams({
|
|
160
|
+
agentId,
|
|
161
|
+
includeTotal: "false"
|
|
162
|
+
});
|
|
163
|
+
params.set("limit", String(Math.min(remaining, 100)));
|
|
164
|
+
if (cursor) params.set("cursor", cursor);
|
|
165
|
+
for (const channel of channels ?? []) params.append("channels", channel);
|
|
166
|
+
const page = await get(`/api/v1/conversations?${params.toString()}`, listConversationsResponseSchema);
|
|
167
|
+
all.push(...page.conversations);
|
|
168
|
+
cursor = page.nextCursor ?? void 0;
|
|
169
|
+
onPage?.(limit ? all.slice(0, limit) : [...all]);
|
|
170
|
+
} while (cursor && all.length < maxConversations);
|
|
171
|
+
return limit ? all.slice(0, limit) : all;
|
|
105
172
|
},
|
|
106
173
|
listMessages: async ({ conversationId }) => {
|
|
107
174
|
const { messages } = await get(`/api/v1/conversations/${encodeURIComponent(conversationId)}/messages`, listMessagesResponseSchema);
|
|
108
175
|
return messages;
|
|
109
176
|
},
|
|
177
|
+
listWorkspaceFiles: async ({ agentId }) => {
|
|
178
|
+
const { files } = await get(`/api/v1/workspace-files?${new URLSearchParams({ agentId }).toString()}`, listWorkspaceFilesResponseSchema);
|
|
179
|
+
return files;
|
|
180
|
+
},
|
|
181
|
+
readWorkspaceFile: async ({ fileId, maxBytes = 512 * 1024 }) => {
|
|
182
|
+
const res = await fetch(`${appUrl}/api/v1/workspace-files/${encodeURIComponent(fileId)}/download?disposition=inline`, { headers: {
|
|
183
|
+
...baseHeaders,
|
|
184
|
+
Range: `bytes=0-${maxBytes}`
|
|
185
|
+
} });
|
|
186
|
+
if (!res.ok) throw new HttpError(res.status, await res.text().catch(() => ""));
|
|
187
|
+
const bytes = new Uint8Array(await res.arrayBuffer());
|
|
188
|
+
const truncated = bytes.byteLength > maxBytes;
|
|
189
|
+
return {
|
|
190
|
+
text: new TextDecoder().decode(bytes.subarray(0, maxBytes)),
|
|
191
|
+
truncated
|
|
192
|
+
};
|
|
193
|
+
},
|
|
194
|
+
getRecap: async ({ conversationId }) => {
|
|
195
|
+
const { recap } = await get(`/api/v1/conversations/${encodeURIComponent(conversationId)}/recap`, recapResponseSchema);
|
|
196
|
+
return recap?.text ?? null;
|
|
197
|
+
},
|
|
110
198
|
uploadAttachment: async ({ agentId, fileName, mediaType, data }) => {
|
|
111
199
|
const size = data.byteLength;
|
|
112
200
|
const presign = await post("/api/v1/attachments/presign", {
|
|
@@ -137,11 +225,10 @@ function createRestClient({ appUrl, sessionToken }) {
|
|
|
137
225
|
deleteConversation: async ({ conversationId }) => {
|
|
138
226
|
await del(`/api/v1/conversations/${encodeURIComponent(conversationId)}`);
|
|
139
227
|
},
|
|
140
|
-
sendMessage: async (input) => post("/api/v1/chat/send",
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
},
|
|
228
|
+
sendMessage: async ({ clientSurface, ...input }) => post("/api/v1/chat/send", {
|
|
229
|
+
...input,
|
|
230
|
+
clientSurface
|
|
231
|
+
}, sendResultSchema),
|
|
145
232
|
cancelRun: async ({ runId }) => {
|
|
146
233
|
await post(`/api/v1/chat/runs/${encodeURIComponent(runId)}/cancel`, {}, z.object({ ok: z.boolean() }));
|
|
147
234
|
},
|
|
@@ -168,36 +255,35 @@ function createRestClient({ appUrl, sessionToken }) {
|
|
|
168
255
|
});
|
|
169
256
|
if (!res.ok) throw new HttpError(res.status, await res.text().catch(() => ""));
|
|
170
257
|
},
|
|
171
|
-
streamRun: async ({ runId, signal, onEvent }) => {
|
|
172
|
-
|
|
173
|
-
|
|
258
|
+
streamRun: async ({ runId, signal, onEvent }) => streamEvents({
|
|
259
|
+
path: `/api/v1/chat/runs/${encodeURIComponent(runId)}/stream`,
|
|
260
|
+
label: "run",
|
|
261
|
+
signal,
|
|
262
|
+
onEvent
|
|
263
|
+
}),
|
|
264
|
+
streamMessage: async ({ messageId, signal, onEvent }) => streamEvents({
|
|
265
|
+
path: `/api/v1/chat/messages/${encodeURIComponent(messageId)}/stream`,
|
|
266
|
+
label: "message",
|
|
267
|
+
signal,
|
|
268
|
+
onEvent
|
|
269
|
+
}),
|
|
270
|
+
streamConversation: async ({ conversationId, signal, onEvent }) => {
|
|
174
271
|
let reconnects = 0;
|
|
175
272
|
for (;;) {
|
|
176
273
|
if (signal.aborted) return;
|
|
177
274
|
try {
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
const res = await fetch(`${appUrl}/api/v1/chat/runs/${encodeURIComponent(runId)}/stream`, {
|
|
184
|
-
headers,
|
|
275
|
+
const res = await fetch(`${appUrl}/api/v1/chat/conversations/${encodeURIComponent(conversationId)}/stream`, {
|
|
276
|
+
headers: {
|
|
277
|
+
authorization: `Bearer ${sessionToken}`,
|
|
278
|
+
accept: "text/event-stream"
|
|
279
|
+
},
|
|
185
280
|
signal
|
|
186
281
|
});
|
|
187
282
|
if (!res.ok || !res.body) throw new HttpError(res.status, await res.text().catch(() => ""));
|
|
188
283
|
reconnects = 0;
|
|
189
284
|
const parser = createParser({ onEvent: (message) => {
|
|
190
|
-
|
|
191
|
-
if (
|
|
192
|
-
const { error } = streamErrorSchema.parse(JSON.parse(message.data));
|
|
193
|
-
throw new Error(error);
|
|
194
|
-
}
|
|
195
|
-
const event = runStreamEventSchema.parse(JSON.parse(message.data));
|
|
196
|
-
if (event.kind === "finished") finished = true;
|
|
197
|
-
onEvent(event.kind === "finished" ? {
|
|
198
|
-
...event,
|
|
199
|
-
error: event.error ?? null
|
|
200
|
-
} : event);
|
|
285
|
+
const parsed = conversationStreamEventSchema.safeParse(JSON.parse(message.data));
|
|
286
|
+
if (parsed.success) onEvent(parsed.data);
|
|
201
287
|
} });
|
|
202
288
|
const decoder = new TextDecoder();
|
|
203
289
|
const reader = res.body.getReader();
|
|
@@ -206,7 +292,6 @@ function createRestClient({ appUrl, sessionToken }) {
|
|
|
206
292
|
const { done, value } = await reader.read();
|
|
207
293
|
if (done) break;
|
|
208
294
|
parser.feed(decoder.decode(value, { stream: true }));
|
|
209
|
-
if (finished) return;
|
|
210
295
|
}
|
|
211
296
|
} finally {
|
|
212
297
|
try {
|
|
@@ -221,9 +306,9 @@ function createRestClient({ appUrl, sessionToken }) {
|
|
|
221
306
|
await sleep(Math.min(500 * 2 ** reconnects, 5e3));
|
|
222
307
|
continue;
|
|
223
308
|
}
|
|
224
|
-
if (
|
|
309
|
+
if (signal.aborted) return;
|
|
225
310
|
reconnects += 1;
|
|
226
|
-
if (reconnects > MAX_STREAM_RECONNECTS) throw new Error("
|
|
311
|
+
if (reconnects > MAX_STREAM_RECONNECTS) throw new Error("conversation stream ended unexpectedly");
|
|
227
312
|
await sleep(Math.min(500 * 2 ** reconnects, 5e3));
|
|
228
313
|
}
|
|
229
314
|
}
|
|
@@ -273,11 +358,14 @@ const conversationSummarySchema = z.object({
|
|
|
273
358
|
title: z.string().nullable().optional()
|
|
274
359
|
})
|
|
275
360
|
});
|
|
276
|
-
const
|
|
361
|
+
const conversationDetailSchema = z.object({
|
|
277
362
|
id: z.string().uuid(),
|
|
278
|
-
title: z.string().nullable()
|
|
363
|
+
title: z.string().nullable(),
|
|
364
|
+
agentId: z.string().uuid(),
|
|
365
|
+
createdAt: z.string(),
|
|
366
|
+
updatedAt: z.string()
|
|
279
367
|
});
|
|
280
|
-
const getConversationResponseSchema = z.object({ conversation:
|
|
368
|
+
const getConversationResponseSchema = z.object({ conversation: conversationDetailSchema });
|
|
281
369
|
const listConversationsResponseSchema = z.object({
|
|
282
370
|
conversations: z.array(conversationSummarySchema),
|
|
283
371
|
nextCursor: z.string().nullable().optional(),
|
|
@@ -306,13 +394,31 @@ const uiMessagePartSchema = z.union([
|
|
|
306
394
|
const uiMessageSchema = z.object({
|
|
307
395
|
id: z.string(),
|
|
308
396
|
role: z.string(),
|
|
309
|
-
parts: z.array(uiMessagePartSchema)
|
|
397
|
+
parts: z.array(uiMessagePartSchema),
|
|
398
|
+
metadata: z.object({ custom: z.object({
|
|
399
|
+
agentId: z.string().nullish(),
|
|
400
|
+
agentName: z.string().nullish()
|
|
401
|
+
}).passthrough().optional() }).passthrough().optional()
|
|
310
402
|
});
|
|
403
|
+
const recapResponseSchema = z.object({ recap: z.object({ text: z.string() }).nullable() });
|
|
311
404
|
const listMessagesResponseSchema = z.object({ messages: z.array(uiMessageSchema) });
|
|
405
|
+
const workspaceFileSchema = z.object({
|
|
406
|
+
id: z.string(),
|
|
407
|
+
path: z.string(),
|
|
408
|
+
mediaType: z.string(),
|
|
409
|
+
sizeBytes: z.number(),
|
|
410
|
+
contentHash: z.string(),
|
|
411
|
+
updatedAt: z.string(),
|
|
412
|
+
shareUrl: z.string()
|
|
413
|
+
});
|
|
414
|
+
const listWorkspaceFilesResponseSchema = z.object({ files: z.array(workspaceFileSchema) });
|
|
312
415
|
const sendResultSchema = z.object({
|
|
313
416
|
runId: z.string(),
|
|
417
|
+
messageId: z.string().uuid().nullish(),
|
|
314
418
|
conversationId: z.string().uuid(),
|
|
315
419
|
isNewConversation: z.boolean(),
|
|
420
|
+
agentId: z.string().nullish(),
|
|
421
|
+
agentName: z.string().nullish(),
|
|
316
422
|
steered: z.boolean().optional(),
|
|
317
423
|
directive: z.object({ id: z.string() }).passthrough().optional()
|
|
318
424
|
});
|
|
@@ -327,7 +433,6 @@ const finalizeResponseSchema = z.object({
|
|
|
327
433
|
mediaType: z.string(),
|
|
328
434
|
sizeBytes: z.number().nullable().optional()
|
|
329
435
|
});
|
|
330
|
-
const activeRunResponseSchema = z.object({ run: z.object({ runId: z.string() }).nullable() });
|
|
331
436
|
const oauthConnectResponseSchema = z.object({ connectLink: z.string() }).passthrough();
|
|
332
437
|
const externalOauthConnectResponseSchema = z.object({ authorizationUrl: z.string().optional() }).passthrough();
|
|
333
438
|
const runStreamEventSchema = z.union([z.object({
|
|
@@ -339,104 +444,14 @@ const runStreamEventSchema = z.union([z.object({
|
|
|
339
444
|
error: z.string().nullish()
|
|
340
445
|
})]);
|
|
341
446
|
const streamErrorSchema = z.object({ error: z.string() });
|
|
447
|
+
const conversationStreamEventSchema = z.discriminatedUnion("kind", [z.object({
|
|
448
|
+
kind: z.literal("conversation"),
|
|
449
|
+
id: z.string(),
|
|
450
|
+
title: z.string().nullable()
|
|
451
|
+
}), z.object({
|
|
452
|
+
kind: z.literal("run"),
|
|
453
|
+
runId: z.string()
|
|
454
|
+
})]);
|
|
342
455
|
|
|
343
456
|
//#endregion
|
|
344
|
-
|
|
345
|
-
var print_exports = /* @__PURE__ */ __exportAll({
|
|
346
|
-
readStdin: () => readStdin,
|
|
347
|
-
resolveAgent: () => resolveAgent,
|
|
348
|
-
runPrint: () => runPrint
|
|
349
|
-
});
|
|
350
|
-
/**
|
|
351
|
-
* Non-interactive chat, à la `claude -p`. Sends a single prompt to an
|
|
352
|
-
* agent, streams the run, and prints the assistant's reply to stdout
|
|
353
|
-
* before exiting. No OpenTUI, no Bun requirement — this rides the same
|
|
354
|
-
* Node-friendly REST client the TUI uses, so it runs anywhere the
|
|
355
|
-
* management commands do (CI, pipes, scripts).
|
|
356
|
-
*
|
|
357
|
-
* Resolution rules kept deliberately strict because there's no human to
|
|
358
|
-
* disambiguate: an `--agent` selector must match exactly one agent, and
|
|
359
|
-
* when it's omitted we only auto-pick if the account has exactly one.
|
|
360
|
-
*/
|
|
361
|
-
async function runPrint({ appUrl, sessionToken, prompt, agentSelector, conversationId, json }) {
|
|
362
|
-
const client = createRestClient({
|
|
363
|
-
appUrl,
|
|
364
|
-
sessionToken
|
|
365
|
-
});
|
|
366
|
-
const agent = resolveAgent(await client.listAgents({
|
|
367
|
-
scope: "org",
|
|
368
|
-
onPage: null
|
|
369
|
-
}), agentSelector);
|
|
370
|
-
const send = await client.sendMessage({
|
|
371
|
-
agentId: agent.id,
|
|
372
|
-
conversationId,
|
|
373
|
-
content: prompt,
|
|
374
|
-
attachmentIds: []
|
|
375
|
-
});
|
|
376
|
-
let text = "";
|
|
377
|
-
const controller = new AbortController();
|
|
378
|
-
let streamError = null;
|
|
379
|
-
await client.streamRun({
|
|
380
|
-
runId: send.runId,
|
|
381
|
-
signal: controller.signal,
|
|
382
|
-
onEvent: (event) => {
|
|
383
|
-
if (event.kind === "finished") {
|
|
384
|
-
if (event.error) streamError = event.error;
|
|
385
|
-
return;
|
|
386
|
-
}
|
|
387
|
-
const chunk = event.chunk;
|
|
388
|
-
if (chunk["type"] === "text-delta") {
|
|
389
|
-
const delta = typeof chunk["delta"] === "string" ? chunk["delta"] : typeof chunk["text"] === "string" ? chunk["text"] : "";
|
|
390
|
-
if (delta) {
|
|
391
|
-
text += delta;
|
|
392
|
-
if (!json) process.stdout.write(delta);
|
|
393
|
-
}
|
|
394
|
-
} else if (chunk["type"] === "error") streamError = typeof chunk["errorText"] === "string" ? chunk["errorText"] : "unknown error";
|
|
395
|
-
}
|
|
396
|
-
});
|
|
397
|
-
if (streamError) throw new Error(streamError);
|
|
398
|
-
if (!json && text && !text.endsWith("\n")) process.stdout.write("\n");
|
|
399
|
-
return {
|
|
400
|
-
agentId: agent.id,
|
|
401
|
-
agentName: agent.name,
|
|
402
|
-
conversationId: send.conversationId,
|
|
403
|
-
isNewConversation: send.isNewConversation,
|
|
404
|
-
runId: send.runId,
|
|
405
|
-
text
|
|
406
|
-
};
|
|
407
|
-
}
|
|
408
|
-
/**
|
|
409
|
-
* Pick the target agent. With no selector, auto-pick only when the
|
|
410
|
-
* account has exactly one agent; otherwise the user must name one (there's
|
|
411
|
-
* no picker in non-interactive mode). A selector matches by id first, then
|
|
412
|
-
* a unique case-insensitive slug/name; ambiguous or missing matches throw
|
|
413
|
-
* with the candidate list so the caller knows what to pass.
|
|
414
|
-
*/
|
|
415
|
-
function resolveAgent(agents, selector) {
|
|
416
|
-
if (!selector) {
|
|
417
|
-
const [only, ...rest] = agents;
|
|
418
|
-
if (!only) throw new Error("No agents on this account.");
|
|
419
|
-
if (rest.length === 0) return only;
|
|
420
|
-
throw new Error(`Multiple agents on this account — pass --agent <id|slug|name>. Candidates:\n${formatCandidates(agents)}`);
|
|
421
|
-
}
|
|
422
|
-
const byId = agents.find((a) => a.id === selector);
|
|
423
|
-
if (byId) return byId;
|
|
424
|
-
const needle = selector.toLowerCase();
|
|
425
|
-
const matches = agents.filter((a) => a.slug && a.slug.toLowerCase() === needle || a.name.toLowerCase() === needle);
|
|
426
|
-
const [firstMatch, ...restMatches] = matches;
|
|
427
|
-
if (firstMatch && restMatches.length === 0) return firstMatch;
|
|
428
|
-
if (restMatches.length > 0) throw new Error(`Multiple agents match "${selector}" — pass the id instead. Candidates:\n${formatCandidates(matches)}`);
|
|
429
|
-
throw new Error(`No agent matches "${selector}". Candidates:\n${formatCandidates(agents)}`);
|
|
430
|
-
}
|
|
431
|
-
function formatCandidates(agents) {
|
|
432
|
-
return agents.slice(0, 25).map((a) => ` ${a.id} ${a.slug ?? a.name}`).join("\n");
|
|
433
|
-
}
|
|
434
|
-
/** Read all of stdin as UTF-8. Used when `-p` is passed with no value. */
|
|
435
|
-
async function readStdin() {
|
|
436
|
-
const chunks = [];
|
|
437
|
-
for await (const chunk of process.stdin) chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
438
|
-
return Buffer.concat(chunks).toString("utf8");
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
//#endregion
|
|
442
|
-
export { createRestClient as i, resolveAgent as n, HttpError as r, print_exports as t };
|
|
457
|
+
export { createRestClient as n, errorDetail as r, HttpError as t };
|