@dudko.dev/agent-web 0.0.4 → 0.0.5

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.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/config.ts","../src/llm/generate.ts","../src/llm/util.ts","../src/memory/compress.ts","../src/providers/types.ts","../src/providers/registry.ts","../src/prompts.ts","../src/tools/mode.ts","../src/tools/types.ts","../src/tools/prompted.ts","../src/llm/tool-loop.ts","../src/parse.ts","../src/agent/internal.ts","../src/agent/executor.ts","../src/agent/loop-types.ts","../src/agent/schemas.ts","../src/agent/planner.ts","../src/agent/replanner.ts","../src/agent/synthesizer.ts","../src/agent/runner.ts","../src/providers/capabilities.ts","../src/storage/db.ts","../src/secrets/crypto.ts","../src/secrets/vault.ts","../src/secrets/store.ts","../src/tools/define.ts","../src/memory/store.ts","../src/memory/sessions.ts"],"sourcesContent":["import type { ContextStore } from './memory/store.js'\nimport type { ModelInput, StageInput } from './providers/types.js'\nimport type { Prompts } from './prompts.js'\nimport type { CredentialStore } from './secrets/store.js'\nimport type { AgentToolSet } from './tools/types.js'\n\n/** Force a tool-calling strategy, or let the agent pick per model ('auto'). */\nexport type ToolMode = 'auto' | 'native' | 'prompted'\n\n/**\n * 'all' — the executor sees the full ToolSet on every step.\n * 'plan-narrowed' — the executor sees only a step's suggestedTools (the planner\n * must populate them). Empty means a reasoning-only step.\n */\nexport type ToolSelectionStrategy = 'all' | 'plan-narrowed'\n\n/** Per-phase generation budgets (max output tokens). */\nexport interface PhaseBudgets {\n planner?: number\n executor?: number\n replanner?: number\n synthesizer?: number\n}\n\nexport interface BrowserAgentConfig {\n /** The default (executor) model: a ready AI SDK model, or a ProviderModelSpec to resolve. */\n model: ModelInput\n /** Optional per-stage model overrides. A partial override inherits base provider/creds. */\n planner?: StageInput\n synthesizer?: StageInput\n /** Fetches API keys for ProviderModelSpec models. Default: none (inline keys only). */\n credentials?: CredentialStore\n /** Propagated to the openai-compatible provider name and the MCP client. */\n clientName?: string\n\n /** Host tools the executor may call (an AI SDK ToolSet; use defineTool). */\n tools?: AgentToolSet\n /** Whitelist: only these tool names from `tools` are mounted (default: all). */\n availableTools?: string[]\n /** Blacklist: these tool names are removed after the whitelist is applied. */\n excludedTools?: string[]\n /** Force native/prompted tool-calling; 'auto' picks per model (default 'auto'). */\n toolMode?: ToolMode\n toolSelectionStrategy?: ToolSelectionStrategy\n\n /** Prepended to every phase's system prompt. */\n systemPrompt?: string\n /** Override any phase prompt builder. */\n prompts?: Partial<Prompts>\n /** Serialize the host's current world state into prompt context (grounding). */\n describeState?: () => string | Promise<string>\n\n /**\n * Persist the transcript (e.g. new IndexedDBStore()). The last few messages\n * are also read back into the planner prompt, so follow-up goals can refer\n * to earlier turns.\n */\n memory?: ContextStore\n sessionId?: string\n\n /** Hard cap on executed steps incl. replans (default 8). */\n maxIterations?: number\n /** Cap on LLM steps inside a single native executor call (default 4). */\n maxStepsPerTask?: number\n /** Cap on replanner \"revise\" decisions per run (default 2). */\n maxRevisions?: number\n /** Per-call timeout so a hang can't freeze a run (default 120000). */\n chatTimeoutMs?: number\n budgets?: PhaseBudgets\n temperature?: number\n\n /** Replan after a blocked/failed step (default true). */\n replan?: boolean\n /** Write a final natural-language summary (default true). */\n synthesize?: boolean\n /** Compress stored history past this many chars (0 = off, default 12000). */\n compressAfterChars?: number\n}\n\nexport interface ResolvedConfig {\n clientName: string\n sessionId: string\n toolMode: ToolMode\n toolSelectionStrategy: ToolSelectionStrategy\n maxIterations: number\n maxStepsPerTask: number\n maxRevisions: number\n chatTimeoutMs: number\n budgets: Required<PhaseBudgets>\n temperature: number | undefined\n replan: boolean\n synthesize: boolean\n compressAfterChars: number\n}\n\nexport const resolveConfig = (c: BrowserAgentConfig): ResolvedConfig => ({\n clientName: c.clientName ?? 'agent-web',\n sessionId: c.sessionId ?? 'default',\n toolMode: c.toolMode ?? 'auto',\n toolSelectionStrategy: c.toolSelectionStrategy ?? 'all',\n maxIterations: c.maxIterations ?? 8,\n maxStepsPerTask: c.maxStepsPerTask ?? 4,\n maxRevisions: c.maxRevisions ?? 2,\n chatTimeoutMs: c.chatTimeoutMs ?? 120_000,\n budgets: {\n planner: c.budgets?.planner ?? 800,\n executor: c.budgets?.executor ?? 1200,\n replanner: c.budgets?.replanner ?? 400,\n synthesizer: c.budgets?.synthesizer ?? 400,\n },\n temperature: c.temperature,\n replan: c.replan ?? true,\n synthesize: c.synthesize ?? true,\n compressAfterChars: c.compressAfterChars ?? 12_000,\n})\n","import {\n generateObject,\n generateText,\n streamText,\n type LanguageModel,\n type ModelMessage,\n type ToolSet,\n} from 'ai'\nimport type { ZodType } from 'zod'\nimport { promptOf, timeoutSignal } from './util.js'\n\n/** Options shared by the low-level generation helpers. Provide `prompt` OR `messages`. */\nexport interface GenerateOptions {\n system?: string\n prompt?: string\n messages?: ModelMessage[]\n tools?: ToolSet\n maxOutputTokens?: number\n temperature?: number\n abortSignal?: AbortSignal\n /** Time-box the call; combined with `abortSignal` (0/undefined = no timeout). */\n timeoutMs?: number\n}\n\n/**\n * One-shot text generation. Thin, provider-agnostic wrapper over the AI SDK's\n * `generateText` — the same call works against a cloud model, a local WebLLM\n * model, or Chrome/Edge built-in AI. Returns the full AI SDK result (`.text`,\n * `.usage`, `.toolCalls`, `.steps`, …).\n */\nexport const generate = (\n model: LanguageModel,\n opts: GenerateOptions = {},\n): ReturnType<typeof generateText> =>\n generateText({\n model,\n system: opts.system,\n ...promptOf(opts),\n tools: opts.tools,\n maxOutputTokens: opts.maxOutputTokens,\n temperature: opts.temperature,\n abortSignal: timeoutSignal(opts.abortSignal, opts.timeoutMs),\n })\n\n/** Streaming text generation. Returns the AI SDK `streamText` result (`.textStream`, `.fullStream`). */\nexport const stream = (\n model: LanguageModel,\n opts: GenerateOptions = {},\n): ReturnType<typeof streamText> =>\n streamText({\n model,\n system: opts.system,\n ...promptOf(opts),\n tools: opts.tools,\n maxOutputTokens: opts.maxOutputTokens,\n temperature: opts.temperature,\n abortSignal: timeoutSignal(opts.abortSignal, opts.timeoutMs),\n })\n\n/**\n * Structured output constrained to a Zod schema, via the AI SDK's\n * `generateObject`. Cloud models and WebLLM both support this; tiny local\n * models can be unreliable — the agent's prompted mode is the fallback.\n * Returns the AI SDK result (`.object`, `.usage`).\n */\nexport const generateStructured = <OBJECT>(\n model: LanguageModel,\n schema: ZodType<OBJECT>,\n opts: GenerateOptions = {},\n) =>\n generateObject({\n model,\n schema,\n system: opts.system,\n ...promptOf(opts),\n maxOutputTokens: opts.maxOutputTokens,\n temperature: opts.temperature,\n abortSignal: timeoutSignal(opts.abortSignal, opts.timeoutMs),\n })\n","import type { ModelMessage } from 'ai'\nimport type { IUsage } from '../agent/loop-types.js'\n\n/**\n * The AI SDK prompt is `{ prompt } XOR { messages }` — passing both keys (even\n * with one undefined) breaks the discriminated union. Pick exactly one.\n */\nexport const promptOf = (opts: {\n prompt?: string\n messages?: ModelMessage[]\n}): { prompt: string } | { messages: ModelMessage[] } =>\n opts.messages ? { messages: opts.messages } : { prompt: opts.prompt ?? '' }\n\n/** Normalise the AI SDK usage shape (fields can be undefined) into IUsage. */\nexport const normalizeUsage = (u?: {\n inputTokens?: number\n outputTokens?: number\n totalTokens?: number\n}): IUsage => {\n const inputTokens = u?.inputTokens ?? 0\n const outputTokens = u?.outputTokens ?? 0\n return {\n inputTokens,\n outputTokens,\n totalTokens: u?.totalTokens ?? inputTokens + outputTokens,\n }\n}\n\n/**\n * Combine the caller's AbortSignal with a timeout so a hung generation can't\n * freeze a run. Returns the original signal when no timeout is set. Uses the\n * standard `AbortSignal.timeout`/`AbortSignal.any` (Node ≥ 20, modern browsers).\n */\nexport const timeoutSignal = (signal?: AbortSignal, ms?: number): AbortSignal | undefined => {\n if (!ms || ms <= 0) return signal\n const timeout = AbortSignal.timeout(ms)\n if (!signal) return timeout\n return typeof AbortSignal.any === 'function' ? AbortSignal.any([signal, timeout]) : signal\n}\n","import type { LanguageModel } from 'ai'\nimport { generate } from '../llm/generate.js'\nimport type { StoredMessage } from './store.js'\n\nexport interface CompressOptions {\n /** Compress once the transcript exceeds this many characters (0 = never). */\n maxChars?: number\n /** How many most-recent messages to keep verbatim. */\n keepRecent?: number\n /** Time-box the summarisation call so it can never hang the caller. */\n timeoutMs?: number\n abortSignal?: AbortSignal\n}\n\nconst totalChars = (msgs: StoredMessage[]): number => msgs.reduce((n, m) => n + m.content.length, 0)\n\n/**\n * When the transcript grows too long, summarise everything except the last\n * `keepRecent` messages into a single system message (via the model), so the\n * session stays within the model's context window. Returns the same array\n * unchanged when no compression is needed; never throws.\n */\nexport const compressHistory = async (\n messages: StoredMessage[],\n model: LanguageModel,\n opts: CompressOptions = {},\n): Promise<StoredMessage[]> => {\n const maxChars = opts.maxChars ?? 12_000\n const keepRecent = opts.keepRecent ?? 6\n if (maxChars <= 0 || messages.length <= keepRecent + 1 || totalChars(messages) <= maxChars) {\n return messages\n }\n const head = messages.slice(0, messages.length - keepRecent)\n const tail = messages.slice(messages.length - keepRecent)\n const transcript = head\n .map((m) => `${m.role}: ${m.content}`)\n .join('\\n')\n .slice(0, 8000)\n try {\n const result = await generate(model, {\n system:\n 'Summarize the following conversation into a compact set of durable facts and decisions. Output plain text only.',\n prompt: transcript,\n maxOutputTokens: 400,\n timeoutMs: opts.timeoutMs,\n abortSignal: opts.abortSignal,\n })\n const clean = (result.text || '').trim()\n if (!clean) return messages\n const summaryMsg: StoredMessage = {\n role: 'system',\n content: `Summary of earlier conversation:\\n${clean}`,\n ts: head[0]?.ts,\n }\n return [summaryMsg, ...tail]\n } catch {\n return messages\n }\n}\n","import type { LanguageModel } from 'ai'\n\n/**\n * Providers the browser registry can resolve from a spec. This is deliberately\n * a browser-safe subset of the Node sibling's list: Amazon Bedrock (SigV4\n * signing), Google Vertex (ADC via google-auth-library) and Cloudflare\n * (Worker bindings / process.env) are Node-only and omitted; Azure folds into\n * `openai-compatible`. `web-llm` is the local WebGPU pseudo-provider (no API\n * key). Any other runtime — Chrome/Edge built-in AI, a custom LanguageModel —\n * is passed to the agent directly and never touches this registry.\n */\nexport type ProviderType =\n | 'openai'\n | 'anthropic'\n | 'google'\n | 'openai-compatible'\n | 'xai'\n | 'deepseek'\n | 'gateway'\n | 'web-llm'\n\n/** A model described by provider + id, resolved through the registry (+ vault). */\nexport interface ProviderModelSpec {\n providerType: ProviderType\n /** Model id, e.g. \"gpt-4o-mini\", \"claude-haiku-4-5\", \"Llama-3.2-3B-Instruct-q4f16_1-MLC\". */\n model: string\n /** Provider endpoint override. Required for `openai-compatible`; a proxy URL for the rest. */\n baseURL?: string\n /** Id under which the API key is stored in the CredentialStore / vault. Preferred. */\n credentialRef?: string\n /**\n * Dev-only inline API key. Prefer `credentialRef` so the key lives encrypted\n * in the vault, not on a long-lived config object. Using this logs a warning.\n */\n apiKey?: string\n /** Extra request headers merged into the provider factory (e.g. a proxy auth header). */\n headers?: Record<string, string>\n /** Escape hatch spread into the SDK factory after baseURL / apiKey / headers. */\n providerOptions?: Record<string, unknown>\n}\n\n/**\n * A per-stage override that inherits the base provider + credentials and\n * changes only the fields it sets (typically just `model`). Distinguished from\n * a full ProviderModelSpec by the absence of `providerType`.\n */\nexport interface StageOverride {\n model?: string\n baseURL?: string\n credentialRef?: string\n apiKey?: string\n headers?: Record<string, string>\n providerOptions?: Record<string, unknown>\n}\n\n/** What a caller hands us for a model: a ready AI SDK model, or a spec to resolve. */\nexport type ModelInput = LanguageModel | ProviderModelSpec\n\n/** A model input, plus the partial-override form usable for per-stage layering. */\nexport type StageInput = ModelInput | StageOverride\n\n/** Outcome of resolving one stage: either a ready model, or a fully-resolved spec. */\nexport type ResolvedStage =\n { type: 'direct'; model: LanguageModel } | { type: 'spec'; spec: ProviderModelSpec }\n\n/** True for a ready AI SDK model: a gateway model-id string or a LanguageModelV* object. */\nexport const isDirectModel = (m: unknown): m is LanguageModel =>\n typeof m === 'string' || (typeof m === 'object' && m !== null && 'specificationVersion' in m)\n\n/** True for a full provider spec (carries the `providerType` discriminator). */\nexport const isProviderSpec = (m: unknown): m is ProviderModelSpec =>\n typeof m === 'object' &&\n m !== null &&\n !isDirectModel(m) &&\n typeof (m as { providerType?: unknown }).providerType === 'string'\n","import type { LanguageModel } from 'ai'\nimport type { CredentialStore } from '../secrets/store.js'\nimport {\n isDirectModel,\n isProviderSpec,\n type ModelInput,\n type ProviderModelSpec,\n type ProviderType,\n type ResolvedStage,\n type StageInput,\n type StageOverride,\n} from './types.js'\n\n// Providers whose endpoint the SDK cannot imply and must be given explicitly.\nconst REQUIRES_BASE_URL: ReadonlySet<ProviderType> = new Set<ProviderType>(['openai-compatible'])\n\n// Providers that authenticate without an API key.\nconst NO_KEY: ReadonlySet<ProviderType> = new Set<ProviderType>(['web-llm'])\n\n// provider -> npm package for the dynamic import and the \"please install X\"\n// message. `gateway` (ships in `ai`) and `web-llm` (its own adapter) are not here.\nconst PROVIDER_PACKAGE: Record<Exclude<ProviderType, 'gateway' | 'web-llm'>, string> = {\n openai: '@ai-sdk/openai',\n anthropic: '@ai-sdk/anthropic',\n google: '@ai-sdk/google',\n 'openai-compatible': '@ai-sdk/openai-compatible',\n xai: '@ai-sdk/xai',\n deepseek: '@ai-sdk/deepseek',\n}\n\nconst loadProvider = async <T>(pkg: string): Promise<T> => {\n try {\n // A variable dynamic import of an optional peer. Both bundler hints are\n // required: without `webpackIgnore` webpack emits \"Critical dependency:\n // the request of a dependency is an expression\" (an error under CI) and\n // tries to build a context module; without `@vite-ignore` Vite warns.\n // Bundlers thus leave the import to the runtime — bundler-less pages map\n // the bare specifier via an import map (see README), and hosts that never\n // use cloud providers (e.g. local WebLLM only) are unaffected.\n return (await import(/* webpackIgnore: true */ /* @vite-ignore */ pkg)) as T\n } catch {\n throw new Error(\n `Provider package \"${pkg}\" is not installed. Add it to your app: npm install ${pkg}`,\n )\n }\n}\n\nconst normalizeSpec = (spec: ProviderModelSpec): ProviderModelSpec => {\n if (REQUIRES_BASE_URL.has(spec.providerType) && !spec.baseURL) {\n throw new Error(`provider \"${spec.providerType}\" requires a baseURL (point it at your server)`)\n }\n return spec\n}\n\n/**\n * Resolve one stage to either a ready model or a fully-resolved spec, layering\n * an optional override on the base:\n * - a direct model (or full spec) override wins outright;\n * - a partial StageOverride inherits the base provider + credentials, changing\n * only the fields it sets (e.g. `{ model: 'gpt-4o-mini' }`);\n * - a full-spec override that switches provider MUST carry its own key\n * (credentialRef/apiKey) — inheriting a key across vendors is a footgun.\n */\nexport const resolveStage = (\n base: ModelInput,\n override: StageInput | undefined,\n stageName: string,\n): ResolvedStage => {\n if (override !== undefined && isDirectModel(override)) {\n return { type: 'direct', model: override }\n }\n if (override !== undefined && isProviderSpec(override)) {\n if (\n isProviderSpec(base) &&\n override.providerType !== base.providerType &&\n !override.credentialRef &&\n !override.apiKey &&\n !NO_KEY.has(override.providerType)\n ) {\n throw new Error(\n `${stageName}: provider \"${override.providerType}\" differs from the base \"${base.providerType}\"; set ${stageName}.credentialRef or apiKey (cross-provider key inheritance is unsafe)`,\n )\n }\n return { type: 'spec', spec: normalizeSpec(override) }\n }\n\n // No override, or a partial StageOverride to layer onto the base.\n if (isDirectModel(base)) {\n if (override && Object.keys(override).length > 0) {\n throw new Error(\n `${stageName}: cannot layer a partial override onto a direct model — pass a full model or ProviderModelSpec for ${stageName}`,\n )\n }\n return { type: 'direct', model: base }\n }\n if (!isProviderSpec(base)) {\n throw new Error(`${stageName}: base model must be a LanguageModel or a ProviderModelSpec`)\n }\n\n const ov = (override ?? {}) as StageOverride\n const merged: ProviderModelSpec = {\n providerType: base.providerType,\n model: ov.model ?? base.model,\n baseURL: ov.baseURL ?? base.baseURL,\n credentialRef: ov.credentialRef ?? base.credentialRef,\n apiKey: ov.apiKey ?? base.apiKey,\n headers: ov.headers ?? base.headers,\n providerOptions: ov.providerOptions ?? base.providerOptions,\n }\n return { type: 'spec', spec: normalizeSpec(merged) }\n}\n\nconst resolveApiKey = async (\n spec: ProviderModelSpec,\n credentials?: CredentialStore,\n): Promise<string | undefined> => {\n if (spec.apiKey) {\n console.warn(\n `[agent-web] using an inline apiKey for provider \"${spec.providerType}\"; prefer credentialRef so the key stays in the encrypted vault`,\n )\n return spec.apiKey\n }\n if (spec.credentialRef) {\n if (!credentials) {\n throw new Error(\n `credentialRef \"${spec.credentialRef}\" is set but no CredentialStore was provided to the agent`,\n )\n }\n const key = await credentials.getApiKey(spec.credentialRef)\n if (!key) {\n throw new Error(\n `no API key found in the CredentialStore for credentialRef \"${spec.credentialRef}\"`,\n )\n }\n return key\n }\n return undefined\n}\n\n/**\n * Turn a resolved stage into an AI SDK `LanguageModel`. Direct models pass\n * through untouched; specs are built by dynamically importing the provider's\n * optional-peer package and fetching the API key from the CredentialStore.\n */\nexport const buildModelFromStage = async (\n resolved: ResolvedStage,\n credentials?: CredentialStore,\n clientName = 'agent-web',\n): Promise<LanguageModel> => {\n if (resolved.type === 'direct') return resolved.model\n const spec = resolved.spec\n const providerOptions = spec.providerOptions ?? {}\n const apiKey = await resolveApiKey(spec, credentials)\n\n switch (spec.providerType) {\n case 'web-llm': {\n const { createWebLLMModel } = await import('./webllm.js')\n return createWebLLMModel(spec.model, providerOptions)\n }\n case 'gateway': {\n // The Vercel AI Gateway ships inside `ai` — no separate peer to install.\n const { createGateway } = await import('ai')\n const provider = createGateway({\n baseURL: spec.baseURL || undefined,\n apiKey,\n headers: spec.headers,\n ...providerOptions,\n })\n return provider(spec.model)\n }\n case 'openai': {\n const { createOpenAI } = await loadProvider<typeof import('@ai-sdk/openai')>(\n PROVIDER_PACKAGE.openai,\n )\n const provider = createOpenAI({\n baseURL: spec.baseURL || undefined,\n apiKey,\n headers: spec.headers,\n ...providerOptions,\n })\n return provider(spec.model)\n }\n case 'anthropic': {\n const { createAnthropic } = await loadProvider<typeof import('@ai-sdk/anthropic')>(\n PROVIDER_PACKAGE.anthropic,\n )\n const provider = createAnthropic({\n baseURL: spec.baseURL || undefined,\n apiKey,\n // Anthropic's SDK refuses browser calls unless this opt-in header is\n // set; host headers may override it.\n headers: { 'anthropic-dangerous-direct-browser-access': 'true', ...spec.headers },\n ...providerOptions,\n })\n return provider(spec.model)\n }\n case 'google': {\n const { createGoogleGenerativeAI } = await loadProvider<typeof import('@ai-sdk/google')>(\n PROVIDER_PACKAGE.google,\n )\n const provider = createGoogleGenerativeAI({\n baseURL: spec.baseURL || undefined,\n apiKey,\n headers: spec.headers,\n ...providerOptions,\n })\n return provider(spec.model)\n }\n case 'openai-compatible': {\n const { createOpenAICompatible } = await loadProvider<\n typeof import('@ai-sdk/openai-compatible')\n >(PROVIDER_PACKAGE['openai-compatible'])\n const provider = createOpenAICompatible({\n name: clientName,\n baseURL: spec.baseURL as string,\n apiKey,\n headers: spec.headers,\n ...providerOptions,\n })\n return provider(spec.model)\n }\n case 'xai': {\n const { createXai } = await loadProvider<typeof import('@ai-sdk/xai')>(PROVIDER_PACKAGE.xai)\n const provider = createXai({\n baseURL: spec.baseURL || undefined,\n apiKey,\n headers: spec.headers,\n ...providerOptions,\n })\n return provider(spec.model)\n }\n case 'deepseek': {\n const { createDeepSeek } = await loadProvider<typeof import('@ai-sdk/deepseek')>(\n PROVIDER_PACKAGE.deepseek,\n )\n const provider = createDeepSeek({\n baseURL: spec.baseURL || undefined,\n apiKey,\n headers: spec.headers,\n ...providerOptions,\n })\n return provider(spec.model)\n }\n }\n}\n\n/** Resolve a single ModelInput straight to a LanguageModel (no per-stage layering). */\nexport const resolveModel = (\n input: ModelInput,\n credentials?: CredentialStore,\n clientName?: string,\n): Promise<LanguageModel> =>\n buildModelFromStage(resolveStage(input, undefined, 'model'), credentials, clientName)\n","/**\n * Default phase prompts. Each builder returns `{ system, prompt }` strings.\n * Because the agent runs in two tool-modes, the builders switch on `ctx.mode`:\n *\n * - `native` — the model calls tools / emits schema-constrained JSON via the\n * AI SDK, so the prompts describe the task and let the SDK enforce structure.\n * - `prompted` — weak local models can't do that reliably, so the prompts spell\n * out an exact JSON shape and (for the executor) include a tool catalogue;\n * the output is salvaged by parse.ts.\n *\n * Override any builder via `BrowserAgentConfig.prompts`.\n */\n\nexport type ToolCallMode = 'native' | 'prompted'\n\nexport interface PromptParts {\n system: string\n prompt: string\n}\n\nexport interface PlannerPromptContext {\n goal: string\n state?: string\n toolCatalog: string\n mode: ToolCallMode\n /** Prior session messages (oldest first), for resolving references to earlier turns. */\n history?: { role: string; content: string }[]\n}\nexport interface ExecutorPromptContext {\n goal: string\n state?: string\n step: string\n index: number\n total: number\n toolCatalog: string\n done: string[]\n mode: ToolCallMode\n}\nexport interface ReplannerPromptContext {\n goal: string\n state?: string\n done: string[]\n remaining: string[]\n mode: ToolCallMode\n}\nexport interface SynthesizerPromptContext {\n goal: string\n state?: string\n done: string[]\n}\n\nexport interface Prompts {\n planner(ctx: PlannerPromptContext): PromptParts\n executor(ctx: ExecutorPromptContext): PromptParts\n replanner(ctx: ReplannerPromptContext): PromptParts\n synthesizer(ctx: SynthesizerPromptContext): PromptParts\n}\n\nconst numbered = (items: string[], empty: string): string =>\n items.length ? items.map((s, i) => `${i + 1}. ${s}`).join('\\n') : empty\n\nconst stateBlock = (state?: string): string => (state && state.trim() ? `\\n\\nSTATE:\\n${state}` : '')\n\nconst clip = (s: string, max: number): string => (s.length > max ? `${s.slice(0, max - 1)}…` : s)\n\n// The last few session messages, capped so a long transcript can't crowd out\n// the goal (memory compression keeps the full story in a summary message).\nconst historyBlock = (history?: { role: string; content: string }[]): string => {\n if (!history || history.length === 0) return ''\n const lines = history.slice(-8).map((m) => `${m.role}: ${clip(m.content, 400)}`)\n return `\\n\\nCONVERSATION SO FAR:\\n${lines.join('\\n')}`\n}\n\n// --- planner ---------------------------------------------------------------\n\nconst PLANNER_NATIVE = `You are the PLANNER of a tool-using agent that changes a workspace step by step.\nProduce a brief \"thought\" and an ordered \"steps\" list (1–6 DISTINCT, self-contained steps) grounded in the current STATE and the available TOOLS.\nIf the user only greets, thanks, makes small talk, asks a question, or is unclear: return an EMPTY steps list and put a short, friendly answer in \"thought\".\nIf a CONVERSATION SO FAR section is present, use it to resolve references to earlier turns.\nNever repeat or pad steps.`\n\nconst PLANNER_PROMPTED = `You are the PLANNER of a tool-using agent that changes a workspace step by step.\n\nReply with a single JSON object, nothing else:\n{ \"reply\": string, \"plan\": string[] }\n- Only produce a \"plan\" when the user CLEARLY asks to build, do, or change something. For a greeting, small talk, thanks, a question, or an unclear/empty request: set \"plan\": [] and put a short, friendly \"reply\".\n- For a real goal: \"reply\" is one short sentence; \"plan\" is 1–6 DISTINCT, self-contained steps. Never repeat or pad steps.\n- Plan realistic steps the available TOOLS can perform, grounded in the current STATE.\n- If a CONVERSATION SO FAR section is present, use it to resolve references to earlier turns.`\n\n// --- executor --------------------------------------------------------------\n\nconst EXECUTOR_NATIVE = `You are the EXECUTOR of a tool-using agent. Carry out ONLY the current step by calling the provided tools.\nBuild on the current STATE — do not repeat work that is already there.\nWhen the step is done, reply with one short human sentence describing what you did (no JSON).\nIf you CANNOT complete the step (a needed tool is missing or an input is unavailable), explain why in one sentence and include the token [BLOCKER].`\n\nconst EXECUTOR_PROMPTED = `You are the EXECUTOR of a tool-using agent. Carry out ONLY the current step by emitting tool calls.\n\nReply with a single JSON object, nothing else:\n{ \"reply\": string, \"actions\": [ { \"tool\": string, \"args\": object } ] }\n- \"actions\" are the tool calls for THIS step ([] if none are needed). Use ONLY tools from the TOOLS list; \"args\" must match the tool's parameters.\n- Build on the current STATE — do not repeat work that is already there.\n- \"reply\" is one short human sentence (no JSON) describing what you did.\n- If you CANNOT complete the step, set \"actions\": [] and put the token [BLOCKER] in \"reply\" with a short reason.`\n\n// --- replanner -------------------------------------------------------------\n\nconst REPLANNER_NATIVE = `You are the REPLANNER. After a step that was blocked or had a failed tool call, decide whether to keep going, revise the remaining steps, or finish.\n\"continue\": the remaining steps still fit. \"revise\": provide a better \"plan\" for the REMAINING work (never repeat done work). \"finish\": the goal is already met.\nJudge from the current STATE vs the goal. Prefer \"continue\".`\n\nconst REPLANNER_PROMPTED = `You are the REPLANNER. After each executed step you decide whether to keep going, revise the remaining steps, or finish.\n\nReply with a single JSON object, nothing else:\n{ \"decision\": \"continue\" | \"revise\" | \"finish\", \"reason\": string, \"plan\": string[] }\n- \"continue\": remaining steps still fit — proceed (omit \"plan\").\n- \"revise\": replace the REMAINING steps with a better list in \"plan\"; never repeat done work.\n- \"finish\": the goal is already met — stop (omit \"plan\").\nJudge from the current STATE vs the goal. Prefer \"continue\".`\n\nconst SYNTHESIZER_SYSTEM = `You are the SYNTHESIZER. In 1–3 short, friendly sentences, tell the user what was done to meet their goal. Be concrete. Output plain text only — no JSON, no code.`\n\nexport const defaultPrompts: Prompts = {\n planner: (ctx) => ({\n system: ctx.mode === 'prompted' ? PLANNER_PROMPTED : PLANNER_NATIVE,\n prompt: `GOAL: ${ctx.goal}${historyBlock(ctx.history)}${stateBlock(ctx.state)}\\n\\nTOOLS:\\n${ctx.toolCatalog}`,\n }),\n executor: (ctx) => ({\n system: ctx.mode === 'prompted' ? EXECUTOR_PROMPTED : EXECUTOR_NATIVE,\n prompt: [\n `GOAL: ${ctx.goal}`,\n stateBlock(ctx.state).trimStart(),\n ctx.mode === 'prompted' ? `TOOLS:\\n${ctx.toolCatalog}` : '',\n ctx.done.length ? `Already done:\\n${numbered(ctx.done, '')}` : '',\n `STEP ${ctx.index}/${ctx.total}: ${ctx.step}`,\n ]\n .filter(Boolean)\n .join('\\n\\n'),\n }),\n replanner: (ctx) => ({\n system: ctx.mode === 'prompted' ? REPLANNER_PROMPTED : REPLANNER_NATIVE,\n prompt: [\n `GOAL: ${ctx.goal}`,\n stateBlock(ctx.state).trimStart(),\n `Already done:\\n${numbered(ctx.done, '(nothing yet)')}`,\n `Remaining plan:\\n${numbered(ctx.remaining, '(none)')}`,\n 'Decide: continue, revise, or finish.',\n ]\n .filter(Boolean)\n .join('\\n\\n'),\n }),\n synthesizer: (ctx) => ({\n system: SYNTHESIZER_SYSTEM,\n prompt: [\n `GOAL: ${ctx.goal}`,\n stateBlock(ctx.state).trimStart(),\n `What was done:\\n${numbered(ctx.done, '(no changes)')}`,\n 'Write the final summary for the user.',\n ]\n .filter(Boolean)\n .join('\\n\\n'),\n }),\n}\n\n/** Prepend a host-supplied systemPrompt to a phase system prompt, if present. */\nexport const withSystem = (base: string, extra?: string): string =>\n extra && extra.trim() ? `${extra.trim()}\\n\\n${base}` : base\n","import type { LanguageModel } from 'ai'\nimport type { ToolMode } from '../config.js'\n\n// Local / on-device runtimes whose tiny models are unreliable at native\n// function-calling and JSON-schema output — default them to the prompted path.\nconst LOCAL_RE = /web-?llm|mlc|browser-ai|transformers|nano|built-?in/i\n\n/**\n * Decide the tool-calling strategy for a resolved model. An explicit\n * config.toolMode of 'native'/'prompted' always wins; 'auto' (default) inspects\n * the model's provider id — local/on-device runtimes → 'prompted', cloud → 'native'.\n * A string model is a gateway model id (\"openai/gpt-4o\") — always cloud; the\n * LOCAL_RE must not see it, or model names like \"gpt-5-nano\" would match `nano`.\n */\nexport const selectToolMode = (\n model: LanguageModel,\n mode: ToolMode = 'auto',\n): 'native' | 'prompted' => {\n if (mode === 'native' || mode === 'prompted') return mode\n if (typeof model === 'string') return 'native'\n const provider = (model as { provider?: string }).provider ?? ''\n return LOCAL_RE.test(provider) ? 'prompted' : 'native'\n}\n","import type { Tool, ToolSet } from 'ai'\n\n/**\n * The canonical tool shape is the AI SDK `Tool` — the same object the native\n * tool-calling path passes straight to `streamText({ tools })`, and the same\n * shape MCP tools take. We add one optional field, `promptHint`, a short\n * human-readable parameter hint (e.g. \"{ text: string, x?: number }\") used only\n * by the prompted/salvage path when it renders the tool catalogue into a text\n * prompt for weak local models.\n */\nexport type AgentTool = Tool & { promptHint?: string }\n\n/** A named collection of tools — a plain AI SDK ToolSet, usable directly. */\nexport type AgentToolSet = ToolSet\n\n/** Read the optional promptHint attached by defineTool, if any. */\nexport const promptHintOf = (tool: Tool): string | undefined =>\n typeof (tool as { promptHint?: unknown }).promptHint === 'string'\n ? (tool as { promptHint?: string }).promptHint\n : undefined\n","import type { ModelMessage, ToolSet } from 'ai'\nimport type { RawAction } from '../parse.js'\nimport type { IToolCall } from '../agent/loop-types.js'\nimport { promptHintOf, type AgentToolSet } from './types.js'\n\n/**\n * Render a ToolSet into a plain-text catalogue for the prompted/salvage path:\n * `- name(hint): description`. The hint comes from `defineTool({ promptHint })`\n * when present; weak local models lean on it to fill args correctly.\n */\nexport const renderCatalog = (tools: AgentToolSet): string => {\n const names = Object.keys(tools)\n if (names.length === 0) return '(no tools)'\n return names\n .map((name) => {\n const t = tools[name]\n const hint = promptHintOf(t) ?? ''\n const desc = typeof t.description === 'string' ? t.description : ''\n return `- ${name}(${hint}): ${desc}`\n })\n .join('\\n')\n}\n\ninterface DispatchContext {\n abortSignal?: AbortSignal\n messages?: ModelMessage[]\n toolCallId?: string\n}\n\n/**\n * Validate and execute a single salvaged tool call against the ToolSet, using\n * the tool's OWN `execute` and `inputSchema` — the identical implementation the\n * native path calls. Unknown tools, schema-invalid args, and thrown errors all\n * become a failed IToolCall rather than throwing.\n */\nexport const dispatch = async (\n action: RawAction,\n tools: ToolSet,\n ctx: DispatchContext = {},\n): Promise<IToolCall> => {\n const t = tools[action.tool]\n if (!t) {\n return {\n name: action.tool,\n input: action.args,\n output: `unknown tool \"${action.tool}\"`,\n ok: false,\n }\n }\n let input: unknown = action.args\n const schema = (t as { inputSchema?: unknown }).inputSchema\n // Best-effort Zod validation (a jsonSchema() input has no safeParse — the\n // tool's execute is expected to guard those itself).\n if (schema && typeof (schema as { safeParse?: unknown }).safeParse === 'function') {\n const parsed = (\n schema as {\n safeParse: (v: unknown) => { success: boolean; data?: unknown; error?: { message: string } }\n }\n ).safeParse(input)\n if (!parsed.success) {\n return {\n name: action.tool,\n input,\n output: `invalid args for \"${action.tool}\": ${parsed.error?.message ?? 'schema validation failed'}`,\n ok: false,\n }\n }\n input = parsed.data\n }\n const execute = (t as { execute?: (i: unknown, o: unknown) => unknown }).execute\n if (typeof execute !== 'function') {\n return { name: action.tool, input, output: `tool \"${action.tool}\" has no execute`, ok: false }\n }\n try {\n const output = await execute(input, {\n toolCallId: ctx.toolCallId ?? `prompted-${action.tool}`,\n messages: ctx.messages ?? [],\n abortSignal: ctx.abortSignal,\n })\n return { name: action.tool, input, output, ok: true }\n } catch (err) {\n return {\n name: action.tool,\n input,\n output: err instanceof Error ? err.message : 'tool error',\n ok: false,\n }\n }\n}\n","import {\n generateText,\n stepCountIs,\n streamText,\n type LanguageModel,\n type ModelMessage,\n type ToolSet,\n} from 'ai'\nimport type { IToolCall, IUsage } from '../agent/loop-types.js'\nimport { parseExecutorResponse } from '../parse.js'\nimport { dispatch } from '../tools/prompted.js'\nimport { normalizeUsage, promptOf, timeoutSignal } from './util.js'\n\nexport interface ToolLoopCallbacks {\n onTextDelta?: (delta: string) => void\n onToolCall?: (name: string, input: unknown) => void\n onToolResult?: (name: string, output: unknown, ok: boolean) => void\n}\n\nexport interface ToolLoopOptions {\n /** 'native' = SDK function-calling; 'prompted' = parse JSON out of plain text. */\n mode: 'native' | 'prompted'\n system?: string\n prompt?: string\n messages?: ModelMessage[]\n /** In native mode: the callable tools. In prompted mode: used to dispatch salvaged calls. */\n tools: ToolSet\n /**\n * Restrict callable tools to these names (plan-narrowed). Native mode passes\n * them to the SDK's `activeTools`; prompted mode bounds `dispatch` to them.\n */\n activeTools?: string[]\n /** Native mode: cap on internal tool-calling steps (default 4). */\n maxSteps?: number\n maxOutputTokens?: number\n temperature?: number\n abortSignal?: AbortSignal\n timeoutMs?: number\n callbacks?: ToolLoopCallbacks\n}\n\nexport interface ToolLoopResult {\n text: string\n toolCalls: IToolCall[]\n usage: IUsage\n}\n\n/**\n * Run one round of tool-calling in whichever mode the model needs, returning a\n * normalised result. Native mode streams the SDK's multi-step function-calling;\n * prompted mode does a single generation, salvages a `{ reply, actions }` JSON\n * from the text, and dispatches each action through the tool's own execute.\n * Both call the exact same tool implementations.\n */\nexport const runToolLoop = (\n model: LanguageModel,\n opts: ToolLoopOptions,\n): Promise<ToolLoopResult> =>\n opts.mode === 'prompted' ? runPrompted(model, opts) : runNative(model, opts)\n\nconst runNative = async (model: LanguageModel, opts: ToolLoopOptions): Promise<ToolLoopResult> => {\n const toolCalls: IToolCall[] = []\n const pending = new Map<string, { name: string; input: unknown }>()\n\n const result = streamText({\n model,\n tools: opts.tools,\n ...(opts.activeTools ? { activeTools: opts.activeTools } : {}),\n stopWhen: stepCountIs(opts.maxSteps ?? 4),\n system: opts.system,\n ...promptOf(opts),\n maxOutputTokens: opts.maxOutputTokens,\n temperature: opts.temperature,\n abortSignal: timeoutSignal(opts.abortSignal, opts.timeoutMs),\n })\n\n for await (const part of result.fullStream) {\n switch (part.type) {\n case 'text-delta':\n if (part.text) opts.callbacks?.onTextDelta?.(part.text)\n break\n case 'tool-call':\n pending.set(part.toolCallId, { name: part.toolName, input: part.input })\n opts.callbacks?.onToolCall?.(part.toolName, part.input)\n break\n case 'tool-result': {\n const known = pending.get(part.toolCallId)\n toolCalls.push({\n name: part.toolName,\n input: known?.input ?? part.input,\n output: part.output,\n ok: true,\n })\n opts.callbacks?.onToolResult?.(part.toolName, part.output, true)\n pending.delete(part.toolCallId)\n break\n }\n case 'tool-error': {\n const known = pending.get(part.toolCallId)\n toolCalls.push({\n name: part.toolName,\n input: known?.input ?? part.input,\n output: part.error,\n ok: false,\n })\n opts.callbacks?.onToolResult?.(part.toolName, part.error, false)\n pending.delete(part.toolCallId)\n break\n }\n case 'error':\n throw part.error instanceof Error ? part.error : new Error(String(part.error))\n }\n }\n\n const [text, usage] = await Promise.all([result.text, result.usage])\n return { text: text.trim(), toolCalls, usage: normalizeUsage(usage) }\n}\n\nconst runPrompted = async (\n model: LanguageModel,\n opts: ToolLoopOptions,\n): Promise<ToolLoopResult> => {\n // Prompted mode does NOT pass tools to the SDK — the tool catalogue is\n // already rendered into the prompt (see tools/prompted.ts renderCatalog); the\n // model replies with JSON, which we salvage and dispatch ourselves.\n const result = await generateText({\n model,\n system: opts.system,\n ...promptOf(opts),\n maxOutputTokens: opts.maxOutputTokens,\n temperature: opts.temperature,\n abortSignal: timeoutSignal(opts.abortSignal, opts.timeoutMs),\n })\n\n const parsed = parseExecutorResponse(result.text)\n // Surface the parsed human reply, never the raw JSON envelope.\n if (parsed.reply) opts.callbacks?.onTextDelta?.(parsed.reply)\n\n const active = opts.activeTools\n const tools = active\n ? Object.fromEntries(Object.entries(opts.tools).filter(([name]) => active.includes(name)))\n : opts.tools\n const toolCalls: IToolCall[] = []\n for (const action of parsed.actions) {\n opts.callbacks?.onToolCall?.(action.tool, action.args)\n const rec = await dispatch(action, tools, { abortSignal: opts.abortSignal })\n toolCalls.push(rec)\n opts.callbacks?.onToolResult?.(rec.name, rec.output, rec.ok)\n }\n return { text: parsed.reply, toolCalls, usage: normalizeUsage(result.usage) }\n}\n","/**\n * Robust parsing of model output. Small in-browser models emit JSON wrapped in\n * prose or code fences, truncate it mid-token when they loop, or drift to plain\n * text. Every parser here is defensive: it salvages what it can and NEVER\n * throws, and it never surfaces raw JSON as user-facing text. This is the\n * backbone of the \"prompted\" tool-mode (see tools/mode.ts).\n */\n\n/** A tool the executor asked to run. */\nexport interface RawAction {\n tool: string\n args: Record<string, unknown>\n}\n\nexport type ReplanDecision = 'continue' | 'revise' | 'finish'\n\nconst stripFences = (text: string): string => (text || '').replace(/```(?:json)?/gi, '').trim()\n\n/** Extracts the first balanced {...} or [...] block, respecting strings. */\nconst extractBalanced = (text: string, open: '{' | '['): string | undefined => {\n const close = open === '{' ? '}' : ']'\n const start = text.indexOf(open)\n if (start < 0) return undefined\n let depth = 0\n let inStr = false\n let esc = false\n for (let i = start; i < text.length; i += 1) {\n const c = text[i]\n if (inStr) {\n if (esc) esc = false\n else if (c === '\\\\') esc = true\n else if (c === '\"') inStr = false\n continue\n }\n if (c === '\"') inStr = true\n else if (c === open) depth += 1\n else if (c === close) {\n depth -= 1\n if (depth === 0) return text.slice(start, i + 1)\n }\n }\n return undefined\n}\n\nconst tryParse = (s: string | undefined): unknown => {\n if (!s) return undefined\n try {\n return JSON.parse(s)\n } catch {\n return undefined\n }\n}\n\n/** True when a string is (or is dominated by) raw JSON — kept out of the UI. */\nexport const looksLikeJson = (s: string): boolean => {\n const t = (s || '').trim()\n return (\n t.startsWith('{') ||\n t.startsWith('[') ||\n /\"(tool|args|plan|reply|actions|decision)\"\\s*:/.test(t)\n )\n}\n\nconst asObject = (text: string): Record<string, unknown> | undefined => {\n const v = tryParse(text) ?? tryParse(extractBalanced(text, '{'))\n return v && typeof v === 'object' && !Array.isArray(v)\n ? (v as Record<string, unknown>)\n : undefined\n}\n\n/** Trim, drop empties, de-duplicate (case-insensitive), cap length. */\nexport const normalizeSteps = (arr: unknown, cap = 12): string[] => {\n if (!Array.isArray(arr)) return []\n const seen: Record<string, boolean> = {}\n const out: string[] = []\n for (const s of arr) {\n if (out.length >= cap || typeof s !== 'string') continue\n const step = s.trim()\n const key = step.toLowerCase()\n if (!step || seen[key]) continue\n seen[key] = true\n out.push(step)\n }\n return out\n}\n\n/** Decode a JSON string body (\\\" \\\\n \\\\uXXXX …); falls back to the raw text. */\nconst decodeJsonString = (body: string): string => {\n const v = tryParse(`\"${body}\"`)\n return typeof v === 'string' ? v : body\n}\n\n/**\n * Pull \"...\"-quoted strings out of a (possibly truncated) named array. The scan\n * is bounded to the array itself — from its `[` to the matching `]`, or the end\n * of the text when truncated — so values of LATER fields are never swept in.\n */\nconst salvageStringArray = (text: string, field: string): string[] => {\n const m = new RegExp(`\"${field}\"\\\\s*:\\\\s*\\\\[`).exec(text)\n if (!m) return []\n const out: string[] = []\n let i = m.index + m[0].length\n while (i < text.length && text[i] !== ']') {\n if (text[i] !== '\"') {\n i += 1\n continue\n }\n let j = i + 1\n let esc = false\n while (j < text.length && (esc || text[j] !== '\"')) {\n esc = !esc && text[j] === '\\\\'\n j += 1\n }\n if (j >= text.length) break // truncated mid-string — drop the fragment\n out.push(decodeJsonString(text.slice(i + 1, j)))\n i = j + 1\n }\n return out\n}\n\nconst salvageString = (text: string, field: string): string => {\n const m = text.match(new RegExp(`\"${field}\"\\\\s*:\\\\s*\"((?:[^\"\\\\\\\\]|\\\\\\\\.)*)\"`))\n return m ? decodeJsonString(m[1]).trim() : ''\n}\n\n// --- planner ---------------------------------------------------------------\n\nexport interface PlannerResult {\n reply: string\n plan: string[]\n}\n\nexport const parsePlannerResponse = (raw: string): PlannerResult => {\n const text = stripFences(raw)\n const obj = asObject(text)\n if (obj) {\n const reply = typeof obj.reply === 'string' ? obj.reply.trim() : ''\n return { reply, plan: normalizeSteps(obj.plan) }\n }\n if (/\"plan\"\\s*:/.test(text)) {\n return {\n reply: salvageString(text, 'reply'),\n plan: normalizeSteps(salvageStringArray(text, 'plan')),\n }\n }\n return { reply: looksLikeJson(text) ? '' : text.trim(), plan: [] }\n}\n\n// --- executor (tool calls) -------------------------------------------------\n\nexport interface ExecutorResult {\n reply: string\n actions: RawAction[]\n}\n\nconst toActions = (value: unknown): RawAction[] => {\n if (!Array.isArray(value)) return []\n const out: RawAction[] = []\n for (const a of value) {\n if (a && typeof a === 'object' && typeof (a as { tool?: unknown }).tool === 'string') {\n const rec = a as { tool: string; args?: unknown }\n out.push({\n tool: rec.tool,\n args:\n rec.args && typeof rec.args === 'object' && !Array.isArray(rec.args)\n ? (rec.args as Record<string, unknown>)\n : {},\n })\n }\n }\n return out\n}\n\nexport const parseExecutorResponse = (raw: string): ExecutorResult => {\n const text = stripFences(raw)\n const obj = asObject(text)\n if (obj) {\n const reply = typeof obj.reply === 'string' ? obj.reply.trim() : ''\n return { reply, actions: toActions(obj.actions) }\n }\n // Bare actions array.\n const arr = tryParse(extractBalanced(text, '['))\n if (Array.isArray(arr)) {\n const actions = toActions(arr)\n return { reply: '', actions }\n }\n return { reply: looksLikeJson(text) ? '' : text.trim(), actions: [] }\n}\n\n// --- replanner -------------------------------------------------------------\n\nexport interface ReplannerResult {\n decision: ReplanDecision\n reason: string\n plan: string[]\n}\n\nexport const parseReplannerResponse = (raw: string): ReplannerResult => {\n const obj = asObject(stripFences(raw))\n const decision: ReplanDecision =\n obj?.decision === 'revise' || obj?.decision === 'finish' ? obj.decision : 'continue'\n const reason = typeof obj?.reason === 'string' ? obj.reason.trim() : ''\n return { decision, reason, plan: normalizeSteps(obj?.plan) }\n}\n\n// --- plain text (synthesizer / chat answers) -------------------------------\n\n/** Extracts a clean human sentence, never raw JSON. */\nexport const parsePlainText = (raw: string): string => {\n const text = stripFences(raw)\n const obj = asObject(text)\n if (obj && typeof obj.reply === 'string') return obj.reply.trim()\n return looksLikeJson(text) ? '' : text.trim()\n}\n","import type { LanguageModel } from 'ai'\nimport type { BrowserAgentConfig, ResolvedConfig } from '../config.js'\nimport type { AgentEvent } from '../events.js'\nimport type { StoredMessage } from '../memory/store.js'\nimport type { Prompts, ToolCallMode } from '../prompts.js'\nimport { withSystem } from '../prompts.js'\nimport type { AgentToolSet } from '../tools/types.js'\n\n/** Everything the phase functions (planner/executor/replanner/synthesizer) share. */\nexport interface AgentContext {\n config: ResolvedConfig\n raw: BrowserAgentConfig\n plannerModel: LanguageModel\n executorModel: LanguageModel\n synthesizerModel: LanguageModel\n /** Tool-mode for the planner/replanner (from the planner model). */\n plannerMode: ToolCallMode\n /** Tool-mode for the executor (from the executor model). */\n executorMode: ToolCallMode\n tools: AgentToolSet\n toolCatalog: string\n prompts: Prompts\n emit: (event: AgentEvent) => void\n signal?: AbortSignal\n /** Current world state for grounding, or undefined when no describeState is configured. */\n state: () => Promise<string | undefined>\n /** Session transcript loaded from memory BEFORE this run's goal was appended. */\n history?: StoredMessage[]\n}\n\n/** Prepend the host's systemPrompt to a phase system prompt. */\nexport const systemFor = (ctx: AgentContext, base: string): string =>\n withSystem(base, ctx.raw.systemPrompt)\n\nexport const aborted = (ctx: AgentContext): boolean => ctx.signal?.aborted === true\n","import { runToolLoop } from '../llm/tool-loop.js'\nimport { renderCatalog } from '../tools/prompted.js'\nimport type { IPlanStep, IStepResult, IUsage } from './loop-types.js'\nimport { systemFor, type AgentContext } from './internal.js'\n\nconst BLOCKER = '[BLOCKER]'\n\n/**\n * Split the executor's reply into a clean summary and a structural `blocked`\n * flag. The [BLOCKER] sentinel — emitted by the executor when it can't complete\n * a step — is language-agnostic and drives the replanner; we strip every copy\n * so it never leaks into downstream prompts.\n */\nexport const splitBlocker = (raw: string): { summary: string; blocked: boolean } => {\n if (!raw.includes(BLOCKER)) return { summary: raw.trim(), blocked: false }\n return { summary: raw.split(BLOCKER).join('').trim(), blocked: true }\n}\n\nconst activeToolNames = (ctx: AgentContext, step: IPlanStep): string[] | undefined => {\n if (ctx.config.toolSelectionStrategy !== 'plan-narrowed') return undefined\n const suggested = step.suggestedTools ?? []\n const known = suggested.filter((n) => ctx.tools[n])\n // A step that named tools but all were unknown still wants tools: fall back to\n // the full set rather than stalling with zero.\n if (known.length === 0 && suggested.length > 0) return Object.keys(ctx.tools)\n return known\n}\n\nconst summaryOf = (text: string, toolCallCount: number): string => {\n if (text.length > 0) return text\n return toolCallCount > 0 ? `Executed ${toolCallCount} tool call(s).` : 'Step produced no output.'\n}\n\n/** Execute one plan step: run the tool loop (native or prompted) and emit events. */\nexport const executeStep = async (\n ctx: AgentContext,\n goal: string,\n step: IPlanStep,\n index: number,\n total: number,\n done: string[],\n): Promise<{ result: IStepResult; usage: IUsage }> => {\n const state = await ctx.state()\n // Under plan-narrowed selection the prompted path must also see the narrowed\n // catalogue — the prompt is its only tool surface (native mode gets the SDK's\n // activeTools instead and never renders the catalogue).\n const active = activeToolNames(ctx, step)\n const toolCatalog =\n active === undefined\n ? ctx.toolCatalog\n : renderCatalog(Object.fromEntries(active.map((name) => [name, ctx.tools[name]])))\n const parts = ctx.prompts.executor({\n goal,\n state,\n step: step.description,\n index,\n total,\n toolCatalog,\n done,\n mode: ctx.executorMode,\n })\n\n const loop = await runToolLoop(ctx.executorModel, {\n mode: ctx.executorMode,\n system: systemFor(ctx, parts.system),\n prompt: parts.prompt,\n tools: ctx.tools,\n activeTools: active,\n maxSteps: ctx.config.maxStepsPerTask,\n maxOutputTokens: ctx.config.budgets.executor,\n temperature: ctx.config.temperature,\n abortSignal: ctx.signal,\n timeoutMs: ctx.config.chatTimeoutMs,\n callbacks: {\n onTextDelta: (delta) => ctx.emit({ type: 'step.text-delta', step, delta }),\n onToolCall: (name, input) => ctx.emit({ type: 'step.tool-call', step, name, input }),\n onToolResult: (name, output, ok) =>\n ctx.emit({ type: 'step.tool-result', step, name, output, ok }),\n },\n })\n\n const { summary, blocked } = splitBlocker(loop.text)\n return {\n result: {\n step,\n summary: summaryOf(summary, loop.toolCalls.length),\n toolCalls: loop.toolCalls,\n blocked,\n },\n usage: loop.usage,\n }\n}\n\n/** The replanner runs when a step was blocked or any of its tool calls failed. */\nexport const shouldReplan = (result: IStepResult): boolean =>\n result.blocked || result.toolCalls.some((c) => !c.ok)\n","/** A single step of a plan. Mirrors the Node sibling's IPlanStep. */\nexport interface IPlanStep {\n id: string\n description: string\n expectedOutcome?: string\n /** Tools the planner thinks this step needs (drives 'plan-narrowed' selection). */\n suggestedTools?: string[]\n /** Set by the pipeline when suggestedTools were named but all were unknown. */\n requiresTools?: boolean\n}\n\nexport interface IPlan {\n thought: string\n steps: IPlanStep[]\n}\n\nexport interface IUsage {\n inputTokens: number\n outputTokens: number\n totalTokens: number\n}\n\nexport interface IToolCall {\n name: string\n input: unknown\n output: unknown\n ok: boolean\n}\n\nexport interface IStepResult {\n step: IPlanStep\n summary: string\n toolCalls: IToolCall[]\n /** True when the executor signalled it could not complete the step ([BLOCKER]). */\n blocked: boolean\n}\n\nexport const emptyUsage = (): IUsage => ({ inputTokens: 0, outputTokens: 0, totalTokens: 0 })\n\nexport const addUsage = (a: IUsage, b: IUsage): IUsage => ({\n inputTokens: a.inputTokens + b.inputTokens,\n outputTokens: a.outputTokens + b.outputTokens,\n totalTokens: a.totalTokens + b.totalTokens,\n})\n","import { z } from 'zod'\n\n/**\n * Structured-output schemas for the native path (generateObject). Kept free of\n * `.max()`/`.min()` constraints — some providers reject or mis-handle them in\n * JSON-schema mode; we cap/clean in code instead (see parse.ts normalizeSteps).\n */\nexport const PlanStepSchema = z.object({\n description: z.string(),\n expectedOutcome: z.string().optional(),\n suggestedTools: z.array(z.string()).optional(),\n})\n\nexport const PlanSchema = z.object({\n /** One short sentence. For a greeting/question/unclear request, holds the answer and steps is empty. */\n thought: z.string(),\n steps: z.array(PlanStepSchema),\n})\n\nexport const ReplanSchema = z.object({\n decision: z.enum(['continue', 'revise', 'finish']),\n reason: z.string(),\n /** Replacement for the REMAINING steps when decision is 'revise'. */\n plan: z.array(z.string()).optional(),\n})\n\nexport type PlanShape = z.infer<typeof PlanSchema>\nexport type ReplanShape = z.infer<typeof ReplanSchema>\n","import { generate, generateStructured } from '../llm/generate.js'\nimport { normalizeUsage } from '../llm/util.js'\nimport { parsePlannerResponse } from '../parse.js'\nimport type { ToolCallMode } from '../prompts.js'\nimport type { IPlan, IUsage } from './loop-types.js'\nimport { systemFor, type AgentContext } from './internal.js'\nimport { PlanSchema } from './schemas.js'\n\nconst toSteps = (\n raw: { description: string; expectedOutcome?: string; suggestedTools?: string[] }[],\n): IPlan['steps'] =>\n raw\n .filter((s) => s.description && s.description.trim())\n .map((s, i) => ({\n id: `s${i + 1}`,\n description: s.description.trim(),\n expectedOutcome: s.expectedOutcome,\n suggestedTools: s.suggestedTools,\n }))\n\n/**\n * Build the initial plan. Native mode uses generateObject(PlanSchema); prompted\n * mode salvages `{ reply, plan }` from plain text. Native failures (a weak model\n * that can't satisfy the schema) fall back to the prompted parse rather than\n * throwing, so the run degrades gracefully. An empty `steps` list signals the\n * runner to answer directly (greeting / question / unclear).\n */\nexport const createPlan = async (\n ctx: AgentContext,\n goal: string,\n): Promise<{ plan: IPlan; usage: IUsage }> => {\n const state = await ctx.state()\n const commonFor = (mode: ToolCallMode) => {\n const parts = ctx.prompts.planner({\n goal,\n state,\n toolCatalog: ctx.toolCatalog,\n mode,\n history: ctx.history,\n })\n return {\n system: systemFor(ctx, parts.system),\n prompt: parts.prompt,\n maxOutputTokens: ctx.config.budgets.planner,\n temperature: ctx.config.temperature,\n abortSignal: ctx.signal,\n timeoutMs: ctx.config.chatTimeoutMs,\n }\n }\n\n if (ctx.plannerMode === 'native') {\n try {\n const result = await generateStructured(ctx.plannerModel, PlanSchema, commonFor('native'))\n return {\n plan: { thought: result.object.thought, steps: toSteps(result.object.steps) },\n usage: normalizeUsage(result.usage),\n }\n } catch (err) {\n // Graceful degradation: fall back to the salvage parser instead of failing.\n ctx.emit({ type: 'retry', phase: 'plan', attempt: 1, error: asMessage(err) })\n }\n }\n\n // The prompted path — also the fallback after a native failure. Rendered with\n // mode 'prompted' so the model gets explicit JSON-shape instructions even\n // when the schema-constrained call just failed.\n const result = await generate(ctx.plannerModel, commonFor('prompted'))\n const parsed = parsePlannerResponse(result.text)\n return {\n plan: {\n thought: parsed.reply,\n steps: toSteps(parsed.plan.map((description) => ({ description }))),\n },\n usage: normalizeUsage(result.usage),\n }\n}\n\nconst asMessage = (err: unknown): string => (err instanceof Error ? err.message : String(err))\n","import { generate, generateStructured } from '../llm/generate.js'\nimport { normalizeUsage } from '../llm/util.js'\nimport { parseReplannerResponse, type ReplanDecision } from '../parse.js'\nimport type { ToolCallMode } from '../prompts.js'\nimport type { IUsage } from './loop-types.js'\nimport { emptyUsage } from './loop-types.js'\nimport { systemFor, type AgentContext } from './internal.js'\nimport { ReplanSchema } from './schemas.js'\n\nexport interface ReplanOutcome {\n decision: ReplanDecision\n reason: string\n /** Replacement remaining steps (descriptions) when decision is 'revise'. */\n plan: string[]\n usage: IUsage\n}\n\n/**\n * Decide whether to continue, revise the remaining plan, or finish, after a\n * blocked/failed step. Native mode uses generateObject(ReplanSchema); prompted\n * mode salvages the decision from text. Any failure degrades to 'continue' so a\n * flaky replanner never aborts the run.\n */\nexport const decideReplan = async (\n ctx: AgentContext,\n goal: string,\n done: string[],\n remaining: string[],\n): Promise<ReplanOutcome> => {\n const state = await ctx.state()\n const commonFor = (mode: ToolCallMode) => {\n const parts = ctx.prompts.replanner({ goal, state, done, remaining, mode })\n return {\n system: systemFor(ctx, parts.system),\n prompt: parts.prompt,\n maxOutputTokens: ctx.config.budgets.replanner,\n temperature: ctx.config.temperature,\n abortSignal: ctx.signal,\n timeoutMs: ctx.config.chatTimeoutMs,\n }\n }\n\n if (ctx.plannerMode === 'native') {\n try {\n const result = await generateStructured(ctx.plannerModel, ReplanSchema, commonFor('native'))\n return {\n decision: result.object.decision,\n reason: result.object.reason,\n plan: result.object.plan ?? [],\n usage: normalizeUsage(result.usage),\n }\n } catch {\n /* fall through to the prompted salvage below */\n }\n }\n\n try {\n // The prompted path — also the fallback after a native failure, re-rendered\n // with explicit JSON-shape instructions.\n const result = await generate(ctx.plannerModel, commonFor('prompted'))\n const parsed = parseReplannerResponse(result.text)\n return {\n decision: parsed.decision,\n reason: parsed.reason,\n plan: parsed.plan,\n usage: normalizeUsage(result.usage),\n }\n } catch {\n return { decision: 'continue', reason: 'replanner unavailable', plan: [], usage: emptyUsage() }\n }\n}\n","import { stream } from '../llm/generate.js'\nimport { normalizeUsage } from '../llm/util.js'\nimport { looksLikeJson, parsePlainText } from '../parse.js'\nimport type { IUsage } from './loop-types.js'\nimport { systemFor, type AgentContext } from './internal.js'\n\n/**\n * Write the final natural-language summary of what the run accomplished,\n * streaming it as `final.text-delta` events. Plain text only (parsePlainText\n * strips any stray JSON; deltas are suppressed entirely when the model drifts\n * into JSON, so raw structure never reaches a UI). Falls back to a default\n * sentence if the model returns nothing usable.\n */\nexport const synthesizeAnswer = async (\n ctx: AgentContext,\n goal: string,\n done: string[],\n): Promise<{ text: string; usage: IUsage }> => {\n const state = await ctx.state()\n const parts = ctx.prompts.synthesizer({ goal, state, done })\n const result = stream(ctx.synthesizerModel, {\n system: systemFor(ctx, parts.system),\n prompt: parts.prompt,\n maxOutputTokens: ctx.config.budgets.synthesizer,\n temperature: ctx.config.temperature,\n abortSignal: ctx.signal,\n timeoutMs: ctx.config.chatTimeoutMs,\n })\n\n let text = ''\n let verdict: 'unknown' | 'emit' | 'suppress' = 'unknown'\n for await (const delta of result.textStream) {\n text += delta\n if (verdict === 'unknown') {\n const lead = text.trimStart()\n if (!lead) continue\n verdict = looksLikeJson(lead) ? 'suppress' : 'emit'\n if (verdict === 'emit') ctx.emit({ type: 'final.text-delta', delta: text })\n } else if (verdict === 'emit') {\n ctx.emit({ type: 'final.text-delta', delta })\n }\n }\n\n const clean = parsePlainText(text)\n return {\n text: clean || 'Done — the changes have been applied.',\n usage: normalizeUsage(await result.usage),\n }\n}\n","import type { LanguageModel } from 'ai'\nimport type { BrowserAgentConfig } from '../config.js'\nimport { resolveConfig } from '../config.js'\nimport type { AgentEvent, AgentEventHandler, Phase } from '../events.js'\nimport { compressHistory } from '../memory/compress.js'\nimport type { StoredMessage } from '../memory/store.js'\nimport { buildModelFromStage, resolveStage } from '../providers/registry.js'\nimport { defaultPrompts, type Prompts } from '../prompts.js'\nimport { selectToolMode } from '../tools/mode.js'\nimport { renderCatalog } from '../tools/prompted.js'\nimport type { AgentToolSet } from '../tools/types.js'\nimport { executeStep, shouldReplan } from './executor.js'\nimport type { AgentContext } from './internal.js'\nimport {\n addUsage,\n emptyUsage,\n type IPlan,\n type IPlanStep,\n type IStepResult,\n type IUsage,\n} from './loop-types.js'\nimport { createPlan } from './planner.js'\nimport { decideReplan } from './replanner.js'\nimport { synthesizeAnswer } from './synthesizer.js'\n\nexport interface RunOptions {\n onEvent?: AgentEventHandler\n signal?: AbortSignal\n /** Override the config's sessionId for this run. */\n sessionId?: string\n}\n\nexport interface RunResult {\n goal: string\n final: string\n plan: IPlan\n trace: IStepResult[]\n steps: number\n /** Total successful tool calls across the run. */\n applied: number\n stopped: boolean\n usage: IUsage\n}\n\nexport interface Agent {\n run(goal: string, opts?: RunOptions): Promise<RunResult>\n /** The resolved models, for hosts that want to reuse them (e.g. warm-up). */\n readonly models: {\n planner: LanguageModel\n executor: LanguageModel\n synthesizer: LanguageModel\n }\n}\n\nconst errMessage = (err: unknown): string => (err instanceof Error ? err.message : String(err))\n\n/** Apply the config's availableTools whitelist and excludedTools blacklist. */\nconst filterTools = (\n all: AgentToolSet,\n available?: string[],\n excluded?: string[],\n): AgentToolSet => {\n let entries = Object.entries(all)\n if (available && available.length > 0) entries = entries.filter(([n]) => available.includes(n))\n if (excluded && excluded.length > 0) entries = entries.filter(([n]) => !excluded.includes(n))\n return Object.fromEntries(entries)\n}\n\n/**\n * Create a headless plan → execute → replan → synthesize agent. Models are\n * resolved eagerly (dynamic provider imports + vault key fetch), so this is\n * async. Each `run` streams typed AgentEvents for any UI to render.\n */\nexport const createAgent = async (config: BrowserAgentConfig): Promise<Agent> => {\n const cfg = resolveConfig(config)\n // Build the executor once; a stage without an override reuses it instead of\n // constructing a second identical model (for web-llm that would mean loading\n // the same weights into the GPU again).\n const buildStage = (override: BrowserAgentConfig['planner'], stageName: string) =>\n buildModelFromStage(\n resolveStage(config.model, override, stageName),\n config.credentials,\n cfg.clientName,\n )\n const executorP = buildStage(undefined, 'executor')\n const [executorModel, plannerModel, synthesizerModel] = await Promise.all([\n executorP,\n config.planner === undefined ? executorP : buildStage(config.planner, 'planner'),\n config.synthesizer === undefined ? executorP : buildStage(config.synthesizer, 'synthesizer'),\n ])\n\n const plannerMode = selectToolMode(plannerModel, cfg.toolMode)\n const executorMode = selectToolMode(executorModel, cfg.toolMode)\n const tools: AgentToolSet = filterTools(\n config.tools ?? {},\n config.availableTools,\n config.excludedTools,\n )\n const toolCatalog = renderCatalog(tools)\n const prompts: Prompts = { ...defaultPrompts, ...config.prompts }\n\n const run = async (goal: string, opts: RunOptions = {}): Promise<RunResult> => {\n const emit = (event: AgentEvent): void => {\n try {\n opts.onEvent?.(event)\n } catch {\n /* a bad handler must not break the run */\n }\n }\n const text = goal.trim()\n const sessionId = opts.sessionId ?? cfg.sessionId\n let usage = emptyUsage()\n const result: RunResult = {\n goal: text,\n final: '',\n plan: { thought: '', steps: [] },\n trace: [],\n steps: 0,\n applied: 0,\n stopped: false,\n usage,\n }\n if (!text) return result\n\n const state = async (): Promise<string | undefined> =>\n config.describeState ? config.describeState() : undefined\n const isAborted = (): boolean => opts.signal?.aborted === true\n const bumpUsage = (u: IUsage, phase: Phase): void => {\n usage = addUsage(usage, u)\n result.usage = usage\n emit({ type: 'usage', phase, usage: u })\n }\n const remember = async (msg: StoredMessage): Promise<void> => {\n if (!config.memory) return\n try {\n await config.memory.append(sessionId, msg)\n } catch {\n /* persistence is best-effort */\n }\n }\n\n emit({ type: 'run.start', goal: text })\n // Read back the session transcript BEFORE appending the current goal, so\n // the planner can resolve references to earlier turns (\"make it bigger\").\n let history: StoredMessage[] = []\n if (config.memory) {\n try {\n history = await config.memory.load(sessionId)\n } catch {\n /* persistence is best-effort */\n }\n }\n const ctx: AgentContext = {\n config: cfg,\n raw: config,\n plannerModel,\n executorModel,\n synthesizerModel,\n plannerMode,\n executorMode,\n tools,\n toolCatalog,\n prompts,\n emit,\n signal: opts.signal,\n state,\n history,\n }\n await remember({ role: 'user', content: text })\n\n try {\n // 1) PLAN\n const planned = await createPlan(ctx, text)\n bumpUsage(planned.usage, 'plan')\n result.plan = planned.plan\n if (isAborted()) {\n emit({ type: 'stopped' })\n result.stopped = true\n return result\n }\n\n // Greeting / question / unclear → answer directly, run no tools.\n if (planned.plan.steps.length === 0) {\n const answer = planned.plan.thought.trim() || \"Tell me what you'd like to do.\"\n emit({ type: 'final', text: answer })\n await remember({ role: 'assistant', content: answer })\n result.final = answer\n return result\n }\n emit({ type: 'plan.created', plan: planned.plan })\n planned.plan.steps.forEach((step, index) => emit({ type: 'plan.step-added', step, index }))\n\n // 2) EXECUTE → REPLAN\n const done: string[] = []\n let remaining: IPlanStep[] = [...planned.plan.steps]\n let iter = 0\n let revisions = 0\n while (remaining.length > 0 && iter < cfg.maxIterations) {\n if (isAborted()) {\n emit({ type: 'stopped' })\n result.stopped = true\n return result\n }\n iter += 1\n const step = remaining.shift() as IPlanStep\n const stepNo = done.length + 1\n const total = stepNo + remaining.length\n emit({ type: 'step.start', step, index: stepNo, total })\n\n let stepResult: IStepResult\n try {\n const out = await executeStep(ctx, text, step, stepNo, total, done)\n bumpUsage(out.usage, 'execute')\n stepResult = out.result\n } catch (err) {\n // A user abort surfaces as a thrown AbortError — that is a stop, not\n // a step failure.\n if (isAborted()) {\n emit({ type: 'stopped' })\n result.stopped = true\n return result\n }\n emit({ type: 'error', phase: 'execute', error: errMessage(err) })\n stepResult = { step, summary: errMessage(err), toolCalls: [], blocked: true }\n }\n\n result.trace.push(stepResult)\n const applied = stepResult.toolCalls.filter((c) => c.ok).length\n const failed = stepResult.toolCalls.length - applied\n result.applied += applied\n result.steps = stepNo\n emit({ type: 'step.complete', step, result: stepResult })\n done.push(\n `${step.description} — ${applied} applied${failed ? `, ${failed} failed` : ''}${stepResult.blocked ? ', blocked' : ''}`,\n )\n\n // 2b) REPLAN (only after a blocked / failed step). Also runs when the\n // FAILED step was the last one — 'revise' can then add remedial steps.\n if (\n cfg.replan &&\n iter < cfg.maxIterations &&\n revisions < cfg.maxRevisions &&\n !isAborted() &&\n shouldReplan(stepResult)\n ) {\n const decision = await decideReplan(\n ctx,\n text,\n done,\n remaining.map((s) => s.description),\n )\n bumpUsage(decision.usage, 'replan')\n emit({ type: 'replan.decision', mode: decision.decision, reason: decision.reason })\n if (decision.decision === 'finish') break\n if (decision.decision === 'revise' && decision.plan.length > 0) {\n revisions += 1\n remaining = decision.plan\n .slice(0, cfg.maxIterations - iter)\n .map((description, i) => ({ id: `r${iter}-${i + 1}`, description }))\n emit({\n type: 'plan.revised',\n plan: { thought: planned.plan.thought, steps: remaining },\n reason: decision.reason,\n })\n }\n }\n }\n\n if (isAborted()) {\n emit({ type: 'stopped' })\n result.stopped = true\n return result\n }\n\n // 3) SYNTHESIZE\n let summary = 'Done — the changes have been applied.'\n if (cfg.synthesize) {\n try {\n const synth = await synthesizeAnswer(ctx, text, done)\n bumpUsage(synth.usage, 'synthesize')\n if (synth.text) summary = synth.text\n } catch {\n /* keep the default */\n }\n }\n emit({ type: 'final', text: summary })\n await remember({ role: 'assistant', content: summary })\n result.final = summary\n\n // 4) COMPRESS persisted history\n if (config.memory && cfg.compressAfterChars > 0) {\n try {\n const transcript = await config.memory.load(sessionId)\n const compacted = await compressHistory(transcript, synthesizerModel, {\n maxChars: cfg.compressAfterChars,\n timeoutMs: cfg.chatTimeoutMs,\n abortSignal: opts.signal,\n })\n if (compacted !== transcript) await config.memory.replace(sessionId, compacted)\n } catch {\n /* best-effort */\n }\n }\n return result\n } catch (err) {\n emit({ type: 'error', phase: 'run', error: errMessage(err) })\n result.final = errMessage(err)\n return result\n }\n }\n\n return {\n run,\n models: { planner: plannerModel, executor: executorModel, synthesizer: synthesizerModel },\n }\n}\n","import type { ProviderType } from './types.js'\n\n// Cloud providers are reliable at native function-calling and JSON-schema\n// structured output. Local WebGPU models (web-llm) technically support both,\n// but tiny (1–3B) models are unreliable at them, so we default local models to\n// the prompted/salvage path (overridable via config.toolMode).\nconst CLOUD: ReadonlySet<ProviderType> = new Set<ProviderType>([\n 'openai',\n 'anthropic',\n 'google',\n 'openai-compatible',\n 'xai',\n 'deepseek',\n 'gateway',\n])\n\n/** Whether native tool-calling is reliable enough to be the default for a provider. */\nexport const supportsNativeTools = (p: ProviderType): boolean => CLOUD.has(p)\n\n/** Whether native structured output (generateObject) is the default for a provider. */\nexport const supportsStructuredOutput = (p: ProviderType): boolean => CLOUD.has(p)\n\n/**\n * Whether calling this provider straight from a browser origin with a BYOK key\n * is expected to work (CORS + browser-access policy). Hosts can use this to\n * warn users before a direct call fails.\n *\n * - `google`: Gemini's endpoint is CORS-enabled — the most reliable direct BYOK path.\n * - `gateway` / `openai-compatible`: the host controls the endpoint / CORS.\n * - `anthropic`: works, but only with the direct-browser-access header, which\n * the registry injects automatically.\n * - `openai`: api.openai.com does NOT reliably send CORS for browser calls —\n * route through a proxy `baseURL` or the gateway.\n * - `xai` / `deepseek`: unreliable from the browser; prefer a proxy.\n */\nexport const directBrowserOk = (p: ProviderType): boolean =>\n p === 'google' || p === 'gateway' || p === 'openai-compatible' || p === 'anthropic'\n","import { openDB, type IDBPDatabase } from 'idb'\n\nexport interface AgentWebDBOptions {\n /** Database name (default 'agent-web'). Use a distinct name to isolate apps. */\n dbName?: string\n}\n\nexport const KEYS_STORE = 'keys'\nexport const SECRETS_STORE = 'secrets'\nexport const SESSIONS_STORE = 'sessions'\n\nlet cache = new Map<string, Promise<IDBPDatabase>>()\n\n/**\n * The single owner of the IndexedDB database. Every persistent store — the\n * non-extractable crypto key, encrypted secrets, and session transcripts —\n * lives under ONE database name + version. Centralising `openDB` here prevents\n * the classic bug where two modules open the same DB name with different store\n * sets and the second call throws a VersionError.\n */\nexport const openAgentWebDB = (opts: AgentWebDBOptions = {}): Promise<IDBPDatabase> => {\n const name = opts.dbName ?? 'agent-web'\n let p = cache.get(name)\n if (!p) {\n p = openDB(name, 1, {\n upgrade(db) {\n if (!db.objectStoreNames.contains(KEYS_STORE)) db.createObjectStore(KEYS_STORE)\n if (!db.objectStoreNames.contains(SECRETS_STORE)) db.createObjectStore(SECRETS_STORE)\n if (!db.objectStoreNames.contains(SESSIONS_STORE)) db.createObjectStore(SESSIONS_STORE)\n },\n })\n cache.set(name, p)\n // A failed open (private mode, storage denied) must not stay cached, or\n // every later call would replay the same rejection forever.\n p.catch(() => {\n if (cache.get(name) === p) cache.delete(name)\n })\n }\n return p\n}\n\n/** Test hook: drop cached connections so a fresh (e.g. fake-indexeddb) DB is opened. */\nexport const _resetDBCache = (): void => {\n cache = new Map()\n}\n","import { KEYS_STORE, openAgentWebDB } from '../storage/db.js'\n\nconst KEY_ID = 'vault-key-v1'\n\nconst webcrypto = (): Crypto => {\n const c = (globalThis as { crypto?: Crypto }).crypto\n if (!c?.subtle || !c.getRandomValues) {\n throw new Error('WebCrypto (crypto.subtle) is unavailable in this environment')\n }\n return c\n}\n\nconst loadOrCreateKey = async (dbName?: string): Promise<CryptoKey> => {\n const db = await openAgentWebDB({ dbName })\n const existing = (await db.get(KEYS_STORE, KEY_ID)) as CryptoKey | undefined\n if (existing) return existing\n const key = await webcrypto().subtle.generateKey(\n { name: 'AES-GCM', length: 256 },\n /* extractable */ false,\n ['encrypt', 'decrypt'],\n )\n // Double-check inside one readwrite transaction: another tab may have created\n // a key while ours was generating. Losing that race and overwriting would\n // leave the other tab's secrets permanently undecryptable.\n const tx = db.transaction(KEYS_STORE, 'readwrite')\n const winner = (await tx.store.get(KEY_ID)) as CryptoKey | undefined\n if (winner) {\n await tx.done\n return winner\n }\n await tx.store.put(key, KEY_ID)\n await tx.done\n return key\n}\n\nconst keyCache = new Map<string, Promise<CryptoKey>>()\n\n/**\n * Fetch (or lazily create) the vault's AES-GCM key. The key is generated\n * NON-EXTRACTABLE and stored as a live `CryptoKey` in IndexedDB — a CryptoKey\n * is structured-cloneable, so it persists across reloads WITHOUT its raw bytes\n * ever being exposed to JavaScript. Not even in-page script can read it out; it\n * can only be used to encrypt / decrypt. That is what makes at-rest storage of\n * the secrets meaningful (see IndexedDBVault's threat model).\n *\n * Concurrent callers share one in-flight promise per DB, and creation is\n * double-checked in a single IDB transaction, so two racing writers can never\n * end up encrypting under different keys.\n */\nexport const getOrCreateVaultKey = (dbName?: string): Promise<CryptoKey> => {\n const cacheKey = dbName ?? 'agent-web'\n let p = keyCache.get(cacheKey)\n if (!p) {\n p = loadOrCreateKey(dbName)\n keyCache.set(cacheKey, p)\n p.catch(() => {\n if (keyCache.get(cacheKey) === p) keyCache.delete(cacheKey)\n })\n }\n return p\n}\n\nexport interface EncryptedBlob {\n /** 96-bit random IV, fresh per write. */\n iv: Uint8Array\n ciphertext: ArrayBuffer\n}\n\nconst textEncoder = new TextEncoder()\nconst textDecoder = new TextDecoder()\n\n/** Encrypt a JSON-serialisable value with a fresh 96-bit IV (AES-GCM). */\nexport const encryptJSON = async (key: CryptoKey, value: unknown): Promise<EncryptedBlob> => {\n const c = webcrypto()\n const iv = c.getRandomValues(new Uint8Array(12))\n const data = textEncoder.encode(JSON.stringify(value))\n const ciphertext = await c.subtle.encrypt({ name: 'AES-GCM', iv }, key, data)\n return { iv, ciphertext }\n}\n\n/** Decrypt a blob produced by encryptJSON. Throws if the key or blob don't match. */\nexport const decryptJSON = async <T = unknown>(key: CryptoKey, blob: EncryptedBlob): Promise<T> => {\n // Copy the IV into a fresh ArrayBuffer-backed view: after a round-trip through\n // IndexedDB its element buffer is typed as ArrayBufferLike, which no longer\n // satisfies BufferSource under TS's stricter typed-array generics.\n const iv = new Uint8Array(blob.iv)\n const plain = await webcrypto().subtle.decrypt({ name: 'AES-GCM', iv }, key, blob.ciphertext)\n return JSON.parse(textDecoder.decode(plain)) as T\n}\n","import { openAgentWebDB, SECRETS_STORE } from '../storage/db.js'\nimport { decryptJSON, encryptJSON, getOrCreateVaultKey, type EncryptedBlob } from './crypto.js'\n\nexport interface VaultOptions {\n /** Database name, forwarded to the shared IDB owner (default 'agent-web'). */\n dbName?: string\n}\n\n/**\n * Encrypted key/value secret store backed by IndexedDB. Values are encrypted at\n * rest with the non-extractable AES-GCM vault key (see crypto.ts).\n *\n * ── THREAT MODEL (read before shipping any app-owned key to a browser) ──\n * This vault PROTECTS secrets **at rest** — an IndexedDB / disk dump yields\n * only ciphertext — and against **casual DevTools inspection** — no plaintext\n * key is stored, and the AES key cannot be exported even by in-page script.\n *\n * It does **NOT** defend against **active XSS on your origin**: any script that\n * already runs on the page can call `getSecret()`, or use the live `CryptoKey`\n * to decrypt. Browser storage is not a secrets manager.\n *\n * Therefore this vault is for the **end user's OWN key on their OWN device**\n * (bring-your-own-key). A shared, app-owned key must NEVER reach the client —\n * put it behind a server proxy (`ProviderModelSpec.baseURL`) or the Vercel AI\n * Gateway instead.\n */\nexport class IndexedDBVault {\n private readonly dbName?: string\n\n constructor(opts: VaultOptions = {}) {\n this.dbName = opts.dbName\n }\n\n private key(): Promise<CryptoKey> {\n return getOrCreateVaultKey(this.dbName)\n }\n\n /** Encrypt and store a secret string under `id`. */\n async setSecret(id: string, value: string): Promise<void> {\n const blob = await encryptJSON(await this.key(), value)\n const db = await openAgentWebDB({ dbName: this.dbName })\n await db.put(SECRETS_STORE, blob, id)\n }\n\n /** Fetch and decrypt a secret, or undefined if absent. */\n async getSecret(id: string): Promise<string | undefined> {\n const db = await openAgentWebDB({ dbName: this.dbName })\n const blob = (await db.get(SECRETS_STORE, id)) as EncryptedBlob | undefined\n if (!blob) return undefined\n return decryptJSON<string>(await this.key(), blob)\n }\n\n async deleteSecret(id: string): Promise<void> {\n const db = await openAgentWebDB({ dbName: this.dbName })\n await db.delete(SECRETS_STORE, id)\n }\n\n async listSecretIds(): Promise<string[]> {\n const db = await openAgentWebDB({ dbName: this.dbName })\n return (await db.getAllKeys(SECRETS_STORE)).map(String)\n }\n}\n","import { IndexedDBVault, type VaultOptions } from './vault.js'\n\n/**\n * The seam the provider registry uses to fetch API keys at model-build time.\n * Swap in any backend: the encrypted vault (default), an in-memory map (tests /\n * SSR), or a `fetch` to your own short-lived-token endpoint.\n */\nexport interface CredentialStore {\n getApiKey(ref: string): Promise<string | undefined>\n setApiKey(ref: string, key: string): Promise<void>\n deleteApiKey(ref: string): Promise<void>\n}\n\n/** Default CredentialStore: encrypted, IndexedDB-backed (see IndexedDBVault). */\nexport class VaultCredentialStore implements CredentialStore {\n private readonly vault: IndexedDBVault\n\n constructor(opts: VaultOptions = {}) {\n this.vault = new IndexedDBVault(opts)\n }\n\n getApiKey(ref: string): Promise<string | undefined> {\n return this.vault.getSecret(ref)\n }\n setApiKey(ref: string, key: string): Promise<void> {\n return this.vault.setSecret(ref, key)\n }\n deleteApiKey(ref: string): Promise<void> {\n return this.vault.deleteSecret(ref)\n }\n}\n\n/** Non-persistent CredentialStore for tests / SSR / ephemeral sessions. */\nexport class MemoryCredentialStore implements CredentialStore {\n private readonly map = new Map<string, string>()\n\n constructor(initial?: Record<string, string>) {\n if (initial) for (const [k, v] of Object.entries(initial)) this.map.set(k, v)\n }\n\n async getApiKey(ref: string): Promise<string | undefined> {\n return this.map.get(ref)\n }\n async setApiKey(ref: string, key: string): Promise<void> {\n this.map.set(ref, key)\n }\n async deleteApiKey(ref: string): Promise<void> {\n this.map.delete(ref)\n }\n}\n","import { tool, type Tool } from 'ai'\nimport type { AgentTool } from './types.js'\n\n/**\n * Define a host tool. Thin wrapper over the AI SDK `tool()`: pass a\n * `description`, an `inputSchema` (a Zod schema or the result of `jsonSchema()`),\n * and an `execute` function. The returned tool works unchanged on the native\n * tool-calling path.\n *\n * Generic over INPUT/OUTPUT so the schema's inferred type flows into\n * `execute(input)` — `Parameters<typeof tool>[0]` must NOT be used here: with\n * an overloaded `tool()` it resolves to the last overload (`Tool<never, never>`),\n * which rejects every real schema and types `execute` as `undefined`.\n *\n * Optionally add `promptHint` — a short parameter hint like\n * \"{ text: string, x?: number }\" — which the prompted/salvage path shows to\n * weak local models that can't do native function-calling.\n *\n * @example\n * const tools = {\n * add_text: defineTool({\n * description: 'Add a text block to the page.',\n * inputSchema: z.object({ text: z.string(), x: z.number().optional() }),\n * promptHint: '{ text: string, x?: number }',\n * execute: async ({ text, x }) => addTextBlock(text, x),\n * }),\n * }\n */\nexport const defineTool = <INPUT = unknown, OUTPUT = unknown>(\n config: Tool<INPUT, OUTPUT> & { promptHint?: string },\n): AgentTool => {\n const { promptHint, ...rest } = config\n const t = tool(rest as Tool<INPUT, OUTPUT>) as AgentTool\n if (promptHint) t.promptHint = promptHint\n return t\n}\n","export interface StoredMessage {\n role: 'system' | 'user' | 'assistant'\n content: string\n ts?: number\n}\n\n/** Persists an agent session's transcript. Swap in any backend. */\nexport interface ContextStore {\n load(sessionId: string): Promise<StoredMessage[]>\n append(sessionId: string, message: StoredMessage): Promise<void>\n replace(sessionId: string, messages: StoredMessage[]): Promise<void>\n clear(sessionId: string): Promise<void>\n}\n\n/** Non-persistent fallback (tests, SSR, private mode). */\nexport class MemoryStore implements ContextStore {\n private readonly data = new Map<string, StoredMessage[]>()\n\n async load(sessionId: string): Promise<StoredMessage[]> {\n return (this.data.get(sessionId) ?? []).slice()\n }\n async append(sessionId: string, message: StoredMessage): Promise<void> {\n const arr = this.data.get(sessionId) ?? []\n arr.push(message)\n this.data.set(sessionId, arr)\n }\n async replace(sessionId: string, messages: StoredMessage[]): Promise<void> {\n this.data.set(sessionId, messages.slice())\n }\n async clear(sessionId: string): Promise<void> {\n this.data.delete(sessionId)\n }\n}\n","import { openAgentWebDB, SESSIONS_STORE } from '../storage/db.js'\nimport type { ContextStore, StoredMessage } from './store.js'\n\nexport interface IndexedDBStoreOptions {\n /** Database name, forwarded to the shared IDB owner (default 'agent-web'). */\n dbName?: string\n}\n\n/**\n * IndexedDB-backed transcript store — one record (message array) per session,\n * in the shared `sessions` object store (see storage/db.ts). Also exposes\n * session utilities: list and delete.\n */\nexport class IndexedDBStore implements ContextStore {\n private readonly dbName?: string\n\n constructor(opts: IndexedDBStoreOptions = {}) {\n this.dbName = opts.dbName\n }\n\n async load(sessionId: string): Promise<StoredMessage[]> {\n const db = await openAgentWebDB({ dbName: this.dbName })\n const value = (await db.get(SESSIONS_STORE, sessionId)) as StoredMessage[] | undefined\n return Array.isArray(value) ? value : []\n }\n\n async replace(sessionId: string, messages: StoredMessage[]): Promise<void> {\n const db = await openAgentWebDB({ dbName: this.dbName })\n await db.put(SESSIONS_STORE, messages, sessionId)\n }\n\n async append(sessionId: string, message: StoredMessage): Promise<void> {\n const current = await this.load(sessionId)\n current.push(message)\n await this.replace(sessionId, current)\n }\n\n async clear(sessionId: string): Promise<void> {\n const db = await openAgentWebDB({ dbName: this.dbName })\n await db.delete(SESSIONS_STORE, sessionId)\n }\n\n /** List all stored session ids. */\n async listSessions(): Promise<string[]> {\n const db = await openAgentWebDB({ dbName: this.dbName })\n return (await db.getAllKeys(SESSIONS_STORE)).map(String)\n }\n}\n"],"mappings":"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","names":["createWebLLMModel","tool","generateText","streamText","streamText","generateText","result"]}
1
+ {"version":3,"sources":["../src/config.ts","../src/llm/generate.ts","../src/llm/util.ts","../src/memory/compress.ts","../src/providers/types.ts","../src/providers/registry.ts","../src/prompts.ts","../src/tools/mode.ts","../src/tools/types.ts","../src/tools/prompted.ts","../src/llm/tool-loop.ts","../src/parse.ts","../src/agent/internal.ts","../src/agent/executor.ts","../src/agent/loop-types.ts","../src/agent/schemas.ts","../src/agent/planner.ts","../src/agent/replanner.ts","../src/agent/synthesizer.ts","../src/logger.ts","../src/agent/runner.ts","../src/providers/capabilities.ts","../src/storage/db.ts","../src/secrets/crypto.ts","../src/secrets/vault.ts","../src/secrets/store.ts","../src/tools/define.ts","../src/memory/store.ts","../src/memory/sessions.ts"],"sourcesContent":["import type { ContextStore } from './memory/store.js'\nimport type { AgentLoggerSink, LogLevel } from './logger.js'\nimport type { ModelInput, StageInput } from './providers/types.js'\nimport type { Prompts } from './prompts.js'\nimport type { CredentialStore } from './secrets/store.js'\nimport type { AgentToolSet } from './tools/types.js'\n\n/** Force a tool-calling strategy, or let the agent pick per model ('auto'). */\nexport type ToolMode = 'auto' | 'native' | 'prompted'\n\n/**\n * 'all' — the executor sees the full ToolSet on every step.\n * 'plan-narrowed' — the executor sees only a step's suggestedTools (the planner\n * must populate them). Empty means a reasoning-only step.\n */\nexport type ToolSelectionStrategy = 'all' | 'plan-narrowed'\n\n/** Per-phase generation budgets (max output tokens). */\nexport interface PhaseBudgets {\n planner?: number\n executor?: number\n replanner?: number\n synthesizer?: number\n}\n\nexport interface BrowserAgentConfig {\n /** The default (executor) model: a ready AI SDK model, or a ProviderModelSpec to resolve. */\n model: ModelInput\n /** Optional per-stage model overrides. A partial override inherits base provider/creds. */\n planner?: StageInput\n synthesizer?: StageInput\n /** Fetches API keys for ProviderModelSpec models. Default: none (inline keys only). */\n credentials?: CredentialStore\n /** Propagated to the openai-compatible provider name and the MCP client. */\n clientName?: string\n\n /** Host tools the executor may call (an AI SDK ToolSet; use defineTool). */\n tools?: AgentToolSet\n /** Whitelist: only these tool names from `tools` are mounted (default: all). */\n availableTools?: string[]\n /** Blacklist: these tool names are removed after the whitelist is applied. */\n excludedTools?: string[]\n /** Force native/prompted tool-calling; 'auto' picks per model (default 'auto'). */\n toolMode?: ToolMode\n toolSelectionStrategy?: ToolSelectionStrategy\n\n /** Prepended to every phase's system prompt. */\n systemPrompt?: string\n /** Override any phase prompt builder. */\n prompts?: Partial<Prompts>\n /** Serialize the host's current world state into prompt context (grounding). */\n describeState?: () => string | Promise<string>\n\n /**\n * Persist the transcript (e.g. new IndexedDBStore()). The last few messages\n * are also read back into the planner prompt, so follow-up goals can refer\n * to earlier turns.\n */\n memory?: ContextStore\n sessionId?: string\n\n /** Hard cap on executed steps incl. replans (default 8). */\n maxIterations?: number\n /** Cap on LLM steps inside a single native executor call (default 4). */\n maxStepsPerTask?: number\n /** Cap on replanner \"revise\" decisions per run (default 2). */\n maxRevisions?: number\n /** Per-call timeout so a hang can't freeze a run (default 120000). */\n chatTimeoutMs?: number\n budgets?: PhaseBudgets\n temperature?: number\n\n /** Replan after a blocked/failed step (default true). */\n replan?: boolean\n /** Write a final natural-language summary (default true). */\n synthesize?: boolean\n /** Compress stored history past this many chars (0 = off, default 12000). */\n compressAfterChars?: number\n\n /** Verbosity: 'silent' | 'error' | 'warn' (default) | 'info' | 'debug'. */\n logLevel?: LogLevel\n /** Console-like sink the logs go to (default: the global console). */\n logger?: AgentLoggerSink\n}\n\nexport interface ResolvedConfig {\n clientName: string\n sessionId: string\n toolMode: ToolMode\n toolSelectionStrategy: ToolSelectionStrategy\n maxIterations: number\n maxStepsPerTask: number\n maxRevisions: number\n chatTimeoutMs: number\n budgets: Required<PhaseBudgets>\n temperature: number | undefined\n replan: boolean\n synthesize: boolean\n compressAfterChars: number\n logLevel: LogLevel\n}\n\nexport const resolveConfig = (c: BrowserAgentConfig): ResolvedConfig => ({\n clientName: c.clientName ?? 'agent-web',\n sessionId: c.sessionId ?? 'default',\n toolMode: c.toolMode ?? 'auto',\n toolSelectionStrategy: c.toolSelectionStrategy ?? 'all',\n maxIterations: c.maxIterations ?? 8,\n maxStepsPerTask: c.maxStepsPerTask ?? 4,\n maxRevisions: c.maxRevisions ?? 2,\n chatTimeoutMs: c.chatTimeoutMs ?? 120_000,\n budgets: {\n planner: c.budgets?.planner ?? 800,\n executor: c.budgets?.executor ?? 1200,\n replanner: c.budgets?.replanner ?? 400,\n synthesizer: c.budgets?.synthesizer ?? 400,\n },\n temperature: c.temperature,\n replan: c.replan ?? true,\n synthesize: c.synthesize ?? true,\n compressAfterChars: c.compressAfterChars ?? 12_000,\n logLevel: c.logLevel ?? 'warn',\n})\n","import {\n generateObject,\n generateText,\n streamText,\n type LanguageModel,\n type ModelMessage,\n type ToolSet,\n} from 'ai'\nimport type { ZodType } from 'zod'\nimport { promptOf, timeoutSignal } from './util.js'\n\n/** Options shared by the low-level generation helpers. Provide `prompt` OR `messages`. */\nexport interface GenerateOptions {\n system?: string\n prompt?: string\n messages?: ModelMessage[]\n tools?: ToolSet\n maxOutputTokens?: number\n temperature?: number\n abortSignal?: AbortSignal\n /** Time-box the call; combined with `abortSignal` (0/undefined = no timeout). */\n timeoutMs?: number\n}\n\n/**\n * One-shot text generation. Thin, provider-agnostic wrapper over the AI SDK's\n * `generateText` — the same call works against a cloud model, a local WebLLM\n * model, or Chrome/Edge built-in AI. Returns the full AI SDK result (`.text`,\n * `.usage`, `.toolCalls`, `.steps`, …).\n */\nexport const generate = (\n model: LanguageModel,\n opts: GenerateOptions = {},\n): ReturnType<typeof generateText> =>\n generateText({\n model,\n system: opts.system,\n ...promptOf(opts),\n tools: opts.tools,\n maxOutputTokens: opts.maxOutputTokens,\n temperature: opts.temperature,\n abortSignal: timeoutSignal(opts.abortSignal, opts.timeoutMs),\n })\n\n/** Streaming text generation. Returns the AI SDK `streamText` result (`.textStream`, `.fullStream`). */\nexport const stream = (\n model: LanguageModel,\n opts: GenerateOptions = {},\n): ReturnType<typeof streamText> =>\n streamText({\n model,\n system: opts.system,\n ...promptOf(opts),\n tools: opts.tools,\n maxOutputTokens: opts.maxOutputTokens,\n temperature: opts.temperature,\n abortSignal: timeoutSignal(opts.abortSignal, opts.timeoutMs),\n })\n\n/**\n * Structured output constrained to a Zod schema, via the AI SDK's\n * `generateObject`. Cloud models and WebLLM both support this; tiny local\n * models can be unreliable — the agent's prompted mode is the fallback.\n * Returns the AI SDK result (`.object`, `.usage`).\n */\nexport const generateStructured = <OBJECT>(\n model: LanguageModel,\n schema: ZodType<OBJECT>,\n opts: GenerateOptions = {},\n) =>\n generateObject({\n model,\n schema,\n system: opts.system,\n ...promptOf(opts),\n maxOutputTokens: opts.maxOutputTokens,\n temperature: opts.temperature,\n abortSignal: timeoutSignal(opts.abortSignal, opts.timeoutMs),\n })\n","import type { ModelMessage } from 'ai'\nimport type { IUsage } from '../agent/loop-types.js'\n\n/**\n * The AI SDK prompt is `{ prompt } XOR { messages }` — passing both keys (even\n * with one undefined) breaks the discriminated union. Pick exactly one.\n */\nexport const promptOf = (opts: {\n prompt?: string\n messages?: ModelMessage[]\n}): { prompt: string } | { messages: ModelMessage[] } =>\n opts.messages ? { messages: opts.messages } : { prompt: opts.prompt ?? '' }\n\n/** Normalise the AI SDK usage shape (fields can be undefined) into IUsage. */\nexport const normalizeUsage = (u?: {\n inputTokens?: number\n outputTokens?: number\n totalTokens?: number\n}): IUsage => {\n const inputTokens = u?.inputTokens ?? 0\n const outputTokens = u?.outputTokens ?? 0\n return {\n inputTokens,\n outputTokens,\n totalTokens: u?.totalTokens ?? inputTokens + outputTokens,\n }\n}\n\n/**\n * Combine the caller's AbortSignal with a timeout so a hung generation can't\n * freeze a run. Returns the original signal when no timeout is set. Uses the\n * standard `AbortSignal.timeout`/`AbortSignal.any` (Node ≥ 20, modern browsers).\n */\nexport const timeoutSignal = (signal?: AbortSignal, ms?: number): AbortSignal | undefined => {\n if (!ms || ms <= 0) return signal\n const timeout = AbortSignal.timeout(ms)\n if (!signal) return timeout\n return typeof AbortSignal.any === 'function' ? AbortSignal.any([signal, timeout]) : signal\n}\n","import type { LanguageModel } from 'ai'\nimport { generate } from '../llm/generate.js'\nimport type { StoredMessage } from './store.js'\n\nexport interface CompressOptions {\n /** Compress once the transcript exceeds this many characters (0 = never). */\n maxChars?: number\n /** How many most-recent messages to keep verbatim. */\n keepRecent?: number\n /** Time-box the summarisation call so it can never hang the caller. */\n timeoutMs?: number\n abortSignal?: AbortSignal\n}\n\nconst totalChars = (msgs: StoredMessage[]): number => msgs.reduce((n, m) => n + m.content.length, 0)\n\n/**\n * When the transcript grows too long, summarise everything except the last\n * `keepRecent` messages into a single system message (via the model), so the\n * session stays within the model's context window. Returns the same array\n * unchanged when no compression is needed; never throws.\n */\nexport const compressHistory = async (\n messages: StoredMessage[],\n model: LanguageModel,\n opts: CompressOptions = {},\n): Promise<StoredMessage[]> => {\n const maxChars = opts.maxChars ?? 12_000\n const keepRecent = opts.keepRecent ?? 6\n if (maxChars <= 0 || messages.length <= keepRecent + 1 || totalChars(messages) <= maxChars) {\n return messages\n }\n const head = messages.slice(0, messages.length - keepRecent)\n const tail = messages.slice(messages.length - keepRecent)\n const transcript = head\n .map((m) => `${m.role}: ${m.content}`)\n .join('\\n')\n .slice(0, 8000)\n try {\n const result = await generate(model, {\n system:\n 'Summarize the following conversation into a compact set of durable facts and decisions. Output plain text only.',\n prompt: transcript,\n maxOutputTokens: 400,\n timeoutMs: opts.timeoutMs,\n abortSignal: opts.abortSignal,\n })\n const clean = (result.text || '').trim()\n if (!clean) return messages\n const summaryMsg: StoredMessage = {\n role: 'system',\n content: `Summary of earlier conversation:\\n${clean}`,\n ts: head[0]?.ts,\n }\n return [summaryMsg, ...tail]\n } catch {\n return messages\n }\n}\n","import type { LanguageModel } from 'ai'\n\n/**\n * Providers the browser registry can resolve from a spec. This is deliberately\n * a browser-safe subset of the Node sibling's list: Amazon Bedrock (SigV4\n * signing), Google Vertex (ADC via google-auth-library) and Cloudflare\n * (Worker bindings / process.env) are Node-only and omitted; Azure folds into\n * `openai-compatible`. `web-llm` is the local WebGPU pseudo-provider (no API\n * key). Any other runtime — Chrome/Edge built-in AI, a custom LanguageModel —\n * is passed to the agent directly and never touches this registry.\n */\nexport type ProviderType =\n | 'openai'\n | 'anthropic'\n | 'google'\n | 'openai-compatible'\n | 'xai'\n | 'deepseek'\n | 'gateway'\n | 'web-llm'\n\n/** A model described by provider + id, resolved through the registry (+ vault). */\nexport interface ProviderModelSpec {\n providerType: ProviderType\n /** Model id, e.g. \"gpt-4o-mini\", \"claude-haiku-4-5\", \"Llama-3.2-3B-Instruct-q4f16_1-MLC\". */\n model: string\n /** Provider endpoint override. Required for `openai-compatible`; a proxy URL for the rest. */\n baseURL?: string\n /** Id under which the API key is stored in the CredentialStore / vault. Preferred. */\n credentialRef?: string\n /**\n * Dev-only inline API key. Prefer `credentialRef` so the key lives encrypted\n * in the vault, not on a long-lived config object. Using this logs a warning.\n */\n apiKey?: string\n /** Extra request headers merged into the provider factory (e.g. a proxy auth header). */\n headers?: Record<string, string>\n /** Escape hatch spread into the SDK factory after baseURL / apiKey / headers. */\n providerOptions?: Record<string, unknown>\n}\n\n/**\n * A per-stage override that inherits the base provider + credentials and\n * changes only the fields it sets (typically just `model`). Distinguished from\n * a full ProviderModelSpec by the absence of `providerType`.\n */\nexport interface StageOverride {\n model?: string\n baseURL?: string\n credentialRef?: string\n apiKey?: string\n headers?: Record<string, string>\n providerOptions?: Record<string, unknown>\n}\n\n/** What a caller hands us for a model: a ready AI SDK model, or a spec to resolve. */\nexport type ModelInput = LanguageModel | ProviderModelSpec\n\n/** A model input, plus the partial-override form usable for per-stage layering. */\nexport type StageInput = ModelInput | StageOverride\n\n/** Outcome of resolving one stage: either a ready model, or a fully-resolved spec. */\nexport type ResolvedStage =\n { type: 'direct'; model: LanguageModel } | { type: 'spec'; spec: ProviderModelSpec }\n\n/** True for a ready AI SDK model: a gateway model-id string or a LanguageModelV* object. */\nexport const isDirectModel = (m: unknown): m is LanguageModel =>\n typeof m === 'string' || (typeof m === 'object' && m !== null && 'specificationVersion' in m)\n\n/** True for a full provider spec (carries the `providerType` discriminator). */\nexport const isProviderSpec = (m: unknown): m is ProviderModelSpec =>\n typeof m === 'object' &&\n m !== null &&\n !isDirectModel(m) &&\n typeof (m as { providerType?: unknown }).providerType === 'string'\n","import type { LanguageModel } from 'ai'\nimport type { CredentialStore } from '../secrets/store.js'\nimport {\n isDirectModel,\n isProviderSpec,\n type ModelInput,\n type ProviderModelSpec,\n type ProviderType,\n type ResolvedStage,\n type StageInput,\n type StageOverride,\n} from './types.js'\n\n// Providers whose endpoint the SDK cannot imply and must be given explicitly.\nconst REQUIRES_BASE_URL: ReadonlySet<ProviderType> = new Set<ProviderType>(['openai-compatible'])\n\n// Providers that authenticate without an API key.\nconst NO_KEY: ReadonlySet<ProviderType> = new Set<ProviderType>(['web-llm'])\n\n// provider -> npm package for the dynamic import and the \"please install X\"\n// message. `gateway` (ships in `ai`) and `web-llm` (its own adapter) are not here.\nconst PROVIDER_PACKAGE: Record<Exclude<ProviderType, 'gateway' | 'web-llm'>, string> = {\n openai: '@ai-sdk/openai',\n anthropic: '@ai-sdk/anthropic',\n google: '@ai-sdk/google',\n 'openai-compatible': '@ai-sdk/openai-compatible',\n xai: '@ai-sdk/xai',\n deepseek: '@ai-sdk/deepseek',\n}\n\nconst loadProvider = async <T>(pkg: string): Promise<T> => {\n try {\n // A variable dynamic import of an optional peer. Both bundler hints are\n // required: without `webpackIgnore` webpack emits \"Critical dependency:\n // the request of a dependency is an expression\" (an error under CI) and\n // tries to build a context module; without `@vite-ignore` Vite warns.\n // Bundlers thus leave the import to the runtime — bundler-less pages map\n // the bare specifier via an import map (see README), and hosts that never\n // use cloud providers (e.g. local WebLLM only) are unaffected.\n return (await import(/* webpackIgnore: true */ /* @vite-ignore */ pkg)) as T\n } catch {\n throw new Error(\n `Provider package \"${pkg}\" is not installed. Add it to your app: npm install ${pkg}`,\n )\n }\n}\n\nconst normalizeSpec = (spec: ProviderModelSpec): ProviderModelSpec => {\n if (REQUIRES_BASE_URL.has(spec.providerType) && !spec.baseURL) {\n throw new Error(`provider \"${spec.providerType}\" requires a baseURL (point it at your server)`)\n }\n return spec\n}\n\n/**\n * Resolve one stage to either a ready model or a fully-resolved spec, layering\n * an optional override on the base:\n * - a direct model (or full spec) override wins outright;\n * - a partial StageOverride inherits the base provider + credentials, changing\n * only the fields it sets (e.g. `{ model: 'gpt-4o-mini' }`);\n * - a full-spec override that switches provider MUST carry its own key\n * (credentialRef/apiKey) — inheriting a key across vendors is a footgun.\n */\nexport const resolveStage = (\n base: ModelInput,\n override: StageInput | undefined,\n stageName: string,\n): ResolvedStage => {\n if (override !== undefined && isDirectModel(override)) {\n return { type: 'direct', model: override }\n }\n if (override !== undefined && isProviderSpec(override)) {\n if (\n isProviderSpec(base) &&\n override.providerType !== base.providerType &&\n !override.credentialRef &&\n !override.apiKey &&\n !NO_KEY.has(override.providerType)\n ) {\n throw new Error(\n `${stageName}: provider \"${override.providerType}\" differs from the base \"${base.providerType}\"; set ${stageName}.credentialRef or apiKey (cross-provider key inheritance is unsafe)`,\n )\n }\n return { type: 'spec', spec: normalizeSpec(override) }\n }\n\n // No override, or a partial StageOverride to layer onto the base.\n if (isDirectModel(base)) {\n if (override && Object.keys(override).length > 0) {\n throw new Error(\n `${stageName}: cannot layer a partial override onto a direct model — pass a full model or ProviderModelSpec for ${stageName}`,\n )\n }\n return { type: 'direct', model: base }\n }\n if (!isProviderSpec(base)) {\n throw new Error(`${stageName}: base model must be a LanguageModel or a ProviderModelSpec`)\n }\n\n const ov = (override ?? {}) as StageOverride\n const merged: ProviderModelSpec = {\n providerType: base.providerType,\n model: ov.model ?? base.model,\n baseURL: ov.baseURL ?? base.baseURL,\n credentialRef: ov.credentialRef ?? base.credentialRef,\n apiKey: ov.apiKey ?? base.apiKey,\n headers: ov.headers ?? base.headers,\n providerOptions: ov.providerOptions ?? base.providerOptions,\n }\n return { type: 'spec', spec: normalizeSpec(merged) }\n}\n\nconst resolveApiKey = async (\n spec: ProviderModelSpec,\n credentials?: CredentialStore,\n): Promise<string | undefined> => {\n if (spec.apiKey) {\n console.warn(\n `[agent-web] using an inline apiKey for provider \"${spec.providerType}\"; prefer credentialRef so the key stays in the encrypted vault`,\n )\n return spec.apiKey\n }\n if (spec.credentialRef) {\n if (!credentials) {\n throw new Error(\n `credentialRef \"${spec.credentialRef}\" is set but no CredentialStore was provided to the agent`,\n )\n }\n const key = await credentials.getApiKey(spec.credentialRef)\n if (!key) {\n throw new Error(\n `no API key found in the CredentialStore for credentialRef \"${spec.credentialRef}\"`,\n )\n }\n return key\n }\n return undefined\n}\n\n/**\n * Turn a resolved stage into an AI SDK `LanguageModel`. Direct models pass\n * through untouched; specs are built by dynamically importing the provider's\n * optional-peer package and fetching the API key from the CredentialStore.\n */\nexport const buildModelFromStage = async (\n resolved: ResolvedStage,\n credentials?: CredentialStore,\n clientName = 'agent-web',\n): Promise<LanguageModel> => {\n if (resolved.type === 'direct') return resolved.model\n const spec = resolved.spec\n const providerOptions = spec.providerOptions ?? {}\n const apiKey = await resolveApiKey(spec, credentials)\n\n switch (spec.providerType) {\n case 'web-llm': {\n const { createWebLLMModel } = await import('./webllm.js')\n return createWebLLMModel(spec.model, providerOptions)\n }\n case 'gateway': {\n // The Vercel AI Gateway ships inside `ai` — no separate peer to install.\n const { createGateway } = await import('ai')\n const provider = createGateway({\n baseURL: spec.baseURL || undefined,\n apiKey,\n headers: spec.headers,\n ...providerOptions,\n })\n return provider(spec.model)\n }\n case 'openai': {\n const { createOpenAI } = await loadProvider<typeof import('@ai-sdk/openai')>(\n PROVIDER_PACKAGE.openai,\n )\n const provider = createOpenAI({\n baseURL: spec.baseURL || undefined,\n apiKey,\n headers: spec.headers,\n ...providerOptions,\n })\n return provider(spec.model)\n }\n case 'anthropic': {\n const { createAnthropic } = await loadProvider<typeof import('@ai-sdk/anthropic')>(\n PROVIDER_PACKAGE.anthropic,\n )\n const provider = createAnthropic({\n baseURL: spec.baseURL || undefined,\n apiKey,\n // Anthropic's SDK refuses browser calls unless this opt-in header is\n // set; host headers may override it.\n headers: { 'anthropic-dangerous-direct-browser-access': 'true', ...spec.headers },\n ...providerOptions,\n })\n return provider(spec.model)\n }\n case 'google': {\n const { createGoogleGenerativeAI } = await loadProvider<typeof import('@ai-sdk/google')>(\n PROVIDER_PACKAGE.google,\n )\n const provider = createGoogleGenerativeAI({\n baseURL: spec.baseURL || undefined,\n apiKey,\n headers: spec.headers,\n ...providerOptions,\n })\n return provider(spec.model)\n }\n case 'openai-compatible': {\n const { createOpenAICompatible } = await loadProvider<\n typeof import('@ai-sdk/openai-compatible')\n >(PROVIDER_PACKAGE['openai-compatible'])\n const provider = createOpenAICompatible({\n name: clientName,\n baseURL: spec.baseURL as string,\n apiKey,\n headers: spec.headers,\n ...providerOptions,\n })\n return provider(spec.model)\n }\n case 'xai': {\n const { createXai } = await loadProvider<typeof import('@ai-sdk/xai')>(PROVIDER_PACKAGE.xai)\n const provider = createXai({\n baseURL: spec.baseURL || undefined,\n apiKey,\n headers: spec.headers,\n ...providerOptions,\n })\n return provider(spec.model)\n }\n case 'deepseek': {\n const { createDeepSeek } = await loadProvider<typeof import('@ai-sdk/deepseek')>(\n PROVIDER_PACKAGE.deepseek,\n )\n const provider = createDeepSeek({\n baseURL: spec.baseURL || undefined,\n apiKey,\n headers: spec.headers,\n ...providerOptions,\n })\n return provider(spec.model)\n }\n }\n}\n\n/** Resolve a single ModelInput straight to a LanguageModel (no per-stage layering). */\nexport const resolveModel = (\n input: ModelInput,\n credentials?: CredentialStore,\n clientName?: string,\n): Promise<LanguageModel> =>\n buildModelFromStage(resolveStage(input, undefined, 'model'), credentials, clientName)\n","/**\n * Default phase prompts. Each builder returns `{ system, prompt }` strings.\n * Because the agent runs in two tool-modes, the builders switch on `ctx.mode`:\n *\n * - `native` — the model calls tools / emits schema-constrained JSON via the\n * AI SDK, so the prompts describe the task and let the SDK enforce structure.\n * - `prompted` — weak local models can't do that reliably, so the prompts spell\n * out an exact JSON shape and (for the executor) include a tool catalogue;\n * the output is salvaged by parse.ts.\n *\n * Override any builder via `BrowserAgentConfig.prompts`.\n */\n\nexport type ToolCallMode = 'native' | 'prompted'\n\nexport interface PromptParts {\n system: string\n prompt: string\n}\n\nexport interface PlannerPromptContext {\n goal: string\n state?: string\n toolCatalog: string\n mode: ToolCallMode\n /** Prior session messages (oldest first), for resolving references to earlier turns. */\n history?: { role: string; content: string }[]\n}\nexport interface ExecutorPromptContext {\n goal: string\n state?: string\n step: string\n index: number\n total: number\n toolCatalog: string\n done: string[]\n mode: ToolCallMode\n}\nexport interface ReplannerPromptContext {\n goal: string\n state?: string\n done: string[]\n remaining: string[]\n mode: ToolCallMode\n}\nexport interface SynthesizerPromptContext {\n goal: string\n state?: string\n done: string[]\n}\n\nexport interface Prompts {\n planner(ctx: PlannerPromptContext): PromptParts\n executor(ctx: ExecutorPromptContext): PromptParts\n replanner(ctx: ReplannerPromptContext): PromptParts\n synthesizer(ctx: SynthesizerPromptContext): PromptParts\n}\n\nconst numbered = (items: string[], empty: string): string =>\n items.length ? items.map((s, i) => `${i + 1}. ${s}`).join('\\n') : empty\n\nconst stateBlock = (state?: string): string => (state && state.trim() ? `\\n\\nSTATE:\\n${state}` : '')\n\nconst clip = (s: string, max: number): string => (s.length > max ? `${s.slice(0, max - 1)}…` : s)\n\n// The last few session messages, capped so a long transcript can't crowd out\n// the goal (memory compression keeps the full story in a summary message).\nconst historyBlock = (history?: { role: string; content: string }[]): string => {\n if (!history || history.length === 0) return ''\n const lines = history.slice(-8).map((m) => `${m.role}: ${clip(m.content, 400)}`)\n return `\\n\\nCONVERSATION SO FAR:\\n${lines.join('\\n')}`\n}\n\n// --- planner ---------------------------------------------------------------\n\nconst PLANNER_NATIVE = `You are the PLANNER of a tool-using agent that changes a workspace step by step.\nProduce a brief \"thought\" and an ordered \"steps\" list (1–6 DISTINCT, self-contained steps) grounded in the current STATE and the available TOOLS.\nIf the user only greets, thanks, makes small talk, asks a question, or is unclear: return an EMPTY steps list and put a short, friendly answer in \"thought\".\nIf a CONVERSATION SO FAR section is present, use it to resolve references to earlier turns.\nNever repeat or pad steps.`\n\nconst PLANNER_PROMPTED = `You are the PLANNER of a tool-using agent that changes a workspace step by step.\n\nReply with a single JSON object, nothing else:\n{ \"reply\": string, \"plan\": string[] }\n- Only produce a \"plan\" when the user CLEARLY asks to build, do, or change something. For a greeting, small talk, thanks, a question, or an unclear/empty request: set \"plan\": [] and put a short, friendly \"reply\".\n- For a real goal: \"reply\" is one short sentence; \"plan\" is 1–6 DISTINCT, self-contained steps. Never repeat or pad steps.\n- Plan realistic steps the available TOOLS can perform, grounded in the current STATE.\n- If a CONVERSATION SO FAR section is present, use it to resolve references to earlier turns.`\n\n// --- executor --------------------------------------------------------------\n\nconst EXECUTOR_NATIVE = `You are the EXECUTOR of a tool-using agent. Carry out ONLY the current step by calling the provided tools.\nBuild on the current STATE — do not repeat work that is already there.\nWhen the step is done, reply with one short human sentence describing what you did (no JSON).\nIf you CANNOT complete the step (a needed tool is missing or an input is unavailable), explain why in one sentence and include the token [BLOCKER].`\n\nconst EXECUTOR_PROMPTED = `You are the EXECUTOR of a tool-using agent. Carry out ONLY the current step by emitting tool calls.\n\nReply with a single JSON object, nothing else:\n{ \"reply\": string, \"actions\": [ { \"tool\": string, \"args\": object } ] }\n- \"actions\" are the tool calls for THIS step ([] if none are needed). Use ONLY tools from the TOOLS list; \"args\" must match the tool's parameters.\n- Build on the current STATE — do not repeat work that is already there.\n- \"reply\" is one short human sentence (no JSON) describing what you did.\n- If you CANNOT complete the step, set \"actions\": [] and put the token [BLOCKER] in \"reply\" with a short reason.`\n\n// --- replanner -------------------------------------------------------------\n\nconst REPLANNER_NATIVE = `You are the REPLANNER. After a step that was blocked or had a failed tool call, decide whether to keep going, revise the remaining steps, or finish.\n\"continue\": the remaining steps still fit. \"revise\": provide a better \"plan\" for the REMAINING work (never repeat done work). \"finish\": the goal is already met.\nJudge from the current STATE vs the goal. Prefer \"continue\".`\n\nconst REPLANNER_PROMPTED = `You are the REPLANNER. After each executed step you decide whether to keep going, revise the remaining steps, or finish.\n\nReply with a single JSON object, nothing else:\n{ \"decision\": \"continue\" | \"revise\" | \"finish\", \"reason\": string, \"plan\": string[] }\n- \"continue\": remaining steps still fit — proceed (omit \"plan\").\n- \"revise\": replace the REMAINING steps with a better list in \"plan\"; never repeat done work.\n- \"finish\": the goal is already met — stop (omit \"plan\").\nJudge from the current STATE vs the goal. Prefer \"continue\".`\n\nconst SYNTHESIZER_SYSTEM = `You are the SYNTHESIZER. In 1–3 short, friendly sentences, tell the user what was done to meet their goal. Be concrete. Output plain text only — no JSON, no code.`\n\nexport const defaultPrompts: Prompts = {\n planner: (ctx) => ({\n system: ctx.mode === 'prompted' ? PLANNER_PROMPTED : PLANNER_NATIVE,\n prompt: `GOAL: ${ctx.goal}${historyBlock(ctx.history)}${stateBlock(ctx.state)}\\n\\nTOOLS:\\n${ctx.toolCatalog}`,\n }),\n executor: (ctx) => ({\n system: ctx.mode === 'prompted' ? EXECUTOR_PROMPTED : EXECUTOR_NATIVE,\n prompt: [\n `GOAL: ${ctx.goal}`,\n stateBlock(ctx.state).trimStart(),\n ctx.mode === 'prompted' ? `TOOLS:\\n${ctx.toolCatalog}` : '',\n ctx.done.length ? `Already done:\\n${numbered(ctx.done, '')}` : '',\n `STEP ${ctx.index}/${ctx.total}: ${ctx.step}`,\n ]\n .filter(Boolean)\n .join('\\n\\n'),\n }),\n replanner: (ctx) => ({\n system: ctx.mode === 'prompted' ? REPLANNER_PROMPTED : REPLANNER_NATIVE,\n prompt: [\n `GOAL: ${ctx.goal}`,\n stateBlock(ctx.state).trimStart(),\n `Already done:\\n${numbered(ctx.done, '(nothing yet)')}`,\n `Remaining plan:\\n${numbered(ctx.remaining, '(none)')}`,\n 'Decide: continue, revise, or finish.',\n ]\n .filter(Boolean)\n .join('\\n\\n'),\n }),\n synthesizer: (ctx) => ({\n system: SYNTHESIZER_SYSTEM,\n prompt: [\n `GOAL: ${ctx.goal}`,\n stateBlock(ctx.state).trimStart(),\n `What was done:\\n${numbered(ctx.done, '(no changes)')}`,\n 'Write the final summary for the user.',\n ]\n .filter(Boolean)\n .join('\\n\\n'),\n }),\n}\n\n/** Prepend a host-supplied systemPrompt to a phase system prompt, if present. */\nexport const withSystem = (base: string, extra?: string): string =>\n extra && extra.trim() ? `${extra.trim()}\\n\\n${base}` : base\n","import type { LanguageModel } from 'ai'\nimport type { ToolMode } from '../config.js'\n\n// Local / on-device runtimes whose tiny models are unreliable at native\n// function-calling and JSON-schema output — default them to the prompted path.\nconst LOCAL_RE = /web-?llm|mlc|browser-ai|transformers|nano|built-?in/i\n\n/**\n * Decide the tool-calling strategy for a resolved model. An explicit\n * config.toolMode of 'native'/'prompted' always wins; 'auto' (default) inspects\n * the model's provider id — local/on-device runtimes → 'prompted', cloud → 'native'.\n * A string model is a gateway model id (\"openai/gpt-4o\") — always cloud; the\n * LOCAL_RE must not see it, or model names like \"gpt-5-nano\" would match `nano`.\n */\nexport const selectToolMode = (\n model: LanguageModel,\n mode: ToolMode = 'auto',\n): 'native' | 'prompted' => {\n if (mode === 'native' || mode === 'prompted') return mode\n if (typeof model === 'string') return 'native'\n const provider = (model as { provider?: string }).provider ?? ''\n return LOCAL_RE.test(provider) ? 'prompted' : 'native'\n}\n","import type { Tool, ToolSet } from 'ai'\n\n/**\n * The canonical tool shape is the AI SDK `Tool` — the same object the native\n * tool-calling path passes straight to `streamText({ tools })`, and the same\n * shape MCP tools take. We add one optional field, `promptHint`, a short\n * human-readable parameter hint (e.g. \"{ text: string, x?: number }\") used only\n * by the prompted/salvage path when it renders the tool catalogue into a text\n * prompt for weak local models.\n */\nexport type AgentTool = Tool & { promptHint?: string }\n\n/** A named collection of tools — a plain AI SDK ToolSet, usable directly. */\nexport type AgentToolSet = ToolSet\n\n/** Read the optional promptHint attached by defineTool, if any. */\nexport const promptHintOf = (tool: Tool): string | undefined =>\n typeof (tool as { promptHint?: unknown }).promptHint === 'string'\n ? (tool as { promptHint?: string }).promptHint\n : undefined\n","import type { ModelMessage, ToolSet } from 'ai'\nimport type { RawAction } from '../parse.js'\nimport type { IToolCall } from '../agent/loop-types.js'\nimport { promptHintOf, type AgentToolSet } from './types.js'\n\n/**\n * Render a ToolSet into a plain-text catalogue for the prompted/salvage path:\n * `- name(hint): description`. The hint comes from `defineTool({ promptHint })`\n * when present; weak local models lean on it to fill args correctly.\n */\nexport const renderCatalog = (tools: AgentToolSet): string => {\n const names = Object.keys(tools)\n if (names.length === 0) return '(no tools)'\n return names\n .map((name) => {\n const t = tools[name]\n const hint = promptHintOf(t) ?? ''\n const desc = typeof t.description === 'string' ? t.description : ''\n return `- ${name}(${hint}): ${desc}`\n })\n .join('\\n')\n}\n\ninterface DispatchContext {\n abortSignal?: AbortSignal\n messages?: ModelMessage[]\n toolCallId?: string\n}\n\n/**\n * Validate and execute a single salvaged tool call against the ToolSet, using\n * the tool's OWN `execute` and `inputSchema` — the identical implementation the\n * native path calls. Unknown tools, schema-invalid args, and thrown errors all\n * become a failed IToolCall rather than throwing.\n */\nexport const dispatch = async (\n action: RawAction,\n tools: ToolSet,\n ctx: DispatchContext = {},\n): Promise<IToolCall> => {\n const t = tools[action.tool]\n if (!t) {\n return {\n name: action.tool,\n input: action.args,\n output: `unknown tool \"${action.tool}\"`,\n ok: false,\n }\n }\n let input: unknown = action.args\n const schema = (t as { inputSchema?: unknown }).inputSchema\n // Best-effort Zod validation (a jsonSchema() input has no safeParse — the\n // tool's execute is expected to guard those itself).\n if (schema && typeof (schema as { safeParse?: unknown }).safeParse === 'function') {\n const parsed = (\n schema as {\n safeParse: (v: unknown) => { success: boolean; data?: unknown; error?: { message: string } }\n }\n ).safeParse(input)\n if (!parsed.success) {\n return {\n name: action.tool,\n input,\n output: `invalid args for \"${action.tool}\": ${parsed.error?.message ?? 'schema validation failed'}`,\n ok: false,\n }\n }\n input = parsed.data\n }\n const execute = (t as { execute?: (i: unknown, o: unknown) => unknown }).execute\n if (typeof execute !== 'function') {\n return { name: action.tool, input, output: `tool \"${action.tool}\" has no execute`, ok: false }\n }\n try {\n const output = await execute(input, {\n toolCallId: ctx.toolCallId ?? `prompted-${action.tool}`,\n messages: ctx.messages ?? [],\n abortSignal: ctx.abortSignal,\n })\n return { name: action.tool, input, output, ok: true }\n } catch (err) {\n return {\n name: action.tool,\n input,\n output: err instanceof Error ? err.message : 'tool error',\n ok: false,\n }\n }\n}\n","import {\n generateText,\n stepCountIs,\n streamText,\n type LanguageModel,\n type ModelMessage,\n type ToolSet,\n} from 'ai'\nimport type { IToolCall, IUsage } from '../agent/loop-types.js'\nimport { parseExecutorResponse } from '../parse.js'\nimport { dispatch } from '../tools/prompted.js'\nimport { normalizeUsage, promptOf, timeoutSignal } from './util.js'\n\nexport interface ToolLoopCallbacks {\n onTextDelta?: (delta: string) => void\n onToolCall?: (name: string, input: unknown) => void\n onToolResult?: (name: string, output: unknown, ok: boolean) => void\n}\n\nexport interface ToolLoopOptions {\n /** 'native' = SDK function-calling; 'prompted' = parse JSON out of plain text. */\n mode: 'native' | 'prompted'\n system?: string\n prompt?: string\n messages?: ModelMessage[]\n /** In native mode: the callable tools. In prompted mode: used to dispatch salvaged calls. */\n tools: ToolSet\n /**\n * Restrict callable tools to these names (plan-narrowed). Native mode passes\n * them to the SDK's `activeTools`; prompted mode bounds `dispatch` to them.\n */\n activeTools?: string[]\n /** Native mode: cap on internal tool-calling steps (default 4). */\n maxSteps?: number\n maxOutputTokens?: number\n temperature?: number\n abortSignal?: AbortSignal\n timeoutMs?: number\n callbacks?: ToolLoopCallbacks\n}\n\nexport interface ToolLoopResult {\n text: string\n toolCalls: IToolCall[]\n usage: IUsage\n}\n\n/**\n * Run one round of tool-calling in whichever mode the model needs, returning a\n * normalised result. Native mode streams the SDK's multi-step function-calling;\n * prompted mode does a single generation, salvages a `{ reply, actions }` JSON\n * from the text, and dispatches each action through the tool's own execute.\n * Both call the exact same tool implementations.\n */\nexport const runToolLoop = (\n model: LanguageModel,\n opts: ToolLoopOptions,\n): Promise<ToolLoopResult> =>\n opts.mode === 'prompted' ? runPrompted(model, opts) : runNative(model, opts)\n\nconst runNative = async (model: LanguageModel, opts: ToolLoopOptions): Promise<ToolLoopResult> => {\n const toolCalls: IToolCall[] = []\n const pending = new Map<string, { name: string; input: unknown }>()\n\n const result = streamText({\n model,\n tools: opts.tools,\n ...(opts.activeTools ? { activeTools: opts.activeTools } : {}),\n stopWhen: stepCountIs(opts.maxSteps ?? 4),\n system: opts.system,\n ...promptOf(opts),\n maxOutputTokens: opts.maxOutputTokens,\n temperature: opts.temperature,\n abortSignal: timeoutSignal(opts.abortSignal, opts.timeoutMs),\n })\n\n for await (const part of result.fullStream) {\n switch (part.type) {\n case 'text-delta':\n if (part.text) opts.callbacks?.onTextDelta?.(part.text)\n break\n case 'tool-call':\n pending.set(part.toolCallId, { name: part.toolName, input: part.input })\n opts.callbacks?.onToolCall?.(part.toolName, part.input)\n break\n case 'tool-result': {\n const known = pending.get(part.toolCallId)\n toolCalls.push({\n name: part.toolName,\n input: known?.input ?? part.input,\n output: part.output,\n ok: true,\n })\n opts.callbacks?.onToolResult?.(part.toolName, part.output, true)\n pending.delete(part.toolCallId)\n break\n }\n case 'tool-error': {\n const known = pending.get(part.toolCallId)\n toolCalls.push({\n name: part.toolName,\n input: known?.input ?? part.input,\n output: part.error,\n ok: false,\n })\n opts.callbacks?.onToolResult?.(part.toolName, part.error, false)\n pending.delete(part.toolCallId)\n break\n }\n case 'error':\n throw part.error instanceof Error ? part.error : new Error(String(part.error))\n }\n }\n\n const [text, usage] = await Promise.all([result.text, result.usage])\n return { text: text.trim(), toolCalls, usage: normalizeUsage(usage) }\n}\n\nconst runPrompted = async (\n model: LanguageModel,\n opts: ToolLoopOptions,\n): Promise<ToolLoopResult> => {\n // Prompted mode does NOT pass tools to the SDK — the tool catalogue is\n // already rendered into the prompt (see tools/prompted.ts renderCatalog); the\n // model replies with JSON, which we salvage and dispatch ourselves.\n const result = await generateText({\n model,\n system: opts.system,\n ...promptOf(opts),\n maxOutputTokens: opts.maxOutputTokens,\n temperature: opts.temperature,\n abortSignal: timeoutSignal(opts.abortSignal, opts.timeoutMs),\n })\n\n const parsed = parseExecutorResponse(result.text)\n // Surface the parsed human reply, never the raw JSON envelope.\n if (parsed.reply) opts.callbacks?.onTextDelta?.(parsed.reply)\n\n const active = opts.activeTools\n const tools = active\n ? Object.fromEntries(Object.entries(opts.tools).filter(([name]) => active.includes(name)))\n : opts.tools\n const toolCalls: IToolCall[] = []\n for (const action of parsed.actions) {\n opts.callbacks?.onToolCall?.(action.tool, action.args)\n const rec = await dispatch(action, tools, { abortSignal: opts.abortSignal })\n toolCalls.push(rec)\n opts.callbacks?.onToolResult?.(rec.name, rec.output, rec.ok)\n }\n return { text: parsed.reply, toolCalls, usage: normalizeUsage(result.usage) }\n}\n","/**\n * Robust parsing of model output. Small in-browser models emit JSON wrapped in\n * prose or code fences, truncate it mid-token when they loop, or drift to plain\n * text. Every parser here is defensive: it salvages what it can and NEVER\n * throws, and it never surfaces raw JSON as user-facing text. This is the\n * backbone of the \"prompted\" tool-mode (see tools/mode.ts).\n */\n\n/** A tool the executor asked to run. */\nexport interface RawAction {\n tool: string\n args: Record<string, unknown>\n}\n\nexport type ReplanDecision = 'continue' | 'revise' | 'finish'\n\nconst stripFences = (text: string): string => (text || '').replace(/```(?:json)?/gi, '').trim()\n\n/** Extracts the first balanced {...} or [...] block, respecting strings. */\nconst extractBalanced = (text: string, open: '{' | '['): string | undefined => {\n const close = open === '{' ? '}' : ']'\n const start = text.indexOf(open)\n if (start < 0) return undefined\n let depth = 0\n let inStr = false\n let esc = false\n for (let i = start; i < text.length; i += 1) {\n const c = text[i]\n if (inStr) {\n if (esc) esc = false\n else if (c === '\\\\') esc = true\n else if (c === '\"') inStr = false\n continue\n }\n if (c === '\"') inStr = true\n else if (c === open) depth += 1\n else if (c === close) {\n depth -= 1\n if (depth === 0) return text.slice(start, i + 1)\n }\n }\n return undefined\n}\n\nconst tryParse = (s: string | undefined): unknown => {\n if (!s) return undefined\n try {\n return JSON.parse(s)\n } catch {\n return undefined\n }\n}\n\n/** True when a string is (or is dominated by) raw JSON — kept out of the UI. */\nexport const looksLikeJson = (s: string): boolean => {\n const t = (s || '').trim()\n return (\n t.startsWith('{') ||\n t.startsWith('[') ||\n /\"(tool|args|plan|reply|actions|decision)\"\\s*:/.test(t)\n )\n}\n\nconst asObject = (text: string): Record<string, unknown> | undefined => {\n const v = tryParse(text) ?? tryParse(extractBalanced(text, '{'))\n return v && typeof v === 'object' && !Array.isArray(v)\n ? (v as Record<string, unknown>)\n : undefined\n}\n\n/** Trim, drop empties, de-duplicate (case-insensitive), cap length. */\nexport const normalizeSteps = (arr: unknown, cap = 12): string[] => {\n if (!Array.isArray(arr)) return []\n const seen: Record<string, boolean> = {}\n const out: string[] = []\n for (const s of arr) {\n if (out.length >= cap || typeof s !== 'string') continue\n const step = s.trim()\n const key = step.toLowerCase()\n if (!step || seen[key]) continue\n seen[key] = true\n out.push(step)\n }\n return out\n}\n\n/** Decode a JSON string body (\\\" \\\\n \\\\uXXXX …); falls back to the raw text. */\nconst decodeJsonString = (body: string): string => {\n const v = tryParse(`\"${body}\"`)\n return typeof v === 'string' ? v : body\n}\n\n/**\n * Pull \"...\"-quoted strings out of a (possibly truncated) named array. The scan\n * is bounded to the array itself — from its `[` to the matching `]`, or the end\n * of the text when truncated — so values of LATER fields are never swept in.\n */\nconst salvageStringArray = (text: string, field: string): string[] => {\n const m = new RegExp(`\"${field}\"\\\\s*:\\\\s*\\\\[`).exec(text)\n if (!m) return []\n const out: string[] = []\n let i = m.index + m[0].length\n while (i < text.length && text[i] !== ']') {\n if (text[i] !== '\"') {\n i += 1\n continue\n }\n let j = i + 1\n let esc = false\n while (j < text.length && (esc || text[j] !== '\"')) {\n esc = !esc && text[j] === '\\\\'\n j += 1\n }\n if (j >= text.length) break // truncated mid-string — drop the fragment\n out.push(decodeJsonString(text.slice(i + 1, j)))\n i = j + 1\n }\n return out\n}\n\nconst salvageString = (text: string, field: string): string => {\n const m = text.match(new RegExp(`\"${field}\"\\\\s*:\\\\s*\"((?:[^\"\\\\\\\\]|\\\\\\\\.)*)\"`))\n return m ? decodeJsonString(m[1]).trim() : ''\n}\n\n// --- planner ---------------------------------------------------------------\n\nexport interface PlannerResult {\n reply: string\n plan: string[]\n}\n\nexport const parsePlannerResponse = (raw: string): PlannerResult => {\n const text = stripFences(raw)\n const obj = asObject(text)\n if (obj) {\n const reply = typeof obj.reply === 'string' ? obj.reply.trim() : ''\n return { reply, plan: normalizeSteps(obj.plan) }\n }\n if (/\"plan\"\\s*:/.test(text)) {\n return {\n reply: salvageString(text, 'reply'),\n plan: normalizeSteps(salvageStringArray(text, 'plan')),\n }\n }\n return { reply: looksLikeJson(text) ? '' : text.trim(), plan: [] }\n}\n\n// --- executor (tool calls) -------------------------------------------------\n\nexport interface ExecutorResult {\n reply: string\n actions: RawAction[]\n}\n\nconst toActions = (value: unknown): RawAction[] => {\n if (!Array.isArray(value)) return []\n const out: RawAction[] = []\n for (const a of value) {\n if (a && typeof a === 'object' && typeof (a as { tool?: unknown }).tool === 'string') {\n const rec = a as { tool: string; args?: unknown }\n out.push({\n tool: rec.tool,\n args:\n rec.args && typeof rec.args === 'object' && !Array.isArray(rec.args)\n ? (rec.args as Record<string, unknown>)\n : {},\n })\n }\n }\n return out\n}\n\nexport const parseExecutorResponse = (raw: string): ExecutorResult => {\n const text = stripFences(raw)\n const obj = asObject(text)\n if (obj) {\n const reply = typeof obj.reply === 'string' ? obj.reply.trim() : ''\n return { reply, actions: toActions(obj.actions) }\n }\n // Bare actions array.\n const arr = tryParse(extractBalanced(text, '['))\n if (Array.isArray(arr)) {\n const actions = toActions(arr)\n return { reply: '', actions }\n }\n return { reply: looksLikeJson(text) ? '' : text.trim(), actions: [] }\n}\n\n// --- replanner -------------------------------------------------------------\n\nexport interface ReplannerResult {\n decision: ReplanDecision\n reason: string\n plan: string[]\n}\n\nexport const parseReplannerResponse = (raw: string): ReplannerResult => {\n const obj = asObject(stripFences(raw))\n const decision: ReplanDecision =\n obj?.decision === 'revise' || obj?.decision === 'finish' ? obj.decision : 'continue'\n const reason = typeof obj?.reason === 'string' ? obj.reason.trim() : ''\n return { decision, reason, plan: normalizeSteps(obj?.plan) }\n}\n\n// --- plain text (synthesizer / chat answers) -------------------------------\n\n/** Extracts a clean human sentence, never raw JSON. */\nexport const parsePlainText = (raw: string): string => {\n const text = stripFences(raw)\n const obj = asObject(text)\n if (obj && typeof obj.reply === 'string') return obj.reply.trim()\n return looksLikeJson(text) ? '' : text.trim()\n}\n","import type { LanguageModel } from 'ai'\nimport type { BrowserAgentConfig, ResolvedConfig } from '../config.js'\nimport type { AgentEvent } from '../events.js'\nimport type { StoredMessage } from '../memory/store.js'\nimport type { Prompts, ToolCallMode } from '../prompts.js'\nimport { withSystem } from '../prompts.js'\nimport type { AgentToolSet } from '../tools/types.js'\nimport type { AgentLogger } from '../logger.js'\n\n/** Everything the phase functions (planner/executor/replanner/synthesizer) share. */\nexport interface AgentContext {\n config: ResolvedConfig\n raw: BrowserAgentConfig\n plannerModel: LanguageModel\n executorModel: LanguageModel\n synthesizerModel: LanguageModel\n /** Tool-mode for the planner/replanner (from the planner model). */\n plannerMode: ToolCallMode\n /** Tool-mode for the executor (from the executor model). */\n executorMode: ToolCallMode\n tools: AgentToolSet\n toolCatalog: string\n prompts: Prompts\n emit: (event: AgentEvent) => void\n /** Leveled logger (config.logLevel over config.logger ?? console). */\n log: AgentLogger\n signal?: AbortSignal\n /** Current world state for grounding, or undefined when no describeState is configured. */\n state: () => Promise<string | undefined>\n /** Session transcript loaded from memory BEFORE this run's goal was appended. */\n history?: StoredMessage[]\n}\n\n/** Prepend the host's systemPrompt to a phase system prompt. */\nexport const systemFor = (ctx: AgentContext, base: string): string =>\n withSystem(base, ctx.raw.systemPrompt)\n\nexport const aborted = (ctx: AgentContext): boolean => ctx.signal?.aborted === true\n","import { runToolLoop } from '../llm/tool-loop.js'\nimport { renderCatalog } from '../tools/prompted.js'\nimport type { IPlanStep, IStepResult, IUsage } from './loop-types.js'\nimport { systemFor, type AgentContext } from './internal.js'\n\nconst BLOCKER = '[BLOCKER]'\n\n/**\n * Split the executor's reply into a clean summary and a structural `blocked`\n * flag. The [BLOCKER] sentinel — emitted by the executor when it can't complete\n * a step — is language-agnostic and drives the replanner; we strip every copy\n * so it never leaks into downstream prompts.\n */\nexport const splitBlocker = (raw: string): { summary: string; blocked: boolean } => {\n if (!raw.includes(BLOCKER)) return { summary: raw.trim(), blocked: false }\n return { summary: raw.split(BLOCKER).join('').trim(), blocked: true }\n}\n\nconst activeToolNames = (ctx: AgentContext, step: IPlanStep): string[] | undefined => {\n if (ctx.config.toolSelectionStrategy !== 'plan-narrowed') return undefined\n const suggested = step.suggestedTools ?? []\n const known = suggested.filter((n) => ctx.tools[n])\n // A step that named tools but all were unknown still wants tools: fall back to\n // the full set rather than stalling with zero.\n if (known.length === 0 && suggested.length > 0) return Object.keys(ctx.tools)\n return known\n}\n\nconst summaryOf = (text: string, toolCallCount: number): string => {\n if (text.length > 0) return text\n return toolCallCount > 0 ? `Executed ${toolCallCount} tool call(s).` : 'Step produced no output.'\n}\n\n/** Execute one plan step: run the tool loop (native or prompted) and emit events. */\nexport const executeStep = async (\n ctx: AgentContext,\n goal: string,\n step: IPlanStep,\n index: number,\n total: number,\n done: string[],\n): Promise<{ result: IStepResult; usage: IUsage }> => {\n const state = await ctx.state()\n // Under plan-narrowed selection the prompted path must also see the narrowed\n // catalogue — the prompt is its only tool surface (native mode gets the SDK's\n // activeTools instead and never renders the catalogue).\n const active = activeToolNames(ctx, step)\n const toolCatalog =\n active === undefined\n ? ctx.toolCatalog\n : renderCatalog(Object.fromEntries(active.map((name) => [name, ctx.tools[name]])))\n const parts = ctx.prompts.executor({\n goal,\n state,\n step: step.description,\n index,\n total,\n toolCatalog,\n done,\n mode: ctx.executorMode,\n })\n\n const loop = await runToolLoop(ctx.executorModel, {\n mode: ctx.executorMode,\n system: systemFor(ctx, parts.system),\n prompt: parts.prompt,\n tools: ctx.tools,\n activeTools: active,\n maxSteps: ctx.config.maxStepsPerTask,\n maxOutputTokens: ctx.config.budgets.executor,\n temperature: ctx.config.temperature,\n abortSignal: ctx.signal,\n timeoutMs: ctx.config.chatTimeoutMs,\n callbacks: {\n onTextDelta: (delta) => ctx.emit({ type: 'step.text-delta', step, delta }),\n onToolCall: (name, input) => {\n ctx.log.info(`tool call: ${name}`, input)\n ctx.emit({ type: 'step.tool-call', step, name, input })\n },\n onToolResult: (name, output, ok) => {\n ctx.log.debug(`tool result: ${name} ${ok ? 'ok' : 'FAILED'}`, output)\n ctx.emit({ type: 'step.tool-result', step, name, output, ok })\n },\n },\n })\n ctx.log.debug('executor text:', loop.text)\n\n const { summary, blocked } = splitBlocker(loop.text)\n return {\n result: {\n step,\n summary: summaryOf(summary, loop.toolCalls.length),\n toolCalls: loop.toolCalls,\n blocked,\n },\n usage: loop.usage,\n }\n}\n\n/** The replanner runs when a step was blocked or any of its tool calls failed. */\nexport const shouldReplan = (result: IStepResult): boolean =>\n result.blocked || result.toolCalls.some((c) => !c.ok)\n","/** A single step of a plan. Mirrors the Node sibling's IPlanStep. */\nexport interface IPlanStep {\n id: string\n description: string\n expectedOutcome?: string\n /** Tools the planner thinks this step needs (drives 'plan-narrowed' selection). */\n suggestedTools?: string[]\n /** Set by the pipeline when suggestedTools were named but all were unknown. */\n requiresTools?: boolean\n}\n\nexport interface IPlan {\n thought: string\n steps: IPlanStep[]\n}\n\nexport interface IUsage {\n inputTokens: number\n outputTokens: number\n totalTokens: number\n}\n\nexport interface IToolCall {\n name: string\n input: unknown\n output: unknown\n ok: boolean\n}\n\nexport interface IStepResult {\n step: IPlanStep\n summary: string\n toolCalls: IToolCall[]\n /** True when the executor signalled it could not complete the step ([BLOCKER]). */\n blocked: boolean\n}\n\nexport const emptyUsage = (): IUsage => ({ inputTokens: 0, outputTokens: 0, totalTokens: 0 })\n\nexport const addUsage = (a: IUsage, b: IUsage): IUsage => ({\n inputTokens: a.inputTokens + b.inputTokens,\n outputTokens: a.outputTokens + b.outputTokens,\n totalTokens: a.totalTokens + b.totalTokens,\n})\n","import { z } from 'zod'\n\n/**\n * Structured-output schemas for the native path (generateObject). Kept free of\n * `.max()`/`.min()` constraints — some providers reject or mis-handle them in\n * JSON-schema mode; we cap/clean in code instead (see parse.ts normalizeSteps).\n */\nexport const PlanStepSchema = z.object({\n description: z.string(),\n expectedOutcome: z.string().optional(),\n suggestedTools: z.array(z.string()).optional(),\n})\n\nexport const PlanSchema = z.object({\n /** One short sentence. For a greeting/question/unclear request, holds the answer and steps is empty. */\n thought: z.string(),\n steps: z.array(PlanStepSchema),\n})\n\nexport const ReplanSchema = z.object({\n decision: z.enum(['continue', 'revise', 'finish']),\n reason: z.string(),\n /** Replacement for the REMAINING steps when decision is 'revise'. */\n plan: z.array(z.string()).optional(),\n})\n\nexport type PlanShape = z.infer<typeof PlanSchema>\nexport type ReplanShape = z.infer<typeof ReplanSchema>\n","import { generate, generateStructured } from '../llm/generate.js'\nimport { normalizeUsage } from '../llm/util.js'\nimport { parsePlannerResponse } from '../parse.js'\nimport type { ToolCallMode } from '../prompts.js'\nimport type { IPlan, IUsage } from './loop-types.js'\nimport { systemFor, type AgentContext } from './internal.js'\nimport { PlanSchema } from './schemas.js'\n\nconst toSteps = (\n raw: { description: string; expectedOutcome?: string; suggestedTools?: string[] }[],\n): IPlan['steps'] =>\n raw\n .filter((s) => s.description && s.description.trim())\n .map((s, i) => ({\n id: `s${i + 1}`,\n description: s.description.trim(),\n expectedOutcome: s.expectedOutcome,\n suggestedTools: s.suggestedTools,\n }))\n\n/**\n * Build the initial plan. Native mode uses generateObject(PlanSchema); prompted\n * mode salvages `{ reply, plan }` from plain text. Native failures (a weak model\n * that can't satisfy the schema) fall back to the prompted parse rather than\n * throwing, so the run degrades gracefully. An empty `steps` list signals the\n * runner to answer directly (greeting / question / unclear).\n */\nexport const createPlan = async (\n ctx: AgentContext,\n goal: string,\n /** Extra instruction appended to the goal (used by the empty-plan retry). */\n nudge?: string,\n): Promise<{ plan: IPlan; usage: IUsage }> => {\n const state = await ctx.state()\n const effectiveGoal = nudge ? `${goal}\\n\\n${nudge}` : goal\n const commonFor = (mode: ToolCallMode) => {\n const parts = ctx.prompts.planner({\n goal: effectiveGoal,\n state,\n toolCatalog: ctx.toolCatalog,\n mode,\n history: ctx.history,\n })\n return {\n system: systemFor(ctx, parts.system),\n prompt: parts.prompt,\n maxOutputTokens: ctx.config.budgets.planner,\n temperature: ctx.config.temperature,\n abortSignal: ctx.signal,\n timeoutMs: ctx.config.chatTimeoutMs,\n }\n }\n\n if (ctx.plannerMode === 'native') {\n try {\n const result = await generateStructured(ctx.plannerModel, PlanSchema, commonFor('native'))\n ctx.log.debug('planner (native):', result.object)\n return {\n plan: { thought: result.object.thought, steps: toSteps(result.object.steps) },\n usage: normalizeUsage(result.usage),\n }\n } catch (err) {\n // Graceful degradation: fall back to the salvage parser instead of failing.\n ctx.log.warn('planner: native structured output failed, salvaging:', asMessage(err))\n ctx.emit({ type: 'retry', phase: 'plan', attempt: 1, error: asMessage(err) })\n }\n }\n\n // The prompted path — also the fallback after a native failure. Rendered with\n // mode 'prompted' so the model gets explicit JSON-shape instructions even\n // when the schema-constrained call just failed.\n const result = await generate(ctx.plannerModel, commonFor('prompted'))\n const parsed = parsePlannerResponse(result.text)\n ctx.log.debug('planner (prompted) raw:', result.text)\n ctx.log.debug('planner (prompted) parsed:', parsed)\n return {\n plan: {\n thought: parsed.reply,\n steps: toSteps(parsed.plan.map((description) => ({ description }))),\n },\n usage: normalizeUsage(result.usage),\n }\n}\n\nconst asMessage = (err: unknown): string => (err instanceof Error ? err.message : String(err))\n","import { generate, generateStructured } from '../llm/generate.js'\nimport { normalizeUsage } from '../llm/util.js'\nimport { parseReplannerResponse, type ReplanDecision } from '../parse.js'\nimport type { ToolCallMode } from '../prompts.js'\nimport type { IUsage } from './loop-types.js'\nimport { emptyUsage } from './loop-types.js'\nimport { systemFor, type AgentContext } from './internal.js'\nimport { ReplanSchema } from './schemas.js'\n\nexport interface ReplanOutcome {\n decision: ReplanDecision\n reason: string\n /** Replacement remaining steps (descriptions) when decision is 'revise'. */\n plan: string[]\n usage: IUsage\n}\n\n/**\n * Decide whether to continue, revise the remaining plan, or finish, after a\n * blocked/failed step. Native mode uses generateObject(ReplanSchema); prompted\n * mode salvages the decision from text. Any failure degrades to 'continue' so a\n * flaky replanner never aborts the run.\n */\nexport const decideReplan = async (\n ctx: AgentContext,\n goal: string,\n done: string[],\n remaining: string[],\n): Promise<ReplanOutcome> => {\n const state = await ctx.state()\n const commonFor = (mode: ToolCallMode) => {\n const parts = ctx.prompts.replanner({ goal, state, done, remaining, mode })\n return {\n system: systemFor(ctx, parts.system),\n prompt: parts.prompt,\n maxOutputTokens: ctx.config.budgets.replanner,\n temperature: ctx.config.temperature,\n abortSignal: ctx.signal,\n timeoutMs: ctx.config.chatTimeoutMs,\n }\n }\n\n if (ctx.plannerMode === 'native') {\n try {\n const result = await generateStructured(ctx.plannerModel, ReplanSchema, commonFor('native'))\n return {\n decision: result.object.decision,\n reason: result.object.reason,\n plan: result.object.plan ?? [],\n usage: normalizeUsage(result.usage),\n }\n } catch {\n /* fall through to the prompted salvage below */\n }\n }\n\n try {\n // The prompted path — also the fallback after a native failure, re-rendered\n // with explicit JSON-shape instructions.\n const result = await generate(ctx.plannerModel, commonFor('prompted'))\n const parsed = parseReplannerResponse(result.text)\n return {\n decision: parsed.decision,\n reason: parsed.reason,\n plan: parsed.plan,\n usage: normalizeUsage(result.usage),\n }\n } catch {\n return { decision: 'continue', reason: 'replanner unavailable', plan: [], usage: emptyUsage() }\n }\n}\n","import { stream } from '../llm/generate.js'\nimport { normalizeUsage } from '../llm/util.js'\nimport { looksLikeJson, parsePlainText } from '../parse.js'\nimport type { IUsage } from './loop-types.js'\nimport { systemFor, type AgentContext } from './internal.js'\n\n/**\n * Write the final natural-language summary of what the run accomplished,\n * streaming it as `final.text-delta` events. Plain text only (parsePlainText\n * strips any stray JSON; deltas are suppressed entirely when the model drifts\n * into JSON, so raw structure never reaches a UI). Falls back to a default\n * sentence if the model returns nothing usable.\n */\nexport const synthesizeAnswer = async (\n ctx: AgentContext,\n goal: string,\n done: string[],\n): Promise<{ text: string; usage: IUsage }> => {\n const state = await ctx.state()\n const parts = ctx.prompts.synthesizer({ goal, state, done })\n const result = stream(ctx.synthesizerModel, {\n system: systemFor(ctx, parts.system),\n prompt: parts.prompt,\n maxOutputTokens: ctx.config.budgets.synthesizer,\n temperature: ctx.config.temperature,\n abortSignal: ctx.signal,\n timeoutMs: ctx.config.chatTimeoutMs,\n })\n\n let text = ''\n let verdict: 'unknown' | 'emit' | 'suppress' = 'unknown'\n for await (const delta of result.textStream) {\n text += delta\n if (verdict === 'unknown') {\n const lead = text.trimStart()\n if (!lead) continue\n verdict = looksLikeJson(lead) ? 'suppress' : 'emit'\n if (verdict === 'emit') ctx.emit({ type: 'final.text-delta', delta: text })\n } else if (verdict === 'emit') {\n ctx.emit({ type: 'final.text-delta', delta })\n }\n }\n\n const clean = parsePlainText(text)\n return {\n text: clean || 'Done — the changes have been applied.',\n usage: normalizeUsage(await result.usage),\n }\n}\n","/**\n * Leveled logging for the agent. The host passes a console-like sink and a\n * level; everything below the level is a no-op. Default: 'warn' onto the\n * global console — silent in normal operation, but salvage fallbacks, empty\n * plans, degraded tool modes and failed tool calls stay visible.\n *\n * Set `logLevel: 'debug'` to see every phase's raw model output, parsed\n * results and tool dispatches — the first thing to reach for when the agent\n * \"says it did something but nothing happened\".\n */\n\nexport type LogLevel = 'silent' | 'error' | 'warn' | 'info' | 'debug'\n\n/** Console-compatible sink (pass `console`, or your own collector). */\nexport interface AgentLoggerSink {\n error(...args: unknown[]): void\n warn(...args: unknown[]): void\n info(...args: unknown[]): void\n debug(...args: unknown[]): void\n}\n\nexport interface AgentLogger extends AgentLoggerSink {\n readonly level: LogLevel\n}\n\nconst WEIGHT: Record<LogLevel, number> = {\n silent: 0,\n error: 1,\n warn: 2,\n info: 3,\n debug: 4,\n}\n\nconst PREFIX = '[agent-web]'\n\nconst noop = (): void => undefined\n\nexport const createLogger = (\n level: LogLevel = 'warn',\n sink: AgentLoggerSink = console,\n): AgentLogger => {\n const at = (min: LogLevel, fn: (...args: unknown[]) => void) =>\n WEIGHT[level] >= WEIGHT[min] ? (...args: unknown[]) => fn.call(sink, PREFIX, ...args) : noop\n return {\n level,\n error: at('error', sink.error),\n warn: at('warn', sink.warn),\n info: at('info', sink.info),\n debug: at('debug', sink.debug),\n }\n}\n","import type { LanguageModel } from 'ai'\nimport type { BrowserAgentConfig } from '../config.js'\nimport { resolveConfig } from '../config.js'\nimport type { AgentEvent, AgentEventHandler, Phase } from '../events.js'\nimport { compressHistory } from '../memory/compress.js'\nimport type { StoredMessage } from '../memory/store.js'\nimport { buildModelFromStage, resolveStage } from '../providers/registry.js'\nimport { defaultPrompts, type Prompts } from '../prompts.js'\nimport { selectToolMode } from '../tools/mode.js'\nimport { renderCatalog } from '../tools/prompted.js'\nimport type { AgentToolSet } from '../tools/types.js'\nimport { executeStep, shouldReplan } from './executor.js'\nimport type { AgentContext } from './internal.js'\nimport {\n addUsage,\n emptyUsage,\n type IPlan,\n type IPlanStep,\n type IStepResult,\n type IUsage,\n} from './loop-types.js'\nimport { createPlan } from './planner.js'\nimport { decideReplan } from './replanner.js'\nimport { synthesizeAnswer } from './synthesizer.js'\nimport { createLogger } from '../logger.js'\n\nexport interface RunOptions {\n onEvent?: AgentEventHandler\n signal?: AbortSignal\n /** Override the config's sessionId for this run. */\n sessionId?: string\n}\n\nexport interface RunResult {\n goal: string\n final: string\n plan: IPlan\n trace: IStepResult[]\n steps: number\n /** Total successful tool calls across the run. */\n applied: number\n stopped: boolean\n usage: IUsage\n}\n\nexport interface Agent {\n run(goal: string, opts?: RunOptions): Promise<RunResult>\n /** The resolved models, for hosts that want to reuse them (e.g. warm-up). */\n readonly models: {\n planner: LanguageModel\n executor: LanguageModel\n synthesizer: LanguageModel\n }\n}\n\nconst errMessage = (err: unknown): string => (err instanceof Error ? err.message : String(err))\n\n/** Apply the config's availableTools whitelist and excludedTools blacklist. */\nconst filterTools = (\n all: AgentToolSet,\n available?: string[],\n excluded?: string[],\n): AgentToolSet => {\n let entries = Object.entries(all)\n if (available && available.length > 0) entries = entries.filter(([n]) => available.includes(n))\n if (excluded && excluded.length > 0) entries = entries.filter(([n]) => !excluded.includes(n))\n return Object.fromEntries(entries)\n}\n\n/**\n * Create a headless plan → execute → replan → synthesize agent. Models are\n * resolved eagerly (dynamic provider imports + vault key fetch), so this is\n * async. Each `run` streams typed AgentEvents for any UI to render.\n */\nexport const createAgent = async (config: BrowserAgentConfig): Promise<Agent> => {\n const cfg = resolveConfig(config)\n // Build the executor once; a stage without an override reuses it instead of\n // constructing a second identical model (for web-llm that would mean loading\n // the same weights into the GPU again).\n const buildStage = (override: BrowserAgentConfig['planner'], stageName: string) =>\n buildModelFromStage(\n resolveStage(config.model, override, stageName),\n config.credentials,\n cfg.clientName,\n )\n const executorP = buildStage(undefined, 'executor')\n const [executorModel, plannerModel, synthesizerModel] = await Promise.all([\n executorP,\n config.planner === undefined ? executorP : buildStage(config.planner, 'planner'),\n config.synthesizer === undefined ? executorP : buildStage(config.synthesizer, 'synthesizer'),\n ])\n\n const plannerMode = selectToolMode(plannerModel, cfg.toolMode)\n const executorMode = selectToolMode(executorModel, cfg.toolMode)\n const tools: AgentToolSet = filterTools(\n config.tools ?? {},\n config.availableTools,\n config.excludedTools,\n )\n const toolCatalog = renderCatalog(tools)\n const prompts: Prompts = { ...defaultPrompts, ...config.prompts }\n const log = createLogger(cfg.logLevel, config.logger)\n log.info(\n `agent ready — tools: [${Object.keys(tools).join(', ') || 'none'}], planner mode: ${plannerMode}, executor mode: ${executorMode}`,\n )\n\n const run = async (goal: string, opts: RunOptions = {}): Promise<RunResult> => {\n const emit = (event: AgentEvent): void => {\n try {\n opts.onEvent?.(event)\n } catch {\n /* a bad handler must not break the run */\n }\n }\n const text = goal.trim()\n const sessionId = opts.sessionId ?? cfg.sessionId\n let usage = emptyUsage()\n const result: RunResult = {\n goal: text,\n final: '',\n plan: { thought: '', steps: [] },\n trace: [],\n steps: 0,\n applied: 0,\n stopped: false,\n usage,\n }\n if (!text) return result\n\n const state = async (): Promise<string | undefined> =>\n config.describeState ? config.describeState() : undefined\n const isAborted = (): boolean => opts.signal?.aborted === true\n const bumpUsage = (u: IUsage, phase: Phase): void => {\n usage = addUsage(usage, u)\n result.usage = usage\n emit({ type: 'usage', phase, usage: u })\n }\n const remember = async (msg: StoredMessage): Promise<void> => {\n if (!config.memory) return\n try {\n await config.memory.append(sessionId, msg)\n } catch {\n /* persistence is best-effort */\n }\n }\n\n emit({ type: 'run.start', goal: text })\n // Read back the session transcript BEFORE appending the current goal, so\n // the planner can resolve references to earlier turns (\"make it bigger\").\n let history: StoredMessage[] = []\n if (config.memory) {\n try {\n history = await config.memory.load(sessionId)\n } catch {\n /* persistence is best-effort */\n }\n }\n const ctx: AgentContext = {\n config: cfg,\n raw: config,\n plannerModel,\n executorModel,\n synthesizerModel,\n plannerMode,\n executorMode,\n tools,\n toolCatalog,\n prompts,\n emit,\n log,\n signal: opts.signal,\n state,\n history,\n }\n await remember({ role: 'user', content: text })\n log.info('run:', text)\n\n try {\n // 1) PLAN\n let planned = await createPlan(ctx, text)\n bumpUsage(planned.usage, 'plan')\n if (isAborted()) {\n emit({ type: 'stopped' })\n result.stopped = true\n return result\n }\n\n // Small models sometimes return an empty plan for a clearly actionable\n // goal — and put a hallucinated \"done!\" into the thought, so the run\n // would claim success while never touching a tool. Give the planner one\n // nudged retry before treating the turn as conversational.\n if (planned.plan.steps.length === 0 && text.split(/\\s+/).length > 2) {\n log.warn(\n 'planner returned no steps for a multi-word goal — retrying with a nudge. thought:',\n planned.plan.thought,\n )\n const retried = await createPlan(\n ctx,\n text,\n 'NOTE: If the message above asks to build, add, change, clear or delete ANYTHING, you MUST output 1-6 concrete steps. Output an empty plan ONLY for a pure greeting or question.',\n )\n bumpUsage(retried.usage, 'plan')\n if (retried.plan.steps.length > 0) planned = retried\n }\n result.plan = planned.plan\n if (isAborted()) {\n emit({ type: 'stopped' })\n result.stopped = true\n return result\n }\n\n // Greeting / question / unclear → answer directly, run no tools.\n if (planned.plan.steps.length === 0) {\n log.info('no plan — answering directly (no tools will run)')\n const answer = planned.plan.thought.trim() || \"Tell me what you'd like to do.\"\n emit({ type: 'final', text: answer })\n await remember({ role: 'assistant', content: answer })\n result.final = answer\n return result\n }\n log.info(\n `plan (${planned.plan.steps.length} steps):`,\n planned.plan.steps.map((s) => s.description),\n )\n emit({ type: 'plan.created', plan: planned.plan })\n planned.plan.steps.forEach((step, index) => emit({ type: 'plan.step-added', step, index }))\n\n // 2) EXECUTE → REPLAN\n const done: string[] = []\n let remaining: IPlanStep[] = [...planned.plan.steps]\n let iter = 0\n let revisions = 0\n while (remaining.length > 0 && iter < cfg.maxIterations) {\n if (isAborted()) {\n emit({ type: 'stopped' })\n result.stopped = true\n return result\n }\n iter += 1\n const step = remaining.shift() as IPlanStep\n const stepNo = done.length + 1\n const total = stepNo + remaining.length\n emit({ type: 'step.start', step, index: stepNo, total })\n\n let stepResult: IStepResult\n try {\n const out = await executeStep(ctx, text, step, stepNo, total, done)\n bumpUsage(out.usage, 'execute')\n stepResult = out.result\n } catch (err) {\n // A user abort surfaces as a thrown AbortError — that is a stop, not\n // a step failure.\n if (isAborted()) {\n emit({ type: 'stopped' })\n result.stopped = true\n return result\n }\n emit({ type: 'error', phase: 'execute', error: errMessage(err) })\n stepResult = { step, summary: errMessage(err), toolCalls: [], blocked: true }\n }\n\n result.trace.push(stepResult)\n const applied = stepResult.toolCalls.filter((c) => c.ok).length\n const failed = stepResult.toolCalls.length - applied\n result.applied += applied\n result.steps = stepNo\n log.info(\n `step ${stepNo}/${total} \"${step.description}\" — ${stepResult.toolCalls.length} tool call(s), ${applied} ok${failed ? `, ${failed} FAILED` : ''}${stepResult.blocked ? ', BLOCKED' : ''}`,\n )\n if (stepResult.toolCalls.length === 0) {\n log.warn(`step ${stepNo} made no tool calls — nothing changed in this step`)\n }\n stepResult.toolCalls\n .filter((c) => !c.ok)\n .forEach((c) => log.warn(`tool ${c.name} failed:`, c.output))\n log.debug(`step ${stepNo} detail:`, stepResult)\n emit({ type: 'step.complete', step, result: stepResult })\n done.push(\n `${step.description} — ${applied} applied${failed ? `, ${failed} failed` : ''}${stepResult.blocked ? ', blocked' : ''}`,\n )\n\n // 2b) REPLAN (only after a blocked / failed step). Also runs when the\n // FAILED step was the last one — 'revise' can then add remedial steps.\n if (\n cfg.replan &&\n iter < cfg.maxIterations &&\n revisions < cfg.maxRevisions &&\n !isAborted() &&\n shouldReplan(stepResult)\n ) {\n const decision = await decideReplan(\n ctx,\n text,\n done,\n remaining.map((s) => s.description),\n )\n bumpUsage(decision.usage, 'replan')\n emit({ type: 'replan.decision', mode: decision.decision, reason: decision.reason })\n if (decision.decision === 'finish') break\n if (decision.decision === 'revise' && decision.plan.length > 0) {\n revisions += 1\n remaining = decision.plan\n .slice(0, cfg.maxIterations - iter)\n .map((description, i) => ({ id: `r${iter}-${i + 1}`, description }))\n emit({\n type: 'plan.revised',\n plan: { thought: planned.plan.thought, steps: remaining },\n reason: decision.reason,\n })\n }\n }\n }\n\n if (isAborted()) {\n emit({ type: 'stopped' })\n result.stopped = true\n return result\n }\n\n // 3) SYNTHESIZE\n let summary = 'Done — the changes have been applied.'\n if (cfg.synthesize) {\n try {\n const synth = await synthesizeAnswer(ctx, text, done)\n bumpUsage(synth.usage, 'synthesize')\n if (synth.text) summary = synth.text\n } catch {\n /* keep the default */\n }\n }\n log.info(`done — ${result.applied} tool call(s) applied over ${result.steps} step(s)`)\n emit({ type: 'final', text: summary })\n await remember({ role: 'assistant', content: summary })\n result.final = summary\n\n // 4) COMPRESS persisted history\n if (config.memory && cfg.compressAfterChars > 0) {\n try {\n const transcript = await config.memory.load(sessionId)\n const compacted = await compressHistory(transcript, synthesizerModel, {\n maxChars: cfg.compressAfterChars,\n timeoutMs: cfg.chatTimeoutMs,\n abortSignal: opts.signal,\n })\n if (compacted !== transcript) await config.memory.replace(sessionId, compacted)\n } catch {\n /* best-effort */\n }\n }\n return result\n } catch (err) {\n emit({ type: 'error', phase: 'run', error: errMessage(err) })\n result.final = errMessage(err)\n return result\n }\n }\n\n return {\n run,\n models: { planner: plannerModel, executor: executorModel, synthesizer: synthesizerModel },\n }\n}\n","import type { ProviderType } from './types.js'\n\n// Cloud providers are reliable at native function-calling and JSON-schema\n// structured output. Local WebGPU models (web-llm) technically support both,\n// but tiny (1–3B) models are unreliable at them, so we default local models to\n// the prompted/salvage path (overridable via config.toolMode).\nconst CLOUD: ReadonlySet<ProviderType> = new Set<ProviderType>([\n 'openai',\n 'anthropic',\n 'google',\n 'openai-compatible',\n 'xai',\n 'deepseek',\n 'gateway',\n])\n\n/** Whether native tool-calling is reliable enough to be the default for a provider. */\nexport const supportsNativeTools = (p: ProviderType): boolean => CLOUD.has(p)\n\n/** Whether native structured output (generateObject) is the default for a provider. */\nexport const supportsStructuredOutput = (p: ProviderType): boolean => CLOUD.has(p)\n\n/**\n * Whether calling this provider straight from a browser origin with a BYOK key\n * is expected to work (CORS + browser-access policy). Hosts can use this to\n * warn users before a direct call fails.\n *\n * - `google`: Gemini's endpoint is CORS-enabled — the most reliable direct BYOK path.\n * - `gateway` / `openai-compatible`: the host controls the endpoint / CORS.\n * - `anthropic`: works, but only with the direct-browser-access header, which\n * the registry injects automatically.\n * - `openai`: api.openai.com does NOT reliably send CORS for browser calls —\n * route through a proxy `baseURL` or the gateway.\n * - `xai` / `deepseek`: unreliable from the browser; prefer a proxy.\n */\nexport const directBrowserOk = (p: ProviderType): boolean =>\n p === 'google' || p === 'gateway' || p === 'openai-compatible' || p === 'anthropic'\n","import { openDB, type IDBPDatabase } from 'idb'\n\nexport interface AgentWebDBOptions {\n /** Database name (default 'agent-web'). Use a distinct name to isolate apps. */\n dbName?: string\n}\n\nexport const KEYS_STORE = 'keys'\nexport const SECRETS_STORE = 'secrets'\nexport const SESSIONS_STORE = 'sessions'\n\nlet cache = new Map<string, Promise<IDBPDatabase>>()\n\n/**\n * The single owner of the IndexedDB database. Every persistent store — the\n * non-extractable crypto key, encrypted secrets, and session transcripts —\n * lives under ONE database name + version. Centralising `openDB` here prevents\n * the classic bug where two modules open the same DB name with different store\n * sets and the second call throws a VersionError.\n */\nexport const openAgentWebDB = (opts: AgentWebDBOptions = {}): Promise<IDBPDatabase> => {\n const name = opts.dbName ?? 'agent-web'\n let p = cache.get(name)\n if (!p) {\n p = openDB(name, 1, {\n upgrade(db) {\n if (!db.objectStoreNames.contains(KEYS_STORE)) db.createObjectStore(KEYS_STORE)\n if (!db.objectStoreNames.contains(SECRETS_STORE)) db.createObjectStore(SECRETS_STORE)\n if (!db.objectStoreNames.contains(SESSIONS_STORE)) db.createObjectStore(SESSIONS_STORE)\n },\n })\n cache.set(name, p)\n // A failed open (private mode, storage denied) must not stay cached, or\n // every later call would replay the same rejection forever.\n p.catch(() => {\n if (cache.get(name) === p) cache.delete(name)\n })\n }\n return p\n}\n\n/** Test hook: drop cached connections so a fresh (e.g. fake-indexeddb) DB is opened. */\nexport const _resetDBCache = (): void => {\n cache = new Map()\n}\n","import { KEYS_STORE, openAgentWebDB } from '../storage/db.js'\n\nconst KEY_ID = 'vault-key-v1'\n\nconst webcrypto = (): Crypto => {\n const c = (globalThis as { crypto?: Crypto }).crypto\n if (!c?.subtle || !c.getRandomValues) {\n throw new Error('WebCrypto (crypto.subtle) is unavailable in this environment')\n }\n return c\n}\n\nconst loadOrCreateKey = async (dbName?: string): Promise<CryptoKey> => {\n const db = await openAgentWebDB({ dbName })\n const existing = (await db.get(KEYS_STORE, KEY_ID)) as CryptoKey | undefined\n if (existing) return existing\n const key = await webcrypto().subtle.generateKey(\n { name: 'AES-GCM', length: 256 },\n /* extractable */ false,\n ['encrypt', 'decrypt'],\n )\n // Double-check inside one readwrite transaction: another tab may have created\n // a key while ours was generating. Losing that race and overwriting would\n // leave the other tab's secrets permanently undecryptable.\n const tx = db.transaction(KEYS_STORE, 'readwrite')\n const winner = (await tx.store.get(KEY_ID)) as CryptoKey | undefined\n if (winner) {\n await tx.done\n return winner\n }\n await tx.store.put(key, KEY_ID)\n await tx.done\n return key\n}\n\nconst keyCache = new Map<string, Promise<CryptoKey>>()\n\n/**\n * Fetch (or lazily create) the vault's AES-GCM key. The key is generated\n * NON-EXTRACTABLE and stored as a live `CryptoKey` in IndexedDB — a CryptoKey\n * is structured-cloneable, so it persists across reloads WITHOUT its raw bytes\n * ever being exposed to JavaScript. Not even in-page script can read it out; it\n * can only be used to encrypt / decrypt. That is what makes at-rest storage of\n * the secrets meaningful (see IndexedDBVault's threat model).\n *\n * Concurrent callers share one in-flight promise per DB, and creation is\n * double-checked in a single IDB transaction, so two racing writers can never\n * end up encrypting under different keys.\n */\nexport const getOrCreateVaultKey = (dbName?: string): Promise<CryptoKey> => {\n const cacheKey = dbName ?? 'agent-web'\n let p = keyCache.get(cacheKey)\n if (!p) {\n p = loadOrCreateKey(dbName)\n keyCache.set(cacheKey, p)\n p.catch(() => {\n if (keyCache.get(cacheKey) === p) keyCache.delete(cacheKey)\n })\n }\n return p\n}\n\nexport interface EncryptedBlob {\n /** 96-bit random IV, fresh per write. */\n iv: Uint8Array\n ciphertext: ArrayBuffer\n}\n\nconst textEncoder = new TextEncoder()\nconst textDecoder = new TextDecoder()\n\n/** Encrypt a JSON-serialisable value with a fresh 96-bit IV (AES-GCM). */\nexport const encryptJSON = async (key: CryptoKey, value: unknown): Promise<EncryptedBlob> => {\n const c = webcrypto()\n const iv = c.getRandomValues(new Uint8Array(12))\n const data = textEncoder.encode(JSON.stringify(value))\n const ciphertext = await c.subtle.encrypt({ name: 'AES-GCM', iv }, key, data)\n return { iv, ciphertext }\n}\n\n/** Decrypt a blob produced by encryptJSON. Throws if the key or blob don't match. */\nexport const decryptJSON = async <T = unknown>(key: CryptoKey, blob: EncryptedBlob): Promise<T> => {\n // Copy the IV into a fresh ArrayBuffer-backed view: after a round-trip through\n // IndexedDB its element buffer is typed as ArrayBufferLike, which no longer\n // satisfies BufferSource under TS's stricter typed-array generics.\n const iv = new Uint8Array(blob.iv)\n const plain = await webcrypto().subtle.decrypt({ name: 'AES-GCM', iv }, key, blob.ciphertext)\n return JSON.parse(textDecoder.decode(plain)) as T\n}\n","import { openAgentWebDB, SECRETS_STORE } from '../storage/db.js'\nimport { decryptJSON, encryptJSON, getOrCreateVaultKey, type EncryptedBlob } from './crypto.js'\n\nexport interface VaultOptions {\n /** Database name, forwarded to the shared IDB owner (default 'agent-web'). */\n dbName?: string\n}\n\n/**\n * Encrypted key/value secret store backed by IndexedDB. Values are encrypted at\n * rest with the non-extractable AES-GCM vault key (see crypto.ts).\n *\n * ── THREAT MODEL (read before shipping any app-owned key to a browser) ──\n * This vault PROTECTS secrets **at rest** — an IndexedDB / disk dump yields\n * only ciphertext — and against **casual DevTools inspection** — no plaintext\n * key is stored, and the AES key cannot be exported even by in-page script.\n *\n * It does **NOT** defend against **active XSS on your origin**: any script that\n * already runs on the page can call `getSecret()`, or use the live `CryptoKey`\n * to decrypt. Browser storage is not a secrets manager.\n *\n * Therefore this vault is for the **end user's OWN key on their OWN device**\n * (bring-your-own-key). A shared, app-owned key must NEVER reach the client —\n * put it behind a server proxy (`ProviderModelSpec.baseURL`) or the Vercel AI\n * Gateway instead.\n */\nexport class IndexedDBVault {\n private readonly dbName?: string\n\n constructor(opts: VaultOptions = {}) {\n this.dbName = opts.dbName\n }\n\n private key(): Promise<CryptoKey> {\n return getOrCreateVaultKey(this.dbName)\n }\n\n /** Encrypt and store a secret string under `id`. */\n async setSecret(id: string, value: string): Promise<void> {\n const blob = await encryptJSON(await this.key(), value)\n const db = await openAgentWebDB({ dbName: this.dbName })\n await db.put(SECRETS_STORE, blob, id)\n }\n\n /** Fetch and decrypt a secret, or undefined if absent. */\n async getSecret(id: string): Promise<string | undefined> {\n const db = await openAgentWebDB({ dbName: this.dbName })\n const blob = (await db.get(SECRETS_STORE, id)) as EncryptedBlob | undefined\n if (!blob) return undefined\n return decryptJSON<string>(await this.key(), blob)\n }\n\n async deleteSecret(id: string): Promise<void> {\n const db = await openAgentWebDB({ dbName: this.dbName })\n await db.delete(SECRETS_STORE, id)\n }\n\n async listSecretIds(): Promise<string[]> {\n const db = await openAgentWebDB({ dbName: this.dbName })\n return (await db.getAllKeys(SECRETS_STORE)).map(String)\n }\n}\n","import { IndexedDBVault, type VaultOptions } from './vault.js'\n\n/**\n * The seam the provider registry uses to fetch API keys at model-build time.\n * Swap in any backend: the encrypted vault (default), an in-memory map (tests /\n * SSR), or a `fetch` to your own short-lived-token endpoint.\n */\nexport interface CredentialStore {\n getApiKey(ref: string): Promise<string | undefined>\n setApiKey(ref: string, key: string): Promise<void>\n deleteApiKey(ref: string): Promise<void>\n}\n\n/** Default CredentialStore: encrypted, IndexedDB-backed (see IndexedDBVault). */\nexport class VaultCredentialStore implements CredentialStore {\n private readonly vault: IndexedDBVault\n\n constructor(opts: VaultOptions = {}) {\n this.vault = new IndexedDBVault(opts)\n }\n\n getApiKey(ref: string): Promise<string | undefined> {\n return this.vault.getSecret(ref)\n }\n setApiKey(ref: string, key: string): Promise<void> {\n return this.vault.setSecret(ref, key)\n }\n deleteApiKey(ref: string): Promise<void> {\n return this.vault.deleteSecret(ref)\n }\n}\n\n/** Non-persistent CredentialStore for tests / SSR / ephemeral sessions. */\nexport class MemoryCredentialStore implements CredentialStore {\n private readonly map = new Map<string, string>()\n\n constructor(initial?: Record<string, string>) {\n if (initial) for (const [k, v] of Object.entries(initial)) this.map.set(k, v)\n }\n\n async getApiKey(ref: string): Promise<string | undefined> {\n return this.map.get(ref)\n }\n async setApiKey(ref: string, key: string): Promise<void> {\n this.map.set(ref, key)\n }\n async deleteApiKey(ref: string): Promise<void> {\n this.map.delete(ref)\n }\n}\n","import { tool, type Tool } from 'ai'\nimport type { AgentTool } from './types.js'\n\n/**\n * Define a host tool. Thin wrapper over the AI SDK `tool()`: pass a\n * `description`, an `inputSchema` (a Zod schema or the result of `jsonSchema()`),\n * and an `execute` function. The returned tool works unchanged on the native\n * tool-calling path.\n *\n * Generic over INPUT/OUTPUT so the schema's inferred type flows into\n * `execute(input)` — `Parameters<typeof tool>[0]` must NOT be used here: with\n * an overloaded `tool()` it resolves to the last overload (`Tool<never, never>`),\n * which rejects every real schema and types `execute` as `undefined`.\n *\n * Optionally add `promptHint` — a short parameter hint like\n * \"{ text: string, x?: number }\" — which the prompted/salvage path shows to\n * weak local models that can't do native function-calling.\n *\n * @example\n * const tools = {\n * add_text: defineTool({\n * description: 'Add a text block to the page.',\n * inputSchema: z.object({ text: z.string(), x: z.number().optional() }),\n * promptHint: '{ text: string, x?: number }',\n * execute: async ({ text, x }) => addTextBlock(text, x),\n * }),\n * }\n */\nexport const defineTool = <INPUT = unknown, OUTPUT = unknown>(\n config: Tool<INPUT, OUTPUT> & { promptHint?: string },\n): AgentTool => {\n const { promptHint, ...rest } = config\n const t = tool(rest as Tool<INPUT, OUTPUT>) as AgentTool\n if (promptHint) t.promptHint = promptHint\n return t\n}\n","export interface StoredMessage {\n role: 'system' | 'user' | 'assistant'\n content: string\n ts?: number\n}\n\n/** Persists an agent session's transcript. Swap in any backend. */\nexport interface ContextStore {\n load(sessionId: string): Promise<StoredMessage[]>\n append(sessionId: string, message: StoredMessage): Promise<void>\n replace(sessionId: string, messages: StoredMessage[]): Promise<void>\n clear(sessionId: string): Promise<void>\n}\n\n/** Non-persistent fallback (tests, SSR, private mode). */\nexport class MemoryStore implements ContextStore {\n private readonly data = new Map<string, StoredMessage[]>()\n\n async load(sessionId: string): Promise<StoredMessage[]> {\n return (this.data.get(sessionId) ?? []).slice()\n }\n async append(sessionId: string, message: StoredMessage): Promise<void> {\n const arr = this.data.get(sessionId) ?? []\n arr.push(message)\n this.data.set(sessionId, arr)\n }\n async replace(sessionId: string, messages: StoredMessage[]): Promise<void> {\n this.data.set(sessionId, messages.slice())\n }\n async clear(sessionId: string): Promise<void> {\n this.data.delete(sessionId)\n }\n}\n","import { openAgentWebDB, SESSIONS_STORE } from '../storage/db.js'\nimport type { ContextStore, StoredMessage } from './store.js'\n\nexport interface IndexedDBStoreOptions {\n /** Database name, forwarded to the shared IDB owner (default 'agent-web'). */\n dbName?: string\n}\n\n/**\n * IndexedDB-backed transcript store — one record (message array) per session,\n * in the shared `sessions` object store (see storage/db.ts). Also exposes\n * session utilities: list and delete.\n */\nexport class IndexedDBStore implements ContextStore {\n private readonly dbName?: string\n\n constructor(opts: IndexedDBStoreOptions = {}) {\n this.dbName = opts.dbName\n }\n\n async load(sessionId: string): Promise<StoredMessage[]> {\n const db = await openAgentWebDB({ dbName: this.dbName })\n const value = (await db.get(SESSIONS_STORE, sessionId)) as StoredMessage[] | undefined\n return Array.isArray(value) ? value : []\n }\n\n async replace(sessionId: string, messages: StoredMessage[]): Promise<void> {\n const db = await openAgentWebDB({ dbName: this.dbName })\n await db.put(SESSIONS_STORE, messages, sessionId)\n }\n\n async append(sessionId: string, message: StoredMessage): Promise<void> {\n const current = await this.load(sessionId)\n current.push(message)\n await this.replace(sessionId, current)\n }\n\n async clear(sessionId: string): Promise<void> {\n const db = await openAgentWebDB({ dbName: this.dbName })\n await db.delete(SESSIONS_STORE, sessionId)\n }\n\n /** List all stored session ids. */\n async listSessions(): Promise<string[]> {\n const db = await openAgentWebDB({ dbName: this.dbName })\n return (await db.getAllKeys(SESSIONS_STORE)).map(String)\n }\n}\n"],"mappings":"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","names":["createWebLLMModel","tool","generateText","streamText","streamText","generateText","result"]}