lobster-cli 0.1.0

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.
Files changed (45) hide show
  1. package/README.md +389 -0
  2. package/dist/agent/core.js +1013 -0
  3. package/dist/agent/core.js.map +1 -0
  4. package/dist/agent/index.js +1027 -0
  5. package/dist/agent/index.js.map +1 -0
  6. package/dist/brain/index.js +60 -0
  7. package/dist/brain/index.js.map +1 -0
  8. package/dist/browser/dom/index.js +1096 -0
  9. package/dist/browser/dom/index.js.map +1 -0
  10. package/dist/browser/index.js +2034 -0
  11. package/dist/browser/index.js.map +1 -0
  12. package/dist/browser/manager.js +86 -0
  13. package/dist/browser/manager.js.map +1 -0
  14. package/dist/browser/page-adapter.js +1345 -0
  15. package/dist/browser/page-adapter.js.map +1 -0
  16. package/dist/cascade/index.js +138 -0
  17. package/dist/cascade/index.js.map +1 -0
  18. package/dist/config/index.js +110 -0
  19. package/dist/config/index.js.map +1 -0
  20. package/dist/config/schema.js +66 -0
  21. package/dist/config/schema.js.map +1 -0
  22. package/dist/discover/index.js +545 -0
  23. package/dist/discover/index.js.map +1 -0
  24. package/dist/index.js +5529 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/lib.js +4206 -0
  27. package/dist/lib.js.map +1 -0
  28. package/dist/llm/client.js +379 -0
  29. package/dist/llm/client.js.map +1 -0
  30. package/dist/llm/index.js +397 -0
  31. package/dist/llm/index.js.map +1 -0
  32. package/dist/llm/openai-client.js +214 -0
  33. package/dist/llm/openai-client.js.map +1 -0
  34. package/dist/output/index.js +93 -0
  35. package/dist/output/index.js.map +1 -0
  36. package/dist/pipeline/index.js +802 -0
  37. package/dist/pipeline/index.js.map +1 -0
  38. package/dist/router/decision.js +80 -0
  39. package/dist/router/decision.js.map +1 -0
  40. package/dist/router/index.js +3443 -0
  41. package/dist/router/index.js.map +1 -0
  42. package/dist/types/index.js +23 -0
  43. package/dist/types/index.js.map +1 -0
  44. package/logo.svg +11 -0
  45. package/package.json +65 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/agent/core.ts","../../src/llm/errors.ts","../../src/llm/openai-client.ts","../../src/llm/utils.ts","../../src/llm/client.ts","../../src/agent/tools/click.ts","../../src/agent/tools/type.ts","../../src/agent/tools/scroll.ts","../../src/agent/tools/select.ts","../../src/agent/tools/wait.ts","../../src/agent/tools/done.ts","../../src/agent/tools/ask-user.ts","../../src/agent/tools/execute-js.ts","../../src/agent/tools/index.ts","../../src/agent/macro-tool.ts","../../src/agent/auto-fixer.ts","../../src/browser/dom/flat-tree.ts","../../src/utils/logger.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { join, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { IPage } from '../types/page.js';\nimport type {\n AgentConfig, AgentTool, ExecutionResult, HistoricalEvent,\n AgentStepEvent, ObservationEvent, AgentStatus,\n AgentEvent, AgentEventListener, AgentEventType,\n} from '../types/agent.js';\nimport { LLM } from '../llm/client.js';\nimport type { Message } from '../types/llm.js';\nimport { createDefaultTools } from './tools/index.js';\nimport { packMacroTool } from './macro-tool.js';\nimport { flatTreeToString } from '../browser/dom/flat-tree.js';\nimport { log } from '../utils/logger.js';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nexport class AgentCore {\n private page: IPage;\n private config: AgentConfig;\n private llm: LLM;\n private history: HistoricalEvent[] = [];\n private _status: AgentStatus = 'idle';\n private listeners = new Map<AgentEventType, Set<AgentEventListener>>();\n private previousElementHashes = new Set<string>();\n private totalWaitTime = 0;\n\n constructor(page: IPage, config: AgentConfig) {\n this.page = page;\n this.config = config;\n this.llm = new LLM(config.llm);\n }\n\n // ── Event system ──\n on(event: AgentEventType, listener: AgentEventListener): void {\n if (!this.listeners.has(event)) this.listeners.set(event, new Set());\n this.listeners.get(event)!.add(listener);\n }\n\n off(event: AgentEventType, listener: AgentEventListener): void {\n this.listeners.get(event)?.delete(listener);\n }\n\n private emit(event: AgentEvent): void {\n const listeners = this.listeners.get(event.type as AgentEventType);\n if (listeners) {\n for (const fn of listeners) {\n try { fn(event); } catch {}\n }\n }\n }\n\n get status(): AgentStatus { return this._status; }\n\n private setStatus(newStatus: AgentStatus): void {\n const prev = this._status;\n this._status = newStatus;\n this.emit({ type: 'statuschange', status: newStatus, previousStatus: prev });\n }\n\n private pushHistory(event: HistoricalEvent): void {\n this.history.push(event);\n this.emit({ type: 'historychange', history: this.history });\n }\n\n async execute(task: string, abortSignal?: AbortSignal): Promise<ExecutionResult> {\n this.setStatus('running');\n this.history = [];\n this.previousElementHashes.clear();\n this.totalWaitTime = 0;\n\n const maxSteps = this.config.maxSteps ?? 40;\n const stepDelay = this.config.stepDelay ?? 0.4;\n\n // Build tools\n const tools: Record<string, AgentTool> = {\n ...createDefaultTools(this.page),\n ...(this.config.customTools || {}),\n };\n for (const [name, tool] of Object.entries(tools)) {\n if (tool === null) delete tools[name];\n }\n\n const macroTool = packMacroTool(tools as Record<string, AgentTool>);\n\n // Load system prompt\n let systemPrompt: string;\n try {\n systemPrompt = readFileSync(join(__dirname, 'prompts', 'system.md'), 'utf-8');\n } catch {\n systemPrompt = 'You are an AI web agent that navigates web pages to complete tasks.';\n }\n\n if (this.config.instructions?.system) {\n systemPrompt += '\\n\\n' + this.config.instructions.system;\n }\n\n let lastURL = '';\n\n for (let step = 1; step <= maxSteps; step++) {\n if (abortSignal?.aborted) {\n this.setStatus('error');\n return { success: false, data: 'Aborted', history: this.history };\n }\n\n // ── Observe phase ──\n const browserState = await this.page.browserState().catch(() => ({\n url: '', title: '', viewportWidth: 0, viewportHeight: 0,\n pageWidth: 0, pageHeight: 0, scrollX: 0, scrollY: 0,\n scrollPercent: 0, pixelsAbove: 0, pixelsBelow: 0,\n }));\n\n const flatTree = await this.page.flatTree().catch(() => ({ rootId: '', map: {} }));\n const pageContent = flatTreeToString(flatTree);\n\n // ── New element tracking ──\n const currentHashes = new Set<string>();\n let newElementCount = 0;\n for (const node of Object.values(flatTree.map)) {\n if (node.isInteractive && node.highlightIndex !== undefined) {\n const hash = `${node.tagName}:${node.text || ''}:${JSON.stringify(node.attributes || {})}`;\n currentHashes.add(hash);\n if (!this.previousElementHashes.has(hash)) {\n newElementCount++;\n }\n }\n }\n this.previousElementHashes = currentHashes;\n\n // ── Build observations ──\n const observations: string[] = [];\n if (browserState.url !== lastURL && lastURL) {\n observations.push(`Navigated to ${browserState.url}`);\n }\n lastURL = browserState.url;\n\n if (newElementCount > 0 && step > 1) {\n observations.push(`${newElementCount} new interactive element(s) appeared`);\n }\n\n if (this.totalWaitTime > 3) {\n observations.push(`Total wait time: ${this.totalWaitTime.toFixed(1)}s — consider if page is still loading`);\n }\n\n if (step >= maxSteps - 5) {\n observations.push(`Warning: ${maxSteps - step} steps remaining`);\n }\n\n if (this.config.instructions?.getPageInstructions) {\n try {\n const pi = this.config.instructions.getPageInstructions(browserState.url);\n if (pi) observations.push(`Page instructions: ${pi}`);\n } catch {}\n }\n\n for (const obs of observations) {\n this.pushHistory({ type: 'observation', message: obs } as ObservationEvent);\n this.emit({ type: 'activity', kind: 'observation', message: obs, step });\n }\n\n // ── Assemble user prompt with browser state ──\n const userPrompt = assembleUserPrompt(\n task, pageContent, browserState, this.history, step, maxSteps,\n );\n\n // ── Think phase ──\n const messages: Message[] = [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: userPrompt },\n ];\n\n log.step(step, `Thinking... (${browserState.url})`);\n this.emit({ type: 'activity', kind: 'thinking', message: `Step ${step}: thinking`, step });\n\n if (this.config.onBeforeStep) await this.config.onBeforeStep(step);\n\n const startTime = Date.now();\n let result;\n try {\n result = await this.llm.invoke(messages, macroTool, abortSignal);\n } catch (err) {\n log.error(`LLM error at step ${step}: ${err}`);\n this.pushHistory({ type: 'error', error: String(err), step });\n this.emit({ type: 'activity', kind: 'error', message: String(err), step });\n continue;\n }\n const duration = Date.now() - startTime;\n\n // ── Act phase ──\n const args = result.toolCall.args;\n const action = (args.action || args) as Record<string, unknown>;\n const [actionName, actionInput] = Object.entries(action)[0] || ['unknown', {}];\n\n this.emit({ type: 'activity', kind: 'executing', message: actionName, step });\n\n // Track wait time\n if (actionName === 'wait') {\n const secs = (actionInput as any)?.seconds || 0;\n this.totalWaitTime += secs;\n }\n\n const stepEvent: AgentStepEvent = {\n type: 'step',\n step,\n reflection: {\n evaluation_previous_goal: (args.evaluation_previous_goal as string) || '',\n memory: (args.memory as string) || '',\n next_goal: (args.next_goal as string) || '',\n },\n action: { name: actionName, args: actionInput as Record<string, unknown> },\n output: result.toolResult,\n duration,\n };\n this.pushHistory(stepEvent);\n\n log.step(step, `Action: ${actionName} → ${result.toolResult.slice(0, 100)}`);\n this.emit({ type: 'activity', kind: 'executed', message: `${actionName}: ${result.toolResult.slice(0, 80)}`, step, duration });\n\n if (this.config.onAfterStep) await this.config.onAfterStep(this.history);\n\n // Check for done\n if (actionName === 'done') {\n try {\n const doneResult = JSON.parse(result.toolResult);\n this.setStatus('completed');\n return { success: doneResult.success, data: doneResult.text || result.toolResult, history: this.history };\n } catch {\n this.setStatus('completed');\n return { success: true, data: result.toolResult, history: this.history };\n }\n }\n\n if (stepDelay > 0) {\n await new Promise((r) => setTimeout(r, stepDelay * 1000));\n }\n }\n\n this.setStatus('error');\n return { success: false, data: `Reached maximum steps (${maxSteps})`, history: this.history };\n }\n}\n\nfunction assembleUserPrompt(\n task: string,\n pageContent: string,\n state: { url: string; title: string; viewportWidth: number; viewportHeight: number; pageHeight: number; scrollPercent: number; pixelsAbove: number; pixelsBelow: number },\n history: HistoricalEvent[],\n step: number,\n maxSteps: number,\n): string {\n let prompt = `# Task\\n${task}\\n\\n`;\n\n // Browser state header\n prompt += `# Current Page\\n`;\n prompt += `URL: ${state.url}\\n`;\n prompt += `Title: ${state.title}\\n`;\n prompt += `Viewport: ${state.viewportWidth}x${state.viewportHeight} | Page height: ${state.pageHeight}px\\n`;\n prompt += `Scroll: ${state.scrollPercent}%`;\n if (state.pixelsAbove > 50) prompt += ` | ${state.pixelsAbove}px above`;\n if (state.pixelsBelow > 50) prompt += ` | ${state.pixelsBelow}px below`;\n prompt += `\\nStep: ${step}/${maxSteps}\\n\\n`;\n\n prompt += `# Browser State\\n${pageContent}\\n\\n`;\n\n if (history.length > 0) {\n prompt += `# History\\n`;\n const recent = history.slice(-10);\n for (const event of recent) {\n if (event.type === 'step') {\n const s = event as AgentStepEvent;\n prompt += `<step_${s.step}>\\n`;\n if (s.reflection) {\n prompt += ` eval: ${s.reflection.evaluation_previous_goal}\\n`;\n prompt += ` memory: ${s.reflection.memory}\\n`;\n prompt += ` goal: ${s.reflection.next_goal}\\n`;\n }\n prompt += ` action: ${s.action.name}(${JSON.stringify(s.action.args)})\\n`;\n prompt += ` result: ${s.output.slice(0, 200)}\\n`;\n prompt += `</step_${s.step}>\\n`;\n } else if (event.type === 'observation') {\n prompt += `<sys>${(event as ObservationEvent).message}</sys>\\n`;\n }\n }\n }\n\n return prompt;\n}\n","export enum InvokeErrorType {\n NETWORK_ERROR = 'NETWORK_ERROR',\n AUTH_ERROR = 'AUTH_ERROR',\n RATE_LIMIT = 'RATE_LIMIT',\n SERVER_ERROR = 'SERVER_ERROR',\n CONTEXT_LENGTH = 'CONTEXT_LENGTH',\n CONTENT_FILTER = 'CONTENT_FILTER',\n NO_TOOL_CALL = 'NO_TOOL_CALL',\n INVALID_TOOL_ARGS = 'INVALID_TOOL_ARGS',\n TOOL_EXECUTION_ERROR = 'TOOL_EXECUTION_ERROR',\n UNKNOWN = 'UNKNOWN',\n}\n\nexport class InvokeError extends Error {\n type: InvokeErrorType;\n retryable: boolean;\n rawError?: unknown;\n rawResponse?: unknown;\n\n constructor(type: InvokeErrorType, message: string, opts?: { retryable?: boolean; rawError?: unknown; rawResponse?: unknown }) {\n super(message);\n this.name = 'InvokeError';\n this.type = type;\n this.retryable = opts?.retryable ?? isRetryable(type);\n this.rawError = opts?.rawError;\n this.rawResponse = opts?.rawResponse;\n }\n}\n\nfunction isRetryable(type: InvokeErrorType): boolean {\n switch (type) {\n case InvokeErrorType.NETWORK_ERROR:\n case InvokeErrorType.RATE_LIMIT:\n case InvokeErrorType.SERVER_ERROR:\n case InvokeErrorType.NO_TOOL_CALL:\n case InvokeErrorType.INVALID_TOOL_ARGS:\n case InvokeErrorType.TOOL_EXECUTION_ERROR:\n case InvokeErrorType.UNKNOWN:\n return true;\n case InvokeErrorType.AUTH_ERROR:\n case InvokeErrorType.CONTEXT_LENGTH:\n case InvokeErrorType.CONTENT_FILTER:\n return false;\n }\n}\n","import type { Message, ToolCall } from '../types/llm.js';\nimport type { LLMTool } from '../types/llm.js';\nimport { InvokeError, InvokeErrorType } from './errors.js';\nimport type { LLMProvider } from '../config/schema.js';\n\nexport interface OpenAIClientConfig {\n baseURL: string;\n model: string;\n apiKey?: string;\n temperature?: number;\n provider?: LLMProvider;\n}\n\nexport class OpenAIClient {\n private config: OpenAIClientConfig;\n\n constructor(config: OpenAIClientConfig) {\n this.config = config;\n }\n\n /**\n * Build auth headers based on the provider.\n * - OpenAI/Gemini/Ollama: Bearer token\n * - Anthropic: x-api-key header + anthropic-version\n */\n private buildHeaders(): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n\n if (!this.config.apiKey) return headers;\n\n if (this.config.provider === 'anthropic') {\n headers['x-api-key'] = this.config.apiKey;\n headers['anthropic-version'] = '2023-06-01';\n } else {\n headers['Authorization'] = `Bearer ${this.config.apiKey}`;\n }\n\n return headers;\n }\n\n /**\n * Build the request body based on provider.\n * Anthropic Messages API is different from OpenAI chat completions.\n */\n private buildBody(\n messages: Message[],\n tools?: LLMTool[],\n opts?: { toolChoice?: string | { type: 'function'; function: { name: string } } },\n ): { url: string; body: Record<string, unknown> } {\n if (this.config.provider === 'anthropic') {\n return this.buildAnthropicBody(messages, tools, opts);\n }\n\n // OpenAI-compatible format (OpenAI, Gemini, Ollama all use this)\n const body: Record<string, unknown> = {\n model: this.config.model,\n messages,\n temperature: this.config.temperature ?? 0.1,\n };\n\n if (tools && tools.length > 0) {\n body.tools = tools;\n body.parallel_tool_calls = false;\n if (opts?.toolChoice) {\n body.tool_choice = typeof opts.toolChoice === 'string'\n ? opts.toolChoice\n : opts.toolChoice;\n }\n }\n\n return { url: `${this.config.baseURL}/chat/completions`, body };\n }\n\n /**\n * Build Anthropic Messages API request.\n * Converts OpenAI-style messages/tools to Anthropic format.\n */\n private buildAnthropicBody(\n messages: Message[],\n tools?: LLMTool[],\n opts?: { toolChoice?: string | { type: 'function'; function: { name: string } } },\n ): { url: string; body: Record<string, unknown> } {\n // Extract system message\n let system: string | undefined;\n const anthropicMessages: Record<string, unknown>[] = [];\n\n for (const msg of messages) {\n if (msg.role === 'system') {\n system = msg.content as string;\n } else {\n anthropicMessages.push({\n role: msg.role === 'assistant' ? 'assistant' : 'user',\n content: msg.content,\n });\n }\n }\n\n const body: Record<string, unknown> = {\n model: this.config.model,\n messages: anthropicMessages,\n max_tokens: 4096,\n temperature: this.config.temperature ?? 0.1,\n };\n\n if (system) body.system = system;\n\n // Convert OpenAI tools format to Anthropic tools format\n if (tools && tools.length > 0) {\n body.tools = tools.map((t) => {\n const fn = (t as any).function;\n return {\n name: fn.name,\n description: fn.description,\n input_schema: fn.parameters,\n };\n });\n\n if (opts?.toolChoice) {\n if (typeof opts.toolChoice === 'string') {\n body.tool_choice = opts.toolChoice === 'required'\n ? { type: 'any' }\n : { type: opts.toolChoice };\n } else {\n body.tool_choice = { type: 'tool', name: opts.toolChoice.function.name };\n }\n }\n }\n\n return { url: `${this.config.baseURL}/messages`, body };\n }\n\n /**\n * Parse Anthropic response into our unified format.\n */\n private parseAnthropicResponse(json: Record<string, unknown>): {\n toolCalls?: ToolCall[];\n content?: string;\n usage?: { promptTokens: number; completionTokens: number; totalTokens: number };\n } {\n const content = json.content as any[];\n if (!content || !Array.isArray(content)) {\n throw new InvokeError(InvokeErrorType.UNKNOWN, 'No content in Anthropic response', { rawResponse: json });\n }\n\n let textContent: string | undefined;\n const toolCalls: ToolCall[] = [];\n\n for (const block of content) {\n if (block.type === 'text') {\n textContent = block.text;\n } else if (block.type === 'tool_use') {\n toolCalls.push({\n id: block.id,\n type: 'function',\n function: {\n name: block.name,\n arguments: JSON.stringify(block.input),\n },\n });\n }\n }\n\n const usage = json.usage as Record<string, number> | undefined;\n\n return {\n toolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n content: textContent,\n usage: usage ? {\n promptTokens: usage.input_tokens ?? 0,\n completionTokens: usage.output_tokens ?? 0,\n totalTokens: (usage.input_tokens ?? 0) + (usage.output_tokens ?? 0),\n } : undefined,\n };\n }\n\n async chatCompletion(\n messages: Message[],\n tools?: LLMTool[],\n opts?: { toolChoice?: string | { type: 'function'; function: { name: string } } }\n ): Promise<{\n toolCalls?: ToolCall[];\n content?: string;\n usage?: { promptTokens: number; completionTokens: number; totalTokens: number };\n }> {\n const { url, body } = this.buildBody(messages, tools, opts);\n const headers = this.buildHeaders();\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n });\n } catch (err) {\n throw new InvokeError(InvokeErrorType.NETWORK_ERROR, `Network error: ${err}`, { rawError: err });\n }\n\n if (!response.ok) {\n const text = await response.text().catch(() => '');\n if (response.status === 401) {\n throw new InvokeError(InvokeErrorType.AUTH_ERROR, `Authentication failed: ${text}`, { retryable: false, rawResponse: text });\n }\n if (response.status === 429) {\n throw new InvokeError(InvokeErrorType.RATE_LIMIT, `Rate limited: ${text}`, { rawResponse: text });\n }\n if (response.status >= 500) {\n throw new InvokeError(InvokeErrorType.SERVER_ERROR, `Server error ${response.status}: ${text}`, { rawResponse: text });\n }\n throw new InvokeError(InvokeErrorType.UNKNOWN, `HTTP ${response.status}: ${text}`, { rawResponse: text });\n }\n\n const json = await response.json() as Record<string, unknown>;\n\n // Route to provider-specific parser\n if (this.config.provider === 'anthropic') {\n return this.parseAnthropicResponse(json);\n }\n\n // OpenAI-compatible response parsing (OpenAI, Gemini, Ollama)\n const choice = (json.choices as any[])?.[0];\n if (!choice) {\n throw new InvokeError(InvokeErrorType.UNKNOWN, 'No choices in response', { rawResponse: json });\n }\n\n const message = choice.message;\n const finishReason = choice.finish_reason;\n\n if (finishReason === 'content_filter') {\n throw new InvokeError(InvokeErrorType.CONTENT_FILTER, 'Content filtered', { retryable: false, rawResponse: json });\n }\n\n if (finishReason === 'length') {\n throw new InvokeError(InvokeErrorType.CONTEXT_LENGTH, 'Context length exceeded', { retryable: false, rawResponse: json });\n }\n\n const usage = json.usage as Record<string, number> | undefined;\n\n return {\n toolCalls: message.tool_calls as ToolCall[] | undefined,\n content: message.content as string | undefined,\n usage: usage ? {\n promptTokens: usage.prompt_tokens ?? 0,\n completionTokens: usage.completion_tokens ?? 0,\n totalTokens: usage.total_tokens ?? 0,\n } : undefined,\n };\n }\n}\n","import type { z } from 'zod';\nimport type { LLMTool } from '../types/llm.js';\n\nexport function zodToJsonSchema(schema: z.ZodType): Record<string, unknown> {\n // Simplified Zod-to-JSON-Schema converter for common types\n if ('_def' in schema) {\n const def = (schema as any)._def;\n const typeName = def.typeName;\n\n if (typeName === 'ZodObject') {\n const shape = def.shape();\n const properties: Record<string, unknown> = {};\n const required: string[] = [];\n for (const [key, value] of Object.entries(shape)) {\n properties[key] = zodToJsonSchema(value as z.ZodType);\n if (!((value as any)._def?.typeName === 'ZodOptional')) {\n required.push(key);\n }\n }\n const result: Record<string, unknown> = { type: 'object', properties };\n if (required.length > 0) result.required = required;\n if (def.description) result.description = def.description;\n return result;\n }\n\n if (typeName === 'ZodString') {\n const result: Record<string, unknown> = { type: 'string' };\n if (def.description) result.description = def.description;\n return result;\n }\n\n if (typeName === 'ZodNumber') {\n const result: Record<string, unknown> = { type: 'number' };\n if (def.description) result.description = def.description;\n return result;\n }\n\n if (typeName === 'ZodBoolean') {\n const result: Record<string, unknown> = { type: 'boolean' };\n if (def.description) result.description = def.description;\n return result;\n }\n\n if (typeName === 'ZodEnum') {\n return { type: 'string', enum: def.values, ...(def.description ? { description: def.description } : {}) };\n }\n\n if (typeName === 'ZodArray') {\n return { type: 'array', items: zodToJsonSchema(def.type), ...(def.description ? { description: def.description } : {}) };\n }\n\n if (typeName === 'ZodOptional') {\n return zodToJsonSchema(def.innerType);\n }\n\n if (typeName === 'ZodDefault') {\n const inner = zodToJsonSchema(def.innerType);\n return { ...inner, default: def.defaultValue() };\n }\n\n if (typeName === 'ZodUnion') {\n return { oneOf: def.options.map((opt: z.ZodType) => zodToJsonSchema(opt)) };\n }\n\n if (typeName === 'ZodRecord') {\n return { type: 'object', additionalProperties: zodToJsonSchema(def.valueType) };\n }\n\n if (typeName === 'ZodLiteral') {\n return { const: def.value };\n }\n\n if (typeName === 'ZodAny') {\n return {};\n }\n }\n\n return { type: 'string' };\n}\n\nexport function zodToOpenAITool(name: string, description: string, schema: z.ZodType): LLMTool {\n return {\n type: 'function',\n function: {\n name,\n description,\n parameters: zodToJsonSchema(schema),\n },\n };\n}\n","import type { z } from 'zod';\nimport type { Message, InvokeResult, LLMTool } from '../types/llm.js';\nimport type { LLMConfig } from '../types/llm.js';\nimport { OpenAIClient } from './openai-client.js';\nimport { InvokeError, InvokeErrorType } from './errors.js';\nimport { zodToOpenAITool } from './utils.js';\n\nexport interface MacroTool {\n name: string;\n description: string;\n schema: z.ZodType;\n execute: (args: Record<string, unknown>) => Promise<string>;\n}\n\nexport class LLM {\n private client: OpenAIClient;\n private config: LLMConfig;\n\n constructor(config: LLMConfig) {\n this.config = config;\n this.client = new OpenAIClient({\n baseURL: config.baseURL,\n model: config.model,\n apiKey: config.apiKey,\n temperature: config.temperature,\n provider: config.provider as any,\n });\n }\n\n async invoke(\n messages: Message[],\n tool: MacroTool,\n abortSignal?: AbortSignal\n ): Promise<InvokeResult> {\n const openaiTool = zodToOpenAITool(tool.name, tool.description, tool.schema);\n\n return this.withRetry(async () => {\n if (abortSignal?.aborted) throw new Error('Aborted');\n\n const response = await this.client.chatCompletion(\n messages,\n [openaiTool],\n { toolChoice: { type: 'function', function: { name: tool.name } } }\n );\n\n // Extract tool call\n const toolCall = response.toolCalls?.[0];\n if (!toolCall) {\n // Try to extract from content (some models put JSON in content)\n if (response.content) {\n const extracted = extractJsonFromString(response.content);\n if (extracted) {\n const args = typeof extracted === 'string' ? JSON.parse(extracted) : extracted;\n const result = await tool.execute(args);\n return {\n toolCall: { name: tool.name, args },\n toolResult: result,\n usage: response.usage,\n };\n }\n }\n throw new InvokeError(InvokeErrorType.NO_TOOL_CALL, 'No tool call in response');\n }\n\n let args: Record<string, unknown>;\n try {\n args = JSON.parse(toolCall.function.arguments);\n } catch {\n // Try double-parse (some models double-stringify)\n try {\n args = JSON.parse(JSON.parse(toolCall.function.arguments));\n } catch {\n throw new InvokeError(InvokeErrorType.INVALID_TOOL_ARGS, `Invalid JSON in tool args: ${toolCall.function.arguments}`);\n }\n }\n\n let result: string;\n try {\n result = await tool.execute(args);\n } catch (err) {\n throw new InvokeError(InvokeErrorType.TOOL_EXECUTION_ERROR, `Tool execution failed: ${err}`, { rawError: err });\n }\n\n return {\n toolCall: { name: tool.name, args },\n toolResult: result,\n usage: response.usage,\n };\n });\n }\n\n private async withRetry<T>(fn: () => Promise<T>): Promise<T> {\n const maxRetries = this.config.maxRetries ?? 3;\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await fn();\n } catch (err) {\n lastError = err;\n if (err instanceof InvokeError && !err.retryable) throw err;\n if (err instanceof Error && err.name === 'AbortError') throw err;\n if (attempt < maxRetries) {\n await new Promise((r) => setTimeout(r, 100 * (attempt + 1)));\n }\n }\n }\n\n throw lastError;\n }\n}\n\nfunction extractJsonFromString(str: string): unknown | null {\n const start = str.indexOf('{');\n const end = str.lastIndexOf('}');\n if (start === -1 || end === -1 || end <= start) return null;\n try {\n return JSON.parse(str.slice(start, end + 1));\n } catch {\n return null;\n }\n}\n","import { z } from 'zod';\nimport type { AgentTool } from '../../types/agent.js';\nimport type { IPage } from '../../types/page.js';\n\nexport function createClickTool(page: IPage): AgentTool {\n return {\n description: 'Click on an interactive element by its index number from the page content.',\n inputSchema: z.object({\n index: z.number().describe('The index of the element to click'),\n }),\n execute: async (args) => {\n await page.click(args.index);\n return `Clicked element [${args.index}]`;\n },\n };\n}\n","import { z } from 'zod';\nimport type { AgentTool } from '../../types/agent.js';\nimport type { IPage } from '../../types/page.js';\n\nexport function createTypeTool(page: IPage): AgentTool {\n return {\n description: 'Type text into an input field identified by its index number.',\n inputSchema: z.object({\n index: z.number().describe('The index of the input element'),\n text: z.string().describe('The text to type'),\n }),\n execute: async (args) => {\n await page.typeText(args.index, args.text);\n return `Typed \"${args.text}\" into element [${args.index}]`;\n },\n };\n}\n","import { z } from 'zod';\nimport type { AgentTool } from '../../types/agent.js';\nimport type { IPage } from '../../types/page.js';\n\nexport function createScrollTool(page: IPage): AgentTool {\n return {\n description: 'Scroll the page in a given direction. Use to reveal more content.',\n inputSchema: z.object({\n direction: z.enum(['up', 'down', 'left', 'right']).describe('Scroll direction'),\n amount: z.number().optional().describe('Pixels to scroll (default 500)'),\n }),\n execute: async (args) => {\n await page.scroll(args.direction, args.amount);\n return `Scrolled ${args.direction}${args.amount ? ` ${args.amount}px` : ''}`;\n },\n };\n}\n","import { z } from 'zod';\nimport type { AgentTool } from '../../types/agent.js';\nimport type { IPage } from '../../types/page.js';\n\nexport function createSelectTool(page: IPage): AgentTool {\n return {\n description: 'Select an option from a dropdown/select element by its index.',\n inputSchema: z.object({\n index: z.number().describe('The index of the select element'),\n value: z.string().describe('The option text or value to select'),\n }),\n execute: async (args) => {\n await page.selectOption(args.index, args.value);\n return `Selected \"${args.value}\" in element [${args.index}]`;\n },\n };\n}\n","import { z } from 'zod';\nimport type { AgentTool } from '../../types/agent.js';\n\nexport function createWaitTool(): AgentTool {\n return {\n description: 'Wait for a specified number of seconds before continuing.',\n inputSchema: z.object({\n seconds: z.number().min(0.1).max(30).describe('Seconds to wait'),\n }),\n execute: async (args) => {\n await new Promise((r) => setTimeout(r, args.seconds * 1000));\n return `Waited ${args.seconds} seconds`;\n },\n };\n}\n","import { z } from 'zod';\nimport type { AgentTool } from '../../types/agent.js';\n\nexport function createDoneTool(): AgentTool {\n return {\n description: 'Signal that the task is complete. Call this when you have finished the task or cannot proceed further.',\n inputSchema: z.object({\n success: z.boolean().describe('Whether the task was completed successfully'),\n text: z.string().describe('Summary of the result or explanation of failure'),\n }),\n execute: async (args) => {\n return JSON.stringify({ done: true, success: args.success, text: args.text });\n },\n };\n}\n","import { z } from 'zod';\nimport type { AgentTool } from '../../types/agent.js';\nimport { createInterface } from 'node:readline';\n\nexport function createAskUserTool(): AgentTool {\n return {\n description: 'Ask the user a question when you need clarification or input to proceed.',\n inputSchema: z.object({\n question: z.string().describe('The question to ask the user'),\n }),\n execute: async (args) => {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n return new Promise<string>((resolve) => {\n rl.question(`\\n🤖 Agent asks: ${args.question}\\n> `, (answer) => {\n rl.close();\n resolve(`User answered: ${answer}`);\n });\n });\n },\n };\n}\n","import { z } from 'zod';\nimport type { AgentTool } from '../../types/agent.js';\nimport type { IPage } from '../../types/page.js';\n\nexport function createExecuteJsTool(page: IPage): AgentTool {\n return {\n description: 'Execute JavaScript code on the current page. Returns the result.',\n inputSchema: z.object({\n code: z.string().describe('JavaScript code to execute on the page'),\n }),\n execute: async (args) => {\n const result = await page.evaluate(args.code);\n return typeof result === 'string' ? result : JSON.stringify(result, null, 2);\n },\n };\n}\n","import type { AgentTool } from '../../types/agent.js';\nimport type { IPage } from '../../types/page.js';\nimport { createClickTool } from './click.js';\nimport { createTypeTool } from './type.js';\nimport { createScrollTool } from './scroll.js';\nimport { createSelectTool } from './select.js';\nimport { createWaitTool } from './wait.js';\nimport { createDoneTool } from './done.js';\nimport { createAskUserTool } from './ask-user.js';\nimport { createExecuteJsTool } from './execute-js.js';\n\nexport function createDefaultTools(page: IPage): Record<string, AgentTool> {\n return {\n click_element_by_index: createClickTool(page),\n input_text: createTypeTool(page),\n scroll: createScrollTool(page),\n select_dropdown_option: createSelectTool(page),\n wait: createWaitTool(),\n done: createDoneTool(),\n ask_user: createAskUserTool(),\n execute_javascript: createExecuteJsTool(page),\n };\n}\n","import { z } from 'zod';\nimport type { AgentTool } from '../types/agent.js';\nimport type { MacroTool } from '../llm/client.js';\nimport { normalizeResponse } from './auto-fixer.js';\n\nexport function packMacroTool(\n tools: Record<string, AgentTool>\n): MacroTool {\n // Build the action union schema\n const actionSchemas: z.ZodTypeAny[] = [];\n const toolNames: string[] = [];\n\n for (const [name, tool] of Object.entries(tools)) {\n toolNames.push(name);\n actionSchemas.push(\n z.object({ [name]: tool.inputSchema }).describe(tool.description)\n );\n }\n\n const actionSchema = actionSchemas.length === 1\n ? actionSchemas[0]\n : z.union(actionSchemas as [z.ZodTypeAny, z.ZodTypeAny, ...z.ZodTypeAny[]]);\n\n const macroSchema = z.object({\n evaluation_previous_goal: z.string().optional().describe('Evaluate whether the previous goal was achieved'),\n memory: z.string().optional().describe('Important information to remember for future steps'),\n next_goal: z.string().optional().describe('The next immediate goal to achieve'),\n action: actionSchema.describe('The action to take'),\n });\n\n return {\n name: 'AgentOutput',\n description: 'The agent\\'s output containing reflection and action. Must be called every step.',\n schema: macroSchema,\n execute: async (args: Record<string, unknown>) => {\n // Normalize messy LLM output\n const normalized = normalizeResponse(args, 'AgentOutput', toolNames, tools);\n const action = normalized.action as Record<string, unknown>;\n\n // Find the tool to execute\n const [toolName, toolInput] = Object.entries(action)[0];\n const tool = tools[toolName];\n\n if (!tool) {\n return `Error: Unknown tool \"${toolName}\". Available: ${toolNames.join(', ')}`;\n }\n\n try {\n const result = await tool.execute(toolInput as any);\n return result;\n } catch (err) {\n return `Error executing ${toolName}: ${err}`;\n }\n },\n };\n}\n","import type { z } from 'zod';\nimport type { AgentTool } from '../types/agent.js';\n\n/**\n * Normalize messy LLM responses into valid MacroTool output.\n * Uses tool schemas for validation instead of hardcoded tool names.\n */\nexport function normalizeResponse(\n raw: Record<string, unknown>,\n toolName: string,\n availableActions: string[],\n toolSchemas?: Record<string, AgentTool>,\n): Record<string, unknown> {\n let result = { ...raw };\n\n // Fix 1: Nested function wrapper — unwrap {type: 'function', function: {arguments}}\n if (result.type === 'function' && result.function) {\n const fn = result.function as Record<string, unknown>;\n if (typeof fn.arguments === 'string') {\n try { result = JSON.parse(fn.arguments); } catch {}\n } else if (typeof fn.arguments === 'object') {\n result = fn.arguments as Record<string, unknown>;\n }\n }\n\n // Fix 2: Double-stringified arguments\n for (const [key, value] of Object.entries(result)) {\n if (typeof value === 'string') {\n try {\n const parsed = JSON.parse(value);\n if (typeof parsed === 'object' && parsed !== null) {\n result[key] = parsed;\n }\n } catch {}\n }\n }\n\n // Fix 3: If no action field, try to infer one\n if (!result.action) {\n for (const actionName of availableActions) {\n if (actionName in result) {\n result = {\n ...result,\n action: { [actionName]: result[actionName] },\n };\n delete result[actionName];\n break;\n }\n }\n }\n\n // Fix 4: Still no action — fallback to wait\n if (!result.action) {\n result.action = { wait: { seconds: 1 } };\n }\n\n // Fix 5: Action is a string instead of object\n if (typeof result.action === 'string') {\n if (availableActions.includes(result.action)) {\n result.action = { [result.action]: {} };\n } else {\n result.action = { wait: { seconds: 1 } };\n }\n }\n\n // Fix 6: Schema-based validation & primitive coercion\n const action = result.action as Record<string, unknown>;\n for (const [name, input] of Object.entries(action)) {\n if (typeof input !== 'object' || input === null) {\n // Use schema to determine expected shape\n if (toolSchemas && toolSchemas[name]) {\n const schema = toolSchemas[name].inputSchema;\n const coerced = coercePrimitiveToSchema(input, schema);\n if (coerced !== null) {\n action[name] = coerced;\n continue;\n }\n }\n\n // Fallback: hardcoded coercion for known patterns\n if (typeof input === 'number') {\n action[name] = { index: input };\n } else if (typeof input === 'string') {\n action[name] = { text: input };\n } else {\n action[name] = {};\n }\n }\n\n // Fix 7: Validate action args against schema if available\n if (toolSchemas && toolSchemas[name] && typeof action[name] === 'object') {\n const schema = toolSchemas[name].inputSchema;\n const validation = schema.safeParse(action[name]);\n if (!validation.success) {\n // Try to fix common issues: wrong field names, missing required fields\n const fixed = attemptSchemaFix(action[name] as Record<string, unknown>, schema, validation.error);\n if (fixed) {\n action[name] = fixed;\n }\n }\n }\n }\n\n return result;\n}\n\n/**\n * Coerce a primitive value into an object matching a Zod schema.\n * Inspects the schema to find a single required field and wraps the value.\n */\nfunction coercePrimitiveToSchema(value: unknown, schema: z.ZodType): Record<string, unknown> | null {\n try {\n const def = (schema as any)._def;\n if (def?.typeName !== 'ZodObject') return null;\n\n const shape = def.shape();\n const keys = Object.keys(shape);\n\n // Single required field — wrap the primitive\n const requiredKeys = keys.filter((k) => {\n const fieldDef = (shape[k] as any)?._def;\n return fieldDef?.typeName !== 'ZodOptional';\n });\n\n if (requiredKeys.length === 1) {\n return { [requiredKeys[0]]: value };\n }\n\n // Multiple fields but value is a number — likely an index field\n const indexField = keys.find((k) => /index|idx|num|number/i.test(k));\n if (indexField && typeof value === 'number') {\n return { [indexField]: value };\n }\n\n // Value is a string — likely a text field\n const textField = keys.find((k) => /text|value|query|code|question|url/i.test(k));\n if (textField && typeof value === 'string') {\n return { [textField]: value };\n }\n } catch {}\n\n return null;\n}\n\n/**\n * Attempt to fix validation errors by mapping common mistakes.\n */\nfunction attemptSchemaFix(\n input: Record<string, unknown>,\n schema: z.ZodType,\n error: z.ZodError,\n): Record<string, unknown> | null {\n try {\n const def = (schema as any)._def;\n if (def?.typeName !== 'ZodObject') return null;\n\n const shape = def.shape();\n const expectedKeys = Object.keys(shape);\n const inputKeys = Object.keys(input);\n const fixed = { ...input };\n\n // Fix: wrong key names — try to map by position or type match\n for (const issue of error.issues) {\n if (issue.code === 'invalid_type' && issue.path.length === 1) {\n const key = String(issue.path[0]);\n const val = input[key];\n // Try type coercion\n if (issue.expected === 'number' && typeof val === 'string') {\n const num = Number(val);\n if (!isNaN(num)) fixed[key] = num;\n } else if (issue.expected === 'string' && typeof val === 'number') {\n fixed[key] = String(val);\n } else if (issue.expected === 'boolean' && typeof val === 'string') {\n fixed[key] = val === 'true';\n }\n }\n\n if (issue.code === 'unrecognized_keys') {\n // Remove unrecognized keys\n for (const k of (issue as any).keys || []) {\n delete fixed[k];\n }\n }\n }\n\n // Re-validate\n const result = schema.safeParse(fixed);\n if (result.success) return fixed;\n } catch {}\n\n return null;\n}\n\nexport function safeJsonParse(str: string): unknown {\n try {\n return JSON.parse(str);\n } catch {\n return str;\n }\n}\n\nexport function extractJsonFromString(str: string): unknown | null {\n const start = str.indexOf('{');\n const end = str.lastIndexOf('}');\n if (start === -1 || end === -1 || end <= start) return null;\n try {\n return JSON.parse(str.slice(start, end + 1));\n } catch {\n return null;\n }\n}\n","/**\n * Script that runs inside the browser to extract a flat DOM tree\n * with indexed interactive elements — the format the AI agent uses.\n *\n * Based on Page Agent's DOM extraction approach.\n */\nexport const FLAT_TREE_SCRIPT = `\n(() => {\n const INTERACTIVE_TAGS = new Set([\n 'a', 'button', 'input', 'select', 'textarea', 'details', 'summary',\n 'label', 'option', 'fieldset', 'legend',\n ]);\n\n const INTERACTIVE_ROLES = new Set([\n 'button', 'link', 'textbox', 'checkbox', 'radio', 'combobox',\n 'listbox', 'menu', 'menuitem', 'tab', 'switch', 'slider',\n 'searchbox', 'spinbutton', 'option', 'menuitemcheckbox', 'menuitemradio',\n ]);\n\n const ATTR_WHITELIST = [\n 'type', 'role', 'aria-label', 'aria-expanded', 'aria-selected',\n 'aria-checked', 'aria-disabled', 'placeholder', 'title', 'href',\n 'value', 'name', 'alt', 'src',\n ];\n\n let highlightIndex = 0;\n const nodes = {};\n const selectorMap = {};\n\n function isVisible(el) {\n if (el.offsetWidth === 0 && el.offsetHeight === 0) return false;\n const style = getComputedStyle(el);\n if (style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0') return false;\n return true;\n }\n\n function isInteractive(el) {\n const tag = el.tagName.toLowerCase();\n if (INTERACTIVE_TAGS.has(tag)) return true;\n const role = el.getAttribute('role');\n if (role && INTERACTIVE_ROLES.has(role)) return true;\n if (el.getAttribute('contenteditable') === 'true') return true;\n if (el.getAttribute('tabindex') !== null && parseInt(el.getAttribute('tabindex')) >= 0) return true;\n if (el.onclick || el.getAttribute('onclick')) return true;\n return false;\n }\n\n function getAttributes(el) {\n const attrs = {};\n for (const attr of ATTR_WHITELIST) {\n const val = el.getAttribute(attr);\n if (val !== null && val !== '') attrs[attr] = val;\n }\n return attrs;\n }\n\n function getScrollable(el) {\n const style = getComputedStyle(el);\n const overflowY = style.overflowY;\n const overflowX = style.overflowX;\n const isScrollableY = (overflowY === 'auto' || overflowY === 'scroll') && el.scrollHeight > el.clientHeight;\n const isScrollableX = (overflowX === 'auto' || overflowX === 'scroll') && el.scrollWidth > el.clientWidth;\n if (!isScrollableY && !isScrollableX) return null;\n return {\n left: el.scrollLeft,\n top: el.scrollTop,\n right: el.scrollWidth - el.clientWidth - el.scrollLeft,\n bottom: el.scrollHeight - el.clientHeight - el.scrollTop,\n };\n }\n\n function walk(el, parentId) {\n if (!el || el.nodeType === 8) return; // skip comments\n\n if (el.nodeType === 3) { // text node\n const text = el.textContent.trim();\n if (!text) return;\n const id = 'text_' + Math.random().toString(36).slice(2, 8);\n nodes[id] = { id, tagName: '#text', text, parentId };\n if (parentId && nodes[parentId]) {\n nodes[parentId].children = nodes[parentId].children || [];\n nodes[parentId].children.push(id);\n }\n return;\n }\n\n if (el.nodeType !== 1) return; // only elements\n\n const tag = el.tagName.toLowerCase();\n if (['script', 'style', 'noscript', 'svg', 'path'].includes(tag)) return;\n if (!isVisible(el)) return;\n\n const id = tag + '_' + Math.random().toString(36).slice(2, 8);\n const interactive = isInteractive(el);\n const node = {\n id,\n tagName: tag,\n attributes: getAttributes(el),\n parentId,\n children: [],\n isInteractive: interactive,\n };\n\n if (interactive) {\n node.highlightIndex = highlightIndex;\n selectorMap[highlightIndex] = id;\n highlightIndex++;\n }\n\n const scrollable = getScrollable(el);\n if (scrollable) node.scrollable = scrollable;\n\n const text = [];\n for (const child of el.childNodes) {\n if (child.nodeType === 3 && child.textContent.trim()) {\n text.push(child.textContent.trim());\n }\n }\n if (text.length > 0) node.text = text.join(' ').slice(0, 200);\n\n nodes[id] = node;\n\n if (parentId && nodes[parentId]) {\n nodes[parentId].children.push(id);\n }\n\n for (const child of el.children) {\n walk(child, id);\n }\n }\n\n const rootId = 'root';\n nodes[rootId] = { id: rootId, tagName: 'body', children: [], attributes: {} };\n for (const child of document.body.children) {\n walk(child, rootId);\n }\n\n return { rootId, map: nodes, selectorMap };\n})()\n`;\n\n/**\n * Convert a FlatDomTree into the indexed text format that the LLM agent reads.\n * Example output:\n * [0]<button type=submit>Search</>\n * [1]<input type=text placeholder=\"Enter query\" />\n */\nexport function flatTreeToString(tree: { rootId: string; map: Record<string, any> }): string {\n const lines: string[] = [];\n\n function walk(nodeId: string, depth: number) {\n const node = tree.map[nodeId];\n if (!node) return;\n\n const indent = '\\t'.repeat(depth);\n\n if (node.tagName === '#text') {\n if (node.text) lines.push(`${indent}${node.text}`);\n return;\n }\n\n const attrs = node.attributes || {};\n const attrStr = Object.entries(attrs)\n .map(([k, v]) => (v === '' ? k : `${k}=\"${v}\"`))\n .join(' ');\n\n const prefix = node.highlightIndex !== undefined ? `[${node.highlightIndex}]` : '';\n const scrollInfo = node.scrollable\n ? ` |scroll: ${Math.round(node.scrollable.top)}px up, ${Math.round(node.scrollable.bottom)}px down|`\n : '';\n\n const text = node.text || '';\n const tag = node.tagName;\n\n if (prefix || text || node.children?.length > 0) {\n const opening = `${indent}${prefix}<${tag}${attrStr ? ' ' + attrStr : ''}${scrollInfo}>`;\n\n if (!node.children?.length || (node.children.length === 0 && text)) {\n lines.push(`${opening}${text}</>`);\n } else {\n lines.push(`${opening}${text}`);\n for (const childId of node.children || []) {\n walk(childId, depth + 1);\n }\n }\n } else {\n for (const childId of node.children || []) {\n walk(childId, depth);\n }\n }\n }\n\n walk(tree.rootId, 0);\n return lines.join('\\n');\n}\n","import chalk from 'chalk';\n\nexport const log = {\n info: (msg: string) => console.log(chalk.blue('ℹ'), msg),\n success: (msg: string) => console.log(chalk.green('✓'), msg),\n warn: (msg: string) => console.log(chalk.yellow('⚠'), msg),\n error: (msg: string) => console.error(chalk.red('✗'), msg),\n debug: (msg: string) => {\n if (process.env.LOBSTER_DEBUG) console.log(chalk.gray('⋯'), msg);\n },\n step: (n: number, msg: string) => console.log(chalk.cyan(`[${n}]`), msg),\n dim: (msg: string) => console.log(chalk.dim(msg)),\n};\n"],"mappings":"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","names":["args","result","z","z","z","z","z","z","z","z","extractJsonFromString","z"]}
@@ -0,0 +1,60 @@
1
+ // src/brain/index.ts
2
+ var CLASSIFIER_PROMPT = `You are an intent classifier for a web automation tool. Given a user's question about a webpage, decide what data sources are needed to answer it.
3
+
4
+ Respond ONLY with a JSON object:
5
+ {
6
+ "screenshot": true/false,
7
+ "markdown": true/false,
8
+ "forms": true/false,
9
+ "network": true/false,
10
+ "intent": "brief 5-word description"
11
+ }
12
+
13
+ Rules:
14
+ - screenshot=true ONLY when the answer requires SEEING the page (images, visual layout, colors, charts, what something looks like)
15
+ - markdown=true for ANY question about text content, meaning, topics, summaries
16
+ - forms=true ONLY when specifically asking about form fields or inputs
17
+ - network=true ONLY when asking about APIs, requests, or data fetching
18
+ - Most questions need only markdown=true`;
19
+ async function classifyIntent(prompt, pageTitle, llmCall) {
20
+ if (llmCall) {
21
+ try {
22
+ const systemPrompt = CLASSIFIER_PROMPT + `
23
+ Current page: "${pageTitle}"`;
24
+ const response = await llmCall(systemPrompt, prompt);
25
+ const jsonMatch = response.match(/\{[\s\S]*?\}/);
26
+ if (jsonMatch) {
27
+ const parsed = JSON.parse(jsonMatch[0]);
28
+ return {
29
+ screenshot: !!parsed.screenshot,
30
+ markdown: parsed.markdown !== false,
31
+ forms: !!parsed.forms,
32
+ network: !!parsed.network,
33
+ intent: parsed.intent || "",
34
+ source: "llm"
35
+ };
36
+ }
37
+ } catch {
38
+ }
39
+ }
40
+ return heuristicClassify(prompt);
41
+ }
42
+ function heuristicClassify(prompt) {
43
+ const lower = prompt.toLowerCase();
44
+ const screenshot = /look|see|visual|image|screenshot|screen|what('s| is) (on|showing|displayed|visible)|describe.*layout|picture|colour|color|design|ui |logo|icon|chart|graph|photo|video|banner|appear/i.test(lower);
45
+ const forms = /form|input|field|submit|login|sign.?in|password|checkbox|dropdown|select|textarea|search.?box|fill/i.test(lower);
46
+ const network = /api|network|request|fetch|xhr|endpoint|call.*server|data.*load/i.test(lower);
47
+ return {
48
+ screenshot,
49
+ markdown: true,
50
+ forms,
51
+ network,
52
+ intent: "heuristic classification",
53
+ source: "heuristic"
54
+ };
55
+ }
56
+ export {
57
+ classifyIntent,
58
+ heuristicClassify
59
+ };
60
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/brain/index.ts"],"sourcesContent":["/**\n * Brain — Intent classifier for LobsterCLI.\n *\n * Analyzes a user's question and decides what data sources are needed\n * to answer it. Uses a cheap/fast LLM call for classification,\n * with heuristic fallback when no LLM is available.\n *\n * Works in both CLI and extension contexts.\n */\n\nexport interface BrainDecision {\n /** Needs to SEE the page (images, layout, colors, visual content) */\n screenshot: boolean;\n /** Needs page text content (articles, paragraphs, written content) */\n markdown: boolean;\n /** Asking about forms, inputs, fields */\n forms: boolean;\n /** Asking about API calls, network requests */\n network: boolean;\n /** Brief description of what the user wants */\n intent: string;\n /** How the decision was made */\n source: 'llm' | 'heuristic';\n}\n\nconst CLASSIFIER_PROMPT = `You are an intent classifier for a web automation tool. Given a user's question about a webpage, decide what data sources are needed to answer it.\n\nRespond ONLY with a JSON object:\n{\n \"screenshot\": true/false,\n \"markdown\": true/false,\n \"forms\": true/false,\n \"network\": true/false,\n \"intent\": \"brief 5-word description\"\n}\n\nRules:\n- screenshot=true ONLY when the answer requires SEEING the page (images, visual layout, colors, charts, what something looks like)\n- markdown=true for ANY question about text content, meaning, topics, summaries\n- forms=true ONLY when specifically asking about form fields or inputs\n- network=true ONLY when asking about APIs, requests, or data fetching\n- Most questions need only markdown=true`;\n\n/**\n * Classify intent using LLM (requires a callable LLM function)\n */\nexport async function classifyIntent(\n prompt: string,\n pageTitle: string,\n llmCall?: (systemPrompt: string, userPrompt: string) => Promise<string>,\n): Promise<BrainDecision> {\n // If we have an LLM function, use it\n if (llmCall) {\n try {\n const systemPrompt = CLASSIFIER_PROMPT + `\\nCurrent page: \"${pageTitle}\"`;\n const response = await llmCall(systemPrompt, prompt);\n\n const jsonMatch = response.match(/\\{[\\s\\S]*?\\}/);\n if (jsonMatch) {\n const parsed = JSON.parse(jsonMatch[0]);\n return {\n screenshot: !!parsed.screenshot,\n markdown: parsed.markdown !== false,\n forms: !!parsed.forms,\n network: !!parsed.network,\n intent: parsed.intent || '',\n source: 'llm',\n };\n }\n } catch {\n // Fall through to heuristic\n }\n }\n\n return heuristicClassify(prompt);\n}\n\n/**\n * Heuristic classification — no LLM needed, instant, free.\n */\nexport function heuristicClassify(prompt: string): BrainDecision {\n const lower = prompt.toLowerCase();\n\n const screenshot = /look|see|visual|image|screenshot|screen|what('s| is) (on|showing|displayed|visible)|describe.*layout|picture|colour|color|design|ui |logo|icon|chart|graph|photo|video|banner|appear/i.test(lower);\n\n const forms = /form|input|field|submit|login|sign.?in|password|checkbox|dropdown|select|textarea|search.?box|fill/i.test(lower);\n\n const network = /api|network|request|fetch|xhr|endpoint|call.*server|data.*load/i.test(lower);\n\n return {\n screenshot,\n markdown: true,\n forms,\n network,\n intent: 'heuristic classification',\n source: 'heuristic',\n };\n}\n"],"mappings":";AAyBA,IAAM,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAqB1B,eAAsB,eACpB,QACA,WACA,SACwB;AAExB,MAAI,SAAS;AACX,QAAI;AACF,YAAM,eAAe,oBAAoB;AAAA,iBAAoB,SAAS;AACtE,YAAM,WAAW,MAAM,QAAQ,cAAc,MAAM;AAEnD,YAAM,YAAY,SAAS,MAAM,cAAc;AAC/C,UAAI,WAAW;AACb,cAAM,SAAS,KAAK,MAAM,UAAU,CAAC,CAAC;AACtC,eAAO;AAAA,UACL,YAAY,CAAC,CAAC,OAAO;AAAA,UACrB,UAAU,OAAO,aAAa;AAAA,UAC9B,OAAO,CAAC,CAAC,OAAO;AAAA,UAChB,SAAS,CAAC,CAAC,OAAO;AAAA,UAClB,QAAQ,OAAO,UAAU;AAAA,UACzB,QAAQ;AAAA,QACV;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SAAO,kBAAkB,MAAM;AACjC;AAKO,SAAS,kBAAkB,QAA+B;AAC/D,QAAM,QAAQ,OAAO,YAAY;AAEjC,QAAM,aAAa,wLAAwL,KAAK,KAAK;AAErN,QAAM,QAAQ,sGAAsG,KAAK,KAAK;AAE9H,QAAM,UAAU,kEAAkE,KAAK,KAAK;AAE5F,SAAO;AAAA,IACL;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AACF;","names":[]}