mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-09 16:21:15 +00:00
refactor(providers): flatten shared stream hooks
This commit is contained in:
@@ -317,7 +317,7 @@ export function buildOpenAICodexProviderPlugin(): ProviderPlugin {
|
||||
transport: "auto",
|
||||
};
|
||||
},
|
||||
wrapStreamFn: (ctx) => OPENAI_RESPONSES_STREAM_HOOKS.wrapStreamFn?.(ctx),
|
||||
...OPENAI_RESPONSES_STREAM_HOOKS,
|
||||
resolveTransportTurnState: (ctx) => resolveOpenAITransportTurnState(ctx),
|
||||
resolveWebSocketSessionPolicy: (ctx) => resolveOpenAIWebSocketSessionPolicy(ctx),
|
||||
resolveReasoningOutputMode: () => "native",
|
||||
|
||||
@@ -256,7 +256,7 @@ export function buildOpenAIProvider(): ProviderPlugin {
|
||||
...(hasExplicitWarmup ? {} : { openaiWsWarmup: true }),
|
||||
};
|
||||
},
|
||||
wrapStreamFn: (ctx) => OPENAI_RESPONSES_STREAM_HOOKS.wrapStreamFn?.(ctx),
|
||||
...OPENAI_RESPONSES_STREAM_HOOKS,
|
||||
matchesContextOverflowError: ({ errorMessage }) =>
|
||||
/content_filter.*(?:prompt|input).*(?:too long|exceed)/i.test(errorMessage),
|
||||
resolveTransportTurnState: (ctx) => resolveOpenAITransportTurnState(ctx),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js";
|
||||
import openrouterPlugin from "./index.js";
|
||||
|
||||
@@ -14,4 +14,41 @@ describe("openrouter provider hooks", () => {
|
||||
} as never),
|
||||
).toBe("native");
|
||||
});
|
||||
|
||||
it("injects provider routing into compat before applying stream wrappers", async () => {
|
||||
const provider = await registerSingleProviderPlugin(openrouterPlugin);
|
||||
const baseStreamFn = vi.fn(() => ({ async *[Symbol.asyncIterator]() {} }) as never);
|
||||
|
||||
const wrapped = provider.wrapStreamFn?.({
|
||||
provider: "openrouter",
|
||||
modelId: "openai/gpt-5.4",
|
||||
extraParams: {
|
||||
provider: {
|
||||
order: ["moonshot"],
|
||||
},
|
||||
},
|
||||
streamFn: baseStreamFn,
|
||||
thinkingLevel: "high",
|
||||
} as never);
|
||||
|
||||
wrapped?.(
|
||||
{
|
||||
provider: "openrouter",
|
||||
api: "openai-completions",
|
||||
id: "openai/gpt-5.4",
|
||||
compat: {},
|
||||
} as never,
|
||||
{ messages: [] } as never,
|
||||
{},
|
||||
);
|
||||
|
||||
expect(baseStreamFn).toHaveBeenCalledOnce();
|
||||
expect(baseStreamFn.mock.calls[0]?.[0]).toMatchObject({
|
||||
compat: {
|
||||
openRouterRouting: {
|
||||
order: ["moonshot"],
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
definePluginEntry,
|
||||
type ProviderResolveDynamicModelContext,
|
||||
type ProviderRuntimeModel,
|
||||
type ProviderWrapStreamFnContext,
|
||||
} from "openclaw/plugin-sdk/plugin-entry";
|
||||
|
||||
const PROVIDER_ID = "openrouter";
|
||||
@@ -80,6 +81,22 @@ export default definePluginEntry({
|
||||
);
|
||||
}
|
||||
|
||||
function wrapOpenRouterProviderStream(
|
||||
ctx: ProviderWrapStreamFnContext,
|
||||
): StreamFn | undefined {
|
||||
const providerRouting =
|
||||
ctx.extraParams?.provider != null && typeof ctx.extraParams.provider === "object"
|
||||
? (ctx.extraParams.provider as Record<string, unknown>)
|
||||
: undefined;
|
||||
const routedStreamFn = providerRouting
|
||||
? injectOpenRouterRouting(ctx.streamFn, providerRouting)
|
||||
: ctx.streamFn;
|
||||
return OPENROUTER_THINKING_STREAM_HOOKS.wrapStreamFn?.({
|
||||
...ctx,
|
||||
streamFn: routedStreamFn,
|
||||
});
|
||||
}
|
||||
|
||||
function isOpenRouterCacheTtlModel(modelId: string): boolean {
|
||||
return OPENROUTER_CACHE_TTL_MODEL_PREFIXES.some((prefix) => modelId.startsWith(prefix));
|
||||
}
|
||||
@@ -133,19 +150,7 @@ export default definePluginEntry({
|
||||
...PASSTHROUGH_GEMINI_REPLAY_HOOKS,
|
||||
resolveReasoningOutputMode: () => "native",
|
||||
isModernModelRef: () => true,
|
||||
wrapStreamFn: (ctx) => {
|
||||
const providerRouting =
|
||||
ctx.extraParams?.provider != null && typeof ctx.extraParams.provider === "object"
|
||||
? (ctx.extraParams.provider as Record<string, unknown>)
|
||||
: undefined;
|
||||
const routedStreamFn = providerRouting
|
||||
? injectOpenRouterRouting(ctx.streamFn, providerRouting)
|
||||
: ctx.streamFn;
|
||||
return OPENROUTER_THINKING_STREAM_HOOKS.wrapStreamFn?.({
|
||||
...ctx,
|
||||
streamFn: routedStreamFn,
|
||||
});
|
||||
},
|
||||
wrapStreamFn: wrapOpenRouterProviderStream,
|
||||
isCacheTtlEligible: (ctx) => isOpenRouterCacheTtlModel(ctx.modelId),
|
||||
});
|
||||
api.registerMediaUnderstandingProvider(openrouterMediaUnderstandingProvider);
|
||||
|
||||
Reference in New Issue
Block a user