diff --git a/packages/sdk/server-ai/__tests__/LDAIClientImpl.test.ts b/packages/sdk/server-ai/__tests__/LDAIClientImpl.test.ts index 77af66a0b5..78ffa0baf7 100644 --- a/packages/sdk/server-ai/__tests__/LDAIClientImpl.test.ts +++ b/packages/sdk/server-ai/__tests__/LDAIClientImpl.test.ts @@ -833,3 +833,86 @@ describe('optional default values', () => { expect(result.enabled).toBe(false); }); }); + +describe('tools map support', () => { + it('includes tools map in completion config from flag variation', async () => { + const client = new LDAIClientImpl(mockLdClient); + const key = 'test-flag'; + const defaultValue: LDAICompletionConfigDefault = { enabled: false }; + const mockVariation = { + model: { name: 'example-model' }, + tools: { + 'web-search-tool': { + name: 'web-search-tool', + type: 'function', + parameters: { type: 'object', properties: {}, required: [] }, + customParameters: { 'some-custom-parameter': 'some-custom-value' }, + }, + }, + _ldMeta: { variationKey: 'v1', enabled: true, mode: 'completion' }, + }; + mockLdClient.variation.mockResolvedValue(mockVariation); + + const result = await client.completionConfig(key, testContext, defaultValue); + + expect(result.tools).toEqual(mockVariation.tools); + }); + + it('includes tools map in agent config from flag variation', async () => { + const client = new LDAIClientImpl(mockLdClient); + const key = 'test-agent'; + const defaultValue: LDAIAgentConfigDefault = { enabled: false }; + const mockVariation = { + model: { name: 'example-model' }, + instructions: 'You are a helpful agent.', + tools: { + 'search-tool': { + name: 'search-tool', + type: 'function', + customParameters: { maxResults: 10 }, + }, + }, + _ldMeta: { variationKey: 'v1', enabled: true, mode: 'agent' }, + }; + mockLdClient.variation.mockResolvedValue(mockVariation); + + const result = await client.agentConfig(key, testContext, defaultValue); + + expect(result.tools).toEqual(mockVariation.tools); + }); + + it('returns undefined tools when variation has no tools', async () => { + const client = new LDAIClientImpl(mockLdClient); + const key = 'test-flag'; + const defaultTools = { + 'default-tool': { + name: 'default-tool', + type: 'function', + customParameters: { priority: 'high' }, + }, + }; + const defaultValue: LDAICompletionConfigDefault = { enabled: true, tools: defaultTools }; + mockLdClient.variation.mockResolvedValue({ + _ldMeta: { enabled: true, mode: 'completion', variationKey: '' }, + }); + + const result = await client.completionConfig(key, testContext, defaultValue); + + expect(result.tools).toBeUndefined(); + }); + + it('returns undefined tools when no tools are configured', async () => { + const client = new LDAIClientImpl(mockLdClient); + const key = 'test-flag'; + const defaultValue: LDAICompletionConfigDefault = { enabled: false }; + const mockVariation = { + model: { name: 'example-model' }, + _ldMeta: { variationKey: 'v1', enabled: true, mode: 'completion' }, + }; + mockLdClient.variation.mockResolvedValue(mockVariation); + + const result = await client.completionConfig(key, testContext, defaultValue); + + expect(result.tools).toBeUndefined(); + }); +}); diff --git a/packages/sdk/server-ai/src/api/config/LDAIConfigUtils.ts b/packages/sdk/server-ai/src/api/config/LDAIConfigUtils.ts index 74ab8ee30a..dc8b36edb4 100644 --- a/packages/sdk/server-ai/src/api/config/LDAIConfigUtils.ts +++ b/packages/sdk/server-ai/src/api/config/LDAIConfigUtils.ts @@ -10,6 +10,7 @@ import { LDMessage, LDModelConfig, LDProviderConfig, + LDTool, } from './types'; /** @@ -32,6 +33,7 @@ export interface LDAIConfigFlagValue { evaluationMetricKey?: string; evaluationMetricKeys?: string[]; judgeConfiguration?: LDJudgeConfiguration; + tools?: { [toolName: string]: LDTool }; } /** @@ -75,6 +77,9 @@ export class LDAIConfigUtils { if ('judgeConfiguration' in config && config.judgeConfiguration !== undefined) { flagValue.judgeConfiguration = config.judgeConfiguration; } + if ('tools' in config && config.tools !== undefined) { + flagValue.tools = config.tools; + } return flagValue; } @@ -172,6 +177,7 @@ export class LDAIConfigUtils { createTracker: trackerFactory, messages: flagValue.messages, judgeConfiguration: flagValue.judgeConfiguration, + tools: flagValue.tools, }; } @@ -193,6 +199,7 @@ export class LDAIConfigUtils { createTracker: trackerFactory, instructions: flagValue.instructions, judgeConfiguration: flagValue.judgeConfiguration, + tools: flagValue.tools, }; } diff --git a/packages/sdk/server-ai/src/api/config/types.ts b/packages/sdk/server-ai/src/api/config/types.ts index 56a54d1ca2..d1c2a161e2 100644 --- a/packages/sdk/server-ai/src/api/config/types.ts +++ b/packages/sdk/server-ai/src/api/config/types.ts @@ -45,6 +45,22 @@ export interface LDProviderConfig { name: string; } +// ============================================================================ +// Tool Types +// ============================================================================ + +/** + * Configuration for a single tool entry in the root-level tools map. + * Separate from model.parameters.tools[] which is the LLM-passable array. + */ +export interface LDTool { + name: string; + description?: string; + type?: string; + parameters?: { [index: string]: unknown }; + customParameters?: { [index: string]: unknown }; +} + // ============================================================================ // Judge Types // ============================================================================ @@ -129,6 +145,10 @@ export interface LDAIAgentConfigDefault extends LDAIConfigDefault { * References judge AI Configs that should evaluate this AI Config. */ judgeConfiguration?: LDJudgeConfiguration; + /** + * Root-level tools map keyed by tool name. Distinct from model.parameters.tools[]. + */ + tools?: { [toolName: string]: LDTool }; } /** @@ -144,6 +164,10 @@ export interface LDAICompletionConfigDefault extends LDAIConfigDefault { * References judge AI Configs that should evaluate this AI Config. */ judgeConfiguration?: LDJudgeConfiguration; + /** + * Root-level tools map keyed by tool name. Distinct from model.parameters.tools[]. + */ + tools?: { [toolName: string]: LDTool }; } /** @@ -192,6 +216,10 @@ export interface LDAIAgentConfig extends LDAIConfig { * References judge AI Configs that should evaluate this AI Config. */ judgeConfiguration?: LDJudgeConfiguration; + /** + * Root-level tools map keyed by tool name. Distinct from model.parameters.tools[]. + */ + tools?: { [toolName: string]: LDTool }; } /** @@ -207,6 +235,10 @@ export interface LDAICompletionConfig extends LDAIConfig { * References judge AI Configs that should evaluate this AI Config. */ judgeConfiguration?: LDJudgeConfiguration; + /** + * Root-level tools map keyed by tool name. Distinct from model.parameters.tools[]. + */ + tools?: { [toolName: string]: LDTool }; } /**