Skip to content

Commit a85273b

Browse files
committed
only cache control on last content block
1 parent 184e904 commit a85273b

File tree

1 file changed

+54
-34
lines changed

1 file changed

+54
-34
lines changed

common/src/util/messages.ts

Lines changed: 54 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -10,62 +10,67 @@ import type {
1010
UserCodebuffMessage,
1111
} from '../types/messages/codebuff-message'
1212
import type { ModelMessage } from 'ai'
13+
import type { ProviderMetadata } from 'src/types/messages/provider-metadata'
1314

1415
export function toContentString(msg: ModelMessage): string {
1516
const { content } = msg
1617
if (typeof content === 'string') return content
1718
return content.map((item) => (item as any)?.text ?? '').join('\n')
1819
}
1920

20-
export function withCacheControl<T extends CodebuffMessage>(msg: T): T {
21-
const message = deepCopy(msg)
22-
if (!message.providerOptions) {
23-
message.providerOptions = {}
21+
export function withCacheControl<
22+
T extends { providerOptions?: ProviderMetadata },
23+
>(obj: T): T {
24+
const wrapper = deepCopy(obj)
25+
if (!wrapper.providerOptions) {
26+
wrapper.providerOptions = {}
2427
}
25-
if (!message.providerOptions.anthropic) {
26-
message.providerOptions.anthropic = {}
28+
if (!wrapper.providerOptions.anthropic) {
29+
wrapper.providerOptions.anthropic = {}
2730
}
28-
message.providerOptions.anthropic.cacheControl = { type: 'ephemeral' }
29-
if (!message.providerOptions.openrouter) {
30-
message.providerOptions.openrouter = {}
31+
wrapper.providerOptions.anthropic.cacheControl = { type: 'ephemeral' }
32+
if (!wrapper.providerOptions.openrouter) {
33+
wrapper.providerOptions.openrouter = {}
3134
}
32-
message.providerOptions.openrouter.cacheControl = { type: 'ephemeral' }
33-
return message
35+
wrapper.providerOptions.openrouter.cacheControl = { type: 'ephemeral' }
36+
return wrapper
3437
}
3538

36-
export function withoutCacheControl<T extends CodebuffMessage>(msg: T): T {
37-
const message = deepCopy(msg)
38-
if (hasKey(message.providerOptions?.anthropic?.cacheControl, 'type')) {
39-
delete message.providerOptions?.anthropic?.cacheControl?.type
39+
export function withoutCacheControl<
40+
T extends { providerOptions?: ProviderMetadata },
41+
>(obj: T): T {
42+
const wrapper = deepCopy(obj)
43+
if (hasKey(wrapper.providerOptions?.anthropic?.cacheControl, 'type')) {
44+
delete wrapper.providerOptions?.anthropic?.cacheControl?.type
4045
}
4146
if (
42-
Object.keys(message.providerOptions?.anthropic?.cacheControl ?? {})
47+
Object.keys(wrapper.providerOptions?.anthropic?.cacheControl ?? {})
4348
.length === 0
4449
) {
45-
delete message.providerOptions?.anthropic?.cacheControl
50+
delete wrapper.providerOptions?.anthropic?.cacheControl
4651
}
47-
if (Object.keys(message.providerOptions?.anthropic ?? {}).length === 0) {
48-
delete message.providerOptions?.anthropic
52+
if (Object.keys(wrapper.providerOptions?.anthropic ?? {}).length === 0) {
53+
delete wrapper.providerOptions?.anthropic
4954
}
5055

51-
if (hasKey(message.providerOptions?.openrouter?.cacheControl, 'type')) {
52-
delete message.providerOptions?.openrouter?.cacheControl?.type
56+
if (hasKey(wrapper.providerOptions?.openrouter?.cacheControl, 'type')) {
57+
delete wrapper.providerOptions?.openrouter?.cacheControl?.type
5358
}
5459
if (
55-
Object.keys(message.providerOptions?.openrouter?.cacheControl ?? {})
60+
Object.keys(wrapper.providerOptions?.openrouter?.cacheControl ?? {})
5661
.length === 0
5762
) {
58-
delete message.providerOptions?.openrouter?.cacheControl
63+
delete wrapper.providerOptions?.openrouter?.cacheControl
5964
}
60-
if (Object.keys(message.providerOptions?.openrouter ?? {}).length === 0) {
61-
delete message.providerOptions?.openrouter
65+
if (Object.keys(wrapper.providerOptions?.openrouter ?? {}).length === 0) {
66+
delete wrapper.providerOptions?.openrouter
6267
}
6368

64-
if (Object.keys(message.providerOptions ?? {}).length === 0) {
65-
delete message.providerOptions
69+
if (Object.keys(wrapper.providerOptions ?? {}).length === 0) {
70+
delete wrapper.providerOptions
6671
}
6772

68-
return message
73+
return wrapper
6974
}
7075

7176
type Nested<P> = Parameters<typeof buildArray<P>>[0]
@@ -204,9 +209,7 @@ export function convertCbToModelMessages({
204209
messages: CodebuffMessage[]
205210
includeCacheControl?: boolean
206211
}): ModelMessage[] {
207-
const noToolMessages = buildArray(
208-
messages.map((m) => convertToolMessages(withoutCacheControl(m))),
209-
)
212+
const noToolMessages = buildArray(messages.map((m) => convertToolMessages(m)))
210213

211214
const aggregated: typeof noToolMessages = []
212215
for (const message of noToolMessages) {
@@ -250,10 +253,27 @@ export function convertCbToModelMessages({
250253
if (index <= 0) {
251254
continue
252255
}
253-
aggregated[index - 1] = withCacheControl(aggregated[index - 1])
256+
const prevMessage = aggregated[index - 1]
257+
const contentBlock = prevMessage.content
258+
if (typeof contentBlock === 'string') {
259+
aggregated[index - 1] = withCacheControl(aggregated[index - 1])
260+
continue
261+
}
262+
contentBlock[contentBlock.length - 1] = withCacheControl(
263+
contentBlock[contentBlock.length - 1],
264+
)
265+
}
266+
267+
const lastMessage = aggregated[aggregated.length - 1]
268+
const contentBlock = lastMessage.content
269+
if (typeof contentBlock === 'string') {
270+
aggregated[aggregated.length - 1] = withCacheControl(
271+
aggregated[aggregated.length - 1],
272+
)
273+
return aggregated
254274
}
255-
aggregated[aggregated.length - 1] = withCacheControl(
256-
aggregated[aggregated.length - 1],
275+
contentBlock[contentBlock.length - 1] = withCacheControl(
276+
contentBlock[contentBlock.length - 1],
257277
)
258278

259279
return aggregated

0 commit comments

Comments
 (0)