






























@@ -10,6 +10,10 @@ import type {
1010ChatCompletionSystemMessageParam,
1111ChatCompletionToolMessageParam,
1212} from "openai/resources/chat/completions.js";
13+import {
14+splitSystemPromptCacheBoundary,
15+stripSystemPromptCacheBoundary,
16+} from "../../agents/system-prompt-cache-boundary.js";
1317import { createReasoningTagTextPartitioner } from "../../shared/text/reasoning-tag-text-partitioner.js";
1418import { getEnvApiKey } from "../env-api-keys.js";
1519import { calculateCost, clampThinkingLevel } from "../model-utils.js";
@@ -584,8 +588,10 @@ function buildParams(
584588compat: ResolvedOpenAICompletionsCompat = getCompat(model),
585589cacheRetention: CacheRetention = resolveCacheRetention(options?.cacheRetention),
586590) {
587-const messages = convertMessages(model, context, compat);
588591const cacheControl = getCompatCacheControl(compat, cacheRetention);
592+const messages = convertMessages(model, context, compat, {
593+preserveSystemPromptCacheBoundary: cacheControl !== undefined,
594+});
589595590596type ChatCompletionRequestParams = Omit<
591597OpenAI.Chat.Completions.ChatCompletionCreateParamsStreaming,
@@ -835,13 +841,7 @@ function addCacheControlToTextContent(
835841if (content.length === 0) {
836842return false;
837843}
838-message.content = [
839-{
840-type: "text",
841-text: content,
842-cache_control: cacheControl,
843-},
844-] as ChatCompletionTextPartWithCacheControl[];
844+message.content = buildCacheControlledTextParts(content, cacheControl);
845845return true;
846846}
847847@@ -852,19 +852,43 @@ function addCacheControlToTextContent(
852852for (let i = content.length - 1; i >= 0; i--) {
853853const part = content[i];
854854if (part?.type === "text") {
855-const textPart = part as ChatCompletionTextPartWithCacheControl;
856-textPart.cache_control = cacheControl;
855+const text = (part as ChatCompletionTextPartWithCacheControl).text;
856+content.splice(i, 1, ...buildCacheControlledTextParts(text, cacheControl));
857857return true;
858858}
859859}
860860861861return false;
862862}
863863864+function buildCacheControlledTextParts(
865+text: string,
866+cacheControl: OpenAICompatCacheControl,
867+): ChatCompletionTextPartWithCacheControl[] {
868+const split = splitSystemPromptCacheBoundary(text);
869+if (!split) {
870+return [{ type: "text", text, cache_control: cacheControl }];
871+}
872+873+const parts: ChatCompletionTextPartWithCacheControl[] = [];
874+if (split.stablePrefix) {
875+parts.push({
876+type: "text",
877+text: split.stablePrefix,
878+cache_control: cacheControl,
879+});
880+}
881+if (split.dynamicSuffix) {
882+parts.push({ type: "text", text: split.dynamicSuffix });
883+}
884+return parts.length > 0 ? parts : [{ type: "text", text: "" }];
885+}
886+864887export function convertMessages(
865888model: Model<"openai-completions">,
866889context: Context,
867890compat: ResolvedOpenAICompletionsCompat,
891+options: { preserveSystemPromptCacheBoundary?: boolean } = {},
868892): ChatCompletionMessageParam[] {
869893const params: ChatCompletionMessageParam[] = [];
870894@@ -892,7 +916,13 @@ export function convertMessages(
892916if (context.systemPrompt) {
893917const useDeveloperRole = model.reasoning && compat.supportsDeveloperRole;
894918const role = useDeveloperRole ? "developer" : "system";
895-params.push({ role, content: sanitizeSurrogates(context.systemPrompt) });
919+const systemPrompt = options.preserveSystemPromptCacheBoundary
920+ ? context.systemPrompt
921+ : stripSystemPromptCacheBoundary(context.systemPrompt);
922+params.push({
923+ role,
924+content: sanitizeSurrogates(systemPrompt),
925+});
896926}
897927898928let lastRole: string | null = null;
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。