Skip to content

Commit 726b1cc

Browse files
committed
sdk: implement promptAiSdkStream
1 parent 1f2f144 commit 726b1cc

File tree

11 files changed

+289
-71
lines changed

11 files changed

+289
-71
lines changed

backend/src/llm-apis/vercel-ai-sdk/ai-sdk.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -140,14 +140,16 @@ export async function* promptAiSdkStream(
140140
return null
141141
}
142142
if (chunk.type === 'reasoning-delta') {
143-
if (
144-
(
145-
params.providerOptions?.openrouter as
146-
| OpenRouterProviderOptions
147-
| undefined
148-
)?.reasoning?.exclude
149-
) {
150-
continue
143+
for (const provider of ['openrouter', 'codebuff'] as const) {
144+
if (
145+
(
146+
params.providerOptions?.[provider] as
147+
| OpenRouterProviderOptions
148+
| undefined
149+
)?.reasoning?.exclude
150+
) {
151+
continue
152+
}
151153
}
152154
yield {
153155
type: 'reasoning',

common/src/types/contracts/database.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ type AgentRun = {
2828
}
2929
export type AgentRunColumn = keyof AgentRun
3030
export type GetAgentRunFromIdInput<T extends AgentRunColumn> = {
31-
agentRunId: string
31+
runId: string
3232
userId: string
3333
fields: readonly T[]
3434
}

common/src/types/contracts/llm.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export type StreamChunk =
2222

2323
export type PromptAiSdkStreamFn = (
2424
params: {
25+
apiKey: string
2526
messages: Message[]
2627
clientSessionId: string
2728
fingerprintId: string

common/src/util/messages.ts

Lines changed: 20 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -26,45 +26,35 @@ export function withCacheControl<
2626
if (!wrapper.providerOptions) {
2727
wrapper.providerOptions = {}
2828
}
29-
if (!wrapper.providerOptions.anthropic) {
30-
wrapper.providerOptions.anthropic = {}
31-
}
32-
wrapper.providerOptions.anthropic.cacheControl = { type: 'ephemeral' }
33-
if (!wrapper.providerOptions.openrouter) {
34-
wrapper.providerOptions.openrouter = {}
29+
30+
for (const provider of ['anthropic', 'openrouter', 'codebuff'] as const) {
31+
if (!wrapper.providerOptions[provider]) {
32+
wrapper.providerOptions[provider] = {}
33+
}
34+
wrapper.providerOptions[provider].cacheControl = { type: 'ephemeral' }
3535
}
36-
wrapper.providerOptions.openrouter.cacheControl = { type: 'ephemeral' }
36+
3737
return wrapper
3838
}
3939

4040
export function withoutCacheControl<
4141
T extends { providerOptions?: ProviderMetadata },
4242
>(obj: T): T {
4343
const wrapper = cloneDeep(obj)
44-
if (has(wrapper.providerOptions?.anthropic?.cacheControl, 'type')) {
45-
delete wrapper.providerOptions?.anthropic?.cacheControl?.type
46-
}
47-
if (
48-
Object.keys(wrapper.providerOptions?.anthropic?.cacheControl ?? {})
49-
.length === 0
50-
) {
51-
delete wrapper.providerOptions?.anthropic?.cacheControl
52-
}
53-
if (Object.keys(wrapper.providerOptions?.anthropic ?? {}).length === 0) {
54-
delete wrapper.providerOptions?.anthropic
55-
}
5644

57-
if (has(wrapper.providerOptions?.openrouter?.cacheControl, 'type')) {
58-
delete wrapper.providerOptions?.openrouter?.cacheControl?.type
59-
}
60-
if (
61-
Object.keys(wrapper.providerOptions?.openrouter?.cacheControl ?? {})
62-
.length === 0
63-
) {
64-
delete wrapper.providerOptions?.openrouter?.cacheControl
65-
}
66-
if (Object.keys(wrapper.providerOptions?.openrouter ?? {}).length === 0) {
67-
delete wrapper.providerOptions?.openrouter
45+
for (const provider of ['anthropic', 'openrouter', 'codebuff'] as const) {
46+
if (has(wrapper.providerOptions?.[provider]?.cacheControl, 'type')) {
47+
delete wrapper.providerOptions?.[provider]?.cacheControl?.type
48+
}
49+
if (
50+
Object.keys(wrapper.providerOptions?.[provider]?.cacheControl ?? {})
51+
.length === 0
52+
) {
53+
delete wrapper.providerOptions?.[provider]?.cacheControl
54+
}
55+
if (Object.keys(wrapper.providerOptions?.[provider] ?? {}).length === 0) {
56+
delete wrapper.providerOptions?.[provider]
57+
}
6858
}
6959

7060
if (Object.keys(wrapper.providerOptions ?? {}).length === 0) {

packages/agent-runtime/src/prompt-agent-stream.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import { providerModelNames } from '@codebuff/common/old-constants'
2-
31
import { globalStopSequence } from './constants'
42

53
import type { AgentTemplate } from './templates/types'
@@ -16,6 +14,7 @@ import type { Message } from '@codebuff/common/types/messages/codebuff-message'
1614
import type { OpenRouterProviderOptions } from '@codebuff/internal/openrouter-ai-sdk'
1715

1816
export const getAgentStreamFromTemplate = (params: {
17+
apiKey: string
1918
clientSessionId: string
2019
fingerprintId: string
2120
userInputId: string
@@ -33,6 +32,7 @@ export const getAgentStreamFromTemplate = (params: {
3332
trackEvent: TrackEventFn
3433
}) => {
3534
const {
35+
apiKey,
3636
clientSessionId,
3737
fingerprintId,
3838
userInputId,
@@ -57,6 +57,7 @@ export const getAgentStreamFromTemplate = (params: {
5757

5858
const getStream = (messages: Message[]) => {
5959
const aiSdkStreamParams: ParamsOf<PromptAiSdkStreamFn> = {
60+
apiKey,
6061
messages,
6162
model,
6263
stopSequences: [globalStopSequence],
@@ -78,18 +79,18 @@ export const getAgentStreamFromTemplate = (params: {
7879

7980
// Add Gemini-specific options if needed
8081
const primaryModel = Array.isArray(model) ? model[0] : model
81-
const provider =
82-
providerModelNames[primaryModel as keyof typeof providerModelNames]
8382

8483
if (!aiSdkStreamParams.providerOptions) {
8584
aiSdkStreamParams.providerOptions = {}
8685
}
87-
if (!aiSdkStreamParams.providerOptions.openrouter) {
88-
aiSdkStreamParams.providerOptions.openrouter = {}
86+
for (const provider of ['openrouter', 'codebuff'] as const) {
87+
if (!aiSdkStreamParams.providerOptions[provider]) {
88+
aiSdkStreamParams.providerOptions[provider] = {}
89+
}
90+
;(
91+
aiSdkStreamParams.providerOptions[provider] as OpenRouterProviderOptions
92+
).reasoning = template.reasoningOptions
8993
}
90-
;(
91-
aiSdkStreamParams.providerOptions.openrouter as OpenRouterProviderOptions
92-
).reasoning = template.reasoningOptions
9394

9495
return promptAiSdkStream(aiSdkStreamParams)
9596
}

packages/agent-runtime/src/util/messages.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,8 +261,9 @@ export function getMessagesSubset(params: {
261261

262262
// Remove cache_control from all messages
263263
for (const message of messagesSubset) {
264-
delete message.providerOptions?.anthropic?.cacheControl
265-
delete message.providerOptions?.openrouter?.cacheControl
264+
for (const provider of ['anthropic', 'openrouter', 'codebuff'] as const) {
265+
delete message.providerOptions?.[provider]?.cacheControl
266+
}
266267
}
267268

268269
// Cache up to the last message!

sdk/src/impl/agent-runtime.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
getUserInfoFromApiKey,
99
startAgentRun,
1010
} from './database'
11+
import { promptAiSdkStream } from './llm'
1112

1213
import type {
1314
AgentRuntimeDeps,
@@ -20,7 +21,6 @@ export function getAgentRuntimeImpl(params: {
2021
apiKey: string
2122
}): Omit<
2223
AgentRuntimeDeps & AgentRuntimeScopedDeps,
23-
| 'promptAiSdkStream'
2424
| 'promptAiSdk'
2525
| 'promptAiSdkStructured'
2626
| 'handleStepsLogChunk'
@@ -48,7 +48,7 @@ export function getAgentRuntimeImpl(params: {
4848
}),
4949

5050
// LLM
51-
// promptAiSdkStream: PromptAiSdkStreamFn,
51+
promptAiSdkStream,
5252
// promptAiSdk: PromptAiSdkFn,
5353
// promptAiSdkStructured: PromptAiSdkStructuredFn,
5454

0 commit comments

Comments
 (0)