@evalops/maestro 0.10.31 → 0.10.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/transport/tool-execution.d.ts +1 -0
- package/dist/agent/transport/tool-execution.d.ts.map +1 -1
- package/dist/agent/transport/tool-execution.js +23 -3
- package/dist/agent/transport/tool-execution.js.map +1 -1
- package/dist/agent/transport/tool-phase-summary.d.ts +6 -0
- package/dist/agent/transport/tool-phase-summary.d.ts.map +1 -0
- package/dist/agent/transport/tool-phase-summary.js +99 -0
- package/dist/agent/transport/tool-phase-summary.js.map +1 -0
- package/dist/agent/transport/tool-safety-pipeline.d.ts +1 -0
- package/dist/agent/transport/tool-safety-pipeline.d.ts.map +1 -1
- package/dist/agent/transport/tool-safety-pipeline.js +9 -4
- package/dist/agent/transport/tool-safety-pipeline.js.map +1 -1
- package/dist/agent/transport.d.ts.map +1 -1
- package/dist/agent/transport.js +4 -99
- package/dist/agent/transport.js.map +1 -1
- package/dist/cli/commands/a2a/args.d.ts +13 -0
- package/dist/cli/commands/a2a/args.d.ts.map +1 -0
- package/dist/cli/commands/a2a/args.js +327 -0
- package/dist/cli/commands/a2a/args.js.map +1 -0
- package/dist/cli/commands/a2a/discovery.d.ts +40 -0
- package/dist/cli/commands/a2a/discovery.d.ts.map +1 -0
- package/dist/cli/commands/a2a/discovery.js +150 -0
- package/dist/cli/commands/a2a/discovery.js.map +1 -0
- package/dist/cli/commands/a2a.d.ts +2 -5
- package/dist/cli/commands/a2a.d.ts.map +1 -1
- package/dist/cli/commands/a2a.js +4 -474
- package/dist/cli/commands/a2a.js.map +1 -1
- package/dist/cli.js +1801 -1528
- package/dist/node_modules/@evalops/contracts/package.json +1 -1
- package/dist/node_modules/@evalops/tui/package.json +1 -1
- package/dist/server/app-context.d.ts +7 -0
- package/dist/server/app-context.d.ts.map +1 -1
- package/dist/server/app-context.js.map +1 -1
- package/dist/server/handlers/chat-ws.d.ts.map +1 -1
- package/dist/server/handlers/chat-ws.js +42 -24
- package/dist/server/handlers/chat-ws.js.map +1 -1
- package/dist/server/handlers/chat.d.ts.map +1 -1
- package/dist/server/handlers/chat.js +54 -35
- package/dist/server/handlers/chat.js.map +1 -1
- package/dist/server/handlers/hosted-runner-identity.d.ts +17 -0
- package/dist/server/handlers/hosted-runner-identity.d.ts.map +1 -1
- package/dist/server/handlers/hosted-runner-identity.js +7 -0
- package/dist/server/handlers/hosted-runner-identity.js.map +1 -1
- package/dist/server/handlers/platform-a2a-push.d.ts.map +1 -1
- package/dist/server/handlers/platform-a2a-push.js +134 -15
- package/dist/server/handlers/platform-a2a-push.js.map +1 -1
- package/dist/server/server-utils.d.ts.map +1 -1
- package/dist/server/server-utils.js +12 -0
- package/dist/server/server-utils.js.map +1 -1
- package/dist/server/session-timeline.d.ts.map +1 -1
- package/dist/server/session-timeline.js +13 -0
- package/dist/server/session-timeline.js.map +1 -1
- package/dist/telemetry/maestro-event-catalog.d.ts +30 -0
- package/dist/telemetry/maestro-event-catalog.d.ts.map +1 -1
- package/dist/telemetry/maestro-event-catalog.js +96 -5
- package/dist/telemetry/maestro-event-catalog.js.map +1 -1
- package/dist/tools/find.d.ts +2 -0
- package/dist/tools/find.d.ts.map +1 -1
- package/dist/tools/find.js +25 -12
- package/dist/tools/find.js.map +1 -1
- package/dist/version.json +2 -2
- package/package.json +6 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat.js","sourceRoot":"","sources":["../../../src/server/handlers/chat.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Chat Handler - Main WebSocket/SSE Endpoint for Agent Conversations\n *\n * This module implements the primary chat endpoint for the web server.\n * It handles incoming chat requests, manages agent execution, and streams\n * responses back to clients via Server-Sent Events (SSE).\n *\n * Request flow:\n * 1. Parse and validate incoming JSON request\n * 2. Acquire SSE connection slot (rate limited)\n * 3. Create or resume session based on sessionId\n * 4. Initialize agent with model and approval settings\n * 5. Hydrate conversation history from request\n * 6. Stream agent events to client via SSE\n * 7. Persist session state on completion\n *\n * Key features:\n * - Circuit breaker protection for agent calls\n * - Graceful handling of client disconnects\n * - Session persistence with auto-initialization\n * - Approval mode configuration via headers\n */\n\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\nimport type { ComposerChatRequest, ComposerMessage } from \"@evalops/contracts\";\nimport { isAssistantMessage } from \"../../agent/type-guards.js\";\nimport type {\n\tAttachment as AgentAttachment,\n\tAgentEvent,\n} from \"../../agent/types.js\";\nimport { runUserPromptWithRecovery } from \"../../agent/user-prompt-runtime.js\";\nimport { dispatchAgentNotification } from \"../../hooks/notification-hooks.js\";\nimport { createSessionHookService } from \"../../hooks/session-integration.js\";\nimport { withMcpPostKeepMessages } from \"../../mcp/prompt-recovery.js\";\nimport {\n\tcreateAutomaticMemoryConsolidationCoordinator,\n\tgetMemoryConsolidationSystemPrompt,\n} from \"../../memory/auto-consolidation.js\";\nimport { createAutomaticMemoryExtractionCoordinator } from \"../../memory/auto-extraction.js\";\nimport type { RegisteredModel } from \"../../models/registry.js\";\nimport {\n\trecordComplianceAssistantAction,\n\trecordComplianceToolAction,\n} from \"../../services/compliance/recorder.js\";\nimport {\n\trecordIntelligentRouterChatMetric,\n\tselectIntelligentRouterModel,\n} from \"../../services/intelligent-router/recorder.js\";\nimport { recordAssistantUsageMetric } from \"../../services/usage-analytics/recorder.js\";\nimport { evaluateModelPolicy } from \"../../services/workspace-config/policy.js\";\nimport { toSessionModelMetadata } from \"../../session/manager.js\";\nimport { createRuntimeSessionSummaryUpdater } from \"../../session/runtime-summary-updater.js\";\nimport { recordSseSkip } from \"../../telemetry.js\";\nimport { createLogger } from \"../../utils/logger.js\";\nimport type { WebServerContext } from \"../app-context.js\";\nimport {\n\tnormalizeApprovalMode,\n\tresolveApprovalModeForRequest,\n} from \"../approval-mode-store.js\";\nimport { WebActionApprovalService } from \"../approval-service.js\";\nimport { publishArtifactUpdate } from \"../artifacts-live-reload.js\";\nimport { getAuthSubject } from \"../authz.js\";\nimport { getAgentCircuitBreaker } from \"../circuit-breaker.js\";\nimport { clientToolService } from \"../client-tools-service.js\";\nimport { isHostedSessionManager } from \"../hosted-session-manager.js\";\nimport { getWorkspaceConfigContext } from \"../request-context.js\";\nimport { serverRequestManager } from \"../server-request-manager.js\";\nimport {\n\tApiError,\n\tgetRequestHeader,\n\trespondWithApiError,\n\tsendJson,\n} from \"../server-utils.js\";\nimport { startSessionWithPolicy } from \"../session-initialization.js\";\nimport { createWebSessionManagerForRequest } from \"../session-scope.js\";\nimport { convertComposerMessagesToApp } from \"../session-serialization.js\";\nimport { SseSession, sendSSE, sendSessionUpdate } from \"../sse-session.js\";\nimport { ServerRequestToolRetryService } from \"../tool-retry-service.js\";\nimport {\n\ttype ChatRequestInput,\n\tChatRequestSchema,\n\tparseAndValidateJson,\n} from \"../validation.js\";\n\nconst logger = createLogger(\"web:chat\");\n\nfunction getComposerTextContent(content: ComposerMessage[\"content\"]): string {\n\tif (typeof content === \"string\") return content;\n\tif (!Array.isArray(content)) return \"\";\n\treturn content\n\t\t.filter((block) => block.type === \"text\")\n\t\t.map((block) => block.text)\n\t\t.join(\"\");\n}\n\n/**\n * Handle an incoming chat request.\n *\n * This is the main entry point for chat interactions. It:\n * 1. Validates the request format\n * 2. Sets up SSE streaming\n * 3. Runs the agent with the user's message\n * 4. Streams events back to the client\n * 5. Persists the session state\n *\n * @param req - The incoming HTTP request\n * @param res - The HTTP response (will be converted to SSE stream)\n * @param context - Server context with agent factory and configuration\n */\nexport async function handleChat(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tcontext: WebServerContext,\n) {\n\t// Destructure context for cleaner code\n\tconst {\n\t\tcreateAgent,\n\t\tcreateBackgroundAgent,\n\t\tgetRegisteredModel,\n\t\tdefaultApprovalMode,\n\t\tacquireSse,\n\t\treleaseSse,\n\t\tcorsHeaders: cors,\n\t} = context;\n\n\t// Track SSE lease for cleanup in finally block\n\tlet sseLease: symbol | null = null;\n\n\ttry {\n\t\t// ===== Phase 1: Request Validation =====\n\t\tconst chatReq = (await parseAndValidateJson<ChatRequestInput>(\n\t\t\treq,\n\t\t\tChatRequestSchema,\n\t\t)) as ComposerChatRequest;\n\n\t\t// Validate message array exists and is non-empty\n\t\tconst incomingMessages = Array.isArray(chatReq.messages)\n\t\t\t? (chatReq.messages as ComposerMessage[])\n\t\t\t: [];\n\t\tif (incomingMessages.length === 0) {\n\t\t\tsendJson(res, 400, { error: \"No messages supplied\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\t// The last message must be the user's current input\n\t\tconst latestMessage = incomingMessages[incomingMessages.length - 1];\n\t\tif (!latestMessage || latestMessage.role !== \"user\") {\n\t\t\tsendJson(\n\t\t\t\tres,\n\t\t\t\t400,\n\t\t\t\t{ error: \"Last message must be a user message\" },\n\t\t\t\tcors,\n\t\t\t\treq,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tconst { attachmentsToSend, attachmentError } = (() => {\n\t\t\tconst MAX_ATTACHMENT_BYTES = 8 * 1024 * 1024;\n\t\t\tconst MAX_TOTAL_BYTES = 20 * 1024 * 1024;\n\n\t\t\tconst raw = latestMessage.attachments;\n\t\t\tif (!Array.isArray(raw) || raw.length === 0) {\n\t\t\t\treturn {\n\t\t\t\t\tattachmentsToSend: undefined as AgentAttachment[] | undefined,\n\t\t\t\t\tattachmentError: null as string | null,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst attachments: AgentAttachment[] = [];\n\t\t\tlet totalBytes = 0;\n\n\t\t\tfor (const item of raw) {\n\t\t\t\tif (!item || typeof item !== \"object\") continue;\n\t\t\t\tconst id = typeof item.id === \"string\" ? item.id : \"\";\n\t\t\t\tconst type =\n\t\t\t\t\titem.type === \"image\" || item.type === \"document\" ? item.type : null;\n\t\t\t\tconst fileName =\n\t\t\t\t\ttypeof item.fileName === \"string\" ? item.fileName : \"attachment\";\n\t\t\t\tconst mimeType =\n\t\t\t\t\ttypeof item.mimeType === \"string\"\n\t\t\t\t\t\t? item.mimeType\n\t\t\t\t\t\t: \"application/octet-stream\";\n\t\t\t\tconst size =\n\t\t\t\t\ttypeof item.size === \"number\" && Number.isFinite(item.size)\n\t\t\t\t\t\t? item.size\n\t\t\t\t\t\t: 0;\n\t\t\t\tconst content = typeof item.content === \"string\" ? item.content : \"\";\n\t\t\t\tconst extractedText =\n\t\t\t\t\ttypeof item.extractedText === \"string\"\n\t\t\t\t\t\t? item.extractedText\n\t\t\t\t\t\t: undefined;\n\t\t\t\tconst preview =\n\t\t\t\t\ttypeof item.preview === \"string\" ? item.preview : undefined;\n\n\t\t\t\tif (!id || !type) continue;\n\t\t\t\tif (!content) {\n\t\t\t\t\t// Content omitted (e.g., session fetch); keep metadata for UI but do not send to model.\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Base64 -> bytes (approx). Prefer validating against actual content length.\n\t\t\t\tconst approxBytes = Math.floor((content.length * 3) / 4);\n\t\t\t\tconst bytes = approxBytes > 0 ? approxBytes : size;\n\n\t\t\t\tif (bytes > MAX_ATTACHMENT_BYTES) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tattachmentsToSend: undefined,\n\t\t\t\t\t\tattachmentError: `Attachment too large: ${fileName} (${Math.ceil(bytes / 1024 / 1024)}MB). Max per file is ${Math.ceil(MAX_ATTACHMENT_BYTES / 1024 / 1024)}MB.`,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\ttotalBytes += bytes;\n\t\t\t\tif (totalBytes > MAX_TOTAL_BYTES) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tattachmentsToSend: undefined,\n\t\t\t\t\t\tattachmentError: `Attachments too large: total exceeds ${Math.ceil(MAX_TOTAL_BYTES / 1024 / 1024)}MB.`,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tattachments.push({\n\t\t\t\t\tid,\n\t\t\t\t\ttype,\n\t\t\t\t\tfileName,\n\t\t\t\t\tmimeType,\n\t\t\t\t\tsize: size || bytes,\n\t\t\t\t\tcontent,\n\t\t\t\t\textractedText,\n\t\t\t\t\tpreview,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tattachmentsToSend: attachments.length ? attachments : undefined,\n\t\t\t\tattachmentError: null,\n\t\t\t};\n\t\t})();\n\n\t\tif (attachmentError) {\n\t\t\tsendJson(res, 413, { error: attachmentError }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst userInput = getComposerTextContent(latestMessage.content).trim();\n\t\tif (!userInput && !attachmentsToSend) {\n\t\t\tsendJson(res, 400, { error: \"User message cannot be empty\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\t// ===== Phase 2: SSE Connection Management =====\n\t\t// Acquire a lease to limit concurrent SSE connections\n\t\tif (acquireSse) {\n\t\t\tsseLease = acquireSse();\n\t\t\tif (!sseLease) {\n\t\t\t\tsendJson(\n\t\t\t\t\tres,\n\t\t\t\t\t429,\n\t\t\t\t\t{ error: \"Too many active SSE connections\" },\n\t\t\t\t\tcors,\n\t\t\t\t\treq,\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// ===== Phase 3: Session and Agent Setup =====\n\t\t// Create session manager (false = don't auto-initialize from disk)\n\t\tconst sessionManager = createWebSessionManagerForRequest(req, false);\n\t\tconst subject = getAuthSubject(req);\n\n\t\t// Resume existing session if sessionId provided\n\t\tlet existingSessionLoaded = false;\n\t\tif (chatReq.sessionId) {\n\t\t\tif (isHostedSessionManager(sessionManager)) {\n\t\t\t\texistingSessionLoaded = await sessionManager.resumeSession(\n\t\t\t\t\tchatReq.sessionId,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tconst sessionFile = sessionManager.getSessionFileById(\n\t\t\t\t\tchatReq.sessionId,\n\t\t\t\t);\n\t\t\t\tif (sessionFile) {\n\t\t\t\t\tsessionManager.setSessionFile(sessionFile);\n\t\t\t\t\texistingSessionLoaded = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Resolve model from registry through the intelligent router. With no history,\n\t\t// this preserves the caller's requested model; with enough data or overrides,\n\t\t// it can select a better-scoring model and expose explicit fallbacks.\n\t\tconst routingSelection = selectIntelligentRouterModel({\n\t\t\treq,\n\t\t\trequestedModel: chatReq.model,\n\t\t\tbody: chatReq,\n\t\t});\n\t\tlet registeredModel: RegisteredModel | undefined;\n\t\tlet lastModelError: unknown;\n\t\tlet selectedModelError: unknown;\n\t\tlet selectedModelPolicyViolation: ReturnType<\n\t\t\ttypeof evaluateModelPolicy\n\t\t> | null = null;\n\t\tfor (const [index, modelInput] of routingSelection.modelInputs.entries()) {\n\t\t\ttry {\n\t\t\t\tconst candidateModel = await getRegisteredModel(modelInput);\n\t\t\t\tconst violation = evaluateModelPolicy(\n\t\t\t\t\tgetWorkspaceConfigContext()?.config,\n\t\t\t\t\t{\n\t\t\t\t\t\tprovider: candidateModel.provider,\n\t\t\t\t\t\tmodelId: candidateModel.id,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tif (violation) {\n\t\t\t\t\tif (index === 0) {\n\t\t\t\t\t\tselectedModelPolicyViolation = violation;\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tregisteredModel = candidateModel;\n\t\t\t\tbreak;\n\t\t\t} catch (error) {\n\t\t\t\tlastModelError = error;\n\t\t\t\tif (index === 0) {\n\t\t\t\t\tselectedModelError = error;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (!registeredModel && selectedModelPolicyViolation) {\n\t\t\tsendJson(\n\t\t\t\tres,\n\t\t\t\t403,\n\t\t\t\t{\n\t\t\t\t\terror: selectedModelPolicyViolation.message,\n\t\t\t\t\tcode: selectedModelPolicyViolation.code,\n\t\t\t\t\tworkspaceId: selectedModelPolicyViolation.workspaceId,\n\t\t\t\t},\n\t\t\t\tcors,\n\t\t\t\treq,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tif (!registeredModel) {\n\t\t\tthrow selectedModelError ?? lastModelError;\n\t\t}\n\t\tconst routeStartedAt = Date.now();\n\n\t\t// Parse approval mode from request header (allows per-request override)\n\t\tconst headerApproval = normalizeApprovalMode(\n\t\t\tgetRequestHeader(\n\t\t\t\treq,\n\t\t\t\t\"x-composer-approval-mode\",\n\t\t\t\t\"x-maestro-approval-mode\",\n\t\t\t) ?? undefined,\n\t\t);\n\n\t\tconst effectiveApproval = resolveApprovalModeForRequest({\n\t\t\tsessionId: chatReq.sessionId,\n\t\t\tsubject,\n\t\t\theaderApprovalMode: headerApproval,\n\t\t\tdefaultApprovalMode,\n\t\t});\n\n\t\t// Create the agent with the resolved configuration\n\t\tconst clientToolsHeader =\n\t\t\tgetRequestHeader(\n\t\t\t\treq,\n\t\t\t\t\"x-composer-client-tools\",\n\t\t\t\t\"x-maestro-client-tools\",\n\t\t\t) === \"1\";\n\n\t\tconst clientHeader = getRequestHeader(\n\t\t\treq,\n\t\t\t\"x-composer-client\",\n\t\t\t\"x-maestro-client\",\n\t\t)?.toLowerCase();\n\t\tconst sessionIdProvider = () => sessionManager.getSessionId() ?? undefined;\n\t\tconst requestApprovalService = new WebActionApprovalService(\n\t\t\teffectiveApproval,\n\t\t\tsessionIdProvider,\n\t\t);\n\t\tconst toolRetryService = new ServerRequestToolRetryService(\n\t\t\t\"prompt\",\n\t\t\tsessionIdProvider,\n\t\t);\n\n\t\tconst agent = await createAgent(\n\t\t\tregisteredModel,\n\t\t\tchatReq.thinkingLevel || \"off\",\n\t\t\teffectiveApproval,\n\t\t\t{\n\t\t\t\tapprovalService: requestApprovalService,\n\t\t\t\ttoolRetryService,\n\t\t\t\t...(clientToolsHeader\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tenableClientTools: true,\n\t\t\t\t\t\t\tclientToolService:\n\t\t\t\t\t\t\t\tclientToolService.forSession(sessionIdProvider),\n\t\t\t\t\t\t\tincludeVscodeTools: clientHeader === \"vscode\",\n\t\t\t\t\t\t\tincludeJetBrainsTools: clientHeader === \"jetbrains\",\n\t\t\t\t\t\t\tincludeConductorTools: clientHeader === \"conductor\",\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t);\n\n\t\t// Hydrate conversation history (all messages except the current user input)\n\t\tconst historyMessages = incomingMessages.slice(0, -1);\n\t\tconst hydratedHistory = convertComposerMessagesToApp(\n\t\t\thistoryMessages,\n\t\t\tregisteredModel,\n\t\t);\n\t\tif (hydratedHistory.length > 0) {\n\t\t\tagent.replaceMessages(hydratedHistory);\n\t\t} else {\n\t\t\tagent.clearMessages();\n\t\t}\n\n\t\t// ===== Phase 4: SSE Stream Setup =====\n\t\t// Initialize the SSE response headers\n\t\tres.writeHead(200, {\n\t\t\t\"Content-Type\": \"text/event-stream\",\n\t\t\t\"Cache-Control\": \"no-cache\",\n\t\t\tConnection: \"keep-alive\",\n\t\t\t...cors,\n\t\t});\n\n\t\t// Create SSE session with telemetry callback for skip tracking\n\t\tconst requestId = Math.random().toString(36).slice(2);\n\t\tconst modelKey = `${registeredModel.provider}/${registeredModel.id}`;\n\t\tconst sseSession = new SseSession(\n\t\t\tres,\n\t\t\t(metrics) => {\n\t\t\t\t// Record telemetry when SSE writes are skipped (client disconnected)\n\t\t\t\trecordSseSkip(metrics.sent, metrics.skipped, {\n\t\t\t\t\trequestId: metrics.context?.requestId,\n\t\t\t\t\tmodelKey: metrics.context?.modelKey,\n\t\t\t\t\tsessionId: metrics.context?.sessionId,\n\t\t\t\t\tlastError:\n\t\t\t\t\t\tmetrics.lastError instanceof Error\n\t\t\t\t\t\t\t? metrics.lastError.message\n\t\t\t\t\t\t\t: metrics.lastError,\n\t\t\t\t});\n\t\t\t},\n\t\t\t{ requestId, modelKey },\n\t\t);\n\t\tsseSession.startHeartbeat(); // Keep connection alive during idle periods\n\n\t\t// Track cleanup state to prevent double-cleanup\n\t\tlet cleanedUp = false;\n\n\t\t// ===== Phase 5: Agent Event Subscription =====\n\t\t// Subscribe to agent events and forward them to the SSE stream\n\t\t// Pre-load enterprise context for session tracking\n\t\tconst { enterpriseContext } = await import(\"../../enterprise/context.js\");\n\n\t\tconst initializeSessionIfNeeded = async (): Promise<string | null> => {\n\t\t\tif (existingSessionLoaded || sessionManager.isInitialized()) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst initializationError = await startSessionWithPolicy({\n\t\t\t\tagent,\n\t\t\t\tenterpriseContext,\n\t\t\t\tlogger,\n\t\t\t\tmodelId: registeredModel.id,\n\t\t\t\tonSessionReady: (sessionId) => {\n\t\t\t\t\tsendSessionUpdate(sseSession, sessionId);\n\t\t\t\t\tsseSession.setContext({ sessionId });\n\t\t\t\t},\n\t\t\t\tsessionManager,\n\t\t\t\tsubject,\n\t\t\t});\n\t\t\tif (initializationError) {\n\t\t\t\treturn initializationError;\n\t\t\t}\n\t\t\texistingSessionLoaded = true;\n\t\t\treturn null;\n\t\t};\n\n\t\tconst initializationError = await initializeSessionIfNeeded();\n\t\tif (initializationError) {\n\t\t\tsendSSE(sseSession, {\n\t\t\t\ttype: \"error\",\n\t\t\t\tmessage: `[Policy] ${initializationError}`,\n\t\t\t});\n\t\t\tsseSession.end();\n\t\t\tif (sseLease && releaseSse) {\n\t\t\t\treleaseSse(sseLease);\n\t\t\t\tsseLease = null;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst toolArgsByCallId = new Map<string, Record<string, unknown>>();\n\t\tconst storeToolArgs = (toolCallId: string, args: unknown) => {\n\t\t\ttoolArgsByCallId.set(\n\t\t\t\ttoolCallId,\n\t\t\t\t(args && typeof args === \"object\" && !Array.isArray(args)\n\t\t\t\t\t? (args as Record<string, unknown>)\n\t\t\t\t\t: {}) as Record<string, unknown>,\n\t\t\t);\n\t\t};\n\t\tconst slimValue = getRequestHeader(\n\t\t\treq,\n\t\t\t\"x-composer-slim-events\",\n\t\t\t\"x-maestro-slim-events\",\n\t\t);\n\t\tconst slimEvents = slimValue === \"1\" || slimValue === \"true\";\n\t\tconst slimToolCallArgsLimit = (() => {\n\t\t\tconst raw = process.env.MAESTRO_SLIM_TOOLCALL_ARGS_MAX_BYTES;\n\t\t\tif (!raw) return 4096;\n\t\t\tconst parsed = Number(raw);\n\t\t\tif (!Number.isFinite(parsed) || parsed <= 0) return 4096;\n\t\t\treturn Math.min(parsed, 1024 * 1024);\n\t\t})();\n\t\tconst extractToolCallInfo = (assistantEvent: {\n\t\t\tcontentIndex?: number;\n\t\t\tpartial?: { content?: unknown[] };\n\t\t}): {\n\t\t\ttoolCallId?: string;\n\t\t\ttoolCallName?: string;\n\t\t\ttoolCallArgs?: Record<string, unknown>;\n\t\t\ttoolCallArgsTruncated?: boolean;\n\t\t} => {\n\t\t\tconst assistantMessageEvent = assistantEvent.partial;\n\t\t\tconst contentIndex = assistantEvent.contentIndex;\n\t\t\tif (\n\t\t\t\t!assistantMessageEvent ||\n\t\t\t\ttypeof contentIndex !== \"number\" ||\n\t\t\t\t!Array.isArray(assistantMessageEvent.content)\n\t\t\t) {\n\t\t\t\treturn {};\n\t\t\t}\n\t\t\tconst block = assistantMessageEvent.content[contentIndex];\n\t\t\tif (!block || typeof block !== \"object\") {\n\t\t\t\treturn {};\n\t\t\t}\n\t\t\tconst maybeToolCall = block as {\n\t\t\t\ttype?: string;\n\t\t\t\tid?: string;\n\t\t\t\tname?: string;\n\t\t\t\targuments?: Record<string, unknown>;\n\t\t\t};\n\t\t\tif (maybeToolCall.type !== \"toolCall\") {\n\t\t\t\treturn {};\n\t\t\t}\n\t\t\tconst maybeArgs = maybeToolCall.arguments;\n\t\t\tconst toolCallArgs =\n\t\t\t\tmaybeArgs && typeof maybeArgs === \"object\" && !Array.isArray(maybeArgs)\n\t\t\t\t\t? maybeArgs\n\t\t\t\t\t: undefined;\n\t\t\tif (toolCallArgs) {\n\t\t\t\ttry {\n\t\t\t\t\tconst size = Buffer.byteLength(JSON.stringify(toolCallArgs), \"utf8\");\n\t\t\t\t\tif (size > slimToolCallArgsLimit) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttoolCallId: maybeToolCall.id,\n\t\t\t\t\t\t\ttoolCallName: maybeToolCall.name,\n\t\t\t\t\t\t\ttoolCallArgsTruncated: true,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttoolCallId: maybeToolCall.id,\n\t\t\t\t\t\ttoolCallName: maybeToolCall.name,\n\t\t\t\t\t\ttoolCallArgsTruncated: true,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn {\n\t\t\t\ttoolCallId: maybeToolCall.id,\n\t\t\t\ttoolCallName: maybeToolCall.name,\n\t\t\t\ttoolCallArgs,\n\t\t\t};\n\t\t};\n\t\tconst maybeSlimEvent = (event: AgentEvent): AgentEvent => {\n\t\t\tif (!slimEvents || event.type !== \"message_update\") {\n\t\t\t\treturn event;\n\t\t\t}\n\n\t\t\tconst assistantEvent = event.assistantMessageEvent;\n\t\t\tconst slimEvent: Record<string, unknown> = { ...event };\n\t\t\tdelete slimEvent.message;\n\n\t\t\tif (!assistantEvent) {\n\t\t\t\treturn slimEvent as AgentEvent;\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tassistantEvent.type === \"text_delta\" ||\n\t\t\t\tassistantEvent.type === \"thinking_delta\"\n\t\t\t) {\n\t\t\t\tconst { partial, ...assistantWithoutPartial } = assistantEvent as {\n\t\t\t\t\tpartial?: unknown;\n\t\t\t\t\t[key: string]: unknown;\n\t\t\t\t};\n\n\t\t\t\tslimEvent.assistantMessageEvent = assistantWithoutPartial;\n\t\t\t\treturn slimEvent as AgentEvent;\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tassistantEvent.type === \"toolcall_start\" ||\n\t\t\t\tassistantEvent.type === \"toolcall_delta\" ||\n\t\t\t\tassistantEvent.type === \"toolcall_end\"\n\t\t\t) {\n\t\t\t\tconst { partial, ...assistantWithoutPartial } = assistantEvent as {\n\t\t\t\t\tpartial?: unknown;\n\t\t\t\t\t[key: string]: unknown;\n\t\t\t\t};\n\t\t\t\tconst toolCallInfo =\n\t\t\t\t\tassistantEvent.type === \"toolcall_end\"\n\t\t\t\t\t\t? {}\n\t\t\t\t\t\t: extractToolCallInfo(assistantEvent);\n\n\t\t\t\tslimEvent.assistantMessageEvent = {\n\t\t\t\t\t...assistantWithoutPartial,\n\t\t\t\t\t...toolCallInfo,\n\t\t\t\t};\n\t\t\t\treturn slimEvent as AgentEvent;\n\t\t\t}\n\n\t\t\tslimEvent.assistantMessageEvent = assistantEvent;\n\t\t\treturn slimEvent as AgentEvent;\n\t\t};\n\t\tconst updateSessionSummary =\n\t\t\tcreateRuntimeSessionSummaryUpdater(sessionManager);\n\t\tconst automaticMemoryConsolidation =\n\t\t\tcreateAutomaticMemoryConsolidationCoordinator({\n\t\t\t\tcreateAgent: async () =>\n\t\t\t\t\tcreateBackgroundAgent(agent.state.model as RegisteredModel, {\n\t\t\t\t\t\tsystemPrompt: getMemoryConsolidationSystemPrompt(),\n\t\t\t\t\t}),\n\t\t\t\tgetModel: () => agent.state.model,\n\t\t\t});\n\t\tconst automaticMemoryExtraction =\n\t\t\tcreateAutomaticMemoryExtractionCoordinator({\n\t\t\t\tcreateAgent: async () =>\n\t\t\t\t\tcreateBackgroundAgent(agent.state.model as RegisteredModel),\n\t\t\t\tgetModel: () => agent.state.model,\n\t\t\t\tonProcessed: () => automaticMemoryConsolidation.schedule(),\n\t\t\t\tsessionManager,\n\t\t\t});\n\t\tconst sessionHookService = createSessionHookService({\n\t\t\tcwd: process.cwd(),\n\t\t\tsessionId: sessionManager.getSessionId(),\n\t\t});\n\t\tconst unsubscribeMcpElicitationBridge = serverRequestManager.subscribe(\n\t\t\t(event) => {\n\t\t\t\tconst activeSessionId = sessionIdProvider();\n\t\t\t\tif (!activeSessionId || event.request.sessionId !== activeSessionId) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (event.request.kind !== \"mcp_elicitation\") {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (event.type === \"registered\") {\n\t\t\t\t\tsendSSE(sseSession, {\n\t\t\t\t\t\ttype: \"client_tool_request\",\n\t\t\t\t\t\ttoolCallId: event.request.callId,\n\t\t\t\t\t\ttoolName: event.request.toolName,\n\t\t\t\t\t\targs: event.request.args,\n\t\t\t\t\t});\n\t\t\t\t\tstoreToolArgs(event.request.callId, event.request.args);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\ttoolArgsByCallId.delete(event.request.callId);\n\t\t\t},\n\t\t);\n\n\t\tconst unsubscribe = agent.subscribe((event: AgentEvent) => {\n\t\t\tupdateSessionSummary(event);\n\n\t\t\t// Forward event to client\n\t\t\tsendSSE(sseSession, maybeSlimEvent(event));\n\n\t\t\t// Track tool args for later event correlation (used by artifact live reload)\n\t\t\tif (event.type === \"tool_execution_start\") {\n\t\t\t\tstoreToolArgs(event.toolCallId, event.args);\n\t\t\t}\n\t\t\tif (event.type === \"client_tool_request\") {\n\t\t\t\tstoreToolArgs(event.toolCallId, event.args);\n\t\t\t}\n\t\t\tif (event.type === \"tool_execution_end\") {\n\t\t\t\trecordComplianceToolAction({\n\t\t\t\t\treq,\n\t\t\t\t\tevent,\n\t\t\t\t\tsessionId: sessionManager.getSessionId(),\n\t\t\t\t\tsubject,\n\t\t\t\t});\n\t\t\t\tif (event.toolName === \"artifacts\" && !event.isError) {\n\t\t\t\t\tconst sessionId = sessionManager.getSessionId();\n\t\t\t\t\tconst args = toolArgsByCallId.get(event.toolCallId) ?? {};\n\t\t\t\t\tconst filename =\n\t\t\t\t\t\ttypeof args.filename === \"string\" ? args.filename : null;\n\t\t\t\t\tconst command =\n\t\t\t\t\t\ttypeof args.command === \"string\" ? args.command : null;\n\t\t\t\t\tif (\n\t\t\t\t\t\tsessionId &&\n\t\t\t\t\t\tfilename &&\n\t\t\t\t\t\t(command === \"create\" ||\n\t\t\t\t\t\t\tcommand === \"update\" ||\n\t\t\t\t\t\t\tcommand === \"rewrite\" ||\n\t\t\t\t\t\t\tcommand === \"delete\")\n\t\t\t\t\t) {\n\t\t\t\t\t\tpublishArtifactUpdate(sessionId, filename);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\ttoolArgsByCallId.delete(event.toolCallId);\n\t\t\t}\n\n\t\t\t// Handle message completion - persist to session\n\t\t\tif (event.type === \"message_end\") {\n\t\t\t\tsessionManager.saveMessage(event.message);\n\t\t\t\tif (isAssistantMessage(event.message)) {\n\t\t\t\t\trecordAssistantUsageMetric({\n\t\t\t\t\t\treq,\n\t\t\t\t\t\tmessage: event.message,\n\t\t\t\t\t\tsessionId: sessionManager.getSessionId(),\n\t\t\t\t\t\tsubject,\n\t\t\t\t\t});\n\t\t\t\t\trecordIntelligentRouterChatMetric({\n\t\t\t\t\t\ttaskType: routingSelection.taskType,\n\t\t\t\t\t\tprovider: registeredModel.provider,\n\t\t\t\t\t\tmodel: registeredModel.id,\n\t\t\t\t\t\tstartedAt: routeStartedAt,\n\t\t\t\t\t\tmessage: event.message,\n\t\t\t\t\t});\n\t\t\t\t\trecordComplianceAssistantAction({\n\t\t\t\t\t\treq,\n\t\t\t\t\t\tmessage: event.message,\n\t\t\t\t\t\tsessionId: sessionManager.getSessionId(),\n\t\t\t\t\t\tsubject,\n\t\t\t\t\t});\n\t\t\t\t\tautomaticMemoryExtraction.schedule(sessionManager.getSessionFile());\n\t\t\t\t}\n\t\t\t\t// Update session snapshot on every event\n\t\t\t\tsessionManager.updateSnapshot(\n\t\t\t\t\tagent.state,\n\t\t\t\t\ttoSessionModelMetadata(registeredModel),\n\t\t\t\t);\n\t\t\t\tdispatchAgentNotification(\n\t\t\t\t\tevent,\n\t\t\t\t\t{\n\t\t\t\t\t\tcwd: process.cwd(),\n\t\t\t\t\t\tsessionId: sessionManager.getSessionId(),\n\t\t\t\t\t\tmessages: agent.state.messages,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tsessionHookService,\n\t\t\t\t\t\tlogger,\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Update session snapshot on every event\n\t\t\tsessionManager.updateSnapshot(\n\t\t\t\tagent.state,\n\t\t\t\ttoSessionModelMetadata(registeredModel),\n\t\t\t);\n\t\t\tdispatchAgentNotification(\n\t\t\t\tevent,\n\t\t\t\t{\n\t\t\t\t\tcwd: process.cwd(),\n\t\t\t\t\tsessionId: sessionManager.getSessionId(),\n\t\t\t\t\tmessages: agent.state.messages,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tsessionHookService,\n\t\t\t\t\tlogger,\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\n\t\t// ===== Phase 6: Connection Close Handling =====\n\t\t// Abort agent and cleanup when client disconnects\n\t\tconst handleConnectionClose = () => {\n\t\t\tagent.abort();\n\t\t\tvoid cleanup(true);\n\t\t};\n\n\t\treq.on(\"close\", handleConnectionClose);\n\t\tres.on(\"close\", handleConnectionClose);\n\n\t\t/**\n\t\t * Cleanup resources after request completion or abort.\n\t\t * Idempotent - safe to call multiple times.\n\t\t */\n\t\tconst cleanup = async (aborted = false) => {\n\t\t\tif (cleanedUp) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcleanedUp = true;\n\n\t\t\t// Stop keepalive and remove event listeners\n\t\t\tsseSession.stopHeartbeat();\n\t\t\treq.off(\"close\", handleConnectionClose);\n\t\t\tres.off(\"close\", handleConnectionClose);\n\t\t\tunsubscribe();\n\t\t\tunsubscribeMcpElicitationBridge();\n\n\t\t\tawait automaticMemoryExtraction.flush();\n\t\t\tawait automaticMemoryConsolidation.flush();\n\t\t\tawait sessionManager.flush();\n\n\t\t\t// Send final SSE events if connection is still open\n\t\t\tif (!res.writableEnded) {\n\t\t\t\tif (aborted) {\n\t\t\t\t\tsseSession.sendAborted();\n\t\t\t\t}\n\t\t\t\tsseSession.end();\n\t\t\t}\n\n\t\t\t// Log if we had to skip writes due to client disconnect\n\t\t\tconst metrics = sseSession.getMetrics();\n\t\t\tif (metrics.skipped > 0) {\n\t\t\t\tconsole.debug(\"SSE writes skipped after disconnect\", metrics);\n\t\t\t}\n\t\t};\n\n\t\t// ===== Phase 7: Agent Execution =====\n\t\ttry {\n\t\t\t// Use circuit breaker to protect against cascading failures\n\t\t\t// If the provider is having issues, we'll fail fast\n\t\t\tconst breaker = getAgentCircuitBreaker(registeredModel.provider);\n\n\t\t\t// Execute the agent with the user's input\n\t\t\tawait runUserPromptWithRecovery({\n\t\t\t\tagent,\n\t\t\t\tsessionManager,\n\t\t\t\tcwd: process.cwd(),\n\t\t\t\tprompt: userInput,\n\t\t\t\tattachmentCount: attachmentsToSend?.length ?? 0,\n\t\t\t\tattachmentNames: attachmentsToSend?.map(\n\t\t\t\t\t(attachment) => attachment.fileName,\n\t\t\t\t),\n\t\t\t\texecute: () =>\n\t\t\t\t\tbreaker.execute(() => agent.prompt(userInput, attachmentsToSend)),\n\t\t\t\tgetPostKeepMessages: withMcpPostKeepMessages(),\n\t\t\t});\n\n\t\t\t// Send completion signal if connection is still open\n\t\t\tif (!res.writableEnded) {\n\t\t\t\tsseSession.sendDone();\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Log and forward errors to client\n\t\t\tlogger.error(\n\t\t\t\t\"Agent prompt error\",\n\t\t\t\terror instanceof Error ? error : undefined,\n\t\t\t\t{ sessionId: sessionManager.getSessionId?.() },\n\t\t\t);\n\t\t\tsendSSE(sseSession, {\n\t\t\t\ttype: \"error\",\n\t\t\t\tmessage: error instanceof Error ? error.message : \"Unknown error\",\n\t\t\t});\n\t\t} finally {\n\t\t\t// Always cleanup, even on error\n\t\t\tawait cleanup(false);\n\t\t}\n\t} catch (error) {\n\t\t// Handle errors during setup (before SSE stream is established)\n\t\tlogger.error(\n\t\t\t\"Chat handler error\",\n\t\t\terror instanceof Error ? error : undefined,\n\t\t);\n\t\trespondWithApiError(res, error, 500, cors, req);\n\t} finally {\n\t\t// Release SSE connection slot\n\t\tif (sseLease && releaseSse) {\n\t\t\treleaseSse(sseLease);\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"chat.js","sourceRoot":"","sources":["../../../src/server/handlers/chat.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Chat Handler - Main WebSocket/SSE Endpoint for Agent Conversations\n *\n * This module implements the primary chat endpoint for the web server.\n * It handles incoming chat requests, manages agent execution, and streams\n * responses back to clients via Server-Sent Events (SSE).\n *\n * Request flow:\n * 1. Parse and validate incoming JSON request\n * 2. Acquire SSE connection slot (rate limited)\n * 3. Create or resume session based on sessionId\n * 4. Initialize agent with model and approval settings\n * 5. Hydrate conversation history from request\n * 6. Stream agent events to client via SSE\n * 7. Persist session state on completion\n *\n * Key features:\n * - Circuit breaker protection for agent calls\n * - Graceful handling of client disconnects\n * - Session persistence with auto-initialization\n * - Approval mode configuration via headers\n */\n\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\nimport type { ComposerChatRequest, ComposerMessage } from \"@evalops/contracts\";\nimport { isAssistantMessage } from \"../../agent/type-guards.js\";\nimport type {\n\tAttachment as AgentAttachment,\n\tAgentEvent,\n} from \"../../agent/types.js\";\nimport { runUserPromptWithRecovery } from \"../../agent/user-prompt-runtime.js\";\nimport { dispatchAgentNotification } from \"../../hooks/notification-hooks.js\";\nimport { createSessionHookService } from \"../../hooks/session-integration.js\";\nimport { withMcpPostKeepMessages } from \"../../mcp/prompt-recovery.js\";\nimport {\n\tcreateAutomaticMemoryConsolidationCoordinator,\n\tgetMemoryConsolidationSystemPrompt,\n} from \"../../memory/auto-consolidation.js\";\nimport { createAutomaticMemoryExtractionCoordinator } from \"../../memory/auto-extraction.js\";\nimport type { RegisteredModel } from \"../../models/registry.js\";\nimport {\n\trecordComplianceAssistantAction,\n\trecordComplianceToolAction,\n} from \"../../services/compliance/recorder.js\";\nimport {\n\trecordIntelligentRouterChatMetric,\n\tselectIntelligentRouterModel,\n} from \"../../services/intelligent-router/recorder.js\";\nimport { recordAssistantUsageMetric } from \"../../services/usage-analytics/recorder.js\";\nimport { evaluateModelPolicy } from \"../../services/workspace-config/policy.js\";\nimport { toSessionModelMetadata } from \"../../session/manager.js\";\nimport { createRuntimeSessionSummaryUpdater } from \"../../session/runtime-summary-updater.js\";\nimport { recordSseSkip } from \"../../telemetry.js\";\nimport { createLogger } from \"../../utils/logger.js\";\nimport type { WebServerContext } from \"../app-context.js\";\nimport {\n\tnormalizeApprovalMode,\n\tresolveApprovalModeForRequest,\n} from \"../approval-mode-store.js\";\nimport { WebActionApprovalService } from \"../approval-service.js\";\nimport { publishArtifactUpdate } from \"../artifacts-live-reload.js\";\nimport { getAuthSubject } from \"../authz.js\";\nimport { getAgentCircuitBreaker } from \"../circuit-breaker.js\";\nimport { clientToolService } from \"../client-tools-service.js\";\nimport { isHostedSessionManager } from \"../hosted-session-manager.js\";\nimport { getWorkspaceConfigContext } from \"../request-context.js\";\nimport { serverRequestManager } from \"../server-request-manager.js\";\nimport {\n\tApiError,\n\tgetRequestHeader,\n\trespondWithApiError,\n\tsendJson,\n} from \"../server-utils.js\";\nimport { startSessionWithPolicy } from \"../session-initialization.js\";\nimport { createWebSessionManagerForRequest } from \"../session-scope.js\";\nimport { convertComposerMessagesToApp } from \"../session-serialization.js\";\nimport { SseSession, sendSSE, sendSessionUpdate } from \"../sse-session.js\";\nimport { ServerRequestToolRetryService } from \"../tool-retry-service.js\";\nimport {\n\ttype ChatRequestInput,\n\tChatRequestSchema,\n\tparseAndValidateJson,\n} from \"../validation.js\";\n\nconst logger = createLogger(\"web:chat\");\n\nconst noopAutomaticMemoryExtraction = {\n\tschedule: (_sessionPath?: string | null) => {},\n\tflush: async () => {},\n};\n\nconst noopAutomaticMemoryConsolidation = {\n\tschedule: () => {},\n\tflush: async () => {},\n};\n\nfunction getComposerTextContent(content: ComposerMessage[\"content\"]): string {\n\tif (typeof content === \"string\") return content;\n\tif (!Array.isArray(content)) return \"\";\n\treturn content\n\t\t.filter((block) => block.type === \"text\")\n\t\t.map((block) => block.text)\n\t\t.join(\"\");\n}\n\n/**\n * Handle an incoming chat request.\n *\n * This is the main entry point for chat interactions. It:\n * 1. Validates the request format\n * 2. Sets up SSE streaming\n * 3. Runs the agent with the user's message\n * 4. Streams events back to the client\n * 5. Persists the session state\n *\n * @param req - The incoming HTTP request\n * @param res - The HTTP response (will be converted to SSE stream)\n * @param context - Server context with agent factory and configuration\n */\nexport async function handleChat(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tcontext: WebServerContext,\n) {\n\t// Destructure context for cleaner code\n\tconst {\n\t\tcreateAgent,\n\t\tcreateBackgroundAgent,\n\t\tgetRegisteredModel,\n\t\tdefaultApprovalMode,\n\t\tacquireSse,\n\t\treleaseSse,\n\t\tcorsHeaders: cors,\n\t} = context;\n\n\t// Track SSE lease for cleanup in finally block\n\tlet sseLease: symbol | null = null;\n\n\ttry {\n\t\t// ===== Phase 1: Request Validation =====\n\t\tconst chatReq = (await parseAndValidateJson<ChatRequestInput>(\n\t\t\treq,\n\t\t\tChatRequestSchema,\n\t\t)) as ComposerChatRequest;\n\n\t\t// Validate message array exists and is non-empty\n\t\tconst incomingMessages = Array.isArray(chatReq.messages)\n\t\t\t? (chatReq.messages as ComposerMessage[])\n\t\t\t: [];\n\t\tif (incomingMessages.length === 0) {\n\t\t\tsendJson(res, 400, { error: \"No messages supplied\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\t// The last message must be the user's current input\n\t\tconst latestMessage = incomingMessages[incomingMessages.length - 1];\n\t\tif (!latestMessage || latestMessage.role !== \"user\") {\n\t\t\tsendJson(\n\t\t\t\tres,\n\t\t\t\t400,\n\t\t\t\t{ error: \"Last message must be a user message\" },\n\t\t\t\tcors,\n\t\t\t\treq,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tconst { attachmentsToSend, attachmentError } = (() => {\n\t\t\tconst MAX_ATTACHMENT_BYTES = 8 * 1024 * 1024;\n\t\t\tconst MAX_TOTAL_BYTES = 20 * 1024 * 1024;\n\n\t\t\tconst raw = latestMessage.attachments;\n\t\t\tif (!Array.isArray(raw) || raw.length === 0) {\n\t\t\t\treturn {\n\t\t\t\t\tattachmentsToSend: undefined as AgentAttachment[] | undefined,\n\t\t\t\t\tattachmentError: null as string | null,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst attachments: AgentAttachment[] = [];\n\t\t\tlet totalBytes = 0;\n\n\t\t\tfor (const item of raw) {\n\t\t\t\tif (!item || typeof item !== \"object\") continue;\n\t\t\t\tconst id = typeof item.id === \"string\" ? item.id : \"\";\n\t\t\t\tconst type =\n\t\t\t\t\titem.type === \"image\" || item.type === \"document\" ? item.type : null;\n\t\t\t\tconst fileName =\n\t\t\t\t\ttypeof item.fileName === \"string\" ? item.fileName : \"attachment\";\n\t\t\t\tconst mimeType =\n\t\t\t\t\ttypeof item.mimeType === \"string\"\n\t\t\t\t\t\t? item.mimeType\n\t\t\t\t\t\t: \"application/octet-stream\";\n\t\t\t\tconst size =\n\t\t\t\t\ttypeof item.size === \"number\" && Number.isFinite(item.size)\n\t\t\t\t\t\t? item.size\n\t\t\t\t\t\t: 0;\n\t\t\t\tconst content = typeof item.content === \"string\" ? item.content : \"\";\n\t\t\t\tconst extractedText =\n\t\t\t\t\ttypeof item.extractedText === \"string\"\n\t\t\t\t\t\t? item.extractedText\n\t\t\t\t\t\t: undefined;\n\t\t\t\tconst preview =\n\t\t\t\t\ttypeof item.preview === \"string\" ? item.preview : undefined;\n\n\t\t\t\tif (!id || !type) continue;\n\t\t\t\tif (!content) {\n\t\t\t\t\t// Content omitted (e.g., session fetch); keep metadata for UI but do not send to model.\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Base64 -> bytes (approx). Prefer validating against actual content length.\n\t\t\t\tconst approxBytes = Math.floor((content.length * 3) / 4);\n\t\t\t\tconst bytes = approxBytes > 0 ? approxBytes : size;\n\n\t\t\t\tif (bytes > MAX_ATTACHMENT_BYTES) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tattachmentsToSend: undefined,\n\t\t\t\t\t\tattachmentError: `Attachment too large: ${fileName} (${Math.ceil(bytes / 1024 / 1024)}MB). Max per file is ${Math.ceil(MAX_ATTACHMENT_BYTES / 1024 / 1024)}MB.`,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\ttotalBytes += bytes;\n\t\t\t\tif (totalBytes > MAX_TOTAL_BYTES) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tattachmentsToSend: undefined,\n\t\t\t\t\t\tattachmentError: `Attachments too large: total exceeds ${Math.ceil(MAX_TOTAL_BYTES / 1024 / 1024)}MB.`,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tattachments.push({\n\t\t\t\t\tid,\n\t\t\t\t\ttype,\n\t\t\t\t\tfileName,\n\t\t\t\t\tmimeType,\n\t\t\t\t\tsize: size || bytes,\n\t\t\t\t\tcontent,\n\t\t\t\t\textractedText,\n\t\t\t\t\tpreview,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tattachmentsToSend: attachments.length ? attachments : undefined,\n\t\t\t\tattachmentError: null,\n\t\t\t};\n\t\t})();\n\n\t\tif (attachmentError) {\n\t\t\tsendJson(res, 413, { error: attachmentError }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst userInput = getComposerTextContent(latestMessage.content).trim();\n\t\tif (!userInput && !attachmentsToSend) {\n\t\t\tsendJson(res, 400, { error: \"User message cannot be empty\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\t// ===== Phase 2: SSE Connection Management =====\n\t\t// Acquire a lease to limit concurrent SSE connections\n\t\tif (acquireSse) {\n\t\t\tsseLease = acquireSse();\n\t\t\tif (!sseLease) {\n\t\t\t\tsendJson(\n\t\t\t\t\tres,\n\t\t\t\t\t429,\n\t\t\t\t\t{ error: \"Too many active SSE connections\" },\n\t\t\t\t\tcors,\n\t\t\t\t\treq,\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// ===== Phase 3: Session and Agent Setup =====\n\t\t// Create session manager (false = don't auto-initialize from disk)\n\t\tconst sessionManager = createWebSessionManagerForRequest(req, false);\n\t\tconst subject = getAuthSubject(req);\n\n\t\t// Resume existing session if sessionId provided\n\t\tlet existingSessionLoaded = false;\n\t\tif (chatReq.sessionId) {\n\t\t\tif (isHostedSessionManager(sessionManager)) {\n\t\t\t\texistingSessionLoaded = await sessionManager.resumeSession(\n\t\t\t\t\tchatReq.sessionId,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tconst sessionFile = sessionManager.getSessionFileById(\n\t\t\t\t\tchatReq.sessionId,\n\t\t\t\t);\n\t\t\t\tif (sessionFile) {\n\t\t\t\t\tsessionManager.setSessionFile(sessionFile);\n\t\t\t\t\texistingSessionLoaded = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Resolve model from registry through the intelligent router. With no history,\n\t\t// this preserves the caller's requested model; with enough data or overrides,\n\t\t// it can select a better-scoring model and expose explicit fallbacks.\n\t\tconst routingSelection = selectIntelligentRouterModel({\n\t\t\treq,\n\t\t\trequestedModel: chatReq.model,\n\t\t\tbody: chatReq,\n\t\t});\n\t\tlet registeredModel: RegisteredModel | undefined;\n\t\tlet lastModelError: unknown;\n\t\tlet selectedModelError: unknown;\n\t\tlet selectedModelPolicyViolation: ReturnType<\n\t\t\ttypeof evaluateModelPolicy\n\t\t> | null = null;\n\t\tfor (const [index, modelInput] of routingSelection.modelInputs.entries()) {\n\t\t\ttry {\n\t\t\t\tconst candidateModel = await getRegisteredModel(modelInput);\n\t\t\t\tconst violation = evaluateModelPolicy(\n\t\t\t\t\tgetWorkspaceConfigContext()?.config,\n\t\t\t\t\t{\n\t\t\t\t\t\tprovider: candidateModel.provider,\n\t\t\t\t\t\tmodelId: candidateModel.id,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tif (violation) {\n\t\t\t\t\tif (index === 0) {\n\t\t\t\t\t\tselectedModelPolicyViolation = violation;\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tregisteredModel = candidateModel;\n\t\t\t\tbreak;\n\t\t\t} catch (error) {\n\t\t\t\tlastModelError = error;\n\t\t\t\tif (index === 0) {\n\t\t\t\t\tselectedModelError = error;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (!registeredModel && selectedModelPolicyViolation) {\n\t\t\tsendJson(\n\t\t\t\tres,\n\t\t\t\t403,\n\t\t\t\t{\n\t\t\t\t\terror: selectedModelPolicyViolation.message,\n\t\t\t\t\tcode: selectedModelPolicyViolation.code,\n\t\t\t\t\tworkspaceId: selectedModelPolicyViolation.workspaceId,\n\t\t\t\t},\n\t\t\t\tcors,\n\t\t\t\treq,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tif (!registeredModel) {\n\t\t\tthrow selectedModelError ?? lastModelError;\n\t\t}\n\t\tconst routeStartedAt = Date.now();\n\n\t\t// Parse approval mode from request header (allows per-request override)\n\t\tconst headerApproval = normalizeApprovalMode(\n\t\t\tgetRequestHeader(\n\t\t\t\treq,\n\t\t\t\t\"x-composer-approval-mode\",\n\t\t\t\t\"x-maestro-approval-mode\",\n\t\t\t) ?? undefined,\n\t\t);\n\n\t\tconst effectiveApproval = resolveApprovalModeForRequest({\n\t\t\tsessionId: chatReq.sessionId,\n\t\t\tsubject,\n\t\t\theaderApprovalMode: headerApproval,\n\t\t\tdefaultApprovalMode,\n\t\t});\n\n\t\t// Create the agent with the resolved configuration\n\t\tconst clientToolsHeader =\n\t\t\tgetRequestHeader(\n\t\t\t\treq,\n\t\t\t\t\"x-composer-client-tools\",\n\t\t\t\t\"x-maestro-client-tools\",\n\t\t\t) === \"1\";\n\n\t\tconst clientHeader = getRequestHeader(\n\t\t\treq,\n\t\t\t\"x-composer-client\",\n\t\t\t\"x-maestro-client\",\n\t\t)?.toLowerCase();\n\t\tconst sessionIdProvider = () => sessionManager.getSessionId() ?? undefined;\n\t\tconst requestApprovalService = new WebActionApprovalService(\n\t\t\teffectiveApproval,\n\t\t\tsessionIdProvider,\n\t\t);\n\t\tconst toolRetryService = new ServerRequestToolRetryService(\n\t\t\t\"prompt\",\n\t\t\tsessionIdProvider,\n\t\t);\n\n\t\tconst agent = await createAgent(\n\t\t\tregisteredModel,\n\t\t\tchatReq.thinkingLevel || \"off\",\n\t\t\teffectiveApproval,\n\t\t\t{\n\t\t\t\tapprovalService: requestApprovalService,\n\t\t\t\ttoolRetryService,\n\t\t\t\t...(clientToolsHeader\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tenableClientTools: true,\n\t\t\t\t\t\t\tclientToolService:\n\t\t\t\t\t\t\t\tclientToolService.forSession(sessionIdProvider),\n\t\t\t\t\t\t\tincludeVscodeTools: clientHeader === \"vscode\",\n\t\t\t\t\t\t\tincludeJetBrainsTools: clientHeader === \"jetbrains\",\n\t\t\t\t\t\t\tincludeConductorTools: clientHeader === \"conductor\",\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t);\n\n\t\t// Hydrate conversation history (all messages except the current user input)\n\t\tconst historyMessages = incomingMessages.slice(0, -1);\n\t\tconst hydratedHistory = convertComposerMessagesToApp(\n\t\t\thistoryMessages,\n\t\t\tregisteredModel,\n\t\t);\n\t\tif (hydratedHistory.length > 0) {\n\t\t\tagent.replaceMessages(hydratedHistory);\n\t\t} else {\n\t\t\tagent.clearMessages();\n\t\t}\n\n\t\t// ===== Phase 4: SSE Stream Setup =====\n\t\t// Initialize the SSE response headers\n\t\tres.writeHead(200, {\n\t\t\t\"Content-Type\": \"text/event-stream\",\n\t\t\t\"Cache-Control\": \"no-cache\",\n\t\t\tConnection: \"keep-alive\",\n\t\t\t...cors,\n\t\t});\n\n\t\t// Create SSE session with telemetry callback for skip tracking\n\t\tconst requestId = Math.random().toString(36).slice(2);\n\t\tconst modelKey = `${registeredModel.provider}/${registeredModel.id}`;\n\t\tconst sseSession = new SseSession(\n\t\t\tres,\n\t\t\t(metrics) => {\n\t\t\t\t// Record telemetry when SSE writes are skipped (client disconnected)\n\t\t\t\trecordSseSkip(metrics.sent, metrics.skipped, {\n\t\t\t\t\trequestId: metrics.context?.requestId,\n\t\t\t\t\tmodelKey: metrics.context?.modelKey,\n\t\t\t\t\tsessionId: metrics.context?.sessionId,\n\t\t\t\t\tlastError:\n\t\t\t\t\t\tmetrics.lastError instanceof Error\n\t\t\t\t\t\t\t? metrics.lastError.message\n\t\t\t\t\t\t\t: metrics.lastError,\n\t\t\t\t});\n\t\t\t},\n\t\t\t{ requestId, modelKey },\n\t\t);\n\t\tsseSession.startHeartbeat(); // Keep connection alive during idle periods\n\n\t\t// Track cleanup state to prevent double-cleanup\n\t\tlet cleanedUp = false;\n\t\tlet cleanupPromise: Promise<void> | null = null;\n\n\t\t// ===== Phase 5: Agent Event Subscription =====\n\t\t// Subscribe to agent events and forward them to the SSE stream\n\t\t// Pre-load enterprise context for session tracking\n\t\tconst { enterpriseContext } = await import(\"../../enterprise/context.js\");\n\n\t\tconst initializeSessionIfNeeded = async (): Promise<string | null> => {\n\t\t\tif (existingSessionLoaded || sessionManager.isInitialized()) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst initializationError = await startSessionWithPolicy({\n\t\t\t\tagent,\n\t\t\t\tenterpriseContext,\n\t\t\t\tlogger,\n\t\t\t\tmodelId: registeredModel.id,\n\t\t\t\tonSessionReady: (sessionId) => {\n\t\t\t\t\tsendSessionUpdate(sseSession, sessionId);\n\t\t\t\t\tsseSession.setContext({ sessionId });\n\t\t\t\t},\n\t\t\t\tsessionManager,\n\t\t\t\tsubject,\n\t\t\t});\n\t\t\tif (initializationError) {\n\t\t\t\treturn initializationError;\n\t\t\t}\n\t\t\texistingSessionLoaded = true;\n\t\t\treturn null;\n\t\t};\n\n\t\tconst initializationError = await initializeSessionIfNeeded();\n\t\tif (initializationError) {\n\t\t\tsendSSE(sseSession, {\n\t\t\t\ttype: \"error\",\n\t\t\t\tmessage: `[Policy] ${initializationError}`,\n\t\t\t});\n\t\t\tsseSession.end();\n\t\t\tif (sseLease && releaseSse) {\n\t\t\t\treleaseSse(sseLease);\n\t\t\t\tsseLease = null;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst toolArgsByCallId = new Map<string, Record<string, unknown>>();\n\t\tconst storeToolArgs = (toolCallId: string, args: unknown) => {\n\t\t\ttoolArgsByCallId.set(\n\t\t\t\ttoolCallId,\n\t\t\t\t(args && typeof args === \"object\" && !Array.isArray(args)\n\t\t\t\t\t? (args as Record<string, unknown>)\n\t\t\t\t\t: {}) as Record<string, unknown>,\n\t\t\t);\n\t\t};\n\t\tconst slimValue = getRequestHeader(\n\t\t\treq,\n\t\t\t\"x-composer-slim-events\",\n\t\t\t\"x-maestro-slim-events\",\n\t\t);\n\t\tconst slimEvents = slimValue === \"1\" || slimValue === \"true\";\n\t\tconst slimToolCallArgsLimit = (() => {\n\t\t\tconst raw = process.env.MAESTRO_SLIM_TOOLCALL_ARGS_MAX_BYTES;\n\t\t\tif (!raw) return 4096;\n\t\t\tconst parsed = Number(raw);\n\t\t\tif (!Number.isFinite(parsed) || parsed <= 0) return 4096;\n\t\t\treturn Math.min(parsed, 1024 * 1024);\n\t\t})();\n\t\tconst extractToolCallInfo = (assistantEvent: {\n\t\t\tcontentIndex?: number;\n\t\t\tpartial?: { content?: unknown[] };\n\t\t}): {\n\t\t\ttoolCallId?: string;\n\t\t\ttoolCallName?: string;\n\t\t\ttoolCallArgs?: Record<string, unknown>;\n\t\t\ttoolCallArgsTruncated?: boolean;\n\t\t} => {\n\t\t\tconst assistantMessageEvent = assistantEvent.partial;\n\t\t\tconst contentIndex = assistantEvent.contentIndex;\n\t\t\tif (\n\t\t\t\t!assistantMessageEvent ||\n\t\t\t\ttypeof contentIndex !== \"number\" ||\n\t\t\t\t!Array.isArray(assistantMessageEvent.content)\n\t\t\t) {\n\t\t\t\treturn {};\n\t\t\t}\n\t\t\tconst block = assistantMessageEvent.content[contentIndex];\n\t\t\tif (!block || typeof block !== \"object\") {\n\t\t\t\treturn {};\n\t\t\t}\n\t\t\tconst maybeToolCall = block as {\n\t\t\t\ttype?: string;\n\t\t\t\tid?: string;\n\t\t\t\tname?: string;\n\t\t\t\targuments?: Record<string, unknown>;\n\t\t\t};\n\t\t\tif (maybeToolCall.type !== \"toolCall\") {\n\t\t\t\treturn {};\n\t\t\t}\n\t\t\tconst maybeArgs = maybeToolCall.arguments;\n\t\t\tconst toolCallArgs =\n\t\t\t\tmaybeArgs && typeof maybeArgs === \"object\" && !Array.isArray(maybeArgs)\n\t\t\t\t\t? maybeArgs\n\t\t\t\t\t: undefined;\n\t\t\tif (toolCallArgs) {\n\t\t\t\ttry {\n\t\t\t\t\tconst size = Buffer.byteLength(JSON.stringify(toolCallArgs), \"utf8\");\n\t\t\t\t\tif (size > slimToolCallArgsLimit) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttoolCallId: maybeToolCall.id,\n\t\t\t\t\t\t\ttoolCallName: maybeToolCall.name,\n\t\t\t\t\t\t\ttoolCallArgsTruncated: true,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttoolCallId: maybeToolCall.id,\n\t\t\t\t\t\ttoolCallName: maybeToolCall.name,\n\t\t\t\t\t\ttoolCallArgsTruncated: true,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn {\n\t\t\t\ttoolCallId: maybeToolCall.id,\n\t\t\t\ttoolCallName: maybeToolCall.name,\n\t\t\t\ttoolCallArgs,\n\t\t\t};\n\t\t};\n\t\tconst maybeSlimEvent = (event: AgentEvent): AgentEvent => {\n\t\t\tif (!slimEvents || event.type !== \"message_update\") {\n\t\t\t\treturn event;\n\t\t\t}\n\n\t\t\tconst assistantEvent = event.assistantMessageEvent;\n\t\t\tconst slimEvent: Record<string, unknown> = { ...event };\n\t\t\tdelete slimEvent.message;\n\n\t\t\tif (!assistantEvent) {\n\t\t\t\treturn slimEvent as AgentEvent;\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tassistantEvent.type === \"text_delta\" ||\n\t\t\t\tassistantEvent.type === \"thinking_delta\"\n\t\t\t) {\n\t\t\t\tconst { partial, ...assistantWithoutPartial } = assistantEvent as {\n\t\t\t\t\tpartial?: unknown;\n\t\t\t\t\t[key: string]: unknown;\n\t\t\t\t};\n\n\t\t\t\tslimEvent.assistantMessageEvent = assistantWithoutPartial;\n\t\t\t\treturn slimEvent as AgentEvent;\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tassistantEvent.type === \"toolcall_start\" ||\n\t\t\t\tassistantEvent.type === \"toolcall_delta\" ||\n\t\t\t\tassistantEvent.type === \"toolcall_end\"\n\t\t\t) {\n\t\t\t\tconst { partial, ...assistantWithoutPartial } = assistantEvent as {\n\t\t\t\t\tpartial?: unknown;\n\t\t\t\t\t[key: string]: unknown;\n\t\t\t\t};\n\t\t\t\tconst toolCallInfo =\n\t\t\t\t\tassistantEvent.type === \"toolcall_end\"\n\t\t\t\t\t\t? {}\n\t\t\t\t\t\t: extractToolCallInfo(assistantEvent);\n\n\t\t\t\tslimEvent.assistantMessageEvent = {\n\t\t\t\t\t...assistantWithoutPartial,\n\t\t\t\t\t...toolCallInfo,\n\t\t\t\t};\n\t\t\t\treturn slimEvent as AgentEvent;\n\t\t\t}\n\n\t\t\tslimEvent.assistantMessageEvent = assistantEvent;\n\t\t\treturn slimEvent as AgentEvent;\n\t\t};\n\t\tconst updateSessionSummary =\n\t\t\tcreateRuntimeSessionSummaryUpdater(sessionManager);\n\t\tconst automaticMemoryConsolidation =\n\t\t\ttypeof createBackgroundAgent === \"function\"\n\t\t\t\t? createAutomaticMemoryConsolidationCoordinator({\n\t\t\t\t\t\tcreateAgent: async () =>\n\t\t\t\t\t\t\tcreateBackgroundAgent(agent.state.model as RegisteredModel, {\n\t\t\t\t\t\t\t\tsystemPrompt: getMemoryConsolidationSystemPrompt(),\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\tgetModel: () => agent.state.model,\n\t\t\t\t\t})\n\t\t\t\t: noopAutomaticMemoryConsolidation;\n\t\tconst automaticMemoryExtraction =\n\t\t\ttypeof createBackgroundAgent === \"function\"\n\t\t\t\t? createAutomaticMemoryExtractionCoordinator({\n\t\t\t\t\t\tcreateAgent: async () =>\n\t\t\t\t\t\t\tcreateBackgroundAgent(agent.state.model as RegisteredModel),\n\t\t\t\t\t\tgetModel: () => agent.state.model,\n\t\t\t\t\t\tonProcessed: () => automaticMemoryConsolidation.schedule(),\n\t\t\t\t\t\tsessionManager,\n\t\t\t\t\t})\n\t\t\t\t: noopAutomaticMemoryExtraction;\n\t\tconst sessionHookService = createSessionHookService({\n\t\t\tcwd: process.cwd(),\n\t\t\tsessionId: sessionManager.getSessionId(),\n\t\t});\n\t\tconst unsubscribeMcpElicitationBridge = serverRequestManager.subscribe(\n\t\t\t(event) => {\n\t\t\t\tconst activeSessionId = sessionIdProvider();\n\t\t\t\tif (!activeSessionId || event.request.sessionId !== activeSessionId) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (event.request.kind !== \"mcp_elicitation\") {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (event.type === \"registered\") {\n\t\t\t\t\tsendSSE(sseSession, {\n\t\t\t\t\t\ttype: \"client_tool_request\",\n\t\t\t\t\t\ttoolCallId: event.request.callId,\n\t\t\t\t\t\ttoolName: event.request.toolName,\n\t\t\t\t\t\targs: event.request.args,\n\t\t\t\t\t});\n\t\t\t\t\tstoreToolArgs(event.request.callId, event.request.args);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\ttoolArgsByCallId.delete(event.request.callId);\n\t\t\t},\n\t\t);\n\n\t\tconst unsubscribe = agent.subscribe((event: AgentEvent) => {\n\t\t\tupdateSessionSummary(event);\n\n\t\t\t// Forward event to client\n\t\t\tsendSSE(sseSession, maybeSlimEvent(event));\n\n\t\t\t// Track tool args for later event correlation (used by artifact live reload)\n\t\t\tif (event.type === \"tool_execution_start\") {\n\t\t\t\tstoreToolArgs(event.toolCallId, event.args);\n\t\t\t}\n\t\t\tif (event.type === \"client_tool_request\") {\n\t\t\t\tstoreToolArgs(event.toolCallId, event.args);\n\t\t\t}\n\t\t\tif (event.type === \"tool_execution_end\") {\n\t\t\t\trecordComplianceToolAction({\n\t\t\t\t\treq,\n\t\t\t\t\tevent,\n\t\t\t\t\tsessionId: sessionManager.getSessionId(),\n\t\t\t\t\tsubject,\n\t\t\t\t});\n\t\t\t\tif (event.toolName === \"artifacts\" && !event.isError) {\n\t\t\t\t\tconst sessionId = sessionManager.getSessionId();\n\t\t\t\t\tconst args = toolArgsByCallId.get(event.toolCallId) ?? {};\n\t\t\t\t\tconst filename =\n\t\t\t\t\t\ttypeof args.filename === \"string\" ? args.filename : null;\n\t\t\t\t\tconst command =\n\t\t\t\t\t\ttypeof args.command === \"string\" ? args.command : null;\n\t\t\t\t\tif (\n\t\t\t\t\t\tsessionId &&\n\t\t\t\t\t\tfilename &&\n\t\t\t\t\t\t(command === \"create\" ||\n\t\t\t\t\t\t\tcommand === \"update\" ||\n\t\t\t\t\t\t\tcommand === \"rewrite\" ||\n\t\t\t\t\t\t\tcommand === \"delete\")\n\t\t\t\t\t) {\n\t\t\t\t\t\tpublishArtifactUpdate(sessionId, filename);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\ttoolArgsByCallId.delete(event.toolCallId);\n\t\t\t}\n\n\t\t\t// Handle message completion - persist to session\n\t\t\tif (event.type === \"message_end\") {\n\t\t\t\tsessionManager.saveMessage(event.message);\n\t\t\t\tif (isAssistantMessage(event.message)) {\n\t\t\t\t\trecordAssistantUsageMetric({\n\t\t\t\t\t\treq,\n\t\t\t\t\t\tmessage: event.message,\n\t\t\t\t\t\tsessionId: sessionManager.getSessionId(),\n\t\t\t\t\t\tsubject,\n\t\t\t\t\t});\n\t\t\t\t\trecordIntelligentRouterChatMetric({\n\t\t\t\t\t\ttaskType: routingSelection.taskType,\n\t\t\t\t\t\tprovider: registeredModel.provider,\n\t\t\t\t\t\tmodel: registeredModel.id,\n\t\t\t\t\t\tstartedAt: routeStartedAt,\n\t\t\t\t\t\tmessage: event.message,\n\t\t\t\t\t});\n\t\t\t\t\trecordComplianceAssistantAction({\n\t\t\t\t\t\treq,\n\t\t\t\t\t\tmessage: event.message,\n\t\t\t\t\t\tsessionId: sessionManager.getSessionId(),\n\t\t\t\t\t\tsubject,\n\t\t\t\t\t});\n\t\t\t\t\tautomaticMemoryExtraction.schedule(sessionManager.getSessionFile());\n\t\t\t\t}\n\t\t\t\t// Update session snapshot on every event\n\t\t\t\tsessionManager.updateSnapshot(\n\t\t\t\t\tagent.state,\n\t\t\t\t\ttoSessionModelMetadata(registeredModel),\n\t\t\t\t);\n\t\t\t\tdispatchAgentNotification(\n\t\t\t\t\tevent,\n\t\t\t\t\t{\n\t\t\t\t\t\tcwd: process.cwd(),\n\t\t\t\t\t\tsessionId: sessionManager.getSessionId(),\n\t\t\t\t\t\tmessages: agent.state.messages,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tsessionHookService,\n\t\t\t\t\t\tlogger,\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Update session snapshot on every event\n\t\t\tsessionManager.updateSnapshot(\n\t\t\t\tagent.state,\n\t\t\t\ttoSessionModelMetadata(registeredModel),\n\t\t\t);\n\t\t\tdispatchAgentNotification(\n\t\t\t\tevent,\n\t\t\t\t{\n\t\t\t\t\tcwd: process.cwd(),\n\t\t\t\t\tsessionId: sessionManager.getSessionId(),\n\t\t\t\t\tmessages: agent.state.messages,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tsessionHookService,\n\t\t\t\t\tlogger,\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\n\t\t// ===== Phase 6: Connection Close Handling =====\n\t\t// Abort agent and cleanup when client disconnects\n\t\tconst handleConnectionClose = () => {\n\t\t\tagent.abort();\n\t\t\tvoid cleanup(true);\n\t\t};\n\n\t\treq.on(\"close\", handleConnectionClose);\n\t\tres.on(\"close\", handleConnectionClose);\n\n\t\t/**\n\t\t * Cleanup resources after request completion or abort.\n\t\t * Idempotent - safe to call multiple times.\n\t\t */\n\t\tconst cleanup = async (aborted = false) => {\n\t\t\tif (cleanupPromise) {\n\t\t\t\treturn cleanupPromise;\n\t\t\t}\n\t\t\tcleanupPromise = (async () => {\n\t\t\t\tif (cleanedUp) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tcleanedUp = true;\n\n\t\t\t\t// Stop keepalive and remove event listeners\n\t\t\t\tsseSession.stopHeartbeat();\n\t\t\t\treq.off(\"close\", handleConnectionClose);\n\t\t\t\tres.off(\"close\", handleConnectionClose);\n\t\t\t\tunsubscribe();\n\t\t\t\tunsubscribeMcpElicitationBridge();\n\n\t\t\t\tawait automaticMemoryExtraction.flush();\n\t\t\t\tawait automaticMemoryConsolidation.flush();\n\t\t\t\tawait sessionManager.flush();\n\n\t\t\t\t// Send final SSE events if connection is still open\n\t\t\t\tif (!res.writableEnded) {\n\t\t\t\t\tif (aborted) {\n\t\t\t\t\t\tsseSession.sendAborted();\n\t\t\t\t\t}\n\t\t\t\t\tsseSession.end();\n\t\t\t\t}\n\n\t\t\t\t// Log if we had to skip writes due to client disconnect\n\t\t\t\tconst metrics = sseSession.getMetrics();\n\t\t\t\tif (metrics.skipped > 0) {\n\t\t\t\t\tconsole.debug(\"SSE writes skipped after disconnect\", metrics);\n\t\t\t\t}\n\t\t\t})();\n\t\t\treturn cleanupPromise;\n\t\t};\n\n\t\t// ===== Phase 7: Agent Execution =====\n\t\ttry {\n\t\t\t// Use circuit breaker to protect against cascading failures\n\t\t\t// If the provider is having issues, we'll fail fast\n\t\t\tconst breaker = getAgentCircuitBreaker(registeredModel.provider);\n\n\t\t\t// Execute the agent with the user's input\n\t\t\tawait runUserPromptWithRecovery({\n\t\t\t\tagent,\n\t\t\t\tsessionManager,\n\t\t\t\tcwd: process.cwd(),\n\t\t\t\tprompt: userInput,\n\t\t\t\tattachmentCount: attachmentsToSend?.length ?? 0,\n\t\t\t\tattachmentNames: attachmentsToSend?.map(\n\t\t\t\t\t(attachment) => attachment.fileName,\n\t\t\t\t),\n\t\t\t\texecute: () =>\n\t\t\t\t\tbreaker.execute(() => agent.prompt(userInput, attachmentsToSend)),\n\t\t\t\tgetPostKeepMessages: withMcpPostKeepMessages(),\n\t\t\t});\n\n\t\t\t// Send completion signal if connection is still open\n\t\t\tif (!res.writableEnded) {\n\t\t\t\tsseSession.sendDone();\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Log and forward errors to client\n\t\t\tlogger.error(\n\t\t\t\t\"Agent prompt error\",\n\t\t\t\terror instanceof Error ? error : undefined,\n\t\t\t\t{ sessionId: sessionManager.getSessionId?.() },\n\t\t\t);\n\t\t\tsendSSE(sseSession, {\n\t\t\t\ttype: \"error\",\n\t\t\t\tmessage: error instanceof Error ? error.message : \"Unknown error\",\n\t\t\t});\n\t\t} finally {\n\t\t\t// Always cleanup, even on error\n\t\t\tawait cleanup(false);\n\t\t}\n\t} catch (error) {\n\t\t// Handle errors during setup (before SSE stream is established)\n\t\tlogger.error(\n\t\t\t\"Chat handler error\",\n\t\t\terror instanceof Error ? error : undefined,\n\t\t);\n\t\trespondWithApiError(res, error, 500, cors, req);\n\t} finally {\n\t\t// Release SSE connection slot\n\t\tif (sseLease && releaseSse) {\n\t\t\treleaseSse(sseLease);\n\t\t}\n\t}\n}\n"]}
|
|
@@ -13,6 +13,23 @@ export interface HostedRunnerIdentity {
|
|
|
13
13
|
agent_run_id?: string;
|
|
14
14
|
a2a_message_id?: string;
|
|
15
15
|
a2a_task_id?: string;
|
|
16
|
+
last_platform_a2a_push?: {
|
|
17
|
+
kind: string;
|
|
18
|
+
task_id?: string;
|
|
19
|
+
context_id?: string;
|
|
20
|
+
state?: string;
|
|
21
|
+
final?: boolean;
|
|
22
|
+
received_at: string;
|
|
23
|
+
runtime_event_id?: string;
|
|
24
|
+
runtime_event_type?: string;
|
|
25
|
+
traceparent?: string;
|
|
26
|
+
tracestate?: string;
|
|
27
|
+
organization_id?: string;
|
|
28
|
+
workspace_id?: string;
|
|
29
|
+
tenant_id?: string;
|
|
30
|
+
agent_id?: string;
|
|
31
|
+
actor_id?: string;
|
|
32
|
+
};
|
|
16
33
|
agent_runtime_worker_queue?: string;
|
|
17
34
|
agent_runtime_correlation_path?: string;
|
|
18
35
|
runtime_lease?: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hosted-runner-identity.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/hosted-runner-identity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EACN,KAAK,oCAAoC,EAEzC,MAAM,2BAA2B,CAAC;AAInC,eAAO,MAAM,2BAA2B,gDACM,CAAC;AAE/C,eAAO,MAAM,uCAAuC,sCAChB,CAAC;AAErC,MAAM,WAAW,oBAAoB;IACpC,gBAAgB,EAAE,OAAO,uCAAuC,CAAC;IACjE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,8BAA8B,CAAC,EAAE,MAAM,CAAC;IACxC,aAAa,CAAC,EAAE;QACf,gBAAgB,EAAE,OAAO,oCAAoC,CAAC;QAC9D,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;QACnB,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,mBAAmB,EAAE,OAAO,CAAC;QAC7B,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,yBAAyB,CAC9C,YAAY,CAAC,EAAE,mBAAmB,GAChC,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"hosted-runner-identity.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/hosted-runner-identity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EACN,KAAK,oCAAoC,EAEzC,MAAM,2BAA2B,CAAC;AAInC,eAAO,MAAM,2BAA2B,gDACM,CAAC;AAE/C,eAAO,MAAM,uCAAuC,sCAChB,CAAC;AAErC,MAAM,WAAW,oBAAoB;IACpC,gBAAgB,EAAE,OAAO,uCAAuC,CAAC;IACjE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sBAAsB,CAAC,EAAE;QACxB,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,OAAO,CAAC;QAChB,WAAW,EAAE,MAAM,CAAC;QACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,8BAA8B,CAAC,EAAE,MAAM,CAAC;IACxC,aAAa,CAAC,EAAE;QACf,gBAAgB,EAAE,OAAO,oCAAoC,CAAC;QAC9D,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;QACnB,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,mBAAmB,EAAE,OAAO,CAAC;QAC7B,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,yBAAyB,CAC9C,YAAY,CAAC,EAAE,mBAAmB,GAChC,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CA2EtC;AAED,wBAAsB,0BAA0B,CAC/C,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,YAAY,CAAC,EAAE,mBAAmB,GAChC,OAAO,CAAC,IAAI,CAAC,CAiBf"}
|
|
@@ -30,11 +30,18 @@ export async function buildHostedRunnerIdentity(hostedRunner) {
|
|
|
30
30
|
kind: hostedRunner.lastPlatformA2APush.kind,
|
|
31
31
|
task_id: hostedRunner.lastPlatformA2APush.taskId,
|
|
32
32
|
context_id: hostedRunner.lastPlatformA2APush.contextId,
|
|
33
|
+
workspace_id: hostedRunner.lastPlatformA2APush.workspaceId,
|
|
34
|
+
organization_id: hostedRunner.lastPlatformA2APush.organizationId,
|
|
35
|
+
tenant_id: hostedRunner.lastPlatformA2APush.tenantId,
|
|
33
36
|
state: hostedRunner.lastPlatformA2APush.state,
|
|
34
37
|
final: hostedRunner.lastPlatformA2APush.final,
|
|
35
38
|
received_at: hostedRunner.lastPlatformA2APush.receivedAt,
|
|
36
39
|
runtime_event_id: hostedRunner.lastPlatformA2APush.runtimeEventId,
|
|
37
40
|
runtime_event_type: hostedRunner.lastPlatformA2APush.runtimeEventType,
|
|
41
|
+
traceparent: hostedRunner.lastPlatformA2APush.traceparent,
|
|
42
|
+
tracestate: hostedRunner.lastPlatformA2APush.tracestate,
|
|
43
|
+
agent_id: hostedRunner.lastPlatformA2APush.agentId,
|
|
44
|
+
actor_id: hostedRunner.lastPlatformA2APush.actorId,
|
|
38
45
|
},
|
|
39
46
|
}
|
|
40
47
|
: {}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hosted-runner-identity.js","sourceRoot":"","sources":["../../../src/server/handlers/hosted-runner-identity.ts"],"names":[],"mappings":"AAEA,OAAO,EAEN,yBAAyB,GACzB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAEzD,MAAM,CAAC,MAAM,2BAA2B,GACvC,6CAA6C,CAAC;AAE/C,MAAM,CAAC,MAAM,uCAAuC,GACnD,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"hosted-runner-identity.js","sourceRoot":"","sources":["../../../src/server/handlers/hosted-runner-identity.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport type { HostedRunnerContext } from \"../app-context.js\";\nimport {\n\ttype HOSTED_RUNNER_LEASE_PROTOCOL_VERSION,\n\thostedRunnerLeaseSnapshot,\n} from \"../hosted-runner-lease.js\";\nimport { sendJson } from \"../server-utils.js\";\nimport { checkHostedRunnerReadiness } from \"./health.js\";\n\nexport const HOSTED_RUNNER_IDENTITY_PATH =\n\t\"/.well-known/evalops/remote-runner/identity\";\n\nexport const HOSTED_RUNNER_IDENTITY_PROTOCOL_VERSION =\n\t\"evalops.remote-runner.identity.v1\";\n\nexport interface HostedRunnerIdentity {\n\tprotocol_version: typeof HOSTED_RUNNER_IDENTITY_PROTOCOL_VERSION;\n\trunner_session_id: string;\n\towner_instance_id: string;\n\tready: boolean;\n\tdraining: boolean;\n\tagent_id?: string;\n\tagent_run_id?: string;\n\ta2a_message_id?: string;\n\ta2a_task_id?: string;\n\tlast_platform_a2a_push?: {\n\t\tkind: string;\n\t\ttask_id?: string;\n\t\tcontext_id?: string;\n\t\tstate?: string;\n\t\tfinal?: boolean;\n\t\treceived_at: string;\n\t\truntime_event_id?: string;\n\t\truntime_event_type?: string;\n\t\ttraceparent?: string;\n\t\ttracestate?: string;\n\t\torganization_id?: string;\n\t\tworkspace_id?: string;\n\t\ttenant_id?: string;\n\t\tagent_id?: string;\n\t\tactor_id?: string;\n\t};\n\tagent_runtime_worker_queue?: string;\n\tagent_runtime_correlation_path?: string;\n\truntime_lease?: {\n\t\tprotocol_version: typeof HOSTED_RUNNER_LEASE_PROTOCOL_VERSION;\n\t\tstate: string;\n\t\tgeneration: number;\n\t\tmaestro_session_id?: string;\n\t\tlease_token_present: boolean;\n\t\theartbeat_at: string;\n\t\tupdated_at: string;\n\t};\n\tdrain_status?: string;\n\tdrain_manifest_path?: string;\n\tdrained_at?: string;\n}\n\nexport async function buildHostedRunnerIdentity(\n\thostedRunner?: HostedRunnerContext,\n): Promise<HostedRunnerIdentity | null> {\n\tif (!hostedRunner?.runnerSessionId || !hostedRunner.ownerInstanceId) {\n\t\treturn null;\n\t}\n\n\tconst readiness = await checkHostedRunnerReadiness(hostedRunner);\n\tconst draining = readiness.status === \"draining\";\n\tconst lease = hostedRunnerLeaseSnapshot(hostedRunner);\n\n\treturn {\n\t\tprotocol_version: HOSTED_RUNNER_IDENTITY_PROTOCOL_VERSION,\n\t\trunner_session_id: hostedRunner.runnerSessionId,\n\t\towner_instance_id: hostedRunner.ownerInstanceId,\n\t\tready: readiness.status === \"ready\",\n\t\tdraining,\n\t\t...(hostedRunner.agentId ? { agent_id: hostedRunner.agentId } : {}),\n\t\t...(hostedRunner.agentRunId\n\t\t\t? { agent_run_id: hostedRunner.agentRunId }\n\t\t\t: {}),\n\t\t...(hostedRunner.a2aMessageId\n\t\t\t? { a2a_message_id: hostedRunner.a2aMessageId }\n\t\t\t: {}),\n\t\t...(hostedRunner.a2aTaskId ? { a2a_task_id: hostedRunner.a2aTaskId } : {}),\n\t\t...(hostedRunner.lastPlatformA2APush\n\t\t\t? {\n\t\t\t\t\tlast_platform_a2a_push: {\n\t\t\t\t\t\tkind: hostedRunner.lastPlatformA2APush.kind,\n\t\t\t\t\t\ttask_id: hostedRunner.lastPlatformA2APush.taskId,\n\t\t\t\t\t\tcontext_id: hostedRunner.lastPlatformA2APush.contextId,\n\t\t\t\t\t\tworkspace_id: hostedRunner.lastPlatformA2APush.workspaceId,\n\t\t\t\t\t\torganization_id: hostedRunner.lastPlatformA2APush.organizationId,\n\t\t\t\t\t\ttenant_id: hostedRunner.lastPlatformA2APush.tenantId,\n\t\t\t\t\t\tstate: hostedRunner.lastPlatformA2APush.state,\n\t\t\t\t\t\tfinal: hostedRunner.lastPlatformA2APush.final,\n\t\t\t\t\t\treceived_at: hostedRunner.lastPlatformA2APush.receivedAt,\n\t\t\t\t\t\truntime_event_id: hostedRunner.lastPlatformA2APush.runtimeEventId,\n\t\t\t\t\t\truntime_event_type:\n\t\t\t\t\t\t\thostedRunner.lastPlatformA2APush.runtimeEventType,\n\t\t\t\t\t\ttraceparent: hostedRunner.lastPlatformA2APush.traceparent,\n\t\t\t\t\t\ttracestate: hostedRunner.lastPlatformA2APush.tracestate,\n\t\t\t\t\t\tagent_id: hostedRunner.lastPlatformA2APush.agentId,\n\t\t\t\t\t\tactor_id: hostedRunner.lastPlatformA2APush.actorId,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t: {}),\n\t\t...(hostedRunner.agentRuntimeWorkerQueue\n\t\t\t? { agent_runtime_worker_queue: hostedRunner.agentRuntimeWorkerQueue }\n\t\t\t: {}),\n\t\t...(hostedRunner.agentRuntimeCorrelationPath\n\t\t\t? {\n\t\t\t\t\tagent_runtime_correlation_path:\n\t\t\t\t\t\thostedRunner.agentRuntimeCorrelationPath,\n\t\t\t\t}\n\t\t\t: {}),\n\t\truntime_lease: {\n\t\t\tprotocol_version: lease.protocolVersion,\n\t\t\tstate: lease.state,\n\t\t\tgeneration: lease.generation,\n\t\t\t...(lease.maestroSessionId\n\t\t\t\t? { maestro_session_id: lease.maestroSessionId }\n\t\t\t\t: {}),\n\t\t\tlease_token_present: Boolean(lease.leaseToken),\n\t\t\theartbeat_at: lease.heartbeatAt,\n\t\t\tupdated_at: lease.updatedAt,\n\t\t},\n\t\t...(hostedRunner.lastDrain?.status\n\t\t\t? { drain_status: hostedRunner.lastDrain.status }\n\t\t\t: {}),\n\t\t...(hostedRunner.lastDrain?.manifestPath\n\t\t\t? { drain_manifest_path: hostedRunner.lastDrain.manifestPath }\n\t\t\t: {}),\n\t\t...(hostedRunner.lastDrain?.drainedAt\n\t\t\t? { drained_at: hostedRunner.lastDrain.drainedAt }\n\t\t\t: {}),\n\t};\n}\n\nexport async function handleHostedRunnerIdentity(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tcors: Record<string, string>,\n\thostedRunner?: HostedRunnerContext,\n): Promise<void> {\n\tres.setHeader(\"Cache-Control\", \"no-store\");\n\tconst identity = await buildHostedRunnerIdentity(hostedRunner);\n\tif (!identity) {\n\t\tsendJson(\n\t\t\tres,\n\t\t\t404,\n\t\t\t{\n\t\t\t\terror: \"hosted runner identity unavailable\",\n\t\t\t},\n\t\t\tcors,\n\t\t\treq,\n\t\t);\n\t\treturn;\n\t}\n\n\tsendJson(res, 200, identity, cors, req);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform-a2a-push.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/platform-a2a-push.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,KAAK,EAAuB,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAS/E,eAAO,MAAM,+BAA+B,2BAA2B,CAAC;AAOxE,wBAAgB,sCAAsC,IAAI,SAAS,MAAM,EAAE,CAE1E;
|
|
1
|
+
{"version":3,"file":"platform-a2a-push.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/platform-a2a-push.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,KAAK,EAAuB,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAS/E,eAAO,MAAM,+BAA+B,2BAA2B,CAAC;AAOxE,wBAAgB,sCAAsC,IAAI,SAAS,MAAM,EAAE,CAE1E;AAgCD,wBAAsB,6BAA6B,CAClD,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,OAAO,EAAE,gBAAgB,GACvB,OAAO,CAAC,IAAI,CAAC,CAgBf"}
|
|
@@ -13,16 +13,12 @@ export async function handlePlatformA2APushCallback(req, res, context) {
|
|
|
13
13
|
}
|
|
14
14
|
assertCallbackToken(req);
|
|
15
15
|
const body = await readJsonBody(req);
|
|
16
|
-
const snapshot = platformA2APushSnapshot(body);
|
|
16
|
+
const snapshot = platformA2APushSnapshot(body, req);
|
|
17
17
|
if (!snapshot) {
|
|
18
18
|
throw new ApiError(400, "Invalid A2A push notification payload");
|
|
19
19
|
}
|
|
20
20
|
const hostedRunner = context.hostedRunner;
|
|
21
|
-
|
|
22
|
-
snapshot.taskId &&
|
|
23
|
-
hostedRunner.a2aTaskId !== snapshot.taskId) {
|
|
24
|
-
throw new ApiError(404, "A2A task not found");
|
|
25
|
-
}
|
|
21
|
+
assertHostedRunnerA2APushBoundary(hostedRunner, snapshot);
|
|
26
22
|
if (hostedRunner) {
|
|
27
23
|
recordHostedRunnerA2APush(hostedRunner, snapshot);
|
|
28
24
|
}
|
|
@@ -38,65 +34,141 @@ function assertCallbackToken(req) {
|
|
|
38
34
|
throw new ApiError(401, "Invalid A2A notification token");
|
|
39
35
|
}
|
|
40
36
|
}
|
|
41
|
-
function platformA2APushSnapshot(payload) {
|
|
37
|
+
function platformA2APushSnapshot(payload, req) {
|
|
42
38
|
if (!isJsonObject(payload)) {
|
|
43
39
|
return null;
|
|
44
40
|
}
|
|
41
|
+
const requestContext = platformA2APushRequestContext(req);
|
|
45
42
|
if (isJsonObject(payload.statusUpdate)) {
|
|
46
43
|
const taskId = stringField(payload.statusUpdate, "taskId");
|
|
47
44
|
if (!taskId) {
|
|
48
45
|
return null;
|
|
49
46
|
}
|
|
50
|
-
return {
|
|
47
|
+
return withPlatformA2APushContext({
|
|
51
48
|
kind: "statusUpdate",
|
|
52
49
|
taskId,
|
|
53
50
|
contextId: stringField(payload.statusUpdate, "contextId"),
|
|
51
|
+
...ownershipFields(payload, payload.statusUpdate),
|
|
54
52
|
state: statusState(payload.statusUpdate),
|
|
55
53
|
final: booleanField(payload.statusUpdate, "final"),
|
|
56
54
|
receivedAt: new Date().toISOString(),
|
|
57
55
|
runtimeEventId: metadataString(payload.statusUpdate, "runtimeEventId"),
|
|
58
56
|
runtimeEventType: metadataString(payload.statusUpdate, "runtimeEventType"),
|
|
59
|
-
};
|
|
57
|
+
}, payload.statusUpdate, requestContext);
|
|
60
58
|
}
|
|
61
59
|
if (isJsonObject(payload.task)) {
|
|
62
60
|
const taskId = stringField(payload.task, "id");
|
|
63
61
|
if (!taskId) {
|
|
64
62
|
return null;
|
|
65
63
|
}
|
|
66
|
-
return {
|
|
64
|
+
return withPlatformA2APushContext({
|
|
67
65
|
kind: "task",
|
|
68
66
|
taskId,
|
|
69
67
|
contextId: stringField(payload.task, "contextId"),
|
|
68
|
+
...ownershipFields(payload, payload.task),
|
|
70
69
|
state: statusState(payload.task),
|
|
71
70
|
receivedAt: new Date().toISOString(),
|
|
72
|
-
};
|
|
71
|
+
}, payload.task, requestContext);
|
|
73
72
|
}
|
|
74
73
|
if (isJsonObject(payload.artifactUpdate)) {
|
|
75
74
|
const taskId = stringField(payload.artifactUpdate, "taskId");
|
|
76
75
|
if (!taskId) {
|
|
77
76
|
return null;
|
|
78
77
|
}
|
|
79
|
-
return {
|
|
78
|
+
return withPlatformA2APushContext({
|
|
80
79
|
kind: "artifactUpdate",
|
|
81
80
|
taskId,
|
|
82
81
|
contextId: stringField(payload.artifactUpdate, "contextId"),
|
|
82
|
+
...ownershipFields(payload, payload.artifactUpdate),
|
|
83
83
|
receivedAt: new Date().toISOString(),
|
|
84
|
-
};
|
|
84
|
+
}, payload.artifactUpdate, requestContext);
|
|
85
85
|
}
|
|
86
86
|
if (isJsonObject(payload.message)) {
|
|
87
87
|
const taskId = stringField(payload.message, "taskId");
|
|
88
88
|
if (!taskId) {
|
|
89
89
|
return null;
|
|
90
90
|
}
|
|
91
|
-
return {
|
|
91
|
+
return withPlatformA2APushContext({
|
|
92
92
|
kind: "message",
|
|
93
93
|
taskId,
|
|
94
94
|
contextId: stringField(payload.message, "contextId"),
|
|
95
|
+
...ownershipFields(payload, payload.message),
|
|
95
96
|
receivedAt: new Date().toISOString(),
|
|
96
|
-
};
|
|
97
|
+
}, payload.message, requestContext);
|
|
97
98
|
}
|
|
98
99
|
return null;
|
|
99
100
|
}
|
|
101
|
+
function withPlatformA2APushContext(snapshot, payload, requestContext) {
|
|
102
|
+
const metadataContext = platformA2APushMetadataContext(payload);
|
|
103
|
+
return {
|
|
104
|
+
...snapshot,
|
|
105
|
+
...metadataContext,
|
|
106
|
+
...requestContext,
|
|
107
|
+
organizationId: snapshot.organizationId ??
|
|
108
|
+
metadataContext.organizationId ??
|
|
109
|
+
requestContext.organizationId,
|
|
110
|
+
workspaceId: snapshot.workspaceId ??
|
|
111
|
+
metadataContext.workspaceId ??
|
|
112
|
+
requestContext.workspaceId,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function platformA2APushRequestContext(req) {
|
|
116
|
+
return compactPlatformA2APushContext({
|
|
117
|
+
traceparent: getRequestHeader(req, "traceparent") ?? undefined,
|
|
118
|
+
tracestate: getRequestHeader(req, "tracestate") ?? undefined,
|
|
119
|
+
organizationId: getRequestHeader(req, "x-organization-id", "x-evalops-organization-id") ??
|
|
120
|
+
undefined,
|
|
121
|
+
workspaceId: getRequestHeader(req, "x-workspace-id", "x-evalops-workspace-id") ??
|
|
122
|
+
undefined,
|
|
123
|
+
agentId: getRequestHeader(req, "x-evalops-agent-id", "x-maestro-agent-id") ??
|
|
124
|
+
undefined,
|
|
125
|
+
actorId: getRequestHeader(req, "x-evalops-actor-id", "x-evalops-user-id") ??
|
|
126
|
+
undefined,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
function platformA2APushMetadataContext(value) {
|
|
130
|
+
const metadata = isJsonObject(value.metadata) ? value.metadata : undefined;
|
|
131
|
+
if (!metadata) {
|
|
132
|
+
return {};
|
|
133
|
+
}
|
|
134
|
+
return compactPlatformA2APushContext({
|
|
135
|
+
traceparent: stringField(metadata, "traceparent") ??
|
|
136
|
+
stringField(metadata, "traceParent") ??
|
|
137
|
+
stringField(metadata, "trace_parent"),
|
|
138
|
+
tracestate: stringField(metadata, "tracestate") ??
|
|
139
|
+
stringField(metadata, "traceState") ??
|
|
140
|
+
stringField(metadata, "trace_state"),
|
|
141
|
+
organizationId: stringField(metadata, "organizationId") ??
|
|
142
|
+
stringField(metadata, "organization_id"),
|
|
143
|
+
workspaceId: stringField(metadata, "workspaceId") ??
|
|
144
|
+
stringField(metadata, "workspace_id"),
|
|
145
|
+
agentId: stringField(metadata, "agentId") ?? stringField(metadata, "agent_id"),
|
|
146
|
+
actorId: stringField(metadata, "actorId") ?? stringField(metadata, "actor_id"),
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
function compactPlatformA2APushContext(context) {
|
|
150
|
+
return Object.fromEntries(Object.entries(context).filter(([, value]) => typeof value === "string" && value.length > 0));
|
|
151
|
+
}
|
|
152
|
+
function assertHostedRunnerA2APushBoundary(hostedRunner, snapshot) {
|
|
153
|
+
if (hostedRunner?.a2aTaskId &&
|
|
154
|
+
snapshot.taskId &&
|
|
155
|
+
hostedRunner.a2aTaskId !== snapshot.taskId) {
|
|
156
|
+
throw new ApiError(404, "A2A task not found");
|
|
157
|
+
}
|
|
158
|
+
if (!hostedRunner?.workspaceId) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const workspaceMarker = snapshot.workspaceId;
|
|
162
|
+
if (workspaceMarker) {
|
|
163
|
+
if (!sameIdentifier(workspaceMarker, hostedRunner.workspaceId)) {
|
|
164
|
+
throw new ApiError(403, "A2A push notification workspace mismatch");
|
|
165
|
+
}
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
if (!hostedRunner.a2aTaskId) {
|
|
169
|
+
throw new ApiError(403, "A2A push notification is missing workspace metadata");
|
|
170
|
+
}
|
|
171
|
+
}
|
|
100
172
|
function recordHostedRunnerA2APush(hostedRunner, snapshot) {
|
|
101
173
|
hostedRunner.lastPlatformA2APush = snapshot;
|
|
102
174
|
if (snapshot.taskId && !hostedRunner.a2aTaskId) {
|
|
@@ -111,6 +183,53 @@ function metadataString(value, key) {
|
|
|
111
183
|
const metadata = isJsonObject(value.metadata) ? value.metadata : undefined;
|
|
112
184
|
return metadata ? stringField(metadata, key) : undefined;
|
|
113
185
|
}
|
|
186
|
+
function ownershipFields(payload, value) {
|
|
187
|
+
return {
|
|
188
|
+
...optionalField("workspaceId", ownershipString(payload, value, ["workspaceId", "workspace_id"])),
|
|
189
|
+
...optionalField("organizationId", ownershipString(payload, value, [
|
|
190
|
+
"organizationId",
|
|
191
|
+
"organization_id",
|
|
192
|
+
"orgId",
|
|
193
|
+
"org_id",
|
|
194
|
+
])),
|
|
195
|
+
...optionalField("tenantId", ownershipString(payload, value, ["tenantId", "tenant_id", "tenant"])),
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
function ownershipString(payload, value, keys) {
|
|
199
|
+
for (const source of ownershipSources(payload, value)) {
|
|
200
|
+
for (const key of keys) {
|
|
201
|
+
const direct = stringField(source, key);
|
|
202
|
+
if (direct) {
|
|
203
|
+
return direct;
|
|
204
|
+
}
|
|
205
|
+
const metadata = metadataString(source, key);
|
|
206
|
+
if (metadata) {
|
|
207
|
+
return metadata;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return undefined;
|
|
212
|
+
}
|
|
213
|
+
function ownershipSources(payload, value) {
|
|
214
|
+
const sources = [value, payload];
|
|
215
|
+
const status = isJsonObject(value.status) ? value.status : undefined;
|
|
216
|
+
if (status) {
|
|
217
|
+
sources.push(status);
|
|
218
|
+
if (isJsonObject(status.message)) {
|
|
219
|
+
sources.push(status.message);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
if (isJsonObject(value.artifact)) {
|
|
223
|
+
sources.push(value.artifact);
|
|
224
|
+
}
|
|
225
|
+
return sources;
|
|
226
|
+
}
|
|
227
|
+
function optionalField(key, value) {
|
|
228
|
+
return value ? { [key]: value } : {};
|
|
229
|
+
}
|
|
230
|
+
function sameIdentifier(left, right) {
|
|
231
|
+
return left.trim().toLowerCase() === right.trim().toLowerCase();
|
|
232
|
+
}
|
|
114
233
|
function stringField(value, key) {
|
|
115
234
|
const field = value[key];
|
|
116
235
|
return typeof field === "string" && field.trim().length > 0
|