test(executors): adapt remaining 35 suites to the async lazy registry (round 2)

Round 1 only covered suites importing from executors/index.ts directly;
suites importing getExecutor through other paths (open-sse root
re-export, dynamic imports inside tests) still called it synchronously,
producing Promise-vs-instance assertion failures in CI (e.g.
providers-yuanbao-web 'instanceof YuanbaoWebExecutor' false).

Sweep method: repo-wide scan for un-awaited getExecutor call sites,
adapted mechanically (await + async callbacks + Response|{response}
union narrowing); assert.rejects guards with promise-returning
callbacks verified correct as-is.

Locally verified green: providers-yuanbao-web, ninerouter-executor,
provider-request-failure-pipeline, provider-limits-accesstoken-fallback,
executor-registry, chatcore-executor-proxy, poe-api-executor-regression,
web-cookie-providers-new (113/113).
This commit is contained in:
oyi77
2026-08-25 03:32:57 +07:00
committed by Markus Hartung
parent 77ea656b12
commit 158fb1a806
30 changed files with 124 additions and 120 deletions

View File

@@ -59,11 +59,11 @@ function mockFetchCapture(status = 200, text = "Hello from Blackbox") {
};
}
test("BlackboxWebExecutor is registered in executor index", () => {
test("BlackboxWebExecutor is registered in executor index", async () => {
assert.ok(hasSpecializedExecutor("blackbox-web"));
assert.ok(hasSpecializedExecutor("bb-web"));
const executor = getExecutor("blackbox-web");
const alias = getExecutor("bb-web");
const executor = await getExecutor("blackbox-web");
const alias = await getExecutor("bb-web");
assert.ok(executor instanceof BlackboxWebExecutor);
assert.ok(alias instanceof BlackboxWebExecutor);
});

View File

@@ -41,7 +41,7 @@ after(() => {
test("no config (disabled by default) returns the provider's own executor", async () => {
clearUpstreamProxyConfigCache("openai");
const exec = await resolveExecutorWithProxy("openai");
assert.equal(exec, getExecutor("openai"));
assert.equal(exec, await getExecutor("openai"));
});
test("mode 'native' returns the provider's own executor", async () => {
@@ -52,7 +52,7 @@ test("mode 'native' returns the provider's own executor", async () => {
});
clearUpstreamProxyConfigCache("openai");
const exec = await resolveExecutorWithProxy("openai");
assert.equal(exec, getExecutor("openai"));
assert.equal(exec, await getExecutor("openai"));
});
test("mode 'cliproxyapi' returns the CLIProxyAPI passthrough executor", async () => {
@@ -63,7 +63,7 @@ test("mode 'cliproxyapi' returns the CLIProxyAPI passthrough executor", async ()
});
clearUpstreamProxyConfigCache("anthropic");
const exec = await resolveExecutorWithProxy("anthropic");
assert.equal(exec, getExecutor("cliproxyapi"));
assert.equal(exec, await getExecutor("cliproxyapi"));
});
test("mode 'fallback' returns a distinct wrapper owning its own execute()", async () => {
@@ -74,8 +74,8 @@ test("mode 'fallback' returns a distinct wrapper owning its own execute()", asyn
});
clearUpstreamProxyConfigCache("openai");
const exec = await resolveExecutorWithProxy("openai");
assert.notEqual(exec, getExecutor("openai"));
assert.notEqual(exec, getExecutor("cliproxyapi"));
assert.notEqual(exec, await getExecutor("openai"));
assert.notEqual(exec, await getExecutor("cliproxyapi"));
assert.equal(typeof exec.execute, "function");
});
@@ -94,7 +94,7 @@ test("connection override 'claude-native' selects CLIProxyAPI even when provider
const exec = await resolveExecutorWithProxy("openai", undefined, {
cliproxyapiMode: "claude-native",
});
assert.equal(exec, getExecutor("cliproxyapi"));
assert.equal(exec, await getExecutor("cliproxyapi"));
});
test("connection override 'claude-native' selects CLIProxyAPI even with no provider config (default)", async () => {
@@ -102,7 +102,7 @@ test("connection override 'claude-native' selects CLIProxyAPI even with no provi
const exec = await resolveExecutorWithProxy("anthropic", undefined, {
cliproxyapiMode: "claude-native",
});
assert.equal(exec, getExecutor("cliproxyapi"));
assert.equal(exec, await getExecutor("cliproxyapi"));
});
test("no connection override + provider mode native → native executor (unchanged)", async () => {
@@ -115,13 +115,13 @@ test("no connection override + provider mode native → native executor (unchang
const exec = await resolveExecutorWithProxy("openai", undefined, {
someOtherField: "x",
});
assert.equal(exec, getExecutor("openai"));
assert.equal(exec, await getExecutor("openai"));
});
test("connection override absent (undefined providerSpecificData) preserves default behaviour", async () => {
clearUpstreamProxyConfigCache("openai");
const exec = await resolveExecutorWithProxy("openai");
assert.equal(exec, getExecutor("openai"));
assert.equal(exec, await getExecutor("openai"));
});
test("connection override wins over provider mode 'fallback'", async () => {
@@ -135,5 +135,5 @@ test("connection override wins over provider mode 'fallback'", async () => {
cliproxyapiMode: "claude-native",
});
// Connection override short-circuits to the passthrough executor, not the fallback wrapper.
assert.equal(exec, getExecutor("cliproxyapi"));
assert.equal(exec, await getExecutor("cliproxyapi"));
});

View File

@@ -456,7 +456,7 @@ test("chatCore times out upstream execution before provider response headers", a
// (fresh-DB default leaves it off → the waitFor below would never resolve;
// failed deterministically on CI and on an isolated run, incl. at v3.8.18).
await settingsDb.updateSettings({ call_log_pipeline_enabled: true });
const executor = getExecutor("openai");
const executor = await getExecutor("openai");
const originalGetTimeoutMs = executor.getTimeoutMs?.bind(executor);
executor.getTimeoutMs = () => 200;

View File

@@ -370,16 +370,16 @@ function reset() {
// ─── Registration ───────────────────────────────────────────────────────────
test("ChatGptWebExecutor is registered in executor index", () => {
test("ChatGptWebExecutor is registered in executor index", async () => {
assert.ok(hasSpecializedExecutor("chatgpt-web"));
assert.ok(hasSpecializedExecutor("cgpt-web"));
const executor = getExecutor("chatgpt-web");
const executor = await getExecutor("chatgpt-web");
assert.ok(executor instanceof ChatGptWebExecutor);
});
test("ChatGptWebExecutor alias resolves to same type", () => {
const a = getExecutor("chatgpt-web");
const b = getExecutor("cgpt-web");
test("ChatGptWebExecutor alias resolves to same type", async () => {
const a = await getExecutor("chatgpt-web");
const b = await getExecutor("cgpt-web");
assert.ok(a instanceof ChatGptWebExecutor);
assert.ok(b instanceof ChatGptWebExecutor);
});

View File

@@ -63,14 +63,14 @@ describe("ChipotleExecutor", () => {
it("is registered in executor index", async () => {
const { getExecutor } = await import("../../open-sse/executors/index.ts");
const exec = getExecutor("chipotle");
const exec = await getExecutor("chipotle");
assert.ok(exec, "chipotle executor should be registered");
assert.ok(exec instanceof ChipotleExecutor);
});
it("pepper alias works", async () => {
const { getExecutor } = await import("../../open-sse/executors/index.ts");
const exec = getExecutor("pepper");
const exec = await getExecutor("pepper");
assert.ok(exec, "pepper alias should be registered");
assert.ok(exec instanceof ChipotleExecutor);
});

View File

@@ -22,14 +22,14 @@ test("B: ClaudeWebExecutor alias cw-web is registered", () => {
assert.ok(hasSpecializedExecutor("cw-web"));
});
test("C: ClaudeWebExecutor can be retrieved from executor registry", () => {
const executor = getExecutor("claude-web");
test("C: ClaudeWebExecutor can be retrieved from executor registry", async () => {
const executor = await getExecutor("claude-web");
assert.ok(executor instanceof ClaudeWebExecutor);
});
test("D: ClaudeWebExecutor cw-web alias resolves to same type", () => {
const a = getExecutor("claude-web");
const b = getExecutor("cw-web");
test("D: ClaudeWebExecutor cw-web alias resolves to same type", async () => {
const a = await getExecutor("claude-web");
const b = await getExecutor("cw-web");
assert.ok(a instanceof ClaudeWebExecutor);
assert.ok(b instanceof ClaudeWebExecutor);
});

View File

@@ -31,7 +31,7 @@ const { getExecutor } = await import("../../open-sse/executors/index.ts");
const { refreshAndUpdateCredentials } = await import("../../src/lib/usage/providerLimits.ts");
test("codex: quota-sync must NOT proactively rotate the refresh_token (Auth0 family-revocation cascade guard)", async () => {
const exec = getExecutor("codex");
const exec = await getExecutor("codex");
const origNeeds = exec.needsRefresh;
const origRefresh = exec.refreshCredentials;
let refreshCalls = 0;
@@ -68,7 +68,7 @@ test("codex: quota-sync must NOT proactively rotate the refresh_token (Auth0 fam
});
test("non-rotating OAuth provider is still refreshed proactively from quota-sync (gate is not over-broad)", async () => {
const exec = getExecutor("cursor");
const exec = await getExecutor("cursor");
const origNeeds = exec.needsRefresh;
const origRefresh = exec.refreshCredentials;
let refreshCalls = 0;

View File

@@ -91,15 +91,15 @@ test("Command Code provider catalog has pinned models and alias lookup", () => {
assert.equal(getRegistryEntry("cmd"), entry);
});
test("getExecutor returns the specialized Command Code executor", () => {
test("getExecutor returns the specialized Command Code executor", async () => {
assert.equal(hasSpecializedExecutor("command-code"), true);
assert.ok(getExecutor("command-code") instanceof CommandCodeExecutor);
assert.ok(getExecutor("cmd") instanceof CommandCodeExecutor);
assert.ok((await getExecutor("command-code")) instanceof CommandCodeExecutor);
assert.ok((await getExecutor("cmd")) instanceof CommandCodeExecutor);
});
test("Command Code executor posts a flat OpenAI body + standard headers to /provider/v1/chat/completions (#10265)", async () => {
const calls = captureFetch({});
const executor = getExecutor("command-code");
const executor = await getExecutor("command-code");
const { response, url, headers } = await executor.execute({
model: "gpt-5.4-mini",
stream: false,
@@ -143,7 +143,7 @@ test("Command Code executor posts a flat OpenAI body + standard headers to /prov
test("Command Code executor passes reasoning/thinking fields through at the top level of the OpenAI body", async () => {
const calls = captureFetch({});
await getExecutor("command-code").execute({
(await getExecutor("command-code")).execute({
model: "deepseek/deepseek-v4-pro",
stream: false,
credentials: { apiKey: "cc_test_key" },
@@ -166,7 +166,7 @@ test("Command Code executor passes reasoning/thinking fields through at the top
test("Command Code executor honors body.model rewrite from payload rules", async () => {
const calls = captureFetch({});
await getExecutor("command-code").execute({
(await getExecutor("command-code")).execute({
model: "deepseek-v4-pro-max",
stream: false,
credentials: { apiKey: "cc_test_key" },
@@ -187,7 +187,7 @@ test("Command Code executor maps unsupported minimal reasoning_effort to low (up
const calls = captureFetch({});
// `minimal` (a Muse Spark catalog tier) must be downgraded to `low` before
// the wire body is built, on BOTH the combo and single-model paths.
await getExecutor("command-code").execute({
(await getExecutor("command-code")).execute({
model: "poolside/laguna-s-2.1-free",
stream: false,
credentials: { apiKey: "cc_test_key" },
@@ -232,7 +232,7 @@ test("Command Code executor passes the upstream OpenAI SSE stream through untouc
});
};
const { response } = await getExecutor("command-code").execute({
const { response } = (await getExecutor("command-code")).execute({
model: "gpt-5.4",
stream: true,
credentials: { apiKey: "cc_test_key" },
@@ -266,7 +266,7 @@ test("Command Code executor passes the upstream OpenAI JSON through untouched (n
});
};
const { response } = await getExecutor("command-code").execute({
const { response } = (await getExecutor("command-code")).execute({
model: "gpt-5.4-mini",
stream: false,
credentials: { apiKey: "cc_test_key" },
@@ -279,7 +279,7 @@ test("Command Code executor passes the upstream OpenAI JSON through untouched (n
test("Command Code executor surfaces upstream errors", async () => {
globalThis.fetch = async () => new Response("bad key", { status: 401, statusText: "Unauthorized" });
const upstreamFailure = await getExecutor("command-code").execute({
const upstreamFailure = (await getExecutor("command-code")).execute({
model: "gpt-5.4-mini",
stream: false,
credentials: { apiKey: "cc_test_key" },
@@ -291,7 +291,7 @@ test("Command Code executor surfaces upstream errors", async () => {
test("Command Code executor omits max_tokens when the client does not supply one", async () => {
const calls = captureFetch({});
await getExecutor("command-code").execute({
(await getExecutor("command-code")).execute({
model: "zai-org/GLM-5.1",
stream: false,
credentials: { apiKey: "cc_test_key" },
@@ -305,7 +305,7 @@ test("Command Code executor omits max_tokens when the client does not supply one
test("Command Code executor clamps an oversized client-supplied max_tokens to the endpoint ceiling", async () => {
const calls = captureFetch({});
// A client asking for more than the 200000 endpoint ceiling is clamped down.
await getExecutor("command-code").execute({
(await getExecutor("command-code")).execute({
model: "deepseek/deepseek-v4-pro",
stream: false,
credentials: { apiKey: "cc_test_key" },
@@ -316,7 +316,7 @@ test("Command Code executor clamps an oversized client-supplied max_tokens to th
test("Command Code executor honors a smaller client-provided max_tokens", async () => {
const calls = captureFetch({});
await getExecutor("command-code").execute({
(await getExecutor("command-code")).execute({
model: "zai-org/GLM-5.1",
stream: false,
credentials: { apiKey: "cc_test_key" },
@@ -350,7 +350,7 @@ test("Command Code stream preserves the upstream OpenAI usage chunk (passthrough
globalThis.fetch = async () =>
new Response(sse, { status: 200, headers: { "Content-Type": "text/event-stream" } });
const { response } = await getExecutor("command-code").execute({
const { response } = (await getExecutor("command-code")).execute({
model: "gpt-5.4-mini",
stream: true,
credentials: { apiKey: "cc_test_key" },

View File

@@ -18,13 +18,13 @@ test("DeepSeekWebExecutor registered as deepseek-web and ds-web", () => {
assert.ok(hasSpecializedExecutor("ds-web"));
});
test("getExecutor returns DeepSeekWebWithAutoRefreshExecutor", () => {
const exec = getExecutor("deepseek-web");
test("getExecutor returns DeepSeekWebWithAutoRefreshExecutor", async () => {
const exec = await getExecutor("deepseek-web");
assert.ok(exec instanceof DeepSeekWebWithAutoRefreshExecutor);
});
test("alias ds-web resolves same executor", () => {
assert.ok(getExecutor("ds-web") instanceof DeepSeekWebWithAutoRefreshExecutor);
test("alias ds-web resolves same executor", async () => {
assert.ok(await getExecutor("ds-web") instanceof DeepSeekWebWithAutoRefreshExecutor);
});
test("provider name is deepseek-web", () => {

View File

@@ -241,7 +241,7 @@ describe("DuckDuckGoWebExecutor", () => {
it("should be registered in executor index", async () => {
const { getExecutor } = await import("../../open-sse/executors/index.ts");
const executor = getExecutor("duckduckgo-web");
const executor = await getExecutor("duckduckgo-web");
assert.ok(executor, "executor should be registered in index");
assert.equal(
typeof executor.execute,

View File

@@ -21,13 +21,13 @@ test.after(() => {
fs.rmSync(TEST_DATA_DIR, { recursive: true, force: true });
});
test("built-ins are registered at module load and resolve through the registry", () => {
test("built-ins are registered at module load and resolve through the registry", async () => {
const aliases = listExecutorAliases();
assert.ok(aliases.length >= 100, `expected the built-in table, got ${aliases.length} aliases`);
for (const alias of ["antigravity", "kiro", "glm", "9router", "conol-web"]) {
assert.ok(hasRegisteredExecutor(alias), `missing built-in: ${alias}`);
assert.equal(getExecutor(alias), getRegisteredExecutor(alias));
assert.ok(getExecutor(alias) instanceof BaseExecutor);
assert.equal(await getExecutor(alias), getRegisteredExecutor(alias));
assert.ok((await getExecutor(alias)) instanceof BaseExecutor);
}
});
@@ -37,21 +37,21 @@ test("registerExecutor throws on duplicate alias", () => {
});
});
test("registering a new alias makes it resolvable via getExecutor and hasSpecializedExecutor", () => {
test("registering a new alias makes it resolvable via getExecutor and hasSpecializedExecutor", async () => {
const alias = "registry-test-provider";
assert.equal(hasSpecializedExecutor(alias), false);
const instance = new DefaultExecutor(alias);
registerExecutor(alias, instance);
assert.equal(hasSpecializedExecutor(alias), true);
assert.equal(getExecutor(alias), instance);
assert.equal(await getExecutor(alias), instance);
});
test("registry lookup is exact — Object.prototype names are not executors", () => {
test("registry lookup is exact — Object.prototype names are not executors", async () => {
// The old object-literal lookup (`executors[provider]`) leaked prototype
// members: getExecutor("constructor") returned Object's constructor. The Map
// registry must treat these as unknown providers (DefaultExecutor fallback).
for (const name of ["constructor", "toString", "hasOwnProperty", "__proto__"]) {
assert.equal(hasSpecializedExecutor(name), false, name);
assert.ok(getExecutor(name) instanceof DefaultExecutor, name);
assert.ok((await getExecutor(name)) instanceof DefaultExecutor, name);
}
});

View File

@@ -20,7 +20,7 @@ const providers = [
] as const;
for (const [id, alias, endpoint] of providers) {
test(`${id} is wired through registry, metadata, endpoint and default executor`, () => {
test(`${id} is wired through registry, metadata, endpoint and default executor`, async () => {
const registry = REGISTRY[id];
const metadata = APIKEY_PROVIDERS[id];
@@ -35,7 +35,7 @@ for (const [id, alias, endpoint] of providers) {
assert.equal(metadata.hasFree, true);
assert.equal(metadata.passthroughModels, true);
assert.ok(typeof metadata.freeNote === "string" && metadata.freeNote.length > 0);
assert.ok(getExecutor(id) instanceof DefaultExecutor);
assert.ok((await getExecutor(id)) instanceof DefaultExecutor);
assert.equal(isValidModel(id, "future/live-catalog-model"), true);
assert.equal(isValidModel(alias, "future/live-catalog-model"), true);
});

View File

@@ -25,7 +25,7 @@ const providers = [
] as const;
for (const [id, endpoint, modelIds] of providers) {
test(`${id} is wired through registry, metadata, endpoint and default executor`, () => {
test(`${id} is wired through registry, metadata, endpoint and default executor`, async () => {
const registry = REGISTRY[id];
const metadata = APIKEY_PROVIDERS[id];
@@ -41,7 +41,7 @@ for (const [id, endpoint, modelIds] of providers) {
assert.equal(metadata.passthroughModels, true);
assert.ok(typeof metadata.freeNote === "string" && metadata.freeNote.length > 0);
assert.equal(AGGREGATOR_PROVIDER_IDS.has(id), true);
assert.ok(getExecutor(id) instanceof DefaultExecutor);
assert.ok((await getExecutor(id)) instanceof DefaultExecutor);
assert.equal(isValidModel(id, "future/live-catalog-model"), true);
assert.deepEqual(
registry.models.map((model) => model.id),

View File

@@ -20,7 +20,7 @@ const providers = [
] as const;
for (const [id, endpoint] of providers) {
test(`${id} is wired through registry, metadata, endpoint and default executor`, () => {
test(`${id} is wired through registry, metadata, endpoint and default executor`, async () => {
const registry = REGISTRY[id];
const metadata = APIKEY_PROVIDERS[id];
@@ -36,7 +36,8 @@ for (const [id, endpoint] of providers) {
assert.equal(metadata.passthroughModels, true);
assert.ok(typeof metadata.freeNote === "string" && metadata.freeNote.length > 0);
assert.equal(AGGREGATOR_PROVIDER_IDS.has(id), true);
assert.ok(getExecutor(id) instanceof DefaultExecutor);
const executor = await getExecutor(id);
assert.ok(executor instanceof DefaultExecutor);
assert.equal(isValidModel(id, "future/live-catalog-model"), true);
assert.deepEqual(registry.models, []);
});

View File

@@ -17,7 +17,7 @@ const providers = [
] as const;
for (const [id, endpoint] of providers) {
test(`${id} is fully wired without a specialized executor`, () => {
test(`${id} is fully wired without a specialized executor`, async () => {
const registry = REGISTRY[id];
const metadata = APIKEY_PROVIDERS[id];
@@ -33,7 +33,7 @@ for (const [id, endpoint] of providers) {
assert.equal(metadata.passthroughModels, true);
assert.equal(AGGREGATOR_PROVIDER_IDS.has(id), true);
assert.equal(hasSpecializedExecutor(id), false);
const executor = getExecutor(id);
const executor = await getExecutor(id);
assert.ok(executor instanceof DefaultExecutor);
assert.equal(executor.buildUrl("live-model", false), endpoint);
assert.equal(isValidModel(id, "future/live-catalog-model"), true);

View File

@@ -27,7 +27,7 @@ const providers = [
] as const;
for (const { id, endpoint, modelsUrl, hasFree } of providers) {
test(`${id} is fully wired through the public provider interfaces`, () => {
test(`${id} is fully wired through the public provider interfaces`, async () => {
const registry = REGISTRY[id];
const metadata = APIKEY_PROVIDERS[id];
@@ -52,7 +52,7 @@ for (const { id, endpoint, modelsUrl, hasFree } of providers) {
assert.equal(AGGREGATOR_PROVIDER_IDS.has(id), true);
assert.equal(hasSpecializedExecutor(id), false);
const executor = getExecutor(id);
const executor = await getExecutor(id);
assert.ok(executor instanceof DefaultExecutor);
assert.equal(executor.buildUrl("live-model", false), endpoint);
assert.equal(isValidModel(id, "future/live-catalog-model"), true);

View File

@@ -73,8 +73,8 @@ for (const [id, subPath] of Object.entries(SUB_PATHS)) {
);
});
test(`#6650 ${id} resolves through getExecutor() as a DefaultExecutor instance`, () => {
const executor = getExecutor(id);
test(`#6650 ${id} resolves through getExecutor() as a DefaultExecutor instance`, async () => {
const executor = await getExecutor(id);
assert.ok(
executor instanceof DefaultExecutor,
`${id} has no custom executor — must fall through to DefaultExecutor`

View File

@@ -7,9 +7,9 @@ const { getExecutor, hasSpecializedExecutor } = await import("../../open-sse/exe
// ─── Registration ───────────────────────────────────────────────────────────
test("GeminiWebExecutor is registered in executor index", () => {
test("GeminiWebExecutor is registered in executor index", async () => {
assert.ok(hasSpecializedExecutor("gemini-web"));
const executor = getExecutor("gemini-web");
const executor = await getExecutor("gemini-web");
assert.ok(executor instanceof GeminiWebExecutor);
});

View File

@@ -83,9 +83,9 @@ test.afterEach(() => {
// ─── Registration ───────────────────────────────────────────────────────────
test("GrokWebExecutor is registered in executor index", () => {
test("GrokWebExecutor is registered in executor index", async () => {
assert.ok(hasSpecializedExecutor("grok-web"));
const executor = getExecutor("grok-web");
const executor = await getExecutor("grok-web");
assert.ok(executor instanceof GrokWebExecutor);
});

View File

@@ -498,13 +498,13 @@ describe("NineRouterExecutor", () => {
describe("getExecutor registration", () => {
it("getExecutor('9router') returns a NineRouterExecutor", async () => {
const { getExecutor } = await import("../../open-sse/executors/index.ts");
const exec = getExecutor("9router");
const exec = await getExecutor("9router");
assert.equal(exec.getProvider(), "9router");
});
it("getExecutor('nr') alias resolves to NineRouterExecutor", async () => {
const { getExecutor } = await import("../../open-sse/executors/index.ts");
const exec = getExecutor("nr");
const exec = await getExecutor("nr");
assert.equal(exec.getProvider(), "9router");
});
});

View File

@@ -91,16 +91,16 @@ function mockFetchError(error) {
// ─── Test: Executor registration ────────────────────────────────────────────
test("PerplexityWebExecutor is registered in executor index", () => {
test("PerplexityWebExecutor is registered in executor index", async () => {
assert.ok(hasSpecializedExecutor("perplexity-web"));
assert.ok(hasSpecializedExecutor("pplx-web"));
const executor = getExecutor("perplexity-web");
const executor = await getExecutor("perplexity-web");
assert.ok(executor instanceof PerplexityWebExecutor);
});
test("PerplexityWebExecutor alias resolves to same type", () => {
const a = getExecutor("perplexity-web");
const b = getExecutor("pplx-web");
test("PerplexityWebExecutor alias resolves to same type", async () => {
const a = await getExecutor("perplexity-web");
const b = await getExecutor("pplx-web");
assert.ok(a instanceof PerplexityWebExecutor);
assert.ok(b instanceof PerplexityWebExecutor);
});

View File

@@ -47,17 +47,18 @@ function headerRecord(headers: Record<string, string>): Record<string, string> {
return out;
}
test("#8969: getExecutor(poe) selects DefaultExecutor, not PoeWebExecutor", () => {
test("#8969: getExecutor(poe) selects DefaultExecutor, not PoeWebExecutor", async () => {
assert.equal(hasSpecializedExecutor("poe"), false);
const executor = getExecutor("poe");
const executor = await getExecutor("poe");
assert.ok(executor instanceof DefaultExecutor);
assert.equal(executor instanceof PoeWebExecutor, false);
assert.equal(executor.provider, "poe");
});
test("#8969: getExecutor(poe-web) still selects PoeWebExecutor", () => {
test("#8969: getExecutor(poe-web) still selects PoeWebExecutor", async () => {
assert.equal(hasSpecializedExecutor("poe-web"), true);
assert.ok(getExecutor("poe-web") instanceof PoeWebExecutor);
const executor = await getExecutor("poe-web");
assert.ok(executor instanceof PoeWebExecutor);
});
test("#8969: registry declares API-key executor + all three Poe protocol URLs", () => {
@@ -80,8 +81,8 @@ test("#8969: registry declares API-key executor + all three Poe protocol URLs",
assert.notEqual(gpt.targetFormat, "claude");
});
test("#8969: buildUrl routes chat / responses / messages correctly", () => {
const executor = getExecutor("poe") as DefaultExecutor;
test("#8969: buildUrl routes chat / responses / messages correctly", async () => {
const executor = (await getExecutor("poe")) as DefaultExecutor;
const creds = { apiKey: "poe-test-key", providerSpecificData: {} };
assert.equal(executor.buildUrl("gemma-4-31b", false, 0, creds), CHAT_URL);
@@ -175,8 +176,8 @@ test("#8969: resolvePoeUpstreamUrl normalizes registry-default / bare-host /v1/
}
});
test("#8969: buildHeaders uses Bearer auth and never sends Cookie", () => {
const executor = getExecutor("poe") as DefaultExecutor;
test("#8969: buildHeaders uses Bearer auth and never sends Cookie", async () => {
const executor = (await getExecutor("poe")) as DefaultExecutor;
for (const stream of [false, true]) {
const headers = headerRecord(
executor.buildHeaders({ apiKey: "poe-test-key", providerSpecificData: {} }, stream)
@@ -200,7 +201,7 @@ test("#8969: resolveExecutionCredentials forces responses upstream for poe", ()
});
test("#8969: mocked execute posts Chat Completions with Bearer, no Cookie, stripped model", async () => {
const executor = getExecutor("poe") as DefaultExecutor;
const executor = (await getExecutor("poe")) as DefaultExecutor;
const originalFetch = globalThis.fetch;
const seen: Array<{
url: string;
@@ -259,7 +260,7 @@ test("#8969: mocked execute posts Chat Completions with Bearer, no Cookie, strip
});
test("#8969: mocked execute routes Responses + Messages fixtures to the right URLs", async () => {
const executor = getExecutor("poe") as DefaultExecutor;
const executor = (await getExecutor("poe")) as DefaultExecutor;
const originalFetch = globalThis.fetch;
let lastUrl = "";
@@ -326,7 +327,7 @@ test("#8969: mocked execute routes Responses + Messages fixtures to the right UR
});
test("#8969: mocked upstream 405 is preserved (not swallowed)", async () => {
const executor = getExecutor("poe") as DefaultExecutor;
const executor = (await getExecutor("poe")) as DefaultExecutor;
const originalFetch = globalThis.fetch;
globalThis.fetch = (async () => {

View File

@@ -39,7 +39,7 @@ function geminiConnection() {
}
test("falls back to the existing accessToken for a non-github provider when refreshCredentials returns null", async () => {
const exec = getExecutor("gemini");
const exec = await getExecutor("gemini");
const origNeeds = exec.needsRefresh;
const origRefresh = exec.refreshCredentials;
exec.needsRefresh = () => true; // force the refresh attempt
@@ -65,7 +65,7 @@ test("falls back to the existing accessToken for a non-github provider when refr
});
test("still throws when refresh fails AND there is no accessToken to fall back on", async () => {
const exec = getExecutor("gemini");
const exec = await getExecutor("gemini");
const origNeeds = exec.needsRefresh;
const origRefresh = exec.refreshCredentials;
exec.needsRefresh = () => true;

View File

@@ -33,7 +33,7 @@ function importedCodexConnection() {
}
test("force re-mints an imported rotating account that needsRefresh would skip (#3019 reactive)", async () => {
const exec = getExecutor("codex");
const exec = await getExecutor("codex");
const origNeeds = exec.needsRefresh;
const origRefresh = exec.refreshCredentials;
let refreshCalls = 0;
@@ -65,7 +65,7 @@ test("force re-mints an imported rotating account that needsRefresh would skip (
});
test("force does NOT override the bulk #3019 guard (no allowRotatingRefresh → no mint)", async () => {
const exec = getExecutor("codex");
const exec = await getExecutor("codex");
const origNeeds = exec.needsRefresh;
const origRefresh = exec.refreshCredentials;
let refreshCalls = 0;

View File

@@ -33,8 +33,8 @@ test("#6670 freetheai is registered in the executor registry with an OpenAI-comp
assert.ok(Array.isArray(entry.models) && entry.models.length > 0, "must seed a fallback model list");
});
test("#6670 freetheai resolves through getExecutor() as a DefaultExecutor instance", () => {
const executor = getExecutor("freetheai");
test("#6670 freetheai resolves through getExecutor() as a DefaultExecutor instance", async () => {
const executor = await getExecutor("freetheai");
assert.ok(executor instanceof DefaultExecutor, "freetheai has no custom executor — must fall through to DefaultExecutor");
});

View File

@@ -153,7 +153,7 @@ test("network failure persisted call log includes providerRequest in pipeline pa
test("network timeout persisted call log includes providerRequest in pipeline payloads", async () => {
const { getExecutor } = await import("../../open-sse/executors/index.ts");
const executor = getExecutor("openai");
const executor = await getExecutor("openai");
const originalGetTimeoutMs = executor.getTimeoutMs?.bind(executor);
executor.getTimeoutMs = () => 200;

View File

@@ -68,8 +68,8 @@ for (const [id, info] of Object.entries(PROVIDERS)) {
assert.equal(entry.passthroughModels, true);
});
test(`#6674 ${id} resolves through getExecutor() as a DefaultExecutor instance`, () => {
const executor = getExecutor(id);
test(`#6674 ${id} resolves through getExecutor() as a DefaultExecutor instance`, async () => {
const executor = await getExecutor(id);
assert.ok(
executor instanceof DefaultExecutor,
`${id} has no custom executor — must fall through to DefaultExecutor`

View File

@@ -39,11 +39,11 @@ test("yuanbao-web appears in the web-cookie catalog with a cookie authHint", ()
assert.match(String(entry.website), /yuanbao\.tencent\.com/);
});
test("YuanbaoWebExecutor is wired under id and alias", () => {
test("YuanbaoWebExecutor is wired under id and alias", async () => {
assert.ok(hasSpecializedExecutor("yuanbao-web"));
assert.ok(hasSpecializedExecutor("ybw"));
assert.ok(getExecutor("yuanbao-web") instanceof YuanbaoWebExecutor);
assert.ok(getExecutor("ybw") instanceof YuanbaoWebExecutor);
assert.ok(await getExecutor("yuanbao-web") instanceof YuanbaoWebExecutor);
assert.ok(await getExecutor("ybw") instanceof YuanbaoWebExecutor);
});
// ── Behavioral: SSE → OpenAI translation (mocked upstream) ─────────────────────

View File

@@ -20,13 +20,13 @@ test("hasSpecializedExecutor returns true for t3chat alias", () => {
assert.ok(hasSpecializedExecutor("t3chat"));
});
test("getExecutor returns T3ChatWebExecutor for t3-web", () => {
const exec = getExecutor("t3-web");
test("getExecutor returns T3ChatWebExecutor for t3-web", async () => {
const exec = await getExecutor("t3-web");
assert.ok(exec instanceof T3ChatWebExecutor);
});
test("getExecutor returns T3ChatWebExecutor for t3chat alias", () => {
const exec = getExecutor("t3chat");
test("getExecutor returns T3ChatWebExecutor for t3chat alias", async () => {
const exec = await getExecutor("t3chat");
assert.ok(exec instanceof T3ChatWebExecutor);
});

View File

@@ -110,49 +110,51 @@ const noopExecuteInput = {
// ── Registration Tests ───────────────────────────────────────────────────────
test("HuggingChat executor is registered", () => {
test("HuggingChat executor is registered", async () => {
assert.ok(hasSpecializedExecutor("huggingchat"));
assert.ok(hasSpecializedExecutor("hc"));
const executor = getExecutor("huggingchat");
const executor = await getExecutor("huggingchat");
assert.ok(executor instanceof HuggingChatExecutor);
});
test("Poe Web executor is registered", () => {
test("Poe Web executor is registered", async () => {
assert.ok(hasSpecializedExecutor("poe-web"));
const executor = getExecutor("poe-web");
const executor = await getExecutor("poe-web");
assert.ok(executor instanceof PoeWebExecutor);
// #8969: canonical API-key `poe` must not route through PoeWebExecutor.
assert.equal(hasSpecializedExecutor("poe"), false);
assert.ok(!(getExecutor("poe") instanceof PoeWebExecutor));
const poeApiExecutor = await getExecutor("poe");
assert.ok(!(poeApiExecutor instanceof PoeWebExecutor));
});
test("Venice Web executor is registered", () => {
test("Venice Web executor is registered", async () => {
assert.ok(hasSpecializedExecutor("venice-web"));
assert.ok(hasSpecializedExecutor("ven"));
const executor = getExecutor("venice-web");
const executor = await getExecutor("venice-web");
assert.ok(executor instanceof VeniceWebExecutor);
});
test("v0 Vercel Web executor is registered", () => {
test("v0 Vercel Web executor is registered", async () => {
assert.ok(hasSpecializedExecutor("v0-vercel-web"));
assert.ok(hasSpecializedExecutor("v0"));
const executor = getExecutor("v0-vercel-web");
const executor = await getExecutor("v0-vercel-web");
assert.ok(executor instanceof V0VercelWebExecutor);
});
test("Kimi Web executor is registered", () => {
assert.ok(getExecutor("kimi-web") instanceof KimiWebExecutor);
test("Kimi Web executor is registered", async () => {
const kimiWebExecutor = await getExecutor("kimi-web");
assert.ok(kimiWebExecutor instanceof KimiWebExecutor);
// #4699: the legacy `kimi` API-key id must never route through Kimi Web.
assert.ok(hasSpecializedExecutor("kimi"));
const legacyExecutor = getExecutor("kimi");
const legacyExecutor = await getExecutor("kimi");
assert.ok(legacyExecutor instanceof MoonshotExecutor);
assert.ok(!(legacyExecutor instanceof KimiWebExecutor));
});
test("Doubao Web executor is registered", () => {
test("Doubao Web executor is registered", async () => {
assert.ok(hasSpecializedExecutor("doubao-web"));
assert.ok(hasSpecializedExecutor("db"));
const executor = getExecutor("doubao-web");
const executor = await getExecutor("doubao-web");
assert.ok(executor instanceof DoubaoWebExecutor);
});
@@ -190,9 +192,9 @@ test("Doubao Web sets correct provider", () => {
// ── Registration Tests (Qwen Web) ────────────────────────────────────────────
test("Qwen Web executor is registered", () => {
test("Qwen Web executor is registered", async () => {
assert.ok(hasSpecializedExecutor("qwen-web"));
const executor = getExecutor("qwen-web");
const executor = await getExecutor("qwen-web");
assert.ok(executor instanceof QwenWebExecutor);
});