@evalops/maestro 0.10.22 → 0.10.23

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,cAAc,kCAAkC,CAAC;AACjD,cAAc,0CAA0C,CAAC;AACzD,OAAO,KAAK,aAAa,MAAM,mCAAmC,CAAC;AACnE,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mCAAmC,CAAC;AAClD,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,eAAe,CAAC;AAksC9B,+BAA+B;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC","sourcesContent":["/**\n * @fileoverview @evalops/contracts - Shared TypeScript Definitions\n *\n * This package provides the TypeScript type definitions that form the contract\n * between Composer's frontend (Web UI) and backend (API server). All shared\n * types, interfaces, and enums are defined here to ensure type safety across\n * the client-server boundary.\n *\n * ## Key Types\n *\n * | Type | Description |\n * |------|-------------|\n * | `ComposerMessage` | Chat message with role, content, tools, and usage |\n * | `ComposerSession` | Session with metadata and message history |\n * | `ComposerChatRequest` | Request payload for the chat API |\n * | `ComposerUsage` | Token usage and cost tracking |\n * | `ComposerToolCall` | Tool invocation with status and result |\n *\n * ## Usage\n *\n * ```typescript\n * import type {\n * ComposerMessage,\n * ComposerSession,\n * ComposerChatRequest\n * } from \"@evalops/contracts\";\n *\n * // Type-safe message handling\n * const message: ComposerMessage = {\n * role: \"user\",\n * content: \"Hello, Composer!\",\n * timestamp: new Date().toISOString(),\n * };\n *\n * // Type-safe API request\n * const request: ComposerChatRequest = {\n * messages: [message],\n * model: \"claude-sonnet-4-5\",\n * thinkingLevel: \"medium\",\n * };\n * ```\n *\n * @module @evalops/contracts\n */\n\nexport * from \"./headless-protocol-generated.js\";\nexport * from \"./headless-protocol-schemas.generated.js\";\nexport * as headlessProto from \"./proto/maestro/v1/headless_pb.js\";\nexport * from \"./advisor-effort.js\";\nexport * from \"./delegation-prompt.js\";\nexport * from \"./guarded-files-settings.js\";\nexport * from \"./key-value-tokens.js\";\nexport * from \"./mcp-settings.js\";\nexport * from \"./memory.js\";\nexport * from \"./memory-utils.js\";\nexport * from \"./maestro-app-server.js\";\nexport * from \"./onboarding-utils.js\";\nexport * from \"./proto/maestro/v1/headless_pb.js\";\nexport * from \"./runtime-constraints.js\";\nexport * from \"./runtime-app-server.js\";\nexport * from \"./runtime-server-request.js\";\nexport * from \"./scenario.js\";\n\n/**\n * Role of a message in the conversation.\n *\n * - `user` - Messages from the human user\n * - `assistant` - Messages from the AI assistant\n * - `system` - System prompts and instructions\n * - `tool` - Tool execution results\n */\nexport type ComposerRole = \"user\" | \"assistant\" | \"system\" | \"tool\";\n\n/**\n * Content blocks used for rich message payloads.\n */\nexport interface ComposerTextContent {\n\ttype: \"text\";\n\ttext: string;\n\ttextSignature?: string;\n}\n\nexport interface ComposerImageContent {\n\ttype: \"image\";\n\tdata: string;\n\tmimeType: string;\n}\n\nexport interface ComposerThinkingContent {\n\ttype: \"thinking\";\n\tthinking: string;\n\tthinkingSignature?: string;\n}\n\nexport interface ComposerToolCallContent {\n\ttype: \"toolCall\";\n\tid: string;\n\tname: string;\n\targuments: Record<string, unknown>;\n\tthoughtSignature?: string;\n}\n\nexport type ComposerContentBlock =\n\t| ComposerTextContent\n\t| ComposerImageContent\n\t| ComposerThinkingContent\n\t| ComposerToolCallContent;\n\n/**\n * Extended thinking/reasoning level for supported models.\n *\n * Higher levels produce more detailed reasoning at the cost of latency:\n * - `off` - No extended thinking\n * - `minimal` - Brief reasoning hints\n * - `low` - Light reasoning\n * - `medium` - Moderate reasoning depth\n * - `high` - Thorough step-by-step reasoning\n */\nexport type ComposerThinkingLevel =\n\t| \"off\"\n\t| \"minimal\"\n\t| \"low\"\n\t| \"medium\"\n\t| \"high\";\n\n/**\n * Represents a tool invocation within a message.\n *\n * Tools are actions the agent can take like reading files, executing commands,\n * or searching the web. Each tool call tracks its execution lifecycle.\n */\nexport interface ComposerToolCall {\n\t/** Name of the tool being invoked (e.g., \"read\", \"bash\", \"search\") */\n\tname: string;\n\t/** Current execution status of the tool call */\n\tstatus: \"pending\" | \"running\" | \"completed\" | \"error\";\n\t/** Arguments passed to the tool */\n\targs?: Record<string, unknown>;\n\t/** Result returned by the tool (if completed) */\n\tresult?: unknown;\n\t/** Unique identifier for this tool call (for matching results) */\n\ttoolCallId?: string;\n}\n\n/**\n * File attachment included in a user message.\n *\n * Attachments can be images (for vision-capable models) or documents\n * (typically accompanied by extracted text for model consumption).\n *\n * `content` is base64-encoded raw bytes. Servers may omit `content` in some\n * read APIs for size reasons; when omitted, `contentOmitted` is set to true.\n */\nexport interface ComposerAttachment {\n\t/** Unique identifier for this attachment */\n\tid: string;\n\t/** Attachment type */\n\ttype: \"image\" | \"document\";\n\t/** Original filename */\n\tfileName: string;\n\t/** MIME type */\n\tmimeType: string;\n\t/** Size in bytes */\n\tsize: number;\n\t/** Base64-encoded file content (may be omitted) */\n\tcontent?: string;\n\t/** True when `content` was intentionally omitted */\n\tcontentOmitted?: boolean;\n\t/** Extracted text content (for documents) */\n\textractedText?: string;\n\t/** Preview image (typically base64, small) */\n\tpreview?: string;\n}\n\n/**\n * A message in the Composer conversation.\n *\n * Messages can contain text content, tool calls, thinking traces,\n * and usage statistics. This is the primary data structure for\n * conversation history.\n */\nexport interface ComposerMessage {\n\t/** Role of the message sender */\n\trole: ComposerRole;\n\t/** Text content of the message */\n\tcontent: string | ComposerContentBlock[];\n\t/** Optional file attachments (for user messages) */\n\tattachments?: ComposerAttachment[];\n\t/** ISO 8601 timestamp when the message was created */\n\ttimestamp?: string;\n\t/** Extended thinking/reasoning trace (for supported models) */\n\tthinking?: string;\n\t/** Tool calls made in this message (for assistant messages) */\n\ttools?: ComposerToolCall[];\n\t/** Name of the tool (for tool result messages) */\n\ttoolName?: string;\n\t/** Whether this message represents an error */\n\tisError?: boolean;\n\t/** Token usage and cost for this message */\n\tusage?: ComposerUsage;\n\t/** Original provider for assistant messages (for cross-provider resume) */\n\tprovider?: string;\n\t/** Original API for assistant messages (for cross-provider resume) */\n\tapi?: string;\n\t/** Original model ID for assistant messages (for cross-provider resume) */\n\tmodel?: string;\n}\n\n/**\n * Cost breakdown for token usage.\n *\n * Costs are typically in USD, calculated based on the model's pricing.\n */\nexport interface ComposerUsageCost {\n\t/** Cost for input tokens */\n\tinput: number;\n\t/** Cost for output tokens */\n\toutput: number;\n\t/** Cost savings from cache reads (if applicable) */\n\tcacheRead?: number;\n\t/** Cost for cache writes (if applicable) */\n\tcacheWrite?: number;\n\t/** Total cost for this message */\n\ttotal?: number;\n}\n\n/**\n * Token usage statistics for a message or session.\n *\n * Tracks input/output tokens and cache utilization for cost monitoring.\n */\nexport interface ComposerUsage {\n\t/** Number of input tokens consumed */\n\tinput: number;\n\t/** Number of output tokens generated */\n\toutput: number;\n\t/** Tokens served from cache (reduces cost) */\n\tcacheRead?: number;\n\t/** Tokens written to cache */\n\tcacheWrite?: number;\n\t/** Calculated cost breakdown */\n\tcost?: ComposerUsageCost;\n}\n\n/**\n * Model capability metadata exposed by the API.\n */\nexport interface ComposerModelCapabilities {\n\tstreaming?: boolean;\n\ttools?: boolean;\n\tvision?: boolean;\n\treasoning?: boolean;\n}\n\n/**\n * Model metadata returned by `/api/models` and `/api/model`.\n */\nexport interface ComposerModel {\n\tid: string;\n\tprovider: string;\n\tname: string;\n\tapi?: string;\n\tcontextWindow?: number;\n\tmaxOutputTokens?: number;\n\tmaxTokens?: number;\n\treasoning?: boolean;\n\tcost?: ComposerUsageCost;\n\tcapabilities?: ComposerModelCapabilities;\n}\n\n/**\n * Response payload for `/api/models`.\n */\nexport interface ComposerModelListResponse {\n\tmodels: ComposerModel[];\n}\n\n/**\n * Argument definition for a custom command.\n */\nexport interface ComposerCommandArg {\n\tname: string;\n\trequired?: boolean;\n}\n\n/**\n * Custom command definition (safe for client consumption).\n */\nexport interface ComposerCommand {\n\tname: string;\n\tdescription?: string;\n\tprompt: string;\n\targs?: ComposerCommandArg[];\n}\n\n/**\n * Response payload for `/api/commands`.\n */\nexport interface ComposerCommandListResponse {\n\tcommands: ComposerCommand[];\n}\n\n/**\n * Command favorites/recents preferences.\n */\nexport interface ComposerCommandPrefs {\n\tfavorites: string[];\n\trecents: string[];\n}\n\n/**\n * Update payload for command preferences.\n */\nexport interface ComposerCommandPrefsUpdate {\n\tfavorites?: string[];\n\trecents?: string[];\n}\n\n/**\n * Response payload for command preference updates.\n */\nexport interface ComposerCommandPrefsWriteResponse {\n\tok: boolean;\n}\n\n/**\n * Request payload for `/api/config`.\n */\nexport interface ComposerConfigWriteRequest {\n\tconfig: Record<string, unknown>;\n}\n\n/**\n * Response payload for `/api/config` GET.\n */\nexport interface ComposerConfigResponse {\n\tconfig: Record<string, unknown>;\n\tconfigPath: string;\n}\n\n/**\n * Response payload for `/api/config` POST.\n */\nexport interface ComposerConfigWriteResponse {\n\tsuccess: boolean;\n}\n\n/**\n * Response payload for `/api/files`.\n */\nexport interface ComposerFilesResponse {\n\tfiles: string[];\n}\n\n/**\n * Request payload for the chat API endpoint.\n *\n * Sent to `POST /api/chat` to initiate or continue a conversation.\n */\nexport interface ComposerChatRequest {\n\t/** Model ID to use (e.g., \"claude-sonnet-4-5-20250929\") */\n\tmodel?: string;\n\t/** Conversation history including the current user message */\n\tmessages: ComposerMessage[];\n\t/** Extended thinking level for supported models */\n\tthinkingLevel?: ComposerThinkingLevel;\n\t/** Session ID to resume (optional - creates new session if omitted) */\n\tsessionId?: string;\n\t/** Whether to stream the response via SSE (default: true) */\n\tstream?: boolean;\n}\n\n/**\n * Request payload for prompt suggestion generation.\n *\n * Sent to `POST /api/prompt-suggestion` to generate a likely next user prompt\n * from the current conversation state.\n */\nexport interface ComposerPromptSuggestionRequest {\n\t/** Optional model preference used to select a suggestion model. */\n\tmodel?: string;\n\t/** Conversation history to summarize into a likely next user prompt. */\n\tmessages: ComposerMessage[];\n\t/** Optional session id for callers that want request correlation. */\n\tsessionId?: string;\n}\n\n/**\n * Response payload for prompt suggestion generation.\n */\nexport interface ComposerPromptSuggestionResponse {\n\t/** Suggested next user prompt, or null when suggestion generation is suppressed. */\n\tsuggestion: string | null;\n\t/** Optional suppression or filtering reason when no suggestion is returned. */\n\tsuppressedReason?: string;\n\t/** Model used to generate the suggestion, when generation ran. */\n\tmodel?: string;\n}\n\n/**\n * Summary metadata for a session (without full message history).\n *\n * Used in session list views for performance.\n */\nexport interface ComposerSessionSummary {\n\t/** Unique session identifier */\n\tid: string;\n\t/** User-assigned or auto-generated title */\n\ttitle?: string;\n\t/** Short persisted recap shown when resuming a session */\n\tresumeSummary?: string;\n\t/** ISO 8601 timestamp when session was created */\n\tcreatedAt: string;\n\t/** ISO 8601 timestamp when session was last updated */\n\tupdatedAt: string;\n\t/** Total number of messages in the session */\n\tmessageCount: number;\n\t/** Whether the session is marked as a favorite */\n\tfavorite?: boolean;\n\t/** User-assigned tags for organization */\n\ttags?: string[];\n}\n\nexport type ComposerSessionMessagesView = \"full\" | \"summary\" | \"notLoaded\";\n\nexport interface ComposerPendingClientToolRequest {\n\ttoolCallId: string;\n\ttoolName: string;\n\targs: unknown;\n\tkind?: \"client_tool\" | \"mcp_elicitation\" | \"user_input\";\n\treason?: string;\n}\n\nexport type ComposerPendingRequestKind =\n\t| \"approval\"\n\t| \"client_tool\"\n\t| \"mcp_elicitation\"\n\t| \"user_input\"\n\t| \"tool_retry\";\n\nexport type ComposerPendingRequestResolution =\n\t| \"approved\"\n\t| \"denied\"\n\t| \"completed\"\n\t| \"failed\"\n\t| \"answered\"\n\t| \"retried\"\n\t| \"skipped\"\n\t| \"aborted\"\n\t| \"cancelled\";\n\nexport type ComposerPendingRequestPlatformOperation =\n\t| \"ResolveApproval\"\n\t| \"ResumeToolExecution\"\n\t| \"ResumeRun\";\n\nexport interface ComposerPendingRequestPlatformRef {\n\tsource: \"approvals_service\" | \"tool_execution\";\n\ttoolExecutionId?: string;\n\tapprovalRequestId?: string;\n}\n\nexport interface ComposerPendingRequest {\n\tid: string;\n\tkind: ComposerPendingRequestKind;\n\tstatus: \"pending\";\n\tvisibility: \"user\";\n\tsessionId?: string;\n\ttoolCallId: string;\n\ttoolName: string;\n\tdisplayName?: string;\n\tsummaryLabel?: string;\n\tactionDescription?: string;\n\targs: unknown;\n\treason: string;\n\tcreatedAt: string;\n\texpiresAt?: string;\n\tsource: \"local\" | \"platform\";\n\tplatform?: ComposerPendingRequestPlatformRef;\n}\n\nexport type ComposerClientToolResultContent =\n\t| ComposerTextContent\n\t| ComposerImageContent;\n\nexport interface ComposerPendingRequestResumeRequest {\n\tkind?: ComposerPendingRequestKind;\n\tsessionId?: string;\n\tdecision?: \"approved\" | \"denied\";\n\taction?: \"retry\" | \"skip\" | \"abort\";\n\tcontent?: ComposerClientToolResultContent[];\n\tisError?: boolean;\n\treason?: string;\n}\n\nexport interface ComposerPendingRequestResumeResponse {\n\tsuccess: true;\n\trequest: {\n\t\tid: string;\n\t\tkind: ComposerPendingRequestKind;\n\t\tsessionId?: string;\n\t\tresolution: ComposerPendingRequestResolution;\n\t\tsource: \"local\" | \"platform\";\n\t\tplatform?: ComposerPendingRequestPlatformRef;\n\t\tplatformOperation?: ComposerPendingRequestPlatformOperation;\n\t};\n}\n\nexport type ComposerRunTimelineVisibility = \"user\" | \"admin\" | \"audit\";\n\nexport type ComposerRunTimelineSource = \"local\" | \"platform\";\n\nexport type ComposerRunTimelineEventType =\n\t| \"session.started\"\n\t| \"session.updated\"\n\t| \"message.user\"\n\t| \"message.assistant\"\n\t| \"tool.requested\"\n\t| \"tool.completed\"\n\t| \"tool.failed\"\n\t| \"file.changed\"\n\t| \"diagnostic.delta\"\n\t| \"artifact.linked\"\n\t| \"policy.decision\"\n\t| \"wait.pending\"\n\t| \"agent.run.started\"\n\t| \"agent.run.completed\"\n\t| \"agent.run.failed\"\n\t| \"compaction.created\"\n\t| \"branch.created\"\n\t| \"model.changed\"\n\t| \"thinking.changed\"\n\t| \"runtime.recovery\"\n\t| \"runtime.finished\"\n\t| \"custom.event\";\n\nexport type ComposerRunTimelineStatus =\n\t| \"pending\"\n\t| \"running\"\n\t| \"completed\"\n\t| \"failed\"\n\t| \"approved\"\n\t| \"denied\"\n\t| \"info\";\n\nexport interface ComposerRunTimelineItem {\n\tid: string;\n\tsessionId: string;\n\ttimestamp: string;\n\ttype: ComposerRunTimelineEventType;\n\ttitle: string;\n\tvisibility: ComposerRunTimelineVisibility;\n\tsource: ComposerRunTimelineSource;\n\tstatus?: ComposerRunTimelineStatus;\n\tsummary?: string;\n\trole?: ComposerRole;\n\ttoolCallId?: string;\n\ttoolName?: string;\n\tpendingRequestId?: string;\n\tpendingRequestKind?: ComposerPendingRequestKind;\n\tapprovalRequestId?: string;\n\ttoolExecutionId?: string;\n\tartifactId?: string;\n\tagentRunId?: string;\n\tparentAgentRunId?: string;\n\tchildAgentRunId?: string;\n\tremoteRunnerSessionId?: string;\n\tplatform?: ComposerPendingRequestPlatformRef;\n\tplatformOperation?: ComposerPendingRequestPlatformOperation;\n\tmetadata?: Record<string, unknown>;\n}\n\nexport interface ComposerRunTimelineResponse {\n\tsessionId: string;\n\tsource: ComposerRunTimelineSource;\n\tgeneratedAt: string;\n\tplatformBacked: boolean;\n\tpendingRequestCount: number;\n\titems: ComposerRunTimelineItem[];\n}\n\n/**\n * Full session data including message history.\n *\n * Returned when loading a specific session.\n */\nexport interface ComposerSession extends ComposerSessionSummary {\n\t/** Hydration level used for the messages array. Defaults to full. */\n\tmessagesView?: ComposerSessionMessagesView;\n\t/** Complete conversation history */\n\tmessages: ComposerMessage[];\n\t/** Pending approval requests that still require a decision */\n\tpendingApprovalRequests?: ComposerActionApprovalRequest[];\n\t/** Pending client or ask_user requests that still require client handling */\n\tpendingClientToolRequests?: ComposerPendingClientToolRequest[];\n\t/** Pending tool retry requests that still require a decision */\n\tpendingToolRetryRequests?: ComposerToolRetryRequest[];\n\t/** Unified pending requests for hosted attach, Platform, and admin surfaces */\n\tpendingRequests?: ComposerPendingRequest[];\n}\n\n/**\n * Streaming events emitted while generating assistant messages.\n */\nexport type ComposerAssistantMessageEvent =\n\t| {\n\t\t\ttype: \"start\";\n\t\t\tpartial: ComposerMessage;\n\t }\n\t| {\n\t\t\ttype: \"text_start\";\n\t\t\tcontentIndex: number;\n\t\t\tpartial: ComposerMessage;\n\t }\n\t| {\n\t\t\ttype: \"text_delta\";\n\t\t\tcontentIndex: number;\n\t\t\tdelta: string;\n\t\t\tpartial?: ComposerMessage;\n\t }\n\t| {\n\t\t\ttype: \"text_end\";\n\t\t\tcontentIndex: number;\n\t\t\tcontent: string;\n\t\t\tpartial: ComposerMessage;\n\t }\n\t| {\n\t\t\ttype: \"thinking_start\";\n\t\t\tcontentIndex: number;\n\t\t\tpartial: ComposerMessage;\n\t }\n\t| {\n\t\t\ttype: \"thinking_delta\";\n\t\t\tcontentIndex: number;\n\t\t\tdelta: string;\n\t\t\tpartial?: ComposerMessage;\n\t }\n\t| {\n\t\t\ttype: \"thinking_end\";\n\t\t\tcontentIndex: number;\n\t\t\tcontent: string;\n\t\t\tpartial: ComposerMessage;\n\t }\n\t| {\n\t\t\ttype: \"toolcall_start\";\n\t\t\tcontentIndex: number;\n\t\t\tpartial?: ComposerMessage;\n\t\t\ttoolCallId?: string;\n\t\t\ttoolCallName?: string;\n\t\t\ttoolCallArgs?: Record<string, unknown>;\n\t\t\ttoolCallArgsTruncated?: boolean;\n\t }\n\t| {\n\t\t\ttype: \"toolcall_delta\";\n\t\t\tcontentIndex: number;\n\t\t\tdelta: string;\n\t\t\tpartial?: ComposerMessage;\n\t\t\ttoolCallId?: string;\n\t\t\ttoolCallName?: string;\n\t\t\ttoolCallArgs?: Record<string, unknown>;\n\t\t\ttoolCallArgsTruncated?: boolean;\n\t }\n\t| {\n\t\t\ttype: \"toolcall_end\";\n\t\t\tcontentIndex: number;\n\t\t\ttoolCall: ComposerToolCallContent;\n\t\t\tpartial?: ComposerMessage;\n\t }\n\t| {\n\t\t\ttype: \"done\";\n\t\t\treason: \"stop\" | \"length\" | \"toolUse\";\n\t\t\tmessage: ComposerMessage;\n\t }\n\t| {\n\t\t\ttype: \"error\";\n\t\t\treason: \"aborted\" | \"error\";\n\t\t\terror: ComposerMessage;\n\t };\n\nexport interface ComposerActionApprovalRequest {\n\tid: string;\n\ttoolName: string;\n\tdisplayName?: string;\n\tsummaryLabel?: string;\n\tactionDescription?: string;\n\targs: unknown;\n\treason: string;\n\tstartedAtMs?: number;\n\tplatform?: ComposerPendingRequestPlatformRef;\n}\n\nexport interface ComposerActionApprovalDecision {\n\tapproved: boolean;\n\treason?: string;\n\tresolvedBy: \"policy\" | \"user\";\n\tresolvedAtMs?: number;\n}\n\nexport interface ComposerToolRetryRequest {\n\tid: string;\n\ttoolCallId: string;\n\ttoolName: string;\n\targs: unknown;\n\terrorMessage: string;\n\tattempt: number;\n\tmaxAttempts?: number;\n\tsummary?: string;\n}\n\nexport interface ComposerToolRetryDecision {\n\taction: \"retry\" | \"skip\" | \"abort\";\n\treason?: string;\n\tresolvedBy: \"policy\" | \"user\" | \"runtime\";\n}\n\n/**\n * Agent-level streaming events (SSE payloads).\n */\nexport type ComposerAgentEvent =\n\t| { type: \"agent_start\" }\n\t| {\n\t\t\ttype: \"agent_end\";\n\t\t\tmessages: ComposerMessage[];\n\t\t\taborted?: boolean;\n\t\t\tpartialAccepted?: ComposerMessage;\n\t\t\tstopReason?: \"stop\" | \"length\" | \"toolUse\" | \"error\" | \"aborted\";\n\t }\n\t| { type: \"status\"; status: string; details: Record<string, unknown> }\n\t| { type: \"error\"; message: string }\n\t| { type: \"turn_start\" }\n\t| {\n\t\t\ttype: \"turn_end\";\n\t\t\tmessage: ComposerMessage;\n\t\t\ttoolResults: ComposerMessage[];\n\t }\n\t| { type: \"message_start\"; message: ComposerMessage }\n\t| {\n\t\t\ttype: \"message_update\";\n\t\t\tmessage?: ComposerMessage;\n\t\t\tassistantMessageEvent: ComposerAssistantMessageEvent;\n\t }\n\t| { type: \"message_end\"; message: ComposerMessage }\n\t| {\n\t\t\ttype: \"tool_execution_start\";\n\t\t\ttoolCallId: string;\n\t\t\ttoolName: string;\n\t\t\tdisplayName?: string;\n\t\t\tsummaryLabel?: string;\n\t\t\targs: Record<string, unknown>;\n\t }\n\t| {\n\t\t\ttype: \"tool_execution_update\";\n\t\t\ttoolCallId: string;\n\t\t\ttoolName: string;\n\t\t\tdisplayName?: string;\n\t\t\tsummaryLabel?: string;\n\t\t\targs: Record<string, unknown>;\n\t\t\tpartialResult: unknown;\n\t }\n\t| {\n\t\t\ttype: \"tool_execution_end\";\n\t\t\ttoolCallId: string;\n\t\t\ttoolName: string;\n\t\t\tdisplayName?: string;\n\t\t\tsummaryLabel?: string;\n\t\t\tresult: unknown;\n\t\t\tisError: boolean;\n\t }\n\t| {\n\t\t\ttype: \"tool_batch_summary\";\n\t\t\tsummary: string;\n\t\t\tsummaryLabels: string[];\n\t\t\ttoolCallIds: string[];\n\t\t\ttoolNames: string[];\n\t\t\tcallsSucceeded: number;\n\t\t\tcallsFailed: number;\n\t }\n\t| { type: \"action_approval_required\"; request: ComposerActionApprovalRequest }\n\t| {\n\t\t\ttype: \"action_approval_resolved\";\n\t\t\trequest: ComposerActionApprovalRequest;\n\t\t\tdecision: ComposerActionApprovalDecision;\n\t }\n\t| {\n\t\t\ttype: \"client_tool_request\";\n\t\t\ttoolCallId: string;\n\t\t\ttoolName: string;\n\t\t\targs: unknown;\n\t }\n\t| { type: \"tool_retry_required\"; request: ComposerToolRetryRequest }\n\t| {\n\t\t\ttype: \"tool_retry_resolved\";\n\t\t\trequest: ComposerToolRetryRequest;\n\t\t\tdecision: ComposerToolRetryDecision;\n\t }\n\t| {\n\t\t\ttype: \"compaction\";\n\t\t\tsummary: string;\n\t\t\tfirstKeptEntryIndex: number;\n\t\t\ttokensBefore: number;\n\t\t\tauto?: boolean;\n\t\t\tcustomInstructions?: string;\n\t\t\ttimestamp: string;\n\t }\n\t| {\n\t\t\ttype: \"auto_retry_start\";\n\t\t\tattempt: number;\n\t\t\tmaxAttempts: number;\n\t\t\tdelayMs: number;\n\t\t\terrorMessage: string;\n\t }\n\t| {\n\t\t\ttype: \"auto_retry_end\";\n\t\t\tsuccess: boolean;\n\t\t\tattempt: number;\n\t\t\tfinalError?: string;\n\t }\n\t| { type: \"session_update\"; sessionId: string }\n\t| { type: \"heartbeat\" }\n\t| { type: \"aborted\" }\n\t| { type: \"done\" };\n\n/**\n * Error severity levels for API payloads.\n */\nexport type ComposerErrorSeverity = \"error\" | \"warning\" | \"info\";\n\n/**\n * Error categories for API payloads.\n */\nexport type ComposerErrorCategory =\n\t| \"validation\"\n\t| \"permission\"\n\t| \"network\"\n\t| \"timeout\"\n\t| \"filesystem\"\n\t| \"tool\"\n\t| \"session\"\n\t| \"config\"\n\t| \"api\"\n\t| \"internal\";\n\n/**\n * Structured error payload for API responses.\n */\nexport interface ComposerErrorPayload {\n\tcode: string;\n\tcategory: ComposerErrorCategory;\n\tseverity?: ComposerErrorSeverity;\n\tretriable?: boolean;\n\tcontext?: Record<string, unknown>;\n}\n\n/**\n * Standard API error response shape.\n */\nexport interface ComposerErrorResponse {\n\terror: string;\n\tcode?: string;\n\tdetails?: Record<string, unknown>[];\n\tcomposer?: ComposerErrorPayload;\n}\n\n/**\n * Response payload for session list endpoint.\n */\nexport interface ComposerSessionListResponse {\n\t/** Array of session summaries */\n\tsessions: ComposerSessionSummary[];\n}\n\n/**\n * SSE event sent when a session is created or updated.\n *\n * Allows clients to sync session state in real-time.\n */\nexport interface ComposerSessionUpdateEvent {\n\ttype: \"session_update\";\n\t/** ID of the created/updated session */\n\tsessionId: string;\n}\n\n/**\n * Background task resource limit breach metadata.\n */\nexport interface ComposerBackgroundTaskLimitBreach {\n\tkind: \"memory\" | \"cpu\";\n\tlimit: number;\n\tactual: number;\n}\n\n/**\n * Background task history record.\n */\nexport interface ComposerBackgroundTaskHistoryEntry {\n\tevent: \"started\" | \"restarted\" | \"exited\" | \"failed\" | \"stopped\";\n\ttaskId: string;\n\tstatus: string;\n\tcommand: string;\n\ttimestamp: string;\n\trestartAttempts: number;\n\tfailureReason?: string;\n\tlimitBreach?: ComposerBackgroundTaskLimitBreach;\n}\n\n/**\n * Background task health entry.\n */\nexport interface ComposerBackgroundTaskHealthEntry {\n\tid: string;\n\tstatus: string;\n\tsummary: string;\n\tcommand: string;\n\trestarts?: string;\n\tissues: string[];\n\tlastLogLine?: string;\n\tlogTruncated?: boolean;\n\tdurationSeconds: number;\n}\n\n/**\n * Background task health snapshot.\n */\nexport interface ComposerBackgroundTaskHealth {\n\ttotal: number;\n\trunning: number;\n\trestarting: number;\n\tfailed: number;\n\tentries: ComposerBackgroundTaskHealthEntry[];\n\ttruncated: boolean;\n\tnotificationsEnabled: boolean;\n\tdetailsRedacted: boolean;\n\thistory: ComposerBackgroundTaskHistoryEntry[];\n\thistoryTruncated: boolean;\n}\n\nexport type ComposerGuardianTarget = \"staged\" | \"all\";\n\nexport type ComposerGuardianStatus = \"passed\" | \"failed\" | \"skipped\" | \"error\";\n\nexport interface ComposerGuardianToolResult {\n\ttool: string;\n\texitCode: number;\n\tstdout: string;\n\tstderr: string;\n\tdurationMs: number;\n\tskipped?: boolean;\n\treason?: string;\n}\n\nexport interface ComposerGuardianRunResult {\n\tstatus: ComposerGuardianStatus;\n\texitCode: number;\n\tstartedAt: number;\n\tdurationMs: number;\n\ttarget: ComposerGuardianTarget;\n\ttrigger?: string;\n\tfilesScanned: number;\n\tfiles?: string[];\n\tsummary: string;\n\tskipReason?: string;\n\ttoolResults: ComposerGuardianToolResult[];\n}\n\nexport interface ComposerGuardianState {\n\tenabled: boolean;\n\tlastRun?: ComposerGuardianRunResult;\n}\n\nexport interface ComposerGuardianStatusResponse {\n\tenabled: boolean;\n\tstate: ComposerGuardianState;\n}\n\nexport type ComposerGuardianRunResponse = ComposerGuardianRunResult;\n\nexport interface ComposerGuardianConfigRequest {\n\tenabled: boolean;\n}\n\nexport interface ComposerGuardianConfigResponse {\n\tsuccess: boolean;\n\tenabled: boolean;\n}\n\nexport interface ComposerPlanModeState {\n\tactive: boolean;\n\tfilePath: string;\n\tsessionId?: string;\n\tgitBranch?: string;\n\tgitCommitSha?: string;\n\tcreatedAt: string;\n\tupdatedAt: string;\n\tname?: string;\n}\n\nexport interface ComposerPlanStatusResponse {\n\tstate: ComposerPlanModeState | null;\n\tcontent: string | null;\n}\n\nexport type ComposerPlanRequest =\n\t| { action: \"enter\"; name?: string; sessionId?: string }\n\t| { action: \"exit\" }\n\t| { action: \"update\"; content: string };\n\nexport type ComposerPlanActionResponse =\n\t| { success: boolean; state: ComposerPlanModeState }\n\t| { success: boolean };\n\nexport interface ComposerBackgroundSettings {\n\tnotificationsEnabled: boolean;\n\tstatusDetailsEnabled: boolean;\n}\n\nexport interface ComposerBackgroundStatusSnapshot {\n\trunning: number;\n\ttotal: number;\n\tfailed: number;\n\tdetailsRedacted: boolean;\n}\n\nexport interface ComposerBackgroundStatusResponse {\n\tsettings: ComposerBackgroundSettings;\n\tsnapshot: ComposerBackgroundStatusSnapshot | null;\n}\n\nexport interface ComposerBackgroundHistoryEntry {\n\ttimestamp: string;\n\tevent: \"started\" | \"restarted\" | \"exited\" | \"failed\" | \"stopped\";\n\ttaskId: string;\n\tcommand: string;\n\tfailureReason?: string;\n\tlimitBreach?: ComposerBackgroundTaskLimitBreach;\n}\n\nexport interface ComposerBackgroundHistoryResponse {\n\thistory: ComposerBackgroundHistoryEntry[];\n\ttruncated: boolean;\n}\n\nexport interface ComposerBackgroundPathResponse {\n\tpath: string;\n\texists: boolean;\n\toverridden: boolean;\n}\n\nexport interface ComposerBackgroundUpdateRequest {\n\tenabled: boolean;\n}\n\nexport interface ComposerBackgroundUpdateResponse {\n\tsuccess: boolean;\n\tmessage: string;\n}\n\nexport type ComposerApprovalMode = \"auto\" | \"prompt\" | \"fail\";\n\nexport interface ComposerApprovalsStatusResponse {\n\tmode: ComposerApprovalMode;\n\tavailableModes: ComposerApprovalMode[];\n}\n\nexport interface ComposerApprovalsUpdateRequest {\n\tmode: ComposerApprovalMode;\n\tsessionId?: string;\n}\n\nexport interface ComposerApprovalsUpdateResponse {\n\tsuccess: boolean;\n\tmode: ComposerApprovalMode;\n\tmessage: string;\n}\n\nexport type ComposerFrameworkScope = \"user\" | \"workspace\";\n\nexport interface ComposerFrameworkStatusResponse {\n\tframework: string;\n\tsource: string;\n\tlocked: boolean;\n\tscope: ComposerFrameworkScope;\n}\n\nexport interface ComposerFrameworkListEntry {\n\tid: string;\n\tsummary: string;\n}\n\nexport interface ComposerFrameworkListResponse {\n\tframeworks: ComposerFrameworkListEntry[];\n}\n\nexport interface ComposerFrameworkUpdateRequest {\n\tframework?: string | null;\n\tscope?: ComposerFrameworkScope;\n}\n\nexport interface ComposerFrameworkUpdateResponse {\n\tsuccess: boolean;\n\tmessage: string;\n\tframework: string | null;\n\tsummary?: string;\n\tscope?: ComposerFrameworkScope;\n}\n\nexport type ComposerChangeType = \"create\" | \"modify\" | \"delete\";\n\nexport interface ComposerFileChange {\n\tid: string;\n\ttype: ComposerChangeType;\n\tpath: string;\n\tbefore: string | null;\n\tafter: string | null;\n\ttoolName: string;\n\ttoolCallId: string;\n\ttimestamp: number;\n\tisGitTracked: boolean;\n\tmessageId?: string;\n}\n\nexport type ComposerUndoRestoreAction = \"restore\" | \"delete\" | \"recreate\";\n\nexport interface ComposerUndoPreview {\n\tchanges: ComposerFileChange[];\n\trestores: Array<{ path: string; action: ComposerUndoRestoreAction }>;\n\tconflicts: Array<{ path: string; reason: string }>;\n}\n\nexport interface ComposerUndoCheckpoint {\n\tname: string;\n\tdescription?: string;\n\tchangeCount: number;\n\ttimestamp: number;\n}\n\nexport interface ComposerUndoStatusResponse {\n\ttotalChanges: number;\n\tcanUndo: boolean;\n\tcheckpoints: ComposerUndoCheckpoint[];\n}\n\nexport interface ComposerUndoHistoryEntry {\n\tdescription: string;\n\tfileCount: number;\n\ttimestamp: number;\n}\n\nexport interface ComposerUndoHistoryResponse {\n\thistory: ComposerUndoHistoryEntry[];\n}\n\nexport interface ComposerUndoPreviewMessage {\n\tmessage: string;\n\tfileCount?: number;\n\tdescription?: string;\n}\n\nexport interface ComposerUndoRequest {\n\taction?: \"undo\" | \"checkpoint\" | \"restore\";\n\tcount?: number;\n\tpreview?: boolean;\n\tforce?: boolean;\n\tname?: string;\n\tdescription?: string;\n}\n\nexport type ComposerUndoOperationResponse =\n\t| { success: boolean; undone: number; errors: string[] }\n\t| { success: boolean; message: string; files?: string[] }\n\t| { message: string }\n\t| { preview: ComposerUndoPreview | ComposerUndoPreviewMessage }\n\t| {\n\t\t\tsuccess: boolean;\n\t\t\tcheckpoint: { name: string; changeCount: number; timestamp: number };\n\t }\n\t| { checkpoints: ComposerUndoCheckpoint[] };\n\nexport interface ComposerProjectOnboardingStep {\n\tkey: \"workspace\" | \"instructions\";\n\ttext: string;\n\tisComplete: boolean;\n\tisEnabled: boolean;\n}\n\nexport interface ComposerProjectOnboardingState {\n\tshouldShow: boolean;\n\tcompleted: boolean;\n\tseenCount: number;\n\tsteps: ComposerProjectOnboardingStep[];\n}\n\n/**\n * Workspace status response payload.\n */\nexport interface ComposerStatusResponse {\n\tcwd: string;\n\tgit: {\n\t\tbranch: string;\n\t\tstatus: {\n\t\t\tmodified: number;\n\t\t\tadded: number;\n\t\t\tdeleted: number;\n\t\t\tuntracked: number;\n\t\t\ttotal: number;\n\t\t};\n\t} | null;\n\tcontext: {\n\t\tagentMd: boolean;\n\t\tclaudeMd: boolean;\n\t};\n\tonboarding?: ComposerProjectOnboardingState;\n\tserver: {\n\t\tuptime: number;\n\t\tversion: string;\n\t\tstaticCacheMaxAgeSeconds?: number;\n\t};\n\tdatabase: {\n\t\tconfigured: boolean;\n\t\tconnected: boolean;\n\t};\n\tbackgroundTasks: ComposerBackgroundTaskHealth | null;\n\thooks: {\n\t\tasyncInFlight: number;\n\t\tconcurrency: {\n\t\t\tmax: number;\n\t\t\tactive: number;\n\t\t\tqueued: number;\n\t\t};\n\t};\n\tlastUpdated: number;\n\tlastLatencyMs: number;\n}\n\n/**\n * Token totals for usage summaries.\n */\nexport interface ComposerUsageTokenTotals {\n\tinput: number;\n\toutput: number;\n\tcacheRead: number;\n\tcacheWrite: number;\n\ttotal: number;\n}\n\n/**\n * Usage breakdown entry.\n */\nexport interface ComposerUsageBreakdown {\n\tcost: number;\n\trequests: number;\n\ttokens: number;\n\ttokensDetailed: ComposerUsageTokenTotals;\n\tcalls: number;\n\tcachedTokens: number;\n}\n\n/**\n * Usage summary response payload.\n */\nexport interface ComposerUsageSummary {\n\ttotalCost: number;\n\ttotalRequests: number;\n\ttotalTokens: number;\n\ttokensDetailed: ComposerUsageTokenTotals;\n\ttotalTokensDetailed: ComposerUsageTokenTotals;\n\ttotalTokensBreakdown: ComposerUsageTokenTotals;\n\ttotalCachedTokens: number;\n\tbyProvider: Record<string, ComposerUsageBreakdown>;\n\tbyModel: Record<string, ComposerUsageBreakdown>;\n}\n\n/**\n * Usage API response payload.\n */\nexport interface ComposerUsageResponse {\n\tsummary: ComposerUsageSummary;\n\thasData: boolean;\n}\n\n// Runtime schemas + validators\nexport * from \"./schemas.js\";\nexport * from \"./validators.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,cAAc,kCAAkC,CAAC;AACjD,cAAc,0CAA0C,CAAC;AACzD,OAAO,KAAK,aAAa,MAAM,mCAAmC,CAAC;AACnE,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mCAAmC,CAAC;AAClD,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,eAAe,CAAC;AAksC9B,+BAA+B;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC","sourcesContent":["/**\n * @fileoverview @evalops/contracts - Shared TypeScript Definitions\n *\n * This package provides the TypeScript type definitions that form the contract\n * between Composer's frontend (Web UI) and backend (API server). All shared\n * types, interfaces, and enums are defined here to ensure type safety across\n * the client-server boundary.\n *\n * ## Key Types\n *\n * | Type | Description |\n * |------|-------------|\n * | `ComposerMessage` | Chat message with role, content, tools, and usage |\n * | `ComposerSession` | Session with metadata and message history |\n * | `ComposerChatRequest` | Request payload for the chat API |\n * | `ComposerUsage` | Token usage and cost tracking |\n * | `ComposerToolCall` | Tool invocation with status and result |\n *\n * ## Usage\n *\n * ```typescript\n * import type {\n * ComposerMessage,\n * ComposerSession,\n * ComposerChatRequest\n * } from \"@evalops/contracts\";\n *\n * // Type-safe message handling\n * const message: ComposerMessage = {\n * role: \"user\",\n * content: \"Hello, Composer!\",\n * timestamp: new Date().toISOString(),\n * };\n *\n * // Type-safe API request\n * const request: ComposerChatRequest = {\n * messages: [message],\n * model: \"claude-sonnet-4-5\",\n * thinkingLevel: \"medium\",\n * };\n * ```\n *\n * @module @evalops/contracts\n */\n\nexport * from \"./headless-protocol-generated.js\";\nexport * from \"./headless-protocol-schemas.generated.js\";\nexport * as headlessProto from \"./proto/maestro/v1/headless_pb.js\";\nexport * from \"./advisor-effort.js\";\nexport * from \"./artifacts.js\";\nexport * from \"./delegation-prompt.js\";\nexport * from \"./guarded-files-settings.js\";\nexport * from \"./key-value-tokens.js\";\nexport * from \"./mcp-settings.js\";\nexport * from \"./memory.js\";\nexport * from \"./memory-utils.js\";\nexport * from \"./maestro-app-server.js\";\nexport * from \"./onboarding-utils.js\";\nexport * from \"./proto/maestro/v1/headless_pb.js\";\nexport * from \"./runtime-constraints.js\";\nexport * from \"./runtime-app-server.js\";\nexport * from \"./runtime-server-request.js\";\nexport * from \"./scenario.js\";\n\n/**\n * Role of a message in the conversation.\n *\n * - `user` - Messages from the human user\n * - `assistant` - Messages from the AI assistant\n * - `system` - System prompts and instructions\n * - `tool` - Tool execution results\n */\nexport type ComposerRole = \"user\" | \"assistant\" | \"system\" | \"tool\";\n\n/**\n * Content blocks used for rich message payloads.\n */\nexport interface ComposerTextContent {\n\ttype: \"text\";\n\ttext: string;\n\ttextSignature?: string;\n}\n\nexport interface ComposerImageContent {\n\ttype: \"image\";\n\tdata: string;\n\tmimeType: string;\n}\n\nexport interface ComposerThinkingContent {\n\ttype: \"thinking\";\n\tthinking: string;\n\tthinkingSignature?: string;\n}\n\nexport interface ComposerToolCallContent {\n\ttype: \"toolCall\";\n\tid: string;\n\tname: string;\n\targuments: Record<string, unknown>;\n\tthoughtSignature?: string;\n}\n\nexport type ComposerContentBlock =\n\t| ComposerTextContent\n\t| ComposerImageContent\n\t| ComposerThinkingContent\n\t| ComposerToolCallContent;\n\n/**\n * Extended thinking/reasoning level for supported models.\n *\n * Higher levels produce more detailed reasoning at the cost of latency:\n * - `off` - No extended thinking\n * - `minimal` - Brief reasoning hints\n * - `low` - Light reasoning\n * - `medium` - Moderate reasoning depth\n * - `high` - Thorough step-by-step reasoning\n */\nexport type ComposerThinkingLevel =\n\t| \"off\"\n\t| \"minimal\"\n\t| \"low\"\n\t| \"medium\"\n\t| \"high\";\n\n/**\n * Represents a tool invocation within a message.\n *\n * Tools are actions the agent can take like reading files, executing commands,\n * or searching the web. Each tool call tracks its execution lifecycle.\n */\nexport interface ComposerToolCall {\n\t/** Name of the tool being invoked (e.g., \"read\", \"bash\", \"search\") */\n\tname: string;\n\t/** Current execution status of the tool call */\n\tstatus: \"pending\" | \"running\" | \"completed\" | \"error\";\n\t/** Arguments passed to the tool */\n\targs?: Record<string, unknown>;\n\t/** Result returned by the tool (if completed) */\n\tresult?: unknown;\n\t/** Unique identifier for this tool call (for matching results) */\n\ttoolCallId?: string;\n}\n\n/**\n * File attachment included in a user message.\n *\n * Attachments can be images (for vision-capable models) or documents\n * (typically accompanied by extracted text for model consumption).\n *\n * `content` is base64-encoded raw bytes. Servers may omit `content` in some\n * read APIs for size reasons; when omitted, `contentOmitted` is set to true.\n */\nexport interface ComposerAttachment {\n\t/** Unique identifier for this attachment */\n\tid: string;\n\t/** Attachment type */\n\ttype: \"image\" | \"document\";\n\t/** Original filename */\n\tfileName: string;\n\t/** MIME type */\n\tmimeType: string;\n\t/** Size in bytes */\n\tsize: number;\n\t/** Base64-encoded file content (may be omitted) */\n\tcontent?: string;\n\t/** True when `content` was intentionally omitted */\n\tcontentOmitted?: boolean;\n\t/** Extracted text content (for documents) */\n\textractedText?: string;\n\t/** Preview image (typically base64, small) */\n\tpreview?: string;\n}\n\n/**\n * A message in the Composer conversation.\n *\n * Messages can contain text content, tool calls, thinking traces,\n * and usage statistics. This is the primary data structure for\n * conversation history.\n */\nexport interface ComposerMessage {\n\t/** Role of the message sender */\n\trole: ComposerRole;\n\t/** Text content of the message */\n\tcontent: string | ComposerContentBlock[];\n\t/** Optional file attachments (for user messages) */\n\tattachments?: ComposerAttachment[];\n\t/** ISO 8601 timestamp when the message was created */\n\ttimestamp?: string;\n\t/** Extended thinking/reasoning trace (for supported models) */\n\tthinking?: string;\n\t/** Tool calls made in this message (for assistant messages) */\n\ttools?: ComposerToolCall[];\n\t/** Name of the tool (for tool result messages) */\n\ttoolName?: string;\n\t/** Whether this message represents an error */\n\tisError?: boolean;\n\t/** Token usage and cost for this message */\n\tusage?: ComposerUsage;\n\t/** Original provider for assistant messages (for cross-provider resume) */\n\tprovider?: string;\n\t/** Original API for assistant messages (for cross-provider resume) */\n\tapi?: string;\n\t/** Original model ID for assistant messages (for cross-provider resume) */\n\tmodel?: string;\n}\n\n/**\n * Cost breakdown for token usage.\n *\n * Costs are typically in USD, calculated based on the model's pricing.\n */\nexport interface ComposerUsageCost {\n\t/** Cost for input tokens */\n\tinput: number;\n\t/** Cost for output tokens */\n\toutput: number;\n\t/** Cost savings from cache reads (if applicable) */\n\tcacheRead?: number;\n\t/** Cost for cache writes (if applicable) */\n\tcacheWrite?: number;\n\t/** Total cost for this message */\n\ttotal?: number;\n}\n\n/**\n * Token usage statistics for a message or session.\n *\n * Tracks input/output tokens and cache utilization for cost monitoring.\n */\nexport interface ComposerUsage {\n\t/** Number of input tokens consumed */\n\tinput: number;\n\t/** Number of output tokens generated */\n\toutput: number;\n\t/** Tokens served from cache (reduces cost) */\n\tcacheRead?: number;\n\t/** Tokens written to cache */\n\tcacheWrite?: number;\n\t/** Calculated cost breakdown */\n\tcost?: ComposerUsageCost;\n}\n\n/**\n * Model capability metadata exposed by the API.\n */\nexport interface ComposerModelCapabilities {\n\tstreaming?: boolean;\n\ttools?: boolean;\n\tvision?: boolean;\n\treasoning?: boolean;\n}\n\n/**\n * Model metadata returned by `/api/models` and `/api/model`.\n */\nexport interface ComposerModel {\n\tid: string;\n\tprovider: string;\n\tname: string;\n\tapi?: string;\n\tcontextWindow?: number;\n\tmaxOutputTokens?: number;\n\tmaxTokens?: number;\n\treasoning?: boolean;\n\tcost?: ComposerUsageCost;\n\tcapabilities?: ComposerModelCapabilities;\n}\n\n/**\n * Response payload for `/api/models`.\n */\nexport interface ComposerModelListResponse {\n\tmodels: ComposerModel[];\n}\n\n/**\n * Argument definition for a custom command.\n */\nexport interface ComposerCommandArg {\n\tname: string;\n\trequired?: boolean;\n}\n\n/**\n * Custom command definition (safe for client consumption).\n */\nexport interface ComposerCommand {\n\tname: string;\n\tdescription?: string;\n\tprompt: string;\n\targs?: ComposerCommandArg[];\n}\n\n/**\n * Response payload for `/api/commands`.\n */\nexport interface ComposerCommandListResponse {\n\tcommands: ComposerCommand[];\n}\n\n/**\n * Command favorites/recents preferences.\n */\nexport interface ComposerCommandPrefs {\n\tfavorites: string[];\n\trecents: string[];\n}\n\n/**\n * Update payload for command preferences.\n */\nexport interface ComposerCommandPrefsUpdate {\n\tfavorites?: string[];\n\trecents?: string[];\n}\n\n/**\n * Response payload for command preference updates.\n */\nexport interface ComposerCommandPrefsWriteResponse {\n\tok: boolean;\n}\n\n/**\n * Request payload for `/api/config`.\n */\nexport interface ComposerConfigWriteRequest {\n\tconfig: Record<string, unknown>;\n}\n\n/**\n * Response payload for `/api/config` GET.\n */\nexport interface ComposerConfigResponse {\n\tconfig: Record<string, unknown>;\n\tconfigPath: string;\n}\n\n/**\n * Response payload for `/api/config` POST.\n */\nexport interface ComposerConfigWriteResponse {\n\tsuccess: boolean;\n}\n\n/**\n * Response payload for `/api/files`.\n */\nexport interface ComposerFilesResponse {\n\tfiles: string[];\n}\n\n/**\n * Request payload for the chat API endpoint.\n *\n * Sent to `POST /api/chat` to initiate or continue a conversation.\n */\nexport interface ComposerChatRequest {\n\t/** Model ID to use (e.g., \"claude-sonnet-4-5-20250929\") */\n\tmodel?: string;\n\t/** Conversation history including the current user message */\n\tmessages: ComposerMessage[];\n\t/** Extended thinking level for supported models */\n\tthinkingLevel?: ComposerThinkingLevel;\n\t/** Session ID to resume (optional - creates new session if omitted) */\n\tsessionId?: string;\n\t/** Whether to stream the response via SSE (default: true) */\n\tstream?: boolean;\n}\n\n/**\n * Request payload for prompt suggestion generation.\n *\n * Sent to `POST /api/prompt-suggestion` to generate a likely next user prompt\n * from the current conversation state.\n */\nexport interface ComposerPromptSuggestionRequest {\n\t/** Optional model preference used to select a suggestion model. */\n\tmodel?: string;\n\t/** Conversation history to summarize into a likely next user prompt. */\n\tmessages: ComposerMessage[];\n\t/** Optional session id for callers that want request correlation. */\n\tsessionId?: string;\n}\n\n/**\n * Response payload for prompt suggestion generation.\n */\nexport interface ComposerPromptSuggestionResponse {\n\t/** Suggested next user prompt, or null when suggestion generation is suppressed. */\n\tsuggestion: string | null;\n\t/** Optional suppression or filtering reason when no suggestion is returned. */\n\tsuppressedReason?: string;\n\t/** Model used to generate the suggestion, when generation ran. */\n\tmodel?: string;\n}\n\n/**\n * Summary metadata for a session (without full message history).\n *\n * Used in session list views for performance.\n */\nexport interface ComposerSessionSummary {\n\t/** Unique session identifier */\n\tid: string;\n\t/** User-assigned or auto-generated title */\n\ttitle?: string;\n\t/** Short persisted recap shown when resuming a session */\n\tresumeSummary?: string;\n\t/** ISO 8601 timestamp when session was created */\n\tcreatedAt: string;\n\t/** ISO 8601 timestamp when session was last updated */\n\tupdatedAt: string;\n\t/** Total number of messages in the session */\n\tmessageCount: number;\n\t/** Whether the session is marked as a favorite */\n\tfavorite?: boolean;\n\t/** User-assigned tags for organization */\n\ttags?: string[];\n}\n\nexport type ComposerSessionMessagesView = \"full\" | \"summary\" | \"notLoaded\";\n\nexport interface ComposerPendingClientToolRequest {\n\ttoolCallId: string;\n\ttoolName: string;\n\targs: unknown;\n\tkind?: \"client_tool\" | \"mcp_elicitation\" | \"user_input\";\n\treason?: string;\n}\n\nexport type ComposerPendingRequestKind =\n\t| \"approval\"\n\t| \"client_tool\"\n\t| \"mcp_elicitation\"\n\t| \"user_input\"\n\t| \"tool_retry\";\n\nexport type ComposerPendingRequestResolution =\n\t| \"approved\"\n\t| \"denied\"\n\t| \"completed\"\n\t| \"failed\"\n\t| \"answered\"\n\t| \"retried\"\n\t| \"skipped\"\n\t| \"aborted\"\n\t| \"cancelled\";\n\nexport type ComposerPendingRequestPlatformOperation =\n\t| \"ResolveApproval\"\n\t| \"ResumeToolExecution\"\n\t| \"ResumeRun\";\n\nexport interface ComposerPendingRequestPlatformRef {\n\tsource: \"approvals_service\" | \"tool_execution\";\n\ttoolExecutionId?: string;\n\tapprovalRequestId?: string;\n}\n\nexport interface ComposerPendingRequest {\n\tid: string;\n\tkind: ComposerPendingRequestKind;\n\tstatus: \"pending\";\n\tvisibility: \"user\";\n\tsessionId?: string;\n\ttoolCallId: string;\n\ttoolName: string;\n\tdisplayName?: string;\n\tsummaryLabel?: string;\n\tactionDescription?: string;\n\targs: unknown;\n\treason: string;\n\tcreatedAt: string;\n\texpiresAt?: string;\n\tsource: \"local\" | \"platform\";\n\tplatform?: ComposerPendingRequestPlatformRef;\n}\n\nexport type ComposerClientToolResultContent =\n\t| ComposerTextContent\n\t| ComposerImageContent;\n\nexport interface ComposerPendingRequestResumeRequest {\n\tkind?: ComposerPendingRequestKind;\n\tsessionId?: string;\n\tdecision?: \"approved\" | \"denied\";\n\taction?: \"retry\" | \"skip\" | \"abort\";\n\tcontent?: ComposerClientToolResultContent[];\n\tisError?: boolean;\n\treason?: string;\n}\n\nexport interface ComposerPendingRequestResumeResponse {\n\tsuccess: true;\n\trequest: {\n\t\tid: string;\n\t\tkind: ComposerPendingRequestKind;\n\t\tsessionId?: string;\n\t\tresolution: ComposerPendingRequestResolution;\n\t\tsource: \"local\" | \"platform\";\n\t\tplatform?: ComposerPendingRequestPlatformRef;\n\t\tplatformOperation?: ComposerPendingRequestPlatformOperation;\n\t};\n}\n\nexport type ComposerRunTimelineVisibility = \"user\" | \"admin\" | \"audit\";\n\nexport type ComposerRunTimelineSource = \"local\" | \"platform\";\n\nexport type ComposerRunTimelineEventType =\n\t| \"session.started\"\n\t| \"session.updated\"\n\t| \"message.user\"\n\t| \"message.assistant\"\n\t| \"tool.requested\"\n\t| \"tool.completed\"\n\t| \"tool.failed\"\n\t| \"file.changed\"\n\t| \"diagnostic.delta\"\n\t| \"artifact.linked\"\n\t| \"policy.decision\"\n\t| \"wait.pending\"\n\t| \"agent.run.started\"\n\t| \"agent.run.completed\"\n\t| \"agent.run.failed\"\n\t| \"compaction.created\"\n\t| \"branch.created\"\n\t| \"model.changed\"\n\t| \"thinking.changed\"\n\t| \"runtime.recovery\"\n\t| \"runtime.finished\"\n\t| \"custom.event\";\n\nexport type ComposerRunTimelineStatus =\n\t| \"pending\"\n\t| \"running\"\n\t| \"completed\"\n\t| \"failed\"\n\t| \"approved\"\n\t| \"denied\"\n\t| \"info\";\n\nexport interface ComposerRunTimelineItem {\n\tid: string;\n\tsessionId: string;\n\ttimestamp: string;\n\ttype: ComposerRunTimelineEventType;\n\ttitle: string;\n\tvisibility: ComposerRunTimelineVisibility;\n\tsource: ComposerRunTimelineSource;\n\tstatus?: ComposerRunTimelineStatus;\n\tsummary?: string;\n\trole?: ComposerRole;\n\ttoolCallId?: string;\n\ttoolName?: string;\n\tpendingRequestId?: string;\n\tpendingRequestKind?: ComposerPendingRequestKind;\n\tapprovalRequestId?: string;\n\ttoolExecutionId?: string;\n\tartifactId?: string;\n\tagentRunId?: string;\n\tparentAgentRunId?: string;\n\tchildAgentRunId?: string;\n\tremoteRunnerSessionId?: string;\n\tplatform?: ComposerPendingRequestPlatformRef;\n\tplatformOperation?: ComposerPendingRequestPlatformOperation;\n\tmetadata?: Record<string, unknown>;\n}\n\nexport interface ComposerRunTimelineResponse {\n\tsessionId: string;\n\tsource: ComposerRunTimelineSource;\n\tgeneratedAt: string;\n\tplatformBacked: boolean;\n\tpendingRequestCount: number;\n\titems: ComposerRunTimelineItem[];\n}\n\n/**\n * Full session data including message history.\n *\n * Returned when loading a specific session.\n */\nexport interface ComposerSession extends ComposerSessionSummary {\n\t/** Hydration level used for the messages array. Defaults to full. */\n\tmessagesView?: ComposerSessionMessagesView;\n\t/** Complete conversation history */\n\tmessages: ComposerMessage[];\n\t/** Pending approval requests that still require a decision */\n\tpendingApprovalRequests?: ComposerActionApprovalRequest[];\n\t/** Pending client or ask_user requests that still require client handling */\n\tpendingClientToolRequests?: ComposerPendingClientToolRequest[];\n\t/** Pending tool retry requests that still require a decision */\n\tpendingToolRetryRequests?: ComposerToolRetryRequest[];\n\t/** Unified pending requests for hosted attach, Platform, and admin surfaces */\n\tpendingRequests?: ComposerPendingRequest[];\n}\n\n/**\n * Streaming events emitted while generating assistant messages.\n */\nexport type ComposerAssistantMessageEvent =\n\t| {\n\t\t\ttype: \"start\";\n\t\t\tpartial: ComposerMessage;\n\t }\n\t| {\n\t\t\ttype: \"text_start\";\n\t\t\tcontentIndex: number;\n\t\t\tpartial: ComposerMessage;\n\t }\n\t| {\n\t\t\ttype: \"text_delta\";\n\t\t\tcontentIndex: number;\n\t\t\tdelta: string;\n\t\t\tpartial?: ComposerMessage;\n\t }\n\t| {\n\t\t\ttype: \"text_end\";\n\t\t\tcontentIndex: number;\n\t\t\tcontent: string;\n\t\t\tpartial: ComposerMessage;\n\t }\n\t| {\n\t\t\ttype: \"thinking_start\";\n\t\t\tcontentIndex: number;\n\t\t\tpartial: ComposerMessage;\n\t }\n\t| {\n\t\t\ttype: \"thinking_delta\";\n\t\t\tcontentIndex: number;\n\t\t\tdelta: string;\n\t\t\tpartial?: ComposerMessage;\n\t }\n\t| {\n\t\t\ttype: \"thinking_end\";\n\t\t\tcontentIndex: number;\n\t\t\tcontent: string;\n\t\t\tpartial: ComposerMessage;\n\t }\n\t| {\n\t\t\ttype: \"toolcall_start\";\n\t\t\tcontentIndex: number;\n\t\t\tpartial?: ComposerMessage;\n\t\t\ttoolCallId?: string;\n\t\t\ttoolCallName?: string;\n\t\t\ttoolCallArgs?: Record<string, unknown>;\n\t\t\ttoolCallArgsTruncated?: boolean;\n\t }\n\t| {\n\t\t\ttype: \"toolcall_delta\";\n\t\t\tcontentIndex: number;\n\t\t\tdelta: string;\n\t\t\tpartial?: ComposerMessage;\n\t\t\ttoolCallId?: string;\n\t\t\ttoolCallName?: string;\n\t\t\ttoolCallArgs?: Record<string, unknown>;\n\t\t\ttoolCallArgsTruncated?: boolean;\n\t }\n\t| {\n\t\t\ttype: \"toolcall_end\";\n\t\t\tcontentIndex: number;\n\t\t\ttoolCall: ComposerToolCallContent;\n\t\t\tpartial?: ComposerMessage;\n\t }\n\t| {\n\t\t\ttype: \"done\";\n\t\t\treason: \"stop\" | \"length\" | \"toolUse\";\n\t\t\tmessage: ComposerMessage;\n\t }\n\t| {\n\t\t\ttype: \"error\";\n\t\t\treason: \"aborted\" | \"error\";\n\t\t\terror: ComposerMessage;\n\t };\n\nexport interface ComposerActionApprovalRequest {\n\tid: string;\n\ttoolName: string;\n\tdisplayName?: string;\n\tsummaryLabel?: string;\n\tactionDescription?: string;\n\targs: unknown;\n\treason: string;\n\tstartedAtMs?: number;\n\tplatform?: ComposerPendingRequestPlatformRef;\n}\n\nexport interface ComposerActionApprovalDecision {\n\tapproved: boolean;\n\treason?: string;\n\tresolvedBy: \"policy\" | \"user\";\n\tresolvedAtMs?: number;\n}\n\nexport interface ComposerToolRetryRequest {\n\tid: string;\n\ttoolCallId: string;\n\ttoolName: string;\n\targs: unknown;\n\terrorMessage: string;\n\tattempt: number;\n\tmaxAttempts?: number;\n\tsummary?: string;\n}\n\nexport interface ComposerToolRetryDecision {\n\taction: \"retry\" | \"skip\" | \"abort\";\n\treason?: string;\n\tresolvedBy: \"policy\" | \"user\" | \"runtime\";\n}\n\n/**\n * Agent-level streaming events (SSE payloads).\n */\nexport type ComposerAgentEvent =\n\t| { type: \"agent_start\" }\n\t| {\n\t\t\ttype: \"agent_end\";\n\t\t\tmessages: ComposerMessage[];\n\t\t\taborted?: boolean;\n\t\t\tpartialAccepted?: ComposerMessage;\n\t\t\tstopReason?: \"stop\" | \"length\" | \"toolUse\" | \"error\" | \"aborted\";\n\t }\n\t| { type: \"status\"; status: string; details: Record<string, unknown> }\n\t| { type: \"error\"; message: string }\n\t| { type: \"turn_start\" }\n\t| {\n\t\t\ttype: \"turn_end\";\n\t\t\tmessage: ComposerMessage;\n\t\t\ttoolResults: ComposerMessage[];\n\t }\n\t| { type: \"message_start\"; message: ComposerMessage }\n\t| {\n\t\t\ttype: \"message_update\";\n\t\t\tmessage?: ComposerMessage;\n\t\t\tassistantMessageEvent: ComposerAssistantMessageEvent;\n\t }\n\t| { type: \"message_end\"; message: ComposerMessage }\n\t| {\n\t\t\ttype: \"tool_execution_start\";\n\t\t\ttoolCallId: string;\n\t\t\ttoolName: string;\n\t\t\tdisplayName?: string;\n\t\t\tsummaryLabel?: string;\n\t\t\targs: Record<string, unknown>;\n\t }\n\t| {\n\t\t\ttype: \"tool_execution_update\";\n\t\t\ttoolCallId: string;\n\t\t\ttoolName: string;\n\t\t\tdisplayName?: string;\n\t\t\tsummaryLabel?: string;\n\t\t\targs: Record<string, unknown>;\n\t\t\tpartialResult: unknown;\n\t }\n\t| {\n\t\t\ttype: \"tool_execution_end\";\n\t\t\ttoolCallId: string;\n\t\t\ttoolName: string;\n\t\t\tdisplayName?: string;\n\t\t\tsummaryLabel?: string;\n\t\t\tresult: unknown;\n\t\t\tisError: boolean;\n\t }\n\t| {\n\t\t\ttype: \"tool_batch_summary\";\n\t\t\tsummary: string;\n\t\t\tsummaryLabels: string[];\n\t\t\ttoolCallIds: string[];\n\t\t\ttoolNames: string[];\n\t\t\tcallsSucceeded: number;\n\t\t\tcallsFailed: number;\n\t }\n\t| { type: \"action_approval_required\"; request: ComposerActionApprovalRequest }\n\t| {\n\t\t\ttype: \"action_approval_resolved\";\n\t\t\trequest: ComposerActionApprovalRequest;\n\t\t\tdecision: ComposerActionApprovalDecision;\n\t }\n\t| {\n\t\t\ttype: \"client_tool_request\";\n\t\t\ttoolCallId: string;\n\t\t\ttoolName: string;\n\t\t\targs: unknown;\n\t }\n\t| { type: \"tool_retry_required\"; request: ComposerToolRetryRequest }\n\t| {\n\t\t\ttype: \"tool_retry_resolved\";\n\t\t\trequest: ComposerToolRetryRequest;\n\t\t\tdecision: ComposerToolRetryDecision;\n\t }\n\t| {\n\t\t\ttype: \"compaction\";\n\t\t\tsummary: string;\n\t\t\tfirstKeptEntryIndex: number;\n\t\t\ttokensBefore: number;\n\t\t\tauto?: boolean;\n\t\t\tcustomInstructions?: string;\n\t\t\ttimestamp: string;\n\t }\n\t| {\n\t\t\ttype: \"auto_retry_start\";\n\t\t\tattempt: number;\n\t\t\tmaxAttempts: number;\n\t\t\tdelayMs: number;\n\t\t\terrorMessage: string;\n\t }\n\t| {\n\t\t\ttype: \"auto_retry_end\";\n\t\t\tsuccess: boolean;\n\t\t\tattempt: number;\n\t\t\tfinalError?: string;\n\t }\n\t| { type: \"session_update\"; sessionId: string }\n\t| { type: \"heartbeat\" }\n\t| { type: \"aborted\" }\n\t| { type: \"done\" };\n\n/**\n * Error severity levels for API payloads.\n */\nexport type ComposerErrorSeverity = \"error\" | \"warning\" | \"info\";\n\n/**\n * Error categories for API payloads.\n */\nexport type ComposerErrorCategory =\n\t| \"validation\"\n\t| \"permission\"\n\t| \"network\"\n\t| \"timeout\"\n\t| \"filesystem\"\n\t| \"tool\"\n\t| \"session\"\n\t| \"config\"\n\t| \"api\"\n\t| \"internal\";\n\n/**\n * Structured error payload for API responses.\n */\nexport interface ComposerErrorPayload {\n\tcode: string;\n\tcategory: ComposerErrorCategory;\n\tseverity?: ComposerErrorSeverity;\n\tretriable?: boolean;\n\tcontext?: Record<string, unknown>;\n}\n\n/**\n * Standard API error response shape.\n */\nexport interface ComposerErrorResponse {\n\terror: string;\n\tcode?: string;\n\tdetails?: Record<string, unknown>[];\n\tcomposer?: ComposerErrorPayload;\n}\n\n/**\n * Response payload for session list endpoint.\n */\nexport interface ComposerSessionListResponse {\n\t/** Array of session summaries */\n\tsessions: ComposerSessionSummary[];\n}\n\n/**\n * SSE event sent when a session is created or updated.\n *\n * Allows clients to sync session state in real-time.\n */\nexport interface ComposerSessionUpdateEvent {\n\ttype: \"session_update\";\n\t/** ID of the created/updated session */\n\tsessionId: string;\n}\n\n/**\n * Background task resource limit breach metadata.\n */\nexport interface ComposerBackgroundTaskLimitBreach {\n\tkind: \"memory\" | \"cpu\";\n\tlimit: number;\n\tactual: number;\n}\n\n/**\n * Background task history record.\n */\nexport interface ComposerBackgroundTaskHistoryEntry {\n\tevent: \"started\" | \"restarted\" | \"exited\" | \"failed\" | \"stopped\";\n\ttaskId: string;\n\tstatus: string;\n\tcommand: string;\n\ttimestamp: string;\n\trestartAttempts: number;\n\tfailureReason?: string;\n\tlimitBreach?: ComposerBackgroundTaskLimitBreach;\n}\n\n/**\n * Background task health entry.\n */\nexport interface ComposerBackgroundTaskHealthEntry {\n\tid: string;\n\tstatus: string;\n\tsummary: string;\n\tcommand: string;\n\trestarts?: string;\n\tissues: string[];\n\tlastLogLine?: string;\n\tlogTruncated?: boolean;\n\tdurationSeconds: number;\n}\n\n/**\n * Background task health snapshot.\n */\nexport interface ComposerBackgroundTaskHealth {\n\ttotal: number;\n\trunning: number;\n\trestarting: number;\n\tfailed: number;\n\tentries: ComposerBackgroundTaskHealthEntry[];\n\ttruncated: boolean;\n\tnotificationsEnabled: boolean;\n\tdetailsRedacted: boolean;\n\thistory: ComposerBackgroundTaskHistoryEntry[];\n\thistoryTruncated: boolean;\n}\n\nexport type ComposerGuardianTarget = \"staged\" | \"all\";\n\nexport type ComposerGuardianStatus = \"passed\" | \"failed\" | \"skipped\" | \"error\";\n\nexport interface ComposerGuardianToolResult {\n\ttool: string;\n\texitCode: number;\n\tstdout: string;\n\tstderr: string;\n\tdurationMs: number;\n\tskipped?: boolean;\n\treason?: string;\n}\n\nexport interface ComposerGuardianRunResult {\n\tstatus: ComposerGuardianStatus;\n\texitCode: number;\n\tstartedAt: number;\n\tdurationMs: number;\n\ttarget: ComposerGuardianTarget;\n\ttrigger?: string;\n\tfilesScanned: number;\n\tfiles?: string[];\n\tsummary: string;\n\tskipReason?: string;\n\ttoolResults: ComposerGuardianToolResult[];\n}\n\nexport interface ComposerGuardianState {\n\tenabled: boolean;\n\tlastRun?: ComposerGuardianRunResult;\n}\n\nexport interface ComposerGuardianStatusResponse {\n\tenabled: boolean;\n\tstate: ComposerGuardianState;\n}\n\nexport type ComposerGuardianRunResponse = ComposerGuardianRunResult;\n\nexport interface ComposerGuardianConfigRequest {\n\tenabled: boolean;\n}\n\nexport interface ComposerGuardianConfigResponse {\n\tsuccess: boolean;\n\tenabled: boolean;\n}\n\nexport interface ComposerPlanModeState {\n\tactive: boolean;\n\tfilePath: string;\n\tsessionId?: string;\n\tgitBranch?: string;\n\tgitCommitSha?: string;\n\tcreatedAt: string;\n\tupdatedAt: string;\n\tname?: string;\n}\n\nexport interface ComposerPlanStatusResponse {\n\tstate: ComposerPlanModeState | null;\n\tcontent: string | null;\n}\n\nexport type ComposerPlanRequest =\n\t| { action: \"enter\"; name?: string; sessionId?: string }\n\t| { action: \"exit\" }\n\t| { action: \"update\"; content: string };\n\nexport type ComposerPlanActionResponse =\n\t| { success: boolean; state: ComposerPlanModeState }\n\t| { success: boolean };\n\nexport interface ComposerBackgroundSettings {\n\tnotificationsEnabled: boolean;\n\tstatusDetailsEnabled: boolean;\n}\n\nexport interface ComposerBackgroundStatusSnapshot {\n\trunning: number;\n\ttotal: number;\n\tfailed: number;\n\tdetailsRedacted: boolean;\n}\n\nexport interface ComposerBackgroundStatusResponse {\n\tsettings: ComposerBackgroundSettings;\n\tsnapshot: ComposerBackgroundStatusSnapshot | null;\n}\n\nexport interface ComposerBackgroundHistoryEntry {\n\ttimestamp: string;\n\tevent: \"started\" | \"restarted\" | \"exited\" | \"failed\" | \"stopped\";\n\ttaskId: string;\n\tcommand: string;\n\tfailureReason?: string;\n\tlimitBreach?: ComposerBackgroundTaskLimitBreach;\n}\n\nexport interface ComposerBackgroundHistoryResponse {\n\thistory: ComposerBackgroundHistoryEntry[];\n\ttruncated: boolean;\n}\n\nexport interface ComposerBackgroundPathResponse {\n\tpath: string;\n\texists: boolean;\n\toverridden: boolean;\n}\n\nexport interface ComposerBackgroundUpdateRequest {\n\tenabled: boolean;\n}\n\nexport interface ComposerBackgroundUpdateResponse {\n\tsuccess: boolean;\n\tmessage: string;\n}\n\nexport type ComposerApprovalMode = \"auto\" | \"prompt\" | \"fail\";\n\nexport interface ComposerApprovalsStatusResponse {\n\tmode: ComposerApprovalMode;\n\tavailableModes: ComposerApprovalMode[];\n}\n\nexport interface ComposerApprovalsUpdateRequest {\n\tmode: ComposerApprovalMode;\n\tsessionId?: string;\n}\n\nexport interface ComposerApprovalsUpdateResponse {\n\tsuccess: boolean;\n\tmode: ComposerApprovalMode;\n\tmessage: string;\n}\n\nexport type ComposerFrameworkScope = \"user\" | \"workspace\";\n\nexport interface ComposerFrameworkStatusResponse {\n\tframework: string;\n\tsource: string;\n\tlocked: boolean;\n\tscope: ComposerFrameworkScope;\n}\n\nexport interface ComposerFrameworkListEntry {\n\tid: string;\n\tsummary: string;\n}\n\nexport interface ComposerFrameworkListResponse {\n\tframeworks: ComposerFrameworkListEntry[];\n}\n\nexport interface ComposerFrameworkUpdateRequest {\n\tframework?: string | null;\n\tscope?: ComposerFrameworkScope;\n}\n\nexport interface ComposerFrameworkUpdateResponse {\n\tsuccess: boolean;\n\tmessage: string;\n\tframework: string | null;\n\tsummary?: string;\n\tscope?: ComposerFrameworkScope;\n}\n\nexport type ComposerChangeType = \"create\" | \"modify\" | \"delete\";\n\nexport interface ComposerFileChange {\n\tid: string;\n\ttype: ComposerChangeType;\n\tpath: string;\n\tbefore: string | null;\n\tafter: string | null;\n\ttoolName: string;\n\ttoolCallId: string;\n\ttimestamp: number;\n\tisGitTracked: boolean;\n\tmessageId?: string;\n}\n\nexport type ComposerUndoRestoreAction = \"restore\" | \"delete\" | \"recreate\";\n\nexport interface ComposerUndoPreview {\n\tchanges: ComposerFileChange[];\n\trestores: Array<{ path: string; action: ComposerUndoRestoreAction }>;\n\tconflicts: Array<{ path: string; reason: string }>;\n}\n\nexport interface ComposerUndoCheckpoint {\n\tname: string;\n\tdescription?: string;\n\tchangeCount: number;\n\ttimestamp: number;\n}\n\nexport interface ComposerUndoStatusResponse {\n\ttotalChanges: number;\n\tcanUndo: boolean;\n\tcheckpoints: ComposerUndoCheckpoint[];\n}\n\nexport interface ComposerUndoHistoryEntry {\n\tdescription: string;\n\tfileCount: number;\n\ttimestamp: number;\n}\n\nexport interface ComposerUndoHistoryResponse {\n\thistory: ComposerUndoHistoryEntry[];\n}\n\nexport interface ComposerUndoPreviewMessage {\n\tmessage: string;\n\tfileCount?: number;\n\tdescription?: string;\n}\n\nexport interface ComposerUndoRequest {\n\taction?: \"undo\" | \"checkpoint\" | \"restore\";\n\tcount?: number;\n\tpreview?: boolean;\n\tforce?: boolean;\n\tname?: string;\n\tdescription?: string;\n}\n\nexport type ComposerUndoOperationResponse =\n\t| { success: boolean; undone: number; errors: string[] }\n\t| { success: boolean; message: string; files?: string[] }\n\t| { message: string }\n\t| { preview: ComposerUndoPreview | ComposerUndoPreviewMessage }\n\t| {\n\t\t\tsuccess: boolean;\n\t\t\tcheckpoint: { name: string; changeCount: number; timestamp: number };\n\t }\n\t| { checkpoints: ComposerUndoCheckpoint[] };\n\nexport interface ComposerProjectOnboardingStep {\n\tkey: \"workspace\" | \"instructions\";\n\ttext: string;\n\tisComplete: boolean;\n\tisEnabled: boolean;\n}\n\nexport interface ComposerProjectOnboardingState {\n\tshouldShow: boolean;\n\tcompleted: boolean;\n\tseenCount: number;\n\tsteps: ComposerProjectOnboardingStep[];\n}\n\n/**\n * Workspace status response payload.\n */\nexport interface ComposerStatusResponse {\n\tcwd: string;\n\tgit: {\n\t\tbranch: string;\n\t\tstatus: {\n\t\t\tmodified: number;\n\t\t\tadded: number;\n\t\t\tdeleted: number;\n\t\t\tuntracked: number;\n\t\t\ttotal: number;\n\t\t};\n\t} | null;\n\tcontext: {\n\t\tagentMd: boolean;\n\t\tclaudeMd: boolean;\n\t};\n\tonboarding?: ComposerProjectOnboardingState;\n\tserver: {\n\t\tuptime: number;\n\t\tversion: string;\n\t\tstaticCacheMaxAgeSeconds?: number;\n\t};\n\tdatabase: {\n\t\tconfigured: boolean;\n\t\tconnected: boolean;\n\t};\n\tbackgroundTasks: ComposerBackgroundTaskHealth | null;\n\thooks: {\n\t\tasyncInFlight: number;\n\t\tconcurrency: {\n\t\t\tmax: number;\n\t\t\tactive: number;\n\t\t\tqueued: number;\n\t\t};\n\t};\n\tlastUpdated: number;\n\tlastLatencyMs: number;\n}\n\n/**\n * Token totals for usage summaries.\n */\nexport interface ComposerUsageTokenTotals {\n\tinput: number;\n\toutput: number;\n\tcacheRead: number;\n\tcacheWrite: number;\n\ttotal: number;\n}\n\n/**\n * Usage breakdown entry.\n */\nexport interface ComposerUsageBreakdown {\n\tcost: number;\n\trequests: number;\n\ttokens: number;\n\ttokensDetailed: ComposerUsageTokenTotals;\n\tcalls: number;\n\tcachedTokens: number;\n}\n\n/**\n * Usage summary response payload.\n */\nexport interface ComposerUsageSummary {\n\ttotalCost: number;\n\ttotalRequests: number;\n\ttotalTokens: number;\n\ttokensDetailed: ComposerUsageTokenTotals;\n\ttotalTokensDetailed: ComposerUsageTokenTotals;\n\ttotalTokensBreakdown: ComposerUsageTokenTotals;\n\ttotalCachedTokens: number;\n\tbyProvider: Record<string, ComposerUsageBreakdown>;\n\tbyModel: Record<string, ComposerUsageBreakdown>;\n}\n\n/**\n * Usage API response payload.\n */\nexport interface ComposerUsageResponse {\n\tsummary: ComposerUsageSummary;\n\thasData: boolean;\n}\n\n// Runtime schemas + validators\nexport * from \"./schemas.js\";\nexport * from \"./validators.js\";\n"]}
@@ -175,7 +175,7 @@ export declare const RuntimeAppServerServerNotificationSchema: import("@sinclair
175
175
  approvalRequestId: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
176
176
  }>>;
