mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-31 02:18:08 +00:00
chore(lint): upgrade oxlint to 1.79.0 (#132682)
* chore(lint): upgrade oxlint to 1.79.0 * test(ui): make incremental markdown scan proof deterministic
This commit is contained in:
parent
8b1da5547a
commit
2ac40dedbe
31 changed files with 333 additions and 192 deletions
|
|
@ -394,6 +394,20 @@
|
|||
"rules": {
|
||||
"max-lines": ["error", { "max": 1200, "skipBlankLines": true, "skipComments": true }]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["**/*.{ts,tsx,mts,cts}"],
|
||||
"rules": {
|
||||
// tsgo owns TypeScript type/value namespace validity; no-var still rejects var declarations.
|
||||
"eslint/no-redeclare": "off"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["extensions/qa-lab/src/web-runtime.ts"],
|
||||
"rules": {
|
||||
// Scenario scripts need page-global declarations, unlike Playwright's expression evaluation.
|
||||
"eslint/no-eval": ["error", { "allowIndirect": true }]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
12
docs/ci.md
12
docs/ci.md
|
|
@ -442,6 +442,18 @@ ratchet-down when cleanup lowers the real count.
|
|||
|
||||
## Local equivalents
|
||||
|
||||
Oxlint keeps `eslint/no-redeclare` enabled for JavaScript. For `.ts`, `.tsx`,
|
||||
`.mts`, and `.cts`, `tsgo` owns declaration validity, including intentional
|
||||
type/value pairs with the same public name. `eslint/no-var` remains enabled
|
||||
for all source formats; the compiler does not reject every `var` redeclaration.
|
||||
|
||||
`eslint/no-eval` rejects direct and indirect evaluation by default. Only
|
||||
`extensions/qa-lab/src/web-runtime.ts` allows indirect evaluation, because QA
|
||||
scenario scripts need page-global declaration semantics that Playwright's
|
||||
expression evaluation does not preserve. Direct evaluation remains an error
|
||||
there. Tests that execute emitted browser scripts use isolated `node:vm`
|
||||
contexts instead of process-global evaluation.
|
||||
|
||||
```bash
|
||||
pnpm changed:lanes # inspect the local changed-lane classifier for origin/main...HEAD
|
||||
pnpm check:changed # smart local check gate: changed formatting/typecheck/lint/guards by boundary lane
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ const providerMonitorTestMocks: ProviderMonitorTestMocks = vi.hoisted(() => {
|
|||
monitorLifecycleMock: vi.fn(async (params: { threadBindings: { stop: () => void } }) => {
|
||||
params.threadBindings.stop();
|
||||
}),
|
||||
resolveDiscordAccountMock: vi.fn((_) => ({
|
||||
resolveDiscordAccountMock: vi.fn((_params) => ({
|
||||
accountId: "default",
|
||||
token: "cfg-token",
|
||||
config: baseDiscordAccountConfig(),
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { runInNewContext } from "node:vm";
|
||||
import { Command } from "commander";
|
||||
// Google Meet tests cover index.create plugin behavior.
|
||||
import { createRequireRecord } from "openclaw/plugin-sdk/test-fixtures";
|
||||
|
|
@ -94,8 +95,6 @@ async function runCreateMeetBrowserScript(params: { buttonText: string }) {
|
|||
},
|
||||
querySelectorAll: (selector: string) => (selector === "button" ? [button] : []),
|
||||
};
|
||||
vi.stubGlobal("document", document);
|
||||
vi.stubGlobal("location", location);
|
||||
type BrowserScriptResult = {
|
||||
meetingUri?: string;
|
||||
manualAction?: { reason: string; message: string };
|
||||
|
|
@ -115,8 +114,10 @@ async function runCreateMeetBrowserScript(params: { buttonText: string }) {
|
|||
if (typeof body.fn !== "string") {
|
||||
throw new Error("expected browser create script");
|
||||
}
|
||||
const fn = (0, eval)(`(${body.fn})`) as () => Promise<BrowserScriptResult>;
|
||||
scriptResult = await fn();
|
||||
scriptResult = await (runInNewContext(`(${body.fn})()`, {
|
||||
document,
|
||||
location,
|
||||
}) as Promise<BrowserScriptResult>);
|
||||
return {
|
||||
manualAction: {
|
||||
reason: "meet-permission-required",
|
||||
|
|
|
|||
|
|
@ -35,9 +35,9 @@ const loadConfigMock = vi.fn(() => ({}));
|
|||
const withResolvedRuntimeMatrixClientMock = vi.hoisted(() => vi.fn());
|
||||
const getImageMetadataMock = vi.fn().mockResolvedValue(null);
|
||||
const resizeToJpegMock = vi.fn();
|
||||
const mediaKindFromMimeMock = vi.fn((_: string | null | undefined) => "image");
|
||||
const mediaKindFromMimeMock = vi.fn((_mime: string | null | undefined) => "image");
|
||||
const isVoiceCompatibleAudioMock = vi.fn(
|
||||
(_: { contentType?: string | null; fileName?: string | null }) => false,
|
||||
(_options: { contentType?: string | null; fileName?: string | null }) => false,
|
||||
);
|
||||
const resolveTextChunkLimitMock = vi.fn<
|
||||
(cfg: unknown, channel: unknown, accountId?: unknown) => number
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ const resolveOwningPluginIdsForProviderMock = vi.hoisted(() =>
|
|||
vi.fn<ResolveOwningPluginIdsForProvider>(() => undefined),
|
||||
);
|
||||
const resolveCatalogHookProviderPluginIdsMock = vi.hoisted(() =>
|
||||
vi.fn<ResolveCatalogHookProviderPluginIds>((_) => [] as string[]),
|
||||
vi.fn<ResolveCatalogHookProviderPluginIds>((_params) => [] as string[]),
|
||||
);
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/provider-catalog-runtime", async () => {
|
||||
|
|
|
|||
|
|
@ -125,8 +125,6 @@ export class QaGatewayChildLifecycle {
|
|||
? new QaSuiteInfraError(error.code, message, { cause: error })
|
||||
: new Error(message, { cause: error });
|
||||
if (result.errors.length) {
|
||||
// Oxlint 1.78 checks cause at argument 2; AggregateError takes it at 3.
|
||||
// oxlint-disable-next-line preserve-caught-error
|
||||
throw new AggregateError(
|
||||
[primary, ...result.errors],
|
||||
"qa gateway startup and cleanup failed",
|
||||
|
|
|
|||
|
|
@ -88,10 +88,11 @@ function makeAuthorizeCtx(params?: {
|
|||
},
|
||||
isChannelAllowed: vi.fn(params?.isChannelAllowed ?? (() => true)),
|
||||
resolveUserName: vi.fn(
|
||||
params?.resolveUserName ?? ((_) => Promise.resolve({ name: undefined })),
|
||||
params?.resolveUserName ?? ((_userId) => Promise.resolve({ name: undefined })),
|
||||
),
|
||||
resolveChannelName: vi.fn(
|
||||
params?.resolveChannelName ?? ((_) => Promise.resolve({ name: "general", type: "channel" })),
|
||||
params?.resolveChannelName ??
|
||||
((_channelId) => Promise.resolve({ name: "general", type: "channel" })),
|
||||
),
|
||||
} as unknown as SlackMonitorContext;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ function makeBaseReq(
|
|||
req.url = opts.url ?? "/webhook/synology";
|
||||
req.socket = { remoteAddress: "127.0.0.1" } as unknown as IncomingMessage["socket"];
|
||||
req.destroyed = false;
|
||||
req.destroy = ((_: Error | undefined) => {
|
||||
req.destroy = ((_error: Error | undefined) => {
|
||||
if (req.destroyed) {
|
||||
return req;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@ export async function sendPayload(
|
|||
isSingleUseReplyToMode(turn.replyToMode) &&
|
||||
!targetsDifferentMessage;
|
||||
const deliverablePayload = consumedSingleUseReply
|
||||
? (({ replyToId: _, replyToTag: _tag, replyToCurrent: _current, ...rest }) => rest)(
|
||||
? (({ replyToId: _replyToId, replyToTag: _tag, replyToCurrent: _current, ...rest }) => rest)(
|
||||
targetedPayload,
|
||||
)
|
||||
: targetedPayload;
|
||||
|
|
|
|||
|
|
@ -191,10 +191,14 @@ describe("registerTelegramNativeCommands", () => {
|
|||
expect(registered).toEqual([
|
||||
{ command: "custom_two", description: "Custom two unchanged" },
|
||||
{ command: "custom_one", description: "Custom one unchanged" },
|
||||
...native.filter((command) => !command.isAlias).map(({ isAlias: _, ...command }) => command),
|
||||
...native
|
||||
.filter((command) => !command.isAlias)
|
||||
.map(({ isAlias: _isAlias, ...command }) => command),
|
||||
{ command: "alpha", description: "Alpha unchanged" },
|
||||
{ command: "zeta", description: "Zeta unchanged" },
|
||||
...native.filter((command) => command.isAlias).map(({ isAlias: _, ...command }) => command),
|
||||
...native
|
||||
.filter((command) => command.isAlias)
|
||||
.map(({ isAlias: _isAlias, ...command }) => command),
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -134,8 +134,12 @@ describe("createTelegramBot command menu", () => {
|
|||
expect(registered).toStrictEqual([
|
||||
{ command: "custom_backup", description: "Git backup" },
|
||||
{ command: "custom_generate", description: "Create an image" },
|
||||
...native.filter((command) => !command.isAlias).map(({ isAlias: _, ...command }) => command),
|
||||
...native.filter((command) => command.isAlias).map(({ isAlias: _, ...command }) => command),
|
||||
...native
|
||||
.filter((command) => !command.isAlias)
|
||||
.map(({ isAlias: _isAlias, ...command }) => command),
|
||||
...native
|
||||
.filter((command) => command.isAlias)
|
||||
.map(({ isAlias: _isAlias, ...command }) => command),
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -193,8 +197,12 @@ describe("createTelegramBot command menu", () => {
|
|||
}
|
||||
expect(registered).toStrictEqual([
|
||||
{ command: "custom_backup", description: "Git backup" },
|
||||
...native.filter((command) => !command.isAlias).map(({ isAlias: _, ...command }) => command),
|
||||
...native.filter((command) => command.isAlias).map(({ isAlias: _, ...command }) => command),
|
||||
...native
|
||||
.filter((command) => !command.isAlias)
|
||||
.map(({ isAlias: _isAlias, ...command }) => command),
|
||||
...native
|
||||
.filter((command) => command.isAlias)
|
||||
.map(({ isAlias: _isAlias, ...command }) => command),
|
||||
]);
|
||||
expect(registered.find((command) => command.command === "status")).toEqual({
|
||||
command: nativeStatus.command,
|
||||
|
|
|
|||
|
|
@ -339,7 +339,7 @@ const grammySpies = vi.hoisted(() => ({
|
|||
stopSpy: vi.fn(),
|
||||
commandSpy: vi.fn(),
|
||||
botCtorSpy: vi.fn(
|
||||
(_: string, __?: { client?: { fetch?: typeof fetch }; botInfo?: unknown }) => undefined,
|
||||
(_token: string, __?: { client?: { fetch?: typeof fetch }; botInfo?: unknown }) => undefined,
|
||||
),
|
||||
answerCallbackQuerySpy: vi.fn(async () => undefined) as AnyAsyncMock,
|
||||
sendChatActionSpy: vi.fn(),
|
||||
|
|
|
|||
|
|
@ -2145,7 +2145,7 @@
|
|||
"markdown-it": "15.0.0",
|
||||
"marked": "18.0.10",
|
||||
"oxfmt": "0.60.0",
|
||||
"oxlint": "1.78.0",
|
||||
"oxlint": "1.79.0",
|
||||
"oxlint-tsgolint": "7.0.2001",
|
||||
"playwright": "1.62.1",
|
||||
"postcss": "8.5.26",
|
||||
|
|
|
|||
162
pnpm-lock.yaml
generated
162
pnpm-lock.yaml
generated
|
|
@ -451,8 +451,8 @@ importers:
|
|||
specifier: 0.60.0
|
||||
version: 0.60.0
|
||||
oxlint:
|
||||
specifier: 1.78.0
|
||||
version: 1.78.0(oxlint-tsgolint@7.0.2001)
|
||||
specifier: 1.79.0
|
||||
version: 1.79.0(oxlint-tsgolint@7.0.2001)
|
||||
oxlint-tsgolint:
|
||||
specifier: 7.0.2001
|
||||
version: 7.0.2001
|
||||
|
|
@ -4621,124 +4621,124 @@ packages:
|
|||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@oxlint/binding-android-arm-eabi@1.78.0':
|
||||
resolution: {integrity: sha512-Bu819lmAfZMUHErrpe0cEWj3iaefuUODHSU8+UbXy67V/r7/7f4K3FL0NmbD85E+wiFLDYuhP8Zlv0XnVeXshw==}
|
||||
'@oxlint/binding-android-arm-eabi@1.79.0':
|
||||
resolution: {integrity: sha512-TebFaaMklO/RXzTv7PucaCq9l3X6D1gA+C8H6K4njtjFOV+zWE9MKLpulcJZN9bzytbUbQIY0mZuz12nQ5Kv4Q==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
|
||||
'@oxlint/binding-android-arm64@1.78.0':
|
||||
resolution: {integrity: sha512-CDfxZgB61B7buRdY2FJoAYYPPXCZ1EoC1LKscnC5dg3kjobdxiconvAvvN1BmHyW4PyFT3jRLDag/BY/roSNBQ==}
|
||||
'@oxlint/binding-android-arm64@1.79.0':
|
||||
resolution: {integrity: sha512-KqqnOtAVgNsPPF0YSodkFZA1O80jcKoCZCTu3bgsszxA+MrMP9TLzfXitKjEj1FmrPprKDMdRDMmY3weESO9sg==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@oxlint/binding-darwin-arm64@1.78.0':
|
||||
resolution: {integrity: sha512-2Y2U9Ahrz+OO0Ej88f9SJYq51/jUBp1Mc7iZu0ukrbeeZ3gpRGfzIFnoqfHDY96xr0GEfNrPUBFEy0nN5aD7HA==}
|
||||
'@oxlint/binding-darwin-arm64@1.79.0':
|
||||
resolution: {integrity: sha512-BVC2nsMzqQzRDPc5RhixkZ+m1p7iH4bxRRvqkbwDXX0PlQKm1BPy8J8cRjnAFafOq2QzI+BfO3vE8w2GZ3CBag==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@oxlint/binding-darwin-x64@1.78.0':
|
||||
resolution: {integrity: sha512-rpych6eJq6m9jDRypTEaPD1xysaEW5h9+xuxhGK/QhOg+/xaqPZrCrTNoIl/f3nEjuJeCEmstNDlrE9rJi/3/g==}
|
||||
'@oxlint/binding-darwin-x64@1.79.0':
|
||||
resolution: {integrity: sha512-p6Lm+snmhGuLKL1+CpCV8L6ijkE/qJzK2H2jG9+eKJT0n31RbY4FLsdhexekgP3bLpw4Kgde+9DZuDZQ4yIInA==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@oxlint/binding-freebsd-x64@1.78.0':
|
||||
resolution: {integrity: sha512-IcMGrQT3QizkOESUJd5et+rOhVqSkNDfNik1cvrKDqIbzqx9KMtRswpFgkCuNTSwylCFLKhGUu8KmqY1ZnC0Dg==}
|
||||
'@oxlint/binding-freebsd-x64@1.79.0':
|
||||
resolution: {integrity: sha512-qDMm0dXZnoHyRqSL4N4xUq82T4sqK5cbKSjvd/dF/YbMUXc2R1wEPf+vmA5S0qUmi0nwXfNbjXBtZaIqzQLIMg==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@oxlint/binding-linux-arm-gnueabihf@1.78.0':
|
||||
resolution: {integrity: sha512-/uLdoJ0IXE6vo/0f0LKjinQAp+re+VMaCWaNT8ENIv2EOCkSsc8SGaflXAuW0Jua2dq5+GLVWm1NQK7P3UFSNQ==}
|
||||
'@oxlint/binding-linux-arm-gnueabihf@1.79.0':
|
||||
resolution: {integrity: sha512-2od7s0nuKPzqyUZAWk9KkCyGg7eI9dwFPZg+20lB15fKFkVZ0c9ZFxqPfiBAyDTlTkh9stPI0t+JlPCqMbItVA==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@oxlint/binding-linux-arm-musleabihf@1.78.0':
|
||||
resolution: {integrity: sha512-7xi4Wb/O8NRJhLoUXmDJMUVpNYvB5kefdhFU1Jb8rtae4QoXlTiLwI14X4YvAXVZLNZChP8m5qO9SQAlWQTbkQ==}
|
||||
'@oxlint/binding-linux-arm-musleabihf@1.79.0':
|
||||
resolution: {integrity: sha512-ZOQUjkzDnvlhSE3+tWC3YXx94MMl+sYMlwH+u1+YGApGHOJP/YAc8ZBRFOXZ6eOBmxtXAWuS/fBcdZr8qqNO1A==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@oxlint/binding-linux-arm64-gnu@1.78.0':
|
||||
resolution: {integrity: sha512-4hFW0+fVXa3OIh1Y4A5SPkmvI4wuuBSrCVKzOyE7PTjhc7yEqZ1pmvEEeS5Lj/MaqvegFxXyF33N+6jkehxdyg==}
|
||||
'@oxlint/binding-linux-arm64-gnu@1.79.0':
|
||||
resolution: {integrity: sha512-lu158FR4nGqGeRS3BQvtG85wRgU/Fy4MD5Cxp1hzJXizGiLo6u2742wJSCDKh8cFcZntvX7fcxlq4mMmfryH1g==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@oxlint/binding-linux-arm64-musl@1.78.0':
|
||||
resolution: {integrity: sha512-oC0mvsgBJjlMijSDEhx9KuvR9zYeHXceA9MjbuXB1F8NSR78Yj2unOBrstEvTVaq+pko+kuue6DajC00eqvTdg==}
|
||||
'@oxlint/binding-linux-arm64-musl@1.79.0':
|
||||
resolution: {integrity: sha512-mbpKQeE2aflTjddaHK7MP8KP/OFbUM++lt5M635ENM8IyIdK0jm2t9pb+2v9mVVIvhF6TqA4l7F79Pll1mi+uw==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@oxlint/binding-linux-ppc64-gnu@1.78.0':
|
||||
resolution: {integrity: sha512-XAllT5SUZS+ohjuZ3/5S0cwe0r7eboiuigeStCZ5DXRYx/2KVM2UvQXvAfyzXEimtQjAB7cDQ2YxDe2Zl2WNQQ==}
|
||||
'@oxlint/binding-linux-ppc64-gnu@1.79.0':
|
||||
resolution: {integrity: sha512-WpGNua7gaxaHnpSDeog2ji8IDHn/QLPl9LPzwkR/FvVv58vT5BcXjRXnU+wbu3N75cpeha8CdC7ho/U2OIsB4g==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@oxlint/binding-linux-riscv64-gnu@1.78.0':
|
||||
resolution: {integrity: sha512-trucMER/0QtecoXvc1y/UVqE3kwJipDwrx4oHfj+nNm3dq2zjP44WT0CfHNDPM3G1DXIkx/gY6lAD21NSCZVhA==}
|
||||
'@oxlint/binding-linux-riscv64-gnu@1.79.0':
|
||||
resolution: {integrity: sha512-tK1E93A5LVzISg4ngpKJnfTs7EqtIUceGI7MQ4GyDjJiLi8wPCkEyKlj2xkyKWZ1yzkDJyLHTBJ5/iFWRdnJvg==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@oxlint/binding-linux-riscv64-musl@1.78.0':
|
||||
resolution: {integrity: sha512-cm3O4F/HQbdzOUX5mKHqG5KDL6E5w0pnlZ+fbBy2rmLryPOowkuLagFHTopQsEIpjcaZoPOrL+BmmAytAG9HFg==}
|
||||
'@oxlint/binding-linux-riscv64-musl@1.79.0':
|
||||
resolution: {integrity: sha512-qhQvUIrngXivA2A9pQ+xPCychztn/5qUv7yS3gDwXv3w7Rag+eTeeXWmRyx+t7XsW5x6LuY/8AsTq36UgFIblg==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@oxlint/binding-linux-s390x-gnu@1.78.0':
|
||||
resolution: {integrity: sha512-33wRf6HqGNsybJ3qX4cGaQN2ODPxNmc1rMa0mrTmx3eFq1VzOnvQooi9bIGVYakW8a/wmqVx1mgsUm8R2xfTiw==}
|
||||
'@oxlint/binding-linux-s390x-gnu@1.79.0':
|
||||
resolution: {integrity: sha512-sv6AaVgU/eE6u+6WFiQVDcPPwTxP6IJMSB9k701W2r/r6Tx465e8vPvVyRxquNH4Vy6KwRNu90mVbxXJN8+5gg==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@oxlint/binding-linux-x64-gnu@1.78.0':
|
||||
resolution: {integrity: sha512-rRdISSYegj6VganMZ9tjRjijowfHJ09IZU01i0toBAqr6n5LEtwHq2IeS4FjW2RoskOHlb6efB26H5izYb3GEQ==}
|
||||
'@oxlint/binding-linux-x64-gnu@1.79.0':
|
||||
resolution: {integrity: sha512-iFZL02deziHslb3jEX9KdqlAkYoo4fGyotchKDzdfK1f5mxlIBeiQeHhvK3iFpuEJSB4ma/qeFn9oxPiwnhUPQ==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@oxlint/binding-linux-x64-musl@1.78.0':
|
||||
resolution: {integrity: sha512-GmsP4rW0xTL6u5CVdcDsaN5Fbc7hBc382Wmar1kttbnwSEviM+rSINKOMQ+UQ6iH+AGwC+8gaAiwu134Tgh6Lg==}
|
||||
'@oxlint/binding-linux-x64-musl@1.79.0':
|
||||
resolution: {integrity: sha512-3DtZR2raqObnh7wXZoFYFd0Fw7skBvcb3f7A+/lkEiDuh8hrE6vv9b/62Qxao1a9/OeHLw/FcXlXzgsW9wTRFg==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@oxlint/binding-openharmony-arm64@1.78.0':
|
||||
resolution: {integrity: sha512-sy9yeYuADc8a+n4TLBayzMCZiHPW78DcIFVpOXTmdKHWQeM9xe5uzkqIIZmi326D5hY9XVwacipEB1p7tQjPAg==}
|
||||
'@oxlint/binding-openharmony-arm64@1.79.0':
|
||||
resolution: {integrity: sha512-Oatt4GuA1WJkqzk2ozx4HrWROOi7opV3AKDw/U8qDIqeTqzsjn5K2x3REJMNjU3/KU/Bkq96Zi3CknaiDTaC/Q==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm64]
|
||||
os: [openharmony]
|
||||
|
||||
'@oxlint/binding-win32-arm64-msvc@1.78.0':
|
||||
resolution: {integrity: sha512-rjc2hF1KfMi8fZj1X/m3AmnHbdsF3rL0v6KQg0Uc880Yb2khjz+3U14sfdZ7jWTpRnN1m1NQa/TT7uU9lJWPrA==}
|
||||
'@oxlint/binding-win32-arm64-msvc@1.79.0':
|
||||
resolution: {integrity: sha512-NAgZr9Qp8nIA9rpo0JEvwiabTF/2UVqBNnupBG9X4kxXcQoScJUTi+qHhvabb9s/thgj5wQ4XcIaJvb+ZMgoKw==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@oxlint/binding-win32-ia32-msvc@1.78.0':
|
||||
resolution: {integrity: sha512-zcuXFVrEFHIafRfkCQT8w/Xe41o07ozl/vwHq7p94vB29xVzsB0sZGYORU1jhcYKv3Lr0J3HbJ2T4fHH5rWmvA==}
|
||||
'@oxlint/binding-win32-ia32-msvc@1.79.0':
|
||||
resolution: {integrity: sha512-+KyXjIvcpaXmWW/j9NNY5yWjrIVxaX18VyIheQy3jwc2GSYgpCr7MGI/HxIGQ/shAL5IWEKbhsqoMpAO5Stiog==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@oxlint/binding-win32-x64-msvc@1.78.0':
|
||||
resolution: {integrity: sha512-Sb5ocmLSuYeOuXd+CFOToGKp/gjXUEWDnvIGwhnh8aq8wY4TMmEnKnvbogSW7RdMZv77JSARduS7/gv+khYEjA==}
|
||||
'@oxlint/binding-win32-x64-msvc@1.79.0':
|
||||
resolution: {integrity: sha512-mEelcCMMBS57sIXh2veGMNy+pQwuGtcMxHxGIZWQ5Ba9pJ5jCCUFOZB9E2JhBaxGsURe+WGe0zJp4RVre52gpQ==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
|
@ -8095,8 +8095,8 @@ packages:
|
|||
resolution: {integrity: sha512-KjK/XLcXr1DSyonKhsuFqJRiuKqcyG9j3LJ8nkOsrLzGvodBPqzHOKauy10asLMDI0sUpvb+1sxlzff3udZvfg==}
|
||||
hasBin: true
|
||||
|
||||
oxlint@1.78.0:
|
||||
resolution: {integrity: sha512-QgQePuxIqKOzo1KSjG2EnITEeWvWnKAm77eq8nrMtf6AGoA+zyGc4PFYtDNJSD25g/ibOwfQ851hZ4/SPkMVoA==}
|
||||
oxlint@1.79.0:
|
||||
resolution: {integrity: sha512-hVJ9hq9m2unPS+Of4eJJgCPdIeCC+3DHEUX3tkmrPJr3OK2hz7PhXwgC+ZP71ZcYu8cCDEtQrqLxWNvxBppBVg==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
|
|
@ -11841,61 +11841,61 @@ snapshots:
|
|||
'@oxlint-tsgolint/win32-x64@7.0.2001':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-android-arm-eabi@1.78.0':
|
||||
'@oxlint/binding-android-arm-eabi@1.79.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-android-arm64@1.78.0':
|
||||
'@oxlint/binding-android-arm64@1.79.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-darwin-arm64@1.78.0':
|
||||
'@oxlint/binding-darwin-arm64@1.79.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-darwin-x64@1.78.0':
|
||||
'@oxlint/binding-darwin-x64@1.79.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-freebsd-x64@1.78.0':
|
||||
'@oxlint/binding-freebsd-x64@1.79.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-linux-arm-gnueabihf@1.78.0':
|
||||
'@oxlint/binding-linux-arm-gnueabihf@1.79.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-linux-arm-musleabihf@1.78.0':
|
||||
'@oxlint/binding-linux-arm-musleabihf@1.79.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-linux-arm64-gnu@1.78.0':
|
||||
'@oxlint/binding-linux-arm64-gnu@1.79.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-linux-arm64-musl@1.78.0':
|
||||
'@oxlint/binding-linux-arm64-musl@1.79.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-linux-ppc64-gnu@1.78.0':
|
||||
'@oxlint/binding-linux-ppc64-gnu@1.79.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-linux-riscv64-gnu@1.78.0':
|
||||
'@oxlint/binding-linux-riscv64-gnu@1.79.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-linux-riscv64-musl@1.78.0':
|
||||
'@oxlint/binding-linux-riscv64-musl@1.79.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-linux-s390x-gnu@1.78.0':
|
||||
'@oxlint/binding-linux-s390x-gnu@1.79.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-linux-x64-gnu@1.78.0':
|
||||
'@oxlint/binding-linux-x64-gnu@1.79.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-linux-x64-musl@1.78.0':
|
||||
'@oxlint/binding-linux-x64-musl@1.79.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-openharmony-arm64@1.78.0':
|
||||
'@oxlint/binding-openharmony-arm64@1.79.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-win32-arm64-msvc@1.78.0':
|
||||
'@oxlint/binding-win32-arm64-msvc@1.79.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-win32-ia32-msvc@1.78.0':
|
||||
'@oxlint/binding-win32-ia32-msvc@1.79.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-win32-x64-msvc@1.78.0':
|
||||
'@oxlint/binding-win32-x64-msvc@1.79.0':
|
||||
optional: true
|
||||
|
||||
'@panzoom/panzoom@4.6.2': {}
|
||||
|
|
@ -15568,27 +15568,27 @@ snapshots:
|
|||
'@oxlint-tsgolint/win32-arm64': 7.0.2001
|
||||
'@oxlint-tsgolint/win32-x64': 7.0.2001
|
||||
|
||||
oxlint@1.78.0(oxlint-tsgolint@7.0.2001):
|
||||
oxlint@1.79.0(oxlint-tsgolint@7.0.2001):
|
||||
optionalDependencies:
|
||||
'@oxlint/binding-android-arm-eabi': 1.78.0
|
||||
'@oxlint/binding-android-arm64': 1.78.0
|
||||
'@oxlint/binding-darwin-arm64': 1.78.0
|
||||
'@oxlint/binding-darwin-x64': 1.78.0
|
||||
'@oxlint/binding-freebsd-x64': 1.78.0
|
||||
'@oxlint/binding-linux-arm-gnueabihf': 1.78.0
|
||||
'@oxlint/binding-linux-arm-musleabihf': 1.78.0
|
||||
'@oxlint/binding-linux-arm64-gnu': 1.78.0
|
||||
'@oxlint/binding-linux-arm64-musl': 1.78.0
|
||||
'@oxlint/binding-linux-ppc64-gnu': 1.78.0
|
||||
'@oxlint/binding-linux-riscv64-gnu': 1.78.0
|
||||
'@oxlint/binding-linux-riscv64-musl': 1.78.0
|
||||
'@oxlint/binding-linux-s390x-gnu': 1.78.0
|
||||
'@oxlint/binding-linux-x64-gnu': 1.78.0
|
||||
'@oxlint/binding-linux-x64-musl': 1.78.0
|
||||
'@oxlint/binding-openharmony-arm64': 1.78.0
|
||||
'@oxlint/binding-win32-arm64-msvc': 1.78.0
|
||||
'@oxlint/binding-win32-ia32-msvc': 1.78.0
|
||||
'@oxlint/binding-win32-x64-msvc': 1.78.0
|
||||
'@oxlint/binding-android-arm-eabi': 1.79.0
|
||||
'@oxlint/binding-android-arm64': 1.79.0
|
||||
'@oxlint/binding-darwin-arm64': 1.79.0
|
||||
'@oxlint/binding-darwin-x64': 1.79.0
|
||||
'@oxlint/binding-freebsd-x64': 1.79.0
|
||||
'@oxlint/binding-linux-arm-gnueabihf': 1.79.0
|
||||
'@oxlint/binding-linux-arm-musleabihf': 1.79.0
|
||||
'@oxlint/binding-linux-arm64-gnu': 1.79.0
|
||||
'@oxlint/binding-linux-arm64-musl': 1.79.0
|
||||
'@oxlint/binding-linux-ppc64-gnu': 1.79.0
|
||||
'@oxlint/binding-linux-riscv64-gnu': 1.79.0
|
||||
'@oxlint/binding-linux-riscv64-musl': 1.79.0
|
||||
'@oxlint/binding-linux-s390x-gnu': 1.79.0
|
||||
'@oxlint/binding-linux-x64-gnu': 1.79.0
|
||||
'@oxlint/binding-linux-x64-musl': 1.79.0
|
||||
'@oxlint/binding-openharmony-arm64': 1.79.0
|
||||
'@oxlint/binding-win32-arm64-msvc': 1.79.0
|
||||
'@oxlint/binding-win32-ia32-msvc': 1.79.0
|
||||
'@oxlint/binding-win32-x64-msvc': 1.79.0
|
||||
oxlint-tsgolint: 7.0.2001
|
||||
|
||||
p-finally@1.0.0: {}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ const beforeToolCallMocks = vi.hoisted(() => ({
|
|||
this.reason = reason;
|
||||
}
|
||||
},
|
||||
consumeAdjustedParamsForToolCall: vi.fn((_: string): unknown => undefined),
|
||||
consumeAdjustedParamsForToolCall: vi.fn((_toolCallId: string): unknown => undefined),
|
||||
recordAdjustedParamsForToolCall: vi.fn(),
|
||||
recordStructuredReplayTrustForToolCall: vi.fn(),
|
||||
isToolWrappedWithBeforeToolCallHook: vi.fn(() => false),
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import { toToolDefinitions } from "./agent-tool-definition-adapter.js";
|
|||
|
||||
const hookMocks = vi.hoisted(() => ({
|
||||
runner: {
|
||||
hasHooks: vi.fn((_: string) => true),
|
||||
hasHooks: vi.fn((_hookName: string) => true),
|
||||
runAfterToolCall: vi.fn(async () => {}),
|
||||
},
|
||||
BeforeToolCallBlockedError: class BeforeToolCallBlockedError extends Error {
|
||||
|
|
@ -23,7 +23,7 @@ const hookMocks = vi.hoisted(() => ({
|
|||
}
|
||||
},
|
||||
isToolWrappedWithBeforeToolCallHook: vi.fn(() => false),
|
||||
consumeAdjustedParamsForToolCall: vi.fn((_: string) => undefined as unknown),
|
||||
consumeAdjustedParamsForToolCall: vi.fn((_toolCallId: string) => undefined as unknown),
|
||||
recordAdjustedParamsForToolCall: vi.fn(),
|
||||
recordStructuredReplayTrustForToolCall: vi.fn(),
|
||||
runBeforeToolCallHook: vi.fn(async ({ params }: { params: unknown }) => ({
|
||||
|
|
|
|||
|
|
@ -292,7 +292,7 @@ export function buildAuthHealthSummary(params: {
|
|||
: null;
|
||||
|
||||
const profiles = Object.entries(params.store.profiles)
|
||||
.filter(([_, cred]) =>
|
||||
.filter(([, cred]) =>
|
||||
providerFilter ? providerFilter.has(normalizeProviderId(cred.provider)) : true,
|
||||
)
|
||||
.map(([profileId, credential]) =>
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ const resolveQueueSettingsMock = vi.hoisted(() =>
|
|||
);
|
||||
const listTasksForRelatedSessionKeyForOwnerMock = vi.hoisted(() =>
|
||||
vi.fn(
|
||||
(_: { relatedSessionKey: string; callerOwnerKey: string }) =>
|
||||
(_params: { relatedSessionKey: string; callerOwnerKey: string }) =>
|
||||
[] as Array<Record<string, unknown>>,
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -59,12 +59,12 @@ const state = vi.hoisted(() => ({
|
|||
runEmbeddedAgentEntryMock: vi.fn(),
|
||||
runCliAgentMock: vi.fn(),
|
||||
runWithModelFallbackMock: vi.fn(),
|
||||
isCliProviderMock: vi.fn((_: unknown) => false),
|
||||
isInternalMessageChannelMock: vi.fn((_: unknown) => false),
|
||||
isCliProviderMock: vi.fn((_provider: unknown) => false),
|
||||
isInternalMessageChannelMock: vi.fn((_channel: unknown) => false),
|
||||
createBlockReplyDeliveryHandlerMock: vi.fn(),
|
||||
isCompactionFailureErrorMock: vi.fn((_: string | undefined) => false),
|
||||
isContextOverflowErrorMock: vi.fn((_: string | undefined) => false),
|
||||
isLikelyContextOverflowErrorMock: vi.fn((_: string | undefined) => false),
|
||||
isCompactionFailureErrorMock: vi.fn((_message: string | undefined) => false),
|
||||
isContextOverflowErrorMock: vi.fn((_message: string | undefined) => false),
|
||||
isLikelyContextOverflowErrorMock: vi.fn((_message: string | undefined) => false),
|
||||
updateSessionStoreMock: vi.fn(),
|
||||
resolveCurrentTurnImagesMock: vi.fn(),
|
||||
peekSessionMcpRuntimeMock: vi.fn(),
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ describe("doctor command", () => {
|
|||
|
||||
await doctorCommand(createDoctorRuntime(), { nonInteractive: true });
|
||||
|
||||
const noteTitles = terminalNoteMock.mock.calls.map(([_, title]) => title);
|
||||
const noteTitles = terminalNoteMock.mock.calls.map(([, title]) => title);
|
||||
expect(noteTitles).not.toContain("Extra workspace");
|
||||
|
||||
homedirSpy.mockRestore();
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ type CapturingTestRuntime = {
|
|||
export function createTestRuntime(): TestRuntime {
|
||||
const log = vi.fn() as MockFn<RuntimeEnv["log"]>;
|
||||
const error = vi.fn() as MockFn<RuntimeEnv["error"]>;
|
||||
const exit = vi.fn((_: number) => undefined) as MockFn<RuntimeEnv["exit"]>;
|
||||
const exit = vi.fn((_code: number) => undefined) as MockFn<RuntimeEnv["exit"]>;
|
||||
return {
|
||||
log,
|
||||
error,
|
||||
|
|
|
|||
|
|
@ -84,15 +84,18 @@ describe("worker placement reconciliation teardown authority", () => {
|
|||
activeOwnerEpoch: null,
|
||||
destroyRequestedAtMs: null,
|
||||
},
|
||||
])("keeps failed-placement cleanup fenced with $reason", async ({ reason: _, ...params }) => {
|
||||
const { guard, resumeProvisioning } = createFailedPlacementGuard(params);
|
||||
const reconcileCore = vi.fn(async () => {});
|
||||
])(
|
||||
"keeps failed-placement cleanup fenced with $reason",
|
||||
async ({ reason: _reason, ...params }) => {
|
||||
const { guard, resumeProvisioning } = createFailedPlacementGuard(params);
|
||||
const reconcileCore = vi.fn(async () => {});
|
||||
|
||||
await expect(guard("worker-cleanup", reconcileCore)).rejects.toThrow(
|
||||
"provisioning owner is failed",
|
||||
);
|
||||
await expect(guard("worker-cleanup", reconcileCore)).rejects.toThrow(
|
||||
"provisioning owner is failed",
|
||||
);
|
||||
|
||||
expect(reconcileCore).not.toHaveBeenCalled();
|
||||
expect(resumeProvisioning).not.toHaveBeenCalled();
|
||||
});
|
||||
expect(reconcileCore).not.toHaveBeenCalled();
|
||||
expect(resumeProvisioning).not.toHaveBeenCalled();
|
||||
},
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1389,7 +1389,6 @@ async function persistManagedSourceInstall(params: {
|
|||
try {
|
||||
await params.transaction?.rollback();
|
||||
} catch (rollbackError) {
|
||||
// oxlint-disable-next-line preserve-caught-error -- Oxlint 1.78 ignores AggregateError's third-argument cause.
|
||||
throw new AggregateError(
|
||||
[error, rollbackError],
|
||||
"Plugin install failed and payload rollback failed",
|
||||
|
|
|
|||
|
|
@ -36,23 +36,25 @@ type ResolveBundledProviderPolicySurface =
|
|||
type ResolveProviderPolicySurface =
|
||||
typeof import("./provider-public-artifacts.js").resolveProviderPolicySurface;
|
||||
|
||||
const resolvePluginProvidersMock = vi.fn<ResolvePluginProviders>((_) => [] as ProviderPlugin[]);
|
||||
const isPluginProvidersLoadInFlightMock = vi.fn<IsPluginProvidersLoadInFlight>((_) => false);
|
||||
const resolvePluginProvidersMock = vi.fn<ResolvePluginProviders>(
|
||||
(_params) => [] as ProviderPlugin[],
|
||||
);
|
||||
const isPluginProvidersLoadInFlightMock = vi.fn<IsPluginProvidersLoadInFlight>((_params) => false);
|
||||
const resolveCatalogHookProviderPluginIdsMock = vi.fn<ResolveCatalogHookProviderPluginIds>(
|
||||
(_) => [] as string[],
|
||||
(_params) => [] as string[],
|
||||
);
|
||||
const resolveUsageHookProviderPluginContractsMock = vi.fn<ResolveUsageHookProviderPluginContracts>(
|
||||
(_) => [],
|
||||
(_params) => [],
|
||||
);
|
||||
const resolveExternalAuthProfileProviderPluginIdsMock =
|
||||
vi.fn<ResolveExternalAuthProfileProviderPluginIds>((_) => [] as string[]);
|
||||
vi.fn<ResolveExternalAuthProfileProviderPluginIds>((_params) => [] as string[]);
|
||||
const resolveOwningPluginIdsForProviderMock = vi.fn<ResolveOwningPluginIdsForProvider>(
|
||||
(_) => undefined,
|
||||
(_params) => undefined,
|
||||
);
|
||||
const resolveBundledProviderPolicySurfaceMock = vi.fn<ResolveBundledProviderPolicySurface>(
|
||||
(_) => null,
|
||||
(_providerId) => null,
|
||||
);
|
||||
const resolveProviderPolicySurfaceMock = vi.fn<ResolveProviderPolicySurface>((_) => null);
|
||||
const resolveProviderPolicySurfaceMock = vi.fn<ResolveProviderPolicySurface>((_providerId) => null);
|
||||
const providerRuntimeWarnMock = vi.fn();
|
||||
|
||||
let getAiTransportHost: typeof import("@openclaw/ai").getAiTransportHost;
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ const resolveRuntimePluginRegistryMock = vi.fn<ResolveRuntimePluginRegistry>();
|
|||
const getRuntimePluginRegistryForLoadOptionsMock = vi.fn<GetRuntimePluginRegistryForLoadOptions>();
|
||||
const resolveCompatibleRuntimePluginRegistryMock = vi.fn<ResolveCompatibleRuntimePluginRegistry>();
|
||||
const loadOpenClawPluginsMock = vi.fn<LoadOpenClawPlugins>();
|
||||
const isPluginRegistryLoadInFlightMock = vi.fn<IsPluginRegistryLoadInFlight>((_) => false);
|
||||
const isPluginRegistryLoadInFlightMock = vi.fn<IsPluginRegistryLoadInFlight>((_options) => false);
|
||||
const loadPluginManifestRegistryMock = vi.fn<LoadPluginManifestRegistry>();
|
||||
const loadPluginMetadataSnapshotMock = vi.fn<LoadPluginMetadataSnapshot>();
|
||||
const loadPluginRegistrySnapshotMock = vi.fn<LoadPluginRegistrySnapshot>();
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@ export function listTaskRecords(filter?: (task: Readonly<TaskRecord>) => boolean
|
|||
return (filter ? records.filter(filter) : records)
|
||||
.map((task, insertionIndex) => Object.assign({}, cloneTaskRecord(task), { insertionIndex }))
|
||||
.toSorted(compareTasksNewestFirst)
|
||||
.map(({ insertionIndex: _, ...task }) => task);
|
||||
.map(({ insertionIndex: _insertionIndex, ...task }) => task);
|
||||
}
|
||||
|
||||
export function hasActiveTaskForChildSessionKey(params: {
|
||||
|
|
@ -220,7 +220,7 @@ function listTasksFromIndex(index: Map<string, Set<string>>, key: string): TaskR
|
|||
} => Boolean(task),
|
||||
)
|
||||
.toSorted(compareTasksNewestFirst)
|
||||
.map(({ insertionIndex: _, ...task }) => task);
|
||||
.map(({ insertionIndex: _insertionIndex, ...task }) => task);
|
||||
}
|
||||
|
||||
export function listTasksForSessionKey(sessionKey: string): TaskRecord[] {
|
||||
|
|
@ -273,7 +273,7 @@ export function listFreshTasksForOwnerKey(ownerKey: string): TaskRecord[] {
|
|||
return [...merged.values()]
|
||||
.map((task, insertionIndex) => Object.assign({}, task, { insertionIndex }))
|
||||
.toSorted(compareTasksNewestFirst)
|
||||
.map(({ insertionIndex: _, ...task }) => task);
|
||||
.map(({ insertionIndex: _insertionIndex, ...task }) => task);
|
||||
} catch (error) {
|
||||
taskRegistryLog.warn("Failed to read fresh owner task registry records", {
|
||||
ownerKey: key,
|
||||
|
|
|
|||
|
|
@ -197,8 +197,6 @@ describe("production lint suppressions", () => {
|
|||
"extensions/discord/src/test-support/provider.test-support.ts|typescript/no-unnecessary-type-parameters|1",
|
||||
"extensions/feishu/src/bitable.ts|typescript/no-unnecessary-type-parameters|1",
|
||||
"extensions/matrix/src/onboarding.test-harness.ts|typescript/no-unnecessary-type-parameters|1",
|
||||
// Oxlint 1.78 checks AggregateError cause options at the wrong argument position.
|
||||
"extensions/qa-lab/src/gateway-child-lifecycle.ts|preserve-caught-error|1",
|
||||
"extensions/qa-lab/src/gateway-child-setup.ts|preserve-caught-error|1",
|
||||
"extensions/slack/src/monitor/provider-support.ts|typescript/no-unnecessary-type-parameters|1",
|
||||
"src/agents/agent-bundle-mcp-runtime.ts|unicorn/prefer-add-event-listener|1",
|
||||
|
|
@ -235,7 +233,6 @@ describe("production lint suppressions", () => {
|
|||
"src/plugins/hooks.ts|typescript/no-unnecessary-type-parameters|1",
|
||||
"src/plugins/host-hooks.ts|typescript/no-unnecessary-type-parameters|1",
|
||||
"src/plugins/lazy-service-module.ts|typescript/no-unnecessary-type-parameters|1",
|
||||
"src/plugins/management-service.ts|preserve-caught-error|1",
|
||||
"src/plugins/public-surface-loader.ts|typescript/no-unnecessary-type-parameters|3",
|
||||
"src/plugins/runtime/runtime-plugin-boundary.ts|typescript/no-unnecessary-type-parameters|1",
|
||||
"src/plugins/runtime/types-channel.ts|typescript/no-unnecessary-type-parameters|1",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,12 @@
|
|||
// Oxlint Config tests cover oxlint config script behavior.
|
||||
import { spawnSync } from "node:child_process";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import JSON5 from "json5";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { createScriptTestHarness } from "./test-helpers.js";
|
||||
|
||||
const { createTempDir } = createScriptTestHarness();
|
||||
|
||||
type OxlintConfig = {
|
||||
ignorePatterns?: string[];
|
||||
|
|
@ -123,11 +128,124 @@ const DEFERRED_IMPORT_RULES = [
|
|||
"import/no-unassigned-import",
|
||||
];
|
||||
|
||||
function readJson(path: string): unknown {
|
||||
return JSON5.parse(fs.readFileSync(path, "utf8"));
|
||||
function readJson(filePath: string): unknown {
|
||||
return JSON5.parse(fs.readFileSync(filePath, "utf8"));
|
||||
}
|
||||
|
||||
describe("oxlint config", () => {
|
||||
it("enforces namespace, evaluation, and unused-binding policies with the installed binary", () => {
|
||||
const tempRoot = fs.realpathSync(createTempDir("openclaw-oxlint-policy-"));
|
||||
const typescriptExtensions = ["ts", "tsx", "mts", "cts"];
|
||||
const javascriptExtensions = ["js", "jsx", "cjs", "mjs"];
|
||||
const evaluation = 'eval("1 + 1");\nglobalThis.eval("1 + 1");\n';
|
||||
const fixtures = [
|
||||
...typescriptExtensions.map((extension) => ({
|
||||
file: `src/namespaces.${extension}`,
|
||||
source: [
|
||||
"export type Profile = { ready: boolean };",
|
||||
"export const Profile = { ready: true };",
|
||||
"export interface Adapter { ready: boolean; }",
|
||||
"export const Adapter: Adapter = { ready: true };",
|
||||
].join("\n"),
|
||||
rules: [],
|
||||
})),
|
||||
...javascriptExtensions.map((extension) => ({
|
||||
file: `src/redeclaration.${extension}`,
|
||||
source:
|
||||
"var duplicateBinding = 1;\nvar duplicateBinding = 2;\nconsole.log(duplicateBinding);\n",
|
||||
rules: ["eslint(no-redeclare)", "eslint(no-var)", "eslint(no-var)"],
|
||||
})),
|
||||
...typescriptExtensions.map((extension) => ({
|
||||
file: `src/no-var.${extension}`,
|
||||
source: "export var legacyBinding = 1;\n",
|
||||
rules: ["eslint(no-var)"],
|
||||
})),
|
||||
...[...typescriptExtensions, ...javascriptExtensions].flatMap((extension) => [
|
||||
{
|
||||
file: `src/evaluation.${extension}`,
|
||||
source: evaluation,
|
||||
rules: ["eslint(no-eval)", "eslint(no-eval)"],
|
||||
},
|
||||
{
|
||||
file: `src/unused.${extension}`,
|
||||
source:
|
||||
"function meaningful(_event) { return true; }\nfunction bare(_) { return true; }\nmeaningful(1);\nbare(1);\n",
|
||||
rules: ["eslint(no-unused-vars)"],
|
||||
},
|
||||
]),
|
||||
...[
|
||||
"extensions/qa-lab/src/web-runtime.ts",
|
||||
"extensions/qa-lab/src/web-runtime.test.ts",
|
||||
"extensions/qa-lab/src/other-runtime.ts",
|
||||
"extensions/other/src/web-runtime.ts",
|
||||
].map((file) => ({
|
||||
file,
|
||||
source: evaluation,
|
||||
rules:
|
||||
file === "extensions/qa-lab/src/web-runtime.ts"
|
||||
? ["eslint(no-eval)"]
|
||||
: ["eslint(no-eval)", "eslint(no-eval)"],
|
||||
})),
|
||||
];
|
||||
fs.copyFileSync(".oxlintrc.json", path.join(tempRoot, ".oxlintrc.json"));
|
||||
for (const fixture of fixtures) {
|
||||
const target = path.join(tempRoot, fixture.file);
|
||||
fs.mkdirSync(path.dirname(target), { recursive: true });
|
||||
fs.writeFileSync(target, fixture.source);
|
||||
}
|
||||
// These syntax-rule fixtures need no type program; one batch uses the real config and paths.
|
||||
const result = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
path.resolve("node_modules/oxlint/bin/oxlint"),
|
||||
"--config",
|
||||
".oxlintrc.json",
|
||||
"--format",
|
||||
"json",
|
||||
"--threads=1",
|
||||
"--report-unused-disable-directives-severity",
|
||||
"error",
|
||||
...fixtures.map((fixture) => fixture.file),
|
||||
],
|
||||
{ cwd: tempRoot, encoding: "utf8", timeout: 10_000 },
|
||||
);
|
||||
expect(result.error).toBeUndefined();
|
||||
expect(result.status, result.stderr).toBe(1);
|
||||
const report = JSON.parse(result.stdout) as {
|
||||
number_of_files: number;
|
||||
diagnostics: Array<{
|
||||
filename: string;
|
||||
code: string;
|
||||
severity: string;
|
||||
labels: Array<{ span: { line: number } }>;
|
||||
}>;
|
||||
};
|
||||
expect(report.number_of_files).toBe(fixtures.length);
|
||||
for (const fixture of fixtures) {
|
||||
const diagnostics = report.diagnostics.filter(
|
||||
(diagnostic) => diagnostic.filename.replaceAll("\\", "/") === fixture.file,
|
||||
);
|
||||
expect(diagnostics.map((diagnostic) => diagnostic.code).toSorted(), fixture.file).toEqual(
|
||||
fixture.rules.toSorted(),
|
||||
);
|
||||
expect(
|
||||
diagnostics.every((diagnostic) => diagnostic.severity === "error"),
|
||||
fixture.file,
|
||||
).toBe(true);
|
||||
}
|
||||
const ownerDiagnostics = report.diagnostics.filter(
|
||||
(diagnostic) =>
|
||||
diagnostic.filename.replaceAll("\\", "/") === "extensions/qa-lab/src/web-runtime.ts",
|
||||
);
|
||||
expect(ownerDiagnostics.map((diagnostic) => diagnostic.labels[0]?.span.line)).toEqual([1]);
|
||||
const unusedDiagnostics = report.diagnostics.filter(
|
||||
(diagnostic) => diagnostic.code === "eslint(no-unused-vars)",
|
||||
);
|
||||
expect(unusedDiagnostics.map((diagnostic) => diagnostic.labels[0]?.span.line)).toEqual(
|
||||
[...typescriptExtensions, ...javascriptExtensions].map(() => 2),
|
||||
);
|
||||
});
|
||||
|
||||
it("includes bundled extensions in type-aware lint coverage", () => {
|
||||
const tsconfig = readJson("config/tsconfig/oxlint.json") as OxlintTsconfig;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { runInNewContext } from "node:vm";
|
||||
import { expectDefined } from "@openclaw/normalization-core";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import type { GatewayBrowserClient } from "../../api/gateway.ts";
|
||||
|
|
@ -133,41 +134,29 @@ describe("buildBrowserAnnotationContent", () => {
|
|||
it("preserves valid UTF-16 from inspected accessible names", async () => {
|
||||
const element = document.createElement("button");
|
||||
element.setAttribute("aria-label", `${"a".repeat(78)}${" ".repeat(41)}😀tail`);
|
||||
const originalElementFromPoint = Object.getOwnPropertyDescriptor(document, "elementFromPoint");
|
||||
Object.defineProperty(document, "elementFromPoint", {
|
||||
configurable: true,
|
||||
value: vi.fn(() => element),
|
||||
});
|
||||
const stubDocument = { elementFromPoint: () => element };
|
||||
const client = {
|
||||
request: vi.fn(async (_method: string, envelope: { body?: { fn?: string } }) => {
|
||||
const fn = envelope.body?.fn;
|
||||
if (!fn) {
|
||||
throw new Error("missing browser evaluation function");
|
||||
}
|
||||
return { result: (0, eval)(`(${fn})`)() };
|
||||
return { result: runInNewContext(`(${fn})()`, { document: stubDocument }) };
|
||||
}),
|
||||
};
|
||||
try {
|
||||
const inspected = await inspectBrowserElementAt(client as unknown as GatewayBrowserClient, {
|
||||
targetId: "proof-tab",
|
||||
x: 10,
|
||||
y: 20,
|
||||
});
|
||||
const { modelContext } = buildBrowserAnnotationContent({
|
||||
url: "https://example.com",
|
||||
title: "Boundary proof",
|
||||
strokes: [],
|
||||
element: inspected,
|
||||
});
|
||||
expect(inspected?.name.charCodeAt((inspected?.name.length ?? 0) - 1)).not.toBe(0xd83d);
|
||||
expect(modelContext).toContain(`button "${"a".repeat(78)}"`);
|
||||
} finally {
|
||||
if (originalElementFromPoint) {
|
||||
Object.defineProperty(document, "elementFromPoint", originalElementFromPoint);
|
||||
} else {
|
||||
Reflect.deleteProperty(document, "elementFromPoint");
|
||||
}
|
||||
}
|
||||
const inspected = await inspectBrowserElementAt(client as unknown as GatewayBrowserClient, {
|
||||
targetId: "proof-tab",
|
||||
x: 10,
|
||||
y: 20,
|
||||
});
|
||||
const { modelContext } = buildBrowserAnnotationContent({
|
||||
url: "https://example.com",
|
||||
title: "Boundary proof",
|
||||
strokes: [],
|
||||
element: inspected,
|
||||
});
|
||||
expect(inspected?.name.charCodeAt((inspected?.name.length ?? 0) - 1)).not.toBe(0xd83d);
|
||||
expect(modelContext).toContain(`button "${"a".repeat(78)}"`);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
import { describe, expect, it, vi } from "vitest";
|
||||
import { i18n } from "../i18n/index.ts";
|
||||
import { handleMarkdownCodeBlockClick } from "./markdown-code-blocks.ts";
|
||||
import * as markdownDetails from "./markdown-details.ts";
|
||||
import { splitStableStreamingMarkdown } from "./markdown-streaming.ts";
|
||||
import { toSanitizedMarkdownHtml, toStreamingMarkdownHtml } from "./markdown.ts";
|
||||
|
||||
|
|
@ -865,36 +866,30 @@ PY
|
|||
});
|
||||
|
||||
describe("toStreamingMarkdownHtml", () => {
|
||||
it("keeps appended-prefix splitting below repeated full-rescan cost", () => {
|
||||
const splitIncrementally = splitStableStreamingMarkdown as (
|
||||
markdown: string,
|
||||
streamKey: string,
|
||||
) => ReturnType<typeof splitStableStreamingMarkdown>;
|
||||
it("does not rescan completed disclosures in appended prefixes", () => {
|
||||
const prefixes: string[] = [];
|
||||
let prefix = "<details><summary>Done</summary></details>\n\n";
|
||||
// The ratio catches a reverted full-rescan path without making runner load
|
||||
// part of the assertion by spending most of the test timeout on the baseline.
|
||||
for (let index = 0; index < 48; index += 1) {
|
||||
prefix += `${String(index).padStart(3, "0")} ${"streaming markdown ".repeat(30)}\n`;
|
||||
prefixes.push(prefix);
|
||||
}
|
||||
const measure = (streamKey?: string) => {
|
||||
const startedAt = performance.now();
|
||||
for (const value of prefixes) {
|
||||
if (streamKey) {
|
||||
splitIncrementally(value, streamKey);
|
||||
} else {
|
||||
splitStableStreamingMarkdown(value);
|
||||
}
|
||||
}
|
||||
return performance.now() - startedAt;
|
||||
};
|
||||
measure("line-scan-warmup");
|
||||
const fullRescanMs = measure();
|
||||
const incrementalMs = measure("line-scan-regression");
|
||||
// A full rescan revisits the completed disclosure on every chunk. Observe
|
||||
// the real scanner instead of comparing sub-millisecond wall-clock times.
|
||||
const scanDisclosure = vi.spyOn(markdownDetails, "scanMarkdownDisclosureLine");
|
||||
try {
|
||||
const fullSplits = prefixes.map((value) => splitStableStreamingMarkdown(value));
|
||||
expect(scanDisclosure).toHaveBeenCalledTimes(prefixes.length);
|
||||
scanDisclosure.mockClear();
|
||||
|
||||
expect(incrementalMs).toBeLessThan(fullRescanMs / 5);
|
||||
}, 5_000);
|
||||
const incrementalSplits = prefixes.map((value) =>
|
||||
splitStableStreamingMarkdown(value, "line-scan-regression"),
|
||||
);
|
||||
expect(incrementalSplits).toEqual(fullSplits);
|
||||
expect(scanDisclosure).toHaveBeenCalledTimes(1);
|
||||
} finally {
|
||||
scanDisclosure.mockRestore();
|
||||
}
|
||||
});
|
||||
|
||||
it("keeps chunked-prefix splits identical to full splits", () => {
|
||||
const splitIncrementally = splitStableStreamingMarkdown as (
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue