(
scope: CopilotOtelScope & { requestId: string }
)
| 358 | // Dashboard-column width; long enough for triage disambiguation. |
| 359 | const USER_MESSAGE_PREVIEW_MAX_CHARS = 500 |
| 360 | function buildAgentSpanAttributes( |
| 361 | scope: CopilotOtelScope & { requestId: string } |
| 362 | ): Record<string, string | number | boolean> { |
| 363 | // Gated behind the same env var as full GenAI message capture — a |
| 364 | // 500-char preview is still user prompt content. |
| 365 | const preview = isGenAIMessageCaptureEnabled() |
| 366 | ? truncateUserMessagePreview(scope.userMessagePreview) |
| 367 | : undefined |
| 368 | return { |
| 369 | [TraceAttr.GenAiAgentName]: 'mothership', |
| 370 | [TraceAttr.GenAiAgentId]: |
| 371 | scope.transport === CopilotTransport.Stream ? 'mothership-stream' : 'mothership-headless', |
| 372 | [TraceAttr.GenAiOperationName]: |
| 373 | scope.transport === CopilotTransport.Stream ? 'chat' : 'invoke_agent', |
| 374 | [TraceAttr.RequestId]: scope.requestId, |
| 375 | [TraceAttr.SimRequestId]: scope.requestId, |
| 376 | [TraceAttr.CopilotRoute]: scope.route ?? '', |
| 377 | [TraceAttr.CopilotTransport]: scope.transport, |
| 378 | ...(scope.chatId ? { [TraceAttr.ChatId]: scope.chatId } : {}), |
| 379 | ...(scope.workflowId ? { [TraceAttr.WorkflowId]: scope.workflowId } : {}), |
| 380 | ...(scope.executionId ? { [TraceAttr.CopilotExecutionId]: scope.executionId } : {}), |
| 381 | ...(scope.runId ? { [TraceAttr.RunId]: scope.runId } : {}), |
| 382 | ...(scope.streamId ? { [TraceAttr.StreamId]: scope.streamId } : {}), |
| 383 | ...(preview ? { [TraceAttr.CopilotUserMessagePreview]: preview } : {}), |
| 384 | } |
| 385 | } |
| 386 | |
| 387 | function truncateUserMessagePreview(raw: unknown): string | undefined { |
| 388 | if (typeof raw !== 'string') return undefined |
no test coverage detected