import type { Context } from '@opentelemetry/api' import { TraceAttr } from '@/lib/copilot/generated/trace-attributes-v1' import { fetchGo } from '@/lib/copilot/request/go/fetch' import { AbortReason } from '@/lib/copilot/request/session/abort' import { getMothershipBaseURL, getMothershipSourceEnvHeaders } from '@/lib/copilot/server/agent-url' import { env } from '@/lib/core/config/env' export const DEFAULT_EXPLICIT_ABORT_TIMEOUT_MS = 3000 export async function requestExplicitStreamAbort(params: { streamId: string userId: string chatId?: string workspaceId?: string timeoutMs?: number otelContext?: Context }): Promise { const { streamId, userId, chatId, workspaceId, timeoutMs = DEFAULT_EXPLICIT_ABORT_TIMEOUT_MS, otelContext, } = params const headers: Record = { 'Content-Type': 'application/json', } if (env.COPILOT_API_KEY) { headers['x-api-key'] = env.COPILOT_API_KEY } Object.assign(headers, getMothershipSourceEnvHeaders()) const controller = new AbortController() const timeout = setTimeout( () => controller.abort(AbortReason.ExplicitAbortFetchTimeout), timeoutMs ) try { const mothershipBaseURL = await getMothershipBaseURL({ userId }) const response = await fetchGo(`${mothershipBaseURL}/api/streams/explicit-abort`, { method: 'POST', headers, signal: controller.signal, body: JSON.stringify({ messageId: streamId, userId, ...(chatId ? { chatId } : {}), ...(workspaceId ? { workspaceId } : {}), }), otelContext, spanName: 'sim → go /api/streams/explicit-abort', operation: 'explicit_abort', attributes: { [TraceAttr.StreamId]: streamId, ...(chatId ? { [TraceAttr.ChatId]: chatId } : {}), }, }) if (!response.ok) { throw new Error(`Explicit abort marker request failed: ${response.status}`) } } finally { clearTimeout(timeout) } }