Skip to content

Commit bdda8e5

Browse files
RulaKhaledclaude
andcommitted
test(server-utils): Cover Flue message content recording
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent 9dc64f5 commit bdda8e5

1 file changed

Lines changed: 59 additions & 0 deletions

File tree

packages/server-utils/test/ai/lib/tracing/flue.test.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,65 @@ describe('createFlueInstrumentation', () => {
166166
expect(json?.data['gen_ai.cost.total_tokens']).toBeUndefined();
167167
});
168168

169+
describe('content recording', () => {
170+
const requestContent = {
171+
type: 'turn_request',
172+
turnId: 'turn_1',
173+
request: {
174+
requestedModel: 'claude-haiku-4.5',
175+
input: {
176+
systemPrompt: 'You are helpful.',
177+
messages: [{ role: 'user', content: 'hi' }],
178+
tools: [{ name: 'get_weather', description: 'weather', parameters: {} }],
179+
},
180+
},
181+
} satisfies FlueObservation;
182+
183+
async function record(instr: FlueInstrumentation): Promise<void> {
184+
await instr.interceptor({ type: 'agent' }, AGENT_CTX, async () => {
185+
instr.observe({ type: 'turn_start', turnId: 'turn_1' }, {});
186+
instr.observe(requestContent, {});
187+
instr.observe(turn({ response: { ...turn().response, output: { role: 'assistant' } } }), {});
188+
instr.observe({ type: 'tool_start', toolCallId: 'c1', toolName: 'get_weather', args: { city: 'Berlin' } }, {});
189+
instr.observe({ type: 'tool', toolCallId: 'c1', toolName: 'get_weather', result: 'sunny' }, {});
190+
});
191+
}
192+
193+
it('records messages, instructions, tool definitions, arguments and results by default', async () => {
194+
await record(instrumentation);
195+
196+
const chat = findSpan('chat claude-haiku-4.5');
197+
expect(chat?.data['gen_ai.system_instructions']).toBe('You are helpful.');
198+
expect(chat?.data['gen_ai.input.messages']).toContain('"role":"user"');
199+
expect(chat?.data['gen_ai.output.messages']).toContain('"role":"assistant"');
200+
expect(chat?.data['gen_ai.tool.definitions']).toContain('get_weather');
201+
202+
const tool = findSpan('execute_tool get_weather');
203+
expect(tool?.data['gen_ai.tool.call.arguments']).toBe('{"city":"Berlin"}');
204+
expect(tool?.data['gen_ai.tool.call.result']).toBe('sunny');
205+
});
206+
207+
it('omits inputs when recordInputs is false but keeps outputs', async () => {
208+
await record(createFlueInstrumentation({ recordInputs: false }));
209+
210+
const chat = findSpan('chat claude-haiku-4.5');
211+
expect(chat?.data['gen_ai.input.messages']).toBeUndefined();
212+
expect(chat?.data['gen_ai.system_instructions']).toBeUndefined();
213+
expect(chat?.data['gen_ai.tool.definitions']).toBeUndefined();
214+
expect(chat?.data['gen_ai.output.messages']).toBeDefined();
215+
expect(findSpan('execute_tool get_weather')?.data['gen_ai.tool.call.arguments']).toBeUndefined();
216+
});
217+
218+
it('omits outputs when recordOutputs is false but keeps inputs', async () => {
219+
await record(createFlueInstrumentation({ recordOutputs: false }));
220+
221+
const chat = findSpan('chat claude-haiku-4.5');
222+
expect(chat?.data['gen_ai.output.messages']).toBeUndefined();
223+
expect(chat?.data['gen_ai.input.messages']).toBeDefined();
224+
expect(findSpan('execute_tool get_weather')?.data['gen_ai.tool.call.result']).toBeUndefined();
225+
});
226+
});
227+
169228
it('emits execute_tool spans keyed by tool call id', async () => {
170229
await withAgent(() => {
171230
instrumentation.observe({ type: 'tool_start', toolCallId: 'call_1', toolName: 'get_weather' }, {});

0 commit comments

Comments
 (0)