Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/maintenance/11924-type-the-frozen-any.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Type the 55 `no-explicit-any` sites that had been frozen under #11924 — four redundant casts in `socksConnectorWithFamily.ts` (undici/socks types already accept them) and the mocks/fixtures of the socks-timeout and isFree suites — and drop their suppression entries; the ESLint ratchet shrinks from 5487 to 5432 (Closes #11924)
32 changes: 1 addition & 31 deletions config/quality/eslint-suppressions.json
Original file line number Diff line number Diff line change
Expand Up @@ -837,11 +837,6 @@
"count": 5
}
},
"open-sse/utils/socksConnectorWithFamily.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 4
}
},
"open-sse/utils/stream.ts": {
"@typescript-eslint/no-unused-vars": {
"count": 2
Expand Down Expand Up @@ -4952,11 +4947,6 @@
"count": 20
}
},
"tests/unit/free-models-isfree.test.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 2
}
},
"tests/unit/functional-gateway-mirrors-append.test.ts": {
"@typescript-eslint/no-unused-vars": {
"count": 1
Expand Down Expand Up @@ -5243,11 +5233,6 @@
"count": 3
}
},
"tests/unit/models-db-isfree.test.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 18
}
},
"tests/unit/modelsDevSync-extended.test.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 2
Expand Down Expand Up @@ -5547,11 +5532,6 @@
"count": 4
}
},
"tests/unit/providerModelMutationSchema-isfree.test.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 2
}
},
"tests/unit/providers-route-managed-catalog.test.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 4
Expand Down Expand Up @@ -6021,16 +6001,6 @@
"count": 7
}
},
"tests/unit/socks-connect-timeout-e2e.test.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 11
}
},
"tests/unit/socks-connect-timeout.test.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 18
}
},
"tests/unit/spend-batch-writer.test.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 1
Expand Down Expand Up @@ -6552,4 +6522,4 @@
"count": 2
}
}
}
}
10 changes: 6 additions & 4 deletions open-sse/utils/socksConnectorWithFamily.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,15 @@ export function socksConnectorWithFamily(
const isDisabled = connectTimeout === 0;
// SOCKS lib: 0 throws (isValidTimeoutValue: value>0) and undefined → DEFAULT_TIMEOUT 30s;
// undici: 0 disables (core/util.js: if (!opts.timeout) return noop), undefined → 10s. Divergence intentional.
const handshakeTimeout = isDisabled ? undefined : (connectTimeout ?? resolveSocksHandshakeTimeoutMs());
const handshakeTimeout = isDisabled
? undefined
: (connectTimeout ?? resolveSocksHandshakeTimeoutMs());
const tlsTimeout = connectTimeout;
// Sequential budget: both phases bounded by the same connectTimeout → wall-time up to 60s for https
// (vs 30s direct). Shared-deadline alternative rejected as unjustified complexity.
const build = _buildConnectorForTest ?? buildConnector;
const undiciConnect = build(
tlsTimeout !== undefined ? ({ ...tlsOpts, timeout: tlsTimeout } as any) : tlsOpts
tlsTimeout !== undefined ? { ...tlsOpts, timeout: tlsTimeout } : tlsOpts
);
const socketOptions = buildSocksFamilySocketOptions(family);
return async (options, callback) => {
Expand All @@ -69,7 +71,7 @@ export function socksConnectorWithFamily(
const r = await SocksClient.createConnection({
command: "connect",
proxy,
timeout: handshakeTimeout as any,
timeout: handshakeTimeout,
destination: { host: hostname, port: resolvePort(protocol, port) },
existing_socket: httpSocket as never,
socket_options: socketOptions as never,
Expand Down Expand Up @@ -97,6 +99,6 @@ export function createSocksDispatcherWithFamily(
};
return new Agent({
...rest,
connect: socksConnectorWithFamily(proxy, family, connect as any, connectTimeout as any),
connect: socksConnectorWithFamily(proxy, family, connect, connectTimeout),
});
}
9 changes: 7 additions & 2 deletions tests/unit/free-models-isfree.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,13 @@ describe("isFreeModel isFree opt-in", () => {
assert.equal(isFreeModel("local", { id: "my-model", isFree: true }), true);
});
it("isFree:false/null/undefined/1/'true' → not free (strict ===true)", () => {
for (const v of [false, null, undefined, 1, "true" as any]) {
assert.equal(isFreeModel("any", { id: "x", isFree: v as any }), false, `isFree=${String(v)} should be false`);
const junk: unknown[] = [false, null, undefined, 1, "true"];
for (const v of junk) {
assert.equal(
isFreeModel("any", { id: "x", isFree: v as boolean }),
false,
`isFree=${String(v)} should be false`
);
}
});
it("providerHasFreeModels unchanged by custom isFree", () => {
Expand Down
38 changes: 20 additions & 18 deletions tests/unit/models-db-isfree.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { rmSync, mkdtempSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";

type CustomRow = { id: string; isFree?: boolean };

describe("custom isFree tri-state (DB)", () => {
let dir: string;
let prevDataDir: string | undefined;
Expand Down Expand Up @@ -44,8 +46,8 @@ describe("custom isFree tri-state (DB)", () => {
undefined,
true
);
const rows: any = await getCustomModels("p");
const r = rows.find((x: any) => x.id === "m1");
const rows = (await getCustomModels("p")) as CustomRow[];
const r = rows.find((x) => x.id === "m1");
assert.equal(r.isFree, true);
await addCustomModel(
"p",
Expand All @@ -60,8 +62,8 @@ describe("custom isFree tri-state (DB)", () => {
undefined,
undefined
);
const rows2: any = await getCustomModels("p");
const r2 = rows2.find((x: any) => x.id === "m2");
const rows2 = (await getCustomModels("p")) as CustomRow[];
const r2 = rows2.find((x) => x.id === "m2");
assert.equal(r2.isFree, undefined);
});

Expand All @@ -79,9 +81,9 @@ describe("custom isFree tri-state (DB)", () => {
undefined,
true
);
await updateCustomModel("p", "m", { isFree: null } as any);
const rows: any = await getCustomModels("p");
const r = rows.find((x: any) => x.id === "m");
await updateCustomModel("p", "m", { isFree: null });
const rows = (await getCustomModels("p")) as CustomRow[];
const r = rows.find((x) => x.id === "m");
assert.equal(r.isFree, undefined);
});

Expand All @@ -99,13 +101,13 @@ describe("custom isFree tri-state (DB)", () => {
undefined,
undefined
);
await updateCustomModel("p", "m", { isFree: true } as any);
let rows: any = await getCustomModels("p");
assert.equal(rows.find((x: any) => x.id === "m").isFree, true);
await updateCustomModel("p", "m", { isFree: true });
let rows = (await getCustomModels("p")) as CustomRow[];
assert.equal(rows.find((x) => x.id === "m").isFree, true);
// tri-state helper treats false as Boolean(false) → stored as false (falsy free), but only true is free per isFree guard
await updateCustomModel("p", "m", { isFree: false } as any);
await updateCustomModel("p", "m", { isFree: false });
rows = await getCustomModels("p");
assert.equal(rows.find((x: any) => x.id === "m").isFree, false);
assert.equal(rows.find((x) => x.id === "m").isFree, false);
});

it("replaceCustomModels preserves isFree (new wins else prev)", async () => {
Expand Down Expand Up @@ -138,15 +140,15 @@ describe("custom isFree tri-state (DB)", () => {
// replace with new truth for override, omit for keep (prev should win)
await replaceCustomModels("p", [
{ id: "keep", name: "keep" },
{ id: "override", name: "override", isFree: true } as any,
{ id: "override", name: "override", isFree: true },
]);
const rows: any = await getCustomModels("p");
const rows = (await getCustomModels("p")) as CustomRow[];
assert.equal(
rows.find((x: any) => x.id === "keep").isFree,
rows.find((x) => x.id === "keep").isFree,
true,
"prev isFree preserved when new omits"
);
assert.equal(rows.find((x: any) => x.id === "override").isFree, true, "new isFree wins");
assert.equal(rows.find((x) => x.id === "override").isFree, true, "new isFree wins");
});

it("allowEmpty:false intact (no destructive clear)", async () => {
Expand All @@ -163,8 +165,8 @@ describe("custom isFree tri-state (DB)", () => {
undefined,
true
);
const before: any = await getCustomModels("p");
const after: any = await replaceCustomModels("p", [], { allowEmpty: false });
const before = (await getCustomModels("p")) as CustomRow[];
const after = await replaceCustomModels("p", [], { allowEmpty: false });
assert.equal(after.length, before.length);
});
});
32 changes: 25 additions & 7 deletions tests/unit/providerModelMutationSchema-isfree.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,35 @@ import { providerModelMutationSchema } from "../../src/shared/validation/schemas

describe("providerModelMutationSchema isFree", () => {
it("isFree:true accepted", () => {
assert.equal(providerModelMutationSchema.safeParse({ provider: "p", modelId: "m", isFree: true }).success, true);
assert.equal(
providerModelMutationSchema.safeParse({ provider: "p", modelId: "m", isFree: true }).success,
true
);
});
it("old payload without isFree still valid", () => {
assert.equal(providerModelMutationSchema.safeParse({ provider: "p", modelId: "m" }).success, true);
assert.equal(
providerModelMutationSchema.safeParse({ provider: "p", modelId: "m" }).success,
true
);
});
it("rejects isFree:0 and isFree:\"yes\"", () => {
assert.equal(providerModelMutationSchema.safeParse({ provider: "p", modelId: "m", isFree: 0 as any }).success, false);
assert.equal(providerModelMutationSchema.safeParse({ provider: "p", modelId: "m", isFree: "yes" as any }).success, false);
it('rejects isFree:0 and isFree:"yes"', () => {
assert.equal(
providerModelMutationSchema.safeParse({ provider: "p", modelId: "m", isFree: 0 }).success,
false
);
assert.equal(
providerModelMutationSchema.safeParse({ provider: "p", modelId: "m", isFree: "yes" }).success,
false
);
});
it("nullable true/false/null accepted", () => {
assert.equal(providerModelMutationSchema.safeParse({ provider: "p", modelId: "m", isFree: null }).success, true);
assert.equal(providerModelMutationSchema.safeParse({ provider: "p", modelId: "m", isFree: false }).success, true);
assert.equal(
providerModelMutationSchema.safeParse({ provider: "p", modelId: "m", isFree: null }).success,
true
);
assert.equal(
providerModelMutationSchema.safeParse({ provider: "p", modelId: "m", isFree: false }).success,
true
);
});
});
44 changes: 34 additions & 10 deletions tests/unit/socks-connect-timeout-e2e.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { describe, it, afterEach } from "node:test";
import assert from "node:assert/strict";
import net from "node:net";
import { fetch } from "undici";
import { fetch, type Agent } from "undici";
import type { SocksProxy } from "socks";
import { createSocksDispatcherWithFamily } from "../../open-sse/utils/socksConnectorWithFamily.ts";
import { clearDispatcherCache } from "../../open-sse/utils/proxyDispatcher.ts";

async function startFakeSocks(opts: { stallAfterGrant: boolean }): Promise<{ port: number; close: () => Promise<void> }> {
async function startFakeSocks(opts: {
stallAfterGrant: boolean;
}): Promise<{ port: number; close: () => Promise<void> }> {
return new Promise((resolve) => {
const serverSockets = new Set<net.Socket>();
const server = net.createServer((socket) => {
Expand Down Expand Up @@ -44,22 +47,43 @@ describe("stub SOCKS e2e", () => {

it("pre-grant stall (SOCKS timer) \u2192 error < 1000ms", async () => {
const { port, close } = await startFakeSocks({ stallAfterGrant: false });
const dispatcher = createSocksDispatcherWithFamily({ host: "127.0.0.1", port, type: 5 } as any, 4 as any, { connectTimeout: 300, connect: {} } as any);
const proxy: SocksProxy = { host: "127.0.0.1", port, type: 5 };
const dispatcher = createSocksDispatcherWithFamily(proxy, 4, {
connectTimeout: 300,
connect: {},
} as Agent.Options);
const t0 = Date.now();
await assert.rejects(() => fetch("https://example.invalid/", { dispatcher } as any));
assert.ok(Date.now() - t0 < 1000, `pre-grant stall must error < 1000ms, took ${Date.now() - t0}ms`);
await assert.rejects(() => fetch("https://example.invalid/", { dispatcher }));
assert.ok(
Date.now() - t0 < 1000,
`pre-grant stall must error < 1000ms, took ${Date.now() - t0}ms`
);
await close();
});

it("post-grant stall (TLS timer, https:// only) \u2192 error < 1500ms", async () => {
const { port, close } = await startFakeSocks({ stallAfterGrant: true });
const dispatcher = createSocksDispatcherWithFamily({ host: "127.0.0.1", port, type: 5 } as any, 4 as any, { connectTimeout: 300, connect: {} } as any);
const proxy: SocksProxy = { host: "127.0.0.1", port, type: 5 };
const dispatcher = createSocksDispatcherWithFamily(proxy, 4, {
connectTimeout: 300,
connect: {},
} as Agent.Options);
const t0 = Date.now();
let caught: any = null;
await assert.rejects(async () => { try { await fetch("https://example.invalid/", { dispatcher } as any); } catch (e) { caught = e; throw e; } });
const err: any = caught;
let caught: unknown = null;
await assert.rejects(async () => {
try {
await fetch("https://example.invalid/", { dispatcher });
} catch (e) {
caught = e;
throw e;
}
});
const err = caught as { message?: string } | null;
// The ~1000ms wall time is connectTimeout 300ms + undici immediate/queue overhead, not the 10000ms default.
assert.ok(Date.now() - t0 < 1500, `post-grant stall must error < 1500ms, took ${Date.now() - t0}ms (err: ${String((err as any)?.message ?? err).slice(0, 120)})`);
assert.ok(
Date.now() - t0 < 1500,
`post-grant stall must error < 1500ms, took ${Date.now() - t0}ms (err: ${String(err?.message ?? err).slice(0, 120)})`
);
await close();
});
});
Loading