Releases: OpenLoaf/OpenLoaf
Release list
OpenLoaf Desktop v0.2.5-beta.72
Release v0.2.5-beta.72
OpenLoaf Desktop v0.2.5-beta.71
OpenLoaf Desktop 0.2.5-beta.71
Retries the macOS arm64 build that broke in beta.70 (Apple notarisation 403). The CI pipeline also gains real fail-fast across all build jobs, plus scaffolding for future Windows/Linux arm64 builds.
🚀 Improvements
- CI fail-fast across every platform. The publish-desktop workflow now stops the entire run on the first build failure: each matrix is
fail-fast: true, and each top-level build job ends with agh run cancelstep gated onif: failure(). Saves ~20 minutes of wasted runner time when one platform breaks. - Multi-arch build scripts staged.
apps/desktop/package.jsonnow definesdist:win:arm64[:ci]anddist:linux:arm64[:ci];artifactNamefor Linux / Windows now embeds${arch}. The CI matrix still ships x64 only — these scripts are the building blocks for adding ARM64 to the publish matrix when ready.
🐛 Fixes
- macOS arm64 dmg restored. beta.70's macOS arm64 job hit
Unexpected token 'E', "Error: HTT"... is not valid JSONfrom@electron/notarizebecause the Apple Developer Program License Agreement had to be re-accepted. After re-acceptance this release rebuilds and republishes the missing arm64 artefact, sodownload.json'smac-arm64link points at a real dmg again.
ℹ️ Notes
- No app-side behaviour change.
- After this release lands, double-check
https://openloaf-1329813561.cos.accelerate.myqcloud.com/download.jsonand confirmdesktop.downloads.mac-arm64.urlreturns 200.
OpenLoaf Desktop v0.2.5-beta.70
OpenLoaf Desktop 0.2.5-beta.70
Hotfix for the publish pipeline. Beta.69 installers + manifests reached COS / R2 fine, but the cleanup step at the end of
publish-finalizefailed against COS, which in turn skipped the GitHub Release. End users on download.json were unaffected; this release restores the GitHub Release path.
🐛 Fixes
publish-finalizecleanup compatible with Tencent COS. The sharedcleanupOldVersionshelper usedDeleteObjectsCommand(batch, up to 1000 keys per call) which works on R2 and native S3 but fails on COS withInvalidRequest: Missing required header for this request: Content-MD5. AWS SDK v3 dropped automatic Content-MD5 in favour ofx-amz-sdk-checksum-algorithm; COS does not yet honour the new header. Switched to single-objectDeleteObjectCommandcalls with a small concurrency window — works against R2 / COS / S3 alike, and the runtime cost is a few extra seconds per release.
ℹ️ Notes
- Beta.69 itself is functional via the website /
download.json/ direct COS / R2 URLs. Only the GitHub Release page for desktop@0.2.5-beta.69 is missing; this release brings back the GitHub Release pipeline. - No app-side behaviour change.
OpenLoaf Desktop v0.2.5-beta.68
OpenLoaf Desktop 0.2.5-beta.68
Adds a website-friendly
download-{channel}.jsonindex so the official site can render the latest download buttons by fetching a single JSON. No app-side behaviour change for end users.
🚀 Improvements
download-beta.json/download-stable.jsonpublished per release. Thepublish-finalizestep inpublish-update.mjsnow writes a flat JSON containing the latest desktop version, per-platform installer URLs (dmg / exe / AppImage), R2 + COS mirror links, the GitHub Release tag URL, and the bundled web / server versions. Available at:https://openloaf-1329813561.cos.accelerate.myqcloud.com/download-beta.jsonhttps://openloaf-update.hexems.com/download-beta.json…/download-stable.jsononce the next stable ships.
- The index is regenerated at every
--manifest-onlyfinalize, mirrored to both R2 and COS, and prefers COS in the defaulturlfield so mainland users hit the accelerate edge first.
ℹ️ Notes
- Schema is intentionally flat and includes raw
mirrors.{cos,r2,github}so a static site can dofetch('/download-beta.json').then(r => r.json())and bind URLs without bespoke parsing. sha256for the user-facing dmg/exe/AppImage is currentlynull— electron-updater verifies via the side.blockmap/ sha512 channel. If we need a sha256 for website integrity badges, capture it during the per-platform upload step.
OpenLoaf Desktop v0.2.5-beta.67
OpenLoaf Desktop 0.2.5-beta.67
Cuts the auto-update default endpoint over to Tencent COS so fresh installs in mainland China get noticeably faster downloads. Cloudflare R2 keeps mirroring every release for older clients and overseas users.
🚀 Improvements
- Default update endpoint switched to Tencent COS. New installs now resolve
https://openloaf-1329813561.cos.accelerate.myqcloud.comfor both the Electron auto-updater and the in-app web UI. CI continues to dual-publish to R2 and COS, so the existinghttps://openloaf-update.hexems.commirror stays current — clients pinned to it viaOPENLOAF_UPDATE_URLkeep working. @openloaf-saas/sdkbumped to ^0.3.9 across server, web andpackages/api. Picks up upstream chat / media-task fixes; no API changes on the OpenLoaf side.
🐛 Fixes
- Stray branch-snapshot query on first paint.
ChatCoreProvider/useChatBranchStatenow require a resolvedsessionIdbefore the branch snapshot tRPC query fires. Previously a request could sneak out before the session id was hydrated, hitting the server with an empty id and surfacing a noisy 400 in the network tab.
ℹ️ Notes
- Old installs (≤ 0.2.5-beta.65) still pull updates from R2 and will continue to receive every future release — the cutover is opt-in via reinstall, not forced.
- If you need to override the endpoint (corp proxy, staging, etc.), set
OPENLOAF_UPDATE_URLeither as an env var or inruntime.env. The override is honoured ahead of the new COS default.
OpenLoaf Desktop v0.2.5-beta.66
OpenLoaf Desktop 0.2.5-beta.66
Infrastructure release. Auto-update artifacts now mirror to Tencent COS in addition to Cloudflare R2 so users in mainland China get noticeably faster downloads. Existing installs keep pulling from R2 — nothing changes for them in this version.
🚀 Improvements
- R2 → R2 + Tencent COS dual-publish. Server, web and desktop release pipelines now upload every artifact and manifest to both Cloudflare R2 (海外) and Tencent COS (国内, via global accelerate endpoint). When TENCENT_* secrets are absent the COS leg is skipped silently, so external forks keep working unchanged.
apps/server/scripts/publish-update.mjsandapps/web/scripts/publish-update.mjsgaineduploadFileToAll/uploadJsonToAllwrappers and changelog dual-write, mirroring what desktop already had.- All three publish workflows (
publish-server.yml,publish-web.yml,publish-desktop.yml) now injectTENCENT_COS_*/TENCENT_SECRET_*secrets next to the R2 ones.
- COS env var names aligned with OpenSpeech. Renamed
COS_*toTENCENT_*inscripts/shared/publishUtils.mjsandscripts/sync-r2-to-cos.mjsso the Tencent credentials can be reused across repos. Local.env.prodfiles need the same rename — see Notes.
ℹ️ Notes
- No application code changes. The desktop binary is rebuilt only to pick up the new CI pipeline; this release is functionally identical to 0.2.5-beta.65.
- Default update endpoint is unchanged —
https://openloaf-update.hexems.com(R2) — so old clients keep auto-updating. Switching new clients to the COS endpoint will land in a follow-up release once COS has been verified to receive a full set of artifacts. - If you rely on
node scripts/sync-r2-to-cos.mjslocally, rename the sixCOS_*keys inapps/desktop/.env.prodtoTENCENT_*before running it again.
OpenLoaf Desktop v0.2.5-beta.65
OpenLoaf Desktop 0.2.5-beta.65
Hotfix for 0.2.5-beta.64 — WeChat / SaaS login was broken on every platform (macOS / Windows / Linux) because of a CJS/ESM interop oversight when loading
keytar. Upgrade strongly recommended.
🐛 Fixes
- WeChat / SaaS login restored. In 0.2.5-beta.64 the OAuth code exchange completed against the SaaS side but
POST /auth/exchangethen failed locally withkeytar.setPassword is not a function, leaving the desktop app unable to persist the SaaS refresh token. The bug was platform-independent — Keychain (macOS) / Credential Manager (Windows) / libsecret (Linux) were never reached because the JS layer threw first.- Root cause:
apps/server/src/modules/settings/openloafConfStore.tsdidawait import("keytar")against an ESM bundle.keytaris a CJS package, so the named exports landed under.defaultinstead of being hoisted to the namespace, andkeytar.setPasswordresolved toundefined. - Fix: take
m.default ?? mfrom the dynamic import so the same shape works in both CJS and ESM hosts. One-line change, no behaviour difference on the dev path.
- Root cause:
ℹ️ Notes
- No schema or API changes. Bundled server / web binaries are rebuilt to pick up the fix.
- Users who already exchanged a code on 0.2.5-beta.64 do not need to do anything special — log in again and the refresh token will be written to the OS keychain on first success.
OpenLoaf Desktop v0.2.5-beta.64
OpenLoaf Desktop 0.2.5-beta.64
Re-roll of 0.2.5-beta.63 — the previous tag failed CI because
keytar's.nodebinary tripped esbuild and was not bundled into the desktop package. Both are fixed below.
🔒 Security
- SaaS refresh token now lives in the OS keychain. In production builds the refresh token is persisted via
keytar(macOS Keychain / Windows Credential Manager / Linux libsecret) instead ofauth.json. Dev builds keep usingauth.dev.jsonfor cross-process script convenience. Native binding loads lazily so the dev path never toucheskeytar. - SaaS auth handshake carries client identity. Token exchange and refresh now send a
clientInfopayload (appId: openloaf-server,platform,appVersion) so the SaaS side can attribute and rate-limit per client.
🚀 Improvements
- Cross-provider JSON output stabilised.
auxiliaryInferno longer relies on AI SDKOutput.object(which encodes asresponse_format=json_schema). Dashscope requires thejsonkeyword in messages, DeepSeek doesn't acceptjson_schema, and Kimi silently ignores it — behaviour was inconsistent. Now we generate plain text with an inline schema hint, extract the JSON ourselves, and validate with zod for uniform results across every provider. - New
jsonExtractmodule. Schema-aware JSON parser used by the auxiliary pipeline; ships with focused unit tests plus a Dashscope repro and an end-to-end auxiliary web-fetch test.
🔧 Refactor
- Token store fully async.
applyTokenExchangeResult,setRefreshToken,getRefreshToken,clearAuthSession, and the auth route handlers are nowasyncto accommodate keychain I/O. No behaviour change for existing callers beyond awaiting these calls.
🐛 Build fixes (vs 0.2.5-beta.63)
keytaradded to the serveresbuildexternal list so the.nodenative binary is no longer pulled into the bundle.keytaradded to the desktopforge.config.tsNATIVE_DEP_ROOTSso the package and its native binding are copied into the packaged app'snode_modules.
📦 Dependencies
@openloaf-saas/sdk0.2.4 → 0.3.2 (server / web / packages/api / root).keytar ^7.9.0added (server) — declared in rootonlyBuiltDependenciesso the native binding is built during install.pnpm-lock.yamlrefreshed.
OpenLoaf Desktop v0.2.5-beta.62
OpenLoaf Desktop 0.2.5-beta.62
✨ New
- macOS native control: per-window screenshot & enumeration. New
list_windowsandcapture_windowops in the Swift helper let the model see every renderable window for a target app (not just the frontmost) and grab a pixel-accurate shot of any single window bywindowID.observenow returns awindows[]payload by default and exposesaxRichness/windowChildRolesso the model can reason about UI density before acting. - WeChat channel agent end-to-end.
qwen:OL-TX-008(SaaS Fast Chat Model) is wired up as the channel-agent default for sub-3s ack-first SLO; new harness + identity + approval prompts ship per-language;SendWeChatMediatool added for outbound image / video / file bubbles.MacosObserve/MacosActare now reachable from the WeChat channel so users can remote-drive their Mac via IM. - macOS intent layer. New
macosIntentRegistry+macosIntentRouterresolve high-level user intents (MacosAct type="intent") into concrete strategies, plus a newMacosSurveytool for the "understand first" step before acting. - Notion MCP integration → deferred-load bundle. Notion is now advertised as a single
notion-mcpbundle in the preface; the model pulls the full toolset viaToolSearchon demand. Probe switched fromnotion-get-self(not always available) tonotion-get-users { user_id: "self" }. New integration-identity module persists workspace identity per-account. - MCP mock infrastructure. New
mcpMockStore+mcpMockRoutesplusmcpBundleregistry support deterministic browser tests and dev-time exploration without hitting real MCP servers.
🚀 Improvements
- Late-registered MCP tools become visible mid-session.
agentFactorynow merges live MCP tool IDs intoactiveToolson every step, so a tool that lands in the registry after aToolSearchbundle call (e.g. Notion connecting on demand) is immediately callable instead of being filtered out for the rest of the session. macosControlTools.tsdecomposed. Split intomacosCommon(i18n + perm plumbing),macosIntentRegistry,macosIntentRouter,macosSurveyTool,macosChromeGuardfor clearer ownership and easier extension.- Channel agent prompt restructured. Shared
harness.{en,zh}.mdextracted;identity/approvalrewritten; new tool-description overrides keep IM tone consistent across providers. - Cloud model mapper + provider adapters tightened.
cloudModelMapper,providerAdapters,qwenAdapter,resolveChatModelupdated for the Fast model class;modelRegistrycleanup. ToolSearchsmarter. Bundle resolution + ranking improvements (~156 line diff) so MCP bundles surface before generic tools.- WeChat AI bridge hardened (~900 line diff): improved debounce, abort-on-new, cold-start batching, ack-first behaviour.
💄 UI
ConnectionAccountRowextracted as a reusable status row used by the WeChat connection dialog.- Provider / Agent settings panels polished — clearer dialog sizing, model checkbox UX, agent detail layout.
🌐 i18n
- en-US / zh-CN / zh-TW / ja-JP synced for
ai,connections,project,settingsnamespaces.
🐛 Fixes
Chat.tsxno longer threads the obsoletecanAttachAllprop.- Removed stale
requiredModelTagstest; agent templatetypes.tscleanup.
🔧 Refactor
tokenStore,authCallbackPage, integration OAuth routes/service consolidated for shared identity flows.auxiliaryInferenceService+auxiliaryMessageUtilssimplified.- Settings:
auxiliaryModelConfStore,openloafConfStore,settingConfigTypes,settingsServicealigned with new model class.
📦 Dependencies
pnpm-lock.yamlrefreshed.
OpenLoaf Desktop v0.2.5-beta.61
What's Changed
✨ New Features
- WeChat integration: New channel adapter that bridges WeChat conversations into OpenLoaf ChatSession. Includes per-account poll worker, send/mock services, AI bridge, QR binding UI, and unified session rendering.
- macOS control: New
MacosObserve/MacosActtools with native Screenshot.swift implementation. Tool descriptions and skill docs refreshed;clickis now preferred overax_actionfor standard clicks. - Context compression: Step-budget soft landing and truncated-output handling keep long multi-turn sessions coherent when they approach model limits.
🚀 Improvements
- Chat panel independence: The right-side AI chat panel no longer reacts to sidebar navigation. Chat state lives in a dedicated store keyed per scope (global / projectId), so switching sections keeps the stream alive and preserves panel widths and visibility as user preferences.
- PPTX viewer: Rewritten around canvas rendering with zoom controls, keyboard shortcuts, and better slide navigation / error handling.
- Tool registry: Project, docConvert, and macOS control tool descriptions sharpened so the model picks the right tool more reliably.
- Master prompt discipline: New regression test locks down harness behavior to avoid drift between prompt edits.
💄 UI
- Connections: Redesigned install dialog with clearer copy, icons, and per-integration setup flows.
- File viewers: Consistent lifecycle and save-as handling across Audio / Doc / Excel / Markdown / PDF / PPTX / Video viewers; FilePreviewDialog wires sessionId through props for stack viewers outside ChatSessionProvider.
- Layout: Sidebar, StackHeader, and LeftDock polish; navigation no longer forces
leftWidthPercentor right-chat collapse.
🌐 i18n
- Refreshed en / zh-CN / zh-TW / ja-JP strings for AI, connections, and common namespaces.
🗄️ Database
- Migration
20260423000000_drop_chat_session_wechat_peer_idaligns the ChatSession schema with the new WeChat channel model.
🐛 Fixes
- Browser test
019-context-compression-large-textnow readsmsg.partsinstead of the legacymsg.contentfield, unblockingpnpm check-types.