Skip to content

Commit cfbf6b7

Browse files
committed
switch relace to use openrouter
1 parent 256e22b commit cfbf6b7

File tree

2 files changed

+87
-76
lines changed

2 files changed

+87
-76
lines changed

backend/src/llm-apis/relace-api.ts

Lines changed: 15 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import { models } from '@codebuff/common/old-constants'
2-
import {
3-
createMarkdownFileBlock,
4-
parseMarkdownCodeBlock,
5-
} from '@codebuff/common/util/file'
2+
import { buildArray } from '@codebuff/common/util/array'
3+
import { parseMarkdownCodeBlock } from '@codebuff/common/util/file'
64
import { env } from '@codebuff/internal'
75

86
import { saveMessage } from '../llm-apis/message-cost-tracker'
@@ -22,82 +20,31 @@ export async function promptRelaceAI(
2220
initialCode: string
2321
editSnippet: string
2422
instructions: string | undefined
25-
messageId: string
26-
userMessage?: string
2723
promptAiSdk: PromptAiSdkFn
2824
logger: Logger
29-
} & ParamsExcluding<
30-
typeof saveMessage,
31-
| 'model'
32-
| 'request'
33-
| 'response'
34-
| 'inputTokens'
35-
| 'outputTokens'
36-
| 'finishedAt'
37-
| 'latencyMs'
38-
> &
39-
ParamsExcluding<PromptAiSdkFn, 'messages' | 'model'>,
25+
} & ParamsExcluding<PromptAiSdkFn, 'messages' | 'model'>,
4026
) {
41-
const {
42-
initialCode,
43-
editSnippet,
44-
instructions,
45-
userMessage,
46-
messageId,
47-
promptAiSdk,
48-
logger,
49-
} = params
50-
const startTime = Date.now()
27+
const { initialCode, editSnippet, instructions, promptAiSdk, logger } = params
5128

5229
try {
5330
// const model = 'relace-apply-2.5-lite'
54-
const response = (await Promise.race([
55-
fetch('https://instantapply.endpoint.relace.run/v1/code/apply', {
56-
method: 'POST',
57-
headers: {
58-
'Content-Type': 'application/json',
59-
Authorization: `Bearer ${env.RELACE_API_KEY}`,
60-
},
61-
body: JSON.stringify({
62-
// model,
63-
initialCode,
64-
editSnippet,
65-
...(instructions ? { instructions } : {}),
66-
stream: false,
67-
'relace-metadata': {
68-
'codebuff-id': messageId,
69-
'codebuff-user-prompt': userMessage,
70-
},
71-
}),
72-
}),
73-
timeoutPromise(100_000),
74-
])) as Response
75-
76-
if (!response.ok) {
77-
throw new Error(
78-
`Relace API error: ${response.status} ${response.statusText}`,
79-
)
80-
}
81-
82-
const data = (await response.json()) as { mergedCode: string }
83-
const content = data.mergedCode
84-
85-
const fakeRequestContent = `Initial code:${createMarkdownFileBlock('', initialCode)}\n\nEdit snippet${createMarkdownFileBlock('', editSnippet)}`
86-
saveMessage({
31+
const content = await promptAiSdk({
8732
...params,
88-
model: 'relace-fast-apply',
89-
request: [
33+
model: 'relace/relace-apply-3',
34+
messages: [
9035
{
9136
role: 'user',
92-
content: fakeRequestContent,
37+
content: buildArray(
38+
instructions && `<instruction>${instructions}</instruction>`,
39+
`<code>${initialCode}</code>`,
40+
`<update>${editSnippet}</update>`,
41+
).join('\n'),
9342
},
9443
],
95-
response: content,
96-
inputTokens: countTokens(initialCode + editSnippet),
97-
outputTokens: countTokens(content),
98-
finishedAt: new Date(),
99-
latencyMs: Date.now() - startTime,
44+
system: undefined,
45+
includeCacheControl: false,
10046
})
47+
10148
return content + '\n'
10249
} catch (error) {
10350
logger.error(

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

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import { getErrorObject } from '@codebuff/common/util/error'
88
import { convertCbToModelMessages } from '@codebuff/common/util/messages'
99
import { withTimeout } from '@codebuff/common/util/promise'
1010
import { StopSequenceHandler } from '@codebuff/common/util/stop-sequence'
11-
import { generateCompactId } from '@codebuff/common/util/string'
1211
import { APICallError, generateObject, generateText, streamText } from 'ai'
1312

1413
import { checkLiveUserInput, getLiveUserInputIds } from '../../live-user-inputs'
@@ -252,19 +251,52 @@ export async function promptAiSdk(
252251
messages: convertCbToModelMessages(params),
253252
})
254253
const content = response.text
255-
const inputTokens = response.usage.inputTokens || 0
256-
const outputTokens = response.usage.inputTokens || 0
254+
255+
const messageId = response.response.id
256+
const providerMetadata = response.providerMetadata ?? {}
257+
const usage = response.usage
258+
let inputTokens = usage.inputTokens || 0
259+
const outputTokens = usage.outputTokens || 0
260+
let cacheReadInputTokens: number = 0
261+
let cacheCreationInputTokens: number = 0
262+
let costOverrideDollars: number | undefined
263+
if (providerMetadata.anthropic) {
264+
cacheReadInputTokens =
265+
typeof providerMetadata.anthropic.cacheReadInputTokens === 'number'
266+
? providerMetadata.anthropic.cacheReadInputTokens
267+
: 0
268+
cacheCreationInputTokens =
269+
typeof providerMetadata.anthropic.cacheCreationInputTokens === 'number'
270+
? providerMetadata.anthropic.cacheCreationInputTokens
271+
: 0
272+
}
273+
if (providerMetadata.openrouter) {
274+
if (providerMetadata.openrouter.usage) {
275+
const openrouterUsage = providerMetadata.openrouter
276+
.usage as OpenRouterUsageAccounting
277+
cacheReadInputTokens =
278+
openrouterUsage.promptTokensDetails?.cachedTokens ?? 0
279+
inputTokens = openrouterUsage.promptTokens - cacheReadInputTokens
280+
281+
costOverrideDollars =
282+
(openrouterUsage.cost ?? 0) +
283+
(openrouterUsage.costDetails?.upstreamInferenceCost ?? 0)
284+
}
285+
}
257286

258287
const creditsUsedPromise = saveMessage({
259288
...params,
260-
messageId: generateCompactId(),
289+
messageId,
261290
request: params.messages,
262291
response: content,
263292
inputTokens,
264293
outputTokens,
294+
cacheCreationInputTokens,
295+
cacheReadInputTokens,
265296
finishedAt: new Date(),
266297
latencyMs: Date.now() - startTime,
267298
chargeUser: params.chargeUser ?? true,
299+
costOverrideDollars,
268300
})
269301

270302
// Call the cost callback if provided
@@ -308,20 +340,52 @@ export async function promptAiSdkStructured<T>(
308340
? responsePromise
309341
: withTimeout(responsePromise, params.timeout))
310342
const content = response.object
311-
const inputTokens = response.usage.inputTokens || 0
312-
const outputTokens = response.usage.inputTokens || 0
343+
344+
const messageId = response.response.id
345+
const providerMetadata = response.providerMetadata ?? {}
346+
const usage = response.usage
347+
let inputTokens = usage.inputTokens || 0
348+
const outputTokens = usage.outputTokens || 0
349+
let cacheReadInputTokens: number = 0
350+
let cacheCreationInputTokens: number = 0
351+
let costOverrideDollars: number | undefined
352+
if (providerMetadata.anthropic) {
353+
cacheReadInputTokens =
354+
typeof providerMetadata.anthropic.cacheReadInputTokens === 'number'
355+
? providerMetadata.anthropic.cacheReadInputTokens
356+
: 0
357+
cacheCreationInputTokens =
358+
typeof providerMetadata.anthropic.cacheCreationInputTokens === 'number'
359+
? providerMetadata.anthropic.cacheCreationInputTokens
360+
: 0
361+
}
362+
if (providerMetadata.openrouter) {
363+
if (providerMetadata.openrouter.usage) {
364+
const openrouterUsage = providerMetadata.openrouter
365+
.usage as OpenRouterUsageAccounting
366+
cacheReadInputTokens =
367+
openrouterUsage.promptTokensDetails?.cachedTokens ?? 0
368+
inputTokens = openrouterUsage.promptTokens - cacheReadInputTokens
369+
370+
costOverrideDollars =
371+
(openrouterUsage.cost ?? 0) +
372+
(openrouterUsage.costDetails?.upstreamInferenceCost ?? 0)
373+
}
374+
}
313375

314376
const creditsUsedPromise = saveMessage({
315377
...params,
316-
messageId: generateCompactId(),
378+
messageId,
317379
request: params.messages,
318380
response: JSON.stringify(content),
319381
inputTokens,
320382
outputTokens,
383+
cacheCreationInputTokens,
384+
cacheReadInputTokens,
321385
finishedAt: new Date(),
322386
latencyMs: Date.now() - startTime,
323387
chargeUser: params.chargeUser ?? true,
324-
logger,
388+
costOverrideDollars,
325389
})
326390

327391
// Call the cost callback if provided

0 commit comments

Comments
 (0)