Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
f6eea04
Update plan to push to branch
charleslien Oct 8, 2025
97285ef
Refactor file tree truncation functions to pass logger as parameter
charleslien Oct 8, 2025
e5b56fa
update plan
charleslien Oct 8, 2025
97a2ff3
Refactor three files to pass logger as parameter
charleslien Oct 8, 2025
bda66e7
update maxAgentSteps to 100
charleslien Oct 8, 2025
0cca3d4
Refactor relabelRuns.ts to pass logger as parameter
charleslien Oct 8, 2025
197b605
update refactor plan file
charleslien Oct 8, 2025
1dc8831
Refactor request-files-prompt.ts to pass logger as parameter
charleslien Oct 8, 2025
6daf58f
Refactor tool-executor.ts to pass logger as parameter
charleslien Oct 8, 2025
8387a3e
Refactor message-cost-tracker.ts to pass logger as parameter
charleslien Oct 8, 2025
518e3db
Refactor utility functions and middleware to pass logger as parameter
charleslien Oct 8, 2025
504c7a5
pass in logger to a few more functions
charleslien Oct 9, 2025
4951bb5
fix tests
charleslien Oct 9, 2025
50c56a9
Refactor generate-diffs-prompt.ts to pass logger as parameter
charleslien Oct 9, 2025
d45a2a5
Refactor live-user-inputs.ts to pass logger as parameter
charleslien Oct 9, 2025
97540cb
Refactor get-documentation-for-query.ts to pass logger as parameter
charleslien Oct 9, 2025
cda0711
Refactor think-deeply, create-plan, and find-files to pass logger as …
charleslien Oct 9, 2025
5837477
Refactor read-docs, web-search, and str-replace to pass logger as par…
charleslien Oct 9, 2025
be23932
Refactor write-file to pass logger as parameter
charleslien Oct 9, 2025
6f17f50
Refactor run-agent-step.ts to pass logger as parameter and consolidat…
charleslien Oct 9, 2025
dfb32f6
Refactor clearAgentGeneratorCache to pass logger as parameter
charleslien Oct 9, 2025
268f286
pass in logger to searchLibraries
charleslien Oct 9, 2025
3421c10
pass in logger to gemini with fallbacks
charleslien Oct 9, 2025
fa7a47a
pass in logger to linkup api
charleslien Oct 9, 2025
194e307
pass in logger to relace api
charleslien Oct 9, 2025
0affa94
pass in logger to ai sdk
charleslien Oct 9, 2025
ac87a22
pass in logger to websockets/server
charleslien Oct 9, 2025
1ae20a1
pass in logger to middleware
charleslien Oct 9, 2025
d01700a
mock logger in tests
charleslien Oct 9, 2025
ea5a45f
pass in logger to websocket actions
charleslien Oct 9, 2025
0fb8eea
fix typechecks for scripts/
charleslien Oct 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
246 changes: 191 additions & 55 deletions backend/src/__tests__/agent-registry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ import type { DynamicAgentTemplate } from '@codebuff/common/types/dynamic-agent-
import type { ProjectFileContext } from '@codebuff/common/util/file'
import type { Logger } from '@codebuff/types/logger'

const logger: Logger = {
debug: () => {},
error: () => {},
info: () => {},
warn: () => {},
}

// Create mock static templates that will be used by the agent registry
const mockStaticTemplates: Record<string, AgentTemplate> = {
base: {
Expand Down Expand Up @@ -101,16 +108,6 @@ describe('Agent Registry', () => {
desc: (field: any) => ({ type: 'desc', field }),
eq: (field: any, value: any) => ({ type: 'eq', field, value }),
}))

// Mock logger
mockModule('@codebuff/backend/util/logger', () => ({
logger: {
debug: () => {},
log: () => {},
error: () => {},
warn: () => {},
},
}))
})
let mockFileContext: ProjectFileContext

Expand Down Expand Up @@ -150,16 +147,6 @@ describe('Agent Registry', () => {
desc: (field: any) => ({ type: 'desc', field }),
eq: (field: any, value: any) => ({ type: 'eq', field, value }),
}))

// Mock logger
mockModule('@codebuff/backend/util/logger', () => ({
logger: {
debug: () => {},
log: () => {},
error: () => {},
warn: () => {},
},
}))
})

