diff --git a/src/agents/provider-attribution.ts b/src/agents/provider-attribution.ts index 228be76fa15..6763181b07a 100644 --- a/src/agents/provider-attribution.ts +++ b/src/agents/provider-attribution.ts @@ -573,6 +573,23 @@ export function resolveProviderRequestCapabilities( compatibilityFamily = "moonshot"; } + const isResponsesApi = api !== undefined && OPENAI_RESPONSES_APIS.has(api); + const promptCacheKeySupport = input.compat?.supportsPromptCacheKey; + // Default strip behavior (proxy-like endpoints with responses APIs) is + // preserved as a safety net for providers that reject prompt_cache_key, + // see #48155 (Volcano Engine DeepSeek). Operators running their payload + // through an OpenAI-compatible proxy known to forward the field + // (CLIProxy, LiteLLM, etc.) can opt out via compat.supportsPromptCacheKey + // to recover prompt caching; providers known to reject the field can + // force the strip with compat.supportsPromptCacheKey = false even on + // native endpoints. + const shouldStripResponsesPromptCache = + promptCacheKeySupport === true + ? false + : promptCacheKeySupport === false + ? isResponsesApi + : isResponsesApi && policy.usesExplicitProxyLikeEndpoint; + return { ...policy, isKnownNativeEndpoint, @@ -599,29 +616,14 @@ export function resolveProviderRequestCapabilities( (endpointClass === "default" || endpointClass === "anthropic-public"), // This is intentionally the gate for emitting `store: false` on Responses // transports, not just a statement about vendor support in the abstract. - supportsResponsesStoreField: - input.compat?.supportsStore !== false && api !== undefined && OPENAI_RESPONSES_APIS.has(api), + supportsResponsesStoreField: input.compat?.supportsStore !== false && isResponsesApi, allowsResponsesStore: input.compat?.supportsStore !== false && provider !== undefined && - api !== undefined && - OPENAI_RESPONSES_APIS.has(api) && + isResponsesApi && OPENAI_RESPONSES_PROVIDERS.has(provider) && policy.usesKnownNativeOpenAIEndpoint, - // Default strip behavior (proxy-like endpoints with responses APIs) is - // preserved as a safety net for providers that reject prompt_cache_key — - // see #48155 (Volcano Engine DeepSeek). Operators running their payload - // through an OpenAI-compatible proxy known to forward the field - // (CLIProxy, LiteLLM, etc.) can opt out via compat.supportsPromptCacheKey - // to recover prompt caching; providers known to reject the field can - // force the strip with compat.supportsPromptCacheKey = false even on - // native endpoints. - shouldStripResponsesPromptCache: - input.compat?.supportsPromptCacheKey === true - ? false - : input.compat?.supportsPromptCacheKey === false - ? api !== undefined && OPENAI_RESPONSES_APIS.has(api) - : api !== undefined && OPENAI_RESPONSES_APIS.has(api) && policy.usesExplicitProxyLikeEndpoint, + shouldStripResponsesPromptCache, // Native endpoint class is the real signal here. Users can point a generic // provider key at Moonshot or DashScope and still need streaming usage. supportsNativeStreamingUsageCompat: diff --git a/test/scripts/bundle-a2ui.test.ts b/test/scripts/bundle-a2ui.test.ts index 8611625a317..6abfa705e8c 100644 --- a/test/scripts/bundle-a2ui.test.ts +++ b/test/scripts/bundle-a2ui.test.ts @@ -65,16 +65,16 @@ describe("scripts/bundle-a2ui.mjs", () => { const repoRoot = process.cwd(); const dependencyPaths = getResolvedBundleDependencyPackageJsonPaths(repoRoot); const relativeDependencyPaths = dependencyPaths.map((dependencyPath) => - path.relative(repoRoot, dependencyPath), + path.relative(repoRoot, dependencyPath).replaceAll(path.sep, "/"), ); expect( relativeDependencyPaths.map((relativePath) => relativePath.replace(/^ui\//u, "")), ).toEqual([ - path.join("node_modules", "lit", "package.json"), - path.join("node_modules", "@lit/context", "package.json"), - path.join("node_modules", "@lit-labs/signals", "package.json"), - path.join("node_modules", "signal-utils", "package.json"), + path.posix.join("node_modules", "lit", "package.json"), + path.posix.join("node_modules", "@lit/context", "package.json"), + path.posix.join("node_modules", "@lit-labs/signals", "package.json"), + path.posix.join("node_modules", "signal-utils", "package.json"), ]); expect( relativeDependencyPaths.every((relativePath) => /^(ui\/)?node_modules\//u.test(relativePath)),