linkshell-cli 0.2.122 → 0.2.123
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.
|
@@ -529,6 +529,49 @@ function textFromBlocks(blocks: AgentContentBlock[]): string {
|
|
|
529
529
|
.join("\n");
|
|
530
530
|
}
|
|
531
531
|
|
|
532
|
+
function contentBlocksFromValue(value: unknown): AgentContentBlock[] {
|
|
533
|
+
if (typeof value === "string") {
|
|
534
|
+
return value.trim() ? [{ type: "text", text: value }] : [];
|
|
535
|
+
}
|
|
536
|
+
if (Array.isArray(value)) {
|
|
537
|
+
return value.flatMap((entry) => contentBlocksFromValue(entry));
|
|
538
|
+
}
|
|
539
|
+
const raw = asRecord(value);
|
|
540
|
+
if (!raw) return [];
|
|
541
|
+
const rawType = firstString(raw, ["type", "kind"]);
|
|
542
|
+
const normalizedType = normalizedIdentifier(rawType);
|
|
543
|
+
if (normalizedType === "image" || normalizedType === "inputimage" || normalizedType === "outputimage") {
|
|
544
|
+
const data = firstString(raw, [
|
|
545
|
+
"data",
|
|
546
|
+
"url",
|
|
547
|
+
"uri",
|
|
548
|
+
"imageUrl",
|
|
549
|
+
"image_url",
|
|
550
|
+
"base64",
|
|
551
|
+
]);
|
|
552
|
+
const mimeType = firstString(raw, ["mimeType", "mime_type", "mediaType", "media_type"]);
|
|
553
|
+
const text = firstString(raw, ["text", "alt", "caption", "name"]);
|
|
554
|
+
return [{ type: "image", data, mimeType, text }];
|
|
555
|
+
}
|
|
556
|
+
if (normalizedType === "text" || normalizedType === "outputtext" || normalizedType === "inputtext") {
|
|
557
|
+
const text = firstString(raw, ["text", "content", "message"]);
|
|
558
|
+
return text ? [{ type: "text", text }] : [];
|
|
559
|
+
}
|
|
560
|
+
const nested = raw.content ?? raw.contentItems ?? raw.parts;
|
|
561
|
+
if (Array.isArray(nested)) return contentBlocksFromValue(nested);
|
|
562
|
+
const text = firstString(raw, ["text", "message", "content"]);
|
|
563
|
+
return text ? [{ type: "text", text }] : [];
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
function contentBlocksFromItem(item: Record<string, unknown>): AgentContentBlock[] {
|
|
567
|
+
for (const key of ["content", "contentItems", "parts", "message"]) {
|
|
568
|
+
const blocks = contentBlocksFromValue(item[key]);
|
|
569
|
+
if (blocks.length > 0) return blocks;
|
|
570
|
+
}
|
|
571
|
+
const text = firstString(item, ["text", "message"]);
|
|
572
|
+
return text ? [{ type: "text", text }] : [];
|
|
573
|
+
}
|
|
574
|
+
|
|
532
575
|
function protocolSupportsImages(protocol: AgentProtocol | undefined): boolean {
|
|
533
576
|
return protocol === "codex-app-server" ||
|
|
534
577
|
protocol === "claude-agent-sdk" ||
|
|
@@ -2391,20 +2434,24 @@ export class AgentWorkspaceProxy {
|
|
|
2391
2434
|
if (!conversationId) return;
|
|
2392
2435
|
const itemId = firstString(item, ["id"]) ?? id("msg");
|
|
2393
2436
|
const existing = this.findItem(conversationId, itemId);
|
|
2394
|
-
const content =
|
|
2395
|
-
|
|
2437
|
+
const content = contentBlocksFromItem(item);
|
|
2438
|
+
const nextContent = content.length > 0
|
|
2439
|
+
? content
|
|
2440
|
+
: existing?.content ?? (existing?.text ? [{ type: "text", text: existing.text }] : []);
|
|
2441
|
+
const text = textFromBlocks(nextContent);
|
|
2442
|
+
if (!nextContent.length && !text) return;
|
|
2396
2443
|
this.upsertItem(conversationId, {
|
|
2397
2444
|
id: itemId,
|
|
2398
2445
|
conversationId,
|
|
2399
2446
|
type: "message",
|
|
2400
2447
|
role: "assistant",
|
|
2401
|
-
content:
|
|
2402
|
-
text
|
|
2448
|
+
content: nextContent,
|
|
2449
|
+
text,
|
|
2403
2450
|
createdAt: existing?.createdAt ?? Date.now(),
|
|
2404
2451
|
updatedAt: Date.now(),
|
|
2405
2452
|
isStreaming: streaming,
|
|
2406
2453
|
});
|
|
2407
|
-
this.updateConversationPreview(conversationId,
|
|
2454
|
+
this.updateConversationPreview(conversationId, text || "图片附件", streaming ? "running" : "idle");
|
|
2408
2455
|
}
|
|
2409
2456
|
|
|
2410
2457
|
private handleSessionUpdate(params: unknown): void {
|
|
@@ -2413,7 +2460,8 @@ export class AgentWorkspaceProxy {
|
|
|
2413
2460
|
const text =
|
|
2414
2461
|
firstString(raw, ["delta", "text", "content", "message"]) ??
|
|
2415
2462
|
firstString(nested, ["delta", "text", "content", "message"]);
|
|
2416
|
-
|
|
2463
|
+
const content = contentBlocksFromItem(raw);
|
|
2464
|
+
if (!text && content.length === 0) return;
|
|
2417
2465
|
const conversationId = this.conversationIdFromParams(raw) ?? this.fallbackConversationId();
|
|
2418
2466
|
if (!conversationId) return;
|
|
2419
2467
|
if (firstString(raw, ["toolName", "tool", "name"])) {
|
|
@@ -2430,18 +2478,20 @@ export class AgentWorkspaceProxy {
|
|
|
2430
2478
|
return;
|
|
2431
2479
|
}
|
|
2432
2480
|
const role = raw.role === "user" || raw.role === "system" ? raw.role : "assistant";
|
|
2481
|
+
const blocks = content.length > 0 ? content : [{ type: "text" as const, text }];
|
|
2482
|
+
const preview = textFromBlocks(blocks);
|
|
2433
2483
|
this.upsertItem(conversationId, {
|
|
2434
2484
|
id: firstString(raw, ["messageId", "id"]) ?? id("msg"),
|
|
2435
2485
|
conversationId,
|
|
2436
2486
|
type: "message",
|
|
2437
2487
|
role,
|
|
2438
|
-
content:
|
|
2439
|
-
text,
|
|
2488
|
+
content: blocks,
|
|
2489
|
+
text: preview,
|
|
2440
2490
|
createdAt: Date.now(),
|
|
2441
2491
|
updatedAt: Date.now(),
|
|
2442
2492
|
isStreaming: raw.done === false || raw.isStreaming === true,
|
|
2443
2493
|
});
|
|
2444
|
-
this.updateConversationPreview(conversationId,
|
|
2494
|
+
this.updateConversationPreview(conversationId, preview || "图片附件", raw.done === true ? "idle" : "running");
|
|
2445
2495
|
}
|
|
2446
2496
|
|
|
2447
2497
|
private handleSemanticSystemItem(
|