mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 09:30:43 +00:00
fix: address markdown preview follow-ups
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
export {
|
||||
DEFAULT_AI_SNAPSHOT_MAX_CHARS,
|
||||
DEFAULT_BROWSER_ACTION_TIMEOUT_MS,
|
||||
DEFAULT_BROWSER_DEFAULT_PROFILE_NAME,
|
||||
DEFAULT_BROWSER_EVALUATE_ENABLED,
|
||||
DEFAULT_OPENCLAW_BROWSER_COLOR,
|
||||
|
||||
@@ -35,6 +35,7 @@ import { DEFAULT_UPLOAD_DIR } from "./paths.js";
|
||||
|
||||
export {
|
||||
DEFAULT_AI_SNAPSHOT_MAX_CHARS,
|
||||
DEFAULT_BROWSER_ACTION_TIMEOUT_MS,
|
||||
DEFAULT_BROWSER_DEFAULT_PROFILE_NAME,
|
||||
DEFAULT_BROWSER_EVALUATE_ENABLED,
|
||||
DEFAULT_OPENCLAW_BROWSER_COLOR,
|
||||
|
||||
@@ -263,7 +263,9 @@ describe("gateway update.run", () => {
|
||||
);
|
||||
const res = await onceMessage(ws, (o) => o.type === "res" && o.id === id);
|
||||
expect(res.ok).toBe(true);
|
||||
expect(updateMock).toHaveBeenCalledOnce();
|
||||
await vi.waitFor(() => {
|
||||
expect(updateMock).toHaveBeenCalledOnce();
|
||||
}, FAST_WAIT_OPTS);
|
||||
} finally {
|
||||
process.off("SIGUSR1", sigusr1);
|
||||
}
|
||||
|
||||
@@ -128,6 +128,7 @@ const BROWSER_HELPER_EXPORT_PARITY_CONTRACTS: readonly BrowserHelperExportParity
|
||||
extensionPath: "extensions/browser/browser-profiles.ts",
|
||||
expectedExports: [
|
||||
"DEFAULT_AI_SNAPSHOT_MAX_CHARS",
|
||||
"DEFAULT_BROWSER_ACTION_TIMEOUT_MS",
|
||||
"DEFAULT_BROWSER_DEFAULT_PROFILE_NAME",
|
||||
"DEFAULT_BROWSER_EVALUATE_ENABLED",
|
||||
"DEFAULT_OPENCLAW_BROWSER_COLOR",
|
||||
|
||||
@@ -303,10 +303,14 @@ export function renderToolPreview(
|
||||
`;
|
||||
}
|
||||
|
||||
export function buildSidebarContent(value: string): SidebarContent {
|
||||
export function buildSidebarContent(
|
||||
value: string,
|
||||
options?: { rawText?: string | null },
|
||||
): SidebarContent {
|
||||
return {
|
||||
kind: "markdown",
|
||||
content: value,
|
||||
...(options?.rawText ? { rawText: options.rawText } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
export type MarkdownSidebarContent = {
|
||||
kind: "markdown";
|
||||
content: string;
|
||||
rawText?: string | null;
|
||||
};
|
||||
|
||||
export type CanvasSidebarContent = {
|
||||
|
||||
@@ -47,6 +47,28 @@ function getExtensionLabel(fileName: string) {
|
||||
return ext ? `${ext.toUpperCase()} Preview` : "Preview";
|
||||
}
|
||||
|
||||
function formatWorkspaceRelativePath(filePath: string, workspace: string | null | undefined) {
|
||||
const normalizedPath = filePath.trim();
|
||||
const normalizedWorkspace = workspace?.trim();
|
||||
if (!normalizedPath) {
|
||||
return "";
|
||||
}
|
||||
if (normalizedWorkspace && normalizedPath === normalizedWorkspace) {
|
||||
return ".";
|
||||
}
|
||||
if (normalizedWorkspace && normalizedPath.startsWith(`${normalizedWorkspace}/`)) {
|
||||
return normalizedPath.slice(normalizedWorkspace.length + 1) || ".";
|
||||
}
|
||||
const pathParts = normalizedPath.split(/[\\/]+/);
|
||||
for (let index = pathParts.length - 1; index >= 0; index -= 1) {
|
||||
const pathPart = pathParts[index];
|
||||
if (pathPart) {
|
||||
return pathPart;
|
||||
}
|
||||
}
|
||||
return normalizedPath;
|
||||
}
|
||||
|
||||
function toDomId(value: string) {
|
||||
const normalized = value.toLowerCase().replace(/[^a-z0-9]+/g, "-");
|
||||
return normalized.replace(/^-+|-+$/g, "") || "preview";
|
||||
@@ -413,6 +435,9 @@ export function renderAgentFiles(params: {
|
||||
const draftByteSize = formatBytes(new TextEncoder().encode(draft).length);
|
||||
const draftWordCount = countWords(draft);
|
||||
const draftLineCount = countLines(draft);
|
||||
const activePathLabel = activeEntry
|
||||
? formatWorkspaceRelativePath(activeEntry.path, list?.workspace)
|
||||
: "";
|
||||
const previewTitleId = activeEntry ? `agent-file-preview-title-${toDomId(activeEntry.name)}` : "";
|
||||
const previewStatusLabel = activeEntry?.missing
|
||||
? "Will Create on Save"
|
||||
@@ -574,7 +599,7 @@ export function renderAgentFiles(params: {
|
||||
${activeEntry.name}
|
||||
</div>
|
||||
<div class="md-preview-dialog__path mono" translate="no">
|
||||
${activeEntry.path}
|
||||
${activePathLabel}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -220,7 +220,7 @@ describe("renderAgentFiles", () => {
|
||||
|
||||
expect(container.querySelector(".md-preview-dialog__reader.sidebar-markdown")).not.toBeNull();
|
||||
expect(container.querySelector(".md-preview-dialog__path")?.textContent?.trim()).toBe(
|
||||
"/tmp/workspace/USER.md",
|
||||
"USER.md",
|
||||
);
|
||||
expect(container.querySelector(".md-preview-dialog__chip strong")?.textContent).toBe(
|
||||
"Saved Preview",
|
||||
|
||||
@@ -111,6 +111,42 @@ describe("renderChat", () => {
|
||||
cleanupChatModuleState();
|
||||
});
|
||||
|
||||
it("keeps markdown raw text toggles idempotent", () => {
|
||||
const container = document.createElement("div");
|
||||
const onOpenSidebar = vi.fn();
|
||||
const rawMarkdown = "```ts\nconst value = 1;\n```";
|
||||
|
||||
render(
|
||||
renderChat(
|
||||
createProps({
|
||||
sidebarOpen: true,
|
||||
sidebarContent: {
|
||||
kind: "markdown",
|
||||
content: `\`\`\`\n${rawMarkdown}\n\`\`\``,
|
||||
rawText: rawMarkdown,
|
||||
},
|
||||
stream: null,
|
||||
streamStartedAt: null,
|
||||
onCloseSidebar: () => undefined,
|
||||
onOpenSidebar,
|
||||
}),
|
||||
),
|
||||
container,
|
||||
);
|
||||
|
||||
const rawButton = Array.from(container.querySelectorAll<HTMLButtonElement>("button")).find(
|
||||
(button) => button.textContent?.includes("View Raw Text"),
|
||||
);
|
||||
rawButton?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
||||
|
||||
expect(rawButton).not.toBeNull();
|
||||
expect(onOpenSidebar).toHaveBeenCalledWith({
|
||||
kind: "markdown",
|
||||
content: `\`\`\`\n${rawMarkdown}\n\`\`\``,
|
||||
rawText: rawMarkdown,
|
||||
});
|
||||
});
|
||||
|
||||
it("renders configured assistant text avatars in transcript groups", () => {
|
||||
const container = document.createElement("div");
|
||||
|
||||
|
||||
@@ -141,6 +141,11 @@ function getPinnedMessages(sessionKey: string): PinnedMessages {
|
||||
);
|
||||
}
|
||||
|
||||
function toPlainTextCodeFence(value: string, language = ""): string {
|
||||
const fenceHeader = language ? `\`\`\`${language}` : "```";
|
||||
return `${fenceHeader}\n${value}\n\`\`\``;
|
||||
}
|
||||
|
||||
function getDeletedMessages(sessionKey: string): DeletedMessages {
|
||||
return getOrCreateSessionCacheValue(
|
||||
deletedMessagesMap,
|
||||
@@ -1129,14 +1134,17 @@ export function renderChat(props: ChatProps) {
|
||||
return;
|
||||
}
|
||||
if (props.sidebarContent.kind === "markdown") {
|
||||
const rawText = props.sidebarContent.rawText ?? props.sidebarContent.content;
|
||||
props.onOpenSidebar(
|
||||
buildSidebarContent(`\`\`\`\n${props.sidebarContent.content}\n\`\`\``),
|
||||
buildSidebarContent(toPlainTextCodeFence(rawText), { rawText }),
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (props.sidebarContent.rawText?.trim()) {
|
||||
props.onOpenSidebar(
|
||||
buildSidebarContent(`\`\`\`json\n${props.sidebarContent.rawText}\n\`\`\``),
|
||||
buildSidebarContent(
|
||||
toPlainTextCodeFence(props.sidebarContent.rawText, "json"),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user