diff --git a/extensions/copilot/src/extension/byok/vscode-node/anthropicProvider.ts b/extensions/copilot/src/extension/byok/vscode-node/anthropicProvider.ts index eb1dd08b498..b7b101b9194 100644 --- a/extensions/copilot/src/extension/byok/vscode-node/anthropicProvider.ts +++ b/extensions/copilot/src/extension/byok/vscode-node/anthropicProvider.ts @@ -16,7 +16,7 @@ import { ContextManagementResponse, CUSTOM_TOOL_SEARCH_NAME, getContextManagemen import { IToolDeferralService } from '../../../platform/networking/common/toolDeferralService'; import { IResponseDelta, OpenAiFunctionTool } from '../../../platform/networking/common/fetch'; import { APIUsage } from '../../../platform/networking/common/openai'; -import { CopilotChatAttr, emitInferenceDetailsEvent, GenAiAttr, GenAiMetrics, GenAiOperationName, type OTelModelOptions, StdAttr, toToolDefinitions, truncateForOTel } from '../../../platform/otel/common/index'; +import { CopilotChatAttr, emitInferenceDetailsEvent, GenAiAttr, GenAiMetrics, GenAiOperationName, GenAiProviderName, type OTelModelOptions, StdAttr, toToolDefinitions, truncateForOTel } from '../../../platform/otel/common/index'; import { IOTelService, SpanKind, SpanStatusCode } from '../../../platform/otel/common/otelService'; import { IRequestLogger } from '../../../platform/requestLogger/common/requestLogger'; import { retrieveCapturingTokenByCorrelation, runWithCapturingToken } from '../../../platform/requestLogger/node/requestLogger'; @@ -472,7 +472,7 @@ export class AnthropicLMProvider extends AbstractLanguageModelChatProvider { kind: SpanKind.CLIENT, attributes: { [GenAiAttr.OPERATION_NAME]: GenAiOperationName.CHAT, - [GenAiAttr.PROVIDER_NAME]: 'anthropic', + [GenAiAttr.PROVIDER_NAME]: GenAiProviderName.ANTHROPIC, [GenAiAttr.REQUEST_MODEL]: model.id, [GenAiAttr.AGENT_NAME]: 'AnthropicBYOK', [CopilotChatAttr.MAX_PROMPT_TOKENS]: model.maxInputTokens, diff --git a/extensions/copilot/src/extension/byok/vscode-node/geminiNativeProvider.ts b/extensions/copilot/src/extension/byok/vscode-node/geminiNativeProvider.ts index 76d3bee85e5..aa94687f520 100644 --- a/extensions/copilot/src/extension/byok/vscode-node/geminiNativeProvider.ts +++ b/extensions/copilot/src/extension/byok/vscode-node/geminiNativeProvider.ts @@ -9,7 +9,7 @@ import { ChatFetchResponseType, ChatLocation } from '../../../platform/chat/comm import { ILogService } from '../../../platform/log/common/logService'; import { IResponseDelta, OpenAiFunctionTool } from '../../../platform/networking/common/fetch'; import { APIUsage } from '../../../platform/networking/common/openai'; -import { CopilotChatAttr, emitInferenceDetailsEvent, GenAiAttr, GenAiMetrics, GenAiOperationName, type OTelModelOptions, StdAttr, toToolDefinitions, truncateForOTel } from '../../../platform/otel/common/index'; +import { CopilotChatAttr, emitInferenceDetailsEvent, GenAiAttr, GenAiMetrics, GenAiOperationName, GenAiProviderName, type OTelModelOptions, StdAttr, toToolDefinitions, truncateForOTel } from '../../../platform/otel/common/index'; import { IOTelService, SpanKind, SpanStatusCode } from '../../../platform/otel/common/otelService'; import { IRequestLogger } from '../../../platform/requestLogger/common/requestLogger'; import { retrieveCapturingTokenByCorrelation, runWithCapturingToken } from '../../../platform/requestLogger/node/requestLogger'; @@ -337,7 +337,7 @@ export class GeminiNativeBYOKLMProvider extends AbstractLanguageModelChatProvide kind: SpanKind.CLIENT, attributes: { [GenAiAttr.OPERATION_NAME]: GenAiOperationName.CHAT, - [GenAiAttr.PROVIDER_NAME]: 'gemini', + [GenAiAttr.PROVIDER_NAME]: GenAiProviderName.GEMINI, [GenAiAttr.REQUEST_MODEL]: model.id, [GenAiAttr.AGENT_NAME]: 'GeminiBYOK', [CopilotChatAttr.MAX_PROMPT_TOKENS]: model.maxInputTokens, diff --git a/extensions/copilot/src/extension/chat/vscode-node/chatDebugFileLoggerService.ts b/extensions/copilot/src/extension/chat/vscode-node/chatDebugFileLoggerService.ts index 8dceb151d39..b6cbfcb23c8 100644 --- a/extensions/copilot/src/extension/chat/vscode-node/chatDebugFileLoggerService.ts +++ b/extensions/copilot/src/extension/chat/vscode-node/chatDebugFileLoggerService.ts @@ -1003,7 +1003,7 @@ export class ChatDebugFileLoggerService extends Disposable implements IChatDebug } case GenAiOperationName.EXECUTE_HOOK: { - const hookType = asString(span.attributes['copilot_chat.hook_type']) ?? span.name; + const hookType = asString(span.attributes[CopilotChatAttr.HOOK_TYPE]) ?? span.name; return { ts: span.startTime, dur: duration, @@ -1017,14 +1017,14 @@ export class ChatDebugFileLoggerService extends Disposable implements IChatDebug ...(span.attributes['copilot_chat.hook_command'] !== undefined ? { command: truncate(String(span.attributes['copilot_chat.hook_command']), MAX_ATTR_VALUE_LENGTH) } : {}), - ...(span.attributes['copilot_chat.hook_input'] !== undefined - ? { input: truncate(String(span.attributes['copilot_chat.hook_input']), MAX_ATTR_VALUE_LENGTH) } + ...(span.attributes[CopilotChatAttr.HOOK_INPUT] !== undefined + ? { input: truncate(String(span.attributes[CopilotChatAttr.HOOK_INPUT]), MAX_ATTR_VALUE_LENGTH) } : {}), - ...(span.attributes['copilot_chat.hook_output'] !== undefined - ? { output: truncate(String(span.attributes['copilot_chat.hook_output']), MAX_ATTR_VALUE_LENGTH) } + ...(span.attributes[CopilotChatAttr.HOOK_OUTPUT] !== undefined + ? { output: truncate(String(span.attributes[CopilotChatAttr.HOOK_OUTPUT]), MAX_ATTR_VALUE_LENGTH) } : {}), - ...(span.attributes['copilot_chat.hook_result_kind'] !== undefined - ? { resultKind: String(span.attributes['copilot_chat.hook_result_kind']) } + ...(span.attributes[CopilotChatAttr.HOOK_RESULT_KIND] !== undefined + ? { resultKind: String(span.attributes[CopilotChatAttr.HOOK_RESULT_KIND]) } : {}), ...(isError && span.status.message ? { error: span.status.message } : {}), }, diff --git a/extensions/copilot/src/extension/chat/vscode-node/chatHookService.ts b/extensions/copilot/src/extension/chat/vscode-node/chatHookService.ts index d52d515ebda..473311db1f2 100644 --- a/extensions/copilot/src/extension/chat/vscode-node/chatHookService.ts +++ b/extensions/copilot/src/extension/chat/vscode-node/chatHookService.ts @@ -157,7 +157,7 @@ export class ChatHookService implements IChatHookService { kind: SpanKind.INTERNAL, attributes: { [GenAiAttr.OPERATION_NAME]: GenAiOperationName.EXECUTE_HOOK, - 'copilot_chat.hook_type': hookType, + [CopilotChatAttr.HOOK_TYPE]: hookType, 'copilot_chat.hook_command': hookCommand.command, ...(chatSessionId ? { [CopilotChatAttr.CHAT_SESSION_ID]: chatSessionId } : {}), }, @@ -166,7 +166,7 @@ export class ChatHookService implements IChatHookService { try { // Capture hook input for debug panel resolve try { - span.setAttribute('copilot_chat.hook_input', truncateForOTel(JSON.stringify(commandInput))); + span.setAttribute(CopilotChatAttr.HOOK_INPUT, truncateForOTel(JSON.stringify(commandInput))); } catch { /* swallow serialization errors */ } const sw = StopWatch.create(); @@ -179,7 +179,7 @@ export class ChatHookService implements IChatHookService { const resultKind = commandResult.kind === HookCommandResultKind.Success ? 'success' : commandResult.kind === HookCommandResultKind.NonBlockingError ? 'non_blocking_error' : 'error'; - span.setAttribute('copilot_chat.hook_result_kind', resultKind); + span.setAttribute(CopilotChatAttr.HOOK_RESULT_KIND, resultKind); if (commandResult.kind === HookCommandResultKind.Error || commandResult.kind === HookCommandResultKind.NonBlockingError) { hasError = true; @@ -195,7 +195,7 @@ export class ChatHookService implements IChatHookService { try { const output = typeof commandResult.result === 'string' ? commandResult.result : JSON.stringify(commandResult.result); if (output) { - span.setAttribute('copilot_chat.hook_output', truncateForOTel(output)); + span.setAttribute(CopilotChatAttr.HOOK_OUTPUT, truncateForOTel(output)); } } catch { /* swallow serialization errors */ } } diff --git a/extensions/copilot/src/extension/chatSessions/claude/common/claudeMessageDispatch.ts b/extensions/copilot/src/extension/chatSessions/claude/common/claudeMessageDispatch.ts index a7e93dd1c84..5515ae0e252 100644 --- a/extensions/copilot/src/extension/chatSessions/claude/common/claudeMessageDispatch.ts +++ b/extensions/copilot/src/extension/chatSessions/claude/common/claudeMessageDispatch.ts @@ -384,7 +384,7 @@ export function handleHookStarted( kind: SpanKind.INTERNAL, attributes: { [GenAiAttr.OPERATION_NAME]: GenAiOperationName.EXECUTE_HOOK, - 'copilot_chat.hook_type': message.hook_event, + [CopilotChatAttr.HOOK_TYPE]: message.hook_event, 'copilot_chat.hook_command': message.hook_name, 'copilot_chat.hook_id': message.hook_id, [CopilotChatAttr.CHAT_SESSION_ID]: sessionId, diff --git a/extensions/copilot/src/extension/chatSessions/claude/node/claudeOTelTracker.ts b/extensions/copilot/src/extension/chatSessions/claude/node/claudeOTelTracker.ts index f5690a1a215..cdd20a2acfa 100644 --- a/extensions/copilot/src/extension/chatSessions/claude/node/claudeOTelTracker.ts +++ b/extensions/copilot/src/extension/chatSessions/claude/node/claudeOTelTracker.ts @@ -191,7 +191,7 @@ export class ClaudeOTelTracker { this._currentSpan.setAttribute(CopilotChatAttr.TURN_COUNT, message.num_turns); } if (message.total_cost_usd !== undefined) { - this._currentSpan.setAttribute('copilot_chat.total_cost_usd', message.total_cost_usd); + this._currentSpan.setAttribute(CopilotChatAttr.TOTAL_COST_USD, message.total_cost_usd); } const responseModel = message.modelUsage ? Object.keys(message.modelUsage)[0] : undefined; if (responseModel) { diff --git a/extensions/copilot/src/extension/chatSessions/copilotcli/node/copilotCliBridgeSpanProcessor.ts b/extensions/copilot/src/extension/chatSessions/copilotcli/node/copilotCliBridgeSpanProcessor.ts index e4f58424127..c16987ac440 100644 --- a/extensions/copilot/src/extension/chatSessions/copilotcli/node/copilotCliBridgeSpanProcessor.ts +++ b/extensions/copilot/src/extension/chatSessions/copilotcli/node/copilotCliBridgeSpanProcessor.ts @@ -3,8 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CopilotChatAttr, GenAiAttr, GenAiOperationName } from '../../../../platform/otel/common/genAiAttributes'; -import type { ICompletedSpanData, IOTelService, ISpanEventRecord, SpanStatusCode } from '../../../../platform/otel/common/otelService'; +import { CopilotChatAttr, CopilotCliSdkAttr, GenAiAttr, GenAiOperationName } from '../../../../platform/otel/common/genAiAttributes'; +import { type ICompletedSpanData, type IOTelService, type ISpanEventRecord, SpanStatusCode } from '../../../../platform/otel/common/otelService'; /** * Hook event data stashed by copilotcliSession for bridge enrichment. @@ -160,8 +160,8 @@ export class CopilotCliBridgeSpanProcessor implements SpanProcessor { // SDK native hook spans: enrich with data from session events and // remap to execute_hook so the debug panel shows full details. - const invocationId = span.attributes['github.copilot.hook.invocation_id']; - if (span.name.startsWith('hook ') && span.attributes['github.copilot.hook.type'] && typeof invocationId === 'string') { + const invocationId = span.attributes[CopilotCliSdkAttr.HOOK_INVOCATION_ID]; + if (span.name.startsWith('hook ') && span.attributes[CopilotCliSdkAttr.HOOK_TYPE] && typeof invocationId === 'string') { const hookEndData = this._hookData.get(invocationId); if (hookEndData?.resultKind) { // hook.end data already arrived — enrich and inject immediately @@ -186,15 +186,15 @@ export class CopilotCliBridgeSpanProcessor implements SpanProcessor { const attrs = { ...span.attributes }; attrs[GenAiAttr.OPERATION_NAME] = GenAiOperationName.EXECUTE_HOOK; - attrs['copilot_chat.hook_type'] = data.hookType; + attrs[CopilotChatAttr.HOOK_TYPE] = data.hookType; if (data.input) { - attrs['copilot_chat.hook_input'] = data.input; + attrs[CopilotChatAttr.HOOK_INPUT] = data.input; } if (data.output) { - attrs['copilot_chat.hook_output'] = data.output; + attrs[CopilotChatAttr.HOOK_OUTPUT] = data.output; } if (data.resultKind) { - attrs['copilot_chat.hook_result_kind'] = data.resultKind; + attrs[CopilotChatAttr.HOOK_RESULT_KIND] = data.resultKind; } const enrichedSpan: ICompletedSpanData = { @@ -202,8 +202,8 @@ export class CopilotCliBridgeSpanProcessor implements SpanProcessor { name: `execute_hook ${data.hookType}`, attributes: attrs, status: data.resultKind === 'error' - ? { code: 2 as SpanStatusCode, message: data.errorMessage } - : { code: 1 as SpanStatusCode }, + ? { code: SpanStatusCode.ERROR, message: data.errorMessage } + : { code: SpanStatusCode.OK }, }; this._otelService.injectCompletedSpan(enrichedSpan); } diff --git a/extensions/copilot/src/extension/chatSessions/copilotcli/node/copilotcliSession.ts b/extensions/copilot/src/extension/chatSessions/copilotcli/node/copilotcliSession.ts index 7fbb1fbea9f..64344343843 100644 --- a/extensions/copilot/src/extension/chatSessions/copilotcli/node/copilotcliSession.ts +++ b/extensions/copilot/src/extension/chatSessions/copilotcli/node/copilotcliSession.ts @@ -14,7 +14,7 @@ import { ConfigKey, IConfigurationService } from '../../../../platform/configura import { PermissiveAuthRequiredError } from '../../../../platform/github/common/githubService'; import { ILogService } from '../../../../platform/log/common/logService'; import { GenAiMetrics } from '../../../../platform/otel/common/genAiMetrics'; -import { CopilotChatAttr, GenAiAttr, GenAiOperationName, IOTelService, ISpanHandle, SpanKind, SpanStatusCode, truncateForOTel, resolveWorkspaceOTelMetadata, workspaceMetadataToOTelAttributes } from '../../../../platform/otel/common/index'; +import { CopilotChatAttr, GenAiAttr, GenAiOperationName, GenAiProviderName, IOTelService, ISpanHandle, SpanKind, SpanStatusCode, truncateForOTel, resolveWorkspaceOTelMetadata, workspaceMetadataToOTelAttributes } from '../../../../platform/otel/common/index'; import { CapturingToken } from '../../../../platform/requestLogger/common/capturingToken'; import { IRequestLogger, LoggedRequestKind } from '../../../../platform/requestLogger/common/requestLogger'; import { PromptTokenCategory, PromptTokenLabel } from '../../../../platform/tokenizer/node/promptTokenDetails'; @@ -548,7 +548,7 @@ export class CopilotCLISession extends DisposableStore implements ICopilotCLISes attributes: { [GenAiAttr.OPERATION_NAME]: GenAiOperationName.INVOKE_AGENT, [GenAiAttr.AGENT_NAME]: 'copilotcli', - [GenAiAttr.PROVIDER_NAME]: 'github', + [GenAiAttr.PROVIDER_NAME]: GenAiProviderName.GITHUB, [GenAiAttr.CONVERSATION_ID]: this.sessionId, [CopilotChatAttr.SESSION_ID]: this.sessionId, [CopilotChatAttr.CHAT_SESSION_ID]: this.sessionId, diff --git a/extensions/copilot/src/extension/intents/node/toolCallingLoop.ts b/extensions/copilot/src/extension/intents/node/toolCallingLoop.ts index ff870cf2025..536fba448ee 100644 --- a/extensions/copilot/src/extension/intents/node/toolCallingLoop.ts +++ b/extensions/copilot/src/extension/intents/node/toolCallingLoop.ts @@ -770,7 +770,7 @@ export abstract class ToolCallingLoop