openclaw/extensions/openai/index.ts
Peter Steinberger 4994ec4501
fix(openai): retire the Sora video provider after the API shutdown (#159543)
OpenAI shut down its Sora video API: sora-2 and sora-2-pro report
shutdown_date 2026-09-24 and POST/GET /v1/videos now return HTTP 404 for
every project. Every video_generate call routed to openai/* failed with an
opaque "OpenAI video generation failed (HTTP 404)", and because the bundled
openai plugin still advertised a configured video provider, agents on
OpenAI-only installs kept selecting it.

Remove the OpenAI video-generation provider, its manifest contract and
metadata, live-test defaults and workflow filters, and the docs that
advertised Sora. Stale openai/sora-* refs need no migration: the media
runtime already skips them with "No video-generation provider registered
for openai" and continues to configured fallbacks or auto-detected
providers.
2026-09-27 22:52:14 +00:00

95 lines
4 KiB
TypeScript

import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts";
import { resolvePluginConfigObject } from "openclaw/plugin-sdk/plugin-config-runtime";
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
import { buildProviderToolCompatFamilyHooks } from "openclaw/plugin-sdk/provider-tools";
import { buildOpenAIImageGenerationProvider } from "./image-generation-provider.js";
import { openaiMediaUnderstandingProvider } from "./media-understanding-provider.js";
import { openAiMemoryEmbeddingProviderAdapter } from "./memory-embedding-adapter.js";
import { buildOpenAIProvider } from "./openai-provider.js";
import {
resolveOpenAIPromptOverlayMode,
resolveOpenAISystemPromptContribution,
} from "./prompt-overlay.js";
import {
acquireOpenAIQuicksilverBrowserSessionBroker,
releaseOpenAIQuicksilverBrowserSessionBroker,
} from "./realtime-quicksilver-session-owner.js";
import { OPENAI_QUICKSILVER_OFFER_PATH } from "./realtime-quicksilver-session.js";
import { buildOpenAIRealtimeTranscriptionProvider } from "./realtime-transcription-provider-factory.js";
import { buildOpenAIRealtimeVoiceProvider } from "./realtime-voice-provider-factory.js";
import { buildOpenAISpeechProvider } from "./speech-provider.js";
export default definePluginEntry({
id: "openai",
name: "OpenAI Provider",
description: "Bundled OpenAI provider plugins",
register(api) {
const { ensureAuthProfileStore, listProfilesForProvider, isProviderApiKeyConfigured } =
api.runtime.modelAuth;
const openAIToolCompatHooks = buildProviderToolCompatFamilyHooks("openai");
const provider = buildOpenAIProvider();
api.registerProvider({
...provider,
...openAIToolCompatHooks,
resolveSystemPromptContribution: (ctx) => {
const runtimePluginConfig = resolvePluginConfigObject(ctx.config, "openai");
const pluginConfig =
runtimePluginConfig ??
(ctx.config ? undefined : (api.pluginConfig as Record<string, unknown>));
return resolveOpenAISystemPromptContribution({
config: ctx.config,
legacyPluginConfig: pluginConfig,
mode: resolveOpenAIPromptOverlayMode(pluginConfig),
modelProviderId: provider.id,
modelId: ctx.modelId,
trigger: ctx.trigger,
});
},
});
api.registerEmbeddingProvider(openAiMemoryEmbeddingProviderAdapter);
api.registerImageGenerationProvider(
buildOpenAIImageGenerationProvider({
ensureAuthProfileStore,
listProfilesForProvider,
isProviderApiKeyConfigured,
}),
);
api.registerRealtimeTranscriptionProvider(buildOpenAIRealtimeTranscriptionProvider);
api.registerRealtimeVoiceProvider((context) => {
const quicksilverSession =
api.registrationMode === "full"
? acquireOpenAIQuicksilverBrowserSessionBroker(
{
getConfig: () => api.runtime.config.current() as OpenClawConfig,
logger: api.logger,
},
context,
)
: undefined;
if (quicksilverSession) {
api.registerHttpRoute({
path: OPENAI_QUICKSILVER_OFFER_PATH,
auth: "plugin",
match: "exact",
handler: quicksilverSession.handler,
});
api.lifecycle.registerRuntimeLifecycle({
id: "openai-quicksilver-realtime-browser-session",
description: "Close OpenAI browser sidebands when the plugin stops",
cleanup: (ctx) => {
if (ctx.reason !== "disable") {
return undefined;
}
return releaseOpenAIQuicksilverBrowserSessionBroker(quicksilverSession);
},
});
}
return buildOpenAIRealtimeVoiceProvider(context, {
quicksilverBrowserSessionBroker: quicksilverSession?.broker,
logger: api.logger,
});
});
api.registerSpeechProvider(buildOpenAISpeechProvider());
api.registerMediaUnderstandingProvider(openaiMediaUnderstandingProvider);
},
});