Changelog
The canonical changelog lives in the CLI package — cli/CHANGELOG.md — and is rendered below. Entries under Unreleased are shipping on the main branch and not yet tagged.
All notable changes to Glue CLI will be documented in this file.
[Unreleased]
Added
- Native
OllamaAdapter— Ollama now has a dedicatedProviderAdapter+OllamaClientthat talks to/api/chatdirectly instead of riding the OpenAI-compat adapter at/v1/chat/completions. Errors correctly attribute to Ollama (no more "OpenAI API error 404" on missing Ollama models), and Ollama-specific request options now have a home in the native client. options.num_ctxinjection —OllamaClientnow setsoptions.num_ctx = min(ModelDef.contextWindow, 131072)on every request when the catalog knows the model's context window. Fixes the silent agent-loop truncation when Ollama falls back to its 2048-token default. Clamped at 128K so catalog entries that claim 1M contexts don't OOM mid-range GPUs. Uncatalogued passthrough models (user-typed tags) omitoptionsand get Ollama's default.- Exact-match model resolver — new
lib/src/catalog/model_resolver.dartis the single source of truth for turning a user-typed identifier into aModelRef. Explicit<provider>/<id>inputs are never fuzzy-matched: catalogued refs return the catalog entry, uncatalogued refs pass through to the provider verbatim. Bare inputs require an exact match againstidor display name; ambiguous bare inputs return the candidate list and unknown bare inputs return a clear error. The previous substring fallback silently rewrotegemma4intogemma4:26b; it's gone. - Status bar +
/infoshow the wire address — the right-hand status segment now reads<provider> · <apiId>(what the provider actually receives), not the internal catalog key./infoexpands to<name> — <provider>/<apiId>for catalogued models and falls back to<provider>/<modelId>for uncatalogued passthrough. SurfacesapiIddrift (e.g. Groq'sgpt-oss-120bgoes out asopenai/gpt-oss-120b). - Ollama dynamic discovery —
lib/src/providers/ollama_discovery.dartmerges Ollama's/api/tagsinto the/modelpicker. Catalogued+pulled entries render normally; catalogued but not-pulled show[pull]; tag-only locally-installed models show[local]and are synthesised into picker rows. 2 s timeout, 30 s in-memory cache. Fail-soft: picker falls back to the bundled catalog silently when the daemon is down. - "Pull this model?" confirmation flow — selecting a not-installed Ollama tag (via the
/modelpicker or by typingollama/<tag>directly) opens aConfirmModal. On Yes, Glue streamsPOST /api/pullprogress as system messages and only switches the active model after a{"status":"success"}frame. On No or on pull failure, the active model stays put. - Clean
ConfigErrorsurface at startup —bin/glue.dartnow catchesConfigErrorandModelRefParseException, writes a single-lineError: …to stderr, and exits with code 78 (EX_CONFIG) instead of dumping a Dart "Unhandled exception" stack trace.
Changed
- Ollama no longer masquerades as OpenAI-compat. The
ollamaprovider indocs/reference/models.yamlnow usesadapter: ollama(notadapter: openai + compatibility: ollama), andbase_urldrops the legacy/v1suffix. Catalog regenerated. /modelpicker picks the user's intent, not a substring match. See "Exact-match model resolver" under Added. Errors list candidates for ambiguous inputs instead of silently choosing one.
Fixed
- Docker executor test now skips when the daemon is down. The skip guard changed from
docker --version(CLI-only check) todocker info(requires the daemon), so the test stops failing on machines that have Docker installed but not running.
Removed
CompatibilityProfile.ollama— dead after the native adapter move.CompatibilityProfile.fromString('ollama')now falls through toopenai(kept for a forgiving parse; the native adapter handles the real wiring).
[0.1.1] — 2026-04-20
Added
- Build metadata injection —
just buildnow passesGLUE_BUILD_TIME,GLUE_GIT_SHA,GLUE_GIT_DIRTY, andGLUE_BUILT_BYtodart compilevia--defineflags.BuildInforeads them at startup;glue --versionprints a compact summary (e.g.glue v0.1.1 (a1b2c3d, 2026-04-20T…)),glue --version --debugprints a detailed block, and--debugemits a banner to stderr before the TUI launches. Dev builds (dart run) fall back to(dev).just releasenow builds after the tag commit so the binary carries a clean SHA. glue config init— non-interactive config initializer that writes an annotated v2config.yamltemplate to the resolved Glue home (~/.glue/config.yamlor$GLUE_HOME/config.yaml). Supports--forceoverwrite/reset behavior, and/config initnow delegates to the same real config writer instead of creating an empty./config.yaml.glue config pathandglue config validate— scriptable config utilities for printing the resolvedconfig.yamlpath and validating the active config/provider credential setup.glue doctor— read-only install/config diagnostic command that reports resolved paths, parse errors for config/preferences/credentials/catalog files, active config validation, malformed session files, orphaned temp files, and returns non-zero when errors are found. Output uses the Glue brand header (yellow●), bold section headings, and coloured severity glyphs (✓/·/!/✗). Informational findings (e.g., empty session directories missingconversation.jsonl) are hidden by default — pass--verbose/-vto surface them.- DuckDuckGo search provider — zero-config
duckduckgosearch backend that scrapes the HTML endpoint (html.duckduckgo.com/html/), decodes theuddgredirect parameter to surface clean result URLs, and requires no API key. Registered in the default search provider chain. Includes unit tests for the HTML parser and an opt-in live integration test (dart test --run-skipped -t integration test/integration/duckduckgo_search_integration_test.dart). - Hyperbrowser backend for
web_browser— newhyperbrowserbrowser backend provisions Hyperbrowser cloud sessions (POST /api/session), connects over the returnedwsEndpointCDP WebSocket URL, surfaces the live view URL in browser tool output, and stops the remote session on disposal (PUT /api/session/{id}/stop). Configured withweb.browser.backend: hyperbrowserplusHYPERBROWSER_API_KEYorweb.browser.hyperbrowser.api_key. Includes docs/config examples and an opt-in live smoke test:dart test --run-skipped -t hyperbrowser test/integration/hyperbrowser_e2e_test.dart. - Anchor Browser backend for
web_browser— newanchorbrowser backend provisions Anchor Browser cloud sessions, connects over the returned CDP WebSocket URL, includes the live view URL in browser tool output, and stops the remote session on disposal. Configured withweb.browser.backend: anchorplusANCHOR_API_KEYorweb.browser.anchor.api_key. Includes docs/config examples and an opt-in live smoke test:dart test --run-skipped -t anchor_browser test/integration/anchor_browser_e2e_test.dart. ModelDef.apiId— optional field indocs/reference/models.yamldecoupling the stable catalog key from the mutable upstream identifier. Defaults to the YAML key when omitted (zero churn for simple entries). Adapters sendmodel.apiIdon the wire; the YAML key stays as the URL-safe, user-facing identifier in configs, sessions, and the/modelpicker. Motivation: upstream renames (e.g. Groq dropping Qwen3-Coder) no longer invalidate user configs. Matches precedent from OpenRouter, LiteLLM, Continue.dev, MLflow, and Docker.- Ollama catalog registry integration test —
test/integration/ollama_catalog_registry_test.dartverifies every Ollama catalog tag resolves viaregistry.ollama.ai. Opt-in viadart test --run-skipped -t ollama_registry; skipped by default to stay hermetic. Catches future drift when model authors rename tags. glue --where— printsGLUE_HOMEand every resolved path (config.yaml,preferences.json,credentials.json,models.yaml,sessions/,logs/,cache/,skills/,plans/) with an exists / not-yet marker. Useful on a fresh install to see where Glue will read and write.$GLUE_HOMEenvironment variable — overrides the default~/.glueroot. Every on-disk path (sessions, logs, cache, credentials, config) moves with it. Documented indocs/reference/config-yaml.mdand the Installation / Configuration docs.- Installer script at
getglue.dev/install.sh— POSIXsh, detectslinux|macos|windows × x64|arm64, pulls the matching binary from the latest GitHub Release, verifies the.sha256, drops it in~/.local/bin(overridable via--diror$GLUE_INSTALL_DIR). Supports--version vX.Y.Zfor pinned installs. ToolCallPhase.cancelled— distinct fromdenied(never ran) anderror(ran but failed). Agent cancel now marks every in-flight tool — including ones awaiting approval — ascancelledinstead of overloadingerror.- TUI behavior contract —
docs/reference/tui-behavior.mdcodifies the alt-screen, scrollback, resize, tool-phase, spinner, focus-priority, wrapping, and glyph rules the TUI follows today. - CLI prompt arguments and print mode — pass prompts directly from the command line for non-interactive use:
glue "review my code"— positional prompt argumentglue -p "query"— print mode, streams response to stdout without TUIglue -p --json "query"— JSON output for scriptingglue -r <session-id>— resume a specific session by ID- Model aliases:
glue -m opusresolves toclaude-opus-4-6
- DevTools instrumentation — consolidated observability with
dart:developerintegration:DevToolsSinkbridges observability spans todeveloper.log()anddeveloper.postEvent()for Dart DevTools visibilityGlueDevutility: CPU profiler tags (tagRender,tagLlmStream,tagToolExec,tagAgentLoop), Timeline helpers, DevTools URL helper- TTFB (time to first byte) tracking in
ObservedLlmClient - Tool call name and response preview tracking in observability spans
- Session replay improvements — proper tool_call/tool_result grouping during session resume and fork:
- Assistant messages now include their associated tool calls
- Tool results are properly paired with their tool_use IDs
- Orphaned
tool_resultmessages are filtered from conversation history, preventing Anthropic API 400 errors
- Subagent output improvements — richer grouped output display:
_SubagentEntryclass with optional JSON pretty-printing for expandable tool result content_SubagentGroupshows current tool name during execution- Expanded view renders indented JSON for structured results
- Multimodal tool results — tools can now return images (e.g. browser screenshots) as native content blocks instead of base64 text. This reduces token usage from ~738K text tokens to ~1,600 vision tokens per screenshot.
ContentPartsealed class hierarchy (TextPart,ImagePart) for structured content in tool results.Tool.execute()returnsList<ContentPart>— single dispatch method for all content types (text and images).ForwardingToolbase class for decorators (Go embedding pattern) — newToolmethods auto-forward to all decorators.- Provider-native image formats: Anthropic inline
imageblocks intool_result, OpenAI/Ollama follow-up user messages withimage_url/imagesarrays. WebBrowserToolscreenshots now returnImagePartinstead of base64 text strings.
- Observability & debug system — pluggable telemetry with zero changes to business logic. Three wrapper layers instrument all activity without polluting core code:
LoggingHttpClient— wrapshttp.Client, logs every outbound HTTP request (method, URL, status, duration).ObservedLlmClient— wrapsLlmClient, tracks provider, model, message count, token usage, tool calls, and latency per generation.ObservedTool— wraps eachTool, tracks execution time, args, and output size.
/debugslash command — toggles verbose debug mode at runtime. Also available via--debug/-dCLI flag orGLUE_DEBUG=1env var.- File-based debug logging — daily-rotating log files at
~/.glue/logs/glue-debug-YYYY-MM-DD.logwith timestamped entries for HTTP calls, LLM generations, tool executions, and span lifecycle. Observabilityfacade — composite dispatcher that fans out to multiple sinks. Sinks are independently enabled/disabled. The facade provideslog(),startSpan(),flush(), andclose()methods.ObservabilityConfig— configuration model for debug and telemetry settings, parsed from config file and env vars following the existing resolution chain.- Terminology standardization — established canonical glossary (
docs/architecture/glossary.md). Two-level hierarchy: Project (registered directory) → Session (resumable agent conversation). Sessions are independent and carry their own model, worktree, branch, and conversation history. No intermediate "workspace" layer — matches the data model used by Claude Code, Codex CLI, and Cline. - Enhanced
SessionMeta(schema v2) — sessions now store rich metadata:project_path,worktree_path,branch,base_branch,repo_remote,head_sha,title,tags,pr_url,pr_status,token_count,cost,summary. All new fields are optional; schema v1 files are read with permissive defaults. AddedSessionMeta.fromJsonfactory for consistent deserialization andSessionStore.updateMeta()for mid-session metadata writes. Timestamps now consistently use UTC. - Model registry & picker — curated
ModelRegistrycatalog of 10 models across Anthropic, OpenAI, Mistral, and Ollama with capability, cost, and speed metadata./modelwith no args opens a selectable panel picker grouped by provider;/model <name>does fuzzy lookup by ID or display name. Only models with configured API keys are shown. GlueConfig.copyWith— immutable config update for provider/model switching.LlmClientFactory.createFromEntry— create an LLM client directly from aModelEntry.- Spinner animation in status bar during LLM streaming — braille dot pattern cycles at 80ms instead of static
●indicator. - Collapsible subagent output — subagent activity is now grouped by task into compact summary lines (e.g.
↳ [1/3] task… (5 steps…)) that update in-place. Click a group to expand/collapse its full step log. - Alt+Backspace deletes previous word (same as Ctrl+W).
- Alt+Left / Alt+Right word-level cursor navigation in input editor.
KeyEventandCharEventcarry analtflag for modifier-aware input handling.web_fetchtool — fetches a URL and returns clean markdown for the LLM. Three-stage pipeline: (1) tryAccept: text/markdownheader, (2) HTML fetch → Readability-style content extraction → HTML-to-markdown conversion, (3) optional Jina Reader API fallback. Configurable timeout, max bytes, and token budget. Auto-approved (read-only).web_searchtool — searches the web via configurable providers (Brave, Tavily, Firecrawl) with unified result model. Auto-detects provider from available API keys (priority: Brave → Tavily → Firecrawl) with automatic fallback on error. Supports explicit provider selection via parameter. Configured viaweb.search.*in config.yaml orBRAVE_API_KEY/TAVILY_API_KEY/FIRECRAWL_API_KEYenv vars.WebConfig— web tool configuration model withWebFetchConfigandWebSearchConfig, wired intoGlueConfigwith env var and config file resolution following existing patterns.- Hidden aliases for slash commands —
SlashCommandnow supportshiddenAliasesthat resolve on execution but are excluded from autocomplete and/help./qis now a hidden alias for/exit. - Multi-shell support — unified
CommandExecutorabstraction withHostExecutorthat respects the user's shell via$SHELL,GLUE_SHELL/GLUE_SHELL_MODEenv vars, orshell.*in config.yaml. Supports bash, zsh, fish, pwsh with correct flag mapping for interactive/login/non-interactive modes. - Docker sandbox —
DockerExecutorruns agent commands in ephemeraldocker run --rmcontainers with bind-mounted directories. Uses cidfile-based container termination with retry for race conditions.ExecutorFactoryhandles Docker availability detection with automatic host fallback. Configurable viadocker.*in config.yaml orGLUE_DOCKER_*env vars. - Session-scoped Docker mounts —
SessionStatepersists directory whitelist additions instate.jsonper session, merged with config mounts at executor creation. /modelscommand — lists available models from the current provider (Ollama/api/tags, OpenAI/v1/models, Anthropic/v1/models). Shows model name, size (Ollama), and marks current.- E2E integration tests — headless agent loop tests via
AgentRunnerwith real Ollama (qwen3:1.7b). Tagged@e2e, skipped by default, run withdart test --run-skipped -t e2e. Retry wrapper handles small-model non-determinism. - Tool call intent indicator — the UI now shows
▶ Tool: write_file (preparing…)as soon as the LLM begins generating a tool call, rather than waiting for the full arguments to stream. Tool calls progress through visible phases: preparing → running → done (or denied/error). Eliminates the "hanging spinner" feel during large tool argument generation. ToolCallStartLLM chunk — Anthropic and OpenAI clients now yield aToolCallStartchunk atcontent_block_start/ first tool delta, surfacing the tool name before arguments finish streaming.- Mistral LLM provider — fourth provider alongside Anthropic, OpenAI, and Ollama. Uses OpenAI-compatible API with Mistral-specific base URL. Configurable via
MISTRAL_API_KEYenv var ormistral.api_keyin config.yaml. - Agent Skills (
agentskills.iospec) — discover and activate reusable skill definitions from.glue/skills/(project-local),~/.glue/skills/(global), and extra paths via config/env. Skill parser validates YAML frontmatter.skilltool lists or activates skills./skillsslash command opens a two-paneSplitPanelModalbrowser. Configurable viaskills.pathsin config.yaml orGLUE_SKILLS_PATHSenv var. - Browser tool infrastructure —
BrowserManagerwith pluggableBrowserProviderabstraction for Chrome DevTools Protocol connections. Five provider implementations: local Chrome, Docker container, Browserbase (cloud), Browserless (cloud), and Steel (cloud).BrowserConfigwith auto-detection priority chain. - PDF text extraction —
web_fetchnow handles PDF URLs with a two-stage pipeline: (1) direct text extraction from PDF bytes, (2) OCR fallback via Mistral Pixtral or OpenAI GPT-4o vision models for scanned/image-heavy PDFs. - GitHub Actions CI/CD — six workflows: Dart checks (analyze, format, test), multi-OS matrix (Ubuntu/macOS/Windows), docs build validation, nightly e2e integration tests, release tag builds, and auto-labeling. Dependabot configured for Dart and GitHub Actions dependency updates.
Changed
- Web search and browser automation support are constructed lazily during startup.
ServiceLocator.create()now wires memoized lazy factories intoWebSearchToolandWebBrowserTool, soSearchRouter, browser provider selection, andBrowserManagerare only built on first valid tool use. - Model catalog refreshed against live provider availability (April 2026).
- Mistral default →
devstral-latest(agentic coding model). Addedmistral-medium-latest. Keptmistral-large-latest,mistral-small-latest. - Ollama default →
qwen3-coder:30b(community consensus, 256K context, dedicated tool-call parser). Recommended list:qwen3-coder:30b,qwen3.6:35b,gemma4:26b,devstral-small-2:24b,qwen2.5-coder:32b,qwen3:8b. Six popular non-agentic families (mistral:7b,gemma3:12b,codellama:13b,codegemma:7b,starcoder2:15b,deepseek-coder:33b) included asrecommended: falsewith notes explaining why they're not suitable for tool loops. - Groq default →
openai/gpt-oss-120b(reasoning + coding). Addedgpt-oss-20b,llama-3.1-8b-instant. Keptllama-3.3-70b-versatile. - Slash-bearing catalog keys slugified:
groq/openai/gpt-oss-120b→groq/gpt-oss-120b(upstreamopenai/gpt-oss-120bnow lives inapi_id). Same treatment for Groqgpt-oss-20band OpenRouter's three slash-keyed entries.
- Mistral default →
- Resize preserves scroll position.
UserResizeno longer snaps the transcript back to the tail; the render pipeline clamps any out-of-range offset after the viewport changes. Ctrl+Endjumps to the bottom and resumes follow-tail. PlainEndstays reserved for the line editor (cursor-to-end-of-line)./statusis now a hidden alias of/info. One command in help + autocomplete; muscle memory for/statuskeeps working.- Release workflow overhaul — five-way matrix (
linux-x64 / linux-arm64 / macos-x64 / macos-arm64 / windows-x64.exe), per-asset.sha256, aggregatedSHA256SUMS, smoke-test of every binary, prerelease auto-flag for tags containing-. - GH Action version audit.
actions/cache v4 → v5(Node 24); everything else already on current major. - Status bar reformatted: bold mode indicator on left, model/mode/ cwd as right-aligned segments with
│separators. GlueConfig.load()no longer acceptscliProviderparameter (provider inferred from model). Removed--providerflag (frees-pfor print mode).- Terminal parser now decodes CSI modifier parameters (
;3= Alt,;5= Ctrl) from extended arrow key sequences. - Terminal parser handles ESC + byte sequences for Alt+char and Alt+Backspace (macOS Terminal convention: ESC prefix = Alt modifier).
- Eager tool call emission —
AgentToolCallevents are emitted during LLM streaming (not after stream end), so auto-approved tools can start executing while the model may still be finishing the response. - Dart analyzer hardening — expanded
analysis_options.yamlwithalways_use_package_imports,strict-casts,strict-raw-types,avoid_dynamic_calls,prefer_const_constructors,unawaited_futures,discarded_futures, and other safety/style rules on top ofpackage:lints/recommended.yaml. Converted all relative imports topackage:glue/imports across 51 files. Applieddart fixauto-fixes for const correctness, unnecessary lambdas, and parentheses. - Default model strings removed from
GlueConfig—_defaultModel()now delegates toModelRegistry.defaultModelId(). - Subagent updates use a grouped data model (
_SubagentGroup) instead of individual conversation entries — reduces output noise during multi-agent orchestration.
Fixed
- Spinner no longer stuck after cancel.
_cancelAgentImplnow stops the spinner before flipping mode;_cancelBashImplmirrors the pattern defensively. - Tool phase no longer stuck on
awaiting approvalafter cancel — approval-modal-open cancels now transition tocancelledtoo. - Cancel no longer corrupts conversation — cancelling (Escape) while a tool was executing left the conversation with
tool_useblocks but no matchingtool_resultmessages, causing the next API call to fail with a 400 error.ensureToolResultsComplete()now injects synthetic[cancelled by user]results for any unmatched tool calls. - Unused
callIdparameter in_ConversationEntry.toolResult— was accepted but silently discarded; removed the dead parameter. /modelswitch now updates_config(provider + model) viacopyWith, fixing stale config bug where session metadata and subagent spawning read outdated values.- ANSI codes in split panel highlight — reverse-video selection highlight in
SplitPanelModalnow strips ANSI escape sequences before applying highlight. - Skill discovery trailing-slash safety — skill directory paths ending with
/no longer produce empty skill names. - Exit message styling — exit prompt now shows the yellow diamond brand mark with session ID.
- Sema scripting skill documentation examples corrected (8 runtime errors fixed in documented code).
Removed
codestral-latestfrom Mistral catalog — FIM-lineage model; enumerates tools but narrates instead of calling them in agent loops. Replaced bydevstral-latest.qwen/qwen3-coderfrom Groq catalog — Groq no longer serves this model; the entry would 404. Replaced byopenai/gpt-oss-120b.llama3.2:latestfrom Ollama catalog — general chat model, not coding/tool-focused.devstral:latestfrom Ollama catalog — replaced by the pinneddevstral-small-2:24b(known version, known SWE-bench scores).- Interaction modes (
code/architect/ask), plan-mode UI,GLUE_INTERACTION_MODEenv var. - OTEL / Langfuse / DevTools observability sinks —
~/.glue/logs/spans-YYYY-MM-DD.jsonlis the single local trace log now.
[0.1.0] — Initial development
Added
- TUI application shell with raw-mode terminal, layout zones (output/overlay/status/input), and 60fps render throttling.
- Readline-style line editor with history, Emacs keybindings (Ctrl+A/E/K/U/W), and cursor movement.
- AgentCore ReAct loop with streaming LLM ↔ tool execution, parallel tool calls, and token counting.
- LLM providers: Anthropic Messages API (SSE), OpenAI Chat Completions (SSE), Ollama (NDJSON) — each with per-provider tool schema encoding and message mapping.
- SSE stream decoder for chunked event parsing.
- LlmClientFactory for provider instantiation from config.
- GlueConfig resolution chain: CLI args → env vars → ~/.glue/config.yaml → defaults.
- Headless AgentRunner with configurable approval policies (allowlist, always-approve, always-deny).
- AgentManager for subagent orchestration with depth-limited recursive spawning.
spawn_subagentandspawn_parallel_subagentstools.- Built-in tools:
read_file,write_file,edit_file(multi-line find-and-replace),bash(with configurable timeout),grep,list_directory. - Slash command system with
/help,/model,/clear,/resume,/info, and tab-completing autocomplete overlay. @filereference expansion — type@to get fuzzy-matched file hints (recursive, with directory browsing), expanded inline on submit.- Inline confirmation modal for tool approval (hotkeys + arrow navigation).
- Full-screen panel modal with scrolling, barrier rendering, and dismiss.
- Session persistence —
~/.glue/sessions/with conversation logging, listing, and/resumecommand. - ConfigStore with mtime-based caching and atomic saves.
- DebugLogger for
~/.glue/debug.log. - Auto-loads
AGENTS.mdandCLAUDE.mdinto system prompt. - Bash mode —
!prefix for shell passthrough with background job lifecycle management (ShellJobManager). bashMaxLinesconfig setting and box-drawn bash output renderer.- Markdown table rendering with box-drawing characters.
- Animated mascot splash screen with liquid simulation.
- Mascot explodes into goo particles when clicked repeatedly.
- Status bar with mode indicator, model name, working directory, scroll position, and token count.
- Status bar padding accounts for ANSI escape sequence lengths.
- Scroll/resize events routed through event bus.
- Render throttling at ~60fps to reduce flicker during streaming.
Fixed
- Ollama tool results use tool name instead of call ID.
- OpenAI tool call arguments serialized as JSON instead of Dart
toString(). /modelcommand now actually switches the LLM client.- BashTool uses
Process.startwith proper kill on timeout. - ConfigStore uses mtime-based caching with atomic saves and
update()API. - AtFileHint caches directory listing to avoid blocking UI on every keystroke.
- Expanded
@filecontent stored in conversation entries for session logging. - Fire-and-forget
.then()replaced with proper async error handling.