177
177
  }>;
178
- resolution: import("@sinclair/typebox").TUnsafe<"approved" | "denied" | "completed" | "failed" | "answered" | "retried" | "skipped" | "aborted" | "cancelled">;
178
+ resolution: import("@sinclair/typebox").TUnsafe<"completed" | "approved" | "denied" | "failed" | "answered" | "retried" | "skipped" | "aborted" | "cancelled">;
179
179
  reason: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
180
180
  resolvedBy: import("@sinclair/typebox").TUnsafe<"user" | "policy" | "client" | "runtime">;
181
181
  resolvedAtMs: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
@@ -6,7 +6,7 @@ export type RuntimeServerRequestResolution = (typeof runtimeServerRequestResolut
6
6
  export declare const runtimeServerRequestResolvedBy: readonly ["user", "policy", "client", "runtime"];
7
7
  export type RuntimeServerRequestResolvedBy = (typeof runtimeServerRequestResolvedBy)[number];
8
8
  export declare const RuntimeServerRequestKindSchema: import("@sinclair/typebox").TUnsafe<"approval" | "client_tool" | "mcp_elicitation" | "user_input" | "tool_retry">;
9
- export declare const RuntimeServerRequestResolutionSchema: import("@sinclair/typebox").TUnsafe<"approved" | "denied" | "completed" | "failed" | "answered" | "retried" | "skipped" | "aborted" | "cancelled">;
9
+ export declare const RuntimeServerRequestResolutionSchema: import("@sinclair/typebox").TUnsafe<"completed" | "approved" | "denied" | "failed" | "answered" | "retried" | "skipped" | "aborted" | "cancelled">;
10
10
  export declare const RuntimeServerRequestResolvedBySchema: import("@sinclair/typebox").TUnsafe<"user" | "policy" | "client" | "runtime">;
11
11
  export declare const RuntimeServerRequestPlatformRefSchema: import("@sinclair/typebox").TObject<{
12
12
  source: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"approvals_service">, import("@sinclair/typebox").TLiteral<"tool_execution">]>;
@@ -81,7 +81,7 @@ export declare const RuntimeServerRequestResolvedEventSchema: import("@sinclair/
81
81
  approvalRequestId: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
82
82
  }>>;
83
83
  }>;
