Skip to content
Closed
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
Expand Up @@ -113,6 +113,7 @@ export const NO_AUTO_INSTRUMENTATION = [
'suites/tracing/openai/v6/test.ts',
'suites/tracing/openai/v7/test.ts',
'suites/tracing/orchestrion-lazy-registration/test.ts',
'suites/tracing/pi-ai/test.ts',
'suites/tracing/pi-durable/test.ts',
'suites/tracing/postgres/test.ts',
'suites/tracing/postgresjs/test.ts',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ test('instruments a Flue agent with no manual instrument() call', async () => {
await expect
.poll(() => fetchSpanAttributes(traceId!, chat!.event_id!), EVENT_POLLING_OPTIONS)
.toMatchObject({
origin: 'auto.ai.flue',
origin: 'auto.ai.pi_ai',
'gen_ai.provider.name': 'openrouter',
'gen_ai.usage.input_tokens': expect.anything(),
'gen_ai.cost.total_tokens': expect.anything(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ test('traces a PiHarness prompt as invoke_agent with chat, execute_tool and prov
// pi-ai sends the requests through `@anthropic-ai/sdk`, whose own integration must stay out so
// each request is reported once.
expect(spans.filter(span => String(span.attributes[SENTRY_ORIGIN]?.value).startsWith('auto.ai.'))).toEqual(
spans.filter(span => span.attributes[SENTRY_ORIGIN]?.value === 'auto.ai.pi_durable'),
spans.filter(span =>
['auto.ai.pi_durable', 'auto.ai.pi_ai'].includes(String(span.attributes[SENTRY_ORIGIN]?.value)),
),
);

// One tool-calling response, then the answer.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ test('captures the invoke_agent / chat / execute_tool hierarchy for a Flue turn'
expect(invokeAgent?.attributes?.['gen_ai.operation.name']?.value).toBe('invoke_agent');
expect(invokeAgent?.attributes?.['gen_ai.agent.name']?.value).toBe('Hello');

expect(chat?.attributes?.['sentry.origin']?.value).toBe('auto.ai.flue');
expect(chat?.attributes?.['sentry.origin']?.value).toBe('auto.ai.pi_ai');
expect(chat?.attributes?.['gen_ai.provider.name']?.value).toBe('openrouter');
expect(typeof chat?.attributes?.['gen_ai.usage.input_tokens']?.value).toBe('number');
expect(typeof chat?.attributes?.['gen_ai.usage.output_tokens']?.value).toBe('number');
// Flue computes cost itself; no provider SDK reports it.
// pi-ai computes cost itself; no provider SDK reports it.
expect(typeof chat?.attributes?.['gen_ai.cost.total_tokens']?.value).toBe('number');

expect(executeTool?.attributes?.['gen_ai.tool.name']?.value).toBe('get_weather');
Expand Down Expand Up @@ -92,7 +92,7 @@ test('nests a manual span raised inside a tool under that tool span', async ({ b
expect(manualSpan?.parent_span_id).toBe(executeTool?.span_id);
});

// Flue's `model` operation is wrapped so the turn span is active for it, which is what puts the
// The pi-ai integration makes the chat span active for the request it sends, which is what puts the
// provider's HTTP call inside `chat` rather than beside it.
test('nests the provider HTTP call inside the chat span', async ({ baseURL }) => {
const spansPromise = collectStreamedSpans(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,16 @@ test('traces a run as invoke_agent with chat, execute_tool and provider spans',
// pi-ai sends the requests through `@anthropic-ai/sdk`, whose own integration must stay out so
// each request is reported once.
expect(spans.filter(span => String(span.attributes[SENTRY_ORIGIN]?.value).startsWith('auto.ai.'))).toEqual(
spans.filter(span => span.attributes[SENTRY_ORIGIN]?.value === 'auto.ai.pi_durable'),
spans.filter(span =>
['auto.ai.pi_durable', 'auto.ai.pi_ai'].includes(String(span.attributes[SENTRY_ORIGIN]?.value)),
),
);

// One tool-calling response, then the answer.
expect(chats.length).toBeGreaterThanOrEqual(2);
for (const chat of chats) {
expect(chat.parent_span_id).toBe(agent.span_id);
expect(chat.attributes[SENTRY_ORIGIN]?.value).toBe('auto.ai.pi_durable');
expect(chat.attributes[SENTRY_ORIGIN]?.value).toBe('auto.ai.pi_ai');
expect(chat.attributes[GEN_AI_PROVIDER_NAME]?.value).toBe('openrouter');
expect(chat.attributes[GEN_AI_REQUEST_MODEL]?.value).toBe('anthropic/claude-haiku-4.5');
// pi-durable retries a provider error inside the run; such a request has no usage and no HTTP span
Expand Down
3 changes: 3 additions & 0 deletions dev-packages/node-integration-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
"@aws-sdk/client-sfn": "^3.1046.0",
"@aws-sdk/client-sns": "^3.1046.0",
"@aws-sdk/client-sqs": "^3.1046.0",
"@earendil-works/pi-ai": "^1.4.0",
"@flue/runtime": "2.0.3",
"@google/genai": "^1.20.0",
"@growthbook/growthbook": "^1.6.5",
"@hapi/hapi": "^21.3.10",
Expand Down Expand Up @@ -110,6 +112,7 @@
"srvx": "^0.11.22",
"tedious": "^19.2.1",
"unstorage": "2.0.0-alpha.7",
"valibot": "1.4.2",
"winston": "^3.17.0",
"ws": "^8.20.1",
"yargs": "^16.2.0"
Expand Down
Loading
Loading