beforeEach(async () => {
Expand Down Expand Up @@ -253,33 +240,80 @@ describe('Agent Registry', () => {
} as AgentTemplate,
}

const result = await getAgentTemplate('my-agent', localAgents)
const logger = {
debug: () => {},
info: () => {},
warn: () => {},
error: () => {},
}
const result = await getAgentTemplate({
agentId: 'my-agent',
localAgentTemplates: localAgents,
logger,
})
expect(result).toBeTruthy()
expect(result?.id).toBe('my-agent')
})

it('should handle agent IDs with publisher but no version', async () => {
const result = await getAgentTemplate('publisher/agent-name', {})
const logger = {
debug: () => {},
info: () => {},
warn: () => {},
error: () => {},
}
const result = await getAgentTemplate({
agentId: 'publisher/agent-name',
localAgentTemplates: {},
logger,
})
expect(result).toBeNull()
})

it('should handle agent IDs with publisher and version', async () => {
const result = await getAgentTemplate('publisher/agent-name@1.0.0', {})
const logger = {
debug: () => {},
info: () => {},
warn: () => {},
error: () => {},
}
const result = await getAgentTemplate({
agentId: 'publisher/agent-name@1.0.0',
localAgentTemplates: {},
logger,
})
expect(result).toBeNull()
})

it('should return null for invalid agent ID formats', async () => {
const result = await getAgentTemplate(
'invalid/format/with/too/many/slashes',
{},
)
const logger = {
debug: () => {},
info: () => {},
warn: () => {},
error: () => {},
}
const result = await getAgentTemplate({
agentId: 'invalid/format/with/too/many/slashes',
localAgentTemplates: {},
logger,
})
expect(result).toBeNull()
})
})

describe('fetchAgentFromDatabase', () => {
it('should return null when agent not found in database', async () => {
const result = await getAgentTemplate('nonexistent/agent@1.0.0', {})
const logger = {
debug: () => {},
info: () => {},
warn: () => {},
error: () => {},
}
const result = await getAgentTemplate({
agentId: 'nonexistent/agent@1.0.0',
localAgentTemplates: {},
logger,
})
expect(result).toBeNull()
})

Expand Down Expand Up @@ -317,10 +351,17 @@ describe('Agent Registry', () => {
}) as any,
)

const result = await getAgentTemplate(
'test-publisher/test-agent@1.0.0',
{},
)
const logger = {
debug: () => {},
info: () => {},
warn: () => {},
error: () => {},
}
const result = await getAgentTemplate({
agentId: 'test-publisher/test-agent@1.0.0',
localAgentTemplates: {},
logger,
})
expect(result).toBeTruthy()
expect(result?.id).toBe('test-publisher/test-agent@1.0.0')
})
Expand All @@ -347,7 +388,17 @@ describe('Agent Registry', () => {
} as AgentTemplate,
}

