Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { TEST_AGENT_RUNTIME_IMPL } from '@codebuff/common/testing/impl/agent-runtime'
import { describe, test, expect, mock } from 'bun:test'
import { convertJsonSchemaToZod } from 'zod-from-json-schema'
import { z } from 'zod/v4'

import { buildAgentToolInputSchema, buildAgentToolSet } from '../templates/prompts'
Expand Down Expand Up @@ -172,6 +173,30 @@ describe('Schema handling error recovery', () => {
expect(description).toContain('content')
})

test('buildToolDescription preserves MCP params when schema is represented as allOf', () => {
const mcpSchema = convertJsonSchemaToZod({
type: 'object',
properties: {
name: { type: 'string' },
},
required: ['name'],
additionalProperties: false,
})

const description = buildToolDescription({
toolName: 'greet__greet',
schema: mcpSchema,
description: 'Call greet',
endsAgentStep: true,
})

expect(description).toContain('greet__greet')
expect(description).toContain('Params: {')
expect(description).toContain('allOf')
expect(description).toContain('name')
expect(description).not.toContain('Params: None')
})

test('getToolSet handles custom tools with problematic schemas', async () => {
// Create a custom tool definition with a schema that can't be converted
const customToolDefs = {
Expand Down
23 changes: 22 additions & 1 deletion packages/agent-runtime/src/tools/prompts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,27 @@ function toJsonSchemaSafe(schema: z.ZodType): Record<string, unknown> {
}
}

function hasMeaningfulJsonSchema(jsonSchema: Record<string, unknown>): boolean {
const properties = jsonSchema.properties
if (properties && typeof properties === 'object' && Object.keys(properties).length > 0) {
return true
}

for (const key of ['allOf', 'anyOf', 'oneOf']) {
const value = jsonSchema[key]
if (Array.isArray(value) && value.length > 0) {
return true
}
}

const required = jsonSchema.required
if (Array.isArray(required) && required.length > 0) {
return true
}

return false
}

function paramsSection(params: { schema: z.ZodType; endsAgentStep: boolean }) {
const { schema, endsAgentStep } = params
const safeSchema = ensureJsonSchemaCompatible(schema)
Expand All @@ -68,7 +89,7 @@ function paramsSection(params: { schema: z.ZodType; endsAgentStep: boolean }) {
const jsonSchema = toJsonSchemaSafe(schemaWithEndsAgentStepParam)
delete jsonSchema.description
delete jsonSchema['$schema']
const paramsDescription = Object.keys(jsonSchema.properties ?? {}).length
const paramsDescription = hasMeaningfulJsonSchema(jsonSchema)
? JSON.stringify(jsonSchema, null, 2)
: 'None'

Expand Down