@astralform/js 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -612,7 +612,8 @@ var ChatSession = class {
612
612
  options?.enabledClientTools ?? this.enabledClientTools
613
613
  ),
614
614
  upload_ids: options?.uploadIds,
615
- agent_name: options?.agentName
615
+ agent_name: options?.agentName,
616
+ enable_search: options?.enableSearch
616
617
  };
617
618
  await this.processStream(request);
618
619
  }
@@ -714,7 +715,9 @@ var ChatSession = class {
714
715
  displayName: parsed.display_name,
715
716
  description: parsed.description,
716
717
  arguments: parsed.arguments,
717
- isClientTool: parsed.is_client_tool
718
+ isClientTool: parsed.is_client_tool,
719
+ toolCategory: parsed.tool_category,
720
+ iconUrl: parsed.icon_url
718
721
  }
719
722
  ]);
720
723
  await this.client.submitToolResult({
@@ -784,7 +787,9 @@ var ChatSession = class {
784
787
  displayName: event.display_name,
785
788
  description: event.description,
786
789
  arguments: event.arguments,
787
- isClientTool: event.is_client_tool
790
+ isClientTool: event.is_client_tool,
791
+ toolCategory: event.tool_category,
792
+ iconUrl: event.icon_url
788
793
  };
789
794
  this.activeTools.set(event.call_id, {
790
795
  ...request,
@@ -910,6 +915,42 @@ var ChatSession = class {
910
915
  sizeBytes: event.size_bytes
911
916
  });
912
917
  break;
918
+ case "activity":
919
+ this.emit({
920
+ type: "activity",
921
+ activityId: event.activity_id,
922
+ status: event.status,
923
+ category: event.category,
924
+ title: event.title,
925
+ detail: event.detail,
926
+ sources: event.sources,
927
+ toolName: event.tool_name,
928
+ agentName: event.agent_name,
929
+ durationMs: event.duration_ms
930
+ });
931
+ break;
932
+ case "editor_content_start":
933
+ this.emit({
934
+ type: "editor_content_start",
935
+ callId: event.call_id,
936
+ path: event.path,
937
+ language: event.language
938
+ });
939
+ break;
940
+ case "editor_content_delta":
941
+ this.emit({
942
+ type: "editor_content_delta",
943
+ callId: event.call_id,
944
+ path: event.path,
945
+ delta: event.delta
946
+ });
947
+ break;
948
+ case "editor_content_end":
949
+ this.emit({
950
+ type: "editor_content_end",
951
+ callId: event.call_id
952
+ });
953
+ break;
913
954
  }
914
955
  }
915
956
  async executeClientTools(toolCalls) {
@@ -1005,7 +1046,7 @@ var ChatSession = class {
1005
1046
  * Skips text deltas (final content is already in messages[]).
1006
1047
  */
1007
1048
  replayEvent(eventType, data) {
1008
- if (eventType === "content_block_delta" || eventType === "thinking_delta" || eventType === "subagent_content_delta" || eventType === "thinking_complete") {
1049
+ if (eventType === "content_block_delta" || eventType === "thinking_delta" || eventType === "subagent_content_delta" || eventType === "thinking_complete" || eventType === "editor_content_start" || eventType === "editor_content_delta" || eventType === "editor_content_end") {
1009
1050
  return;
1010
1051
  }
1011
1052
  this.applyEvent({ type: eventType, ...data });
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/streaming.ts","../src/client.ts","../src/storage.ts","../src/tools.ts","../src/utils.ts","../src/session.ts"],"sourcesContent":["// Core classes\nexport { AstralformClient } from \"./client.js\";\nexport { ChatSession } from \"./session.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","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 { 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\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(config: AstralformConfig, storage?: ChatStorage) {\n this.client = new AstralformClient(config);\n this.toolRegistry = new ToolRegistry();\n this.storage = storage ?? new InMemoryStorage();\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 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 };\n\n await this.processStream(request);\n }\n\n async resendFromCheckpoint(\n messageId: string,\n newContent: string,\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 };\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 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 // Step 1: Create job\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 let stopTitle: string | undefined;\n\n // Step 2: Stream events\n const stream = this.client.streamJobEvents(\n job.job_id,\n this.lastSeq,\n this.abortController?.signal,\n );\n\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 // Track seq even for non-typed events (e.g. ping)\n if (typeof data?.seq === \"number\") {\n this.lastSeq = data.seq;\n }\n continue;\n }\n parsed = data as SSEEvent;\n // Track seq from every event\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.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 (parsed.is_client_tool) {\n // Execute tool and submit result — job auto-resumes\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 },\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 stopTitle = parsed.title;\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 this.currentJobId = null;\n await this.completeStream(conversationId, messageId, stopTitle);\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 \"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 };\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 });\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 }\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 ): 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 });\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\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 if (eventsResult.status === \"fulfilled\") {\n for (const ev of eventsResult.value) {\n this.replayEvent(ev.event, ev.data);\n }\n }\n }\n\n /**\n * Replay a single persisted event to reconstruct session state.\n * Skips text deltas (final content is already in messages[]).\n */\n private replayEvent(eventType: string, data: Record<string, unknown>): void {\n if (\n eventType === \"content_block_delta\" ||\n eventType === \"thinking_delta\" ||\n eventType === \"subagent_content_delta\" ||\n eventType === \"thinking_complete\"\n ) {\n return;\n }\n this.applyEvent({ type: eventType, ...data } as SSEEvent);\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"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/streaming.ts","../src/client.ts","../src/storage.ts","../src/tools.ts","../src/utils.ts","../src/session.ts"],"sourcesContent":["// Core classes\nexport { AstralformClient } from \"./client.js\";\nexport { ChatSession } from \"./session.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","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 { 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\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(config: AstralformConfig, storage?: ChatStorage) {\n this.client = new AstralformClient(config);\n this.toolRegistry = new ToolRegistry();\n this.storage = storage ?? new InMemoryStorage();\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 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 ): 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 };\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 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 // Step 1: Create job\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 let stopTitle: string | undefined;\n\n // Step 2: Stream events\n const stream = this.client.streamJobEvents(\n job.job_id,\n this.lastSeq,\n this.abortController?.signal,\n );\n\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 // Track seq even for non-typed events (e.g. ping)\n if (typeof data?.seq === \"number\") {\n this.lastSeq = data.seq;\n }\n continue;\n }\n parsed = data as SSEEvent;\n // Track seq from every event\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.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 (parsed.is_client_tool) {\n // Execute tool and submit result — job auto-resumes\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 stopTitle = parsed.title;\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 this.currentJobId = null;\n await this.completeStream(conversationId, messageId, stopTitle);\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 \"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 });\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 \"activity\":\n this.emit({\n type: \"activity\",\n activityId: event.activity_id,\n status: event.status,\n category: event.category,\n title: event.title,\n detail: event.detail,\n sources: event.sources,\n toolName: event.tool_name,\n agentName: event.agent_name,\n durationMs: event.duration_ms,\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 ): 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 });\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\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 if (eventsResult.status === \"fulfilled\") {\n for (const ev of eventsResult.value) {\n this.replayEvent(ev.event, ev.data);\n }\n }\n }\n\n /**\n * Replay a single persisted event to reconstruct session state.\n * Skips text deltas (final content is already in messages[]).\n */\n private replayEvent(eventType: string, data: Record<string, unknown>): void {\n if (\n eventType === \"content_block_delta\" ||\n eventType === \"thinking_delta\" ||\n eventType === \"subagent_content_delta\" ||\n eventType === \"thinking_complete\" ||\n eventType === \"editor_content_start\" ||\n eventType === \"editor_content_delta\" ||\n eventType === \"editor_content_end\"\n ) {\n return;\n }\n this.applyEvent({ type: eventType, ...data } as SSEEvent);\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"],"mappings":"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","names":[]}
package/dist/index.d.cts CHANGED
@@ -29,6 +29,8 @@ interface ToolUseStartEvent {
29
29
  description?: string;
30
30
  arguments: Record<string, unknown>;
31
31
  is_client_tool: boolean;
32
+ tool_category?: string;
33
+ icon_url?: string;
32
34
  }
33
35
  interface ToolUseEndEvent {
34
36
  type: "tool_use_end";
@@ -136,13 +138,45 @@ interface AssetCreatedEvent {
136
138
  media_type: string;
137
139
  size_bytes: number;
138
140
  }
141
+ interface ActivitySSEEvent {
142
+ type: "activity";
143
+ activity_id: string;
144
+ status: "started" | "completed";
145
+ category: string;
146
+ title: string;
147
+ detail?: string;
148
+ sources?: Array<{
149
+ title: string;
150
+ url: string;
151
+ snippet?: string;
152
+ }>;
153
+ tool_name?: string;
154
+ agent_name?: string;
155
+ duration_ms?: number;
156
+ }
157
+ interface EditorContentStartEvent {
158
+ type: "editor_content_start";
159
+ call_id: string;
160
+ path: string;
161
+ language: string;
162
+ }
163
+ interface EditorContentDeltaEvent {
164
+ type: "editor_content_delta";
165
+ call_id: string;
166
+ path: string;
167
+ delta: string;
168
+ }
169
+ interface EditorContentEndEvent {
170
+ type: "editor_content_end";
171
+ call_id: string;
172
+ }
139
173
  interface RetryEvent {
140
174
  type: "retry";
141
175
  attempt: number;
142
176
  max_attempts: number;
143
177
  delay_seconds: number;
144
178
  }
145
- type SSEEvent = MessageStartEvent | ContentBlockDeltaEvent | ToolUseStartEvent | ToolUseEndEvent | AgentStartEvent | AgentEndEvent | SubagentStartEvent | SubagentContentDeltaEvent | SubagentUpdateEvent | SubagentEndEvent | SubagentToolUseEvent | ThinkingDeltaEvent | ThinkingCompleteEvent | SourcesEvent | CapsuleOutputEvent | CapsuleOutputChunkEvent | TodoUpdateEvent | MessageStopEvent | AssetCreatedEvent | RetryEvent | SSEErrorEvent;
179
+ type SSEEvent = MessageStartEvent | ContentBlockDeltaEvent | ToolUseStartEvent | ToolUseEndEvent | AgentStartEvent | AgentEndEvent | SubagentStartEvent | SubagentContentDeltaEvent | SubagentUpdateEvent | SubagentEndEvent | SubagentToolUseEvent | ThinkingDeltaEvent | ThinkingCompleteEvent | SourcesEvent | CapsuleOutputEvent | CapsuleOutputChunkEvent | TodoUpdateEvent | MessageStopEvent | AssetCreatedEvent | ActivitySSEEvent | EditorContentStartEvent | EditorContentDeltaEvent | EditorContentEndEvent | RetryEvent | SSEErrorEvent;
146
180
  type ChatEvent = {
147
181
  type: "connected";
148
182
  } | {
@@ -244,6 +278,34 @@ type ChatEvent = {
244
278
  attempt: number;
245
279
  maxAttempts: number;
246
280
  delaySeconds: number;
281
+ } | {
282
+ type: "activity";
283
+ activityId: string;
284
+ status: "started" | "completed";
285
+ category: string;
286
+ title: string;
287
+ detail?: string;
288
+ sources?: Array<{
289
+ title: string;
290
+ url: string;
291
+ snippet?: string;
292
+ }>;
293
+ toolName?: string;
294
+ agentName?: string;
295
+ durationMs?: number;
296
+ } | {
297
+ type: "editor_content_start";
298
+ callId: string;
299
+ path: string;
300
+ language: string;
301
+ } | {
302
+ type: "editor_content_delta";
303
+ callId: string;
304
+ path: string;
305
+ delta: string;
306
+ } | {
307
+ type: "editor_content_end";
308
+ callId: string;
247
309
  } | {
248
310
  type: "model_info";
249
311
  name: string;
@@ -340,6 +402,7 @@ interface ChatStreamRequest {
340
402
  resend_from?: string;
341
403
  upload_ids?: string[];
342
404
  agent_name?: string;
405
+ enable_search?: boolean;
343
406
  }
344
407
  interface ToolResultRequest {
345
408
  conversation_id: string;
@@ -364,6 +427,8 @@ interface ToolCallRequest {
364
427
  description?: string;
365
428
  arguments: Record<string, unknown>;
366
429
  isClientTool: boolean;
430
+ toolCategory?: string;
431
+ iconUrl?: string;
367
432
  }
368
433
  interface StreamJobSSEOptions {
369
434
  url: string;
@@ -385,6 +450,7 @@ interface SendOptions {
385
450
  enabledClientTools?: string[];
386
451
  uploadIds?: string[];
387
452
  agentName?: string;
453
+ enableSearch?: boolean;
388
454
  }
389
455
  interface ConversationAsset {
390
456
  id: string;
package/dist/index.d.ts CHANGED
@@ -29,6 +29,8 @@ interface ToolUseStartEvent {
29
29
  description?: string;
30
30
  arguments: Record<string, unknown>;
31
31
  is_client_tool: boolean;
32
+ tool_category?: string;
33
+ icon_url?: string;
32
34
  }
33
35
  interface ToolUseEndEvent {
34
36
  type: "tool_use_end";
@@ -136,13 +138,45 @@ interface AssetCreatedEvent {
136
138
  media_type: string;
137
139
  size_bytes: number;
138
140
  }
141
+ interface ActivitySSEEvent {
142
+ type: "activity";
143
+ activity_id: string;
144
+ status: "started" | "completed";
145
+ category: string;
146
+ title: string;
147
+ detail?: string;
148
+ sources?: Array<{
149
+ title: string;
150
+ url: string;
151
+ snippet?: string;
152
+ }>;
153
+ tool_name?: string;
154
+ agent_name?: string;
155
+ duration_ms?: number;
156
+ }
157
+ interface EditorContentStartEvent {
158
+ type: "editor_content_start";
159
+ call_id: string;
160
+ path: string;
161
+ language: string;
162
+ }
163
+ interface EditorContentDeltaEvent {
164
+ type: "editor_content_delta";
165
+ call_id: string;
166
+ path: string;
167
+ delta: string;
168
+ }
169
+ interface EditorContentEndEvent {
170
+ type: "editor_content_end";
171
+ call_id: string;
172
+ }
139
173
  interface RetryEvent {
140
174
  type: "retry";
141
175
  attempt: number;
142
176
  max_attempts: number;
143
177
  delay_seconds: number;
144
178
  }
145
- type SSEEvent = MessageStartEvent | ContentBlockDeltaEvent | ToolUseStartEvent | ToolUseEndEvent | AgentStartEvent | AgentEndEvent | SubagentStartEvent | SubagentContentDeltaEvent | SubagentUpdateEvent | SubagentEndEvent | SubagentToolUseEvent | ThinkingDeltaEvent | ThinkingCompleteEvent | SourcesEvent | CapsuleOutputEvent | CapsuleOutputChunkEvent | TodoUpdateEvent | MessageStopEvent | AssetCreatedEvent | RetryEvent | SSEErrorEvent;
179
+ type SSEEvent = MessageStartEvent | ContentBlockDeltaEvent | ToolUseStartEvent | ToolUseEndEvent | AgentStartEvent | AgentEndEvent | SubagentStartEvent | SubagentContentDeltaEvent | SubagentUpdateEvent | SubagentEndEvent | SubagentToolUseEvent | ThinkingDeltaEvent | ThinkingCompleteEvent | SourcesEvent | CapsuleOutputEvent | CapsuleOutputChunkEvent | TodoUpdateEvent | MessageStopEvent | AssetCreatedEvent | ActivitySSEEvent | EditorContentStartEvent | EditorContentDeltaEvent | EditorContentEndEvent | RetryEvent | SSEErrorEvent;
146
180
  type ChatEvent = {
147
181
  type: "connected";
148
182
  } | {
@@ -244,6 +278,34 @@ type ChatEvent = {
244
278
  attempt: number;
245
279
  maxAttempts: number;
246
280
  delaySeconds: number;
281
+ } | {
282
+ type: "activity";
283
+ activityId: string;
284
+ status: "started" | "completed";
285
+ category: string;
286
+ title: string;
287
+ detail?: string;
288
+ sources?: Array<{
289
+ title: string;
290
+ url: string;
291
+ snippet?: string;
292
+ }>;
293
+ toolName?: string;
294
+ agentName?: string;
295
+ durationMs?: number;
296
+ } | {
297
+ type: "editor_content_start";
298
+ callId: string;
299
+ path: string;
300
+ language: string;
301
+ } | {
302
+ type: "editor_content_delta";
303
+ callId: string;
304
+ path: string;
305
+ delta: string;
306
+ } | {
307
+ type: "editor_content_end";
308
+ callId: string;
247
309
  } | {
248
310
  type: "model_info";
249
311
  name: string;
@@ -340,6 +402,7 @@ interface ChatStreamRequest {
340
402
  resend_from?: string;
341
403
  upload_ids?: string[];
342
404
  agent_name?: string;
405
+ enable_search?: boolean;
343
406
  }
344
407
  interface ToolResultRequest {
345
408
  conversation_id: string;
@@ -364,6 +427,8 @@ interface ToolCallRequest {
364
427
  description?: string;
365
428
  arguments: Record<string, unknown>;
366
429
  isClientTool: boolean;
430
+ toolCategory?: string;
431
+ iconUrl?: string;
367
432
  }
368
433
  interface StreamJobSSEOptions {
369
434
  url: string;
@@ -385,6 +450,7 @@ interface SendOptions {
385
450
  enabledClientTools?: string[];
386
451
  uploadIds?: string[];
387
452
  agentName?: string;
453
+ enableSearch?: boolean;
388
454
  }
389
455
  interface ConversationAsset {
390
456
  id: string;
package/dist/index.js CHANGED
@@ -574,7 +574,8 @@ var ChatSession = class {
574
574
  options?.enabledClientTools ?? this.enabledClientTools
575
575
  ),
576
576
  upload_ids: options?.uploadIds,
577
- agent_name: options?.agentName
577
+ agent_name: options?.agentName,
578
+ enable_search: options?.enableSearch
578
579
  };
579
580
  await this.processStream(request);
580
581
  }
@@ -676,7 +677,9 @@ var ChatSession = class {
676
677
  displayName: parsed.display_name,
677
678
  description: parsed.description,
678
679
  arguments: parsed.arguments,
679
- isClientTool: parsed.is_client_tool
680
+ isClientTool: parsed.is_client_tool,
681
+ toolCategory: parsed.tool_category,
682
+ iconUrl: parsed.icon_url
680
683
  }
681
684
  ]);
682
685
  await this.client.submitToolResult({
@@ -746,7 +749,9 @@ var ChatSession = class {
746
749
  displayName: event.display_name,
747
750
  description: event.description,
748
751
  arguments: event.arguments,
749
- isClientTool: event.is_client_tool
752
+ isClientTool: event.is_client_tool,
753
+ toolCategory: event.tool_category,
754
+ iconUrl: event.icon_url
750
755
  };
751
756
  this.activeTools.set(event.call_id, {
752
757
  ...request,
@@ -872,6 +877,42 @@ var ChatSession = class {
872
877
  sizeBytes: event.size_bytes
873
878
  });
874
879
  break;
880
+ case "activity":
881
+ this.emit({
882
+ type: "activity",
883
+ activityId: event.activity_id,
884
+ status: event.status,
885
+ category: event.category,
886
+ title: event.title,
887
+ detail: event.detail,
888
+ sources: event.sources,
889
+ toolName: event.tool_name,
890
+ agentName: event.agent_name,
891
+ durationMs: event.duration_ms
892
+ });
893
+ break;
894
+ case "editor_content_start":
895
+ this.emit({
896
+ type: "editor_content_start",
897
+ callId: event.call_id,
898
+ path: event.path,
899
+ language: event.language
900
+ });
901
+ break;
902
+ case "editor_content_delta":
903
+ this.emit({
904
+ type: "editor_content_delta",
905
+ callId: event.call_id,
906
+ path: event.path,
907
+ delta: event.delta
908
+ });
909
+ break;
910
+ case "editor_content_end":
911
+ this.emit({
912
+ type: "editor_content_end",
913
+ callId: event.call_id
914
+ });
915
+ break;
875
916
  }
876
917
  }
877
918
  async executeClientTools(toolCalls) {
@@ -967,7 +1008,7 @@ var ChatSession = class {
967
1008
  * Skips text deltas (final content is already in messages[]).
968
1009
  */
969
1010
  replayEvent(eventType, data) {
970
- if (eventType === "content_block_delta" || eventType === "thinking_delta" || eventType === "subagent_content_delta" || eventType === "thinking_complete") {
1011
+ if (eventType === "content_block_delta" || eventType === "thinking_delta" || eventType === "subagent_content_delta" || eventType === "thinking_complete" || eventType === "editor_content_start" || eventType === "editor_content_delta" || eventType === "editor_content_end") {
971
1012
  return;
972
1013
  }
973
1014
  this.applyEvent({ type: eventType, ...data });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/streaming.ts","../src/client.ts","../src/storage.ts","../src/tools.ts","../src/utils.ts","../src/session.ts"],"sourcesContent":["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","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 { 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\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(config: AstralformConfig, storage?: ChatStorage) {\n this.client = new AstralformClient(config);\n this.toolRegistry = new ToolRegistry();\n this.storage = storage ?? new InMemoryStorage();\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 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 };\n\n await this.processStream(request);\n }\n\n async resendFromCheckpoint(\n messageId: string,\n newContent: string,\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 };\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 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 // Step 1: Create job\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 let stopTitle: string | undefined;\n\n // Step 2: Stream events\n const stream = this.client.streamJobEvents(\n job.job_id,\n this.lastSeq,\n this.abortController?.signal,\n );\n\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 // Track seq even for non-typed events (e.g. ping)\n if (typeof data?.seq === \"number\") {\n this.lastSeq = data.seq;\n }\n continue;\n }\n parsed = data as SSEEvent;\n // Track seq from every event\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.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 (parsed.is_client_tool) {\n // Execute tool and submit result — job auto-resumes\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 },\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 stopTitle = parsed.title;\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 this.currentJobId = null;\n await this.completeStream(conversationId, messageId, stopTitle);\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 \"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 };\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 });\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 }\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 ): 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 });\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\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 if (eventsResult.status === \"fulfilled\") {\n for (const ev of eventsResult.value) {\n this.replayEvent(ev.event, ev.data);\n }\n }\n }\n\n /**\n * Replay a single persisted event to reconstruct session state.\n * Skips text deltas (final content is already in messages[]).\n */\n private replayEvent(eventType: string, data: Record<string, unknown>): void {\n if (\n eventType === \"content_block_delta\" ||\n eventType === \"thinking_delta\" ||\n eventType === \"subagent_content_delta\" ||\n eventType === \"thinking_complete\"\n ) {\n return;\n }\n this.applyEvent({ type: eventType, ...data } as SSEEvent);\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"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/streaming.ts","../src/client.ts","../src/storage.ts","../src/tools.ts","../src/utils.ts","../src/session.ts"],"sourcesContent":["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","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 { 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\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(config: AstralformConfig, storage?: ChatStorage) {\n this.client = new AstralformClient(config);\n this.toolRegistry = new ToolRegistry();\n this.storage = storage ?? new InMemoryStorage();\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 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 ): 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 };\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 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 // Step 1: Create job\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 let stopTitle: string | undefined;\n\n // Step 2: Stream events\n const stream = this.client.streamJobEvents(\n job.job_id,\n this.lastSeq,\n this.abortController?.signal,\n );\n\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 // Track seq even for non-typed events (e.g. ping)\n if (typeof data?.seq === \"number\") {\n this.lastSeq = data.seq;\n }\n continue;\n }\n parsed = data as SSEEvent;\n // Track seq from every event\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.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 (parsed.is_client_tool) {\n // Execute tool and submit result — job auto-resumes\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 stopTitle = parsed.title;\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 this.currentJobId = null;\n await this.completeStream(conversationId, messageId, stopTitle);\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 \"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 });\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 \"activity\":\n this.emit({\n type: \"activity\",\n activityId: event.activity_id,\n status: event.status,\n category: event.category,\n title: event.title,\n detail: event.detail,\n sources: event.sources,\n toolName: event.tool_name,\n agentName: event.agent_name,\n durationMs: event.duration_ms,\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 ): 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 });\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\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 if (eventsResult.status === \"fulfilled\") {\n for (const ev of eventsResult.value) {\n this.replayEvent(ev.event, ev.data);\n }\n }\n }\n\n /**\n * Replay a single persisted event to reconstruct session state.\n * Skips text deltas (final content is already in messages[]).\n */\n private replayEvent(eventType: string, data: Record<string, unknown>): void {\n if (\n eventType === \"content_block_delta\" ||\n eventType === \"thinking_delta\" ||\n eventType === \"subagent_content_delta\" ||\n eventType === \"thinking_complete\" ||\n eventType === \"editor_content_start\" ||\n eventType === \"editor_content_delta\" ||\n eventType === \"editor_content_end\"\n ) {\n return;\n }\n this.applyEvent({ type: eventType, ...data } as SSEEvent);\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"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astralform/js",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Astralform JS SDK - AI agent orchestration with WebMCP support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",