diff --git a/extensions/cohere/index.test.ts b/extensions/cohere/index.test.ts index 9cfb63737189..6623ed01736c 100644 --- a/extensions/cohere/index.test.ts +++ b/extensions/cohere/index.test.ts @@ -7,7 +7,7 @@ import { describe, expect, it } from "vitest"; import plugin from "./index.js"; import manifest from "./openclaw.plugin.json" with { type: "json" }; import { COHERE_LIVE_MODEL_DISCOVERY } from "./provider-catalog.js"; -import { createCohereCompletionsWrapper } from "./stream.js"; +import { wrapCohereProviderStream } from "./stream.js"; const COHERE_COMMAND_A_PLUS_MODEL_ID = "command-a-plus-05-2026"; const COHERE_COMMAND_A_REASONING_MODEL_ID = "command-a-reasoning-08-2025"; @@ -50,11 +50,17 @@ function captureCoherePayload( return {} as ReturnType; }; - const wrappedStreamFn = createCohereCompletionsWrapper(baseStreamFn); + const model = requireCohereModel(settings?.modelId); + const wrappedStreamFn = wrapCohereProviderStream({ + provider: "cohere", + modelId: model.id, + model, + streamFn: baseStreamFn, + }); if (!wrappedStreamFn) { throw new Error("Cohere wrapper did not return a stream function"); } - void wrappedStreamFn(requireCohereModel(settings?.modelId), context, { + void wrappedStreamFn(model, context, { onPayload: (payload) => { captured = payload as Record; }, diff --git a/extensions/cohere/index.ts b/extensions/cohere/index.ts index 204b432f0cb1..7deee891f20b 100644 --- a/extensions/cohere/index.ts +++ b/extensions/cohere/index.ts @@ -3,7 +3,7 @@ import { isModernCohereModelId } from "./models.js"; import { applyCohereConfig } from "./onboard.js"; import manifest from "./openclaw.plugin.json" with { type: "json" }; import { COHERE_LIVE_MODEL_DISCOVERY } from "./provider-catalog.js"; -import { createCohereCompletionsWrapper } from "./stream.js"; +import { wrapCohereProviderStream } from "./stream.js"; export default defineSingleProviderPluginEntry({ id: "cohere", @@ -17,8 +17,8 @@ export default defineSingleProviderPluginEntry({ catalog: { liveModelDiscovery: COHERE_LIVE_MODEL_DISCOVERY, }, - wrapStreamFn: (ctx) => createCohereCompletionsWrapper(ctx.streamFn), - wrapSimpleCompletionStreamFn: (ctx) => createCohereCompletionsWrapper(ctx.streamFn), + wrapStreamFn: wrapCohereProviderStream, + wrapSimpleCompletionStreamFn: wrapCohereProviderStream, isModernModelRef: ({ modelId }) => isModernCohereModelId(modelId), }, }); diff --git a/extensions/cohere/stream.ts b/extensions/cohere/stream.ts index 5038cc7acc7a..dea98aee50ed 100644 --- a/extensions/cohere/stream.ts +++ b/extensions/cohere/stream.ts @@ -1,26 +1,20 @@ import type { ProviderWrapStreamFnContext } from "openclaw/plugin-sdk/plugin-entry"; import { createPayloadPatchStreamWrapper } from "openclaw/plugin-sdk/provider-stream-shared"; -function patchCoherePayload(payload: Record): void { - // Cohere's Compatibility API uses developer, not system, for instructions. - if (Array.isArray(payload.messages)) { - payload.messages = payload.messages.map((message) => - message && - typeof message === "object" && - (message as Record).role === "system" - ? { ...(message as Record), role: "developer" } - : message, - ); - } +export function wrapCohereProviderStream(ctx: ProviderWrapStreamFnContext) { + return createPayloadPatchStreamWrapper(ctx.streamFn, ({ payload }) => { + // Cohere's Compatibility API uses developer, not system, for instructions. + if (Array.isArray(payload.messages)) { + payload.messages = payload.messages.map((message) => + message && + typeof message === "object" && + (message as Record).role === "system" + ? { ...(message as Record), role: "developer" } + : message, + ); + } - // Cohere lets tool-capable models choose a tool when tool_choice is omitted. - delete payload.tool_choice; -} - -export function createCohereCompletionsWrapper( - baseStreamFn: ProviderWrapStreamFnContext["streamFn"], -): ProviderWrapStreamFnContext["streamFn"] { - return createPayloadPatchStreamWrapper(baseStreamFn, ({ payload }) => - patchCoherePayload(payload), - ); + // Cohere lets tool-capable models choose a tool when tool_choice is omitted. + delete payload.tool_choice; + }); }