84
- resolution: import("@sinclair/typebox").TUnsafe<"approved" | "denied" | "completed" | "failed" | "answered" | "retried" | "skipped" | "aborted" | "cancelled">;
84
+ resolution: import("@sinclair/typebox").TUnsafe<"completed" | "approved" | "denied" | "failed" | "answered" | "retried" | "skipped" | "aborted" | "cancelled">;
85
85
  reason: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
86
86
  resolvedBy: import("@sinclair/typebox").TUnsafe<"user" | "policy" | "client" | "runtime">;
87
87
  resolvedAtMs: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
@@ -131,7 +131,7 @@ export declare const RuntimeServerRequestLifecycleEventSchema: import("@sinclair
131
131
  approvalRequestId: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
132
132
  }>>;
133
133
  }>;
134
- resolution: import("@sinclair/typebox").TUnsafe<"approved" | "denied" | "completed" | "failed" | "answered" | "retried" | "skipped" | "aborted" | "cancelled">;
134
+ resolution: import("@sinclair/typebox").TUnsafe<"completed" | "approved" | "denied" | "failed" | "answered" | "retried" | "skipped" | "aborted" | "cancelled">;
135
135
  reason: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
136
136
  resolvedBy: import("@sinclair/typebox").TUnsafe<"user" | "policy" | "client" | "runtime">;
