forked from EduCraft/curriculum-project-hub
feat: streaming agent card with tool-use trace, reasoning panel, and tool results
Replace text-only PatchableTextStream with a unified StreamingAgentCard that renders the full agent run lifecycle in a single Feishu interactive card: - Tool-use panel: collapsible, shows each tool call with status (running/ success/error), input summary, and result/error in code blocks - Reasoning panel: collapsible, streams thinking text inline then collapses on completion - Answer text: rendered via native Feishu markdown component (no post-row round-trip) Runner now captures previously-discarded SDK events: - thinking_delta → reasoning stream - tool_use id + input on content_block_start / assistant message - tool_result from user messages (was entirely unhandled) New files: - card/trace-store.ts: per-run in-memory tool-use trace with secret redaction - card/builder.ts: Feishu card JSON builder (tool panel + reasoning + text) - card/streaming-card.ts: StreamingAgentCard controller (400ms throttled) client.ts: add sendCard/patchCard raw JSON primitives
This commit is contained in:
@@ -167,10 +167,19 @@ function textFromCard(card: unknown): string | null {
|
||||
const parts: string[] = [];
|
||||
for (const element of elements) {
|
||||
if (typeof element !== "object" || element === null) continue;
|
||||
// New format: { tag: "markdown", content: string }
|
||||
const tag = (element as { tag?: unknown }).tag;
|
||||
const directContent = (element as { content?: unknown }).content;
|
||||
if (tag === "markdown" && typeof directContent === "string") {
|
||||
parts.push(directContent);
|
||||
continue;
|
||||
}
|
||||
// Old format: { text: { content: string } }
|
||||
const text = (element as { text?: unknown }).text;
|
||||
if (typeof text !== "object" || text === null) continue;
|
||||
const content = (text as { content?: unknown }).content;
|
||||
if (typeof content === "string") parts.push(content);
|
||||
if (typeof text === "object" && text !== null) {
|
||||
const content = (text as { content?: unknown }).content;
|
||||
if (typeof content === "string") parts.push(content);
|
||||
}
|
||||
}
|
||||
return parts.length === 0 ? null : parts.join("\n");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user