github craft-ai-agents/craft-agents-oss v0.9.6

4 hours ago

v0.9.6 — Auto-update window restoration, mid-session credential refresh, and #807/#798/#804 fixes

Features

  • Workspace name in window title when multiple windows are open — With one window open the title stays as the app name ("Craft Agents"). Open a second window and each window's title becomes the workspace name it belongs to, so windows are trivial to tell apart in Cmd-Tab, Mission Control, and the Windows taskbar. The renderer's static <title> is suppressed so it can't clobber the main-process title. (5a49b6ca)

  • Inline markdown-preview block for rendering .md files — A new markdown-preview code-block type mirrors html-preview / pdf-preview / image-preview: reference a .md file by absolute path and the chat renders it through the shared Markdown component, with a disablePreviewBlocks guard that prevents markdown-preview-inside-markdown-preview recursion without disabling other nested preview blocks. Registered in both minimal (assistant chat) and full modes; supports multi-item items arrays. Partially addresses #807. (45760a6f)

Improvements

  • Online-docs coverage for multi-window titles and auto-update restorationapps/online-docs/go-further/workspaces.mdx now documents the new window-title behavior and the auto-update window-state preservation, so users discovering these features in-app can find rationale and edge-case notes in the docs. (755a8b77)

  • Online docs introduction polish — Tightened wording in the getting-started introduction (Mintlify dashboard edit). (3a5378db)

  • Messaging gateway docs reflect the 0.9.5 fallback fix — Clarifies that progress and final_only modes now both fall back to the most recent assistant text when a run ends on a tool call without a non-intermediate text_complete, instead of leaving a thinking bubble (progress) or staying silent (final_only). Genuinely empty runs are still silent. (0cfd1ffb)

Bug Fixes

  • Multi-window state survives auto-update — electron-updater (Squirrel.Mac) destroys all BrowserWindows between quitAndInstall and before-quit firing, so the existing window-state save ran with an empty snapshot and clobbered ~/.craft-agent/window-state.json with { windows: [] }. Users lost their multi-window setup every time they accepted an update. installUpdate now fires a setBeforeUpdateQuitHook callback that captures and saves window state while windows still exist, and the late before-quit path adds an empty-snapshot guard so the pre-update save can't be overwritten. (3db842e0)

  • API source credentials refresh mid-session — Sources with bearer/header/query/basic auth captured the credential as a static string at tool-creation time. After refreshing an expired token via source_credential_prompt, the in-process tool kept sending the stale value (401 until full session restart) even though source_test confirmed the new token worked. Non-OAuth API sources now route through a credential getter that reads the vault on every call, mirroring the existing OAuth / renew-endpoint path. OAuth and renew-endpoint sources are untouched — they already have refresh via TokenRefreshManager. (5b6a0588)

  • Stale source_apikey credential no longer leaks when flipping authType to 'none'SourceCredentialManager.getCredentialId() maps 'none', 'header', and 'query' to the same source_apikey slot. Flipping a source from a credential-bearing authType to 'none' left the stored credential addressable under that slot, where it could later override defaultHeaders on a rebuild — the bare credential value got sent as a Cookie header instead of the new defaultHeaders.Cookie value. saveSourceConfig now best-effort-deletes the source_apikey slot when the new config is an API source with authType:'none'. Cleanup never throws and never blocks the config write. (d0c70f23)

  • Blocked URL schemes now explain why + DOM hrefs are sanitized — When react-markdown's defaultUrlTransform stripped a file: / javascript: URL to empty, the anchor handler fell back to anchor text and new URL(text) rejected it as "Invalid URL" — a generic toast with no rationale. DANGEROUS_SCHEMES is now a Map<scheme, reason>, the reason flows through the OPEN_URL handlers in both server-core and the Electron GUI, and the error message now reads e.g. URL blocked (file:). file: URLs are blocked because shell.openExternal can launch local executables on Windows…. The DOM href attribute is also sanitized through defaultUrlTransform and set to undefined for dangerous schemes, closing the middle-click / cmd-click escape route through Electron's setWindowOpenHandler and will-navigate. Fixes #807 (URL handling part). (746ebb34)

  • cache_control 1h TTL ordering bug and over-broad "tool not supported" classifier — Two bugs surfaced together when extendedPromptCache was enabled on an Anthropic connection at session start. (1) upgradePromptCacheTtl walked system + messages + top-level cache_control but skipped body.tools. Anthropic processes blocks in order tools → system → messages and rejects requests where ttl='1h' appears after ttl='5m', so a stale 5m on any tool produced system.0.cache_control.ttl: a ttl='1h' cache_control block must not come after a ttl='5m' cache_control block. Tools are now walked first in both the upgrade and disabled-strip paths. (2) parseError misclassified the same 400 as "Model Does Not Support Tools" because the heuristic fired on the API's hint string mentioning tools. The overly broad pattern is dropped and a final invalid_request_error / 400 branch routes generic Anthropic 400s to invalid_request instead of unknown_error. (26e6e675)

  • Mobile WebUI send button stays visible when the model name is long — The compact bottom-bar layout had every left-side item as shrink-0 with no overflow guard on the outer row, so a long custom-endpoint model name on a 375 px viewport overflowed the row and pushed the send button off screen. CompactModelSelector's trigger is now shrinkable with a min-w-[64px] tap-target floor, and the compact bottom-bar children are wrapped in their own min-w-0 shrink overflow-hidden group so the model label truncates first and the send button stays anchored to the right. Fixes #798. (5e95e72e)

  • Headless server auto-retries source_activated like the Electron renderer did — The [<slug> activated] re-send moved into SessionManager.processEvent so headless deployments (WebUI, docker server) chain source activations the same way the Electron renderer did. The renderer's auto_retry effect is removed. A 2 s content-match dedup window keyed on a {content, deadlineMs, committed} slot on ManagedSession prevents a double-send during a mixed-version rollout (legacy renderer + new server) — first matching sendMessage (server timer OR legacy RPC) wins and claims the slot, subsequent matches within the window drop. Retry timer + pending slot are cancelled on both session-delete sites (main deleteSession path and the branch-creation rollback path). Fixes #804. Co-authored with Guillaume Gay. (5cb7b8c1)

  • PR 378 review hardening (markdown / Electron URL handling, source-activation auto-retry guards, deterministic stale-credential cleanup) — Follow-up commit addressing review findings on the URL-safety, auto-retry, and credential-cleanup PRs above; also removes a leaking source-test module mock that was hiding the credential-cleanup regression. (42b986e1)

Breaking Changes

  • None. All changes are backward-compatible.

Don't miss a new craft-agents-oss release

NewReleases is sending notifications on new releases.