137
137
  resolvedAtMs: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evalops/contracts",
3
- "version": "0.10.22",
3
+ "version": "0.10.23",
4
4
  "description": "Shared Maestro contracts for frontend/backend integration",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evalops/tui",
3
- "version": "0.10.22",
3
+ "version": "0.10.23",
4
4
  "description": "Terminal UI library with differential rendering for Maestro",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1 +1 @@
1
- {"version":3,"file":"session-artifacts.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/session-artifacts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AA2UjE,wBAAsB,2BAA2B,CAChD,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,iBAiC5B;AAED,wBAAsB,2BAA2B,CAChD,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,iBAsF5B;AAED,wBAAsB,yBAAyB,CAC9C,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,EACxC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,iBAuE5B;AAED,wBAAsB,2BAA2B,CAChD,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,EACxC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,iBA4S5B;AAED,wBAAsB,4BAA4B,CACjD,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,iBAiF5B;AAED,wBAAsB,yBAAyB,CAC9C,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,iBA6C5B"}
1
+ {"version":3,"file":"session-artifacts.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/session-artifacts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAuQjE,wBAAsB,2BAA2B,CAChD,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,iBAiC5B;AAED,wBAAsB,2BAA2B,CAChD,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,iBAsF5B;AAED,wBAAsB,yBAAyB,CAC9C,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,EACxC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,iBAuE5B;AAED,wBAAsB,2BAA2B,CAChD,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,EACxC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,iBA4S5B;AAED,wBAAsB,4BAA4B,CACjD,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,iBAiF5B;AAED,wBAAsB,yBAAyB,CAC9C,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,iBA6C5B"}
@@ -1,3 +1,4 @@
1
+ import { artifactContentsByFilename, isValidArtifactFilename, reconstructArtifactsFromMessages as reconstructArtifactStateFromMessages, } from "@evalops/contracts";
1
2
  import { lookup as lookupMimeType } from "mime-types";
2
3
  import { createLogger } from "../../utils/logger.js";
3
4
  import { ARTIFACT_ACCESS_HEADER, getArtifactAccessGrantFromRequest, getArtifactAccessTokenFromRequest, issueArtifactAccessGrant, } from "../artifact-access.js";
@@ -126,82 +127,20 @@ function injectArtifactsSnapshotRuntime(htmlContent, artifacts) {
126
127
  }
127
128
  return `${html}\n${runtime}`;
128
129
  }
