Skip to content

Commit 0f8bb2c

Browse files
committed
refactor(node): Use shared utilities in Claude Code integration
1 parent 8061ee8 commit 0f8bb2c

File tree

4 files changed

+175
-118
lines changed

4 files changed

+175
-118
lines changed

packages/nextjs/src/server/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@ export { claudeCodeIntegration, createInstrumentedClaudeQuery, patchClaudeCodeQu
5858

5959
// Force rollup to keep the imports by "using" them
6060
const _forceInclude = { claudeCodeIntegration, createInstrumentedClaudeQuery, patchClaudeCodeQuery };
61-
if (false as boolean) { console.log(_forceInclude); }
61+
if (false as boolean) {
62+
console.log(_forceInclude);
63+
}
6264

6365
export { captureUnderscoreErrorException } from '../common/pages-router-instrumentation/_error';
6466

packages/node/src/integrations/tracing/claude-code/helpers.ts

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { getClient } from '@sentry/core';
2-
import { patchClaudeCodeQuery } from './instrumentation';
32
import type { ClaudeCodeOptions } from './index';
3+
import { patchClaudeCodeQuery } from './instrumentation';
44

55
const CLAUDE_CODE_INTEGRATION_NAME = 'ClaudeCode';
66

@@ -30,31 +30,29 @@ async function ensurePatchedQuery(): Promise<void> {
3030

3131
if (!claudeSDK || typeof claudeSDK.query !== 'function') {
3232
throw new Error(
33-
`Failed to find 'query' function in @anthropic-ai/claude-agent-sdk.\n` +
34-
`Make sure you have version >=0.1.0 installed.`,
33+
'Failed to find \'query\' function in @anthropic-ai/claude-agent-sdk.\n' +
34+
'Make sure you have version >=0.1.0 installed.',
3535
);
3636
}
3737

3838
const client = getClient();
3939
const integration = client?.getIntegrationByName(CLAUDE_CODE_INTEGRATION_NAME);
40-
const options = (integration as any)?.options as ClaudeCodeOptions | undefined || {};
40+
const options = ((integration as any)?.options as ClaudeCodeOptions | undefined) || {};
4141

4242
_globalPatchedQuery = patchClaudeCodeQuery(claudeSDK.query, options);
4343
} catch (error) {
4444
// Reset state on failure to allow retry on next call
4545
_initPromise = null;
4646

4747
const errorMessage =
48-
error instanceof Error
49-
? error.message
50-
: 'Unknown error occurred while loading @anthropic-ai/claude-agent-sdk';
48+
error instanceof Error ? error.message : 'Unknown error occurred while loading @anthropic-ai/claude-agent-sdk';
5149

5250
throw new Error(
5351
`Failed to instrument Claude Code SDK:\n${errorMessage}\n\n` +
54-
`Make sure @anthropic-ai/claude-agent-sdk is installed:\n` +
55-
` npm install @anthropic-ai/claude-agent-sdk\n` +
56-
` # or\n` +
57-
` yarn add @anthropic-ai/claude-agent-sdk`,
52+
'Make sure @anthropic-ai/claude-agent-sdk is installed:\n' +
53+
' npm install @anthropic-ai/claude-agent-sdk\n' +
54+
' # or\n' +
55+
' yarn add @anthropic-ai/claude-agent-sdk',
5856
);
5957
}
6058
})();
@@ -72,15 +70,21 @@ async function ensurePatchedQuery(): Promise<void> {
7270
* The Claude Code SDK cannot be automatically instrumented due to ESM module
7371
* and webpack bundling limitations.
7472
*
73+
* @param options - Optional configuration for this specific agent instance
74+
* @param options.name - Custom agent name for differentiation (defaults to 'claude-code')
7575
* @returns An instrumented query function ready to use
7676
*
7777
* @example
7878
* ```typescript
7979
* import { createInstrumentedClaudeQuery } from '@sentry/node';
80-
* import type { SDKUserMessage } from '@anthropic-ai/claude-agent-sdk';
8180
*
81+
* // Default agent name ('claude-code')
8282
* const query = createInstrumentedClaudeQuery();
8383
*
84+
* // Custom agent name for differentiation
85+
* const appBuilder = createInstrumentedClaudeQuery({ name: 'app-builder' });
86+
* const chatAgent = createInstrumentedClaudeQuery({ name: 'chat-assistant' });
87+
*
8488
* // Use as normal - automatically instrumented!
8589
* for await (const message of query({
8690
* prompt: 'Hello',
@@ -104,14 +108,33 @@ async function ensurePatchedQuery(): Promise<void> {
104108
* });
105109
* ```
106110
*/
107-
export function createInstrumentedClaudeQuery(): (...args: unknown[]) => AsyncGenerator<unknown, void, unknown> {
111+
export function createInstrumentedClaudeQuery(
112+
options: { name?: string } = {},
113+
): (...args: unknown[]) => AsyncGenerator<unknown, void, unknown> {
114+
const agentName = options.name ?? 'claude-code';
115+
108116
return async function* query(...args: unknown[]): AsyncGenerator<unknown, void, unknown> {
109117
await ensurePatchedQuery();
110118

111119
if (!_globalPatchedQuery) {
112120
throw new Error('[Sentry] Failed to initialize instrumented Claude Code query function');
113121
}
114122

115-
yield* _globalPatchedQuery(...args);
123+
// Create a new patched instance with custom agent name
124+
const client = getClient();
125+
const integration = client?.getIntegrationByName(CLAUDE_CODE_INTEGRATION_NAME);
126+
const integrationOptions = ((integration as any)?.options as ClaudeCodeOptions | undefined) || {};
127+
128+
// Import SDK again to get fresh query function
129+
const sdkPath = '@anthropic-ai/claude-agent-sdk';
130+
const claudeSDK = await import(/* webpackIgnore: true */ sdkPath);
131+
132+
// Patch with custom agent name
133+
const customPatchedQuery = patchClaudeCodeQuery(claudeSDK.query, {
134+
...integrationOptions,
135+
agentName,
136+
});
137+
138+
yield* customPatchedQuery(...args);
116139
};
117140
}

packages/node/src/integrations/tracing/claude-code/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,18 @@ export interface ClaudeCodeOptions {
1414
* Defaults to Sentry client's `sendDefaultPii` setting.
1515
*/
1616
recordOutputs?: boolean;
17+
18+
/**
19+
* Custom agent name to use for this integration.
20+
* This allows you to differentiate between multiple Claude Code agents in your application.
21+
* Defaults to 'claude-code'.
22+
*
23+
* @example
24+
* ```typescript
25+
* const query = createInstrumentedClaudeQuery({ name: 'app-builder' });
26+
* ```
27+
*/
28+
agentName?: string;
1729
}
1830

1931
const CLAUDE_CODE_INTEGRATION_NAME = 'ClaudeCode';

0 commit comments

Comments
 (0)