Feat(logs) upgrade mothership chat messages to error (#3772)

* feat(log): enable info logs in staging and prod

* Upgrade info logs to error for message route

* Add to orchestrator, remove helm shennanigans

* Fix lint

---------

Co-authored-by: Theodore Li <theo@sim.ai>
This commit is contained in:
Theodore Li
2026-03-25 15:45:17 -07:00
committed by GitHub
parent be6b00d95f
commit 9d1b9763c5
9 changed files with 44 additions and 41 deletions
+8 -8
View File
@@ -193,7 +193,7 @@ export async function POST(req: NextRequest) {
const userMessageIdToUse = userMessageId || crypto.randomUUID()
try {
logger.info(
logger.error(
appendCopilotLogContext('Received chat POST', {
requestId: tracker.requestId,
messageId: userMessageIdToUse,
@@ -250,7 +250,7 @@ export async function POST(req: NextRequest) {
actualChatId
)
agentContexts = processed
logger.info(
logger.error(
appendCopilotLogContext('Contexts processed for request', {
requestId: tracker.requestId,
messageId: userMessageIdToUse,
@@ -357,7 +357,7 @@ export async function POST(req: NextRequest) {
)
try {
logger.info(
logger.error(
appendCopilotLogContext('About to call Sim Agent', {
requestId: tracker.requestId,
messageId: userMessageIdToUse,
@@ -555,7 +555,7 @@ export async function POST(req: NextRequest) {
provider: typeof requestPayload?.provider === 'string' ? requestPayload.provider : undefined,
}
logger.info(
logger.error(
appendCopilotLogContext('Non-streaming response from orchestrator', {
requestId: tracker.requestId,
messageId: userMessageIdToUse,
@@ -600,7 +600,7 @@ export async function POST(req: NextRequest) {
// Start title generation in parallel if this is first message (non-streaming)
if (actualChatId && !currentChat.title && conversationHistory.length === 0) {
logger.info(
logger.error(
appendCopilotLogContext('Starting title generation for non-streaming response', {
requestId: tracker.requestId,
messageId: userMessageIdToUse,
@@ -616,7 +616,7 @@ export async function POST(req: NextRequest) {
updatedAt: new Date(),
})
.where(eq(copilotChats.id, actualChatId!))
logger.info(
logger.error(
appendCopilotLogContext(`Generated and saved title: ${title}`, {
requestId: tracker.requestId,
messageId: userMessageIdToUse,
@@ -645,7 +645,7 @@ export async function POST(req: NextRequest) {
.where(eq(copilotChats.id, actualChatId!))
}
logger.info(
logger.error(
appendCopilotLogContext('Returning non-streaming response', {
requestId: tracker.requestId,
messageId: userMessageIdToUse,
@@ -778,7 +778,7 @@ export async function GET(req: NextRequest) {
...(streamSnapshot ? { streamSnapshot } : {}),
}
logger.info(
logger.error(
appendCopilotLogContext(`Retrieved chat ${chatId}`, {
messageId: chat.conversationId || undefined,
})
@@ -36,7 +36,7 @@ export async function GET(request: NextRequest) {
const toParam = url.searchParams.get('to')
const toEventId = toParam ? Number(toParam) : undefined
logger.info(
logger.error(
appendCopilotLogContext('[Resume] Received resume request', {
messageId: streamId || undefined,
}),
@@ -53,7 +53,7 @@ export async function GET(request: NextRequest) {
}
const meta = (await getStreamMeta(streamId)) as StreamMeta | null
logger.info(appendCopilotLogContext('[Resume] Stream lookup', { messageId: streamId }), {
logger.error(appendCopilotLogContext('[Resume] Stream lookup', { messageId: streamId }), {
streamId,
fromEventId,
toEventId,
@@ -72,7 +72,7 @@ export async function GET(request: NextRequest) {
if (batchMode) {
const events = await readStreamEvents(streamId, fromEventId)
const filteredEvents = toEventId ? events.filter((e) => e.eventId <= toEventId) : events
logger.info(appendCopilotLogContext('[Resume] Batch response', { messageId: streamId }), {
logger.error(appendCopilotLogContext('[Resume] Batch response', { messageId: streamId }), {
streamId,
fromEventId,
toEventId,
@@ -124,7 +124,7 @@ export async function GET(request: NextRequest) {
const flushEvents = async () => {
const events = await readStreamEvents(streamId, lastEventId)
if (events.length > 0) {
logger.info(
logger.error(
appendCopilotLogContext('[Resume] Flushing events', { messageId: streamId }),
{
streamId,
+1 -1
View File
@@ -113,7 +113,7 @@ export async function POST(req: NextRequest) {
const userMessageId = providedMessageId || crypto.randomUUID()
userMessageIdForLogs = userMessageId
logger.info(
logger.error(
appendCopilotLogContext('Received mothership chat start request', {
requestId: tracker.requestId,
messageId: userMessageId,
+1 -1
View File
@@ -83,7 +83,7 @@ export async function POST(req: NextRequest) {
const chatId = parsed.chatId || crypto.randomUUID()
messageId = crypto.randomUUID()
logger.info(
logger.error(
appendCopilotLogContext('Received headless copilot chat start request', { messageId }),
{
workflowId: resolved.workflowId,
+1 -1
View File
@@ -201,7 +201,7 @@ export async function buildCopilotRequestPayload(
})
}
if (mcpTools.length > 0) {
logger.info(
logger.error(
appendCopilotLogContext('Added MCP tools to copilot payload', {
messageId: userMessageId,
}),
+4 -4
View File
@@ -440,7 +440,7 @@ export function createSSEStream(params: StreamingOrchestrationParams): ReadableS
})
if (abortController.signal.aborted) {
logger.info(
logger.error(
appendCopilotLogContext('Stream aborted by explicit stop', { requestId, messageId })
)
await eventWriter.close().catch(() => {})
@@ -456,7 +456,7 @@ export function createSSEStream(params: StreamingOrchestrationParams): ReadableS
'An unexpected error occurred while processing the response.'
if (clientDisconnected) {
logger.info(
logger.error(
appendCopilotLogContext('Stream failed after client disconnect', {
requestId,
messageId,
@@ -500,7 +500,7 @@ export function createSSEStream(params: StreamingOrchestrationParams): ReadableS
await updateRunStatus(runId, 'complete', { completedAt: new Date() }).catch(() => {})
} catch (error) {
if (abortController.signal.aborted) {
logger.info(
logger.error(
appendCopilotLogContext('Stream aborted by explicit stop', { requestId, messageId })
)
await eventWriter.close().catch(() => {})
@@ -509,7 +509,7 @@ export function createSSEStream(params: StreamingOrchestrationParams): ReadableS
return
}
if (clientDisconnected) {
logger.info(
logger.error(
appendCopilotLogContext('Stream errored after client disconnect', {
requestId,
messageId,
+12 -12
View File
@@ -135,7 +135,7 @@ export async function orchestrateCopilotStream(
let claimedToolCallIds: string[] = []
let claimedByWorkerId: string | null = null
logger.info(withLogContext('Starting copilot orchestration'), {
logger.error(withLogContext('Starting copilot orchestration'), {
goRoute,
workflowId,
workspaceId,
@@ -154,7 +154,7 @@ export async function orchestrateCopilotStream(
for (;;) {
context.streamComplete = false
logger.info(withLogContext('Starting orchestration loop iteration'), {
logger.error(withLogContext('Starting orchestration loop iteration'), {
route,
hasPendingAsyncContinuation: Boolean(context.awaitingAsyncContinuation),
claimedToolCallCount: claimedToolCallIds.length,
@@ -167,7 +167,7 @@ export async function orchestrateCopilotStream(
const d = (event.data ?? {}) as Record<string, unknown>
const response = (d.response ?? {}) as Record<string, unknown>
if (response.async_pause) {
logger.info(withLogContext('Detected async pause from copilot backend'), {
logger.error(withLogContext('Detected async pause from copilot backend'), {
route,
checkpointId:
typeof (response.async_pause as Record<string, unknown>)?.checkpointId ===
@@ -200,7 +200,7 @@ export async function orchestrateCopilotStream(
loopOptions
)
logger.info(withLogContext('Completed orchestration loop iteration'), {
logger.error(withLogContext('Completed orchestration loop iteration'), {
route,
streamComplete: context.streamComplete,
wasAborted: context.wasAborted,
@@ -209,7 +209,7 @@ export async function orchestrateCopilotStream(
})
if (claimedToolCallIds.length > 0) {
logger.info(withLogContext('Marking async tool calls as delivered'), {
logger.error(withLogContext('Marking async tool calls as delivered'), {
toolCallIds: claimedToolCallIds,
})
await Promise.all(
@@ -222,7 +222,7 @@ export async function orchestrateCopilotStream(
}
if (options.abortSignal?.aborted || context.wasAborted) {
logger.info(withLogContext('Stopping orchestration because request was aborted'), {
logger.error(withLogContext('Stopping orchestration because request was aborted'), {
pendingToolCallCount: Array.from(context.toolCalls.values()).filter(
(toolCall) => toolCall.status === 'pending' || toolCall.status === 'executing'
).length,
@@ -240,13 +240,13 @@ export async function orchestrateCopilotStream(
const continuation = context.awaitingAsyncContinuation
if (!continuation) {
logger.info(withLogContext('No async continuation pending; finishing orchestration'))
logger.error(withLogContext('No async continuation pending; finishing orchestration'))
break
}
let resumeReady = false
let resumeRetries = 0
logger.info(withLogContext('Processing async continuation'), {
logger.error(withLogContext('Processing async continuation'), {
checkpointId: continuation.checkpointId,
runId: continuation.runId,
pendingToolCallIds: continuation.pendingToolCallIds,
@@ -442,7 +442,7 @@ export async function orchestrateCopilotStream(
}
if (resumeRetries < 3) {
resumeRetries++
logger.info(withLogContext('Retrying async resume after claim contention'), {
logger.error(withLogContext('Retrying async resume after claim contention'), {
checkpointId: continuation.checkpointId,
runId: continuation.runId,
workerId: resumeWorkerId,
@@ -473,7 +473,7 @@ export async function orchestrateCopilotStream(
]
claimedByWorkerId = claimedToolCallIds.length > 0 ? resumeWorkerId : null
logger.info(withLogContext('Resuming async tool continuation'), {
logger.error(withLogContext('Resuming async tool continuation'), {
checkpointId: continuation.checkpointId,
runId: continuation.runId,
workerId: resumeWorkerId,
@@ -539,7 +539,7 @@ export async function orchestrateCopilotStream(
checkpointId: continuation.checkpointId,
results,
}
logger.info(withLogContext('Prepared async continuation payload for resume endpoint'), {
logger.error(withLogContext('Prepared async continuation payload for resume endpoint'), {
route,
checkpointId: continuation.checkpointId,
resultCount: results.length,
@@ -568,7 +568,7 @@ export async function orchestrateCopilotStream(
usage: context.usage,
cost: context.cost,
}
logger.info(withLogContext('Completing copilot orchestration'), {
logger.error(withLogContext('Completing copilot orchestration'), {
success: result.success,
chatId: result.chatId,
hasRequestId: Boolean(result.requestId),
@@ -309,7 +309,7 @@ export const sseHandlers: Record<string, SSEHandler> = {
const rid = typeof event.data === 'string' ? event.data : undefined
if (rid) {
context.requestId = rid
logger.info(
logger.error(
appendCopilotLogContext('Mapped copilot message to Go trace ID', {
messageId: context.messageId,
}),
@@ -187,7 +187,7 @@ async function maybeWriteOutputToFile(
contentType
)
logger.info(
logger.error(
appendCopilotLogContext('Tool output written to file', { messageId: context.messageId }),
{
toolName,
@@ -397,7 +397,7 @@ async function maybeWriteOutputToTable(
}
})
logger.info(
logger.error(
appendCopilotLogContext('Tool output written to table', { messageId: context.messageId }),
{
toolName,
@@ -524,7 +524,7 @@ async function maybeWriteReadCsvToTable(
}
})
logger.info(
logger.error(
appendCopilotLogContext('Read output written to table', { messageId: context.messageId }),
{
toolName,
@@ -595,11 +595,14 @@ export async function executeToolAndReport(
toolCall.status = 'executing'
await markAsyncToolRunning(toolCall.id, 'sim-stream').catch(() => {})
logger.info(appendCopilotLogContext('Tool execution started', { messageId: context.messageId }), {
toolCallId: toolCall.id,
toolName: toolCall.name,
params: toolCall.params,
})
logger.error(
appendCopilotLogContext('Tool execution started', { messageId: context.messageId }),
{
toolCallId: toolCall.id,
toolName: toolCall.name,
params: toolCall.params,
}
)
try {
let result = await executeToolServerSide(toolCall, execContext)
@@ -686,7 +689,7 @@ export async function executeToolAndReport(
: raw && typeof raw === 'object'
? JSON.stringify(raw).slice(0, 200)
: undefined
logger.info(
logger.error(
appendCopilotLogContext('Tool execution succeeded', { messageId: context.messageId }),
{
toolCallId: toolCall.id,