



















@@ -11,7 +11,6 @@ import {
1111import { renderChatRunControls, type ChatRunControlsProps } from "./run-controls.ts";
1212import { renderSideResult } from "./side-result-render.ts";
1313import { renderCompactionIndicator, renderFallbackIndicator } from "./status-indicators.ts";
14-import { renderToolCard } from "./tool-cards.ts";
15141615vi.mock("../icons.ts", () => ({
1716icons: {},
@@ -21,18 +20,6 @@ vi.mock("../markdown.ts", () => ({
2120toSanitizedMarkdownHtml: (value: string) => value,
2221}));
232224-vi.mock("../tool-display.ts", () => ({
25-formatToolDetail: () => undefined,
26-resolveToolDisplay: ({ name }: { name: string }) => ({
27- name,
28-label: name
29-.split(/[._-]/g)
30-.map((part) => (part ? part[0].toUpperCase() + part.slice(1) : part))
31-.join(" "),
32-icon: "zap",
33-}),
34-}));
35-3623function createProps(overrides: Partial<ChatRunControlsProps> = {}): ChatRunControlsProps {
3724return {
3825canAbort: false,
@@ -380,170 +367,3 @@ describe("side result render", () => {
380367expect(container.querySelector(".chat-side-result--error")).not.toBeNull();
381368});
382369});
383-384-describe("tool-cards", () => {
385-it("renders expanded cards with inline input and output sections", () => {
386-const container = document.createElement("div");
387-const toggle = vi.fn();
388-render(
389-renderToolCard(
390-{
391-id: "msg:4:call-4",
392-name: "browser.open",
393-args: { url: "https://example.com" },
394-inputText: '{\n "url": "https://example.com"\n}',
395-outputText: "Opened page",
396-},
397-{ expanded: true, onToggleExpanded: toggle },
398-),
399-container,
400-);
401-402-expect(container.textContent).toContain("Tool input");
403-expect(container.textContent).toContain("Tool output");
404-expect(container.textContent).toContain("https://example.com");
405-expect(container.textContent).toContain("Opened page");
406-});
407-408-it("renders expanded tool calls without an inline output block when no output is present", () => {
409-const container = document.createElement("div");
410-render(
411-renderToolCard(
412-{
413-id: "msg:4b:call-4b",
414-name: "sessions_spawn",
415-args: { mode: "session", thread: true },
416-inputText: '{\n "mode": "session",\n "thread": true\n}',
417-},
418-{ expanded: true, onToggleExpanded: vi.fn() },
419-),
420-container,
421-);
422-423-expect(container.textContent).toContain("Tool input");
424-expect(container.textContent).toContain('"thread": true');
425-expect(container.textContent).not.toContain("Tool output");
426-expect(container.textContent).not.toContain("No output");
427-});
428-429-it("labels collapsed tool calls as tool call", () => {
430-const container = document.createElement("div");
431-render(
432-renderToolCard(
433-{
434-id: "msg:5:call-5",
435-name: "sessions_spawn",
436-args: { mode: "run" },
437-inputText: '{\n "mode": "run"\n}',
438-},
439-{ expanded: false, onToggleExpanded: vi.fn() },
440-),
441-container,
442-);
443-444-expect(container.textContent).toContain("Tool call");
445-expect(container.textContent).not.toContain("Tool input");
446-const summaryButton = container.querySelector("button.chat-tool-msg-summary");
447-expect(summaryButton).not.toBeNull();
448-expect(summaryButton?.getAttribute("aria-expanded")).toBe("false");
449-});
450-451-it("keeps raw details for legacy canvas tool output without rendering tool-row previews", () => {
452-const container = document.createElement("div");
453-render(
454-renderToolCard(
455-{
456-id: "msg:view:7",
457-name: "canvas_render",
458-outputText: JSON.stringify({
459-kind: "canvas",
460-view: {
461-backend: "canvas",
462-id: "cv_counter",
463-url: "/__openclaw__/canvas/documents/cv_counter/index.html",
464-title: "Counter demo",
465-preferred_height: 480,
466-},
467-presentation: {
468-target: "tool_card",
469-},
470-}),
471-preview: {
472-kind: "canvas",
473-surface: "assistant_message",
474-render: "url",
475-viewId: "cv_counter",
476-title: "Counter demo",
477-url: "/__openclaw__/canvas/documents/cv_counter/index.html",
478-preferredHeight: 480,
479-},
480-},
481-{ expanded: true, onToggleExpanded: vi.fn() },
482-),
483-container,
484-);
485-486-const rawToggle = container.querySelector<HTMLButtonElement>(".chat-tool-card__raw-toggle");
487-const rawBody = container.querySelector<HTMLElement>(".chat-tool-card__raw-body");
488-489-expect(container.textContent).toContain("Counter demo");
490-expect(container.querySelector(".chat-tool-card__preview-frame")).toBeNull();
491-expect(rawToggle?.getAttribute("aria-expanded")).toBe("false");
492-expect(rawBody?.hidden).toBe(true);
493-494-rawToggle?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
495-496-expect(rawToggle?.getAttribute("aria-expanded")).toBe("true");
497-expect(rawBody?.hidden).toBe(false);
498-expect(rawBody?.textContent).toContain('"kind":"canvas"');
499-});
500-501-it("opens assistant-surface canvas payloads in the sidebar when explicitly requested", () => {
502-const container = document.createElement("div");
503-const onOpenSidebar = vi.fn();
504-render(
505-renderToolCard(
506-{
507-id: "msg:view:8",
508-name: "canvas_render",
509-outputText: JSON.stringify({
510-kind: "canvas",
511-view: {
512-backend: "canvas",
513-id: "cv_sidebar",
514-url: "/__openclaw__/canvas/documents/cv_sidebar/index.html",
515-title: "Player",
516-preferred_height: 360,
517-},
518-presentation: {
519-target: "assistant_message",
520-},
521-}),
522-preview: {
523-kind: "canvas",
524-surface: "assistant_message",
525-render: "url",
526-viewId: "cv_sidebar",
527-url: "/__openclaw__/canvas/documents/cv_sidebar/index.html",
528-title: "Player",
529-preferredHeight: 360,
530-},
531-},
532-{ expanded: true, onToggleExpanded: vi.fn(), onOpenSidebar },
533-),
534-container,
535-);
536-537-const sidebarButton = container.querySelector<HTMLButtonElement>(".chat-tool-card__action-btn");
538-sidebarButton?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
539-540-expect(sidebarButton).not.toBeNull();
541-expect(onOpenSidebar).toHaveBeenCalledWith(
542-expect.objectContaining({
543-kind: "canvas",
544-docId: "cv_sidebar",
545-entryUrl: "/__openclaw__/canvas/documents/cv_sidebar/index.html",
546-}),
547-);
548-});
549-});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。