mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-28 12:36:55 +02:00
perf: speed up focused tests
This commit is contained in:
@@ -253,7 +253,13 @@ const SOURCE_TEST_TARGETS = new Map([
|
||||
["extensions/google-meet/src/cli.ts", ["extensions/google-meet/src/cli.test.ts"]],
|
||||
["extensions/google-meet/src/create.ts", ["extensions/google-meet/index.test.ts"]],
|
||||
["extensions/google-meet/src/oauth.ts", ["extensions/google-meet/src/oauth.test.ts"]],
|
||||
["src/commands/doctor-memory-search.ts", ["src/commands/doctor-memory-search.test.ts"]],
|
||||
["src/agents/live-model-turn-probes.ts", ["src/agents/live-model-turn-probes.test.ts"]],
|
||||
[
|
||||
"src/memory-host-sdk/host/embedding-defaults.ts",
|
||||
["src/memory-host-sdk/host/embeddings.test.ts"],
|
||||
],
|
||||
["src/memory-host-sdk/host/embeddings.ts", ["src/memory-host-sdk/host/embeddings.test.ts"]],
|
||||
[
|
||||
"src/auto-reply/reply/dispatch-from-config.ts",
|
||||
["src/auto-reply/reply/dispatch-from-config.test.ts"],
|
||||
|
||||
@@ -14,8 +14,8 @@ import {
|
||||
import { formatCliCommand } from "../cli/command-format.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { formatErrorMessage } from "../infra/errors.js";
|
||||
import { DEFAULT_LOCAL_MODEL } from "../memory-host-sdk/engine-embeddings.js";
|
||||
import { checkQmdBinaryAvailability } from "../memory-host-sdk/engine-qmd.js";
|
||||
import { DEFAULT_LOCAL_MODEL } from "../memory-host-sdk/host/embedding-defaults.js";
|
||||
import { hasConfiguredMemorySecretInput } from "../memory-host-sdk/secret.js";
|
||||
import {
|
||||
auditDreamingArtifacts,
|
||||
|
||||
2
src/memory-host-sdk/host/embedding-defaults.ts
Normal file
2
src/memory-host-sdk/host/embedding-defaults.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export const DEFAULT_LOCAL_MODEL =
|
||||
"hf:ggml-org/embeddinggemma-300m-qat-q8_0-GGUF/embeddinggemma-300m-qat-Q8_0.gguf";
|
||||
@@ -1,4 +1,5 @@
|
||||
import { normalizeOptionalString } from "../../shared/string-coerce.js";
|
||||
import { DEFAULT_LOCAL_MODEL } from "./embedding-defaults.js";
|
||||
import { sanitizeAndNormalizeEmbedding } from "./embedding-vectors.js";
|
||||
import type { EmbeddingProvider, EmbeddingProviderOptions } from "./embeddings.types.js";
|
||||
import {
|
||||
@@ -17,8 +18,7 @@ export type {
|
||||
GeminiTaskType,
|
||||
} from "./embeddings.types.js";
|
||||
|
||||
export const DEFAULT_LOCAL_MODEL =
|
||||
"hf:ggml-org/embeddinggemma-300m-qat-q8_0-GGUF/embeddinggemma-300m-qat-Q8_0.gguf";
|
||||
export { DEFAULT_LOCAL_MODEL } from "./embedding-defaults.js";
|
||||
|
||||
export async function createLocalEmbeddingProvider(
|
||||
options: EmbeddingProviderOptions,
|
||||
|
||||
@@ -323,6 +323,22 @@ describe("scripts/test-projects changed-target routing", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("routes memory doctor and embedding default edits to focused tests", () => {
|
||||
expect(
|
||||
resolveChangedTestTargetPlan([
|
||||
"src/commands/doctor-memory-search.ts",
|
||||
"src/memory-host-sdk/host/embedding-defaults.ts",
|
||||
"src/memory-host-sdk/host/embeddings.ts",
|
||||
]),
|
||||
).toEqual({
|
||||
mode: "targets",
|
||||
targets: [
|
||||
"src/commands/doctor-memory-search.test.ts",
|
||||
"src/memory-host-sdk/host/embeddings.test.ts",
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("routes changed utils and shared files to their light scoped lanes", () => {
|
||||
const plans = buildVitestRunPlans(["--changed", "origin/main"], process.cwd(), () => [
|
||||
"src/shared/string-normalization.ts",
|
||||
|
||||
@@ -243,61 +243,32 @@ describe("grouped chat rendering", () => {
|
||||
expect(assistantConfirm?.classList.contains("chat-delete-confirm--right")).toBe(true);
|
||||
});
|
||||
|
||||
it("falls back to the local logo when the assistant avatar is a remote URL", () => {
|
||||
const container = document.createElement("div");
|
||||
it("renders assistant avatar variants", () => {
|
||||
const renderAvatar = (assistantAvatar: string) => {
|
||||
const container = document.createElement("div");
|
||||
renderAssistantMessage(
|
||||
container,
|
||||
{
|
||||
role: "assistant",
|
||||
content: "hello",
|
||||
timestamp: 1000,
|
||||
},
|
||||
{ assistantAvatar, assistantName: "Val" },
|
||||
);
|
||||
return container.querySelector<HTMLElement>(".chat-avatar.assistant");
|
||||
};
|
||||
|
||||
renderAssistantMessage(
|
||||
container,
|
||||
{
|
||||
role: "assistant",
|
||||
content: "hello",
|
||||
timestamp: 1000,
|
||||
},
|
||||
{ assistantAvatar: "https://example.com/avatar.png" },
|
||||
);
|
||||
const remoteAvatar = renderAvatar("https://example.com/avatar.png");
|
||||
expect(remoteAvatar?.getAttribute("src")).toBe("/openclaw-logo.svg");
|
||||
|
||||
const avatar = container.querySelector<HTMLImageElement>(".chat-avatar.assistant");
|
||||
expect(avatar).not.toBeNull();
|
||||
expect(avatar?.getAttribute("src")).toBe("/openclaw-logo.svg");
|
||||
});
|
||||
const blobAvatar = renderAvatar("blob:managed-image");
|
||||
expect(blobAvatar?.tagName).toBe("IMG");
|
||||
expect(blobAvatar?.getAttribute("src")).toBe("blob:managed-image");
|
||||
|
||||
it("renders a blob: assistant avatar as an image", () => {
|
||||
const container = document.createElement("div");
|
||||
|
||||
renderAssistantMessage(
|
||||
container,
|
||||
{
|
||||
role: "assistant",
|
||||
content: "hello",
|
||||
timestamp: 1000,
|
||||
},
|
||||
{ assistantAvatar: "blob:managed-image", assistantName: "Val" },
|
||||
);
|
||||
|
||||
const avatar = container.querySelector<HTMLImageElement>(".chat-avatar.assistant");
|
||||
expect(avatar).not.toBeNull();
|
||||
expect(avatar?.tagName).toBe("IMG");
|
||||
expect(avatar?.getAttribute("src")).toBe("blob:managed-image");
|
||||
});
|
||||
|
||||
it("renders a configured assistant text avatar", () => {
|
||||
const container = document.createElement("div");
|
||||
|
||||
renderAssistantMessage(
|
||||
container,
|
||||
{
|
||||
role: "assistant",
|
||||
content: "hello",
|
||||
timestamp: 1000,
|
||||
},
|
||||
{ assistantAvatar: "VC", assistantName: "Val" },
|
||||
);
|
||||
|
||||
const avatar = container.querySelector<HTMLElement>(".chat-avatar.assistant");
|
||||
expect(avatar).not.toBeNull();
|
||||
expect(avatar?.tagName).toBe("DIV");
|
||||
expect(avatar?.textContent).toContain("VC");
|
||||
expect(avatar?.getAttribute("aria-label")).toBe("Val");
|
||||
const textAvatar = renderAvatar("VC");
|
||||
expect(textAvatar?.tagName).toBe("DIV");
|
||||
expect(textAvatar?.textContent).toContain("VC");
|
||||
expect(textAvatar?.getAttribute("aria-label")).toBe("Val");
|
||||
});
|
||||
|
||||
it("rejects unsafe invisible controls in assistant text avatars", () => {
|
||||
@@ -307,129 +278,80 @@ describe("grouped chat rendering", () => {
|
||||
expect(resolveAssistantTextAvatar("V\u200bC")).toBeNull();
|
||||
});
|
||||
|
||||
it("includes cache tokens when rendering assistant context usage", () => {
|
||||
const container = document.createElement("div");
|
||||
|
||||
renderAssistantMessage(
|
||||
container,
|
||||
{
|
||||
role: "assistant",
|
||||
content: "Done",
|
||||
usage: {
|
||||
input: 1,
|
||||
output: 1200,
|
||||
cacheRead: 438_400,
|
||||
cacheWrite: 307,
|
||||
it("renders assistant context usage from input and cache tokens", () => {
|
||||
const renderUsage = (usage: Record<string, number>, contextWindow: number) => {
|
||||
const container = document.createElement("div");
|
||||
renderAssistantMessage(
|
||||
container,
|
||||
{
|
||||
role: "assistant",
|
||||
content: "Done",
|
||||
usage,
|
||||
model: "anthropic/claude-opus-4-7",
|
||||
timestamp: 1000,
|
||||
},
|
||||
model: "anthropic/claude-opus-4-7",
|
||||
timestamp: 1000,
|
||||
},
|
||||
{ contextWindow: 1_000_000 },
|
||||
);
|
||||
{ contextWindow },
|
||||
);
|
||||
return container;
|
||||
};
|
||||
|
||||
expect(container.querySelector(".msg-meta__ctx")?.textContent).toBe("44% ctx");
|
||||
expect(container.textContent).toContain("R438.4k");
|
||||
expect(container.textContent).toContain("W307");
|
||||
const cached = renderUsage(
|
||||
{
|
||||
input: 1,
|
||||
output: 1200,
|
||||
cacheRead: 438_400,
|
||||
cacheWrite: 307,
|
||||
},
|
||||
1_000_000,
|
||||
);
|
||||
expect(cached.querySelector(".msg-meta__ctx")?.textContent).toBe("44% ctx");
|
||||
expect(cached.textContent).toContain("R438.4k");
|
||||
expect(cached.textContent).toContain("W307");
|
||||
|
||||
const outputHeavy = renderUsage(
|
||||
{
|
||||
input: 1_000,
|
||||
output: 9_000,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
10_000,
|
||||
);
|
||||
expect(outputHeavy.querySelector(".msg-meta__ctx")?.textContent).toBe("10% ctx");
|
||||
});
|
||||
|
||||
it("excludes output tokens when rendering assistant context usage", () => {
|
||||
const container = document.createElement("div");
|
||||
|
||||
renderAssistantMessage(
|
||||
container,
|
||||
{
|
||||
role: "assistant",
|
||||
content: "Long response",
|
||||
usage: {
|
||||
input: 1_000,
|
||||
output: 9_000,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
it("renders configured local user names and avatar variants", () => {
|
||||
const renderUser = (opts: Partial<RenderMessageGroupOptions>) => {
|
||||
const container = document.createElement("div");
|
||||
renderGroupedMessage(
|
||||
container,
|
||||
{
|
||||
role: "user",
|
||||
content: "hello",
|
||||
timestamp: 1000,
|
||||
},
|
||||
timestamp: 1000,
|
||||
},
|
||||
{ contextWindow: 10_000 },
|
||||
);
|
||||
"user",
|
||||
opts,
|
||||
);
|
||||
return container;
|
||||
};
|
||||
|
||||
expect(container.querySelector(".msg-meta__ctx")?.textContent).toBe("10% ctx");
|
||||
});
|
||||
|
||||
it("renders the configured local user name in user message footers", () => {
|
||||
const container = document.createElement("div");
|
||||
|
||||
renderGroupedMessage(
|
||||
container,
|
||||
{
|
||||
role: "user",
|
||||
content: "hello",
|
||||
timestamp: 1000,
|
||||
},
|
||||
"user",
|
||||
{ userName: "Buns" },
|
||||
);
|
||||
|
||||
const sender = container.querySelector<HTMLElement>(".chat-group.user .chat-sender-name");
|
||||
const named = renderUser({ userName: "Buns" });
|
||||
const sender = named.querySelector<HTMLElement>(".chat-group.user .chat-sender-name");
|
||||
expect(sender?.textContent).toBe("Buns");
|
||||
});
|
||||
|
||||
it("renders a local user image avatar when provided", () => {
|
||||
const container = document.createElement("div");
|
||||
for (const src of ["data:image/png;base64,AAA", "/avatar/user"]) {
|
||||
const container = renderUser({ userName: "Buns", userAvatar: src });
|
||||
const avatar = container.querySelector<HTMLImageElement>(".chat-avatar.user");
|
||||
expect(avatar?.getAttribute("src")).toBe(src);
|
||||
expect(avatar?.getAttribute("alt")).toBe("Buns");
|
||||
}
|
||||
|
||||
renderGroupedMessage(
|
||||
container,
|
||||
{
|
||||
role: "user",
|
||||
content: "hello",
|
||||
timestamp: 1000,
|
||||
},
|
||||
"user",
|
||||
{ userName: "Buns", userAvatar: "data:image/png;base64,AAA" },
|
||||
const textAvatar = renderUser({ userAvatar: "🦞" }).querySelector<HTMLElement>(
|
||||
".chat-avatar.user",
|
||||
);
|
||||
|
||||
const avatar = container.querySelector<HTMLImageElement>(".chat-avatar.user");
|
||||
expect(avatar).not.toBeNull();
|
||||
expect(avatar?.getAttribute("src")).toBe("data:image/png;base64,AAA");
|
||||
expect(avatar?.getAttribute("alt")).toBe("Buns");
|
||||
});
|
||||
|
||||
it("renders a local user avatar route when provided", () => {
|
||||
const container = document.createElement("div");
|
||||
|
||||
renderGroupedMessage(
|
||||
container,
|
||||
{
|
||||
role: "user",
|
||||
content: "hello",
|
||||
timestamp: 1000,
|
||||
},
|
||||
"user",
|
||||
{ userName: "Buns", userAvatar: "/avatar/user" },
|
||||
);
|
||||
|
||||
const avatar = container.querySelector<HTMLImageElement>(".chat-avatar.user");
|
||||
expect(avatar).not.toBeNull();
|
||||
expect(avatar?.getAttribute("src")).toBe("/avatar/user");
|
||||
expect(avatar?.getAttribute("alt")).toBe("Buns");
|
||||
});
|
||||
|
||||
it("renders a local user text avatar when provided", () => {
|
||||
const container = document.createElement("div");
|
||||
|
||||
renderGroupedMessage(
|
||||
container,
|
||||
{
|
||||
role: "user",
|
||||
content: "hello",
|
||||
timestamp: 1000,
|
||||
},
|
||||
"user",
|
||||
{ userAvatar: "🦞" },
|
||||
);
|
||||
|
||||
const avatar = container.querySelector<HTMLElement>(".chat-avatar.user");
|
||||
expect(avatar).not.toBeNull();
|
||||
expect(avatar?.tagName).toBe("DIV");
|
||||
expect(avatar?.textContent).toContain("🦞");
|
||||
expect(textAvatar?.tagName).toBe("DIV");
|
||||
expect(textAvatar?.textContent).toContain("🦞");
|
||||
});
|
||||
|
||||
it("keeps inline tool cards collapsed by default and renders expanded state", () => {
|
||||
|
||||
Reference in New Issue
Block a user