@astralform/js 0.2.0 → 0.2.2

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,"sources":["../src/index.ts","../src/errors.ts","../src/streaming.ts","../src/client.ts","../src/block-builder.ts","../src/storage.ts","../src/tools.ts","../src/utils.ts","../src/session.ts","../src/standard-handlers.ts"],"sourcesContent":["// Core classes\nexport { AstralformClient } from \"./client.js\";\nexport { ChatSession } from \"./session.js\";\nexport {\n BlockBuilder,\n type Block,\n type UserBlock,\n type TextBlock,\n type ThinkingBlock,\n type AgentBlock,\n type SubagentBlock,\n type ToolBlock,\n type ErrorBlock,\n type EventHandler,\n} from \"./block-builder.js\";\nexport { standardHandlers } from \"./standard-handlers.js\";\nexport { ToolRegistry, type ToolHandler } from \"./tools.js\";\nexport { InMemoryStorage, type ChatStorage } from \"./storage.js\";\n\n// Errors\nexport {\n AstralformError,\n AuthenticationError,\n RateLimitError,\n LLMNotConfiguredError,\n ServerError,\n ConnectionError,\n StreamAbortedError,\n} from \"./errors.js\";\n\n// Utilities\nexport { generateId } from \"./utils.js\";\n\n// Streaming\nexport { streamJobSSE } from \"./streaming.js\";\n\n// Types\nexport type {\n AstralformConfig,\n MessageStartEvent,\n ContentBlockDeltaEvent,\n ToolUseStartEvent,\n ToolUseEndEvent,\n AgentStartEvent,\n AgentEndEvent,\n SubagentStartEvent,\n SubagentContentDeltaEvent,\n SubagentEndEvent,\n SubagentToolUseEvent,\n ThinkingDeltaEvent,\n ThinkingCompleteEvent,\n SourcesEvent,\n CapsuleOutputEvent,\n CapsuleOutputChunkEvent,\n TodoUpdateEvent,\n MessageStopEvent,\n RetryEvent,\n SSEErrorEvent,\n SSEEvent,\n ChatEvent,\n Conversation,\n Message,\n ProjectStatus,\n AgentInfo,\n SkillInfo,\n SubagentState,\n ToolState,\n CapsuleOutput,\n Source,\n TodoItem,\n ChatStreamRequest,\n ToolResultRequest,\n ToolResult,\n ToolDefinition,\n ToolCallRequest,\n ConversationAsset,\n StreamJobSSEOptions,\n JobCreateResponse,\n ChatStreamEvent,\n ConversationEvent,\n SendOptions,\n} from \"./types.js\";\n","export class AstralformError extends Error {\n constructor(\n message: string,\n public code: string,\n ) {\n super(message);\n this.name = \"AstralformError\";\n }\n}\n\nexport class AuthenticationError extends AstralformError {\n constructor(message = \"Invalid or missing API key\") {\n super(message, \"authentication_error\");\n this.name = \"AuthenticationError\";\n }\n}\n\nexport class RateLimitError extends AstralformError {\n constructor(message = \"Rate limit exceeded\") {\n super(message, \"rate_limit_error\");\n this.name = \"RateLimitError\";\n }\n}\n\nexport class LLMNotConfiguredError extends AstralformError {\n constructor(message = \"LLM provider not configured for this project\") {\n super(message, \"llm_not_configured\");\n this.name = \"LLMNotConfiguredError\";\n }\n}\n\nexport class ServerError extends AstralformError {\n constructor(message = \"Internal server error\") {\n super(message, \"server_error\");\n this.name = \"ServerError\";\n }\n}\n\nexport class ConnectionError extends AstralformError {\n constructor(message = \"Failed to connect to server\") {\n super(message, \"connection_error\");\n this.name = \"ConnectionError\";\n }\n}\n\nexport class StreamAbortedError extends AstralformError {\n constructor(message = \"Stream was aborted\") {\n super(message, \"stream_aborted\");\n this.name = \"StreamAbortedError\";\n }\n}\n","import {\n AuthenticationError,\n ConnectionError,\n RateLimitError,\n ServerError,\n StreamAbortedError,\n} from \"./errors.js\";\nimport type { ChatStreamEvent, StreamJobSSEOptions } from \"./types.js\";\n\n/**\n * GET-based SSE stream for job events.\n */\nexport async function* streamJobSSE(\n options: StreamJobSSEOptions,\n): AsyncGenerator<ChatStreamEvent> {\n const { url, headers, signal, fetchFn } = options;\n\n let response: Response;\n try {\n response = await fetchFn(url, {\n method: \"GET\",\n headers,\n signal,\n });\n } catch (err) {\n if (err instanceof DOMException && err.name === \"AbortError\") {\n throw new StreamAbortedError();\n }\n throw new ConnectionError(\n err instanceof Error ? err.message : \"Failed to connect\",\n );\n }\n\n if (!response.ok) {\n const rawText = await response.text().catch(() => \"\");\n const text = rawText\n ? rawText.slice(0, 500).replace(/Bearer\\s+\\S+/gi, \"Bearer [REDACTED]\")\n : \"\";\n switch (response.status) {\n case 401:\n throw new AuthenticationError();\n case 429:\n throw new RateLimitError();\n default:\n throw new ServerError(text || `HTTP ${response.status}`);\n }\n }\n\n if (!response.body) {\n throw new ConnectionError(\"Response body is null\");\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n let currentEvent = \"\";\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n for (const line of lines) {\n if (line.startsWith(\"event: \")) {\n currentEvent = line.slice(7).trim();\n } else if (line.startsWith(\"data: \")) {\n const data = line.slice(6);\n if (data === \"[DONE]\") {\n return;\n }\n yield { event: currentEvent || \"message\", data };\n }\n if (line === \"\") {\n currentEvent = \"\";\n }\n }\n }\n } catch (err) {\n if (err instanceof DOMException && err.name === \"AbortError\") {\n throw new StreamAbortedError();\n }\n throw err;\n } finally {\n reader.releaseLock();\n }\n}\n","import {\n AuthenticationError,\n ConnectionError,\n RateLimitError,\n ServerError,\n} from \"./errors.js\";\nimport { streamJobSSE } from \"./streaming.js\";\nimport type {\n AgentInfo,\n AstralformConfig,\n ChatStreamEvent,\n ChatStreamRequest,\n ConversationAsset,\n ConversationEvent,\n Conversation,\n JobCreateResponse,\n Message,\n ProjectStatus,\n SkillInfo,\n ToolResultRequest,\n} from \"./types.js\";\n\nconst DEFAULT_BASE_URL = \"https://api.astralform.ai\";\n\nfunction validateBaseURL(url: string): string {\n const cleaned = url.replace(/\\/+$/, \"\");\n try {\n const parsed = new URL(cleaned);\n if (parsed.protocol !== \"https:\" && parsed.protocol !== \"http:\") {\n throw new Error(\n `Invalid baseURL protocol \"${parsed.protocol}\" - only http: and https: are allowed`,\n );\n }\n return parsed.origin + parsed.pathname.replace(/\\/+$/, \"\");\n } catch (err) {\n if (err instanceof Error && err.message.includes(\"Invalid baseURL\")) {\n throw err;\n }\n throw new Error(`Invalid baseURL: \"${cleaned}\" is not a valid URL`);\n }\n}\n\nexport class AstralformClient {\n private readonly apiKey: string;\n private readonly baseURL: string;\n private readonly userId: string;\n private readonly fetchFn: typeof globalThis.fetch;\n\n constructor(config: AstralformConfig) {\n if (!config.apiKey || typeof config.apiKey !== \"string\") {\n throw new Error(\"apiKey is required and must be a non-empty string\");\n }\n this.apiKey = config.apiKey;\n this.baseURL = validateBaseURL(config.baseURL ?? DEFAULT_BASE_URL);\n this.userId = config.userId;\n this.fetchFn = config.fetch ?? globalThis.fetch.bind(globalThis);\n }\n\n private get headers(): Record<string, string> {\n return {\n Authorization: `Bearer ${this.apiKey}`,\n \"X-End-User-ID\": this.userId,\n \"Content-Type\": \"application/json\",\n };\n }\n\n private async request(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<Response> {\n const response = await this.fetchFn(`${this.baseURL}${path}`, {\n method,\n headers: this.headers,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n }).catch((err) => {\n throw new ConnectionError(\n err instanceof Error ? err.message : \"Failed to connect\",\n );\n });\n await this.handleError(response);\n return response;\n }\n\n private async get<T>(path: string): Promise<T> {\n const response = await this.request(\"GET\", path);\n return response.json() as Promise<T>;\n }\n\n private async post<T>(path: string, body: unknown): Promise<T> {\n const response = await this.request(\"POST\", path, body);\n return response.json() as Promise<T>;\n }\n\n private async del(path: string): Promise<void> {\n await this.request(\"DELETE\", path);\n }\n\n private async handleError(response: Response): Promise<void> {\n if (response.ok) return;\n const text = await response.text().catch(() => \"\");\n switch (response.status) {\n case 401:\n throw new AuthenticationError();\n case 429:\n throw new RateLimitError();\n default: {\n // Sanitize server error text to avoid leaking sensitive details\n const safeText = text\n ? text.slice(0, 500).replace(/Bearer\\s+\\S+/gi, \"Bearer [REDACTED]\")\n : \"\";\n throw new ServerError(safeText || `HTTP ${response.status}`);\n }\n }\n }\n\n // --- REST Methods ---\n\n async getHealth(): Promise<{\n status: string;\n version: string;\n ollama_connected: boolean;\n }> {\n return this.get(\"/v1/health\");\n }\n\n async getProjectStatus(): Promise<ProjectStatus> {\n const raw = await this.get<{\n is_ready: boolean;\n llm_configured: boolean;\n llm_provider?: string;\n llm_model?: string;\n message: string;\n }>(\"/v1/project/status\");\n return {\n isReady: raw.is_ready,\n llmConfigured: raw.llm_configured,\n llmProvider: raw.llm_provider,\n llmModel: raw.llm_model,\n message: raw.message,\n };\n }\n\n async getConversations(limit = 50, offset = 0): Promise<Conversation[]> {\n const safeLimit = Math.max(1, Math.min(200, Math.floor(Number(limit))));\n const safeOffset = Math.max(0, Math.floor(Number(offset)));\n const raw = await this.get<\n {\n id: string;\n title: string;\n message_count: number;\n created_at: string;\n updated_at: string;\n }[]\n >(`/v1/conversations?limit=${safeLimit}&offset=${safeOffset}`);\n return raw.map((c) => ({\n id: c.id,\n title: c.title,\n messageCount: c.message_count,\n createdAt: c.created_at,\n updatedAt: c.updated_at,\n }));\n }\n\n async getMessages(conversationId: string): Promise<Message[]> {\n const raw = await this.get<\n {\n id: string;\n conversation_id: string;\n role: \"user\" | \"assistant\" | \"system\";\n content: string;\n parent_id?: string;\n created_at: string;\n }[]\n >(`/v1/conversations/${encodeURIComponent(conversationId)}/messages`);\n return raw.map((m) => ({\n id: m.id,\n conversationId: m.conversation_id,\n role: m.role,\n content: m.content,\n parentId: m.parent_id,\n status: \"complete\" as const,\n createdAt: m.created_at,\n }));\n }\n\n async deleteConversation(id: string): Promise<void> {\n await this.del(`/v1/conversations/${encodeURIComponent(id)}`);\n }\n\n async getAgents(): Promise<AgentInfo[]> {\n const raw = await this.get<\n {\n name: string;\n display_name: string;\n description: string;\n is_orchestrator: boolean;\n is_enabled: boolean;\n avatar_url?: string;\n }[]\n >(\"/v1/agents\");\n return raw.map((a) => ({\n name: a.name,\n displayName: a.display_name,\n description: a.description,\n isOrchestrator: a.is_orchestrator,\n isEnabled: a.is_enabled,\n avatarUrl: a.avatar_url,\n }));\n }\n\n async getSkills(): Promise<SkillInfo[]> {\n const raw = await this.get<\n {\n name: string;\n display_name: string;\n description: string;\n is_enabled: boolean;\n }[]\n >(\"/v1/skills\");\n return raw.map((s) => ({\n name: s.name,\n displayName: s.display_name,\n description: s.description,\n isEnabled: s.is_enabled,\n }));\n }\n\n async getConversationEvents(\n conversationId: string,\n ): Promise<ConversationEvent[]> {\n return this.get(\n `/v1/conversations/${encodeURIComponent(conversationId)}/events`,\n );\n }\n\n async submitToolResult(request: ToolResultRequest): Promise<void> {\n await this.post(\"/v1/tool-result\", request);\n }\n\n // --- Conversation Assets ---\n\n private mapAsset(raw: Record<string, unknown>): ConversationAsset {\n return {\n id: raw.id as string,\n kind: raw.kind as \"upload\" | \"output\",\n originalName: raw.original_name as string,\n mediaType: raw.media_type as string,\n sizeBytes: raw.size_bytes as number,\n workspacePath: raw.workspace_path as string | undefined,\n sourceMessageId: raw.source_message_id as string | undefined,\n agentName: raw.agent_name as string | undefined,\n createdAt: raw.created_at as string,\n };\n }\n\n async uploadFile(\n conversationId: string,\n file: Blob,\n filename?: string,\n ): Promise<ConversationAsset> {\n const formData = new FormData();\n formData.append(\"file\", file, filename);\n\n const response = await this.fetchFn(\n `${this.baseURL}/v1/conversations/${encodeURIComponent(conversationId)}/uploads`,\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n \"X-End-User-ID\": this.userId,\n },\n body: formData,\n },\n ).catch((err) => {\n throw new ConnectionError(\n err instanceof Error ? err.message : \"Failed to connect\",\n );\n });\n await this.handleError(response);\n const raw = await response.json();\n return this.mapAsset(raw as Record<string, unknown>);\n }\n\n async listUploads(conversationId: string): Promise<ConversationAsset[]> {\n const raw = await this.get<Record<string, unknown>[]>(\n `/v1/conversations/${encodeURIComponent(conversationId)}/uploads`,\n );\n return raw.map((r) => this.mapAsset(r));\n }\n\n async listOutputs(conversationId: string): Promise<ConversationAsset[]> {\n const raw = await this.get<Record<string, unknown>[]>(\n `/v1/conversations/${encodeURIComponent(conversationId)}/outputs`,\n );\n return raw.map((r) => this.mapAsset(r));\n }\n\n // --- Jobs API ---\n\n async createJob(request: ChatStreamRequest): Promise<JobCreateResponse> {\n return this.post<JobCreateResponse>(\"/v1/jobs\", request);\n }\n\n async *streamJobEvents(\n jobId: string,\n afterSeq = -1,\n signal?: AbortSignal,\n ): AsyncGenerator<ChatStreamEvent> {\n const url = `${this.baseURL}/v1/jobs/${encodeURIComponent(jobId)}/events?after=${afterSeq}`;\n yield* streamJobSSE({\n url,\n headers: this.headers,\n signal,\n fetchFn: this.fetchFn,\n });\n }\n\n async cancelJob(jobId: string): Promise<void> {\n await this.post(`/v1/jobs/${encodeURIComponent(jobId)}/cancel`, {});\n }\n}\n","/**\n * BlockBuilder — pure rendering engine. Zero default behavior.\n *\n * Clients register handlers that map events to blocks.\n * Both live streaming and restore go through the same engine.\n *\n * import { BlockBuilder, standardHandlers } from \"@astralform/js\";\n * const builder = new BlockBuilder();\n * builder.registerHandlers(standardHandlers);\n */\n\nimport type { ChatEvent } from \"./types.js\";\n\n// =============================================================================\n// Block protocol — typed discriminated union\n// =============================================================================\n\nexport interface UserBlock {\n type: \"user\";\n id: string;\n content: string;\n}\n\nexport interface TextBlock {\n type: \"text\";\n id: string;\n content: string;\n isStreaming: boolean;\n}\n\nexport interface ThinkingBlock {\n type: \"thinking\";\n id: string;\n content: string;\n isActive: boolean;\n durationMs?: number;\n}\n\nexport interface AgentBlock {\n type: \"agent\";\n id: string;\n agentName: string;\n displayName?: string;\n avatarUrl?: string;\n}\n\nexport interface SubagentBlock {\n type: \"subagent\";\n id: string;\n agentName: string;\n displayName: string;\n toolCallId: string;\n avatarUrl?: string;\n description?: string;\n content: string;\n isActive: boolean;\n}\n\nexport interface ToolBlock {\n type: \"tool\";\n id: string;\n callId: string;\n toolName: string;\n displayName?: string;\n description?: string;\n arguments?: Record<string, unknown>;\n status: string;\n iconUrl?: string;\n toolCategory?: string;\n sources?: { title: string; url: string; snippet?: string }[];\n durationMs?: number;\n result?: string;\n}\n\nexport interface ErrorBlock {\n type: \"error\";\n id: string;\n message: string;\n}\n\nexport type Block =\n | UserBlock\n | TextBlock\n | ThinkingBlock\n | AgentBlock\n | SubagentBlock\n | ToolBlock\n | ErrorBlock;\n\n// =============================================================================\n// Event handler type\n// =============================================================================\n\nexport type EventHandler = (event: ChatEvent, builder: BlockBuilder) => void;\n\n// =============================================================================\n// BlockBuilder — pure engine\n// =============================================================================\n\nlet _idCounter = 0;\n\nexport class BlockBuilder {\n private _blocks: Block[] = [];\n private _handlers = new Map<string, EventHandler | null>();\n private _onChange: (() => void) | null = null;\n\n // Active block refs — public so handlers can read/write them\n activeTextId: string | null = null;\n activeThinkingId: string | null = null;\n thinkingStartMs: number | null = null;\n\n // ── Registration ──────────────────────────────────────────────\n\n on(eventType: string, handler: EventHandler | null): void {\n this._handlers.set(eventType, handler);\n }\n\n registerHandlers(handlers: Record<string, EventHandler | null>): void {\n for (const [type, handler] of Object.entries(handlers)) {\n this._handlers.set(type, handler);\n }\n }\n\n // ── Event processing ──────────────────────────────────────────\n\n processEvent(event: ChatEvent): void {\n const handler = this._handlers.get(event.type);\n if (handler === null) return;\n if (!handler) return;\n handler(event, this);\n }\n\n // ── State ─────────────────────────────────────────────────────\n\n getBlocks(): Block[] {\n return [...this._blocks];\n }\n\n reset(): void {\n this._blocks = [];\n this.activeTextId = null;\n this.activeThinkingId = null;\n this.thinkingStartMs = null;\n }\n\n setOnChange(fn: (() => void) | null): void {\n this._onChange = fn;\n }\n\n // ── Block manipulation (used by handlers) ─────────────────────\n\n addBlock(block: Block): void {\n this._blocks = [...this._blocks, block];\n this._notify();\n }\n\n updateBlock<T extends Block[\"type\"]>(\n id: string,\n updater: (\n block: Extract<Block, { type: T }>,\n ) => Extract<Block, { type: T }>,\n ): void {\n let changed = false;\n this._blocks = this._blocks.map((b) => {\n if (b.id !== id) return b;\n changed = true;\n return updater(b as Extract<Block, { type: T }>);\n });\n if (changed) this._notify();\n }\n\n /** Update any block by id with a partial update (type-loose for handlers). */\n patchBlock(id: string, patch: Partial<Block>): void {\n let changed = false;\n this._blocks = this._blocks.map((b) => {\n if (b.id !== id) return b;\n changed = true;\n return { ...b, ...patch } as Block;\n });\n if (changed) this._notify();\n }\n\n findBlock(predicate: (b: Block) => boolean): Block | undefined {\n for (let i = this._blocks.length - 1; i >= 0; i--) {\n const block = this._blocks[i];\n if (block && predicate(block)) return block;\n }\n return undefined;\n }\n\n nextId(): string {\n return `blk_${++_idCounter}`;\n }\n\n // ── Internal ──────────────────────────────────────────────────\n\n private _notify(): void {\n this._onChange?.();\n }\n}\n","import type { Conversation, Message } from \"./types.js\";\n\nexport interface ChatStorage {\n fetchConversations(): Promise<Conversation[]>;\n fetchConversation(id: string): Promise<Conversation | null>;\n createConversation(id: string, title: string): Promise<Conversation>;\n updateConversationTitle(id: string, title: string): Promise<void>;\n deleteConversation(id: string): Promise<void>;\n fetchMessages(conversationId: string): Promise<Message[]>;\n addMessage(message: Message, conversationId: string): Promise<void>;\n updateMessageStatus(id: string, status: Message[\"status\"]): Promise<void>;\n deleteMessage(id: string): Promise<void>;\n}\n\nexport class InMemoryStorage implements ChatStorage {\n private conversations = new Map<string, Conversation>();\n private messages = new Map<string, Message[]>();\n\n async fetchConversations(): Promise<Conversation[]> {\n return Array.from(this.conversations.values()).sort(\n (a, b) =>\n new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime(),\n );\n }\n\n async fetchConversation(id: string): Promise<Conversation | null> {\n return this.conversations.get(id) ?? null;\n }\n\n async createConversation(id: string, title: string): Promise<Conversation> {\n const now = new Date().toISOString();\n const conversation: Conversation = {\n id,\n title,\n messageCount: 0,\n createdAt: now,\n updatedAt: now,\n };\n this.conversations.set(id, conversation);\n this.messages.set(id, []);\n return conversation;\n }\n\n async updateConversationTitle(id: string, title: string): Promise<void> {\n const conv = this.conversations.get(id);\n if (conv) {\n conv.title = title;\n conv.updatedAt = new Date().toISOString();\n }\n }\n\n async deleteConversation(id: string): Promise<void> {\n this.conversations.delete(id);\n this.messages.delete(id);\n }\n\n async fetchMessages(conversationId: string): Promise<Message[]> {\n return this.messages.get(conversationId) ?? [];\n }\n\n async addMessage(message: Message, conversationId: string): Promise<void> {\n const msgs = this.messages.get(conversationId) ?? [];\n msgs.push(message);\n this.messages.set(conversationId, msgs);\n\n const conv = this.conversations.get(conversationId);\n if (conv) {\n conv.messageCount = msgs.length;\n conv.updatedAt = new Date().toISOString();\n }\n }\n\n async updateMessageStatus(\n id: string,\n status: Message[\"status\"],\n ): Promise<void> {\n for (const msgs of this.messages.values()) {\n const msg = msgs.find((m) => m.id === id);\n if (msg) {\n msg.status = status;\n return;\n }\n }\n }\n\n async deleteMessage(id: string): Promise<void> {\n for (const [convId, msgs] of this.messages.entries()) {\n const idx = msgs.findIndex((m) => m.id === id);\n if (idx !== -1) {\n msgs.splice(idx, 1);\n const conv = this.conversations.get(convId);\n if (conv) {\n conv.messageCount = msgs.length;\n }\n return;\n }\n }\n }\n}\n","import type { ToolCallRequest, ToolDefinition, ToolResult } from \"./types.js\";\n\nexport type ToolHandler = (args: Record<string, unknown>) => Promise<string>;\n\ninterface RegisteredTool {\n name: string;\n description: string;\n inputSchema: Record<string, unknown>;\n handler: ToolHandler;\n}\n\n/** Validates tool name: alphanumeric, hyphens, underscores, dots only */\nconst TOOL_NAME_PATTERN = /^[a-zA-Z0-9_.\\-]+$/;\n\n/** Strips prototype-polluting keys from an object */\nfunction sanitizeArgs(args: Record<string, unknown>): Record<string, unknown> {\n const clean: Record<string, unknown> = Object.create(null);\n for (const key of Object.keys(args)) {\n if (key === \"__proto__\" || key === \"constructor\" || key === \"prototype\") {\n continue;\n }\n clean[key] = args[key];\n }\n return clean;\n}\n\nexport class ToolRegistry {\n private tools = new Map<string, RegisteredTool>();\n\n registerTool(\n name: string,\n description: string,\n inputSchema: Record<string, unknown>,\n handler: ToolHandler,\n ): void {\n if (!name || !TOOL_NAME_PATTERN.test(name)) {\n throw new Error(\n `Invalid tool name \"${name}\" - must match ${TOOL_NAME_PATTERN}`,\n );\n }\n if (name.length > 256) {\n throw new Error(\"Tool name must be 256 characters or fewer\");\n }\n this.tools.set(name, { name, description, inputSchema, handler });\n }\n\n unregisterTool(name: string): boolean {\n return this.tools.delete(name);\n }\n\n hasTool(name: string): boolean {\n return this.tools.has(name);\n }\n\n async executeTool(request: ToolCallRequest): Promise<ToolResult> {\n const tool = this.tools.get(request.toolName);\n if (!tool) {\n return {\n call_id: request.callId,\n tool_name: request.toolName,\n result: `Tool \"${request.toolName}\" not found`,\n is_error: true,\n };\n }\n\n try {\n const result = await tool.handler(sanitizeArgs(request.arguments));\n return {\n call_id: request.callId,\n tool_name: request.toolName,\n result,\n is_error: false,\n };\n } catch (err) {\n return {\n call_id: request.callId,\n tool_name: request.toolName,\n result: err instanceof Error ? err.message : String(err),\n is_error: true,\n };\n }\n }\n\n getManifest(): ToolDefinition[] {\n return Array.from(this.tools.values()).map((t) => ({\n name: t.name,\n description: t.description,\n parameters: t.inputSchema,\n }));\n }\n\n getToolNames(): string[] {\n return Array.from(this.tools.keys());\n }\n\n clear(): void {\n this.tools.clear();\n }\n}\n","export function generateId(): string {\n if (typeof crypto !== \"undefined\" && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n // Fallback for environments without crypto.randomUUID\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === \"x\" ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n","import { BlockBuilder } from \"./block-builder.js\";\nimport { AstralformClient } from \"./client.js\";\nimport { AstralformError, ConnectionError } from \"./errors.js\";\nimport { InMemoryStorage, type ChatStorage } from \"./storage.js\";\nimport { ToolRegistry } from \"./tools.js\";\nimport type {\n AgentInfo,\n AstralformConfig,\n CapsuleOutput,\n ChatEvent,\n ChatStreamRequest,\n Conversation,\n Message,\n ProjectStatus,\n SendOptions,\n SkillInfo,\n Source,\n SSEEvent,\n SubagentState,\n TodoItem,\n ToolCallRequest,\n ToolResult,\n ToolState,\n} from \"./types.js\";\nimport { generateId } from \"./utils.js\";\n\ntype ChatEventHandler = (event: ChatEvent) => void;\n\nexport class ChatSession {\n readonly client: AstralformClient;\n readonly toolRegistry: ToolRegistry;\n readonly storage: ChatStorage;\n readonly blockBuilder: BlockBuilder;\n\n // State\n conversationId: string | null = null;\n conversations: Conversation[] = [];\n messages: Message[] = [];\n streamingContent = \"\";\n isStreaming = false;\n executingTool: string | null = null;\n projectStatus: ProjectStatus | null = null;\n agents: AgentInfo[] = [];\n skills: SkillInfo[] = [];\n enabledClientTools = new Set<string>();\n modelDisplayName: string | null = null;\n\n // New state fields\n thinkingContent = \"\";\n isThinking = false;\n activeSubagents = new Map<string, SubagentState>();\n sources: Source[] = [];\n capsuleOutputs: CapsuleOutput[] = [];\n todos: TodoItem[] = [];\n activeTools = new Map<string, ToolState>();\n\n private handlers: Set<ChatEventHandler> = new Set();\n private abortController: AbortController | null = null;\n\n constructor(\n config: AstralformConfig,\n storage?: ChatStorage,\n blockBuilder?: BlockBuilder,\n ) {\n this.client = new AstralformClient(config);\n this.toolRegistry = new ToolRegistry();\n this.storage = storage ?? new InMemoryStorage();\n this.blockBuilder = blockBuilder ?? new BlockBuilder();\n\n // Wire block builder to emit blocks_changed events\n this.blockBuilder.setOnChange(() => {\n this.emit({\n type: \"blocks_changed\",\n blocks: this.blockBuilder.getBlocks(),\n });\n });\n }\n\n on(handler: ChatEventHandler): () => void {\n this.handlers.add(handler);\n return () => {\n this.handlers.delete(handler);\n };\n }\n\n private emit(event: ChatEvent): void {\n // Feed the block builder first (produces blocks_changed events)\n if (event.type !== \"blocks_changed\" && event.type !== \"connected\") {\n this.blockBuilder.processEvent(event);\n }\n\n for (const handler of this.handlers) {\n try {\n handler(event);\n } catch {\n // Don't let handler errors crash the session\n }\n }\n }\n\n async connect(): Promise<void> {\n const [status, conversations, agents, skills] = await Promise.allSettled([\n this.client.getProjectStatus(),\n this.client.getConversations(),\n this.client.getAgents().catch(() => [] as AgentInfo[]),\n this.client.getSkills().catch(() => [] as SkillInfo[]),\n ]);\n\n if (status.status === \"fulfilled\") {\n this.projectStatus = status.value;\n }\n if (conversations.status === \"fulfilled\") {\n this.conversations = conversations.value;\n }\n if (agents.status === \"fulfilled\") {\n this.agents = agents.value;\n }\n if (skills.status === \"fulfilled\") {\n this.skills = skills.value;\n }\n\n this.emit({ type: \"connected\" });\n }\n\n async send(content: string, options?: SendOptions): Promise<void> {\n if (this.isStreaming) return;\n\n const conversationId =\n options?.conversationId ?? this.conversationId ?? undefined;\n\n // Create user message\n const userMessage: Message = {\n id: generateId(),\n conversationId: conversationId ?? \"\",\n role: \"user\",\n content,\n status: \"complete\",\n createdAt: new Date().toISOString(),\n };\n\n if (conversationId) {\n await this.storage.addMessage(userMessage, conversationId);\n }\n this.messages.push(userMessage);\n\n // Build request\n const request: ChatStreamRequest = {\n message: content,\n conversation_id: conversationId,\n mcp_manifest: this.toolRegistry.getManifest(),\n enabled_mcp: Array.from(\n options?.enabledClientTools ?? this.enabledClientTools,\n ),\n upload_ids: options?.uploadIds,\n agent_name: options?.agentName,\n enable_search: options?.enableSearch,\n };\n\n await this.processStream(request);\n }\n\n async resendFromCheckpoint(\n messageId: string,\n newContent: string,\n options?: { enableSearch?: boolean },\n ): Promise<void> {\n if (this.isStreaming) return;\n\n const request: ChatStreamRequest = {\n message: newContent,\n conversation_id: this.conversationId ?? undefined,\n resend_from: messageId,\n mcp_manifest: this.toolRegistry.getManifest(),\n enabled_mcp: Array.from(this.enabledClientTools),\n enable_search: options?.enableSearch,\n };\n\n await this.processStream(request);\n }\n\n private resetStreamingState(): void {\n this.streamingContent = \"\";\n this.thinkingContent = \"\";\n this.isThinking = false;\n this.activeSubagents.clear();\n this.sources = [];\n this.capsuleOutputs = [];\n this.todos = [];\n this.activeTools.clear();\n }\n\n private async processStream(request: ChatStreamRequest): Promise<void> {\n this.isStreaming = true;\n this.resetStreamingState();\n // Don't reset blockBuilder here — the client controls when to reset\n // (e.g. addUserBlock resets before adding the user block)\n this.abortController = new AbortController();\n\n try {\n await this.consumeJobStream(request);\n } catch (err) {\n this.emit({\n type: \"error\",\n error: err instanceof Error ? err : new ConnectionError(String(err)),\n });\n } finally {\n this.isStreaming = false;\n this.executingTool = null;\n this.abortController = null;\n }\n }\n\n /** Last received sequence number for resumable reconnection */\n private lastSeq = -1;\n\n /** Current job ID for cancellation */\n private currentJobId: string | null = null;\n\n private async consumeJobStream(request: ChatStreamRequest): Promise<void> {\n const job = await this.client.createJob(request);\n this.currentJobId = job.job_id;\n\n let conversationId = job.conversation_id;\n if (!this.conversationId) {\n this.conversationId = conversationId;\n }\n\n const messageId = job.message_id;\n this.lastSeq = -1;\n\n const stream = this.client.streamJobEvents(\n job.job_id,\n this.lastSeq,\n this.abortController?.signal,\n );\n\n // completeStream is called inside consumeEventStream when message_stop arrives\n // — no second call needed here\n await this.consumeEventStream(\n stream,\n conversationId,\n messageId,\n true, // executeClientTools\n );\n }\n\n /**\n * Shared event consumption loop used by both consumeJobStream and reconnectToJob.\n */\n private async consumeEventStream(\n stream: AsyncGenerator<{ data: string }>,\n conversationId: string,\n messageId: string,\n executeClientTools: boolean,\n ): Promise<void> {\n for await (const raw of stream) {\n let parsed: SSEEvent;\n try {\n const data = JSON.parse(raw.data);\n if (\n typeof data !== \"object\" ||\n data === null ||\n typeof data.type !== \"string\"\n ) {\n if (typeof data?.seq === \"number\") {\n this.lastSeq = data.seq;\n }\n continue;\n }\n parsed = data as SSEEvent;\n if (typeof (data as Record<string, unknown>).seq === \"number\") {\n this.lastSeq = (data as Record<string, unknown>).seq as number;\n }\n } catch {\n continue;\n }\n\n switch (parsed.type) {\n case \"message_start\":\n conversationId = parsed.conversation_id;\n if (!this.conversationId) {\n this.conversationId = conversationId;\n }\n if (parsed.message_id) {\n messageId = parsed.message_id;\n }\n if (parsed.model_display_name) {\n this.modelDisplayName = parsed.model_display_name;\n this.emit({\n type: \"model_info\",\n name: parsed.model_display_name,\n });\n }\n break;\n\n case \"content_block_delta\":\n this.streamingContent += parsed.delta.text;\n this.emit({ type: \"chunk\", text: parsed.delta.text });\n break;\n\n case \"tool_use_start\": {\n this.applyEvent(parsed);\n if (executeClientTools && parsed.is_client_tool) {\n const results = await this.executeClientTools([\n {\n callId: parsed.call_id,\n toolName: parsed.tool,\n displayName: parsed.display_name,\n description: parsed.description,\n arguments: parsed.arguments,\n isClientTool: parsed.is_client_tool,\n toolCategory: parsed.tool_category,\n iconUrl: parsed.icon_url,\n },\n ]);\n await this.client.submitToolResult({\n conversation_id: conversationId,\n message_id: messageId,\n tool_results: results,\n });\n }\n break;\n }\n\n case \"subagent_content_delta\": {\n const subagent = this.activeSubagents.get(parsed.tool_call_id);\n if (subagent) {\n subagent.content += parsed.delta.text;\n }\n this.emit({\n type: \"subagent_chunk\",\n agentName: parsed.agent_name,\n toolCallId: parsed.tool_call_id,\n text: parsed.delta.text,\n });\n break;\n }\n\n case \"thinking_delta\":\n this.thinkingContent += parsed.delta.text;\n this.isThinking = true;\n this.emit({ type: \"thinking_delta\", text: parsed.delta.text });\n break;\n\n case \"thinking_complete\":\n this.isThinking = false;\n this.emit({ type: \"thinking_complete\" });\n break;\n\n case \"retry\":\n this.emit({\n type: \"retry\",\n attempt: parsed.attempt,\n maxAttempts: parsed.max_attempts,\n delaySeconds: parsed.delay_seconds,\n });\n break;\n\n case \"message_stop\":\n // Emit complete IMMEDIATELY — don't wait for stream close\n // Post-processing continues in background but user is unlocked\n await this.completeStream(\n conversationId,\n messageId,\n parsed.title,\n parsed.metrics,\n parsed.job_id,\n );\n this.isStreaming = false;\n this.currentJobId = null;\n break;\n\n case \"error\":\n this.emit({\n type: \"error\",\n error: new AstralformError(parsed.message, parsed.code),\n });\n break;\n\n default:\n this.applyEvent(parsed);\n }\n }\n }\n\n /**\n * Apply a single SSE event to session state and notify consumers.\n * Shared between live streaming and historical event replay.\n */\n private applyEvent(event: SSEEvent): void {\n switch (event.type) {\n case \"user_message\":\n this.emit({ type: \"user_message\", content: event.content });\n break;\n\n case \"title_generated\":\n this.emit({ type: \"title_generated\", title: event.title });\n break;\n\n case \"message_start\":\n if (event.conversation_id && !this.conversationId) {\n this.conversationId = event.conversation_id;\n }\n if (event.model_display_name) {\n this.modelDisplayName = event.model_display_name;\n this.emit({ type: \"model_info\", name: event.model_display_name });\n }\n break;\n\n case \"content_block_delta\":\n this.streamingContent += event.delta.text;\n this.emit({ type: \"chunk\", text: event.delta.text });\n break;\n\n case \"thinking_delta\":\n this.thinkingContent += event.delta.text;\n this.isThinking = true;\n this.emit({ type: \"thinking_delta\", text: event.delta.text });\n break;\n\n case \"thinking_complete\":\n this.isThinking = false;\n this.emit({ type: \"thinking_complete\" });\n break;\n\n case \"message_stop\":\n this.emit({\n type: \"complete\",\n content: this.streamingContent,\n conversationId: this.conversationId ?? \"\",\n messageId: event.job_id ?? \"\",\n title: event.title,\n metrics: event.metrics,\n job_id: event.job_id,\n });\n break;\n\n case \"tool_use_start\": {\n const request: ToolCallRequest = {\n callId: event.call_id,\n toolName: event.tool,\n displayName: event.display_name,\n description: event.description,\n arguments: event.arguments,\n isClientTool: event.is_client_tool,\n toolCategory: event.tool_category,\n iconUrl: event.icon_url,\n };\n this.activeTools.set(event.call_id, {\n ...request,\n status: event.is_client_tool ? \"calling\" : \"executing\",\n });\n this.emit({ type: \"tool_call\", request });\n break;\n }\n\n case \"tool_use_end\": {\n const toolState = this.activeTools.get(event.call_id);\n if (toolState) {\n toolState.status = \"completed\";\n }\n this.emit({\n type: \"tool_end\",\n callId: event.call_id,\n toolName: event.tool,\n result: event.result,\n sources: event.sources,\n durationMs: event.duration_ms,\n });\n break;\n }\n\n case \"agent_start\":\n this.emit({\n type: \"agent_start\",\n agentName: event.agent_name,\n agentDisplayName: event.agent_display_name,\n avatarUrl: event.avatar_url,\n });\n break;\n\n case \"agent_end\":\n this.emit({ type: \"agent_end\", agentName: event.agent_name });\n break;\n\n case \"subagent_start\":\n this.activeSubagents.set(event.tool_call_id, {\n agentName: event.agent_name,\n displayName: event.display_name,\n avatarUrl: event.avatar_url,\n description: event.description,\n content: \"\",\n isActive: true,\n });\n this.emit({\n type: \"subagent_start\",\n agentName: event.agent_name,\n displayName: event.display_name,\n toolCallId: event.tool_call_id,\n avatarUrl: event.avatar_url,\n description: event.description,\n });\n break;\n\n case \"subagent_update\": {\n const sub = this.activeSubagents.get(event.tool_call_id);\n if (sub) {\n sub.agentName = event.agent_name;\n sub.displayName = event.display_name;\n }\n this.emit({\n type: \"subagent_update\",\n agentName: event.agent_name,\n displayName: event.display_name,\n toolCallId: event.tool_call_id,\n });\n break;\n }\n\n case \"subagent_end\": {\n const sub = this.activeSubagents.get(event.tool_call_id);\n if (sub) {\n sub.isActive = false;\n }\n this.emit({\n type: \"subagent_end\",\n agentName: event.agent_name,\n displayName: event.display_name,\n toolCallId: event.tool_call_id,\n });\n break;\n }\n\n case \"subagent_tool_use\":\n this.emit({\n type: \"subagent_tool_use\",\n agentName: event.agent_name,\n toolName: event.tool,\n toolCallId: event.tool_call_id,\n result: event.result,\n });\n break;\n\n case \"sources\":\n this.sources.push(...event.sources);\n this.emit({ type: \"sources\", sources: event.sources });\n break;\n\n case \"capsule_output\": {\n const capsule: CapsuleOutput = {\n toolName: event.tool_name,\n agentName: event.agent_name,\n command: event.command,\n output: event.output,\n durationMs: event.duration_ms,\n callId: event.call_id,\n };\n this.capsuleOutputs.push(capsule);\n this.emit({ type: \"capsule_output\", ...capsule });\n break;\n }\n\n case \"capsule_output_chunk\":\n this.emit({\n type: \"capsule_output_chunk\",\n callId: event.call_id,\n stream: event.stream,\n chunk: event.chunk,\n });\n break;\n\n case \"todo_update\":\n this.todos = event.todos;\n this.emit({ type: \"todo_update\", todos: event.todos });\n break;\n\n case \"asset_created\":\n this.emit({\n type: \"asset_created\",\n assetId: event.asset_id,\n name: event.name,\n url: event.url,\n mediaType: event.media_type,\n sizeBytes: event.size_bytes,\n });\n break;\n\n case \"timeline_entry\":\n this.emit({\n type: \"timeline_entry\",\n id: event.id,\n status: event.status,\n kind: event.kind,\n agent_name: event.agent_name,\n tool_name: event.tool_name,\n display_name: event.display_name,\n tool_category: event.tool_category,\n viewer: event.viewer,\n call_id: event.call_id,\n detail: event.detail,\n started_at: event.started_at,\n duration_ms: event.duration_ms,\n output_summary: event.output_summary,\n sources: event.sources,\n parent_id: event.parent_id,\n structured_output: event.structured_output,\n });\n break;\n\n case \"editor_content_start\":\n this.emit({\n type: \"editor_content_start\",\n callId: event.call_id,\n path: event.path,\n language: event.language,\n });\n break;\n\n case \"editor_content_delta\":\n this.emit({\n type: \"editor_content_delta\",\n callId: event.call_id,\n path: event.path,\n delta: event.delta,\n });\n break;\n\n case \"editor_content_end\":\n this.emit({\n type: \"editor_content_end\",\n callId: event.call_id,\n });\n break;\n }\n }\n\n private async executeClientTools(\n toolCalls: ToolCallRequest[],\n ): Promise<ToolResult[]> {\n const results: ToolResult[] = [];\n for (const call of toolCalls) {\n this.executingTool = call.toolName;\n const toolState = this.activeTools.get(call.callId);\n if (toolState) {\n toolState.status = \"executing\";\n }\n this.emit({ type: \"tool_executing\", name: call.toolName });\n const result = await this.toolRegistry.executeTool(call);\n results.push(result);\n if (toolState) {\n toolState.status = \"completed\";\n }\n this.emit({\n type: \"tool_completed\",\n name: call.toolName,\n result: result.result,\n });\n }\n this.executingTool = null;\n return results;\n }\n\n private async completeStream(\n conversationId: string,\n messageId: string,\n title?: string,\n metrics?: Record<string, unknown>,\n jobId?: string,\n ): Promise<void> {\n // Store assistant message\n const assistantMessage: Message = {\n id: messageId || generateId(),\n conversationId,\n role: \"assistant\",\n content: this.streamingContent,\n status: \"complete\",\n createdAt: new Date().toISOString(),\n };\n this.messages.push(assistantMessage);\n await this.storage.addMessage(assistantMessage, conversationId);\n\n // Update conversation title if provided\n if (title && conversationId) {\n await this.storage.updateConversationTitle(conversationId, title);\n const conv = this.conversations.find((c) => c.id === conversationId);\n if (conv) {\n conv.title = title;\n }\n }\n\n this.emit({\n type: \"complete\",\n content: this.streamingContent,\n conversationId,\n messageId: assistantMessage.id,\n title,\n metrics,\n job_id: jobId,\n });\n }\n\n /**\n * Load conversation context (messages) without replaying events.\n * Used before reconnectToJob — SSE replay handles event replay.\n */\n async loadConversation(id: string): Promise<void> {\n this.conversationId = id;\n this.resetStreamingState();\n this.blockBuilder.reset();\n this.messages = await this.client\n .getMessages(id)\n .catch(() => this.storage.fetchMessages(id));\n }\n\n /**\n * Reconnect to a running job's SSE stream (e.g. after page reload).\n * Replays all events from the beginning and continues live.\n * Does NOT reset BlockBuilder — caller controls reset.\n */\n async reconnectToJob(jobId: string): Promise<void> {\n if (this.isStreaming) return;\n\n this.isStreaming = true;\n this.currentJobId = jobId;\n this.lastSeq = -1;\n this.resetStreamingState();\n this.abortController = new AbortController();\n\n try {\n const stream = this.client.streamJobEvents(\n jobId,\n this.lastSeq,\n this.abortController?.signal,\n );\n\n // completeStream is called inside consumeEventStream on message_stop\n await this.consumeEventStream(\n stream,\n this.conversationId ?? \"\",\n \"\",\n false, // don't execute client tools on reconnect\n );\n } catch (err) {\n this.emit({\n type: \"error\",\n error: err instanceof Error ? err : new ConnectionError(String(err)),\n });\n } finally {\n this.isStreaming = false;\n this.executingTool = null;\n this.abortController = null;\n }\n }\n\n disconnect(): void {\n // Cancel the running job if any\n if (this.currentJobId) {\n this.client.cancelJob(this.currentJobId).catch(() => {});\n this.currentJobId = null;\n }\n this.abortController?.abort();\n this.abortController = null;\n this.isStreaming = false;\n this.streamingContent = \"\";\n this.executingTool = null;\n this.emit({ type: \"disconnected\" });\n }\n\n async createNewConversation(): Promise<string> {\n const id = generateId();\n const conversation = await this.storage.createConversation(\n id,\n \"New Conversation\",\n );\n this.conversations.unshift(conversation);\n this.conversationId = id;\n this.messages = [];\n this.streamingContent = \"\";\n return id;\n }\n\n async switchConversation(id: string): Promise<void> {\n this.conversationId = id;\n this.resetStreamingState();\n this.blockBuilder.reset();\n\n const [messagesResult, eventsResult] = await Promise.allSettled([\n this.client.getMessages(id).catch(() => this.storage.fetchMessages(id)),\n this.client.getConversationEvents(id),\n ]);\n\n this.messages =\n messagesResult.status === \"fulfilled\" ? messagesResult.value : [];\n\n // Replay ALL stored events through the same handlers as live streaming\n if (eventsResult.status === \"fulfilled\") {\n for (const ev of eventsResult.value) {\n this.applyEvent({ type: ev.event, ...ev.data } as SSEEvent);\n }\n }\n }\n\n async deleteConversation(id: string): Promise<void> {\n try {\n await this.client.deleteConversation(id);\n } catch {\n // May already be deleted on backend\n }\n await this.storage.deleteConversation(id);\n this.conversations = this.conversations.filter((c) => c.id !== id);\n if (this.conversationId === id) {\n this.conversationId = null;\n this.messages = [];\n }\n }\n\n toggleClientTool(name: string): boolean {\n if (this.enabledClientTools.has(name)) {\n this.enabledClientTools.delete(name);\n return false;\n }\n this.enabledClientTools.add(name);\n return true;\n }\n}\n","/**\n * Standard event handlers for BlockBuilder.\n *\n * These define the default event→block mapping rules. Clients import\n * and register them explicitly:\n *\n * import { BlockBuilder, standardHandlers } from \"@astralform/js\";\n * const builder = new BlockBuilder();\n * builder.registerHandlers(standardHandlers);\n */\n\nimport type { BlockBuilder, EventHandler } from \"./block-builder.js\";\nimport type { ChatEvent } from \"./types.js\";\n\n// ── Helpers ─────────────────────────────────────────────────────────\n\nfunction finalizeText(builder: BlockBuilder): void {\n if (builder.activeTextId) {\n builder.patchBlock(builder.activeTextId, {\n isStreaming: false,\n } as Partial<import(\"./block-builder.js\").TextBlock>);\n builder.activeTextId = null;\n }\n}\n\nfunction finalizeThinking(builder: BlockBuilder): void {\n if (builder.activeThinkingId) {\n builder.patchBlock(builder.activeThinkingId, {\n isActive: false,\n } as Partial<import(\"./block-builder.js\").ThinkingBlock>);\n builder.activeThinkingId = null;\n builder.thinkingStartMs = null;\n }\n}\n\n// ── Text streaming ──────────────────────────────────────────────────\n\n// ── User message ────────────────────────────────────────────────────\n\nconst handleUserMessage: EventHandler = (event, builder) => {\n // Skip if user block already exists (optimistic add from frontend)\n if (builder.findBlock((b) => b.type === \"user\")) return;\n const e = event as ChatEvent & { type: \"user_message\" };\n builder.addBlock({ type: \"user\", id: builder.nextId(), content: e.content });\n};\n\n// ── Text streaming ──────────────────────────────────────────────────\n\nconst handleChunk: EventHandler = (event, builder) => {\n const e = event as ChatEvent & { type: \"chunk\" };\n if (!builder.activeTextId) {\n const id = builder.nextId();\n builder.activeTextId = id;\n builder.addBlock({\n type: \"text\",\n id,\n content: e.text,\n isStreaming: true,\n });\n } else {\n const id = builder.activeTextId;\n const existing = builder.findBlock((b) => b.id === id);\n if (existing && existing.type === \"text\") {\n builder.patchBlock(id, {\n content: existing.content + e.text,\n } as Partial<import(\"./block-builder.js\").TextBlock>);\n }\n }\n};\n\n// ── Tool calls ──────────────────────────────────────────────────────\n\nconst handleToolCall: EventHandler = (event, builder) => {\n const e = event as ChatEvent & { type: \"tool_call\" };\n finalizeText(builder);\n builder.addBlock({\n type: \"tool\",\n id: builder.nextId(),\n callId: e.request.callId,\n toolName: e.request.toolName,\n displayName: e.request.displayName,\n description: e.request.description,\n arguments: e.request.arguments,\n toolCategory: e.request.toolCategory,\n iconUrl: e.request.iconUrl,\n status: \"calling\",\n });\n};\n\nconst handleToolExecuting: EventHandler = (event, builder) => {\n const e = event as ChatEvent & { type: \"tool_executing\" };\n const block = builder.findBlock(\n (b) => b.type === \"tool\" && b.toolName === e.name && b.status === \"calling\",\n );\n if (block) {\n builder.patchBlock(block.id, { status: \"executing\" } as Partial<\n import(\"./block-builder.js\").ToolBlock\n >);\n }\n};\n\nconst handleToolEnd: EventHandler = (event, builder) => {\n const e = event as ChatEvent & { type: \"tool_completed\" | \"tool_end\" };\n const callId =\n e.type === \"tool_end\"\n ? (e as ChatEvent & { type: \"tool_end\" }).callId\n : undefined;\n const name =\n e.type === \"tool_end\"\n ? (e as ChatEvent & { type: \"tool_end\" }).toolName\n : (e as ChatEvent & { type: \"tool_completed\" }).name;\n\n const block = builder.findBlock(\n (b) =>\n b.type === \"tool\" &&\n (callId ? b.callId === callId : b.toolName === name) &&\n b.status !== \"completed\",\n );\n if (block) {\n const toolEnd =\n e.type === \"tool_end\" ? (e as ChatEvent & { type: \"tool_end\" }) : null;\n builder.patchBlock(block.id, {\n status: \"completed\",\n ...(toolEnd?.sources ? { sources: toolEnd.sources } : {}),\n ...(toolEnd?.durationMs != null\n ? { durationMs: toolEnd.durationMs }\n : {}),\n ...(toolEnd?.result ? { result: toolEnd.result } : {}),\n } as Partial<import(\"./block-builder.js\").ToolBlock>);\n }\n};\n\n// ── Agent lifecycle ─────────────────────────────────────────────────\n\nconst handleAgentStart: EventHandler = (event, builder) => {\n const e = event as ChatEvent & { type: \"agent_start\" };\n finalizeText(builder);\n builder.addBlock({\n type: \"agent\",\n id: builder.nextId(),\n agentName: e.agentName,\n displayName: e.agentDisplayName,\n avatarUrl: e.avatarUrl,\n });\n};\n\n// ── Thinking ────────────────────────────────────────────────────────\n\nconst handleThinkingDelta: EventHandler = (event, builder) => {\n const e = event as ChatEvent & { type: \"thinking_delta\" };\n if (!builder.activeThinkingId) {\n const id = builder.nextId();\n builder.activeThinkingId = id;\n builder.thinkingStartMs = Date.now();\n builder.addBlock({\n type: \"thinking\",\n id,\n content: e.text,\n isActive: true,\n });\n } else {\n const id = builder.activeThinkingId;\n const existing = builder.findBlock((b) => b.id === id);\n if (existing && existing.type === \"thinking\") {\n builder.patchBlock(id, {\n content: existing.content + e.text,\n } as Partial<import(\"./block-builder.js\").ThinkingBlock>);\n }\n }\n};\n\nconst handleThinkingComplete: EventHandler = (_event, builder) => {\n if (builder.activeThinkingId) {\n const durationMs = builder.thinkingStartMs\n ? Math.max(0, Date.now() - builder.thinkingStartMs)\n : undefined;\n builder.patchBlock(builder.activeThinkingId, {\n isActive: false,\n durationMs,\n } as Partial<import(\"./block-builder.js\").ThinkingBlock>);\n builder.activeThinkingId = null;\n builder.thinkingStartMs = null;\n }\n};\n\n// ── Subagents ───────────────────────────────────────────────────────\n\nconst handleSubagentStart: EventHandler = (event, builder) => {\n const e = event as ChatEvent & { type: \"subagent_start\" };\n finalizeText(builder);\n builder.addBlock({\n type: \"subagent\",\n id: builder.nextId(),\n agentName: e.agentName,\n displayName: e.displayName,\n toolCallId: e.toolCallId,\n avatarUrl: e.avatarUrl,\n description: e.description,\n content: \"\",\n isActive: true,\n });\n};\n\nconst handleSubagentChunk: EventHandler = (event, builder) => {\n const e = event as ChatEvent & { type: \"subagent_chunk\" };\n const block = builder.findBlock(\n (b) => b.type === \"subagent\" && b.toolCallId === e.toolCallId,\n );\n if (block && block.type === \"subagent\") {\n builder.patchBlock(block.id, {\n content: block.content + e.text,\n } as Partial<import(\"./block-builder.js\").SubagentBlock>);\n }\n};\n\nconst handleSubagentUpdate: EventHandler = (event, builder) => {\n const e = event as ChatEvent & { type: \"subagent_update\" };\n const block = builder.findBlock(\n (b) => b.type === \"subagent\" && b.toolCallId === e.toolCallId,\n );\n if (block) {\n builder.patchBlock(block.id, {\n displayName: e.displayName,\n } as Partial<import(\"./block-builder.js\").SubagentBlock>);\n }\n};\n\nconst handleSubagentEnd: EventHandler = (event, builder) => {\n const e = event as ChatEvent & { type: \"subagent_end\" };\n const block = builder.findBlock(\n (b) => b.type === \"subagent\" && b.toolCallId === e.toolCallId,\n );\n if (block) {\n builder.patchBlock(block.id, {\n isActive: false,\n } as Partial<import(\"./block-builder.js\").SubagentBlock>);\n }\n};\n\n// ── Completion / Error / Disconnect ─────────────────────────────────\n\nconst handleComplete: EventHandler = (_event, builder) => {\n finalizeText(builder);\n finalizeThinking(builder);\n for (const b of builder.getBlocks()) {\n if (b.type === \"tool\" && b.status !== \"completed\") {\n builder.patchBlock(b.id, { status: \"completed\" } as Partial<\n import(\"./block-builder.js\").ToolBlock\n >);\n }\n }\n};\n\nconst handleError: EventHandler = (event, builder) => {\n const e = event as ChatEvent & { type: \"error\" };\n finalizeText(builder);\n finalizeThinking(builder);\n builder.addBlock({\n type: \"error\",\n id: builder.nextId(),\n message: e.error.message,\n });\n};\n\nconst handleDisconnected: EventHandler = (_event, builder) => {\n finalizeText(builder);\n finalizeThinking(builder);\n};\n\n// ── Exported handler map ────────────────────────────────────────────\n\nexport const standardHandlers: Record<string, EventHandler> = {\n user_message: handleUserMessage,\n chunk: handleChunk,\n tool_call: handleToolCall,\n tool_executing: handleToolExecuting,\n tool_completed: handleToolEnd,\n tool_end: handleToolEnd,\n agent_start: handleAgentStart,\n thinking_delta: handleThinkingDelta,\n thinking_complete: handleThinkingComplete,\n subagent_start: handleSubagentStart,\n subagent_chunk: handleSubagentChunk,\n subagent_update: handleSubagentUpdate,\n subagent_end: handleSubagentEnd,\n complete: handleComplete,\n error: handleError,\n disconnected: handleDisconnected,\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/streaming.ts","../src/client.ts","../src/block-builder.ts","../src/storage.ts","../src/tools.ts","../src/utils.ts","../src/session.ts","../src/standard-handlers.ts","../src/types.ts","../src/stream-manager.ts"],"sourcesContent":["// Core classes\nexport { AstralformClient } from \"./client.js\";\nexport { ChatSession } from \"./session.js\";\nexport {\n BlockBuilder,\n type Block,\n type UserBlock,\n type TextBlock,\n type ThinkingBlock,\n type AgentBlock,\n type SubagentBlock,\n type ToolBlock,\n type CapsuleBlock,\n type AssetBlock,\n type TodoBlock,\n type EditorBlock,\n type ErrorBlock,\n type EventHandler,\n} from \"./block-builder.js\";\nexport { standardHandlers } from \"./standard-handlers.js\";\nexport { ToolRegistry, type ToolHandler } from \"./tools.js\";\nexport { InMemoryStorage, type ChatStorage } from \"./storage.js\";\n\n// Errors\nexport {\n AstralformError,\n AuthenticationError,\n RateLimitError,\n LLMNotConfiguredError,\n ServerError,\n ConnectionError,\n StreamAbortedError,\n} from \"./errors.js\";\n\n// Utilities\nexport { generateId } from \"./utils.js\";\n\n// Streaming\nexport { streamJobSSE } from \"./streaming.js\";\n\n// Stream manager\nexport { StreamManager } from \"./stream-manager.js\";\nexport type {\n StreamState,\n SendOptions,\n StreamManagerEvent,\n} from \"./stream-manager.js\";\n\n// Constants\nexport { ChatEventType } from \"./types.js\";\n\n// Types\nexport type {\n AstralformConfig,\n MessageStartEvent,\n ContentBlockDeltaEvent,\n ToolUseStartEvent,\n ToolUseEndEvent,\n ToolExecutingEvent,\n ToolProgressEvent,\n AgentStartEvent,\n AgentEndEvent,\n SubagentStartEvent,\n SubagentContentDeltaEvent,\n SubagentEndEvent,\n SubagentToolUseEvent,\n ThinkingDeltaEvent,\n ThinkingCompleteEvent,\n CapsuleOutputEvent,\n CapsuleOutputChunkEvent,\n TodoUpdateEvent,\n MessageStopEvent,\n RetryEvent,\n SSEErrorEvent,\n SSEEvent,\n ChatEvent,\n Conversation,\n Message,\n ProjectStatus,\n AgentInfo,\n SkillInfo,\n SubagentState,\n ToolState,\n CapsuleOutput,\n Source,\n TodoItem,\n ChatStreamRequest,\n ToolResultRequest,\n ToolResult,\n ToolDefinition,\n ToolCallRequest,\n ConversationAsset,\n StreamJobSSEOptions,\n JobCreateResponse,\n ChatStreamEvent,\n ConversationEvent,\n} from \"./types.js\";\n","export class AstralformError extends Error {\n constructor(\n message: string,\n public code: string,\n ) {\n super(message);\n this.name = \"AstralformError\";\n }\n}\n\nexport class AuthenticationError extends AstralformError {\n constructor(message = \"Invalid or missing API key\") {\n super(message, \"authentication_error\");\n this.name = \"AuthenticationError\";\n }\n}\n\nexport class RateLimitError extends AstralformError {\n constructor(message = \"Rate limit exceeded\") {\n super(message, \"rate_limit_error\");\n this.name = \"RateLimitError\";\n }\n}\n\nexport class LLMNotConfiguredError extends AstralformError {\n constructor(message = \"LLM provider not configured for this project\") {\n super(message, \"llm_not_configured\");\n this.name = \"LLMNotConfiguredError\";\n }\n}\n\nexport class ServerError extends AstralformError {\n constructor(message = \"Internal server error\") {\n super(message, \"server_error\");\n this.name = \"ServerError\";\n }\n}\n\nexport class ConnectionError extends AstralformError {\n constructor(message = \"Failed to connect to server\") {\n super(message, \"connection_error\");\n this.name = \"ConnectionError\";\n }\n}\n\nexport class StreamAbortedError extends AstralformError {\n constructor(message = \"Stream was aborted\") {\n super(message, \"stream_aborted\");\n this.name = \"StreamAbortedError\";\n }\n}\n","import {\n AuthenticationError,\n ConnectionError,\n RateLimitError,\n ServerError,\n StreamAbortedError,\n} from \"./errors.js\";\nimport type { ChatStreamEvent, StreamJobSSEOptions } from \"./types.js\";\n\n/**\n * GET-based SSE stream for job events.\n */\nexport async function* streamJobSSE(\n options: StreamJobSSEOptions,\n): AsyncGenerator<ChatStreamEvent> {\n const { url, headers, signal, fetchFn } = options;\n\n let response: Response;\n try {\n response = await fetchFn(url, {\n method: \"GET\",\n headers,\n signal,\n });\n } catch (err) {\n if (err instanceof DOMException && err.name === \"AbortError\") {\n throw new StreamAbortedError();\n }\n throw new ConnectionError(\n err instanceof Error ? err.message : \"Failed to connect\",\n );\n }\n\n if (!response.ok) {\n const rawText = await response.text().catch(() => \"\");\n const text = rawText\n ? rawText.slice(0, 500).replace(/Bearer\\s+\\S+/gi, \"Bearer [REDACTED]\")\n : \"\";\n switch (response.status) {\n case 401:\n throw new AuthenticationError();\n case 429:\n throw new RateLimitError();\n default:\n throw new ServerError(text || `HTTP ${response.status}`);\n }\n }\n\n if (!response.body) {\n throw new ConnectionError(\"Response body is null\");\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n let currentEvent = \"\";\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n for (const line of lines) {\n if (line.startsWith(\"event: \")) {\n currentEvent = line.slice(7).trim();\n } else if (line.startsWith(\"data: \")) {\n const data = line.slice(6);\n if (data === \"[DONE]\") {\n return;\n }\n yield { event: currentEvent || \"message\", data };\n }\n if (line === \"\") {\n currentEvent = \"\";\n }\n }\n }\n } catch (err) {\n if (err instanceof DOMException && err.name === \"AbortError\") {\n throw new StreamAbortedError();\n }\n throw err;\n } finally {\n reader.releaseLock();\n }\n}\n","import {\n AuthenticationError,\n ConnectionError,\n RateLimitError,\n ServerError,\n} from \"./errors.js\";\nimport { streamJobSSE } from \"./streaming.js\";\nimport type {\n AgentInfo,\n AstralformConfig,\n ChatStreamEvent,\n ChatStreamRequest,\n ConversationAsset,\n ConversationEvent,\n Conversation,\n JobCreateResponse,\n Message,\n ProjectStatus,\n SkillInfo,\n ToolResultRequest,\n} from \"./types.js\";\n\nconst DEFAULT_BASE_URL = \"https://api.astralform.ai\";\n\nfunction validateBaseURL(url: string): string {\n const cleaned = url.replace(/\\/+$/, \"\");\n try {\n const parsed = new URL(cleaned);\n if (parsed.protocol !== \"https:\" && parsed.protocol !== \"http:\") {\n throw new Error(\n `Invalid baseURL protocol \"${parsed.protocol}\" - only http: and https: are allowed`,\n );\n }\n return parsed.origin + parsed.pathname.replace(/\\/+$/, \"\");\n } catch (err) {\n if (err instanceof Error && err.message.includes(\"Invalid baseURL\")) {\n throw err;\n }\n throw new Error(`Invalid baseURL: \"${cleaned}\" is not a valid URL`);\n }\n}\n\nexport class AstralformClient {\n private readonly apiKey: string;\n private readonly baseURL: string;\n private readonly userId: string;\n private readonly fetchFn: typeof globalThis.fetch;\n\n constructor(config: AstralformConfig) {\n if (!config.apiKey || typeof config.apiKey !== \"string\") {\n throw new Error(\"apiKey is required and must be a non-empty string\");\n }\n this.apiKey = config.apiKey;\n this.baseURL = validateBaseURL(config.baseURL ?? DEFAULT_BASE_URL);\n this.userId = config.userId;\n this.fetchFn = config.fetch ?? globalThis.fetch.bind(globalThis);\n }\n\n private get headers(): Record<string, string> {\n return {\n Authorization: `Bearer ${this.apiKey}`,\n \"X-End-User-ID\": this.userId,\n \"Content-Type\": \"application/json\",\n };\n }\n\n private async request(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<Response> {\n const response = await this.fetchFn(`${this.baseURL}${path}`, {\n method,\n headers: this.headers,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n }).catch((err) => {\n throw new ConnectionError(\n err instanceof Error ? err.message : \"Failed to connect\",\n );\n });\n await this.handleError(response);\n return response;\n }\n\n async get<T>(path: string): Promise<T> {\n const response = await this.request(\"GET\", path);\n return response.json() as Promise<T>;\n }\n\n async post<T>(path: string, body: unknown): Promise<T> {\n const response = await this.request(\"POST\", path, body);\n return response.json() as Promise<T>;\n }\n\n private async del(path: string): Promise<void> {\n await this.request(\"DELETE\", path);\n }\n\n private async handleError(response: Response): Promise<void> {\n if (response.ok) return;\n const text = await response.text().catch(() => \"\");\n switch (response.status) {\n case 401:\n throw new AuthenticationError();\n case 429:\n throw new RateLimitError();\n default: {\n // Sanitize server error text to avoid leaking sensitive details\n const safeText = text\n ? text.slice(0, 500).replace(/Bearer\\s+\\S+/gi, \"Bearer [REDACTED]\")\n : \"\";\n throw new ServerError(safeText || `HTTP ${response.status}`);\n }\n }\n }\n\n // --- REST Methods ---\n\n async getHealth(): Promise<{\n status: string;\n version: string;\n ollama_connected: boolean;\n }> {\n return this.get(\"/v1/health\");\n }\n\n async getProjectStatus(): Promise<ProjectStatus> {\n const raw = await this.get<{\n is_ready: boolean;\n llm_configured: boolean;\n llm_provider?: string;\n llm_model?: string;\n message: string;\n }>(\"/v1/project/status\");\n return {\n isReady: raw.is_ready,\n llmConfigured: raw.llm_configured,\n llmProvider: raw.llm_provider,\n llmModel: raw.llm_model,\n message: raw.message,\n };\n }\n\n async getConversations(limit = 50, offset = 0): Promise<Conversation[]> {\n const safeLimit = Math.max(1, Math.min(200, Math.floor(Number(limit))));\n const safeOffset = Math.max(0, Math.floor(Number(offset)));\n const raw = await this.get<\n {\n id: string;\n title: string;\n message_count: number;\n created_at: string;\n updated_at: string;\n }[]\n >(`/v1/conversations?limit=${safeLimit}&offset=${safeOffset}`);\n return raw.map((c) => ({\n id: c.id,\n title: c.title,\n messageCount: c.message_count,\n createdAt: c.created_at,\n updatedAt: c.updated_at,\n }));\n }\n\n async getMessages(conversationId: string): Promise<Message[]> {\n const raw = await this.get<\n {\n id: string;\n conversation_id: string;\n role: \"user\" | \"assistant\" | \"system\";\n content: string;\n parent_id?: string;\n created_at: string;\n }[]\n >(`/v1/conversations/${encodeURIComponent(conversationId)}/messages`);\n return raw.map((m) => ({\n id: m.id,\n conversationId: m.conversation_id,\n role: m.role,\n content: m.content,\n parentId: m.parent_id,\n status: \"complete\" as const,\n createdAt: m.created_at,\n }));\n }\n\n async deleteConversation(id: string): Promise<void> {\n await this.del(`/v1/conversations/${encodeURIComponent(id)}`);\n }\n\n async getAgents(): Promise<AgentInfo[]> {\n const raw = await this.get<\n {\n name: string;\n display_name: string;\n description: string;\n is_orchestrator: boolean;\n is_enabled: boolean;\n avatar_url?: string;\n }[]\n >(\"/v1/agents\");\n return raw.map((a) => ({\n name: a.name,\n displayName: a.display_name,\n description: a.description,\n isOrchestrator: a.is_orchestrator,\n isEnabled: a.is_enabled,\n avatarUrl: a.avatar_url,\n }));\n }\n\n async getSkills(): Promise<SkillInfo[]> {\n const raw = await this.get<\n {\n name: string;\n display_name: string;\n description: string;\n is_enabled: boolean;\n }[]\n >(\"/v1/skills\");\n return raw.map((s) => ({\n name: s.name,\n displayName: s.display_name,\n description: s.description,\n isEnabled: s.is_enabled,\n }));\n }\n\n async getConversationEvents(\n conversationId: string,\n jobId?: string,\n ): Promise<ConversationEvent[]> {\n let url = `/v1/conversations/${encodeURIComponent(conversationId)}/events`;\n if (jobId) url += `?job_id=${encodeURIComponent(jobId)}`;\n return this.get(url);\n }\n\n async submitToolResult(request: ToolResultRequest): Promise<void> {\n await this.post(\"/v1/tool-result\", request);\n }\n\n // --- Conversation Assets ---\n\n private mapAsset(raw: Record<string, unknown>): ConversationAsset {\n return {\n id: raw.id as string,\n kind: raw.kind as \"upload\" | \"output\",\n originalName: raw.original_name as string,\n mediaType: raw.media_type as string,\n sizeBytes: raw.size_bytes as number,\n workspacePath: raw.workspace_path as string | undefined,\n sourceMessageId: raw.source_message_id as string | undefined,\n agentName: raw.agent_name as string | undefined,\n createdAt: raw.created_at as string,\n };\n }\n\n async uploadFile(\n conversationId: string,\n file: Blob,\n filename?: string,\n ): Promise<ConversationAsset> {\n const formData = new FormData();\n formData.append(\"file\", file, filename);\n\n const response = await this.fetchFn(\n `${this.baseURL}/v1/conversations/${encodeURIComponent(conversationId)}/uploads`,\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n \"X-End-User-ID\": this.userId,\n },\n body: formData,\n },\n ).catch((err) => {\n throw new ConnectionError(\n err instanceof Error ? err.message : \"Failed to connect\",\n );\n });\n await this.handleError(response);\n const raw = await response.json();\n return this.mapAsset(raw as Record<string, unknown>);\n }\n\n async listUploads(conversationId: string): Promise<ConversationAsset[]> {\n const raw = await this.get<Record<string, unknown>[]>(\n `/v1/conversations/${encodeURIComponent(conversationId)}/uploads`,\n );\n return raw.map((r) => this.mapAsset(r));\n }\n\n async listOutputs(conversationId: string): Promise<ConversationAsset[]> {\n const raw = await this.get<Record<string, unknown>[]>(\n `/v1/conversations/${encodeURIComponent(conversationId)}/outputs`,\n );\n return raw.map((r) => this.mapAsset(r));\n }\n\n // --- Jobs API ---\n\n async createJob(request: ChatStreamRequest): Promise<JobCreateResponse> {\n return this.post<JobCreateResponse>(\"/v1/jobs\", request);\n }\n\n async *streamJobEvents(\n jobId: string,\n afterSeq = -1,\n signal?: AbortSignal,\n ): AsyncGenerator<ChatStreamEvent> {\n const url = `${this.baseURL}/v1/jobs/${encodeURIComponent(jobId)}/events?after=${afterSeq}`;\n yield* streamJobSSE({\n url,\n headers: this.headers,\n signal,\n fetchFn: this.fetchFn,\n });\n }\n\n async cancelJob(jobId: string): Promise<void> {\n await this.post(`/v1/jobs/${encodeURIComponent(jobId)}/cancel`, {});\n }\n}\n","/**\n * BlockBuilder — pure rendering engine. Zero default behavior.\n *\n * Clients register handlers that map events to blocks.\n * Both live streaming and restore go through the same engine.\n *\n * import { BlockBuilder, standardHandlers } from \"@astralform/js\";\n * const builder = new BlockBuilder();\n * builder.registerHandlers(standardHandlers);\n */\n\nimport type { ChatEvent } from \"./types.js\";\n\n// =============================================================================\n// Block protocol — typed discriminated union\n// =============================================================================\n\nexport interface UserBlock {\n type: \"user\";\n id: string;\n content: string;\n createdAt?: number;\n}\n\nexport interface TextBlock {\n type: \"text\";\n id: string;\n content: string;\n isStreaming: boolean;\n}\n\nexport interface ThinkingBlock {\n type: \"thinking\";\n id: string;\n content: string;\n isActive: boolean;\n durationMs?: number;\n}\n\nexport interface AgentBlock {\n type: \"agent\";\n id: string;\n agentName: string;\n displayName?: string;\n avatarUrl?: string;\n}\n\nexport interface SubagentBlock {\n type: \"subagent\";\n id: string;\n agentName: string;\n displayName: string;\n toolCallId: string;\n avatarUrl?: string;\n description?: string;\n content: string;\n isActive: boolean;\n}\n\nexport interface ToolBlock {\n type: \"tool\";\n id: string;\n callId: string;\n toolName: string;\n displayName?: string;\n description?: string;\n arguments?: Record<string, unknown>;\n status: string;\n iconUrl?: string;\n toolCategory?: string;\n sources?: { title: string; url: string; snippet?: string }[];\n durationMs?: number;\n result?: string;\n}\n\nexport interface CapsuleBlock {\n type: \"capsule\";\n id: string;\n callId: string;\n toolName: string;\n command?: string;\n output: string;\n durationMs?: number;\n isActive: boolean;\n}\n\nexport interface AssetBlock {\n type: \"asset\";\n id: string;\n assetId: string;\n name: string;\n url: string;\n mediaType: string;\n sizeBytes: number;\n}\n\nexport interface TodoBlock {\n type: \"todo\";\n id: string;\n todos: { content: string; status: string }[];\n}\n\nexport interface EditorBlock {\n type: \"editor\";\n id: string;\n callId: string;\n path: string;\n language: string;\n content: string;\n isStreaming: boolean;\n}\n\nexport interface ErrorBlock {\n type: \"error\";\n id: string;\n message: string;\n}\n\nexport type Block =\n | UserBlock\n | TextBlock\n | ThinkingBlock\n | AgentBlock\n | SubagentBlock\n | ToolBlock\n | CapsuleBlock\n | AssetBlock\n | TodoBlock\n | EditorBlock\n | ErrorBlock;\n\n// =============================================================================\n// Event handler type\n// =============================================================================\n\nexport type EventHandler = (event: ChatEvent, builder: BlockBuilder) => void;\n\n// =============================================================================\n// BlockBuilder — pure engine\n// =============================================================================\n\nlet _idCounter = 0;\n\nexport class BlockBuilder {\n private _blocks: Block[] = [];\n private _handlers = new Map<string, EventHandler | null>();\n private _onChange: (() => void) | null = null;\n\n // Active block refs — public so handlers can read/write them\n activeTextId: string | null = null;\n activeThinkingId: string | null = null;\n thinkingStartMs: number | null = null;\n activeEditorId: string | null = null;\n activeTodoId: string | null = null;\n\n // ── Registration ──────────────────────────────────────────────\n\n on(eventType: string, handler: EventHandler | null): void {\n this._handlers.set(eventType, handler);\n }\n\n registerHandlers(handlers: Record<string, EventHandler | null>): void {\n for (const [type, handler] of Object.entries(handlers)) {\n this._handlers.set(type, handler);\n }\n }\n\n // ── Event processing ──────────────────────────────────────────\n\n processEvent(event: ChatEvent): void {\n const handler = this._handlers.get(event.type);\n if (handler === null) return;\n if (!handler) return;\n handler(event, this);\n }\n\n // ── State ─────────────────────────────────────────────────────\n\n getBlocks(): Block[] {\n return [...this._blocks];\n }\n\n reset(): void {\n this._blocks = [];\n this.activeTextId = null;\n this.activeThinkingId = null;\n this.thinkingStartMs = null;\n this.activeEditorId = null;\n this.activeTodoId = null;\n }\n\n setOnChange(fn: (() => void) | null): void {\n this._onChange = fn;\n }\n\n // ── Block manipulation (used by handlers) ─────────────────────\n\n addBlock(block: Block): void {\n this._blocks = [...this._blocks, block];\n this._notify();\n }\n\n updateBlock<T extends Block[\"type\"]>(\n id: string,\n updater: (\n block: Extract<Block, { type: T }>,\n ) => Extract<Block, { type: T }>,\n ): void {\n let changed = false;\n this._blocks = this._blocks.map((b) => {\n if (b.id !== id) return b;\n changed = true;\n return updater(b as Extract<Block, { type: T }>);\n });\n if (changed) this._notify();\n }\n\n /** Update any block by id with a partial update (type-loose for handlers). */\n patchBlock(id: string, patch: Partial<Block>): void {\n let changed = false;\n this._blocks = this._blocks.map((b) => {\n if (b.id !== id) return b;\n changed = true;\n return { ...b, ...patch } as Block;\n });\n if (changed) this._notify();\n }\n\n findBlock(predicate: (b: Block) => boolean): Block | undefined {\n for (let i = this._blocks.length - 1; i >= 0; i--) {\n const block = this._blocks[i];\n if (block && predicate(block)) return block;\n }\n return undefined;\n }\n\n nextId(): string {\n return `blk_${++_idCounter}`;\n }\n\n // ── Internal ──────────────────────────────────────────────────\n\n private _notify(): void {\n this._onChange?.();\n }\n}\n","import type { Conversation, Message } from \"./types.js\";\n\nexport interface ChatStorage {\n fetchConversations(): Promise<Conversation[]>;\n fetchConversation(id: string): Promise<Conversation | null>;\n createConversation(id: string, title: string): Promise<Conversation>;\n updateConversationTitle(id: string, title: string): Promise<void>;\n deleteConversation(id: string): Promise<void>;\n fetchMessages(conversationId: string): Promise<Message[]>;\n addMessage(message: Message, conversationId: string): Promise<void>;\n updateMessageStatus(id: string, status: Message[\"status\"]): Promise<void>;\n deleteMessage(id: string): Promise<void>;\n}\n\nexport class InMemoryStorage implements ChatStorage {\n private conversations = new Map<string, Conversation>();\n private messages = new Map<string, Message[]>();\n\n async fetchConversations(): Promise<Conversation[]> {\n return Array.from(this.conversations.values()).sort(\n (a, b) =>\n new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime(),\n );\n }\n\n async fetchConversation(id: string): Promise<Conversation | null> {\n return this.conversations.get(id) ?? null;\n }\n\n async createConversation(id: string, title: string): Promise<Conversation> {\n const now = new Date().toISOString();\n const conversation: Conversation = {\n id,\n title,\n messageCount: 0,\n createdAt: now,\n updatedAt: now,\n };\n this.conversations.set(id, conversation);\n this.messages.set(id, []);\n return conversation;\n }\n\n async updateConversationTitle(id: string, title: string): Promise<void> {\n const conv = this.conversations.get(id);\n if (conv) {\n conv.title = title;\n conv.updatedAt = new Date().toISOString();\n }\n }\n\n async deleteConversation(id: string): Promise<void> {\n this.conversations.delete(id);\n this.messages.delete(id);\n }\n\n async fetchMessages(conversationId: string): Promise<Message[]> {\n return this.messages.get(conversationId) ?? [];\n }\n\n async addMessage(message: Message, conversationId: string): Promise<void> {\n const msgs = this.messages.get(conversationId) ?? [];\n msgs.push(message);\n this.messages.set(conversationId, msgs);\n\n const conv = this.conversations.get(conversationId);\n if (conv) {\n conv.messageCount = msgs.length;\n conv.updatedAt = new Date().toISOString();\n }\n }\n\n async updateMessageStatus(\n id: string,\n status: Message[\"status\"],\n ): Promise<void> {\n for (const msgs of this.messages.values()) {\n const msg = msgs.find((m) => m.id === id);\n if (msg) {\n msg.status = status;\n return;\n }\n }\n }\n\n async deleteMessage(id: string): Promise<void> {\n for (const [convId, msgs] of this.messages.entries()) {\n const idx = msgs.findIndex((m) => m.id === id);\n if (idx !== -1) {\n msgs.splice(idx, 1);\n const conv = this.conversations.get(convId);\n if (conv) {\n conv.messageCount = msgs.length;\n }\n return;\n }\n }\n }\n}\n","import type { ToolCallRequest, ToolDefinition, ToolResult } from \"./types.js\";\n\nexport type ToolHandler = (args: Record<string, unknown>) => Promise<string>;\n\ninterface RegisteredTool {\n name: string;\n description: string;\n inputSchema: Record<string, unknown>;\n handler: ToolHandler;\n}\n\n/** Validates tool name: alphanumeric, hyphens, underscores, dots only */\nconst TOOL_NAME_PATTERN = /^[a-zA-Z0-9_.\\-]+$/;\n\n/** Strips prototype-polluting keys from an object */\nfunction sanitizeArgs(args: Record<string, unknown>): Record<string, unknown> {\n const clean: Record<string, unknown> = Object.create(null);\n for (const key of Object.keys(args)) {\n if (key === \"__proto__\" || key === \"constructor\" || key === \"prototype\") {\n continue;\n }\n clean[key] = args[key];\n }\n return clean;\n}\n\nexport class ToolRegistry {\n private tools = new Map<string, RegisteredTool>();\n\n registerTool(\n name: string,\n description: string,\n inputSchema: Record<string, unknown>,\n handler: ToolHandler,\n ): void {\n if (!name || !TOOL_NAME_PATTERN.test(name)) {\n throw new Error(\n `Invalid tool name \"${name}\" - must match ${TOOL_NAME_PATTERN}`,\n );\n }\n if (name.length > 256) {\n throw new Error(\"Tool name must be 256 characters or fewer\");\n }\n this.tools.set(name, { name, description, inputSchema, handler });\n }\n\n unregisterTool(name: string): boolean {\n return this.tools.delete(name);\n }\n\n hasTool(name: string): boolean {\n return this.tools.has(name);\n }\n\n async executeTool(request: ToolCallRequest): Promise<ToolResult> {\n const tool = this.tools.get(request.toolName);\n if (!tool) {\n return {\n call_id: request.callId,\n tool_name: request.toolName,\n result: `Tool \"${request.toolName}\" not found`,\n is_error: true,\n };\n }\n\n try {\n const result = await tool.handler(sanitizeArgs(request.arguments));\n return {\n call_id: request.callId,\n tool_name: request.toolName,\n result,\n is_error: false,\n };\n } catch (err) {\n return {\n call_id: request.callId,\n tool_name: request.toolName,\n result: err instanceof Error ? err.message : String(err),\n is_error: true,\n };\n }\n }\n\n getManifest(): ToolDefinition[] {\n return Array.from(this.tools.values()).map((t) => ({\n name: t.name,\n description: t.description,\n parameters: t.inputSchema,\n }));\n }\n\n getToolNames(): string[] {\n return Array.from(this.tools.keys());\n }\n\n clear(): void {\n this.tools.clear();\n }\n}\n","export function generateId(): string {\n if (typeof crypto !== \"undefined\" && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n // Fallback for environments without crypto.randomUUID\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === \"x\" ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n","import { BlockBuilder } from \"./block-builder.js\";\nimport { AstralformClient } from \"./client.js\";\nimport { AstralformError, ConnectionError } from \"./errors.js\";\nimport { InMemoryStorage, type ChatStorage } from \"./storage.js\";\nimport { ToolRegistry } from \"./tools.js\";\nimport type {\n AgentInfo,\n AstralformConfig,\n CapsuleOutput,\n ChatEvent,\n ChatStreamRequest,\n Conversation,\n Message,\n ProjectStatus,\n SendOptions,\n SkillInfo,\n SSEEvent,\n SubagentState,\n TodoItem,\n ToolCallRequest,\n ToolResult,\n ToolState,\n} from \"./types.js\";\nimport { generateId } from \"./utils.js\";\n\ntype ChatEventHandler = (event: ChatEvent) => void;\n\nexport class ChatSession {\n readonly client: AstralformClient;\n readonly toolRegistry: ToolRegistry;\n readonly storage: ChatStorage;\n readonly blockBuilder: BlockBuilder;\n\n // State\n conversationId: string | null = null;\n conversations: Conversation[] = [];\n messages: Message[] = [];\n streamingContent = \"\";\n isStreaming = false;\n executingTool: string | null = null;\n projectStatus: ProjectStatus | null = null;\n agents: AgentInfo[] = [];\n skills: SkillInfo[] = [];\n enabledClientTools = new Set<string>();\n modelDisplayName: string | null = null;\n\n // New state fields\n thinkingContent = \"\";\n isThinking = false;\n activeSubagents = new Map<string, SubagentState>();\n capsuleOutputs: CapsuleOutput[] = [];\n todos: TodoItem[] = [];\n activeTools = new Map<string, ToolState>();\n\n private handlers: Set<ChatEventHandler> = new Set();\n private abortController: AbortController | null = null;\n\n constructor(\n config: AstralformConfig,\n storage?: ChatStorage,\n blockBuilder?: BlockBuilder,\n ) {\n this.client = new AstralformClient(config);\n this.toolRegistry = new ToolRegistry();\n this.storage = storage ?? new InMemoryStorage();\n this.blockBuilder = blockBuilder ?? new BlockBuilder();\n\n // Wire block builder to emit blocks_changed events\n this.blockBuilder.setOnChange(() => {\n this.emit({\n type: \"blocks_changed\",\n blocks: this.blockBuilder.getBlocks(),\n });\n });\n }\n\n on(handler: ChatEventHandler): () => void {\n this.handlers.add(handler);\n return () => {\n this.handlers.delete(handler);\n };\n }\n\n private emit(event: ChatEvent): void {\n // Feed the block builder first (produces blocks_changed events)\n if (event.type !== \"blocks_changed\" && event.type !== \"connected\") {\n this.blockBuilder.processEvent(event);\n }\n\n for (const handler of this.handlers) {\n try {\n handler(event);\n } catch {\n // Don't let handler errors crash the session\n }\n }\n }\n\n async connect(): Promise<void> {\n const [status, conversations, agents, skills] = await Promise.allSettled([\n this.client.getProjectStatus(),\n this.client.getConversations(),\n this.client.getAgents().catch(() => [] as AgentInfo[]),\n this.client.getSkills().catch(() => [] as SkillInfo[]),\n ]);\n\n if (status.status === \"fulfilled\") {\n this.projectStatus = status.value;\n }\n if (conversations.status === \"fulfilled\") {\n this.conversations = conversations.value;\n }\n if (agents.status === \"fulfilled\") {\n this.agents = agents.value;\n }\n if (skills.status === \"fulfilled\") {\n this.skills = skills.value;\n }\n\n this.emit({ type: \"connected\" });\n }\n\n async send(content: string, options?: SendOptions): Promise<void> {\n if (this.isStreaming) return;\n\n const conversationId =\n options?.conversationId ?? this.conversationId ?? undefined;\n\n // Create user message\n const userMessage: Message = {\n id: generateId(),\n conversationId: conversationId ?? \"\",\n role: \"user\",\n content,\n status: \"complete\",\n createdAt: new Date().toISOString(),\n };\n\n if (conversationId) {\n await this.storage.addMessage(userMessage, conversationId);\n }\n this.messages.push(userMessage);\n\n // Build request\n const request: ChatStreamRequest = {\n message: content,\n conversation_id: conversationId,\n mcp_manifest: this.toolRegistry.getManifest(),\n enabled_mcp: Array.from(\n options?.enabledClientTools ?? this.enabledClientTools,\n ),\n upload_ids: options?.uploadIds,\n agent_name: options?.agentName,\n enable_search: options?.enableSearch,\n };\n\n await this.processStream(request);\n }\n\n async resendFromCheckpoint(\n messageId: string,\n newContent: string,\n options?: { enableSearch?: boolean },\n ): Promise<void> {\n if (this.isStreaming) return;\n\n const request: ChatStreamRequest = {\n message: newContent,\n conversation_id: this.conversationId ?? undefined,\n resend_from: messageId,\n mcp_manifest: this.toolRegistry.getManifest(),\n enabled_mcp: Array.from(this.enabledClientTools),\n enable_search: options?.enableSearch,\n };\n\n await this.processStream(request);\n }\n\n private resetStreamingState(): void {\n this.streamingContent = \"\";\n this.thinkingContent = \"\";\n this.isThinking = false;\n this.activeSubagents.clear();\n this.capsuleOutputs = [];\n this.todos = [];\n this.activeTools.clear();\n }\n\n private async processStream(request: ChatStreamRequest): Promise<void> {\n this.isStreaming = true;\n this.resetStreamingState();\n // Don't reset blockBuilder here — the client controls when to reset\n // (e.g. addUserBlock resets before adding the user block)\n this.abortController = new AbortController();\n\n try {\n await this.consumeJobStream(request);\n } catch (err) {\n // Don't emit error for intentional abort (detach/disconnect)\n if (!(err instanceof DOMException && err.name === \"AbortError\")) {\n this.emit({\n type: \"error\",\n error: err instanceof Error ? err : new ConnectionError(String(err)),\n });\n }\n } finally {\n this.isStreaming = false;\n this.executingTool = null;\n this.abortController = null;\n }\n }\n\n /** Last received sequence number for resumable reconnection */\n private lastSeq = -1;\n\n /** Current job ID for cancellation */\n currentJobId: string | null = null;\n\n private async consumeJobStream(request: ChatStreamRequest): Promise<void> {\n const job = await this.client.createJob(request);\n this.currentJobId = job.job_id;\n\n let conversationId = job.conversation_id;\n if (!this.conversationId) {\n this.conversationId = conversationId;\n }\n\n const messageId = job.message_id;\n this.lastSeq = -1;\n\n const stream = this.client.streamJobEvents(\n job.job_id,\n this.lastSeq,\n this.abortController?.signal,\n );\n\n // completeStream is called inside consumeEventStream when message_stop arrives\n // — no second call needed here\n await this.consumeEventStream(\n stream,\n conversationId,\n messageId,\n true, // executeClientTools\n );\n }\n\n /**\n * Shared event consumption loop used by both consumeJobStream and reconnectToJob.\n */\n private async consumeEventStream(\n stream: AsyncGenerator<{ data: string }>,\n conversationId: string,\n messageId: string,\n executeClientTools: boolean,\n ): Promise<void> {\n for await (const raw of stream) {\n let parsed: SSEEvent;\n try {\n const data = JSON.parse(raw.data);\n if (\n typeof data !== \"object\" ||\n data === null ||\n typeof data.type !== \"string\"\n ) {\n if (typeof data?.seq === \"number\") {\n this.lastSeq = data.seq;\n }\n continue;\n }\n parsed = data as SSEEvent;\n if (typeof (data as Record<string, unknown>).seq === \"number\") {\n this.lastSeq = (data as Record<string, unknown>).seq as number;\n }\n } catch {\n continue;\n }\n\n switch (parsed.type) {\n case \"message_start\":\n conversationId = parsed.conversation_id;\n if (!this.conversationId) {\n this.conversationId = conversationId;\n }\n if (parsed.message_id) {\n messageId = parsed.message_id;\n }\n if (parsed.model_display_name) {\n this.modelDisplayName = parsed.model_display_name;\n this.emit({\n type: \"model_info\",\n name: parsed.model_display_name,\n });\n }\n break;\n\n case \"content_block_delta\":\n this.streamingContent += parsed.delta.text;\n this.emit({ type: \"chunk\", text: parsed.delta.text });\n break;\n\n case \"tool_use_start\": {\n this.applyEvent(parsed);\n if (executeClientTools && parsed.is_client_tool) {\n const results = await this.executeClientTools([\n {\n callId: parsed.call_id,\n toolName: parsed.tool,\n displayName: parsed.display_name,\n description: parsed.description,\n arguments: parsed.arguments,\n isClientTool: parsed.is_client_tool,\n toolCategory: parsed.tool_category,\n iconUrl: parsed.icon_url,\n },\n ]);\n await this.client.submitToolResult({\n conversation_id: conversationId,\n message_id: messageId,\n tool_results: results,\n });\n }\n break;\n }\n\n case \"subagent_content_delta\": {\n const subagent = this.activeSubagents.get(parsed.tool_call_id);\n if (subagent) {\n subagent.content += parsed.delta.text;\n }\n this.emit({\n type: \"subagent_chunk\",\n agentName: parsed.agent_name,\n toolCallId: parsed.tool_call_id,\n text: parsed.delta.text,\n });\n break;\n }\n\n case \"thinking_delta\":\n this.thinkingContent += parsed.delta.text;\n this.isThinking = true;\n this.emit({ type: \"thinking_delta\", text: parsed.delta.text });\n break;\n\n case \"thinking_complete\":\n this.isThinking = false;\n this.emit({ type: \"thinking_complete\" });\n break;\n\n case \"retry\":\n this.emit({\n type: \"retry\",\n attempt: parsed.attempt,\n maxAttempts: parsed.max_attempts,\n delaySeconds: parsed.delay_seconds,\n });\n break;\n\n case \"message_stop\":\n // Emit complete IMMEDIATELY — don't wait for stream close\n // Post-processing continues in background but user is unlocked\n await this.completeStream(\n conversationId,\n messageId,\n parsed.title,\n parsed.metrics,\n parsed.job_id,\n );\n this.isStreaming = false;\n this.currentJobId = null;\n break;\n\n case \"error\":\n this.emit({\n type: \"error\",\n error: new AstralformError(parsed.message, parsed.code),\n });\n break;\n\n default:\n this.applyEvent(parsed);\n }\n }\n }\n\n /**\n * Apply a single SSE event to session state and notify consumers.\n * Shared between live streaming and historical event replay.\n */\n private applyEvent(event: SSEEvent): void {\n switch (event.type) {\n case \"user_message\":\n this.emit({\n type: \"user_message\",\n content: event.content,\n createdAt: event.created_at,\n });\n break;\n\n case \"title_generated\": {\n // Update SDK's internal conversations array so syncConversations\n // doesn't overwrite the title with a stale value\n if (this.conversationId && event.title) {\n const conv = this.conversations.find(\n (c) => c.id === this.conversationId,\n );\n if (conv) {\n conv.title = event.title;\n }\n }\n this.emit({ type: \"title_generated\", title: event.title });\n break;\n }\n\n case \"message_start\":\n if (event.conversation_id && !this.conversationId) {\n this.conversationId = event.conversation_id;\n }\n if (event.model_display_name) {\n this.modelDisplayName = event.model_display_name;\n this.emit({ type: \"model_info\", name: event.model_display_name });\n }\n break;\n\n case \"content_block_delta\":\n this.streamingContent += event.delta.text;\n this.emit({ type: \"chunk\", text: event.delta.text });\n break;\n\n case \"thinking_delta\":\n this.thinkingContent += event.delta.text;\n this.isThinking = true;\n this.emit({ type: \"thinking_delta\", text: event.delta.text });\n break;\n\n case \"thinking_complete\":\n this.isThinking = false;\n this.emit({ type: \"thinking_complete\" });\n break;\n\n case \"tool_executing\":\n this.emit({\n type: \"tool_executing\",\n name: event.tool,\n call_id: event.call_id,\n });\n break;\n\n case \"tool_progress\":\n this.emit({\n type: \"tool_progress\",\n callId: event.call_id,\n tool: event.tool,\n index: event.index,\n total: event.total,\n item: event.item,\n });\n break;\n\n case \"message_stop\":\n this.emit({\n type: \"complete\",\n content: this.streamingContent,\n conversationId: this.conversationId ?? \"\",\n messageId: event.job_id ?? \"\",\n title: event.title,\n metrics: event.metrics,\n job_id: event.job_id,\n });\n break;\n\n case \"tool_use_start\": {\n const request: ToolCallRequest = {\n callId: event.call_id,\n toolName: event.tool,\n displayName: event.display_name,\n description: event.description,\n arguments: event.arguments,\n isClientTool: event.is_client_tool,\n toolCategory: event.tool_category,\n iconUrl: event.icon_url,\n };\n this.activeTools.set(event.call_id, {\n ...request,\n status: event.is_client_tool ? \"calling\" : \"executing\",\n });\n this.emit({ type: \"tool_call\", request });\n break;\n }\n\n case \"tool_use_end\": {\n const toolState = this.activeTools.get(event.call_id);\n if (toolState) {\n toolState.status = \"completed\";\n }\n this.emit({\n type: \"tool_end\",\n callId: event.call_id,\n toolName: event.tool,\n result: event.result,\n sources: event.sources,\n durationMs: event.duration_ms,\n });\n break;\n }\n\n case \"agent_start\":\n this.emit({\n type: \"agent_start\",\n agentName: event.agent_name,\n agentDisplayName: event.agent_display_name,\n avatarUrl: event.avatar_url,\n });\n break;\n\n case \"agent_end\":\n this.emit({ type: \"agent_end\", agentName: event.agent_name });\n break;\n\n case \"subagent_start\":\n this.activeSubagents.set(event.tool_call_id, {\n agentName: event.agent_name,\n displayName: event.display_name,\n avatarUrl: event.avatar_url,\n description: event.description,\n content: \"\",\n isActive: true,\n });\n this.emit({\n type: \"subagent_start\",\n agentName: event.agent_name,\n displayName: event.display_name,\n toolCallId: event.tool_call_id,\n avatarUrl: event.avatar_url,\n description: event.description,\n });\n break;\n\n case \"subagent_update\": {\n const sub = this.activeSubagents.get(event.tool_call_id);\n if (sub) {\n sub.agentName = event.agent_name;\n sub.displayName = event.display_name;\n }\n this.emit({\n type: \"subagent_update\",\n agentName: event.agent_name,\n displayName: event.display_name,\n toolCallId: event.tool_call_id,\n });\n break;\n }\n\n case \"subagent_end\": {\n const sub = this.activeSubagents.get(event.tool_call_id);\n if (sub) {\n sub.isActive = false;\n }\n this.emit({\n type: \"subagent_end\",\n agentName: event.agent_name,\n displayName: event.display_name,\n toolCallId: event.tool_call_id,\n });\n break;\n }\n\n case \"subagent_tool_use\":\n this.emit({\n type: \"subagent_tool_use\",\n agentName: event.agent_name,\n toolName: event.tool,\n toolCallId: event.tool_call_id,\n result: event.result,\n });\n break;\n\n case \"capsule_output\": {\n const capsule: CapsuleOutput = {\n toolName: event.tool_name,\n agentName: event.agent_name,\n command: event.command,\n output: event.output,\n durationMs: event.duration_ms,\n callId: event.call_id,\n };\n this.capsuleOutputs.push(capsule);\n this.emit({ type: \"capsule_output\", ...capsule });\n break;\n }\n\n case \"capsule_output_chunk\":\n this.emit({\n type: \"capsule_output_chunk\",\n callId: event.call_id,\n stream: event.stream,\n chunk: event.chunk,\n });\n break;\n\n case \"todo_update\":\n this.todos = event.todos;\n this.emit({ type: \"todo_update\", todos: event.todos });\n break;\n\n case \"asset_created\":\n this.emit({\n type: \"asset_created\",\n assetId: event.asset_id,\n name: event.name,\n url: event.url,\n mediaType: event.media_type,\n sizeBytes: event.size_bytes,\n });\n break;\n\n case \"editor_content_start\":\n this.emit({\n type: \"editor_content_start\",\n callId: event.call_id,\n path: event.path,\n language: event.language,\n });\n break;\n\n case \"editor_content_delta\":\n this.emit({\n type: \"editor_content_delta\",\n callId: event.call_id,\n path: event.path,\n delta: event.delta,\n });\n break;\n\n case \"editor_content_end\":\n this.emit({\n type: \"editor_content_end\",\n callId: event.call_id,\n });\n break;\n }\n }\n\n private async executeClientTools(\n toolCalls: ToolCallRequest[],\n ): Promise<ToolResult[]> {\n const results: ToolResult[] = [];\n for (const call of toolCalls) {\n this.executingTool = call.toolName;\n const toolState = this.activeTools.get(call.callId);\n if (toolState) {\n toolState.status = \"executing\";\n }\n this.emit({ type: \"tool_executing\", name: call.toolName });\n const result = await this.toolRegistry.executeTool(call);\n results.push(result);\n if (toolState) {\n toolState.status = \"completed\";\n }\n this.emit({\n type: \"tool_completed\",\n name: call.toolName,\n result: result.result,\n });\n }\n this.executingTool = null;\n return results;\n }\n\n private async completeStream(\n conversationId: string,\n messageId: string,\n title?: string,\n metrics?: Record<string, unknown>,\n jobId?: string,\n ): Promise<void> {\n // Store assistant message\n const assistantMessage: Message = {\n id: messageId || generateId(),\n conversationId,\n role: \"assistant\",\n content: this.streamingContent,\n status: \"complete\",\n createdAt: new Date().toISOString(),\n };\n this.messages.push(assistantMessage);\n await this.storage.addMessage(assistantMessage, conversationId);\n\n // Update conversation title if provided\n if (title && conversationId) {\n await this.storage.updateConversationTitle(conversationId, title);\n const conv = this.conversations.find((c) => c.id === conversationId);\n if (conv) {\n conv.title = title;\n }\n }\n\n this.emit({\n type: \"complete\",\n content: this.streamingContent,\n conversationId,\n messageId: assistantMessage.id,\n title,\n metrics,\n job_id: jobId,\n });\n }\n\n /**\n * Load conversation context (messages) without replaying events.\n * Used before reconnectToJob — SSE replay handles event replay.\n */\n async loadConversation(id: string): Promise<void> {\n this.conversationId = id;\n this.resetStreamingState();\n this.blockBuilder.reset();\n this.messages = await this.client\n .getMessages(id)\n .catch(() => this.storage.fetchMessages(id));\n }\n\n /**\n * Reconnect to a running job's SSE stream (e.g. after page reload).\n * Replays all events from the beginning and continues live.\n * Does NOT reset BlockBuilder — caller controls reset.\n */\n async reconnectToJob(jobId: string): Promise<void> {\n if (this.isStreaming) return;\n\n this.isStreaming = true;\n this.currentJobId = jobId;\n this.lastSeq = -1;\n this.resetStreamingState();\n this.abortController = new AbortController();\n\n try {\n const stream = this.client.streamJobEvents(\n jobId,\n this.lastSeq,\n this.abortController?.signal,\n );\n\n // completeStream is called inside consumeEventStream on message_stop\n await this.consumeEventStream(\n stream,\n this.conversationId ?? \"\",\n \"\",\n false, // don't execute client tools on reconnect\n );\n } catch (err) {\n this.emit({\n type: \"error\",\n error: err instanceof Error ? err : new ConnectionError(String(err)),\n });\n } finally {\n this.isStreaming = false;\n this.executingTool = null;\n this.abortController = null;\n }\n }\n\n /** Detach from the SSE stream without cancelling the job.\n * The backend job keeps running — caller can reconnect later. */\n detach(): void {\n this.abortController?.abort();\n this.abortController = null;\n this.isStreaming = false;\n this.streamingContent = \"\";\n this.executingTool = null;\n // Reset block builder to prevent stale blocks from leaking\n // into the next conversation's render\n this.blockBuilder.reset();\n this.emit({ type: \"disconnected\" });\n }\n\n /** Stop the job and disconnect (explicit user action). */\n disconnect(): void {\n if (this.currentJobId) {\n this.client.cancelJob(this.currentJobId).catch(() => {});\n }\n this.detach();\n this.currentJobId = null;\n }\n\n async createNewConversation(): Promise<string> {\n const id = generateId();\n const conversation = await this.storage.createConversation(\n id,\n \"New Conversation\",\n );\n this.conversations.unshift(conversation);\n this.conversationId = id;\n this.messages = [];\n this.streamingContent = \"\";\n return id;\n }\n\n async switchConversation(id: string, jobId?: string): Promise<void> {\n this.conversationId = id;\n this.resetStreamingState();\n this.blockBuilder.reset();\n\n const [messagesResult, eventsResult] = await Promise.allSettled([\n this.client.getMessages(id).catch(() => this.storage.fetchMessages(id)),\n this.client.getConversationEvents(id, jobId),\n ]);\n\n this.messages =\n messagesResult.status === \"fulfilled\" ? messagesResult.value : [];\n\n // Replay ALL stored events through the same handlers as live streaming\n if (eventsResult.status === \"fulfilled\") {\n for (const ev of eventsResult.value) {\n this.applyEvent({ type: ev.event, ...ev.data } as SSEEvent);\n }\n }\n }\n\n async deleteConversation(id: string): Promise<void> {\n try {\n await this.client.deleteConversation(id);\n } catch {\n // May already be deleted on backend\n }\n await this.storage.deleteConversation(id);\n this.conversations = this.conversations.filter((c) => c.id !== id);\n if (this.conversationId === id) {\n this.conversationId = null;\n this.messages = [];\n }\n }\n\n toggleClientTool(name: string): boolean {\n if (this.enabledClientTools.has(name)) {\n this.enabledClientTools.delete(name);\n return false;\n }\n this.enabledClientTools.add(name);\n return true;\n }\n}\n","/**\n * Standard event handlers for BlockBuilder.\n *\n * These define the default event→block mapping rules. Clients import\n * and register them explicitly:\n *\n * import { BlockBuilder, standardHandlers } from \"@astralform/js\";\n * const builder = new BlockBuilder();\n * builder.registerHandlers(standardHandlers);\n */\n\nimport type {\n BlockBuilder,\n CapsuleBlock,\n EditorBlock,\n EventHandler,\n SubagentBlock,\n TextBlock,\n ThinkingBlock,\n TodoBlock,\n ToolBlock,\n UserBlock,\n} from \"./block-builder.js\";\nimport type { ChatEvent } from \"./types.js\";\n\n// ── Helpers ─────────────────────────────────────────────────────────\n\nfunction finalizeText(builder: BlockBuilder): void {\n if (builder.activeTextId) {\n builder.patchBlock(builder.activeTextId, {\n isStreaming: false,\n } as Partial<TextBlock>);\n builder.activeTextId = null;\n }\n}\n\nfunction finalizeThinking(builder: BlockBuilder): void {\n if (builder.activeThinkingId) {\n builder.patchBlock(builder.activeThinkingId, {\n isActive: false,\n } as Partial<ThinkingBlock>);\n builder.activeThinkingId = null;\n builder.thinkingStartMs = null;\n }\n}\n\nfunction finalizeEditor(builder: BlockBuilder): void {\n if (builder.activeEditorId) {\n builder.patchBlock(builder.activeEditorId, {\n isStreaming: false,\n } as Partial<EditorBlock>);\n builder.activeEditorId = null;\n }\n}\n\n// ── Text streaming ──────────────────────────────────────────────────\n\n// ── User message ────────────────────────────────────────────────────\n\nconst handleUserMessage: EventHandler = (event, builder) => {\n const e = event as ChatEvent & { type: \"user_message\" };\n // Skip if user block already exists (optimistic add from frontend),\n // but patch createdAt if the server provides it\n const existing = builder.findBlock((b) => b.type === \"user\");\n if (existing) {\n if (e.createdAt) {\n builder.patchBlock(existing.id, {\n createdAt: e.createdAt,\n } as Partial<UserBlock>);\n }\n return;\n }\n builder.addBlock({\n type: \"user\",\n id: builder.nextId(),\n content: e.content,\n createdAt: e.createdAt,\n });\n};\n\n// ── Text streaming ──────────────────────────────────────────────────\n\nconst handleChunk: EventHandler = (event, builder) => {\n const e = event as ChatEvent & { type: \"chunk\" };\n if (!builder.activeTextId) {\n const id = builder.nextId();\n builder.activeTextId = id;\n builder.addBlock({\n type: \"text\",\n id,\n content: e.text,\n isStreaming: true,\n });\n } else {\n const id = builder.activeTextId;\n const existing = builder.findBlock((b) => b.id === id);\n if (existing && existing.type === \"text\") {\n builder.patchBlock(id, {\n content: existing.content + e.text,\n } as Partial<TextBlock>);\n }\n }\n};\n\n// ── Tool calls ──────────────────────────────────────────────────────\n\nconst handleToolCall: EventHandler = (event, builder) => {\n const e = event as ChatEvent & { type: \"tool_call\" };\n finalizeText(builder);\n builder.addBlock({\n type: \"tool\",\n id: builder.nextId(),\n callId: e.request.callId,\n toolName: e.request.toolName,\n displayName: e.request.displayName,\n description: e.request.description,\n arguments: e.request.arguments,\n toolCategory: e.request.toolCategory,\n iconUrl: e.request.iconUrl,\n status: \"calling\",\n });\n};\n\nconst handleToolExecuting: EventHandler = (event, builder) => {\n const e = event as ChatEvent & { type: \"tool_executing\"; call_id?: string };\n const block = builder.findBlock(\n (b) =>\n b.type === \"tool\" &&\n (e.call_id ? b.callId === e.call_id : b.toolName === e.name) &&\n b.status === \"calling\",\n );\n if (block) {\n builder.patchBlock(block.id, { status: \"executing\" } as Partial<ToolBlock>);\n }\n};\n\nconst handleToolProgress: EventHandler = (event, builder) => {\n const e = event as ChatEvent & { type: \"tool_progress\" };\n const block = builder.findBlock(\n (b) => b.type === \"tool\" && b.callId === e.callId,\n );\n if (block && block.type === \"tool\") {\n const sources = block.sources ? [...block.sources] : [];\n sources.push(e.item);\n builder.patchBlock(block.id, {\n sources,\n status: \"executing\",\n } as Partial<ToolBlock>);\n }\n};\n\nconst handleToolEnd: EventHandler = (event, builder) => {\n const e = event as ChatEvent & { type: \"tool_completed\" | \"tool_end\" };\n const callId =\n e.type === \"tool_end\"\n ? (e as ChatEvent & { type: \"tool_end\" }).callId\n : undefined;\n const name =\n e.type === \"tool_end\"\n ? (e as ChatEvent & { type: \"tool_end\" }).toolName\n : (e as ChatEvent & { type: \"tool_completed\" }).name;\n\n const block = builder.findBlock(\n (b) =>\n b.type === \"tool\" &&\n (callId ? b.callId === callId : b.toolName === name) &&\n b.status !== \"completed\",\n );\n if (block) {\n const toolEnd =\n e.type === \"tool_end\" ? (e as ChatEvent & { type: \"tool_end\" }) : null;\n builder.patchBlock(block.id, {\n status: \"completed\",\n ...(toolEnd?.sources ? { sources: toolEnd.sources } : {}),\n ...(toolEnd?.durationMs != null\n ? { durationMs: toolEnd.durationMs }\n : {}),\n ...(toolEnd?.result ? { result: toolEnd.result } : {}),\n } as Partial<ToolBlock>);\n }\n};\n\n// ── Agent lifecycle ─────────────────────────────────────────────────\n\nconst handleAgentStart: EventHandler = (event, builder) => {\n const e = event as ChatEvent & { type: \"agent_start\" };\n finalizeText(builder);\n builder.addBlock({\n type: \"agent\",\n id: builder.nextId(),\n agentName: e.agentName,\n displayName: e.agentDisplayName,\n avatarUrl: e.avatarUrl,\n });\n};\n\n// ── Thinking ────────────────────────────────────────────────────────\n\nconst handleThinkingDelta: EventHandler = (event, builder) => {\n const e = event as ChatEvent & { type: \"thinking_delta\" };\n if (!builder.activeThinkingId) {\n const id = builder.nextId();\n builder.activeThinkingId = id;\n builder.thinkingStartMs = Date.now();\n builder.addBlock({\n type: \"thinking\",\n id,\n content: e.text,\n isActive: true,\n });\n } else {\n const id = builder.activeThinkingId;\n const existing = builder.findBlock((b) => b.id === id);\n if (existing && existing.type === \"thinking\") {\n builder.patchBlock(id, {\n content: existing.content + e.text,\n } as Partial<ThinkingBlock>);\n }\n }\n};\n\nconst handleThinkingComplete: EventHandler = (_event, builder) => {\n if (builder.activeThinkingId) {\n const durationMs = builder.thinkingStartMs\n ? Math.max(0, Date.now() - builder.thinkingStartMs)\n : undefined;\n builder.patchBlock(builder.activeThinkingId, {\n isActive: false,\n durationMs,\n } as Partial<ThinkingBlock>);\n builder.activeThinkingId = null;\n builder.thinkingStartMs = null;\n }\n};\n\n// ── Subagents ───────────────────────────────────────────────────────\n\nconst handleSubagentStart: EventHandler = (event, builder) => {\n const e = event as ChatEvent & { type: \"subagent_start\" };\n finalizeText(builder);\n builder.addBlock({\n type: \"subagent\",\n id: builder.nextId(),\n agentName: e.agentName,\n displayName: e.displayName,\n toolCallId: e.toolCallId,\n avatarUrl: e.avatarUrl,\n description: e.description,\n content: \"\",\n isActive: true,\n });\n};\n\nconst handleSubagentChunk: EventHandler = (event, builder) => {\n const e = event as ChatEvent & { type: \"subagent_chunk\" };\n const block = builder.findBlock(\n (b) => b.type === \"subagent\" && b.toolCallId === e.toolCallId,\n );\n if (block && block.type === \"subagent\") {\n builder.patchBlock(block.id, {\n content: block.content + e.text,\n } as Partial<SubagentBlock>);\n }\n};\n\nconst handleSubagentUpdate: EventHandler = (event, builder) => {\n const e = event as ChatEvent & { type: \"subagent_update\" };\n const block = builder.findBlock(\n (b) => b.type === \"subagent\" && b.toolCallId === e.toolCallId,\n );\n if (block) {\n builder.patchBlock(block.id, {\n displayName: e.displayName,\n } as Partial<SubagentBlock>);\n }\n};\n\nconst handleSubagentEnd: EventHandler = (event, builder) => {\n const e = event as ChatEvent & { type: \"subagent_end\" };\n const block = builder.findBlock(\n (b) => b.type === \"subagent\" && b.toolCallId === e.toolCallId,\n );\n if (block) {\n builder.patchBlock(block.id, {\n isActive: false,\n } as Partial<SubagentBlock>);\n }\n};\n\n// ── Completion / Error / Disconnect ─────────────────────────────────\n\nconst handleComplete: EventHandler = (_event, builder) => {\n finalizeText(builder);\n finalizeThinking(builder);\n finalizeEditor(builder);\n for (const b of builder.getBlocks()) {\n if (b.type === \"tool\" && b.status !== \"completed\") {\n builder.patchBlock(b.id, { status: \"completed\" } as Partial<ToolBlock>);\n }\n }\n};\n\nconst handleError: EventHandler = (event, builder) => {\n const e = event as ChatEvent & { type: \"error\" };\n finalizeText(builder);\n finalizeThinking(builder);\n builder.addBlock({\n type: \"error\",\n id: builder.nextId(),\n message: e.error.message,\n });\n};\n\nconst handleDisconnected: EventHandler = (_event, builder) => {\n finalizeText(builder);\n finalizeThinking(builder);\n finalizeEditor(builder);\n};\n\n// ── Capsule output ──────────────────────────────────────────────────\n\nconst handleCapsuleOutputChunk: EventHandler = (event, builder) => {\n const e = event as ChatEvent & { type: \"capsule_output_chunk\" };\n const block = builder.findBlock(\n (b) => b.type === \"capsule\" && b.callId === e.callId,\n );\n if (block && block.type === \"capsule\") {\n builder.patchBlock(block.id, {\n output: block.output + e.chunk,\n } as Partial<CapsuleBlock>);\n } else {\n builder.addBlock({\n type: \"capsule\",\n id: builder.nextId(),\n callId: e.callId,\n toolName: \"\",\n output: e.chunk,\n isActive: true,\n });\n }\n};\n\nconst handleCapsuleOutput: EventHandler = (event, builder) => {\n const e = event as ChatEvent & { type: \"capsule_output\" };\n const block = builder.findBlock(\n (b) => b.type === \"capsule\" && b.callId === (e.callId ?? \"\"),\n );\n if (block) {\n builder.patchBlock(block.id, {\n output: e.output,\n command: e.command,\n toolName: e.toolName,\n durationMs: e.durationMs,\n isActive: false,\n } as Partial<CapsuleBlock>);\n } else {\n builder.addBlock({\n type: \"capsule\",\n id: builder.nextId(),\n callId: e.callId ?? \"\",\n toolName: e.toolName,\n command: e.command,\n output: e.output,\n durationMs: e.durationMs,\n isActive: false,\n });\n }\n};\n\n// ── Assets ──────────────────────────────────────────────────────────\n\nconst handleAssetCreated: EventHandler = (event, builder) => {\n const e = event as ChatEvent & { type: \"asset_created\" };\n builder.addBlock({\n type: \"asset\",\n id: builder.nextId(),\n assetId: e.assetId,\n name: e.name,\n url: e.url,\n mediaType: e.mediaType,\n sizeBytes: e.sizeBytes,\n });\n};\n\n// ── Todos ───────────────────────────────────────────────────────────\n\nconst handleTodoUpdate: EventHandler = (event, builder) => {\n const e = event as ChatEvent & { type: \"todo_update\" };\n if (builder.activeTodoId) {\n builder.patchBlock(builder.activeTodoId, {\n todos: e.todos,\n } as Partial<TodoBlock>);\n } else {\n const id = builder.nextId();\n builder.activeTodoId = id;\n builder.addBlock({\n type: \"todo\",\n id,\n todos: e.todos,\n });\n }\n};\n\n// ── Editor content ──────────────────────────────────────────────────\n\nconst handleEditorContentStart: EventHandler = (event, builder) => {\n const e = event as ChatEvent & { type: \"editor_content_start\" };\n const id = builder.nextId();\n builder.activeEditorId = id;\n builder.addBlock({\n type: \"editor\",\n id,\n callId: e.callId,\n path: e.path,\n language: e.language,\n content: \"\",\n isStreaming: true,\n });\n};\n\nconst handleEditorContentDelta: EventHandler = (event, builder) => {\n const e = event as ChatEvent & { type: \"editor_content_delta\" };\n const block = builder.findBlock(\n (b) => b.type === \"editor\" && b.callId === e.callId,\n );\n if (block && block.type === \"editor\") {\n builder.patchBlock(block.id, {\n content: block.content + e.delta,\n } as Partial<EditorBlock>);\n }\n};\n\nconst handleEditorContentEnd: EventHandler = (event, builder) => {\n const e = event as ChatEvent & { type: \"editor_content_end\" };\n const block = builder.findBlock(\n (b) => b.type === \"editor\" && b.callId === e.callId,\n );\n if (block) {\n builder.patchBlock(block.id, {\n isStreaming: false,\n } as Partial<EditorBlock>);\n }\n builder.activeEditorId = null;\n};\n\n// ── Lifecycle no-ops (intentionally handled, no blocks produced) ────\n\nconst noop: EventHandler = () => {};\n\n// ── Exported handler map ────────────────────────────────────────────\n\nexport const standardHandlers: Record<string, EventHandler> = {\n user_message: handleUserMessage,\n chunk: handleChunk,\n tool_call: handleToolCall,\n tool_executing: handleToolExecuting,\n tool_progress: handleToolProgress,\n tool_completed: handleToolEnd,\n tool_end: handleToolEnd,\n agent_start: handleAgentStart,\n agent_end: noop,\n thinking_delta: handleThinkingDelta,\n thinking_complete: handleThinkingComplete,\n subagent_start: handleSubagentStart,\n subagent_chunk: handleSubagentChunk,\n subagent_update: handleSubagentUpdate,\n subagent_end: handleSubagentEnd,\n subagent_tool_use: noop,\n capsule_output: handleCapsuleOutput,\n capsule_output_chunk: handleCapsuleOutputChunk,\n asset_created: handleAssetCreated,\n todo_update: handleTodoUpdate,\n editor_content_start: handleEditorContentStart,\n editor_content_delta: handleEditorContentDelta,\n editor_content_end: handleEditorContentEnd,\n retry: noop,\n complete: handleComplete,\n error: handleError,\n disconnected: handleDisconnected,\n};\n","// --- Configuration ---\n\nexport interface AstralformConfig {\n apiKey: string;\n baseURL?: string;\n userId: string;\n fetch?: typeof globalThis.fetch;\n}\n\n// --- Event type constants ---\n\nexport const ChatEventType = {\n Connected: \"connected\",\n BlocksChanged: \"blocks_changed\",\n UserMessage: \"user_message\",\n TitleGenerated: \"title_generated\",\n ModelInfo: \"model_info\",\n Chunk: \"chunk\",\n ToolCall: \"tool_call\",\n ToolExecuting: \"tool_executing\",\n ToolProgress: \"tool_progress\",\n ToolCompleted: \"tool_completed\",\n ToolEnd: \"tool_end\",\n AgentStart: \"agent_start\",\n AgentEnd: \"agent_end\",\n ThinkingDelta: \"thinking_delta\",\n ThinkingComplete: \"thinking_complete\",\n SubagentStart: \"subagent_start\",\n SubagentChunk: \"subagent_chunk\",\n SubagentUpdate: \"subagent_update\",\n SubagentEnd: \"subagent_end\",\n SubagentToolUse: \"subagent_tool_use\",\n CapsuleOutput: \"capsule_output\",\n CapsuleOutputChunk: \"capsule_output_chunk\",\n AssetCreated: \"asset_created\",\n TodoUpdate: \"todo_update\",\n EditorContentStart: \"editor_content_start\",\n EditorContentDelta: \"editor_content_delta\",\n EditorContentEnd: \"editor_content_end\",\n Complete: \"complete\",\n Error: \"error\",\n Disconnected: \"disconnected\",\n Retry: \"retry\",\n} as const;\n\n// --- SSE Raw Events (from backend) ---\n\nexport interface UserMessageEvent {\n type: \"user_message\";\n content: string;\n created_at?: number;\n}\n\nexport interface TitleGeneratedEvent {\n type: \"title_generated\";\n title: string;\n}\n\nexport interface MessageStartEvent {\n type: \"message_start\";\n message_id: string;\n conversation_id: string;\n model_display_name?: string;\n agent_name?: string;\n agent_display_name?: string;\n}\n\nexport interface ContentBlockDeltaEvent {\n type: \"content_block_delta\";\n index: number;\n delta: {\n type: \"text_delta\";\n text: string;\n };\n}\n\nexport interface ToolUseStartEvent {\n type: \"tool_use_start\";\n index: number;\n call_id: string;\n tool: string;\n display_name?: string;\n description?: string;\n arguments: Record<string, unknown>;\n is_client_tool: boolean;\n tool_category?: string;\n icon_url?: string;\n}\n\nexport interface ToolUseEndEvent {\n type: \"tool_use_end\";\n call_id: string;\n tool: string;\n result?: string;\n sources?: { title: string; url: string; snippet?: string }[];\n duration_ms?: number;\n}\n\nexport interface ToolExecutingEvent {\n type: \"tool_executing\";\n call_id: string;\n tool: string;\n}\n\nexport interface ToolProgressEvent {\n type: \"tool_progress\";\n call_id: string;\n tool: string;\n index: number;\n total: number;\n item: { title: string; url: string; snippet?: string };\n}\n\nexport interface AgentStartEvent {\n type: \"agent_start\";\n agent_name: string;\n agent_display_name?: string;\n avatar_url?: string;\n}\n\nexport interface AgentEndEvent {\n type: \"agent_end\";\n agent_name: string;\n}\n\nexport interface SubagentStartEvent {\n type: \"subagent_start\";\n agent_name: string;\n display_name: string;\n tool_call_id: string;\n avatar_url?: string;\n description?: string;\n}\n\nexport interface SubagentContentDeltaEvent {\n type: \"subagent_content_delta\";\n agent_name: string;\n tool_call_id: string;\n delta: {\n type: \"text_delta\";\n text: string;\n };\n}\n\nexport interface SubagentUpdateEvent {\n type: \"subagent_update\";\n agent_name: string;\n display_name: string;\n tool_call_id: string;\n}\n\nexport interface SubagentEndEvent {\n type: \"subagent_end\";\n agent_name: string;\n display_name: string;\n tool_call_id: string;\n}\n\nexport interface ThinkingDeltaEvent {\n type: \"thinking_delta\";\n delta: {\n type: \"thinking\";\n text: string;\n };\n}\n\nexport interface ThinkingCompleteEvent {\n type: \"thinking_complete\";\n}\n\nexport interface CapsuleOutputEvent {\n type: \"capsule_output\";\n tool_name: string;\n agent_name: string;\n command?: string;\n output: string;\n duration_ms?: number;\n call_id?: string;\n}\n\nexport interface CapsuleOutputChunkEvent {\n type: \"capsule_output_chunk\";\n call_id: string;\n stream: \"stdout\" | \"stderr\";\n chunk: string;\n}\n\nexport interface TodoUpdateEvent {\n type: \"todo_update\";\n todos: TodoItem[];\n}\n\nexport interface MessageStopEvent {\n type: \"message_stop\";\n stop_reason: \"end_turn\" | \"tool_use\";\n title?: string;\n metrics?: Record<string, unknown>;\n job_id?: string;\n}\n\nexport interface SSEErrorEvent {\n type: \"error\";\n code: string;\n message: string;\n}\n\nexport interface SubagentToolUseEvent {\n type: \"subagent_tool_use\";\n agent_name: string;\n tool: string;\n tool_call_id: string;\n result?: string;\n}\n\nexport interface AssetCreatedEvent {\n type: \"asset_created\";\n asset_id: string;\n name: string;\n url: string;\n media_type: string;\n size_bytes: number;\n}\n\nexport interface EditorContentStartEvent {\n type: \"editor_content_start\";\n call_id: string;\n path: string;\n language: string;\n}\n\nexport interface EditorContentDeltaEvent {\n type: \"editor_content_delta\";\n call_id: string;\n path: string;\n delta: string;\n}\n\nexport interface EditorContentEndEvent {\n type: \"editor_content_end\";\n call_id: string;\n}\n\nexport interface RetryEvent {\n type: \"retry\";\n attempt: number;\n max_attempts: number;\n delay_seconds: number;\n}\n\nexport type SSEEvent =\n | MessageStartEvent\n | UserMessageEvent\n | TitleGeneratedEvent\n | ContentBlockDeltaEvent\n | ToolUseStartEvent\n | ToolUseEndEvent\n | ToolExecutingEvent\n | ToolProgressEvent\n | AgentStartEvent\n | AgentEndEvent\n | SubagentStartEvent\n | SubagentContentDeltaEvent\n | SubagentUpdateEvent\n | SubagentEndEvent\n | SubagentToolUseEvent\n | ThinkingDeltaEvent\n | ThinkingCompleteEvent\n | CapsuleOutputEvent\n | CapsuleOutputChunkEvent\n | TodoUpdateEvent\n | MessageStopEvent\n | AssetCreatedEvent\n | EditorContentStartEvent\n | EditorContentDeltaEvent\n | EditorContentEndEvent\n | RetryEvent\n | SSEErrorEvent;\n\n// --- High-Level Chat Events (SDK → consumer) ---\n\nexport type ChatEvent =\n | { type: \"connected\" }\n | { type: \"user_message\"; content: string; createdAt?: number }\n | { type: \"title_generated\"; title: string }\n | { type: \"chunk\"; text: string }\n | { type: \"tool_call\"; request: ToolCallRequest }\n | { type: \"tool_executing\"; name: string; call_id?: string }\n | { type: \"tool_completed\"; name: string; result: string }\n | {\n type: \"tool_progress\";\n callId: string;\n tool: string;\n index: number;\n total: number;\n item: { title: string; url: string; snippet?: string };\n }\n | {\n type: \"tool_end\";\n callId: string;\n toolName: string;\n result?: string;\n sources?: { title: string; url: string; snippet?: string }[];\n durationMs?: number;\n }\n | {\n type: \"agent_start\";\n agentName: string;\n agentDisplayName?: string;\n avatarUrl?: string;\n }\n | { type: \"agent_end\"; agentName: string }\n | { type: \"thinking_delta\"; text: string }\n | { type: \"thinking_complete\" }\n | {\n type: \"subagent_start\";\n agentName: string;\n displayName: string;\n toolCallId: string;\n avatarUrl?: string;\n description?: string;\n }\n | {\n type: \"subagent_chunk\";\n agentName: string;\n toolCallId: string;\n text: string;\n }\n | {\n type: \"subagent_update\";\n agentName: string;\n displayName: string;\n toolCallId: string;\n }\n | {\n type: \"subagent_end\";\n agentName: string;\n displayName: string;\n toolCallId: string;\n }\n | {\n type: \"capsule_output\";\n toolName: string;\n agentName: string;\n command?: string;\n output: string;\n durationMs?: number;\n callId?: string;\n }\n | {\n type: \"capsule_output_chunk\";\n callId: string;\n stream: \"stdout\" | \"stderr\";\n chunk: string;\n }\n | {\n type: \"todo_update\";\n todos: TodoItem[];\n }\n | {\n type: \"complete\";\n content: string;\n conversationId: string;\n messageId: string;\n title?: string;\n metrics?: Record<string, unknown>;\n job_id?: string;\n }\n | {\n type: \"subagent_tool_use\";\n agentName: string;\n toolName: string;\n toolCallId: string;\n result?: string;\n }\n | {\n type: \"asset_created\";\n assetId: string;\n name: string;\n url: string;\n mediaType: string;\n sizeBytes: number;\n }\n | {\n type: \"retry\";\n attempt: number;\n maxAttempts: number;\n delaySeconds: number;\n }\n | {\n type: \"editor_content_start\";\n callId: string;\n path: string;\n language: string;\n }\n | {\n type: \"editor_content_delta\";\n callId: string;\n path: string;\n delta: string;\n }\n | { type: \"editor_content_end\"; callId: string }\n | { type: \"model_info\"; name: string }\n | { type: \"blocks_changed\"; blocks: import(\"./block-builder.js\").Block[] }\n | { type: \"error\"; error: Error }\n | { type: \"disconnected\" };\n\n// --- Domain Models ---\n\nexport interface Conversation {\n id: string;\n title: string;\n messageCount: number;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface Message {\n id: string;\n conversationId: string;\n role: \"user\" | \"assistant\" | \"system\";\n content: string;\n parentId?: string;\n status: \"sending\" | \"streaming\" | \"complete\" | \"error\";\n createdAt: string;\n toolCalls?: ToolCallRequest[];\n}\n\nexport interface ProjectStatus {\n isReady: boolean;\n llmConfigured: boolean;\n llmProvider?: string;\n llmModel?: string;\n message: string;\n}\n\nexport interface AgentInfo {\n name: string;\n displayName: string;\n description: string;\n isOrchestrator: boolean;\n isEnabled: boolean;\n avatarUrl?: string;\n}\n\nexport interface SkillInfo {\n name: string;\n displayName: string;\n description: string;\n isEnabled: boolean;\n}\n\n// --- State Tracking Types ---\n\nexport interface SubagentState {\n agentName: string;\n displayName: string;\n avatarUrl?: string;\n description?: string;\n content: string;\n isActive: boolean;\n}\n\nexport interface ToolState {\n toolName: string;\n displayName?: string;\n description?: string;\n arguments?: Record<string, unknown>;\n callId: string;\n status: \"calling\" | \"executing\" | \"completed\";\n isClientTool: boolean;\n}\n\nexport interface CapsuleOutput {\n toolName: string;\n agentName: string;\n command?: string;\n output: string;\n durationMs?: number;\n callId?: string;\n}\n\nexport interface Source {\n title: string;\n url: string;\n}\n\nexport interface TodoItem {\n content: string;\n status: \"pending\" | \"in_progress\" | \"completed\";\n id?: string;\n}\n\n// --- Job Types ---\n\nexport interface JobCreateResponse {\n job_id: string;\n conversation_id: string;\n message_id: string;\n status: string;\n}\n\n// --- Request Types ---\n\nexport interface ChatStreamRequest {\n message?: string;\n conversation_id?: string;\n mcp_manifest?: ToolDefinition[];\n enabled_mcp?: string[];\n continue_from_message?: string;\n resend_from?: string;\n upload_ids?: string[];\n agent_name?: string;\n enable_search?: boolean;\n}\n\nexport interface ToolResultRequest {\n conversation_id: string;\n message_id: string;\n tool_results: ToolResult[];\n}\n\nexport interface ToolResult {\n call_id: string;\n tool_name: string;\n result: string;\n is_error: boolean;\n}\n\nexport interface ToolDefinition {\n name: string;\n description: string;\n parameters: Record<string, unknown>;\n}\n\nexport interface ToolCallRequest {\n callId: string;\n toolName: string;\n displayName?: string;\n description?: string;\n arguments: Record<string, unknown>;\n isClientTool: boolean;\n toolCategory?: string;\n iconUrl?: string;\n}\n\n// --- SSE Stream Options ---\n\nexport interface StreamJobSSEOptions {\n url: string;\n headers: Record<string, string>;\n signal?: AbortSignal;\n fetchFn: typeof globalThis.fetch;\n}\n\n// --- Chat Stream Event (raw SSE parsed) ---\n\nexport interface ChatStreamEvent {\n event: string;\n data: string;\n}\n\nexport interface ConversationEvent {\n seq: number;\n event: string;\n data: Record<string, unknown>;\n}\n\n// --- Send Options ---\n\nexport interface SendOptions {\n conversationId?: string;\n enabledClientTools?: string[];\n uploadIds?: string[];\n agentName?: string;\n enableSearch?: boolean;\n}\n\n// --- Conversation Assets ---\n\nexport interface ConversationAsset {\n id: string;\n kind: \"upload\" | \"output\";\n originalName: string;\n mediaType: string;\n sizeBytes: number;\n workspacePath?: string;\n sourceMessageId?: string;\n agentName?: string;\n createdAt: string;\n}\n","/**\n * StreamManager — high-level conversation lifecycle coordinator.\n *\n * Sits on top of ChatSession and manages the state machine for\n * multi-conversation SSE streaming. Framework-agnostic: emits\n * callbacks instead of writing to any state management library.\n *\n * import { ChatSession, StreamManager } from \"@astralform/js\";\n * const session = new ChatSession({ ... });\n * const manager = new StreamManager(session);\n * manager.on(\"blocksChanged\", (convId, blocks) => { ... });\n * await manager.send(\"Hello\");\n */\n\nimport type { ChatEvent } from \"./types.js\";\nimport type { Block } from \"./block-builder.js\";\nimport { ChatEventType } from \"./types.js\";\nimport type { ChatSession } from \"./session.js\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport type StreamState = \"idle\" | \"streaming\" | \"restoring\" | \"detached\";\n\nexport interface SendOptions {\n enableSearch?: boolean;\n agentName?: string;\n uploadIds?: string[];\n}\n\nexport type StreamManagerEvent =\n | { type: \"stateChange\"; state: StreamState; conversationId: string | null }\n | { type: \"blocksChanged\"; conversationId: string; blocks: Block[] }\n | { type: \"conversationChanged\"; conversationId: string | null }\n | {\n type: \"backgroundJobsChanged\";\n jobs: ReadonlyMap<string, string>;\n }\n | { type: \"event\"; conversationId: string | null; event: ChatEvent }\n | { type: \"versionsReady\"; conversationId: string; count: number };\n\ntype EventHandler = (event: StreamManagerEvent) => void;\n\n// =============================================================================\n// StreamManager\n// =============================================================================\n\nexport class StreamManager {\n private session: ChatSession;\n private _state: StreamState = \"idle\";\n private _activeConversationId: string | null = null;\n private _backgroundJobs = new Map<string, string>();\n private handlers: EventHandler[] = [];\n private unsub: (() => void) | null = null;\n\n constructor(session: ChatSession) {\n this.session = session;\n this.attach();\n }\n\n // ── Public state ──────────────────────────────────────────────\n\n get state(): StreamState {\n return this._state;\n }\n\n get activeConversationId(): string | null {\n return this._activeConversationId;\n }\n\n get backgroundJobs(): ReadonlyMap<string, string> {\n return this._backgroundJobs;\n }\n\n // ── Event subscription ────────────────────────────────────────\n\n on(handler: EventHandler): () => void {\n this.handlers.push(handler);\n return () => {\n this.handlers = this.handlers.filter((h) => h !== handler);\n };\n }\n\n private emit(event: StreamManagerEvent): void {\n for (const handler of this.handlers) {\n try {\n handler(event);\n } catch {\n // Don't let handler errors crash the manager\n }\n }\n }\n\n private setState(state: StreamState): void {\n this._state = state;\n this.emit({\n type: \"stateChange\",\n state,\n conversationId: this._activeConversationId,\n });\n }\n\n // ── Session event wiring ──────────────────────────────────────\n\n private attach(): void {\n this.unsub = this.session.on((event: ChatEvent) => {\n this.onSessionEvent(event);\n });\n }\n\n private onSessionEvent(event: ChatEvent): void {\n const convId = this.session.conversationId;\n\n // blocks_changed: only emit during active streaming\n if (event.type === ChatEventType.BlocksChanged) {\n if (this._state === \"streaming\" && convId) {\n this.emit({\n type: \"blocksChanged\",\n conversationId: convId,\n blocks: (event as ChatEvent & { blocks: Block[] }).blocks,\n });\n }\n return;\n }\n\n // Forward all other events to subscribers\n this.emit({\n type: \"event\",\n conversationId: convId,\n event,\n });\n\n // Handle completion\n if (event.type === ChatEventType.Complete) {\n if (this._state === \"streaming\") {\n this.setState(\"idle\");\n }\n }\n }\n\n // ── Send ──────────────────────────────────────────────────────\n\n async send(content: string, options?: SendOptions): Promise<void> {\n if (this._state === \"streaming\") return;\n\n // Auto-create conversation if none active\n if (!this._activeConversationId) {\n const id = await this.session.createNewConversation();\n this.setActiveConversation(id);\n }\n\n this.prepareUserBlock(content);\n this.setState(\"streaming\");\n\n try {\n await this.session.send(content, {\n enableSearch: options?.enableSearch,\n agentName: options?.agentName,\n uploadIds: options?.uploadIds,\n });\n } catch {\n // AbortError from detach is expected\n }\n\n this.finalizeStream();\n }\n\n // ── Regenerate ────────────────────────────────────────────────\n\n async regenerate(): Promise<void> {\n if (this._state === \"streaming\") return;\n\n const userMsgs = this.session.messages.filter(\n (m: { role: string }) => m.role === \"user\",\n );\n const lastUserMsg = userMsgs[userMsgs.length - 1];\n if (!lastUserMsg) return;\n\n this.prepareUserBlock(lastUserMsg.content);\n this.setState(\"streaming\");\n\n try {\n await this.session.resendFromCheckpoint(\n lastUserMsg.id,\n lastUserMsg.content,\n );\n } catch {\n // AbortError from detach is expected\n }\n\n this.finalizeStream();\n }\n\n // ── Switch conversation ───────────────────────────────────────\n\n async switchTo(conversationId: string): Promise<void> {\n if (conversationId === this._activeConversationId) return;\n\n // If streaming, detach (job keeps running in background)\n if (this._state === \"streaming\") {\n const oldConvId = this._activeConversationId;\n const jobId = this.session.currentJobId;\n if (oldConvId && jobId) {\n this._backgroundJobs.set(oldConvId, jobId);\n this.emit({\n type: \"backgroundJobsChanged\",\n jobs: this._backgroundJobs,\n });\n }\n this.session.detach();\n }\n\n // Clear background job for target (we're viewing it now)\n if (this._backgroundJobs.has(conversationId)) {\n this._backgroundJobs.delete(conversationId);\n this.emit({\n type: \"backgroundJobsChanged\",\n jobs: this._backgroundJobs,\n });\n }\n\n this.setActiveConversation(conversationId);\n await this.restore(conversationId);\n }\n\n // ── Create / delete conversation ──────────────────────────────\n\n async createConversation(): Promise<string> {\n const id = await this.session.createNewConversation();\n this.setActiveConversation(id);\n return id;\n }\n\n async deleteConversation(id: string): Promise<void> {\n await this.session.deleteConversation(id);\n this._backgroundJobs.delete(id);\n if (this._activeConversationId === id) {\n this._activeConversationId = null;\n this.emit({ type: \"conversationChanged\", conversationId: null });\n }\n }\n\n // ── Stop (explicit cancel) ────────────────────────────────────\n\n stop(): void {\n this.session.disconnect();\n this.setState(\"idle\");\n }\n\n // ── Cleanup ───────────────────────────────────────────────────\n\n destroy(): void {\n if (this.unsub) {\n this.unsub();\n this.unsub = null;\n }\n this.handlers = [];\n }\n\n // ── Internal: helpers ──────────────────────────────────────────\n\n private prepareUserBlock(content: string): void {\n this.session.blockBuilder.reset();\n this.session.blockBuilder.addBlock({\n type: \"user\",\n id: this.session.blockBuilder.nextId(),\n content,\n });\n }\n\n private finalizeStream(): void {\n if (this._state === \"streaming\") {\n this.setState(\"idle\");\n }\n }\n\n // ── Internal: restore ─────────────────────────────────────────\n\n private async restore(conversationId: string): Promise<void> {\n this.setState(\"restoring\");\n\n // Check for active job\n let activeJobId: string | null = null;\n try {\n const res = await this.session.client.get<{\n job_id: string | null;\n status: string;\n }>(`/v1/conversations/${encodeURIComponent(conversationId)}/active-job`);\n activeJobId = res.job_id ?? null;\n } catch {\n // Network error — assume no active job\n }\n\n if (activeJobId) {\n // Active job: load messages, reconnect to live SSE\n await this.session.loadConversation(conversationId);\n this.setState(\"streaming\");\n try {\n await this.session.reconnectToJob(activeJobId);\n } catch {\n // Stream ended or aborted\n }\n if (this._state === \"streaming\") {\n this.setState(\"idle\");\n }\n } else {\n // Completed: load messages, replay version chain\n await this.session.loadConversation(conversationId);\n\n try {\n const jobs = await this.session.client.get<\n {\n job_id: string;\n status: string;\n metrics?: Record<string, unknown>;\n }[]\n >(`/v1/conversations/${encodeURIComponent(conversationId)}/jobs`);\n const completedJobs = jobs.filter(\n (j: { status: string }) => j.status === \"completed\",\n );\n\n for (const job of completedJobs) {\n await this.session.switchConversation(conversationId, job.job_id);\n }\n\n // Emit final blocks for the last version\n if (completedJobs.length > 0) {\n this.emit({\n type: \"blocksChanged\",\n conversationId,\n blocks: this.session.blockBuilder.getBlocks(),\n });\n this.emit({\n type: \"versionsReady\",\n conversationId,\n count: completedJobs.length,\n });\n }\n } catch {\n // Version chain loading failed — non-blocking\n }\n\n this.setState(\"idle\");\n }\n }\n\n // ── Internal: set active conversation ─────────────────────────\n\n private setActiveConversation(id: string): void {\n this._activeConversationId = id;\n this.emit({ type: \"conversationChanged\", conversationId: id });\n }\n}\n"],"mappings":"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","names":[]}