mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-01 05:00:20 +00:00
[codex] Polish sidebar status, agent skills, and chat rendering (#45451)
* style: update chat layout and spacing for improved UI consistency - Adjusted margin and padding for .chat-thread and .content--chat to enhance layout. - Consolidated CSS selectors for better readability and maintainability. - Introduced new test for log parsing functionality to ensure accurate message extraction. * UI: polish agent skills, chat images, and sidebar status * test: stabilize vitest helper export types * UI: address review feedback on agents refresh and chat styles * test: update outbound gateway client fixture values * test: narrow shared ip fixtures to IPv4
This commit is contained in:
@@ -46,6 +46,7 @@ describe("runServiceRestart token drift", () => {
|
||||
});
|
||||
resetLifecycleServiceMocks();
|
||||
service.readCommand.mockResolvedValue({
|
||||
programArguments: [],
|
||||
environment: { OPENCLAW_GATEWAY_TOKEN: "service-token" },
|
||||
});
|
||||
stubEmptyGatewayEnv();
|
||||
@@ -77,6 +78,7 @@ describe("runServiceRestart token drift", () => {
|
||||
},
|
||||
});
|
||||
service.readCommand.mockResolvedValue({
|
||||
programArguments: [],
|
||||
environment: { OPENCLAW_GATEWAY_TOKEN: "env-token" },
|
||||
});
|
||||
vi.stubEnv("OPENCLAW_GATEWAY_TOKEN", "env-token");
|
||||
|
||||
@@ -1,16 +1,36 @@
|
||||
import { vi } from "vitest";
|
||||
import type { GatewayService } from "../../../daemon/service.js";
|
||||
import type { RuntimeEnv } from "../../../runtime.js";
|
||||
import type { MockFn } from "../../../test-utils/vitest-mock-fn.js";
|
||||
|
||||
export const runtimeLogs: string[] = [];
|
||||
|
||||
export const defaultRuntime = {
|
||||
log: (message: string) => runtimeLogs.push(message),
|
||||
error: vi.fn(),
|
||||
exit: (code: number) => {
|
||||
throw new Error(`__exit__:${code}`);
|
||||
},
|
||||
type LifecycleRuntimeHarness = RuntimeEnv & {
|
||||
error: MockFn<RuntimeEnv["error"]>;
|
||||
exit: MockFn<RuntimeEnv["exit"]>;
|
||||
};
|
||||
|
||||
export const service = {
|
||||
type LifecycleServiceHarness = GatewayService & {
|
||||
install: MockFn<GatewayService["install"]>;
|
||||
uninstall: MockFn<GatewayService["uninstall"]>;
|
||||
stop: MockFn<GatewayService["stop"]>;
|
||||
isLoaded: MockFn<GatewayService["isLoaded"]>;
|
||||
readCommand: MockFn<GatewayService["readCommand"]>;
|
||||
readRuntime: MockFn<GatewayService["readRuntime"]>;
|
||||
restart: MockFn<GatewayService["restart"]>;
|
||||
};
|
||||
|
||||
export const defaultRuntime: LifecycleRuntimeHarness = {
|
||||
log: (...args: unknown[]) => {
|
||||
runtimeLogs.push(args.map((arg) => String(arg)).join(" "));
|
||||
},
|
||||
error: vi.fn(),
|
||||
exit: vi.fn((code: number) => {
|
||||
throw new Error(`__exit__:${code}`);
|
||||
}),
|
||||
};
|
||||
|
||||
export const service: LifecycleServiceHarness = {
|
||||
label: "TestService",
|
||||
loadedText: "loaded",
|
||||
notLoadedText: "not loaded",
|
||||
@@ -32,7 +52,7 @@ export function resetLifecycleServiceMocks() {
|
||||
service.readCommand.mockClear();
|
||||
service.restart.mockClear();
|
||||
service.isLoaded.mockResolvedValue(true);
|
||||
service.readCommand.mockResolvedValue({ environment: {} });
|
||||
service.readCommand.mockResolvedValue({ programArguments: [], environment: {} });
|
||||
service.restart.mockResolvedValue({ outcome: "completed" });
|
||||
}
|
||||
|
||||
|
||||
@@ -14,9 +14,9 @@ vi.mock("../schtasks-exec.js", () => ({
|
||||
}));
|
||||
|
||||
vi.mock("../../infra/ports.js", () => ({
|
||||
inspectPortUsage: (...args: unknown[]) => inspectPortUsage(...args),
|
||||
inspectPortUsage: (port: number) => inspectPortUsage(port),
|
||||
}));
|
||||
|
||||
vi.mock("../../process/kill-tree.js", () => ({
|
||||
killProcessTree: (...args: unknown[]) => killProcessTree(...args),
|
||||
killProcessTree: (pid: number, opts?: { graceMs?: number }) => killProcessTree(pid, opts),
|
||||
}));
|
||||
|
||||
@@ -2,11 +2,15 @@ import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { vi } from "vitest";
|
||||
import type { PortUsage } from "../../infra/ports-types.js";
|
||||
import type { killProcessTree as killProcessTreeImpl } from "../../process/kill-tree.js";
|
||||
import type { MockFn } from "../../test-utils/vitest-mock-fn.js";
|
||||
|
||||
export const schtasksResponses: Array<{ code: number; stdout: string; stderr: string }> = [];
|
||||
export const schtasksCalls: string[][] = [];
|
||||
export const inspectPortUsage = vi.fn();
|
||||
export const killProcessTree = vi.fn();
|
||||
|
||||
export const inspectPortUsage: MockFn<(port: number) => Promise<PortUsage>> = vi.fn();
|
||||
export const killProcessTree: MockFn<typeof killProcessTreeImpl> = vi.fn();
|
||||
|
||||
export async function withWindowsEnv(
|
||||
prefix: string,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { GATEWAY_CLIENT_MODES, GATEWAY_CLIENT_NAMES } from "../../utils/message-channel.js";
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
getDefaultMediaLocalRoots: vi.fn(() => []),
|
||||
@@ -204,8 +205,8 @@ describe("executeSendAction", () => {
|
||||
url: "http://127.0.0.1:18789",
|
||||
token: "tok",
|
||||
timeoutMs: 5000,
|
||||
clientName: "gateway",
|
||||
mode: "gateway",
|
||||
clientName: GATEWAY_CLIENT_NAMES.GATEWAY_CLIENT,
|
||||
mode: GATEWAY_CLIENT_MODES.BACKEND,
|
||||
},
|
||||
},
|
||||
to: "channel:123",
|
||||
@@ -296,8 +297,8 @@ describe("executeSendAction", () => {
|
||||
url: "http://127.0.0.1:18789",
|
||||
token: "tok",
|
||||
timeoutMs: 5000,
|
||||
clientName: "gateway",
|
||||
mode: "gateway",
|
||||
clientName: GATEWAY_CLIENT_NAMES.GATEWAY_CLIENT,
|
||||
mode: GATEWAY_CLIENT_MODES.BACKEND,
|
||||
},
|
||||
},
|
||||
to: "channel:123",
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
isCanonicalDottedDecimalIPv4,
|
||||
isCarrierGradeNatIpv4Address,
|
||||
isIpInCidr,
|
||||
isIpv4Address,
|
||||
isIpv6Address,
|
||||
isLegacyIpv4Literal,
|
||||
isLoopbackIpAddress,
|
||||
@@ -88,7 +89,7 @@ describe("shared ip helpers", () => {
|
||||
|
||||
expect(loopback?.kind()).toBe("ipv4");
|
||||
expect(benchmark?.kind()).toBe("ipv4");
|
||||
if (!loopback || loopback.kind() !== "ipv4" || !benchmark || benchmark.kind() !== "ipv4") {
|
||||
if (!loopback || !isIpv4Address(loopback) || !benchmark || !isIpv4Address(benchmark)) {
|
||||
throw new Error("expected ipv4 fixtures");
|
||||
}
|
||||
|
||||
|
||||
@@ -3,12 +3,28 @@ import type { OpenClawConfig } from "../config/config.js";
|
||||
import type { ChannelGroupPolicy } from "../config/group-policy.js";
|
||||
import type { TelegramAccountConfig } from "../config/types.js";
|
||||
import type { RuntimeEnv } from "../runtime.js";
|
||||
import type { MockFn } from "../test-utils/vitest-mock-fn.js";
|
||||
import { registerTelegramNativeCommands } from "./bot-native-commands.js";
|
||||
|
||||
type RegisterTelegramNativeCommandsParams = Parameters<typeof registerTelegramNativeCommands>[0];
|
||||
type GetPluginCommandSpecsFn = typeof import("../plugins/commands.js").getPluginCommandSpecs;
|
||||
type MatchPluginCommandFn = typeof import("../plugins/commands.js").matchPluginCommand;
|
||||
type ExecutePluginCommandFn = typeof import("../plugins/commands.js").executePluginCommand;
|
||||
type AnyMock = MockFn<(...args: unknown[]) => unknown>;
|
||||
type AnyAsyncMock = MockFn<(...args: unknown[]) => Promise<unknown>>;
|
||||
type NativeCommandHarness = {
|
||||
handlers: Record<string, (ctx: unknown) => Promise<void>>;
|
||||
sendMessage: AnyAsyncMock;
|
||||
setMyCommands: AnyAsyncMock;
|
||||
log: AnyMock;
|
||||
bot: {
|
||||
api: {
|
||||
setMyCommands: AnyAsyncMock;
|
||||
sendMessage: AnyAsyncMock;
|
||||
};
|
||||
command: (name: string, handler: (ctx: unknown) => Promise<void>) => void;
|
||||
};
|
||||
};
|
||||
|
||||
const pluginCommandMocks = vi.hoisted(() => ({
|
||||
getPluginCommandSpecs: vi.fn<GetPluginCommandSpecsFn>(() => []),
|
||||
@@ -86,12 +102,12 @@ export function createNativeCommandsHarness(params?: {
|
||||
nativeEnabled?: boolean;
|
||||
groupConfig?: Record<string, unknown>;
|
||||
resolveGroupPolicy?: () => ChannelGroupPolicy;
|
||||
}) {
|
||||
}): NativeCommandHarness {
|
||||
const handlers: Record<string, (ctx: unknown) => Promise<void>> = {};
|
||||
const sendMessage = vi.fn().mockResolvedValue(undefined);
|
||||
const setMyCommands = vi.fn().mockResolvedValue(undefined);
|
||||
const log = vi.fn();
|
||||
const bot = {
|
||||
const sendMessage: AnyAsyncMock = vi.fn(async () => undefined);
|
||||
const setMyCommands: AnyAsyncMock = vi.fn(async () => undefined);
|
||||
const log: AnyMock = vi.fn();
|
||||
const bot: NativeCommandHarness["bot"] = {
|
||||
api: {
|
||||
setMyCommands,
|
||||
sendMessage,
|
||||
@@ -153,7 +169,7 @@ export function createTelegramGroupCommandContext(params?: {
|
||||
};
|
||||
}
|
||||
|
||||
export function findNotAuthorizedCalls(sendMessage: ReturnType<typeof vi.fn>) {
|
||||
export function findNotAuthorizedCalls(sendMessage: AnyAsyncMock) {
|
||||
return sendMessage.mock.calls.filter(
|
||||
(call) => typeof call[1] === "string" && call[1].includes("not authorized"),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user