const result = await getAgentTemplate('test-agent', localAgents)
const logger = {
debug: () => {},
info: () => {},
warn: () => {},
error: () => {},
}
const result = await getAgentTemplate({
agentId: 'test-agent',
localAgentTemplates: localAgents,
logger,
})
expect(result).toBeTruthy()
expect(result?.displayName).toBe('Local Test Agent')
})
Expand Down Expand Up @@ -387,18 +438,20 @@ describe('Agent Registry', () => {
)

// First call - should hit database
const result1 = await getAgentTemplate(
'test-publisher/cached-agent@1.0.0',
{},
)
const result1 = await getAgentTemplate({
agentId: 'test-publisher/cached-agent@1.0.0',
localAgentTemplates: {},
logger,
})
expect(result1).toBeTruthy()
expect(selectSpy).toHaveBeenCalledTimes(1)

// Second call - should use cache
const result2 = await getAgentTemplate(
'test-publisher/cached-agent@1.0.0',
{},
)
const result2 = await getAgentTemplate({
agentId: 'test-publisher/cached-agent@1.0.0',
localAgentTemplates: {},
logger,
})
expect(result2).toBeTruthy()
expect(result2?.displayName).toBe('Cached Agent')
expect(selectSpy).toHaveBeenCalledTimes(1)
Expand Down Expand Up @@ -426,7 +479,13 @@ describe('Agent Registry', () => {
},
}

const result = assembleLocalAgentTemplates(fileContext)
const logger = {
debug: () => {},
info: () => {},
warn: () => {},
error: () => {},
}
const result = assembleLocalAgentTemplates({ fileContext, logger })

// Should have dynamic template
expect(result.agentTemplates).toHaveProperty('custom-agent')
Expand All @@ -450,7 +509,13 @@ describe('Agent Registry', () => {
},
}

const result = assembleLocalAgentTemplates(fileContext)
const logger = {
debug: () => {},
info: () => {},
warn: () => {},
error: () => {},
}
const result = assembleLocalAgentTemplates({ fileContext, logger })

// Should not have invalid template
expect(result.agentTemplates).not.toHaveProperty('invalid-agent')
Expand All @@ -465,7 +530,13 @@ describe('Agent Registry', () => {
agentTemplates: {},
}

const result = assembleLocalAgentTemplates(fileContext)
const logger = {
debug: () => {},
info: () => {},
warn: () => {},
error: () => {},
}
const result = assembleLocalAgentTemplates({ fileContext, logger })

// Should have no validation errors
expect(result.validationErrors).toHaveLength(0)
Expand Down Expand Up @@ -511,35 +582,83 @@ describe('Agent Registry', () => {
)

// First call - should hit database and populate cache
await getAgentTemplate('test-publisher/cache-test-agent@1.0.0', {})
const logger = {
debug: () => {},
info: () => {},
warn: () => {},
error: () => {},
}
await getAgentTemplate({
agentId: 'test-publisher/cache-test-agent@1.0.0',
localAgentTemplates: {},
logger,
})
expect(selectSpy).toHaveBeenCalledTimes(1)

// Second call - should use cache
await getAgentTemplate('test-publisher/cache-test-agent@1.0.0', {})
await getAgentTemplate({
agentId: 'test-publisher/cache-test-agent@1.0.0',
localAgentTemplates: {},
logger,
})
expect(selectSpy).toHaveBeenCalledTimes(1)

// Clear cache
clearDatabaseCache()

// Third call - should hit database again after cache clear
await getAgentTemplate('test-publisher/cache-test-agent@1.0.0', {})
await getAgentTemplate({
agentId: 'test-publisher/cache-test-agent@1.0.0',
localAgentTemplates: {},
logger,
})
expect(selectSpy).toHaveBeenCalledTimes(2)
})
})

describe('edge cases', () => {
it('should handle empty agent ID', async () => {
const result = await getAgentTemplate('', {})
const logger = {
debug: () => {},
info: () => {},
warn: () => {},
error: () => {},
}
const result = await getAgentTemplate({
agentId: '',
localAgentTemplates: {},
logger,
})
expect(result).toBeNull()
})

it('should handle agent ID with multiple @ symbols', async () => {
const result = await getAgentTemplate('publisher/agent@1.0.0@extra', {})
const logger = {
debug: () => {},
info: () => {},
warn: () => {},
error: () => {},
}
const result = await getAgentTemplate({
agentId: 'publisher/agent@1.0.0@extra',
localAgentTemplates: {},
logger,
})
expect(result).toBeNull()
})

it('should handle agent ID with only @ symbol', async () => {
const result = await getAgentTemplate('publisher/agent@', {})
const logger = {
debug: () => {},
info: () => {},
warn: () => {},
error: () => {},
}
const result = await getAgentTemplate({
agentId: 'publisher/agent@',
localAgentTemplates: {},
logger,
})
expect(result).toBeNull()
})

Expand All @@ -549,7 +668,17 @@ describe('Agent Registry', () => {
throw new Error('Database connection failed')
})

const result = await getAgentTemplate('publisher/agent@1.0.0', {})
const logger = {
debug: () => {},
info: () => {},
warn: () => {},
error: () => {},
}
const result = await getAgentTemplate({
agentId: 'publisher/agent@1.0.0',
localAgentTemplates: {},
logger,
})
expect(result).toBeNull()
})

Expand Down Expand Up @@ -579,10 +708,17 @@ describe('Agent Registry', () => {
}) as any,
)

const result = await getAgentTemplate(
'publisher/malformed-agent@1.0.0',
{},
)
const logger = {
debug: () => {},
info: () => {},
warn: () => {},
error: () => {},
}
const result = await getAgentTemplate({
agentId: 'publisher/malformed-agent@1.0.0',
localAgentTemplates: {},
logger,
})
expect(result).toBeNull()
})
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ describe('Cost Aggregation Integration Tests', () => {

// Mock getAgentTemplate to return our mock templates
spyOn(agentRegistry, 'getAgentTemplate').mockImplementation(
async (agentId, localAgentTemplates) => {
async ({ agentId, localAgentTemplates }) => {
return localAgentTemplates[agentId] || null
},
)
Expand Down
Loading