fix: resolve ci type errors and reconnect test flake

This commit is contained in:
Peter Steinberger
2026-02-22 21:35:11 +00:00
parent d75b594e07
commit 7c109f5737
8 changed files with 59 additions and 23 deletions

View File

@@ -76,8 +76,15 @@ describe("buildWorkspaceSkillSnapshot", () => {
config,
managedSkillsDir: path.join(workspaceDir, ".managed"),
bundledSkillsDir: path.join(workspaceDir, ".bundled"),
eligibility: { remote: { note: "Remote note" } },
} as const;
eligibility: {
remote: {
platforms: ["linux"],
hasBin: (_bin: string) => true,
hasAnyBin: (_bins: string[]) => true,
note: "Remote note",
},
},
};
const snapshot = buildWorkspaceSkillSnapshot(workspaceDir, opts);
const prompt = buildWorkspaceSkillsPrompt(workspaceDir, opts);

View File

@@ -1,4 +1,5 @@
import crypto from "node:crypto";
import type { AgentToolResult } from "@mariozechner/pi-agent-core";
import {
browserAct,
browserArmDialog,
@@ -54,14 +55,17 @@ function wrapBrowserExternalJson(params: {
};
}
function formatTabsToolResult(tabs: unknown[]) {
function formatTabsToolResult(tabs: unknown[]): AgentToolResult<unknown> {
const wrapped = wrapBrowserExternalJson({
kind: "tabs",
payload: { tabs },
includeWarning: false,
});
const content: AgentToolResult<unknown>["content"] = [
{ type: "text", text: wrapped.wrappedText },
];
return {
content: [{ type: "text", text: wrapped.wrappedText }],
content,
details: { ...wrapped.safeDetails, tabCount: tabs.length },
};
}

View File

@@ -4,7 +4,7 @@ import type { OpenClawConfig } from "../config/config.js";
export type ChannelDefaultAccountContext = {
accountIds: string[];
defaultAccountId?: string;
defaultAccountId: string;
account: unknown;
enabled: boolean;
configured: boolean;

View File

@@ -1,4 +1,5 @@
import { describe, expect, it } from "vitest";
import type { OpenClawConfig } from "../config/config.js";
import type { AgentModelEntryConfig } from "../config/types.agent-defaults.js";
import type { ModelDefinitionConfig } from "../config/types.models.js";
import {
@@ -25,7 +26,7 @@ describe("onboard auth provider config merges", () => {
};
it("appends missing default models to existing provider models", () => {
const cfg = {
const cfg: OpenClawConfig = {
models: {
providers: {
custom: {
@@ -56,7 +57,7 @@ describe("onboard auth provider config merges", () => {
});
it("merges model catalogs without duplicating existing model ids", () => {
const cfg = {
const cfg: OpenClawConfig = {
models: {
providers: {
custom: {

View File

@@ -383,7 +383,11 @@ export async function rejectDevicePairing(
baseDir?: string,
): Promise<{ requestId: string; deviceId: string } | null> {
return await withLock(async () => {
return await rejectPendingPairingRequest({
return await rejectPendingPairingRequest<
DevicePairingPendingRequest,
DevicePairingStateFile,
"deviceId"
>({
requestId,
idKey: "deviceId",
loadState: () => loadState(baseDir),

View File

@@ -195,7 +195,11 @@ export async function rejectNodePairing(
baseDir?: string,
): Promise<{ requestId: string; nodeId: string } | null> {
return await withLock(async () => {
return await rejectPendingPairingRequest({
return await rejectPendingPairingRequest<
NodePairingPendingRequest,
NodePairingStateFile,
"nodeId"
>({
requestId,
idKey: "nodeId",
loadState: () => loadState(baseDir),

View File

@@ -1,20 +1,25 @@
type BatchOutputErrorLike = {
error?: { message?: string };
response?: {
body?: {
error?: { message?: string };
};
body?:
| string
| {
error?: { message?: string };
};
};
};
function getResponseErrorMessage(line: BatchOutputErrorLike | undefined): string | undefined {
const body = line?.response?.body;
if (!body || typeof body !== "object") {
return undefined;
}
return typeof body.error?.message === "string" ? body.error.message : undefined;
}
export function extractBatchErrorMessage(lines: BatchOutputErrorLike[]): string | undefined {
const first = lines.find((line) => line.error?.message || line.response?.body?.error);
return (
first?.error?.message ??
(typeof first?.response?.body?.error?.message === "string"
? first?.response?.body?.error?.message
: undefined)
);
const first = lines.find((line) => line.error?.message || getResponseErrorMessage(line));
return first?.error?.message ?? getResponseErrorMessage(first);
}
export function formatUnavailableBatchError(err: unknown): string | undefined {

View File

@@ -127,6 +127,7 @@ describe("web auto-reply", () => {
try {
const sleep = vi.fn(async () => {});
const closeResolvers: Array<(reason: unknown) => void> = [];
const signalCloseSpy = vi.fn();
let capturedOnMessage:
| ((msg: import("./inbound.js").WebInboundMessage) => Promise<void>)
| undefined;
@@ -143,11 +144,14 @@ describe("web auto-reply", () => {
return {
close: vi.fn(),
onClose,
signalClose: (reason?: unknown) => resolveClose(reason),
signalClose: (reason?: unknown) => {
signalCloseSpy(reason);
resolveClose(reason);
},
};
},
);
const { controller, run } = startMonitorWebChannel({
const { runtime, controller, run } = startMonitorWebChannel({
monitorWebChannelFn: monitorWebChannel as never,
listenerFactory,
sleep,
@@ -179,8 +183,15 @@ describe("web auto-reply", () => {
await Promise.resolve();
await vi.advanceTimersByTimeAsync(1);
await Promise.resolve();
expect(listenerFactory).toHaveBeenCalledTimes(2);
expect(signalCloseSpy).toHaveBeenCalledWith(
expect.objectContaining({ status: 499, isLoggedOut: false, error: "watchdog-timeout" }),
);
for (let i = 0; i < 20 && listenerFactory.mock.calls.length < 2; i += 1) {
await vi.advanceTimersByTimeAsync(50);
await Promise.resolve();
}
expect(listenerFactory.mock.calls.length).toBeGreaterThanOrEqual(2);
expect(runtime.error).toHaveBeenCalledWith(expect.stringContaining("Retry 1"));
controller.abort();
closeResolvers[1]?.({ status: 499, isLoggedOut: false });