129
- function asString(value) {
130
- return typeof value === "string" ? value : undefined;
131
- }
132
- function hasControlCharacter(value) {
133
- for (let index = 0; index < value.length; index += 1) {
134
- const code = value.charCodeAt(index);
135
- if (code < 32 || code === 127)
136
- return true;
137
- }
138
- return false;
139
- }
140
- function isValidArtifactFilename(filename) {
141
- return (filename.length > 0 &&
142
- !filename.includes("..") &&
143
- !filename.includes("/") &&
144
- !filename.includes("\\") &&
145
- !hasControlCharacter(filename));
146
- }
147
130
  function reconstructArtifactsFromMessages(messages) {
148
- const byFilename = new Map();
149
- for (const msg of messages) {
150
- const tools = msg.tools ?? [];
151
- for (const tool of tools) {
152
- if (tool.name !== "artifacts")
153
- continue;
154
- if (tool.status !== "completed")
155
- continue;
156
- if (tool.result && typeof tool.result === "object") {
157
- const maybeErr = tool.result;
158
- if (maybeErr.isError)
159
- continue;
160
- }
161
- const args = (tool.args && typeof tool.args === "object"
162
- ? tool.args
163
- : {});
164
- const command = asString(args.command);
165
- const filename = asString(args.filename)?.trim();
166
- if (!command || !filename)
167
- continue;
168
- if (!isValidArtifactFilename(filename))
169
- continue;
170
- if (command === "get" || command === "logs")
171
- continue;
172
- if (command === "create") {
173
- if (byFilename.has(filename))
174
- continue;
175
- byFilename.set(filename, asString(args.content) ?? "");
176
- continue;
177
- }
178
- if (command === "rewrite") {
179
- if (!byFilename.has(filename))
180
- continue;
181
- byFilename.set(filename, asString(args.content) ?? "");
182
- continue;
183
- }
184
- if (command === "update") {
185
- const current = byFilename.get(filename);
186
- if (current === undefined)
187
- continue;
188
- const oldStr = asString(args.old_str);
189
- const newStr = asString(args.new_str);
190
- if (oldStr === undefined || newStr === undefined)
191
- continue;
192
- if (oldStr.length === 0)
193
- continue;
194
- if (!current.includes(oldStr))
195
- continue;
196
- byFilename.set(filename, current.replace(oldStr, newStr));
197
- continue;
198
- }
199
- if (command === "delete") {
200
- byFilename.delete(filename);
201
- }
202
- }
131
+ const diagnostics = [];
132
+ const state = reconstructArtifactStateFromMessages(messages, {
133
+ onDiagnostic: (diagnostic) => {
134
+ diagnostics.push(diagnostic.code);
135
+ },
136
+ });
137
+ if (diagnostics.length > 0) {
138
+ logger.warn("Skipped invalid persisted artifact commands", {
139
+ count: diagnostics.length,
140
+ codes: diagnostics,
141
+ });
203
142
  }
204
- return byFilename;
143
+ return artifactContentsByFilename(state);
205
144
  }
206
145
  async function loadComposerMessages(req, sessionId) {
207
146
  const sessionManager = createWebSessionManagerForRequest(req, true);
@@ -1 +1 @@
1
- {"version":3,"file":"session-artifacts.js","sourceRoot":"","sources":["../../../src/server/handlers/session-artifacts.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,IAAI,cAAc,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EACN,sBAAsB,EAEtB,iCAAiC,EACjC,iCAAiC,EACjC,wBAAwB,GACxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EACN,QAAQ,EACR,uBAAuB,EACvB,QAAQ,GACR,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACN,iCAAiC,EACjC,mBAAmB,GACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,4BAA4B,EAAE,MAAM,6BAA6B,CAAC;AAE3E,MAAM,MAAM,GAAG,YAAY,CAAC,mBAAmB,CAAC,CAAC;AACjD,MAAM,gBAAgB,GAAG,mBAAmB,CAAC;AAE7C,SAAS,mBAAmB,CAAC,IAAY;IACxC,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAY,EAAE,SAAiB;IACxD,OAAO,wBAAwB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,wBAAwB,CAChC,IAAY,EACZ,SAAiB,EACjB,WAA2B;IAE3B,MAAM,WAAW,GAAG,WAAW;QAC9B,CAAC,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,sBAAsB,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI;QACjF,CAAC,CAAC,WAAW,CAAC;IACf,MAAM,UAAU,GAAG;;;;uBAKhB,WAAW;QACV,CAAC,CAAC;sCAC+B,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;oBAC3C,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;OAyBxB;QACF,CAAC,CAAC;oCAC6B,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;;;;;;;;;OAU1D;;;;;;EAMD,CAAC,IAAI,EAAE,CAAC;IACT,MAAM,MAAM,GAAG,aAAa,mBAAmB,CAAC,UAAU,CAAC,aAAa,CAAC;IACzE,MAAM,QAAQ,GAAG,KAAK,MAAM,IAAI,CAAC;IACjC,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5B,OAAO,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,GAAG,QAAQ,SAAS,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,GAAG,IAAI,GAAG,QAAQ,EAAE,CAAC;AAC7B,CAAC;AAED,SAAS,gBAAgB,CAAC,WAAmB;IAC5C,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC;IACnC,MAAM,iBAAiB,GACtB,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAE5D,IAAI,iBAAiB;QAAE,OAAO,OAAO,CAAC;IAEtC,OAAO;;;;;;;EAON,OAAO;;QAED,CAAC;AACT,CAAC;AAED,SAAS,8BAA8B,CACtC,WAAmB,EACnB,SAA8B;IAE9B,MAAM,QAAQ,GAA2B,EAAE,CAAC;IAC5C,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,SAAS,EAAE,CAAC;QACzC,QAAQ,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC;IAC1B,CAAC;IAED,MAAM,OAAO,GAAG;;;;yBAIQ,mBAAmB,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;CAoBrE,CAAC,IAAI,EAAE,CAAC;IAER,MAAM,IAAI,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC;IAC3C,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5B,OAAO,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,OAAO,WAAW,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,GAAG,IAAI,KAAK,OAAO,EAAE,CAAC;AAC9B,CAAC;AAUD,SAAS,QAAQ,CAAC,KAAc;IAC/B,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACtD,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAa;IACzC,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QACrC,IAAI,IAAI,GAAG,EAAE,IAAI,IAAI,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;IAC5C,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED,SAAS,uBAAuB,CAAC,QAAgB;IAChD,OAAO,CACN,QAAQ,CAAC,MAAM,GAAG,CAAC;QACnB,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC;QACxB,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC;QACvB,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC;QACxB,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAC9B,CAAC;AACH,CAAC;AAED,SAAS,gCAAgC,CACxC,QAA2B;IAE3B,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkB,CAAC;IAE7C,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC5B,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;QAC9B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YAC1B,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW;gBAAE,SAAS;YACxC,IAAI,IAAI,CAAC,MAAM,KAAK,WAAW;gBAAE,SAAS;YAC1C,IAAI,IAAI,CAAC,MAAM,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;gBACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,MAA+B,CAAC;gBACtD,IAAI,QAAQ,CAAC,OAAO;oBAAE,SAAS;YAChC,CAAC;YAED,MAAM,IAAI,GAAG,CACZ,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ;gBACzC,CAAC,CAAE,IAAI,CAAC,IAAgC;gBACxC,CAAC,CAAC,EAAE,CACsB,CAAC;YAE7B,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAiC,CAAC;YACvE,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC;YAEjD,IAAI,CAAC,OAAO,IAAI,CAAC,QAAQ;gBAAE,SAAS;YACpC,IAAI,CAAC,uBAAuB,CAAC,QAAQ,CAAC;gBAAE,SAAS;YACjD,IAAI,OAAO,KAAK,KAAK,IAAI,OAAO,KAAK,MAAM;gBAAE,SAAS;YAEtD,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;gBAC1B,IAAI,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC;oBAAE,SAAS;gBACvC,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;gBACvD,SAAS;YACV,CAAC;YAED,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBAC3B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC;oBAAE,SAAS;gBACxC,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;gBACvD,SAAS;YACV,CAAC;YAED,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;gBAC1B,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBACzC,IAAI,OAAO,KAAK,SAAS;oBAAE,SAAS;gBACpC,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACtC,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACtC,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS;oBAAE,SAAS;gBAC3D,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;oBAAE,SAAS;gBAClC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;oBAAE,SAAS;gBACxC,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;gBAC1D,SAAS;YACV,CAAC;YAED,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;gBAC1B,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC7B,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO,UAAU,CAAC;AACnB,CAAC;AAED,KAAK,UAAU,oBAAoB,CAClC,GAAoB,EACpB,SAAiB;IAEjB,MAAM,cAAc,GAAG,iCAAiC,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACpE,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IAC5D,IAAI,CAAC,OAAO,EAAE,CAAC;QACd,MAAM,IAAI,QAAQ,CAAC,GAAG,EAAE,mBAAmB,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,4BAA4B,CAAC,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;AAC7D,CAAC;AAED,SAAS,gBAAgB,CAAC,QAAgB;IACzC,8DAA8D;IAC9D,IAAI,CAAC,uBAAuB,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,QAAQ,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC;IAC7C,CAAC;AACF,CAAC;AAED,SAAS,2BAA2B,CACnC,SAAiB,EACjB,QAAgB,EAChB,OAIC;IAED,MAAM,IAAI,GAAG,iBAAiB,kBAAkB,CAAC,SAAS,CAAC,cAAc,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC;IACxG,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;IAC9C,IAAI,OAAO,EAAE,QAAQ;QAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IAC7D,IAAI,OAAO,EAAE,GAAG;QAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACnD,IAAI,OAAO,EAAE,UAAU;QAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;IACjE,OAAO,GAAG,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC;AACvC,CAAC;AAED,SAAS,6BAA6B,CACrC,SAAiB,EACjB,QAAgB;IAEhB,OAAO,iBAAiB,kBAAkB,CAAC,SAAS,CAAC,cAAc,kBAAkB,CAAC,QAAQ,CAAC,OAAO,CAAC;AACxG,CAAC;AAED,SAAS,8BAA8B,CACtC,SAAiB,EACjB,QAAgB;IAEhB,MAAM,GAAG,GAAG,IAAI,GAAG,CAClB,iBAAiB,kBAAkB,CAAC,SAAS,CAAC,mBAAmB,EACjE,kBAAkB,CAClB,CAAC;IACF,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IAC3C,OAAO,GAAG,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC;AACvC,CAAC;AAED,SAAS,2BAA2B,CAAC,SAAiB;IACrD,OAAO,iBAAiB,kBAAkB,CAAC,SAAS,CAAC,gBAAgB,CAAC;AACvE,CAAC;AAED,SAAS,4BAA4B,CAAC,GAAoB;IAIzD,MAAM,KAAK,GAAG,iCAAiC,CAAC,GAAG,CAAC,CAAC;IACrD,OAAO;QACN,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC,iCAAiC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI;QAClE,KAAK;KACL,CAAC;AACH,CAAC;AAED,SAAS,oBAAoB,CAC5B,KAA2D,EAC3D,MAA4B;IAE5B,OAAO,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAChD,GAAoB,EACpB,GAAmB,EACnB,MAAsB,EACtB,IAA4B;IAE5B,MAAM,SAAS,GAAG,MAAM,CAAC,EAAE,CAAC;IAC5B,IAAI,CAAC;QACJ,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;YAC1B,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACzB,GAAG,CAAC,GAAG,EAAE,CAAC;YACV,OAAO;QACR,CAAC;QACD,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YACvC,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,oBAAoB,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;YAC/D,OAAO;QACR,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC5D,MAAM,SAAS,GAAG,gCAAgC,CAAC,QAAQ,CAAC,CAAC;QAC7D,QAAQ,CACP,GAAG,EACH,GAAG,EACH;YACC,SAAS;YACT,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACrD,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAClB;SACD,EACD,IAAI,EACJ,GAAG,CACH,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,MAAM,KAAK,GACV,GAAG,YAAY,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;QACrE,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;IACtE,CAAC;AACF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAChD,GAAoB,EACpB,GAAmB,EACnB,MAAsB,EACtB,IAA4B;IAE5B,MAAM,SAAS,GAAG,MAAM,CAAC,EAAE,CAAC;IAC5B,IAAI,CAAC;QACJ,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;YAC1B,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACzB,GAAG,CAAC,GAAG,EAAE,CAAC;YACV,OAAO;QACR,CAAC;QACD,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YACvC,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,oBAAoB,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;YAC/D,OAAO;QACR,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,EAAE,kBAAkB,CAAC,CAAC;QACvD,MAAM,QAAQ,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC;QACvE,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CACzB,IAAI,GAAG,CACN,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;aACrC,KAAK,CAAC,GAAG,CAAC;aACV,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;aAC9B,MAAM,CAAC,OAAO,CAAC,CACjB,CACD,CAAC,MAAM,CAAC,CAAC,MAAM,EAAkC,EAAE;YACnD,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;QAEH,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,QAAQ,CACP,GAAG,EACH,GAAG,EACH,EAAE,KAAK,EAAE,iDAAiD,EAAE,EAC5D,IAAI,EACJ,GAAG,CACH,CAAC;YACF,OAAO;QACR,CAAC;QAED,IAAI,QAAQ,EAAE,CAAC;YACd,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAC5B,CAAC;QAED,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,KAAK,KAAK,CAAC,EAAE,CAAC;YAC7D,QAAQ,CACP,GAAG,EACH,GAAG,EACH,EAAE,KAAK,EAAE,+CAA+C,EAAE,EAC1D,IAAI,EACJ,GAAG,CACH,CAAC;YACF,OAAO;QACR,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC5D,MAAM,SAAS,GAAG,gCAAgC,CAAC,QAAQ,CAAC,CAAC;QAE7D,IAAI,QAAQ,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1C,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,oBAAoB,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;YAC/D,OAAO;QACR,CAAC;QAED,MAAM,MAAM,GAAG,wBAAwB,CAAC;YACvC,SAAS;YACT,KAAK,EAAE,mBAAmB,CAAC,GAAG,CAAC;YAC/B,QAAQ;YACR,OAAO;SACP,CAAC,CAAC;QAEH,QAAQ,CACP,GAAG,EACH,GAAG,EACH;YACC,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,SAAS,EAAE,MAAM,CAAC,YAAY;YAC9B,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,SAAS;YACT,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACjC,EACD,IAAI,EACJ,GAAG,CACH,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,MAAM,KAAK,GACV,GAAG,YAAY,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;QACrE,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;IACtE,CAAC;AACF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC9C,GAAoB,EACpB,GAAmB,EACnB,MAAwC,EACxC,IAA4B;IAE5B,MAAM,SAAS,GAAG,MAAM,CAAC,EAAE,CAAC;IAC5B,MAAM,QAAQ,GAAG,kBAAkB,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;IAE3D,IAAI,CAAC;QACJ,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;YAC1B,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACzB,GAAG,CAAC,GAAG,EAAE,CAAC;YACV,OAAO;QACR,CAAC;QACD,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YACvC,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,oBAAoB,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;YAC/D,OAAO;QACR,CAAC;QACD,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAE3B,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC5D,MAAM,SAAS,GAAG,gCAAgC,CAAC,QAAQ,CAAC,CAAC;QAC7D,MAAM,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC3B,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,oBAAoB,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;YAC/D,OAAO;QACR,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,EAAE,kBAAkB,CAAC,CAAC;QACvD,MAAM,aAAa,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,GAAG,CAAC;QAC/D,MAAM,QAAQ,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC;QACrD,MAAM,eAAe,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,GAAG,CAAC;QAEnE,MAAM,IAAI,GAAG,cAAc,CAAC,QAAQ,CAAC,IAAI,2BAA2B,CAAC;QACrE,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;QACpD,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,4BAA4B,CAAC,GAAG,CAAC,CAAC;QAEjE,MAAM,SAAS,GAAG,oBAAoB,CAAC,KAAK,EAAE,QAAQ,CAAC;YACtD,CAAC,CAAC,8BAA8B,CAAC,SAAS,EAAE,QAAQ,CAAC;YACrD,CAAC,CAAC,WAAW;gBACZ,CAAC,CAAC,IAAI;gBACN,CAAC,CAAC,8BAA8B,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAExD,IAAI,IAAI,GACP,MAAM,IAAI,CAAC,QAAQ,IAAI,SAAS;YAC/B,CAAC,CAAC,wBAAwB,CAAC,OAAO,EAAE,SAAS,EAAE,WAAW,CAAC;YAC3D,CAAC,CAAC,OAAO,CAAC;QAEZ,gFAAgF;QAChF,IAAI,MAAM,IAAI,eAAe,EAAE,CAAC;YAC/B,IAAI,GAAG,8BAA8B,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QACxD,CAAC;QAED,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;YAClB,cAAc,EAAE,MAAM,CAAC,IAAI,CAAC;YAC5B,eAAe,EAAE,UAAU;YAC3B,GAAG,CAAC,aAAa,IAAI,eAAe;gBACnC,CAAC,CAAC;oBACA,qBAAqB,EAAE,uBAAuB,CAAC,QAAQ,CAAC;iBACxD;gBACF,CAAC,CAAC,EAAE,CAAC;YACN,GAAG,IAAI;SACP,CAAC,CAAC;QACH,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACf,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,MAAM,CAAC,IAAI,CAAC,0BAA0B,EAAE;YACvC,GAAG,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;YACrD,SAAS;YACT,QAAQ;SACR,CAAC,CAAC;QACH,MAAM,KAAK,GACV,GAAG,YAAY,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;QACrE,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;IACtE,CAAC;AACF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAChD,GAAoB,EACpB,GAAmB,EACnB,MAAwC,EACxC,IAA4B;IAE5B,MAAM,SAAS,GAAG,MAAM,CAAC,EAAE,CAAC;IAC5B,MAAM,QAAQ,GAAG,kBAAkB,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;IAE3D,IAAI,CAAC;QACJ,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;YAC1B,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACzB,GAAG,CAAC,GAAG,EAAE,CAAC;YACV,OAAO;QACR,CAAC;QACD,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YACvC,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,oBAAoB,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;YAC/D,OAAO;QACR,CAAC;QACD,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAE3B,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC5D,MAAM,SAAS,GAAG,gCAAgC,CAAC,QAAQ,CAAC,CAAC;QAC7D,MAAM,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC3B,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,oBAAoB,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;YAC/D,OAAO;QACR,CAAC;QAED,MAAM,IAAI,GAAG,cAAc,CAAC,QAAQ,CAAC,IAAI,2BAA2B,CAAC;QACrE,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;QACpD,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,4BAA4B,CAAC,GAAG,CAAC,CAAC;QAEjE,MAAM,KAAK,GAAG,sBAAsB,QAAQ,EAAE,CAAC;QAC/C,MAAM,SAAS,GAAG,6BAA6B,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAErE,MAAM,SAAS,GAAG,oBAAoB,CAAC,KAAK,EAAE,QAAQ,CAAC;YACtD,CAAC,CAAC,8BAA8B,CAAC,SAAS,EAAE,QAAQ,CAAC;YACrD,CAAC,CAAC,WAAW;gBACZ,CAAC,CAAC,IAAI;gBACN,CAAC,CAAC,8BAA8B,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QACxD,MAAM,MAAM,GAAG,oBAAoB,CAAC,KAAK,EAAE,KAAK,CAAC;YAChD,CAAC,CAAC,2BAA2B,CAAC,SAAS,CAAC;YACxC,CAAC,CAAC,WAAW;gBACZ,CAAC,CAAC,IAAI;gBACN,CAAC,CAAC,2BAA2B,CAAC,SAAS,CAAC,CAAC;QAC3C,MAAM,cAAc,GAAG,oBAAoB,CAAC,KAAK,EAAE,MAAM,CAAC;YACzD,CAAC,CAAC,2BAA2B,CAAC,SAAS,EAAE,QAAQ,EAAE;gBACjD,QAAQ,EAAE,IAAI;gBACd,GAAG,EAAE,IAAI;aACT,CAAC;YACH,CAAC,CAAC,WAAW;gBACZ,CAAC,CAAC,IAAI;gBACN,CAAC,CAAC,2BAA2B,CAAC,SAAS,EAAE,QAAQ,EAAE;oBACjD,QAAQ,EAAE,IAAI;oBACd,GAAG,EAAE,IAAI;iBACT,CAAC,CAAC;QACN,MAAM,qBAAqB,GAAG,MAAM;YACnC,CAAC,CAAC,oBAAoB,CAAC,KAAK,EAAE,MAAM,CAAC;gBACpC,CAAC,CAAC,2BAA2B,CAAC,SAAS,EAAE,QAAQ,EAAE;oBACjD,QAAQ,EAAE,IAAI;oBACd,UAAU,EAAE,IAAI;iBAChB,CAAC;gBACH,CAAC,CAAC,WAAW;oBACZ,CAAC,CAAC,IAAI;oBACN,CAAC,CAAC,2BAA2B,CAAC,SAAS,EAAE,QAAQ,EAAE;wBACjD,QAAQ,EAAE,IAAI;wBACd,UAAU,EAAE,IAAI;qBAChB,CAAC;YACL,CAAC,CAAC,IAAI,CAAC;QAER,MAAM,SAAS,GAAG,MAAM;YACvB,CAAC,CAAC,WAAW;gBACZ,CAAC,CAAC,mFAAmF;gBACrF,CAAC,CAAC,yBAAyB,MAAM,mDAAmD;YACrF,CAAC,CAAC,EAAE,CAAC;QACN,MAAM,iBAAiB,GAAG,cAAc;YACvC,CAAC,CAAC,WAAW;gBACZ,CAAC,CAAC,mFAAmF;gBACrF,CAAC,CAAC,yBAAyB,cAAc,mDAAmD;YAC7F,CAAC,CAAC,EAAE,CAAC;QACN,MAAM,wBAAwB,GAAG,qBAAqB;YACrD,CAAC,CAAC,WAAW;gBACZ,CAAC,CAAC,iGAAiG;gBACnG,CAAC,CAAC,yBAAyB,qBAAqB,0DAA0D;YAC3G,CAAC,CAAC,EAAE,CAAC;QACN,MAAM,eAAe,GAAG,GAAG,SAAS,gBAAgB,CAAC;QAErD,MAAM,MAAM,GAAG,MAAM;YACpB,CAAC,CAAC,8BAA8B,CAAC,OAAO,EAAE,SAAS,CAAC;YACpD,CAAC,CAAC,gBAAgB,CAChB,kLAAkL,OAAO;iBACvL,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;iBACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;iBACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAC/B,CAAC;QAEJ,MAAM,mBAAmB,GAAG;;;;;;;;;;;;;CAa7B,CAAC,IAAI,EAAE,CAAC;QAEP,MAAM,UAAU,GAAG;;;;;aAKR,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;;;;;;;;;;;;;;;;2BAgBnC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;;QAEpE,SAAS;QACT,iBAAiB;QACjB,wBAAwB;;;MAG1B,mBAAmB;;;;;0BAKC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;0BACzB,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;uBAC5B,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;+BACd,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC;sCACvB,IAAI,CAAC,SAAS,CAAC,qBAAqB,CAAC;oCACvC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC;;cAEjD,IAAI,CAAC,SAAS,CAAC,sBAAsB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAsF7B,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;;;iDAGI,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC;2DACrB,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;yEACV,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;;;;QAK7F,SAAS;YACR,CAAC,CAAC;;0BAGF,WAAW;gBACV,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;UAwBE;gBACJ,CAAC,CAAC;uCAC+B,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;;UAG5D;;;;6FAIyF;YACxF,CAAC,CAAC,EACJ;;;QAGK,CAAC;QAEP,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;YAClB,cAAc,EAAE,0BAA0B;YAC1C,eAAe,EAAE,UAAU;YAC3B,GAAG,IAAI;SACP,CAAC,CAAC;QACH,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACrB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,MAAM,KAAK,GACV,GAAG,YAAY,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;QACrE,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;IACtE,CAAC;AACF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,4BAA4B,CACjD,GAAoB,EACpB,GAAmB,EACnB,MAAsB,EACtB,IAA4B;IAE5B,MAAM,SAAS,GAAG,MAAM,CAAC,EAAE,CAAC;IAC5B,IAAI,CAAC;QACJ,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;YAC1B,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACzB,GAAG,CAAC,GAAG,EAAE,CAAC;YACV,OAAO;QACR,CAAC;QACD,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YACvC,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,oBAAoB,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;YAC/D,OAAO;QACR,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,EAAE,kBAAkB,CAAC,CAAC;QACvD,MAAM,cAAc,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAExD,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;YAClB,cAAc,EAAE,mBAAmB;YACnC,eAAe,EAAE,UAAU;YAC3B,UAAU,EAAE,YAAY;YACxB,GAAG,IAAI;SACP,CAAC,CAAC;QAEH,IAAI,MAAM,GAAG,KAAK,CAAC;QACnB,MAAM,QAAQ,GAAG,GAAG,EAAE,CACrB,GAAG,CAAC,QAAQ,KAAK,KAAK,IAAI,CAAC,GAAG,CAAC,aAAa,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC;QAChE,MAAM,SAAS,GAAG,CAAC,OAAe,EAAE,EAAE;YACrC,IAAI,CAAC,QAAQ,EAAE;gBAAE,OAAO,KAAK,CAAC;YAC9B,IAAI,CAAC;gBACJ,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBACnB,OAAO,IAAI,CAAC;YACb,CAAC;YAAC,MAAM,CAAC;gBACR,OAAO,KAAK,CAAC;YACd,CAAC;QACF,CAAC,CAAC;QAEF,IAAI,SAAS,GAA0C,IAAI,CAAC;QAC5D,IAAI,WAAW,GAAe,GAAG,EAAE,GAAE,CAAC,CAAC;QAEvC,MAAM,OAAO,GAAG,GAAG,EAAE;YACpB,IAAI,MAAM;gBAAE,OAAO;YACnB,MAAM,GAAG,IAAI,CAAC;YACd,IAAI,SAAS,EAAE,CAAC;gBACf,aAAa,CAAC,SAAS,CAAC,CAAC;gBACzB,SAAS,GAAG,IAAI,CAAC;YAClB,CAAC;YACD,WAAW,EAAE,CAAC;YACd,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC1B,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC3B,CAAC,CAAC;QAEF,WAAW,GAAG,wBAAwB,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE;YAC3D,IAAI,cAAc,IAAI,KAAK,CAAC,QAAQ,KAAK,cAAc;gBAAE,OAAO;YAChE,IAAI,CAAC,SAAS,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;gBACtD,OAAO,EAAE,CAAC;YACX,CAAC;QACF,CAAC,CAAC,CAAC;QAEH,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE;YAC5B,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,CAAC;gBAC9B,OAAO,EAAE,CAAC;YACX,CAAC;QACF,CAAC,EAAE,MAAM,CAAC,CAAC;QAEX,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC;YACrB,SAAS,CAAC,KAAK,EAAE,CAAC;QACnB,CAAC;QAED,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,CAAC;YAC5B,OAAO,EAAE,CAAC;YACV,OAAO;QACR,CAAC;QAED,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACzB,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC1B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,MAAM,KAAK,GACV,GAAG,YAAY,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;QACrE,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;IACtE,CAAC;AACF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC9C,GAAoB,EACpB,GAAmB,EACnB,MAAsB,EACtB,IAA4B;IAE5B,MAAM,SAAS,GAAG,MAAM,CAAC,EAAE,CAAC;IAC5B,IAAI,CAAC;QACJ,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;YAC1B,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACzB,GAAG,CAAC,GAAG,EAAE,CAAC;YACV,OAAO;QACR,CAAC;QACD,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YACvC,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,oBAAoB,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;YAC/D,OAAO;QACR,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC5D,MAAM,SAAS,GAAG,gCAAgC,CAAC,QAAQ,CAAC,CAAC;QAE7D,wCAAwC;QACxC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;QAEpD,MAAM,OAAO,GAA+B,EAAE,CAAC;QAC/C,KAAK,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,SAAS,EAAE,CAAC;YAC7C,OAAO,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QACtC,CAAC;QAED,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QAEhD,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;YAClB,cAAc,EAAE,iBAAiB;YACjC,qBAAqB,EAAE,uBAAuB,CAC7C,aAAa,SAAS,MAAM,CAC5B;YACD,eAAe,EAAE,UAAU;YAC3B,GAAG,IAAI;SACP,CAAC,CAAC;QACH,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;IAChC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,MAAM,CAAC,IAAI,CAAC,gCAAgC,EAAE;YAC7C,GAAG,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;YACrD,SAAS;SACT,CAAC,CAAC;QACH,MAAM,KAAK,GACV,GAAG,YAAY,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;QACrE,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;IACtE,CAAC;AACF,CAAC","sourcesContent":["import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport type { ComposerMessage } from \"@evalops/contracts\";\nimport { lookup as lookupMimeType } from \"mime-types\";\nimport { createLogger } from \"../../utils/logger.js\";\nimport {\n\tARTIFACT_ACCESS_HEADER,\n\ttype ArtifactAccessAction,\n\tgetArtifactAccessGrantFromRequest,\n\tgetArtifactAccessTokenFromRequest,\n\tissueArtifactAccessGrant,\n} from \"../artifact-access.js\";\nimport { subscribeArtifactUpdates } from \"../artifacts-live-reload.js\";\nimport {\n\tApiError,\n\tbuildContentDisposition,\n\tsendJson,\n} from \"../server-utils.js\";\nimport {\n\tcreateWebSessionManagerForRequest,\n\tresolveSessionScope,\n} from \"../session-scope.js\";\nimport { convertAppMessagesToComposer } from \"../session-serialization.js\";\n\nconst logger = createLogger(\"session-artifacts\");\nconst sessionIdPattern = /^[a-zA-Z0-9._-]+$/;\n\nfunction escapeScriptContent(code: string): string {\n\treturn code.replace(/<\\/script/gi, \"<\\\\/script\");\n}\n\nfunction injectLiveReload(html: string, eventsUrl: string): string {\n\treturn injectLiveReloadWithAuth(html, eventsUrl);\n}\n\nfunction injectLiveReloadWithAuth(\n\thtml: string,\n\teventsUrl: string,\n\taccessToken?: string | null,\n): string {\n\tconst authHeaders = accessToken\n\t\t? `{ ${JSON.stringify(ARTIFACT_ACCESS_HEADER)}: ${JSON.stringify(accessToken)} }`\n\t\t: \"undefined\";\n\tconst scriptBody = `\n\t(function() {\n\t try {\n\t const reload = () => location.reload();\n\t const connect = ${\n\t\t\t\taccessToken\n\t\t\t\t\t? `async () => {\n\t const response = await fetch(${JSON.stringify(eventsUrl)}, {\n\t headers: ${authHeaders},\n\t cache: \"no-store\",\n\t });\n\t if (!response.body) throw new Error(\"Missing response body\");\n\t const reader = response.body.getReader();\n\t const decoder = new TextDecoder();\n\t let buffer = \"\";\n\t while (true) {\n\t const { done, value } = await reader.read();\n\t if (done) break;\n\t buffer += decoder.decode(value, { stream: true });\n\t let boundary = buffer.indexOf(\"\\\\n\\\\n\");\n\t while (boundary !== -1) {\n\t const chunk = buffer.slice(0, boundary);\n\t buffer = buffer.slice(boundary + 2);\n\t const dataLine = chunk\n\t .split(\"\\\\n\")\n\t .find((line) => line.startsWith(\"data:\"));\n\t if (dataLine) {\n\t reload();\n\t return;\n\t }\n\t boundary = buffer.indexOf(\"\\\\n\\\\n\");\n\t }\n\t }\n\t }`\n\t\t\t\t\t: `() => {\n\t const es = new EventSource(${JSON.stringify(eventsUrl)});\n\t es.onmessage = (e) => {\n\t try {\n\t const data = JSON.parse(e.data);\n\t if (data && data.type === \"artifact_updated\") {\n\t reload();\n\t }\n\t } catch (err) { console.error(\"[Maestro] Failed to parse live reload event:\", err); }\n\t };\n\t }`\n\t\t\t};\n\t Promise.resolve(connect()).catch((err) => {\n\t console.error(\"[Maestro] Failed to setup live reload transport:\", err);\n\t });\n\t } catch (err) { console.error(\"[Maestro] Failed to setup live reload EventSource:\", err); }\n\t})();\n\t`.trim();\n\tconst script = `<script>\\n${escapeScriptContent(scriptBody)}\\n</script>`;\n\tconst injected = `\\n${script}\\n`;\n\tif (/<\\/body>/i.test(html)) {\n\t\treturn html.replace(/<\\/body>/i, `${injected}</body>`);\n\t}\n\treturn `${html}${injected}`;\n}\n\nfunction wrapHtmlDocument(htmlContent: string): string {\n\tconst trimmed = htmlContent.trim();\n\tconst looksLikeDocument =\n\t\t/^<!doctype/i.test(trimmed) || /<html[\\s>]/i.test(trimmed);\n\n\tif (looksLikeDocument) return trimmed;\n\n\treturn `<!doctype html>\n<html>\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n </head>\n <body>\n${trimmed}\n </body>\n</html>`;\n}\n\nfunction injectArtifactsSnapshotRuntime(\n\thtmlContent: string,\n\tartifacts: Map<string, string>,\n): string {\n\tconst snapshot: Record<string, string> = {};\n\tfor (const [name, content] of artifacts) {\n\t\tsnapshot[name] = content;\n\t}\n\n\tconst runtime = `\n<script>\n(function() {\n try {\n window.artifacts = ${escapeScriptContent(JSON.stringify(snapshot))};\n } catch (err) {\n console.error(\"[Maestro] Failed to initialize artifacts snapshot:\", err);\n window.artifacts = {};\n }\n\n const isJson = (f) => (f || \"\").toLowerCase().endsWith(\".json\");\n\n window.listArtifacts = async () => Object.keys(window.artifacts || {});\n\n window.getArtifact = async (filename) => {\n const content = (window.artifacts || {})[filename];\n if (typeof content !== \"string\") throw new Error(\"Artifact not found: \" + filename);\n if (isJson(filename)) {\n try { return JSON.parse(content); } catch (e) { throw new Error(\"Failed to parse JSON: \" + e); }\n }\n return content;\n };\n})();\n</script>\n`.trim();\n\n\tconst html = wrapHtmlDocument(htmlContent);\n\tif (/<\\/body>/i.test(html)) {\n\t\treturn html.replace(/<\\/body>/i, `\\n${runtime}\\n</body>`);\n\t}\n\treturn `${html}\\n${runtime}`;\n}\n\ntype ArtifactsCommand =\n\t| \"create\"\n\t| \"update\"\n\t| \"rewrite\"\n\t| \"get\"\n\t| \"delete\"\n\t| \"logs\";\n\nfunction asString(value: unknown): string | undefined {\n\treturn typeof value === \"string\" ? value : undefined;\n}\n\nfunction hasControlCharacter(value: string): boolean {\n\tfor (let index = 0; index < value.length; index += 1) {\n\t\tconst code = value.charCodeAt(index);\n\t\tif (code < 32 || code === 127) return true;\n\t}\n\treturn false;\n}\n\nfunction isValidArtifactFilename(filename: string): boolean {\n\treturn (\n\t\tfilename.length > 0 &&\n\t\t!filename.includes(\"..\") &&\n\t\t!filename.includes(\"/\") &&\n\t\t!filename.includes(\"\\\\\") &&\n\t\t!hasControlCharacter(filename)\n\t);\n}\n\nfunction reconstructArtifactsFromMessages(\n\tmessages: ComposerMessage[],\n): Map<string, string> {\n\tconst byFilename = new Map<string, string>();\n\n\tfor (const msg of messages) {\n\t\tconst tools = msg.tools ?? [];\n\t\tfor (const tool of tools) {\n\t\t\tif (tool.name !== \"artifacts\") continue;\n\t\t\tif (tool.status !== \"completed\") continue;\n\t\t\tif (tool.result && typeof tool.result === \"object\") {\n\t\t\t\tconst maybeErr = tool.result as { isError?: boolean };\n\t\t\t\tif (maybeErr.isError) continue;\n\t\t\t}\n\n\t\t\tconst args = (\n\t\t\t\ttool.args && typeof tool.args === \"object\"\n\t\t\t\t\t? (tool.args as Record<string, unknown>)\n\t\t\t\t\t: {}\n\t\t\t) as Record<string, unknown>;\n\n\t\t\tconst command = asString(args.command) as ArtifactsCommand | undefined;\n\t\t\tconst filename = asString(args.filename)?.trim();\n\n\t\t\tif (!command || !filename) continue;\n\t\t\tif (!isValidArtifactFilename(filename)) continue;\n\t\t\tif (command === \"get\" || command === \"logs\") continue;\n\n\t\t\tif (command === \"create\") {\n\t\t\t\tif (byFilename.has(filename)) continue;\n\t\t\t\tbyFilename.set(filename, asString(args.content) ?? \"\");\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (command === \"rewrite\") {\n\t\t\t\tif (!byFilename.has(filename)) continue;\n\t\t\t\tbyFilename.set(filename, asString(args.content) ?? \"\");\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (command === \"update\") {\n\t\t\t\tconst current = byFilename.get(filename);\n\t\t\t\tif (current === undefined) continue;\n\t\t\t\tconst oldStr = asString(args.old_str);\n\t\t\t\tconst newStr = asString(args.new_str);\n\t\t\t\tif (oldStr === undefined || newStr === undefined) continue;\n\t\t\t\tif (oldStr.length === 0) continue;\n\t\t\t\tif (!current.includes(oldStr)) continue;\n\t\t\t\tbyFilename.set(filename, current.replace(oldStr, newStr));\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (command === \"delete\") {\n\t\t\t\tbyFilename.delete(filename);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn byFilename;\n}\n\nasync function loadComposerMessages(\n\treq: IncomingMessage,\n\tsessionId: string,\n): Promise<ComposerMessage[]> {\n\tconst sessionManager = createWebSessionManagerForRequest(req, true);\n\tconst session = await sessionManager.loadSession(sessionId);\n\tif (!session) {\n\t\tthrow new ApiError(404, \"Session not found\");\n\t}\n\treturn convertAppMessagesToComposer(session.messages || []);\n}\n\nfunction validateFilename(filename: string): void {\n\t// Keep this strict: no path traversal, no folder hierarchies.\n\tif (!isValidArtifactFilename(filename.trim())) {\n\t\tthrow new ApiError(400, \"Invalid filename\");\n\t}\n}\n\nfunction buildSessionArtifactFileUrl(\n\tsessionId: string,\n\tfilename: string,\n\toptions?: {\n\t\tdownload?: boolean;\n\t\traw?: boolean;\n\t\tstandalone?: boolean;\n\t},\n): string {\n\tconst path = `/api/sessions/${encodeURIComponent(sessionId)}/artifacts/${encodeURIComponent(filename)}`;\n\tconst url = new URL(path, \"http://localhost\");\n\tif (options?.download) url.searchParams.set(\"download\", \"1\");\n\tif (options?.raw) url.searchParams.set(\"raw\", \"1\");\n\tif (options?.standalone) url.searchParams.set(\"standalone\", \"1\");\n\treturn `${url.pathname}${url.search}`;\n}\n\nfunction buildSessionArtifactViewerUrl(\n\tsessionId: string,\n\tfilename: string,\n): string {\n\treturn `/api/sessions/${encodeURIComponent(sessionId)}/artifacts/${encodeURIComponent(filename)}/view`;\n}\n\nfunction buildSessionArtifactsEventsUrl(\n\tsessionId: string,\n\tfilename: string,\n): string {\n\tconst url = new URL(\n\t\t`/api/sessions/${encodeURIComponent(sessionId)}/artifacts/events`,\n\t\t\"http://localhost\",\n\t);\n\turl.searchParams.set(\"filename\", filename);\n\treturn `${url.pathname}${url.search}`;\n}\n\nfunction buildSessionArtifactsZipUrl(sessionId: string): string {\n\treturn `/api/sessions/${encodeURIComponent(sessionId)}/artifacts.zip`;\n}\n\nfunction resolveArtifactAccessContext(req: IncomingMessage): {\n\taccessToken: string | null;\n\tgrant: ReturnType<typeof getArtifactAccessGrantFromRequest>;\n} {\n\tconst grant = getArtifactAccessGrantFromRequest(req);\n\treturn {\n\t\taccessToken: grant ? getArtifactAccessTokenFromRequest(req) : null,\n\t\tgrant,\n\t};\n}\n\nfunction canUseArtifactAccess(\n\tgrant: ReturnType<typeof getArtifactAccessGrantFromRequest>,\n\taction: ArtifactAccessAction,\n): boolean {\n\treturn Boolean(grant?.actions.includes(action));\n}\n\nexport async function handleSessionArtifactsIndex(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tparams: { id: string },\n\tcors: Record<string, string>,\n) {\n\tconst sessionId = params.id;\n\ttry {\n\t\tif (req.method !== \"GET\") {\n\t\t\tres.writeHead(405, cors);\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\t\tif (!sessionIdPattern.test(sessionId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid session id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst messages = await loadComposerMessages(req, sessionId);\n\t\tconst artifacts = reconstructArtifactsFromMessages(messages);\n\t\tsendJson(\n\t\t\tres,\n\t\t\t200,\n\t\t\t{\n\t\t\t\tsessionId,\n\t\t\t\tfilenames: Array.from(artifacts.keys()).sort((a, b) =>\n\t\t\t\t\ta.localeCompare(b),\n\t\t\t\t),\n\t\t\t},\n\t\t\tcors,\n\t\t\treq,\n\t\t);\n\t} catch (err) {\n\t\tconst error =\n\t\t\terr instanceof ApiError ? err : new ApiError(500, \"Internal error\");\n\t\tsendJson(res, error.statusCode, { error: error.message }, cors, req);\n\t}\n}\n\nexport async function handleSessionArtifactAccess(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tparams: { id: string },\n\tcors: Record<string, string>,\n) {\n\tconst sessionId = params.id;\n\ttry {\n\t\tif (req.method !== \"GET\") {\n\t\t\tres.writeHead(405, cors);\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\t\tif (!sessionIdPattern.test(sessionId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid session id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst url = new URL(req.url || \"\", \"http://localhost\");\n\t\tconst filename = url.searchParams.get(\"filename\")?.trim() || undefined;\n\t\tconst actions = Array.from(\n\t\t\tnew Set(\n\t\t\t\t(url.searchParams.get(\"actions\") || \"\")\n\t\t\t\t\t.split(\",\")\n\t\t\t\t\t.map((action) => action.trim())\n\t\t\t\t\t.filter(Boolean),\n\t\t\t),\n\t\t).filter((action): action is ArtifactAccessAction => {\n\t\t\treturn [\"view\", \"file\", \"events\", \"zip\"].includes(action);\n\t\t});\n\n\t\tif (actions.length === 0) {\n\t\t\tsendJson(\n\t\t\t\tres,\n\t\t\t\t400,\n\t\t\t\t{ error: \"At least one artifact access action is required\" },\n\t\t\t\tcors,\n\t\t\t\treq,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tif (filename) {\n\t\t\tvalidateFilename(filename);\n\t\t}\n\n\t\tif (!filename && actions.some((action) => action !== \"zip\")) {\n\t\t\tsendJson(\n\t\t\t\tres,\n\t\t\t\t400,\n\t\t\t\t{ error: \"filename is required for artifact file access\" },\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 messages = await loadComposerMessages(req, sessionId);\n\t\tconst artifacts = reconstructArtifactsFromMessages(messages);\n\n\t\tif (filename && !artifacts.has(filename)) {\n\t\t\tsendJson(res, 404, { error: \"Artifact not found\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst access = issueArtifactAccessGrant({\n\t\t\tsessionId,\n\t\t\tscope: resolveSessionScope(req),\n\t\t\tfilename,\n\t\t\tactions,\n\t\t});\n\n\t\tsendJson(\n\t\t\tres,\n\t\t\t200,\n\t\t\t{\n\t\t\t\ttoken: access.token,\n\t\t\t\texpiresAt: access.expiresAtIso,\n\t\t\t\tactions: access.actions,\n\t\t\t\tsessionId,\n\t\t\t\t...(filename ? { filename } : {}),\n\t\t\t},\n\t\t\tcors,\n\t\t\treq,\n\t\t);\n\t} catch (err) {\n\t\tconst error =\n\t\t\terr instanceof ApiError ? err : new ApiError(500, \"Internal error\");\n\t\tsendJson(res, error.statusCode, { error: error.message }, cors, req);\n\t}\n}\n\nexport async function handleSessionArtifactFile(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tparams: { id: string; filename: string },\n\tcors: Record<string, string>,\n) {\n\tconst sessionId = params.id;\n\tconst filename = decodeURIComponent(params.filename || \"\");\n\n\ttry {\n\t\tif (req.method !== \"GET\") {\n\t\t\tres.writeHead(405, cors);\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\t\tif (!sessionIdPattern.test(sessionId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid session id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\t\tvalidateFilename(filename);\n\n\t\tconst messages = await loadComposerMessages(req, sessionId);\n\t\tconst artifacts = reconstructArtifactsFromMessages(messages);\n\t\tconst content = artifacts.get(filename);\n\t\tif (content === undefined) {\n\t\t\tsendJson(res, 404, { error: \"Artifact not found\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst url = new URL(req.url || \"\", \"http://localhost\");\n\t\tconst wantsDownload = url.searchParams.get(\"download\") === \"1\";\n\t\tconst wantsRaw = url.searchParams.get(\"raw\") === \"1\";\n\t\tconst wantsStandalone = url.searchParams.get(\"standalone\") === \"1\";\n\n\t\tconst mime = lookupMimeType(filename) || \"text/plain; charset=utf-8\";\n\t\tconst isHtml = String(mime).startsWith(\"text/html\");\n\t\tconst { accessToken, grant } = resolveArtifactAccessContext(req);\n\n\t\tconst eventsUrl = canUseArtifactAccess(grant, \"events\")\n\t\t\t? buildSessionArtifactsEventsUrl(sessionId, filename)\n\t\t\t: accessToken\n\t\t\t\t? null\n\t\t\t\t: buildSessionArtifactsEventsUrl(sessionId, filename);\n\n\t\tlet body =\n\t\t\tisHtml && !wantsRaw && eventsUrl\n\t\t\t\t? injectLiveReloadWithAuth(content, eventsUrl, accessToken)\n\t\t\t\t: content;\n\n\t\t// Standalone download: force attachment and embed artifacts snapshot + helpers.\n\t\tif (isHtml && wantsStandalone) {\n\t\t\tbody = injectArtifactsSnapshotRuntime(body, artifacts);\n\t\t}\n\n\t\tres.writeHead(200, {\n\t\t\t\"Content-Type\": String(mime),\n\t\t\t\"Cache-Control\": \"no-store\",\n\t\t\t...(wantsDownload || wantsStandalone\n\t\t\t\t? {\n\t\t\t\t\t\t\"Content-Disposition\": buildContentDisposition(filename),\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t\t...cors,\n\t\t});\n\t\tres.end(body);\n\t} catch (err) {\n\t\tlogger.warn(\"Failed to serve artifact\", {\n\t\t\terr: err instanceof Error ? err.message : String(err),\n\t\t\tsessionId,\n\t\t\tfilename,\n\t\t});\n\t\tconst error =\n\t\t\terr instanceof ApiError ? err : new ApiError(500, \"Internal error\");\n\t\tsendJson(res, error.statusCode, { error: error.message }, cors, req);\n\t}\n}\n\nexport async function handleSessionArtifactViewer(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tparams: { id: string; filename: string },\n\tcors: Record<string, string>,\n) {\n\tconst sessionId = params.id;\n\tconst filename = decodeURIComponent(params.filename || \"\");\n\n\ttry {\n\t\tif (req.method !== \"GET\") {\n\t\t\tres.writeHead(405, cors);\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\t\tif (!sessionIdPattern.test(sessionId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid session id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\t\tvalidateFilename(filename);\n\n\t\tconst messages = await loadComposerMessages(req, sessionId);\n\t\tconst artifacts = reconstructArtifactsFromMessages(messages);\n\t\tconst content = artifacts.get(filename);\n\t\tif (content === undefined) {\n\t\t\tsendJson(res, 404, { error: \"Artifact not found\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst mime = lookupMimeType(filename) || \"text/plain; charset=utf-8\";\n\t\tconst isHtml = String(mime).startsWith(\"text/html\");\n\t\tconst { accessToken, grant } = resolveArtifactAccessContext(req);\n\n\t\tconst title = `Maestro Artifact · ${filename}`;\n\t\tconst viewerUrl = buildSessionArtifactViewerUrl(sessionId, filename);\n\n\t\tconst eventsUrl = canUseArtifactAccess(grant, \"events\")\n\t\t\t? buildSessionArtifactsEventsUrl(sessionId, filename)\n\t\t\t: accessToken\n\t\t\t\t? null\n\t\t\t\t: buildSessionArtifactsEventsUrl(sessionId, filename);\n\t\tconst zipUrl = canUseArtifactAccess(grant, \"zip\")\n\t\t\t? buildSessionArtifactsZipUrl(sessionId)\n\t\t\t: accessToken\n\t\t\t\t? null\n\t\t\t\t: buildSessionArtifactsZipUrl(sessionId);\n\t\tconst rawDownloadUrl = canUseArtifactAccess(grant, \"file\")\n\t\t\t? buildSessionArtifactFileUrl(sessionId, filename, {\n\t\t\t\t\tdownload: true,\n\t\t\t\t\traw: true,\n\t\t\t\t})\n\t\t\t: accessToken\n\t\t\t\t? null\n\t\t\t\t: buildSessionArtifactFileUrl(sessionId, filename, {\n\t\t\t\t\t\tdownload: true,\n\t\t\t\t\t\traw: true,\n\t\t\t\t\t});\n\t\tconst standaloneDownloadUrl = isHtml\n\t\t\t? canUseArtifactAccess(grant, \"file\")\n\t\t\t\t? buildSessionArtifactFileUrl(sessionId, filename, {\n\t\t\t\t\t\tdownload: true,\n\t\t\t\t\t\tstandalone: true,\n\t\t\t\t\t})\n\t\t\t\t: accessToken\n\t\t\t\t\t? null\n\t\t\t\t\t: buildSessionArtifactFileUrl(sessionId, filename, {\n\t\t\t\t\t\t\tdownload: true,\n\t\t\t\t\t\t\tstandalone: true,\n\t\t\t\t\t\t})\n\t\t\t: null;\n\n\t\tconst zipAction = zipUrl\n\t\t\t? accessToken\n\t\t\t\t? `<button id=\"download-zip\" class=\"hint-button\" type=\"button\">Download ZIP</button>`\n\t\t\t\t: `<a class=\"hint\" href=\"${zipUrl}\" target=\"_blank\" rel=\"noopener\">Download ZIP</a>`\n\t\t\t: \"\";\n\t\tconst rawDownloadAction = rawDownloadUrl\n\t\t\t? accessToken\n\t\t\t\t? `<button id=\"download-raw\" class=\"hint-button\" type=\"button\">Download Raw</button>`\n\t\t\t\t: `<a class=\"hint\" href=\"${rawDownloadUrl}\" target=\"_blank\" rel=\"noopener\">Download Raw</a>`\n\t\t\t: \"\";\n\t\tconst standaloneDownloadAction = standaloneDownloadUrl\n\t\t\t? accessToken\n\t\t\t\t? `<button id=\"download-standalone\" class=\"hint-button\" type=\"button\">Download Standalone</button>`\n\t\t\t\t: `<a class=\"hint\" href=\"${standaloneDownloadUrl}\" target=\"_blank\" rel=\"noopener\">Download Standalone</a>`\n\t\t\t: \"\";\n\t\tconst zipDownloadName = `${sessionId}-artifacts.zip`;\n\n\t\tconst srcdoc = isHtml\n\t\t\t? injectArtifactsSnapshotRuntime(content, artifacts)\n\t\t\t: wrapHtmlDocument(\n\t\t\t\t\t`<pre style=\"white-space:pre-wrap; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-size: 13px; line-height: 1.4; padding: 16px; margin: 0;\">${content\n\t\t\t\t\t\t.replace(/&/g, \"&amp;\")\n\t\t\t\t\t\t.replace(/</g, \"&lt;\")\n\t\t\t\t\t\t.replace(/>/g, \"&gt;\")}</pre>`,\n\t\t\t\t);\n\n\t\tconst openExternalHandler = `\n<script>\nwindow.addEventListener(\"message\", (e) => {\n if (!e || !e.data) return;\n if (e.data.type !== \"open-external-url\") return;\n const url = e.data.url;\n if (typeof url !== \"string\") return;\n let parsed;\n try { parsed = new URL(url); } catch { return; }\n if (!parsed || (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\")) return;\n window.open(url, \"_blank\", \"noopener,noreferrer\");\n});\n</script>\n`.trim();\n\n\t\tconst viewerHtml = `<!doctype html>\n<html>\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>${title.replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\")}</title>\n <style>\n html, body { height: 100%; margin: 0; background: #0b0c0f; color: #e6edf3; font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }\n .bar { display:flex; align-items:center; gap:12px; padding:10px 12px; border-bottom: 1px solid #1e2023; background: #08090a; position: sticky; top: 0; z-index: 1; }\n .title { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-size: 12px; color: #9da3af; }\n .spacer { flex: 1; }\n a, button { font: inherit; }\n button { background: transparent; border: 1px solid #30363d; color: #c9d1d9; padding: 6px 10px; cursor: pointer; }\n button:hover { border-color: #58a6ff; color: #58a6ff; }\n iframe { width: 100%; height: calc(100% - 52px); border: 0; display:block; background: #fff; }\n .hint { font-size: 12px; color: #7d8590; }\n .hint-button { padding: 0; border: 0; color: #7d8590; font-size: 12px; }\n </style>\n </head>\n <body>\n <div class=\"bar\">\n <div class=\"title\">${title.replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\")}</div>\n <div class=\"spacer\"></div>\n ${zipAction}\n ${rawDownloadAction}\n ${standaloneDownloadAction}\n <button id=\"reload\">Reload</button>\n </div>\n ${openExternalHandler}\n <iframe id=\"frame\" sandbox=\"allow-scripts allow-modals allow-downloads\"></iframe>\n <script>\n const frame = document.getElementById(\"frame\");\n const reloadBtn = document.getElementById(\"reload\");\n const viewerUrl = ${JSON.stringify(viewerUrl)};\n const eventsUrl = ${JSON.stringify(eventsUrl)};\n const zipUrl = ${JSON.stringify(zipUrl)};\n const rawDownloadUrl = ${JSON.stringify(rawDownloadUrl)};\n const standaloneDownloadUrl = ${JSON.stringify(standaloneDownloadUrl)};\n const artifactAccessToken = ${JSON.stringify(accessToken)};\n const artifactAccessHeaders = artifactAccessToken\n ? { ${JSON.stringify(ARTIFACT_ACCESS_HEADER)}: artifactAccessToken }\n : undefined;\n\n const setDoc = (html) => {\n frame.srcdoc = html;\n };\n\n const parseDownloadFilename = (response, fallbackName) => {\n const contentDisposition = response.headers.get(\"content-disposition\") || \"\";\n const utf8Match = contentDisposition.match(/filename\\*=UTF-8''([^;]+)/i);\n if (utf8Match?.[1]) {\n try {\n return decodeURIComponent(utf8Match[1]);\n } catch {\n return utf8Match[1];\n }\n }\n const quotedMatch = contentDisposition.match(/filename=\"([^\"]+)\"/i);\n if (quotedMatch?.[1]) {\n return quotedMatch[1];\n }\n const bareMatch = contentDisposition.match(/filename=([^;]+)/i);\n return bareMatch?.[1]?.trim() || fallbackName || \"\";\n };\n\n const fetchViewerResource = async (url) => {\n const response = await fetch(url, {\n cache: \"no-store\",\n ...(artifactAccessHeaders ? { headers: artifactAccessHeaders } : {}),\n });\n if (!response.ok) {\n\t\t throw new Error(\"Request failed (\" + response.status + \")\");\n }\n return response;\n };\n\n const downloadViewerResource = async (url, fallbackName) => {\n const response = await fetchViewerResource(url);\n const blob = await response.blob();\n const objectUrl = URL.createObjectURL(blob);\n const link = document.createElement(\"a\");\n link.href = objectUrl;\n const downloadName = parseDownloadFilename(response, fallbackName);\n if (downloadName) {\n link.download = downloadName;\n }\n link.rel = \"noopener\";\n link.style.display = \"none\";\n document.body.appendChild(link);\n link.click();\n link.remove();\n setTimeout(() => URL.revokeObjectURL(objectUrl), 60_000);\n };\n\n const refreshViewer = async () => {\n if (!artifactAccessHeaders) {\n location.reload();\n return;\n }\n const response = await fetchViewerResource(viewerUrl);\n const nextHtml = await response.text();\n const nextUrl = URL.createObjectURL(\n new Blob([nextHtml], { type: \"text/html\" }),\n );\n setTimeout(() => URL.revokeObjectURL(nextUrl), 60_000);\n location.replace(nextUrl);\n };\n\n const triggerRefresh = () => {\n void refreshViewer().catch((err) => {\n console.error(\"[Maestro] Failed to refresh viewer:\", err);\n });\n };\n\n const bindDownloadButton = (id, url, fallbackName) => {\n const button = document.getElementById(id);\n if (!button || !url || !artifactAccessHeaders) {\n return;\n }\n button.addEventListener(\"click\", () => {\n void downloadViewerResource(url, fallbackName).catch((err) => {\n console.error(\"[Maestro] Failed to download artifact:\", err);\n });\n });\n };\n\n const srcdoc = ${JSON.stringify(srcdoc)};\n setDoc(srcdoc);\n\n\t\t\t\tbindDownloadButton(\"download-zip\", zipUrl, ${JSON.stringify(zipDownloadName)});\n bindDownloadButton(\"download-raw\", rawDownloadUrl, ${JSON.stringify(filename)});\n bindDownloadButton(\"download-standalone\", standaloneDownloadUrl, ${JSON.stringify(filename)});\n\n reloadBtn.addEventListener(\"click\", () => triggerRefresh());\n\n ${\n\t\t\t\teventsUrl\n\t\t\t\t\t? `try {\n\t\tconst reload = () => triggerRefresh();\n const connect = ${\n\t\t\t\t\taccessToken\n\t\t\t\t\t\t? `async () => {\n\t\t const response = await fetchViewerResource(eventsUrl);\n if (!response.body) throw new Error(\"Missing response body\");\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n let boundary = buffer.indexOf(\"\\\\n\\\\n\");\n while (boundary !== -1) {\n const chunk = buffer.slice(0, boundary);\n buffer = buffer.slice(boundary + 2);\n const dataLine = chunk\n .split(\"\\\\n\")\n .find((line) => line.startsWith(\"data:\"));\n if (dataLine) {\n reload();\n return;\n }\n boundary = buffer.indexOf(\"\\\\n\\\\n\");\n }\n }\n }`\n\t\t\t\t\t\t: `() => {\n const es = new EventSource(${JSON.stringify(eventsUrl)});\n es.onmessage = () => reload();\n }`\n\t\t\t\t};\n Promise.resolve(connect()).catch((err) => {\n console.error(\"[Maestro] Failed to setup viewer live reload transport:\", err);\n });\n } catch (err) { console.error(\"[Maestro] Failed to setup viewer EventSource:\", err); }`\n\t\t\t\t\t: \"\"\n\t\t\t}\n </script>\n </body>\n</html>`;\n\n\t\tres.writeHead(200, {\n\t\t\t\"Content-Type\": \"text/html; charset=utf-8\",\n\t\t\t\"Cache-Control\": \"no-store\",\n\t\t\t...cors,\n\t\t});\n\t\tres.end(viewerHtml);\n\t} catch (err) {\n\t\tconst error =\n\t\t\terr instanceof ApiError ? err : new ApiError(500, \"Internal error\");\n\t\tsendJson(res, error.statusCode, { error: error.message }, cors, req);\n\t}\n}\n\nexport async function handleSessionArtifactsEvents(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tparams: { id: string },\n\tcors: Record<string, string>,\n) {\n\tconst sessionId = params.id;\n\ttry {\n\t\tif (req.method !== \"GET\") {\n\t\t\tres.writeHead(405, cors);\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\t\tif (!sessionIdPattern.test(sessionId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid session id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst url = new URL(req.url || \"\", \"http://localhost\");\n\t\tconst filenameFilter = url.searchParams.get(\"filename\");\n\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\tlet closed = false;\n\t\tconst canWrite = () =>\n\t\t\tres.writable !== false && !res.writableEnded && !res.destroyed;\n\t\tconst safeWrite = (payload: string) => {\n\t\t\tif (!canWrite()) return false;\n\t\t\ttry {\n\t\t\t\tres.write(payload);\n\t\t\t\treturn true;\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t};\n\n\t\tlet heartbeat: ReturnType<typeof setInterval> | null = null;\n\t\tlet unsubscribe: () => void = () => {};\n\n\t\tconst cleanup = () => {\n\t\t\tif (closed) return;\n\t\t\tclosed = true;\n\t\t\tif (heartbeat) {\n\t\t\t\tclearInterval(heartbeat);\n\t\t\t\theartbeat = null;\n\t\t\t}\n\t\t\tunsubscribe();\n\t\t\treq.off(\"close\", cleanup);\n\t\t\tres.off(\"close\", cleanup);\n\t\t};\n\n\t\tunsubscribe = subscribeArtifactUpdates(sessionId, (event) => {\n\t\t\tif (filenameFilter && event.filename !== filenameFilter) return;\n\t\t\tif (!safeWrite(`data: ${JSON.stringify(event)}\\n\\n`)) {\n\t\t\t\tcleanup();\n\t\t\t}\n\t\t});\n\n\t\theartbeat = setInterval(() => {\n\t\t\tif (!safeWrite(\": ping\\n\\n\")) {\n\t\t\t\tcleanup();\n\t\t\t}\n\t\t}, 15_000);\n\n\t\tif (heartbeat.unref) {\n\t\t\theartbeat.unref();\n\t\t}\n\n\t\tif (!safeWrite(\": ok\\n\\n\")) {\n\t\t\tcleanup();\n\t\t\treturn;\n\t\t}\n\n\t\treq.on(\"close\", cleanup);\n\t\tres.on(\"close\", cleanup);\n\t} catch (err) {\n\t\tconst error =\n\t\t\terr instanceof ApiError ? err : new ApiError(500, \"Internal error\");\n\t\tsendJson(res, error.statusCode, { error: error.message }, cors, req);\n\t}\n}\n\nexport async function handleSessionArtifactsZip(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tparams: { id: string },\n\tcors: Record<string, string>,\n) {\n\tconst sessionId = params.id;\n\ttry {\n\t\tif (req.method !== \"GET\") {\n\t\t\tres.writeHead(405, cors);\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\t\tif (!sessionIdPattern.test(sessionId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid session id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst messages = await loadComposerMessages(req, sessionId);\n\t\tconst artifacts = reconstructArtifactsFromMessages(messages);\n\n\t\t// Lazy import to keep startup cost low.\n\t\tconst { strToU8, zipSync } = await import(\"fflate\");\n\n\t\tconst entries: Record<string, Uint8Array> = {};\n\t\tfor (const [filename, content] of artifacts) {\n\t\t\tentries[filename] = strToU8(content);\n\t\t}\n\n\t\tconst zipBytes = zipSync(entries, { level: 6 });\n\n\t\tres.writeHead(200, {\n\t\t\t\"Content-Type\": \"application/zip\",\n\t\t\t\"Content-Disposition\": buildContentDisposition(\n\t\t\t\t`artifacts-${sessionId}.zip`,\n\t\t\t),\n\t\t\t\"Cache-Control\": \"no-store\",\n\t\t\t...cors,\n\t\t});\n\t\tres.end(Buffer.from(zipBytes));\n\t} catch (err) {\n\t\tlogger.warn(\"Failed to export artifacts zip\", {\n\t\t\terr: err instanceof Error ? err.message : String(err),\n\t\t\tsessionId,\n\t\t});\n\t\tconst error =\n\t\t\terr instanceof ApiError ? err : new ApiError(500, \"Internal error\");\n\t\tsendJson(res, error.statusCode, { error: error.message }, cors, req);\n\t}\n}\n"]}
1
+ {"version":3,"file":"session-artifacts.js","sourceRoot":"","sources":["../../../src/server/handlers/session-artifacts.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport {\n\ttype ComposerMessage,\n\tartifactContentsByFilename,\n\tisValidArtifactFilename,\n\treconstructArtifactsFromMessages as reconstructArtifactStateFromMessages,\n} from \"@evalops/contracts\";\nimport { lookup as lookupMimeType } from \"mime-types\";\nimport { createLogger } from \"../../utils/logger.js\";\nimport {\n\tARTIFACT_ACCESS_HEADER,\n\ttype ArtifactAccessAction,\n\tgetArtifactAccessGrantFromRequest,\n\tgetArtifactAccessTokenFromRequest,\n\tissueArtifactAccessGrant,\n} from \"../artifact-access.js\";\nimport { subscribeArtifactUpdates } from \"../artifacts-live-reload.js\";\nimport {\n\tApiError,\n\tbuildContentDisposition,\n\tsendJson,\n} from \"../server-utils.js\";\nimport {\n\tcreateWebSessionManagerForRequest,\n\tresolveSessionScope,\n} from \"../session-scope.js\";\nimport { convertAppMessagesToComposer } from \"../session-serialization.js\";\n\nconst logger = createLogger(\"session-artifacts\");\nconst sessionIdPattern = /^[a-zA-Z0-9._-]+$/;\n\nfunction escapeScriptContent(code: string): string {\n\treturn code.replace(/<\\/script/gi, \"<\\\\/script\");\n}\n\nfunction injectLiveReload(html: string, eventsUrl: string): string {\n\treturn injectLiveReloadWithAuth(html, eventsUrl);\n}\n\nfunction injectLiveReloadWithAuth(\n\thtml: string,\n\teventsUrl: string,\n\taccessToken?: string | null,\n): string {\n\tconst authHeaders = accessToken\n\t\t? `{ ${JSON.stringify(ARTIFACT_ACCESS_HEADER)}: ${JSON.stringify(accessToken)} }`\n\t\t: \"undefined\";\n\tconst scriptBody = `\n\t(function() {\n\t try {\n\t const reload = () => location.reload();\n\t const connect = ${\n\t\t\t\taccessToken\n\t\t\t\t\t? `async () => {\n\t const response = await fetch(${JSON.stringify(eventsUrl)}, {\n\t headers: ${authHeaders},\n\t cache: \"no-store\",\n\t });\n\t if (!response.body) throw new Error(\"Missing response body\");\n\t const reader = response.body.getReader();\n\t const decoder = new TextDecoder();\n\t let buffer = \"\";\n\t while (true) {\n\t const { done, value } = await reader.read();\n\t if (done) break;\n\t buffer += decoder.decode(value, { stream: true });\n\t let boundary = buffer.indexOf(\"\\\\n\\\\n\");\n\t while (boundary !== -1) {\n\t const chunk = buffer.slice(0, boundary);\n\t buffer = buffer.slice(boundary + 2);\n\t const dataLine = chunk\n\t .split(\"\\\\n\")\n\t .find((line) => line.startsWith(\"data:\"));\n\t if (dataLine) {\n\t reload();\n\t return;\n\t }\n\t boundary = buffer.indexOf(\"\\\\n\\\\n\");\n\t }\n\t }\n\t }`\n\t\t\t\t\t: `() => {\n\t const es = new EventSource(${JSON.stringify(eventsUrl)});\n\t es.onmessage = (e) => {\n\t try {\n\t const data = JSON.parse(e.data);\n\t if (data && data.type === \"artifact_updated\") {\n\t reload();\n\t }\n\t } catch (err) { console.error(\"[Maestro] Failed to parse live reload event:\", err); }\n\t };\n\t }`\n\t\t\t};\n\t Promise.resolve(connect()).catch((err) => {\n\t console.error(\"[Maestro] Failed to setup live reload transport:\", err);\n\t });\n\t } catch (err) { console.error(\"[Maestro] Failed to setup live reload EventSource:\", err); }\n\t})();\n\t`.trim();\n\tconst script = `<script>\\n${escapeScriptContent(scriptBody)}\\n</script>`;\n\tconst injected = `\\n${script}\\n`;\n\tif (/<\\/body>/i.test(html)) {\n\t\treturn html.replace(/<\\/body>/i, `${injected}</body>`);\n\t}\n\treturn `${html}${injected}`;\n}\n\nfunction wrapHtmlDocument(htmlContent: string): string {\n\tconst trimmed = htmlContent.trim();\n\tconst looksLikeDocument =\n\t\t/^<!doctype/i.test(trimmed) || /<html[\\s>]/i.test(trimmed);\n\n\tif (looksLikeDocument) return trimmed;\n\n\treturn `<!doctype html>\n<html>\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n </head>\n <body>\n${trimmed}\n </body>\n</html>`;\n}\n\nfunction injectArtifactsSnapshotRuntime(\n\thtmlContent: string,\n\tartifacts: Map<string, string>,\n): string {\n\tconst snapshot: Record<string, string> = {};\n\tfor (const [name, content] of artifacts) {\n\t\tsnapshot[name] = content;\n\t}\n\n\tconst runtime = `\n<script>\n(function() {\n try {\n window.artifacts = ${escapeScriptContent(JSON.stringify(snapshot))};\n } catch (err) {\n console.error(\"[Maestro] Failed to initialize artifacts snapshot:\", err);\n window.artifacts = {};\n }\n\n const isJson = (f) => (f || \"\").toLowerCase().endsWith(\".json\");\n\n window.listArtifacts = async () => Object.keys(window.artifacts || {});\n\n window.getArtifact = async (filename) => {\n const content = (window.artifacts || {})[filename];\n if (typeof content !== \"string\") throw new Error(\"Artifact not found: \" + filename);\n if (isJson(filename)) {\n try { return JSON.parse(content); } catch (e) { throw new Error(\"Failed to parse JSON: \" + e); }\n }\n return content;\n };\n})();\n</script>\n`.trim();\n\n\tconst html = wrapHtmlDocument(htmlContent);\n\tif (/<\\/body>/i.test(html)) {\n\t\treturn html.replace(/<\\/body>/i, `\\n${runtime}\\n</body>`);\n\t}\n\treturn `${html}\\n${runtime}`;\n}\n\nfunction reconstructArtifactsFromMessages(\n\tmessages: ComposerMessage[],\n): Map<string, string> {\n\tconst diagnostics: string[] = [];\n\tconst state = reconstructArtifactStateFromMessages(messages, {\n\t\tonDiagnostic: (diagnostic) => {\n\t\t\tdiagnostics.push(diagnostic.code);\n\t\t},\n\t});\n\tif (diagnostics.length > 0) {\n\t\tlogger.warn(\"Skipped invalid persisted artifact commands\", {\n\t\t\tcount: diagnostics.length,\n\t\t\tcodes: diagnostics,\n\t\t});\n\t}\n\treturn artifactContentsByFilename(state);\n}\n\nasync function loadComposerMessages(\n\treq: IncomingMessage,\n\tsessionId: string,\n): Promise<ComposerMessage[]> {\n\tconst sessionManager = createWebSessionManagerForRequest(req, true);\n\tconst session = await sessionManager.loadSession(sessionId);\n\tif (!session) {\n\t\tthrow new ApiError(404, \"Session not found\");\n\t}\n\treturn convertAppMessagesToComposer(session.messages || []);\n}\n\nfunction validateFilename(filename: string): void {\n\t// Keep this strict: no path traversal, no folder hierarchies.\n\tif (!isValidArtifactFilename(filename.trim())) {\n\t\tthrow new ApiError(400, \"Invalid filename\");\n\t}\n}\n\nfunction buildSessionArtifactFileUrl(\n\tsessionId: string,\n\tfilename: string,\n\toptions?: {\n\t\tdownload?: boolean;\n\t\traw?: boolean;\n\t\tstandalone?: boolean;\n\t},\n): string {\n\tconst path = `/api/sessions/${encodeURIComponent(sessionId)}/artifacts/${encodeURIComponent(filename)}`;\n\tconst url = new URL(path, \"http://localhost\");\n\tif (options?.download) url.searchParams.set(\"download\", \"1\");\n\tif (options?.raw) url.searchParams.set(\"raw\", \"1\");\n\tif (options?.standalone) url.searchParams.set(\"standalone\", \"1\");\n\treturn `${url.pathname}${url.search}`;\n}\n\nfunction buildSessionArtifactViewerUrl(\n\tsessionId: string,\n\tfilename: string,\n): string {\n\treturn `/api/sessions/${encodeURIComponent(sessionId)}/artifacts/${encodeURIComponent(filename)}/view`;\n}\n\nfunction buildSessionArtifactsEventsUrl(\n\tsessionId: string,\n\tfilename: string,\n): string {\n\tconst url = new URL(\n\t\t`/api/sessions/${encodeURIComponent(sessionId)}/artifacts/events`,\n\t\t\"http://localhost\",\n\t);\n\turl.searchParams.set(\"filename\", filename);\n\treturn `${url.pathname}${url.search}`;\n}\n\nfunction buildSessionArtifactsZipUrl(sessionId: string): string {\n\treturn `/api/sessions/${encodeURIComponent(sessionId)}/artifacts.zip`;\n}\n\nfunction resolveArtifactAccessContext(req: IncomingMessage): {\n\taccessToken: string | null;\n\tgrant: ReturnType<typeof getArtifactAccessGrantFromRequest>;\n} {\n\tconst grant = getArtifactAccessGrantFromRequest(req);\n\treturn {\n\t\taccessToken: grant ? getArtifactAccessTokenFromRequest(req) : null,\n\t\tgrant,\n\t};\n}\n\nfunction canUseArtifactAccess(\n\tgrant: ReturnType<typeof getArtifactAccessGrantFromRequest>,\n\taction: ArtifactAccessAction,\n): boolean {\n\treturn Boolean(grant?.actions.includes(action));\n}\n\nexport async function handleSessionArtifactsIndex(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tparams: { id: string },\n\tcors: Record<string, string>,\n) {\n\tconst sessionId = params.id;\n\ttry {\n\t\tif (req.method !== \"GET\") {\n\t\t\tres.writeHead(405, cors);\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\t\tif (!sessionIdPattern.test(sessionId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid session id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst messages = await loadComposerMessages(req, sessionId);\n\t\tconst artifacts = reconstructArtifactsFromMessages(messages);\n\t\tsendJson(\n\t\t\tres,\n\t\t\t200,\n\t\t\t{\n\t\t\t\tsessionId,\n\t\t\t\tfilenames: Array.from(artifacts.keys()).sort((a, b) =>\n\t\t\t\t\ta.localeCompare(b),\n\t\t\t\t),\n\t\t\t},\n\t\t\tcors,\n\t\t\treq,\n\t\t);\n\t} catch (err) {\n\t\tconst error =\n\t\t\terr instanceof ApiError ? err : new ApiError(500, \"Internal error\");\n\t\tsendJson(res, error.statusCode, { error: error.message }, cors, req);\n\t}\n}\n\nexport async function handleSessionArtifactAccess(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tparams: { id: string },\n\tcors: Record<string, string>,\n) {\n\tconst sessionId = params.id;\n\ttry {\n\t\tif (req.method !== \"GET\") {\n\t\t\tres.writeHead(405, cors);\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\t\tif (!sessionIdPattern.test(sessionId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid session id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst url = new URL(req.url || \"\", \"http://localhost\");\n\t\tconst filename = url.searchParams.get(\"filename\")?.trim() || undefined;\n\t\tconst actions = Array.from(\n\t\t\tnew Set(\n\t\t\t\t(url.searchParams.get(\"actions\") || \"\")\n\t\t\t\t\t.split(\",\")\n\t\t\t\t\t.map((action) => action.trim())\n\t\t\t\t\t.filter(Boolean),\n\t\t\t),\n\t\t).filter((action): action is ArtifactAccessAction => {\n\t\t\treturn [\"view\", \"file\", \"events\", \"zip\"].includes(action);\n\t\t});\n\n\t\tif (actions.length === 0) {\n\t\t\tsendJson(\n\t\t\t\tres,\n\t\t\t\t400,\n\t\t\t\t{ error: \"At least one artifact access action is required\" },\n\t\t\t\tcors,\n\t\t\t\treq,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tif (filename) {\n\t\t\tvalidateFilename(filename);\n\t\t}\n\n\t\tif (!filename && actions.some((action) => action !== \"zip\")) {\n\t\t\tsendJson(\n\t\t\t\tres,\n\t\t\t\t400,\n\t\t\t\t{ error: \"filename is required for artifact file access\" },\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 messages = await loadComposerMessages(req, sessionId);\n\t\tconst artifacts = reconstructArtifactsFromMessages(messages);\n\n\t\tif (filename && !artifacts.has(filename)) {\n\t\t\tsendJson(res, 404, { error: \"Artifact not found\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst access = issueArtifactAccessGrant({\n\t\t\tsessionId,\n\t\t\tscope: resolveSessionScope(req),\n\t\t\tfilename,\n\t\t\tactions,\n\t\t});\n\n\t\tsendJson(\n\t\t\tres,\n\t\t\t200,\n\t\t\t{\n\t\t\t\ttoken: access.token,\n\t\t\t\texpiresAt: access.expiresAtIso,\n\t\t\t\tactions: access.actions,\n\t\t\t\tsessionId,\n\t\t\t\t...(filename ? { filename } : {}),\n\t\t\t},\n\t\t\tcors,\n\t\t\treq,\n\t\t);\n\t} catch (err) {\n\t\tconst error =\n\t\t\terr instanceof ApiError ? err : new ApiError(500, \"Internal error\");\n\t\tsendJson(res, error.statusCode, { error: error.message }, cors, req);\n\t}\n}\n\nexport async function handleSessionArtifactFile(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tparams: { id: string; filename: string },\n\tcors: Record<string, string>,\n) {\n\tconst sessionId = params.id;\n\tconst filename = decodeURIComponent(params.filename || \"\");\n\n\ttry {\n\t\tif (req.method !== \"GET\") {\n\t\t\tres.writeHead(405, cors);\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\t\tif (!sessionIdPattern.test(sessionId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid session id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\t\tvalidateFilename(filename);\n\n\t\tconst messages = await loadComposerMessages(req, sessionId);\n\t\tconst artifacts = reconstructArtifactsFromMessages(messages);\n\t\tconst content = artifacts.get(filename);\n\t\tif (content === undefined) {\n\t\t\tsendJson(res, 404, { error: \"Artifact not found\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst url = new URL(req.url || \"\", \"http://localhost\");\n\t\tconst wantsDownload = url.searchParams.get(\"download\") === \"1\";\n\t\tconst wantsRaw = url.searchParams.get(\"raw\") === \"1\";\n\t\tconst wantsStandalone = url.searchParams.get(\"standalone\") === \"1\";\n\n\t\tconst mime = lookupMimeType(filename) || \"text/plain; charset=utf-8\";\n\t\tconst isHtml = String(mime).startsWith(\"text/html\");\n\t\tconst { accessToken, grant } = resolveArtifactAccessContext(req);\n\n\t\tconst eventsUrl = canUseArtifactAccess(grant, \"events\")\n\t\t\t? buildSessionArtifactsEventsUrl(sessionId, filename)\n\t\t\t: accessToken\n\t\t\t\t? null\n\t\t\t\t: buildSessionArtifactsEventsUrl(sessionId, filename);\n\n\t\tlet body =\n\t\t\tisHtml && !wantsRaw && eventsUrl\n\t\t\t\t? injectLiveReloadWithAuth(content, eventsUrl, accessToken)\n\t\t\t\t: content;\n\n\t\t// Standalone download: force attachment and embed artifacts snapshot + helpers.\n\t\tif (isHtml && wantsStandalone) {\n\t\t\tbody = injectArtifactsSnapshotRuntime(body, artifacts);\n\t\t}\n\n\t\tres.writeHead(200, {\n\t\t\t\"Content-Type\": String(mime),\n\t\t\t\"Cache-Control\": \"no-store\",\n\t\t\t...(wantsDownload || wantsStandalone\n\t\t\t\t? {\n\t\t\t\t\t\t\"Content-Disposition\": buildContentDisposition(filename),\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t\t...cors,\n\t\t});\n\t\tres.end(body);\n\t} catch (err) {\n\t\tlogger.warn(\"Failed to serve artifact\", {\n\t\t\terr: err instanceof Error ? err.message : String(err),\n\t\t\tsessionId,\n\t\t\tfilename,\n\t\t});\n\t\tconst error =\n\t\t\terr instanceof ApiError ? err : new ApiError(500, \"Internal error\");\n\t\tsendJson(res, error.statusCode, { error: error.message }, cors, req);\n\t}\n}\n\nexport async function handleSessionArtifactViewer(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tparams: { id: string; filename: string },\n\tcors: Record<string, string>,\n) {\n\tconst sessionId = params.id;\n\tconst filename = decodeURIComponent(params.filename || \"\");\n\n\ttry {\n\t\tif (req.method !== \"GET\") {\n\t\t\tres.writeHead(405, cors);\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\t\tif (!sessionIdPattern.test(sessionId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid session id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\t\tvalidateFilename(filename);\n\n\t\tconst messages = await loadComposerMessages(req, sessionId);\n\t\tconst artifacts = reconstructArtifactsFromMessages(messages);\n\t\tconst content = artifacts.get(filename);\n\t\tif (content === undefined) {\n\t\t\tsendJson(res, 404, { error: \"Artifact not found\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst mime = lookupMimeType(filename) || \"text/plain; charset=utf-8\";\n\t\tconst isHtml = String(mime).startsWith(\"text/html\");\n\t\tconst { accessToken, grant } = resolveArtifactAccessContext(req);\n\n\t\tconst title = `Maestro Artifact · ${filename}`;\n\t\tconst viewerUrl = buildSessionArtifactViewerUrl(sessionId, filename);\n\n\t\tconst eventsUrl = canUseArtifactAccess(grant, \"events\")\n\t\t\t? buildSessionArtifactsEventsUrl(sessionId, filename)\n\t\t\t: accessToken\n\t\t\t\t? null\n\t\t\t\t: buildSessionArtifactsEventsUrl(sessionId, filename);\n\t\tconst zipUrl = canUseArtifactAccess(grant, \"zip\")\n\t\t\t? buildSessionArtifactsZipUrl(sessionId)\n\t\t\t: accessToken\n\t\t\t\t? null\n\t\t\t\t: buildSessionArtifactsZipUrl(sessionId);\n\t\tconst rawDownloadUrl = canUseArtifactAccess(grant, \"file\")\n\t\t\t? buildSessionArtifactFileUrl(sessionId, filename, {\n\t\t\t\t\tdownload: true,\n\t\t\t\t\traw: true,\n\t\t\t\t})\n\t\t\t: accessToken\n\t\t\t\t? null\n\t\t\t\t: buildSessionArtifactFileUrl(sessionId, filename, {\n\t\t\t\t\t\tdownload: true,\n\t\t\t\t\t\traw: true,\n\t\t\t\t\t});\n\t\tconst standaloneDownloadUrl = isHtml\n\t\t\t? canUseArtifactAccess(grant, \"file\")\n\t\t\t\t? buildSessionArtifactFileUrl(sessionId, filename, {\n\t\t\t\t\t\tdownload: true,\n\t\t\t\t\t\tstandalone: true,\n\t\t\t\t\t})\n\t\t\t\t: accessToken\n\t\t\t\t\t? null\n\t\t\t\t\t: buildSessionArtifactFileUrl(sessionId, filename, {\n\t\t\t\t\t\t\tdownload: true,\n\t\t\t\t\t\t\tstandalone: true,\n\t\t\t\t\t\t})\n\t\t\t: null;\n\n\t\tconst zipAction = zipUrl\n\t\t\t? accessToken\n\t\t\t\t? `<button id=\"download-zip\" class=\"hint-button\" type=\"button\">Download ZIP</button>`\n\t\t\t\t: `<a class=\"hint\" href=\"${zipUrl}\" target=\"_blank\" rel=\"noopener\">Download ZIP</a>`\n\t\t\t: \"\";\n\t\tconst rawDownloadAction = rawDownloadUrl\n\t\t\t? accessToken\n\t\t\t\t? `<button id=\"download-raw\" class=\"hint-button\" type=\"button\">Download Raw</button>`\n\t\t\t\t: `<a class=\"hint\" href=\"${rawDownloadUrl}\" target=\"_blank\" rel=\"noopener\">Download Raw</a>`\n\t\t\t: \"\";\n\t\tconst standaloneDownloadAction = standaloneDownloadUrl\n\t\t\t? accessToken\n\t\t\t\t? `<button id=\"download-standalone\" class=\"hint-button\" type=\"button\">Download Standalone</button>`\n\t\t\t\t: `<a class=\"hint\" href=\"${standaloneDownloadUrl}\" target=\"_blank\" rel=\"noopener\">Download Standalone</a>`\n\t\t\t: \"\";\n\t\tconst zipDownloadName = `${sessionId}-artifacts.zip`;\n\n\t\tconst srcdoc = isHtml\n\t\t\t? injectArtifactsSnapshotRuntime(content, artifacts)\n\t\t\t: wrapHtmlDocument(\n\t\t\t\t\t`<pre style=\"white-space:pre-wrap; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-size: 13px; line-height: 1.4; padding: 16px; margin: 0;\">${content\n\t\t\t\t\t\t.replace(/&/g, \"&amp;\")\n\t\t\t\t\t\t.replace(/</g, \"&lt;\")\n\t\t\t\t\t\t.replace(/>/g, \"&gt;\")}</pre>`,\n\t\t\t\t);\n\n\t\tconst openExternalHandler = `\n<script>\nwindow.addEventListener(\"message\", (e) => {\n if (!e || !e.data) return;\n if (e.data.type !== \"open-external-url\") return;\n const url = e.data.url;\n if (typeof url !== \"string\") return;\n let parsed;\n try { parsed = new URL(url); } catch { return; }\n if (!parsed || (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\")) return;\n window.open(url, \"_blank\", \"noopener,noreferrer\");\n});\n</script>\n`.trim();\n\n\t\tconst viewerHtml = `<!doctype html>\n<html>\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>${title.replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\")}</title>\n <style>\n html, body { height: 100%; margin: 0; background: #0b0c0f; color: #e6edf3; font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }\n .bar { display:flex; align-items:center; gap:12px; padding:10px 12px; border-bottom: 1px solid #1e2023; background: #08090a; position: sticky; top: 0; z-index: 1; }\n .title { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-size: 12px; color: #9da3af; }\n .spacer { flex: 1; }\n a, button { font: inherit; }\n button { background: transparent; border: 1px solid #30363d; color: #c9d1d9; padding: 6px 10px; cursor: pointer; }\n button:hover { border-color: #58a6ff; color: #58a6ff; }\n iframe { width: 100%; height: calc(100% - 52px); border: 0; display:block; background: #fff; }\n .hint { font-size: 12px; color: #7d8590; }\n .hint-button { padding: 0; border: 0; color: #7d8590; font-size: 12px; }\n </style>\n </head>\n <body>\n <div class=\"bar\">\n <div class=\"title\">${title.replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\")}</div>\n <div class=\"spacer\"></div>\n ${zipAction}\n ${rawDownloadAction}\n ${standaloneDownloadAction}\n <button id=\"reload\">Reload</button>\n </div>\n ${openExternalHandler}\n <iframe id=\"frame\" sandbox=\"allow-scripts allow-modals allow-downloads\"></iframe>\n <script>\n const frame = document.getElementById(\"frame\");\n const reloadBtn = document.getElementById(\"reload\");\n const viewerUrl = ${JSON.stringify(viewerUrl)};\n const eventsUrl = ${JSON.stringify(eventsUrl)};\n const zipUrl = ${JSON.stringify(zipUrl)};\n const rawDownloadUrl = ${JSON.stringify(rawDownloadUrl)};\n const standaloneDownloadUrl = ${JSON.stringify(standaloneDownloadUrl)};\n const artifactAccessToken = ${JSON.stringify(accessToken)};\n const artifactAccessHeaders = artifactAccessToken\n ? { ${JSON.stringify(ARTIFACT_ACCESS_HEADER)}: artifactAccessToken }\n : undefined;\n\n const setDoc = (html) => {\n frame.srcdoc = html;\n };\n\n const parseDownloadFilename = (response, fallbackName) => {\n const contentDisposition = response.headers.get(\"content-disposition\") || \"\";\n const utf8Match = contentDisposition.match(/filename\\*=UTF-8''([^;]+)/i);\n if (utf8Match?.[1]) {\n try {\n return decodeURIComponent(utf8Match[1]);\n } catch {\n return utf8Match[1];\n }\n }\n const quotedMatch = contentDisposition.match(/filename=\"([^\"]+)\"/i);\n if (quotedMatch?.[1]) {\n return quotedMatch[1];\n }\n const bareMatch = contentDisposition.match(/filename=([^;]+)/i);\n return bareMatch?.[1]?.trim() || fallbackName || \"\";\n };\n\n const fetchViewerResource = async (url) => {\n const response = await fetch(url, {\n cache: \"no-store\",\n ...(artifactAccessHeaders ? { headers: artifactAccessHeaders } : {}),\n });\n if (!response.ok) {\n\t\t throw new Error(\"Request failed (\" + response.status + \")\");\n }\n return response;\n };\n\n const downloadViewerResource = async (url, fallbackName) => {\n const response = await fetchViewerResource(url);\n const blob = await response.blob();\n const objectUrl = URL.createObjectURL(blob);\n const link = document.createElement(\"a\");\n link.href = objectUrl;\n const downloadName = parseDownloadFilename(response, fallbackName);\n if (downloadName) {\n link.download = downloadName;\n }\n link.rel = \"noopener\";\n link.style.display = \"none\";\n document.body.appendChild(link);\n link.click();\n link.remove();\n setTimeout(() => URL.revokeObjectURL(objectUrl), 60_000);\n };\n\n const refreshViewer = async () => {\n if (!artifactAccessHeaders) {\n location.reload();\n return;\n }\n const response = await fetchViewerResource(viewerUrl);\n const nextHtml = await response.text();\n const nextUrl = URL.createObjectURL(\n new Blob([nextHtml], { type: \"text/html\" }),\n );\n setTimeout(() => URL.revokeObjectURL(nextUrl), 60_000);\n location.replace(nextUrl);\n };\n\n const triggerRefresh = () => {\n void refreshViewer().catch((err) => {\n console.error(\"[Maestro] Failed to refresh viewer:\", err);\n });\n };\n\n const bindDownloadButton = (id, url, fallbackName) => {\n const button = document.getElementById(id);\n if (!button || !url || !artifactAccessHeaders) {\n return;\n }\n button.addEventListener(\"click\", () => {\n void downloadViewerResource(url, fallbackName).catch((err) => {\n console.error(\"[Maestro] Failed to download artifact:\", err);\n });\n });\n };\n\n const srcdoc = ${JSON.stringify(srcdoc)};\n setDoc(srcdoc);\n\n\t\t\t\tbindDownloadButton(\"download-zip\", zipUrl, ${JSON.stringify(zipDownloadName)});\n bindDownloadButton(\"download-raw\", rawDownloadUrl, ${JSON.stringify(filename)});\n bindDownloadButton(\"download-standalone\", standaloneDownloadUrl, ${JSON.stringify(filename)});\n\n reloadBtn.addEventListener(\"click\", () => triggerRefresh());\n\n ${\n\t\t\t\teventsUrl\n\t\t\t\t\t? `try {\n\t\tconst reload = () => triggerRefresh();\n const connect = ${\n\t\t\t\t\taccessToken\n\t\t\t\t\t\t? `async () => {\n\t\t const response = await fetchViewerResource(eventsUrl);\n if (!response.body) throw new Error(\"Missing response body\");\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n let boundary = buffer.indexOf(\"\\\\n\\\\n\");\n while (boundary !== -1) {\n const chunk = buffer.slice(0, boundary);\n buffer = buffer.slice(boundary + 2);\n const dataLine = chunk\n .split(\"\\\\n\")\n .find((line) => line.startsWith(\"data:\"));\n if (dataLine) {\n reload();\n return;\n }\n boundary = buffer.indexOf(\"\\\\n\\\\n\");\n }\n }\n }`\n\t\t\t\t\t\t: `() => {\n const es = new EventSource(${JSON.stringify(eventsUrl)});\n es.onmessage = () => reload();\n }`\n\t\t\t\t};\n Promise.resolve(connect()).catch((err) => {\n console.error(\"[Maestro] Failed to setup viewer live reload transport:\", err);\n });\n } catch (err) { console.error(\"[Maestro] Failed to setup viewer EventSource:\", err); }`\n\t\t\t\t\t: \"\"\n\t\t\t}\n </script>\n </body>\n</html>`;\n\n\t\tres.writeHead(200, {\n\t\t\t\"Content-Type\": \"text/html; charset=utf-8\",\n\t\t\t\"Cache-Control\": \"no-store\",\n\t\t\t...cors,\n\t\t});\n\t\tres.end(viewerHtml);\n\t} catch (err) {\n\t\tconst error =\n\t\t\terr instanceof ApiError ? err : new ApiError(500, \"Internal error\");\n\t\tsendJson(res, error.statusCode, { error: error.message }, cors, req);\n\t}\n}\n\nexport async function handleSessionArtifactsEvents(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tparams: { id: string },\n\tcors: Record<string, string>,\n) {\n\tconst sessionId = params.id;\n\ttry {\n\t\tif (req.method !== \"GET\") {\n\t\t\tres.writeHead(405, cors);\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\t\tif (!sessionIdPattern.test(sessionId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid session id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst url = new URL(req.url || \"\", \"http://localhost\");\n\t\tconst filenameFilter = url.searchParams.get(\"filename\");\n\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\tlet closed = false;\n\t\tconst canWrite = () =>\n\t\t\tres.writable !== false && !res.writableEnded && !res.destroyed;\n\t\tconst safeWrite = (payload: string) => {\n\t\t\tif (!canWrite()) return false;\n\t\t\ttry {\n\t\t\t\tres.write(payload);\n\t\t\t\treturn true;\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t};\n\n\t\tlet heartbeat: ReturnType<typeof setInterval> | null = null;\n\t\tlet unsubscribe: () => void = () => {};\n\n\t\tconst cleanup = () => {\n\t\t\tif (closed) return;\n\t\t\tclosed = true;\n\t\t\tif (heartbeat) {\n\t\t\t\tclearInterval(heartbeat);\n\t\t\t\theartbeat = null;\n\t\t\t}\n\t\t\tunsubscribe();\n\t\t\treq.off(\"close\", cleanup);\n\t\t\tres.off(\"close\", cleanup);\n\t\t};\n\n\t\tunsubscribe = subscribeArtifactUpdates(sessionId, (event) => {\n\t\t\tif (filenameFilter && event.filename !== filenameFilter) return;\n\t\t\tif (!safeWrite(`data: ${JSON.stringify(event)}\\n\\n`)) {\n\t\t\t\tcleanup();\n\t\t\t}\n\t\t});\n\n\t\theartbeat = setInterval(() => {\n\t\t\tif (!safeWrite(\": ping\\n\\n\")) {\n\t\t\t\tcleanup();\n\t\t\t}\n\t\t}, 15_000);\n\n\t\tif (heartbeat.unref) {\n\t\t\theartbeat.unref();\n\t\t}\n\n\t\tif (!safeWrite(\": ok\\n\\n\")) {\n\t\t\tcleanup();\n\t\t\treturn;\n\t\t}\n\n\t\treq.on(\"close\", cleanup);\n\t\tres.on(\"close\", cleanup);\n\t} catch (err) {\n\t\tconst error =\n\t\t\terr instanceof ApiError ? err : new ApiError(500, \"Internal error\");\n\t\tsendJson(res, error.statusCode, { error: error.message }, cors, req);\n\t}\n}\n\nexport async function handleSessionArtifactsZip(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tparams: { id: string },\n\tcors: Record<string, string>,\n) {\n\tconst sessionId = params.id;\n\ttry {\n\t\tif (req.method !== \"GET\") {\n\t\t\tres.writeHead(405, cors);\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\t\tif (!sessionIdPattern.test(sessionId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid session id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst messages = await loadComposerMessages(req, sessionId);\n\t\tconst artifacts = reconstructArtifactsFromMessages(messages);\n\n\t\t// Lazy import to keep startup cost low.\n\t\tconst { strToU8, zipSync } = await import(\"fflate\");\n\n\t\tconst entries: Record<string, Uint8Array> = {};\n\t\tfor (const [filename, content] of artifacts) {\n\t\t\tentries[filename] = strToU8(content);\n\t\t}\n\n\t\tconst zipBytes = zipSync(entries, { level: 6 });\n\n\t\tres.writeHead(200, {\n\t\t\t\"Content-Type\": \"application/zip\",\n\t\t\t\"Content-Disposition\": buildContentDisposition(\n\t\t\t\t`artifacts-${sessionId}.zip`,\n\t\t\t),\n\t\t\t\"Cache-Control\": \"no-store\",\n\t\t\t...cors,\n\t\t});\n\t\tres.end(Buffer.from(zipBytes));\n\t} catch (err) {\n\t\tlogger.warn(\"Failed to export artifacts zip\", {\n\t\t\terr: err instanceof Error ? err.message : String(err),\n\t\t\tsessionId,\n\t\t});\n\t\tconst error =\n\t\t\terr instanceof ApiError ? err : new ApiError(500, \"Internal error\");\n\t\tsendJson(res, error.statusCode, { error: error.message }, cors, req);\n\t}\n}\n"]}