Skip to content

Commit d3cfa1d

Browse files
committed
fix(knowledge): keep keyless Ollama and mixed fallback quota attribution accurate
1 parent 4f0635d commit d3cfa1d

2 files changed

Lines changed: 26 additions & 6 deletions

File tree

‎apps/sim/lib/embeddings/client.ts‎

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,8 @@ export class EmbeddingQuotaExhaustedError extends EmbeddingAPIError {
215215
/**
216216
* `isBYOK` must be passed when there is no provider response to read it from — an
217217
* already-open quota pause or an admission refusal — so a workspace key's exhaustion
218-
* is never reported as the platform's.
218+
* is never reported as the platform's. Ollama takes no credential: its provider-level
219+
* `isBYOK` only marks its tokens non-billable, so it never attributes to a customer key.
219220
*/
220221
constructor(
221222
providerId: EmbeddingProviderKind,
@@ -226,7 +227,7 @@ export class EmbeddingQuotaExhaustedError extends EmbeddingAPIError {
226227
super(
227228
`The ${providerId} embedding credential has exhausted its available quota. Add credit or replace the credential before retrying.`,
228229
status,
229-
isBYOK
230+
isBYOK && providerId !== 'ollama'
230231
)
231232
this.name = 'EmbeddingQuotaExhaustedError'
232233
this.providerId = providerId
@@ -249,8 +250,15 @@ export function isEmbeddingQuotaExhaustion(error: unknown): boolean {
249250
return false
250251
}
251252

252-
/** True when a customer-managed embedding credential has no remaining credit. */
253-
export function isBYOKEmbeddingQuotaExhaustion(error: unknown): error is EmbeddingAPIError {
253+
/**
254+
* True when the operation failed on quota and a customer-managed credential is among
255+
* the exhausted ones: adding credit to that key is what lets it run again, even when a
256+
* platform fallback behind it is exhausted too.
257+
*/
258+
export function isBYOKEmbeddingQuotaExhaustion(error: unknown): boolean {
259+
if (error instanceof AggregateError) {
260+
return isEmbeddingQuotaExhaustion(error) && error.errors.some(isBYOKEmbeddingQuotaExhaustion)
261+
}
254262
return error instanceof EmbeddingAPIError && error.isBYOK && error.quotaExhausted === true
255263
}
256264

‎apps/sim/lib/knowledge/api/route-policies.test.ts‎

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ import {
1515
} from '@/lib/knowledge/api/route-policies'
1616
import { SearchDeadlineError } from '@/lib/knowledge/search/budget'
1717

18-
function quotaError(isBYOK: boolean) {
19-
return new EmbeddingQuotaExhaustedError('openai', undefined, isBYOK)
18+
function quotaError(isBYOK: boolean, providerId: 'openai' | 'ollama' = 'openai') {
19+
return new EmbeddingQuotaExhaustedError(providerId, undefined, isBYOK)
2020
}
2121

2222
describe('internal knowledge search error policy', () => {
@@ -29,6 +29,18 @@ describe('internal knowledge search error policy', () => {
2929
503,
3030
/^Knowledge search is temporarily/,
3131
],
32+
[
33+
'a workspace key out of quota ahead of an exhausted platform fallback',
34+
new AggregateError([quotaError(true), quotaError(false)]),
35+
503,
36+
/this workspace's embedding API key/,
37+
],
38+
[
39+
'a keyless Ollama server out of quota',
40+
quotaError(true, 'ollama'),
41+
503,
42+
/^Knowledge search is temporarily/,
43+
],
3244
[
3345
'a rejected workspace key',
3446
new EmbeddingAPIError('Embedding API failed: 401', 401, true),

0 commit comments

Comments
 (0)