Status of the work. See design.md for the architecture, providers.md for the provider matrix, and security.md for the token vault.
- Model substrate — everything is an AI SDK
LanguageModel. Supply a model directly, or byProviderModelSpecresolved through the registry. - Provider registry —
openai · anthropic · google · openai-compatible · xai · deepseek · gateway(dynamic optional-peer imports) +web-llmlocal; per-stage overrides with a cross-provider key guard; Anthropic browser header injected;directBrowserOkhints. - Local models —
createWebLLMModel(WebGPU,@browser-ai/web-llm),isWebGPUAvailable; any custom model (incl. Chrome/Edge built-in AI) works by passing it directly. - Secure token vault — non-extractable AES-GCM key in IndexedDB;
secrets encrypted at rest;
CredentialStore(Vault + Memory). - Low-level primitives —
generate/stream/generateStructured/runToolLoop. - Tools —
defineTool(one AI SDKToolSetshape); native tool-calling and a prompted/salvage fallback for weak local models;selectToolMode. - Agent loop —
createAgent().run(): plan → execute → replan → synthesize, grounded, time-boxed,AbortSignal, typed events; graceful native→prompted degradation. - Memory —
ContextStore+MemoryStore+IndexedDBStore(session list/delete) +compressHistory; recent turns are read back into the planner prompt so follow-up goals can reference earlier ones. - Tool filtering —
availableToolswhitelist /excludedToolsblacklist;plan-narrowedselection honoured on both tool paths. - Streaming final answer — the synthesizer streams
final.text-delta(suppressed when the model drifts into JSON). - MCP — optional
./mcpsubpath: HTTP (StreamableHTTP) connector. - Packaging — tsup ESM + CJS + d.ts,
././mcpentries, optional peers, nonode:*in the core bundle. - Tests —
node --test: registry resolution, vault crypto round-trip (fake-indexeddb), parsers, prompts, tool-mode, prompted dispatch, and a full prompted end-to-end run viaMockLanguageModelV3.
- Eager model preload —
createWebLLMModelnow defaults topreload: true(1-token warm-up), so weights download during creation withinitProgressCallbackfiring, not silently on the first message;preloadWebLLMModel/unloadWebLLMModelhelpers exported (the latter frees GPU memory best-effort when switching models). - Leveled logger —
logLevel('silent'|'error'|'warn'|'info'|'debug', default 'warn') + console-likeloggersink in the config; phases log raw outputs (debug), plans/steps/tool calls (info), empty plans, no-tool steps, failed tools and salvage fallbacks (warn).createLoggerexported. - Empty-plan retry — when the planner returns no steps for a multi-word goal (small models sometimes reply "done!" with an empty plan and the run would claim success without acting), the runner retries once with an explicit nudge before treating the turn as conversational.
-
./reactsubpath — auseAgenthook (kept out of core to stay UI-agnostic). - Streaming structured plan — surface
plan.thought-delta/plan.step-addedfrom a streamedgenerateObject. - Model-load events — wire WebLLM download progress to
model.loadautomatically (today: passinitProgressCallbackviaproviderOptions). - AI SDK v7 — bump once
@browser-ai/web-llmsupports the v7 provider spec. - MCP niceties —
tools/list_changedrefresh; per-tool allow/deny filter. - Examples — a vanilla-JS demo and a React demo (cloud BYOK + local WebLLM).
- OPFS/Blob tool outputs — optional spill target for binary MCP results.
- Built-in UI (chat panel, components) — belongs in host apps.
- Domain-specific tools — hosts register their own via
defineTool. - stdio MCP, filesystem sandbox, run persistence/resume, OpenTelemetry — Node-only
concerns that live in the sibling package
@dudko.dev/agent. - Shipping shared/app-owned API keys to the client — use a proxy or the gateway (see security.md).