skydive-cli 0.1.0-beta.291 → 0.1.0-beta.297
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/js/bin.mjs
CHANGED
|
@@ -16,7 +16,7 @@ import zlib from "node:zlib";
|
|
|
16
16
|
import os from "node:os";
|
|
17
17
|
|
|
18
18
|
//#region package.json
|
|
19
|
-
var version$1 = "0.1.0-beta.
|
|
19
|
+
var version$1 = "0.1.0-beta.297";
|
|
20
20
|
|
|
21
21
|
//#endregion
|
|
22
22
|
//#region src/types.ts
|
|
@@ -1023,7 +1023,12 @@ function createRestClient({ appUrl, sessionToken }) {
|
|
|
1023
1023
|
}, sendResultSchema),
|
|
1024
1024
|
activeRun: async ({ conversationId }) => {
|
|
1025
1025
|
const { run } = await get(`/api/v1/chat/active-run?${new URLSearchParams({ conversationId }).toString()}`, activeRunResponseSchema);
|
|
1026
|
-
return
|
|
1026
|
+
if (!run) return null;
|
|
1027
|
+
return {
|
|
1028
|
+
runId: run.runId,
|
|
1029
|
+
agentId: run.agentId ?? "",
|
|
1030
|
+
agentName: run.agentName ?? ""
|
|
1031
|
+
};
|
|
1027
1032
|
},
|
|
1028
1033
|
cancelRun: async ({ runId }) => {
|
|
1029
1034
|
await post(`/api/v1/chat/runs/${encodeURIComponent(runId)}/cancel`, {}, z.object({ ok: z.boolean() }));
|
|
@@ -1187,7 +1192,11 @@ const uiMessagePartSchema = z.union([
|
|
|
1187
1192
|
const uiMessageSchema = z.object({
|
|
1188
1193
|
id: z.string(),
|
|
1189
1194
|
role: z.string(),
|
|
1190
|
-
parts: z.array(uiMessagePartSchema)
|
|
1195
|
+
parts: z.array(uiMessagePartSchema),
|
|
1196
|
+
metadata: z.object({ custom: z.object({
|
|
1197
|
+
agentId: z.string().nullish(),
|
|
1198
|
+
agentName: z.string().nullish()
|
|
1199
|
+
}).passthrough().optional() }).passthrough().optional()
|
|
1191
1200
|
});
|
|
1192
1201
|
const recapResponseSchema = z.object({ recap: z.object({ text: z.string() }).nullable() });
|
|
1193
1202
|
const listMessagesResponseSchema = z.object({ messages: z.array(uiMessageSchema) });
|
|
@@ -1196,6 +1205,8 @@ const sendResultSchema = z.object({
|
|
|
1196
1205
|
messageId: z.string().uuid().nullish(),
|
|
1197
1206
|
conversationId: z.string().uuid(),
|
|
1198
1207
|
isNewConversation: z.boolean(),
|
|
1208
|
+
agentId: z.string().nullish(),
|
|
1209
|
+
agentName: z.string().nullish(),
|
|
1199
1210
|
steered: z.boolean().optional(),
|
|
1200
1211
|
directive: z.object({ id: z.string() }).passthrough().optional()
|
|
1201
1212
|
});
|
|
@@ -1210,7 +1221,11 @@ const finalizeResponseSchema = z.object({
|
|
|
1210
1221
|
mediaType: z.string(),
|
|
1211
1222
|
sizeBytes: z.number().nullable().optional()
|
|
1212
1223
|
});
|
|
1213
|
-
const activeRunResponseSchema = z.object({ run: z.object({
|
|
1224
|
+
const activeRunResponseSchema = z.object({ run: z.object({
|
|
1225
|
+
runId: z.string(),
|
|
1226
|
+
agentId: z.string().nullish(),
|
|
1227
|
+
agentName: z.string().nullish()
|
|
1228
|
+
}).nullable() });
|
|
1214
1229
|
const oauthConnectResponseSchema = z.object({ connectLink: z.string() }).passthrough();
|
|
1215
1230
|
const externalOauthConnectResponseSchema = z.object({ authorizationUrl: z.string().optional() }).passthrough();
|
|
1216
1231
|
const runStreamEventSchema = z.union([z.object({
|
|
@@ -2592,7 +2607,7 @@ const chatCommand = {
|
|
|
2592
2607
|
printError(`Unknown theme "${themeId}". Valid themes: ${themes.map((t) => t.id).join(", ")}`);
|
|
2593
2608
|
process.exit(1);
|
|
2594
2609
|
}
|
|
2595
|
-
const { runChat } = await import("./boot-
|
|
2610
|
+
const { runChat } = await import("./boot-DYzw1U0y.mjs");
|
|
2596
2611
|
await runChat({
|
|
2597
2612
|
appUrl,
|
|
2598
2613
|
sessionToken: session.value.sessionToken,
|
|
@@ -3375,7 +3390,7 @@ const switchCommand = {
|
|
|
3375
3390
|
printError("The workspace picker needs the Bun runtime and it could not be set up automatically. Pass a workspace slug instead, or install Bun and retry.");
|
|
3376
3391
|
process.exit(1);
|
|
3377
3392
|
}
|
|
3378
|
-
const { runWorkspacePicker } = await import("./boot-
|
|
3393
|
+
const { runWorkspacePicker } = await import("./boot-DYzw1U0y.mjs");
|
|
3379
3394
|
await runWorkspacePicker(session);
|
|
3380
3395
|
return;
|
|
3381
3396
|
}
|
|
@@ -3027,16 +3027,23 @@ function str(chunk, key) {
|
|
|
3027
3027
|
const value = chunk[key];
|
|
3028
3028
|
return typeof value === "string" ? value : null;
|
|
3029
3029
|
}
|
|
3030
|
-
|
|
3030
|
+
/**
|
|
3031
|
+
* `agentName` is the display name of the agent producing this run's stream.
|
|
3032
|
+
* It's stamped onto each assistant-origin item so a multi-agent conversation
|
|
3033
|
+
* can attribute live turns; pass null in a solo thread to leave items
|
|
3034
|
+
* un-attributed (the chat screen only renders the name when the thread has
|
|
3035
|
+
* more than one agent).
|
|
3036
|
+
*/
|
|
3037
|
+
function applyChunk(items, chunk, agentName = null) {
|
|
3031
3038
|
const type = str(chunk, "type");
|
|
3032
3039
|
if (!type) return [...items];
|
|
3033
3040
|
switch (type) {
|
|
3034
|
-
case "text-start": return appendAssistantTextStart(items, str(chunk, "id") ?? cryptoId());
|
|
3041
|
+
case "text-start": return appendAssistantTextStart(items, str(chunk, "id") ?? cryptoId(), agentName);
|
|
3035
3042
|
case "text-delta": {
|
|
3036
3043
|
const id = str(chunk, "id");
|
|
3037
3044
|
const delta = str(chunk, "delta") ?? str(chunk, "text") ?? "";
|
|
3038
3045
|
if (!id || !delta) return [...items];
|
|
3039
|
-
return appendAssistantTextDelta(items, id, delta);
|
|
3046
|
+
return appendAssistantTextDelta(items, id, delta, agentName);
|
|
3040
3047
|
}
|
|
3041
3048
|
case "text-end": {
|
|
3042
3049
|
const id = str(chunk, "id");
|
|
@@ -3049,14 +3056,15 @@ function applyChunk(items, chunk) {
|
|
|
3049
3056
|
kind: "reasoning",
|
|
3050
3057
|
id: bubbleId,
|
|
3051
3058
|
text: "",
|
|
3052
|
-
done: false
|
|
3059
|
+
done: false,
|
|
3060
|
+
agentName
|
|
3053
3061
|
}];
|
|
3054
3062
|
}
|
|
3055
3063
|
case "reasoning-delta": {
|
|
3056
3064
|
const id = str(chunk, "id");
|
|
3057
3065
|
const delta = str(chunk, "delta") ?? str(chunk, "text") ?? "";
|
|
3058
3066
|
if (!id || !delta) return [...items];
|
|
3059
|
-
return appendReasoningDelta(items, id, delta);
|
|
3067
|
+
return appendReasoningDelta(items, id, delta, agentName);
|
|
3060
3068
|
}
|
|
3061
3069
|
case "reasoning-end": {
|
|
3062
3070
|
const id = str(chunk, "id");
|
|
@@ -3079,7 +3087,8 @@ function applyChunk(items, chunk) {
|
|
|
3079
3087
|
inputText: "",
|
|
3080
3088
|
input: null,
|
|
3081
3089
|
output: null,
|
|
3082
|
-
state: "streaming"
|
|
3090
|
+
state: "streaming",
|
|
3091
|
+
agentName
|
|
3083
3092
|
}];
|
|
3084
3093
|
}
|
|
3085
3094
|
case "tool-input-delta": {
|
|
@@ -3108,7 +3117,8 @@ function applyChunk(items, chunk) {
|
|
|
3108
3117
|
inputText: "",
|
|
3109
3118
|
input,
|
|
3110
3119
|
output: null,
|
|
3111
|
-
state: "input-ready"
|
|
3120
|
+
state: "input-ready",
|
|
3121
|
+
agentName
|
|
3112
3122
|
}];
|
|
3113
3123
|
}
|
|
3114
3124
|
case "tool-output-available": {
|
|
@@ -3165,7 +3175,8 @@ function applyChunk(items, chunk) {
|
|
|
3165
3175
|
id,
|
|
3166
3176
|
card,
|
|
3167
3177
|
status: "idle",
|
|
3168
|
-
detail: null
|
|
3178
|
+
detail: null,
|
|
3179
|
+
agentName
|
|
3169
3180
|
};
|
|
3170
3181
|
if (items.some((m) => m.kind === "card" && m.id === id)) return items.map((m) => m.kind === "card" && m.id === id ? next : m);
|
|
3171
3182
|
return [...items, next];
|
|
@@ -3206,16 +3217,17 @@ function openTextIndex(items, id, kind) {
|
|
|
3206
3217
|
}
|
|
3207
3218
|
return -1;
|
|
3208
3219
|
}
|
|
3209
|
-
function appendAssistantTextStart(items, id) {
|
|
3220
|
+
function appendAssistantTextStart(items, id, agentName) {
|
|
3210
3221
|
const bubbleId = freshTextId(items, id, "assistant-text");
|
|
3211
3222
|
return [...items, {
|
|
3212
3223
|
kind: "assistant-text",
|
|
3213
3224
|
id: bubbleId,
|
|
3214
3225
|
text: "",
|
|
3215
|
-
done: false
|
|
3226
|
+
done: false,
|
|
3227
|
+
agentName
|
|
3216
3228
|
}];
|
|
3217
3229
|
}
|
|
3218
|
-
function appendAssistantTextDelta(items, id, delta) {
|
|
3230
|
+
function appendAssistantTextDelta(items, id, delta, agentName) {
|
|
3219
3231
|
const idx = openTextIndex(items, id, "assistant-text");
|
|
3220
3232
|
if (idx === -1) {
|
|
3221
3233
|
const bubbleId = freshTextId(items, id, "assistant-text");
|
|
@@ -3223,7 +3235,8 @@ function appendAssistantTextDelta(items, id, delta) {
|
|
|
3223
3235
|
kind: "assistant-text",
|
|
3224
3236
|
id: bubbleId,
|
|
3225
3237
|
text: delta,
|
|
3226
|
-
done: false
|
|
3238
|
+
done: false,
|
|
3239
|
+
agentName
|
|
3227
3240
|
}];
|
|
3228
3241
|
}
|
|
3229
3242
|
return items.map((m, i) => i === idx && m.kind === "assistant-text" ? {
|
|
@@ -3231,7 +3244,7 @@ function appendAssistantTextDelta(items, id, delta) {
|
|
|
3231
3244
|
text: m.text + delta
|
|
3232
3245
|
} : m);
|
|
3233
3246
|
}
|
|
3234
|
-
function appendReasoningDelta(items, id, delta) {
|
|
3247
|
+
function appendReasoningDelta(items, id, delta, agentName) {
|
|
3235
3248
|
const idx = openTextIndex(items, id, "reasoning");
|
|
3236
3249
|
if (idx === -1) {
|
|
3237
3250
|
const bubbleId = freshTextId(items, id, "reasoning");
|
|
@@ -3239,7 +3252,8 @@ function appendReasoningDelta(items, id, delta) {
|
|
|
3239
3252
|
kind: "reasoning",
|
|
3240
3253
|
id: bubbleId,
|
|
3241
3254
|
text: delta,
|
|
3242
|
-
done: false
|
|
3255
|
+
done: false,
|
|
3256
|
+
agentName
|
|
3243
3257
|
}];
|
|
3244
3258
|
}
|
|
3245
3259
|
return items.map((m, i) => i === idx && m.kind === "reasoning" ? {
|
|
@@ -3269,6 +3283,59 @@ function cryptoId() {
|
|
|
3269
3283
|
return crypto.randomUUID();
|
|
3270
3284
|
}
|
|
3271
3285
|
|
|
3286
|
+
//#endregion
|
|
3287
|
+
//#region src/chat/tui/chat/attribution.ts
|
|
3288
|
+
/**
|
|
3289
|
+
* The agent that authored an item, or null for items with no agent (the user's
|
|
3290
|
+
* own turns, errors, the recap).
|
|
3291
|
+
*/
|
|
3292
|
+
function itemAgentName(m) {
|
|
3293
|
+
return "agentName" in m ? m.agentName ?? null : null;
|
|
3294
|
+
}
|
|
3295
|
+
/**
|
|
3296
|
+
* Items that end an agent's turn: the human speaking or acting. The next
|
|
3297
|
+
* assistant item after one of these starts a new turn and is re-headed with its
|
|
3298
|
+
* author, even when the same agent replies again — in a multi-agent thread the
|
|
3299
|
+
* reader can't be asked to scan back past their own message to work out who is
|
|
3300
|
+
* answering.
|
|
3301
|
+
*/
|
|
3302
|
+
function isTurnSeparator(m) {
|
|
3303
|
+
return m.kind === "user" || m.kind === "pending-steer" || m.kind === "shell";
|
|
3304
|
+
}
|
|
3305
|
+
/**
|
|
3306
|
+
* Every agent that has spoken in the transcript, plus the agent on screen.
|
|
3307
|
+
* Attribution renders only when this holds more than one name, mirroring web's
|
|
3308
|
+
* group-chat gate so a solo thread carries no attribution chrome at all.
|
|
3309
|
+
*/
|
|
3310
|
+
function conversationAgentNames(items, onScreenAgentName) {
|
|
3311
|
+
const names = new Set([onScreenAgentName]);
|
|
3312
|
+
for (const item of items) {
|
|
3313
|
+
const name = itemAgentName(item);
|
|
3314
|
+
if (name) names.add(name);
|
|
3315
|
+
}
|
|
3316
|
+
return names;
|
|
3317
|
+
}
|
|
3318
|
+
/**
|
|
3319
|
+
* The agent-name label to render above `items[i]`, or null for no label. Every
|
|
3320
|
+
* assistant turn is headed with its author's name. Within one turn the items
|
|
3321
|
+
* (text, reasoning, tool calls) share the single header, so a turn isn't
|
|
3322
|
+
* re-labeled on each tool row; `error` and `recap` items are transparent and
|
|
3323
|
+
* don't break that grouping.
|
|
3324
|
+
*/
|
|
3325
|
+
function agentLabelFor(items, i) {
|
|
3326
|
+
const current = items[i];
|
|
3327
|
+
const name = current ? itemAgentName(current) : null;
|
|
3328
|
+
if (!name) return null;
|
|
3329
|
+
for (let j = i - 1; j >= 0; j--) {
|
|
3330
|
+
const prevItem = items[j];
|
|
3331
|
+
if (!prevItem) continue;
|
|
3332
|
+
if (isTurnSeparator(prevItem)) return name;
|
|
3333
|
+
const prev = itemAgentName(prevItem);
|
|
3334
|
+
if (prev !== null) return prev === name ? null : name;
|
|
3335
|
+
}
|
|
3336
|
+
return name;
|
|
3337
|
+
}
|
|
3338
|
+
|
|
3272
3339
|
//#endregion
|
|
3273
3340
|
//#region src/chat/tui/chat/history.ts
|
|
3274
3341
|
function isDynamicTool(part) {
|
|
@@ -3297,6 +3364,7 @@ function uiMessagesToItems(messages) {
|
|
|
3297
3364
|
continue;
|
|
3298
3365
|
}
|
|
3299
3366
|
if (m.role === "assistant") {
|
|
3367
|
+
const agentName = m.metadata?.custom?.agentName ?? null;
|
|
3300
3368
|
let textBuf = "";
|
|
3301
3369
|
let textIdx = 0;
|
|
3302
3370
|
for (const part of m.parts) {
|
|
@@ -3309,7 +3377,8 @@ function uiMessagesToItems(messages) {
|
|
|
3309
3377
|
kind: "assistant-text",
|
|
3310
3378
|
id: `${m.id}#t${textIdx++}`,
|
|
3311
3379
|
text: textBuf,
|
|
3312
|
-
done: true
|
|
3380
|
+
done: true,
|
|
3381
|
+
agentName
|
|
3313
3382
|
});
|
|
3314
3383
|
textBuf = "";
|
|
3315
3384
|
}
|
|
@@ -3318,7 +3387,8 @@ function uiMessagesToItems(messages) {
|
|
|
3318
3387
|
kind: "reasoning",
|
|
3319
3388
|
id: `${m.id}#r${textIdx++}`,
|
|
3320
3389
|
text: "text" in part && typeof part.text === "string" ? part.text : "",
|
|
3321
|
-
done: true
|
|
3390
|
+
done: true,
|
|
3391
|
+
agentName
|
|
3322
3392
|
});
|
|
3323
3393
|
continue;
|
|
3324
3394
|
}
|
|
@@ -3332,7 +3402,8 @@ function uiMessagesToItems(messages) {
|
|
|
3332
3402
|
id: toolCallId ?? `${m.id}#c${textIdx++}`,
|
|
3333
3403
|
card,
|
|
3334
3404
|
status: "idle",
|
|
3335
|
-
detail: null
|
|
3405
|
+
detail: null,
|
|
3406
|
+
agentName
|
|
3336
3407
|
});
|
|
3337
3408
|
}
|
|
3338
3409
|
continue;
|
|
@@ -3352,7 +3423,8 @@ function uiMessagesToItems(messages) {
|
|
|
3352
3423
|
kind: "ok",
|
|
3353
3424
|
value: part.output
|
|
3354
3425
|
} : null,
|
|
3355
|
-
state
|
|
3426
|
+
state,
|
|
3427
|
+
agentName
|
|
3356
3428
|
});
|
|
3357
3429
|
}
|
|
3358
3430
|
}
|
|
@@ -3360,7 +3432,8 @@ function uiMessagesToItems(messages) {
|
|
|
3360
3432
|
kind: "assistant-text",
|
|
3361
3433
|
id: `${m.id}#t${textIdx++}`,
|
|
3362
3434
|
text: textBuf,
|
|
3363
|
-
done: true
|
|
3435
|
+
done: true,
|
|
3436
|
+
agentName
|
|
3364
3437
|
});
|
|
3365
3438
|
}
|
|
3366
3439
|
}
|
|
@@ -5168,10 +5241,11 @@ function ChatScreen({ agent, conversation }) {
|
|
|
5168
5241
|
cancelled = true;
|
|
5169
5242
|
};
|
|
5170
5243
|
}, [rest, initialConversationId]);
|
|
5171
|
-
const attachToRun = useCallback((runId) => {
|
|
5244
|
+
const attachToRun = useCallback((runId, runAgentName) => {
|
|
5172
5245
|
if (!rest) return;
|
|
5173
5246
|
const abort = new AbortController();
|
|
5174
5247
|
const responsePreview = createResponsePreview();
|
|
5248
|
+
const streamAgentName = runAgentName ?? agent.name;
|
|
5175
5249
|
setRun({
|
|
5176
5250
|
kind: "streaming",
|
|
5177
5251
|
runId,
|
|
@@ -5183,7 +5257,7 @@ function ChatScreen({ agent, conversation }) {
|
|
|
5183
5257
|
onEvent: (event) => {
|
|
5184
5258
|
if (event.kind === "chunk") {
|
|
5185
5259
|
responsePreview.addChunk(event.chunk);
|
|
5186
|
-
setItems((prev) => applyChunk(prev, event.chunk));
|
|
5260
|
+
setItems((prev) => applyChunk(prev, event.chunk, streamAgentName));
|
|
5187
5261
|
return;
|
|
5188
5262
|
}
|
|
5189
5263
|
const errorText = event.error;
|
|
@@ -5221,6 +5295,7 @@ function ChatScreen({ agent, conversation }) {
|
|
|
5221
5295
|
agent.name,
|
|
5222
5296
|
agentHost
|
|
5223
5297
|
]);
|
|
5298
|
+
const multiAgent = useMemo(() => conversationAgentNames(items, agent.name), [items, agent.name]).size > 1;
|
|
5224
5299
|
useEffect(() => {
|
|
5225
5300
|
if (!rest || !conversationId) return;
|
|
5226
5301
|
const abort = new AbortController();
|
|
@@ -5244,7 +5319,7 @@ function ChatScreen({ agent, conversation }) {
|
|
|
5244
5319
|
try {
|
|
5245
5320
|
const active = await rest.activeRun({ conversationId });
|
|
5246
5321
|
if (cancelled || !active) return;
|
|
5247
|
-
attachToRun(active.runId);
|
|
5322
|
+
attachToRun(active.runId, active.agentName || null);
|
|
5248
5323
|
} catch (_error) {}
|
|
5249
5324
|
})();
|
|
5250
5325
|
return () => {
|
|
@@ -5311,10 +5386,10 @@ function ChatScreen({ agent, conversation }) {
|
|
|
5311
5386
|
text: trimmed
|
|
5312
5387
|
} : m));
|
|
5313
5388
|
const current = runRef.current;
|
|
5314
|
-
if (!(current.kind === "streaming" && current.runId === result.runId)) attachToRun(result.runId);
|
|
5389
|
+
if (!(current.kind === "streaming" && current.runId === result.runId)) attachToRun(result.runId, result.agentName ?? null);
|
|
5315
5390
|
return;
|
|
5316
5391
|
}
|
|
5317
|
-
attachToRun(result.runId);
|
|
5392
|
+
attachToRun(result.runId, result.agentName ?? null);
|
|
5318
5393
|
} catch (err) {
|
|
5319
5394
|
setItems((prev) => [...prev.filter((m) => m.id !== optimisticId), {
|
|
5320
5395
|
kind: "error",
|
|
@@ -6045,7 +6120,22 @@ function ChatScreen({ agent, conversation }) {
|
|
|
6045
6120
|
agent.name,
|
|
6046
6121
|
" below."
|
|
6047
6122
|
]
|
|
6048
|
-
}) : /* @__PURE__ */ jsx(Fragment, { children: items.map((item
|
|
6123
|
+
}) : /* @__PURE__ */ jsx(Fragment, { children: items.map((item, i) => {
|
|
6124
|
+
const label = multiAgent ? agentLabelFor(items, i) : null;
|
|
6125
|
+
return /* @__PURE__ */ jsxs("box", {
|
|
6126
|
+
style: { flexDirection: "column" },
|
|
6127
|
+
children: [label ? /* @__PURE__ */ jsx("box", {
|
|
6128
|
+
style: {
|
|
6129
|
+
paddingLeft: 3,
|
|
6130
|
+
paddingRight: 1
|
|
6131
|
+
},
|
|
6132
|
+
children: /* @__PURE__ */ jsx("text", {
|
|
6133
|
+
fg: theme.muted,
|
|
6134
|
+
children: /* @__PURE__ */ jsx("b", { children: label })
|
|
6135
|
+
})
|
|
6136
|
+
}) : null, /* @__PURE__ */ jsx(RenderItem, { item })]
|
|
6137
|
+
}, item.id);
|
|
6138
|
+
}) }), run.kind !== "idle" ? /* @__PURE__ */ jsx(ActivityRow, { label: run.kind === "sending" ? "sending" : "working" }) : null]
|
|
6049
6139
|
})
|
|
6050
6140
|
}),
|
|
6051
6141
|
pendingVisible ? /* @__PURE__ */ jsxs("box", {
|