Skip to content

Commit ced2b16

Browse files
committed
pass in logger to credit delegation
1 parent 6a4e738 commit ced2b16

File tree

5 files changed

+73
-50
lines changed

5 files changed

+73
-50
lines changed

backend/src/api/org.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,11 @@ async function isRepoCoveredHandler(
4242
}
4343

4444
// Check if repository is covered by an organization
45-
const orgLookup = await findOrganizationForRepository(userId, remoteUrl)
45+
const orgLookup = await findOrganizationForRepository({
46+
userId,
47+
repositoryUrl: remoteUrl,
48+
logger,
49+
})
4650

4751
return res.status(200).json({
4852
isCovered: orgLookup.found,

backend/src/tools/handlers/tool/web-search.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ export const handleWebSearch = ((params: {
7676
creditsToCharge,
7777
repoUrl,
7878
context: 'web search',
79+
logger,
7980
})
8081

8182
if (!creditResult.success) {

backend/src/websockets/middleware.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,11 @@ protec.use(async (action, clientSessionId, ws, userInfo) => {
181181
const { owner, repo } = ownerRepo
182182

183183
// Perform lookup (cache removed)
184-
const orgLookup = await findOrganizationForRepository(userId, repoUrl)
184+
const orgLookup = await findOrganizationForRepository({
185+
userId,
186+
repositoryUrl: repoUrl,
187+
logger,
188+
})
185189

186190
// If an organization covers this repository, check its balance
187191
if (orgLookup.found && orgLookup.organizationId) {

packages/billing/src/__tests__/credit-delegation.test.ts

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ import {
1010
} from '../credit-delegation'
1111

1212
describe('Credit Delegation', () => {
13+
const logger = {
14+
debug: () => {},
15+
info: () => {},
16+
warn: () => {},
17+
error: () => {},
18+
}
19+
1320
beforeAll(() => {
1421
// Mock the org-billing functions that credit-delegation depends on
1522
mockModule('@codebuff/billing/org-billing', () => ({
@@ -47,14 +54,6 @@ describe('Credit Delegation', () => {
4754
is_active: 'is_active',
4855
},
4956
}))
50-
51-
mockModule('@codebuff/common/util/logger', () => ({
52-
logger: {
53-
debug: mock(() => {}),
54-
info: mock(() => {}),
55-
error: mock(() => {}),
56-
},
57-
}))
5857
})
5958

6059
afterAll(() => {
@@ -66,7 +65,11 @@ describe('Credit Delegation', () => {
6665
const userId = 'user-123'
6766
const repositoryUrl = 'https://github.com/codebuffai/codebuff'
6867

69-
const result = await findOrganizationForRepository(userId, repositoryUrl)
68+
const result = await findOrganizationForRepository({
69+
userId,
70+
repositoryUrl,
71+
logger,
72+
})
7073

7174
expect(result.found).toBe(true)
7275
expect(result.organizationId).toBe('org-123')
@@ -77,7 +80,11 @@ describe('Credit Delegation', () => {
7780
const userId = 'user-123'
7881
const repositoryUrl = 'https://github.com/other/repo'
7982

80-
const result = await findOrganizationForRepository(userId, repositoryUrl)
83+
const result = await findOrganizationForRepository({
84+
userId,
85+
repositoryUrl,
86+
logger,
87+
})
8188

8289
expect(result.found).toBe(false)
8390
})
@@ -89,11 +96,12 @@ describe('Credit Delegation', () => {
8996
const repositoryUrl = null
9097
const creditsToConsume = 100
9198

92-
const result = await consumeCreditsWithDelegation(
99+
const result = await consumeCreditsWithDelegation({
93100
userId,
94101
repositoryUrl,
95102
creditsToConsume,
96-
)
103+
logger,
104+
})
97105

98106
expect(result.success).toBe(false)
99107
expect(result.error).toBe('No repository URL provided')

packages/billing/src/credit-delegation.ts

Lines changed: 42 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import db from '@codebuff/common/db'
22
import * as schema from '@codebuff/common/db/schema'
3-
import { logger } from '@codebuff/common/util/logger'
43
import { eq, and } from 'drizzle-orm'
54

65
import { consumeCredits } from './balance-calculator'
@@ -10,6 +9,8 @@ import {
109
extractOwnerAndRepo,
1110
} from './org-billing'
1211

12+
import type { Logger } from '@codebuff/types/logger'
13+
1314
export interface OrganizationLookupResult {
1415
found: boolean
1516
organizationId?: string
@@ -29,10 +30,13 @@ export interface CreditDelegationResult {
2930
* Finds the organization associated with a repository for a given user.
3031
* Uses owner/repo comparison for better matching.
3132
*/
32-
export async function findOrganizationForRepository(
33-
userId: string,
34-
repositoryUrl: string,
35-
): Promise<OrganizationLookupResult> {
33+
export async function findOrganizationForRepository(params: {
34+
userId: string
35+
repositoryUrl: string
36+
logger: Logger
37+
}): Promise<OrganizationLookupResult> {
38+
const { userId, repositoryUrl, logger } = params
39+
3640
try {
3741
const normalizedUrl = normalizeRepositoryUrl(repositoryUrl)
3842
const ownerRepo = extractOwnerAndRepo(normalizedUrl)
@@ -135,23 +139,28 @@ export async function findOrganizationForRepository(
135139
/**
136140
* Consumes credits with organization delegation if applicable.
137141
*/
138-
export async function consumeCreditsWithDelegation(
139-
userId: string,
140-
repositoryUrl: string | null,
141-
creditsToConsume: number,
142-
): Promise<CreditDelegationResult> {
143-
try {
144-
// If no repository URL, fall back to personal credits
145-
if (!repositoryUrl) {
146-
logger.debug(
147-
{ userId, creditsToConsume },
148-
'No repository URL provided, falling back to personal credits',
149-
)
150-
return { success: false, error: 'No repository URL provided' }
151-
}
142+
export async function consumeCreditsWithDelegation(params: {
143+
userId: string
144+
repositoryUrl: string | null
145+
creditsToConsume: number
146+
logger: Logger
147+
}): Promise<CreditDelegationResult> {
148+
const { userId, repositoryUrl, creditsToConsume, logger } = params
152149

150+
// If no repository URL, fall back to personal credits
151+
if (!repositoryUrl) {
152+
logger.debug(
153+
{ userId, creditsToConsume },
154+
'No repository URL provided, falling back to personal credits',
155+
)
156+
return { success: false, error: 'No repository URL provided' }
157+
}
158+
159+
const withRepoUrl = { ...params, repositoryUrl }
160+
161+
try {
153162
// Find organization for this repository
154-
const orgLookup = await findOrganizationForRepository(userId, repositoryUrl)
163+
const orgLookup = await findOrganizationForRepository(withRepoUrl)
155164

156165
if (!orgLookup.found || !orgLookup.organizationId) {
157166
logger.debug(
@@ -216,13 +225,6 @@ export async function consumeCreditsWithDelegation(
216225
}
217226
}
218227

219-
export interface CreditConsumptionOptions {
220-
userId: string
221-
creditsToCharge: number
222-
repoUrl?: string | null
223-
context: string // Description of what the credits are for (e.g., 'web search', 'documentation lookup')
224-
}
225-
226228
export interface CreditFallbackResult {
227229
success: boolean
228230
organizationId?: string
@@ -235,19 +237,23 @@ export interface CreditFallbackResult {
235237
* Helper function that decides whether to charge credits to an organization or user directly.
236238
* Tries organization delegation first if a repo URL is available, falls back to personal credits.
237239
*/
238-
export async function consumeCreditsWithFallback(
239-
options: CreditConsumptionOptions,
240-
): Promise<CreditFallbackResult> {
241-
const { userId, creditsToCharge, repoUrl, context } = options
240+
export async function consumeCreditsWithFallback(params: {
241+
userId: string
242+
creditsToCharge: number
243+
repoUrl?: string | null
244+
context: string // Description of what the credits are for (e.g., 'web search', 'documentation lookup')
245+
logger: Logger
246+
}): Promise<CreditFallbackResult> {
247+
const { userId, creditsToCharge, repoUrl, context, logger } = params
242248

243249
try {
244250
// Try organization delegation first if repo URL is available
245251
if (repoUrl) {
246-
const delegationResult = await consumeCreditsWithDelegation(
247-
userId,
248-
repoUrl,
249-
creditsToCharge,
250-
)
252+
const delegationResult = await consumeCreditsWithDelegation({
253+
...params,
254+
repositoryUrl: repoUrl,
255+
creditsToConsume: creditsToCharge,
256+
})
251257

252258
if (delegationResult.success) {
253259
logger.debug(

0 commit comments

Comments
 (0)