feat(miniapp): host-side dispatch for node.enabled=false apps#454
Merged
bobleer merged 1 commit intoGCWing:mainfrom Apr 18, 2026
Merged
feat(miniapp): host-side dispatch for node.enabled=false apps#454bobleer merged 1 commit intoGCWing:mainfrom
bobleer merged 1 commit intoGCWing:mainfrom
Conversation
Adds an in-process Rust dispatcher so a MiniApp can use framework
primitives (`fs.*`, `shell.exec`, `os.info`, `net.fetch`) without
booting a Bun/Node worker. Apps that only need to shell out (e.g.
`builtin-coding-selfie` calling `git`) no longer fail with
"JS Worker pool not initialized" in bundled builds, and gain a
faster cold start.
Highlights:
- New `miniapp::host_dispatch` mirrors `worker_host.js` permission
policy (path canonicalization, shell allowlist, net domain
allowlist) and is invoked via the new `miniapp_host_call` Tauri
command.
- `useMiniAppBridge` now routes by `permissions.node.enabled`:
framework primitives + `storage.*` go to the host; only
`app.call('myCustomMethod')` requires a worker.
- `builtin-coding-selfie` migrated to `node.enabled: false` and runs
its git scan directly from `ui.js` via `app.shell.exec`.
- Bundled-build hardening: `worker_host.js` is now declared in
`tauri.conf.json` resources and resolved at runtime; runtime
detection scans common Bun/Node install locations so GUI launches
on macOS find the binary even with a minimal PATH.
- MiniApp skill docs (`SKILL.md`, `api-reference.md`) gain an
explicit "capability boundary" section so generated apps stop
assuming non-existent `app.bitfun.*` / `app.workspace.*` channels.
- Minor: `regex-playground` library list gets its own scroll so the
side column no longer overflows when the pattern list is long.
bobleer
added a commit
that referenced
this pull request
Apr 20, 2026
…466) * feat(agents): upgrade DeepResearch from sub-agent to super agent with parallel orchestration Promote DeepResearch from a SubAgent to a Mode-level agent, enabling it to dispatch multiple sub-agents in parallel via the Task tool. This prevents context explosion by isolating each research chapter in its own sub-agent context window and dramatically reduces total research time through concurrent execution. Changes: - Register DeepResearch as Mode (was SubAgent) in AgentRegistry - Add Task tool to DeepResearch's tool set for sub-agent orchestration - Rewrite prompt to three-phase parallel research workflow: Phase 0: self-directed orientation & planning Phase 1: parallel sub-agent dispatch (3-5 concurrent per batch) Phase 2: assembly & synthesis (written by the agent itself) - Add DeepResearch to ChatInput boost menu alongside Plan and Debug - Add i18n entries (en-US, zh-CN) for mode name and description - Update default model to "auto" (was "primary" as sub-agent) - Update frontend capability tags for Mode category * fix(im-bot): create new Claw session on IM pairing instead of resuming old one (#405) When a user pairs via WeChat/Telegram/Feishu QR code and sends a message without selecting a session, the bot previously resumed the most recent Claw session. This caused topic drift because the user cannot see the prior conversation context in the IM channel. Now a fresh Claw session is always created after successful pairing. Reconnections after BitFun restart are unaffected — they restore the persisted BotChatState (including current_session_id) directly via restore_chat_state, so no duplicate sessions are created on reconnect. Co-authored-by: bowen628 <bowen628@noreply.gitcode.com> * feat(agents): add Team Mode with built-in gstack skills and streamline builtin skills (#407) * feat(agents): add Team Mode with built-in gstack skills Integrate gstack (https://github.com/garrytan/gstack) as a new "Team" super agent mode that orchestrates a virtual engineering team through specialized roles: CEO, Eng Manager, Designer, Code Reviewer, QA Lead, Security Officer, Release Engineer, and more. - Add TeamMode agent with full tool access and team_mode.md system prompt - Embed 15 gstack skills as builtin_skills (gstack-office-hours, gstack-review, gstack-qa, gstack-ship, gstack-cso, etc.) - Skills are only enabled when Team mode is selected via mode filtering in default_profiles.rs with "team" group key in builtin.rs - Register Team mode in AgentRegistry with UI integration (ChatInput, i18n for en-US and zh-CN) * refactor(skills): remove 13 redundant superpowers builtin skills Remove skills that are now covered by native BitFun modes, the Task tool, or the new gstack Team Mode integration: - brainstorming (replaced by gstack office-hours) - dispatching-parallel-agents (native Task tool) - executing-plans (Agentic Mode + TodoWrite) - finishing-a-development-branch (gstack ship) - receiving-code-review (pure convention) - requesting-code-review (gstack review) - subagent-driven-development (Task tool + gstack autoplan) - systematic-debugging (Debug Mode + gstack investigate) - test-driven-development (pure methodology) - using-git-worktrees (Bash tool) - using-superpowers (meta-entry, not applicable to BitFun) - verification-before-completion (pure convention) - writing-plans (Plan Mode + gstack autoplan) Retain: agent-browser, find-skills, writing-skills, docx/pdf/pptx/xlsx. Update cross-references in writing-skills, suggestions.md, and tests. --------- Co-authored-by: bowen628 <bowen628@noreply.gitcode.com> * feat: update Computer-use ux * fix(agents): make Team Mode work correctly with proper prompt and session handling (#408) * feat: update Computer-use ux * fix(agents): make Team Mode work correctly with proper prompt and session handling The Team Mode agent was behaving identically to the default agentic mode due to several issues across the prompt and frontend layers: 1. team_mode.md used invalid placeholders ({CUSTOM_RULES}, {RECENTLY_VIEWED_FILES}) that PromptBuilder does not process, and was missing critical placeholders ({ENV_INFO}, {PROJECT_LAYOUT}, {RULES}, {MEMORIES}, {PROJECT_CONTEXT_FILES}) — so the agent had no project context, no user rules, and no environment info. 2. ChatInput passed `effectiveTargetSession?.mode || modeState.current` as the agent type, which caused a stale session.mode (often "agentic") to override the user's UI selection. Fixed to use modeState.current directly as the authoritative source. 3. useFlowChat.ts hardcoded agentType to 'agentic' when creating sessions, ignoring config.agentType. Fixed to pass through the requested mode. 4. MessageModule.ts did not sync session.mode when the caller provided a different agentType, causing subsequent turns to lose the mode. Added ONE_SHOT_AGENT_TYPES_FOR_SESSION guard and mode sync logic. 5. FlowChatStore VALID_AGENT_TYPES whitelist was missing 'Team' and 'DeepResearch', causing restored historical sessions to fall back to 'agentic'. * fix(web-ui): move AskUserQuestion submit button from header to footer Move the submit button and status indicator below the questions list so users naturally answer all questions before reaching the submit action. --------- Co-authored-by: bowen628 <bowen628@noreply.gitcode.com> * refactor(prompt): restructure agent request context injection - introduce `RequestContextPolicy` to control instruction, memory, rule, and layout sections per agent - split workspace instruction and auto-memory context builders into dedicated modules - inject request context reminders from the execution engine instead of prompt template placeholders - simplify agent prompt templates by removing duplicated project context, rules, and memory placeholders * init sc * feat(self-ctl): add bitfun self control in claw mode * feat(self-ctl): BitFun self-control in Claw mode (#412) * init sc * feat(self-ctl): add bitfun self control in claw mode --------- Co-authored-by: bowen628 <bowen628@noreply.gitcode.com> * Fix inconsistent font size and line-height in user messages Tie user message content to --flowchat-font-size-base CSS token and align line-height (1.65) with AI message FlowTextBlock for consistency. Add unit tests for font-preference token derivation helpers. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(flow-chat): add inline generative ui widgets * fix(agents): harden team mode and self-control followups (#417) * feat: update Computer-use ux * init sc * feat(self-ctl): add bitfun self control in claw mode * fix(agents): harden team mode and self-control followups Normalize passthrough self-control actions so frontend execution stays compatible with the Rust payload contract, and repair default model references when models are removed. Tighten the Team Mode workflow prompt and add regression coverage for the self-control bridge. --------- Co-authored-by: bowen628 <bowen628@noreply.gitcode.com> * refactor: migrate workspace runtime layout and path handling - introduce a dedicated workspace runtime service to centralize runtime layout initialization and verification - migrate legacy runtime data from the project-local `.bitfun` directory into the managed runtime root - unify local, remote, and runtime artifact path resolution in the desktop API layer - update workspace and file APIs to expose runtime-aware metadata and filesystem operations - align frontend and related core services with the new runtime directory structure * Fix generative UI architecture widgets * feat(agentic-os): add unified ControlHub, Playbook system, and CDP browser control Introduce the Agentic OS unified control architecture with three major components: 1. **ControlHub tool** — single entry point for all control operations, routing by domain (desktop, browser, app, terminal, system) to the appropriate backend. Reuses existing ComputerUse, SelfControl, and TerminalControl tools while adding new browser CDP and system-level capabilities. Cross-platform open_app support (macOS/Windows/Linux). 2. **Playbook tool** — predefined YAML-based operation playbooks for common tasks (browser screenshot, data extraction, form fill, desktop automation, model setup). Features template variable substitution with type preservation (numbers/booleans stay native), conditional step filtering (`X is Y`, `X is not Y`, `X is provided`), and output variable annotations. 3. **CDP browser control** — connect to and control the user's default browser (Chrome, Edge, etc.) via Chrome DevTools Protocol, preserving login sessions, cookies, and extensions. Includes: - CdpClient: WebSocket-based CDP command transport - BrowserLauncher: cross-platform browser detection and CDP-enabled launch - BrowserActions: high-level atomic actions (navigate, click, fill, snapshot, screenshot, evaluate JS, etc.) - Desktop API: Tauri commands for status/launch/create-launcher 4. **Frontend UI** — SessionConfig adds browser control section with CDP status display, connect button, and create-launcher button (macOS). All toast messages use i18n (en-US + zh-CN). Existing tools (ComputerUse, SelfControl, TerminalControl) are retained for backward compatibility while ControlHub provides the unified interface. * fix: resolve CI compilation errors on Windows target - Split BrowserKind::Arc from Unknown(name) pattern match to avoid E0408/E0381 on Windows and Linux cfg blocks - Add `let _ = script` in non-macOS applescript branch to suppress unused variable warning - Add cross-platform `shell` script_type for run_script action - Allow unused log::debug import (used only in macOS-gated code) * feat: support inline think parsing for Anthropic-compatible streams * refactor(stream): unify indexed tool-call accumulation across adapters - preserve provider tool-call indices in unified stream types and route interleaved tool deltas by index - move tool-call buffering/finalization into the shared accumulator and remove OpenAI-specific orphan/prelude filtering - update stream processor and response aggregators to consume accumulator outcomes for early detection and param streaming - ignore empty tool argument deltas and keep fallback handling for snapshot/tail-fill edge cases - add OpenAI stream regression fixtures for interleaved args, missing tool type, and trailing empty finish chunks - document that changes to stream processor or ai-adapters must run stream integration tests * feat(config): add global stream idle timeout setting - add global `ai.stream_idle_timeout_secs` config with `None` as no timeout - pass stream idle timeout via runtime stream options instead of per-model AI config - apply the timeout consistently across OpenAI, Responses, Anthropic, and Gemini stream handlers - add models settings UI entry above proxy for configuring the global stream timeout - update frontend config types, i18n copy, and targeted tests/checks * default to text-only extraction for web fetches of deepresearch agent * Improve generative widget theme integration * chore: bump version to 0.2.3 * feat(control-hub): UX hardening for IM flows + ObjC exception safety (#444) * feat(control-hub): update * feat(control-hub): UX hardening for IM flows + ObjC exception safety Two independent rounds of fixes on top of the unified ControlHub: 1. Smoother IM-message flow (WeChat / iMessage / Slack / Lark / ...) - New `desktop.paste` action: clipboard + cmd/ctrl+v + optional submit chord in one tool call. The only robust way to enter CJK / emoji / multi-line text (avoids every IME failure mode of the per-character `type_text` path). Internally clears the `requires_fresh_screenshot_before_enter` guard between paste and submit so the bundled `return` is not rejected. - New `im_send_message` builtin playbook: deterministic send recipe with an initial `escape` state-reset, mid-flow window screenshot verification of the chat header, and a final verification capture. Re-invoking it for each new recipient guarantees `cmd+f` always hits global contact search instead of stale in-chat find. - `claw_mode` prompt updated with a HARD RULE that strongly prefers the playbook for every IM send and forbids reusing `cmd+f` from an open chat when sending to a different contact. - `Bash` tool now hard-rejects `osascript keystroke` for non-ASCII payloads and soft-rejects it for known IM apps, pointing the model at `desktop.paste` / the playbook instead. Stops the classic "AAA..." garbage when AppleScript Keystroke meets CJK input. - Screenshot policy simplified to "focused window OR full display": all historical mouse-centered crop / quadrant-drill / implicit confirmation crop modes are removed at the entry point. `screenshot_window: true` (default) gives the model the full app window via macOS Accessibility; falls back to full display when AX is unavailable. 2. ObjC foreign-exception safety (fix `__rust_foreign_exception` `SIGABRT` crash on macOS) - Enable `objc2/exception` and add a `macos::catch_objc` helper that wraps a closure in an Objective-C `@try/@catch` and converts `NSException` into `BitFunError::tool("Objective-C exception: ...")` instead of letting it cross the FFI boundary and abort the process via Rust's foreign-exception path. - `run_on_main_for_enigo` now returns `BitFunResult<T>` and runs every TSM / HIToolbox / AppKit input job (key chords, type text, mouse events) under `catch_objc`. This is the highest-frequency FFI boundary in computer-use and was the most likely SIGABRT source. - AX `frontmost_window_bounds_global` (called on every screenshot for window-aware crop) is wrapped: failures now degrade to a full-display capture instead of crashing. - AX SoM enumeration (`enumerate_interactive_elements`) is wrapped: a misbehaving frontmost app degrades to an empty SoM list. - Vision OCR (`VNRecognizeTextRequest` in `screen_ocr`) is wrapped: malformed image / OOM during recognition surfaces as a normal `BitFunError` rather than aborting. After this change, any remaining ObjC exception path will surface as a tool result error containing the NSException name + reason instead of a silent process termination, which makes diagnostics tractable. Compile + clippy + tests pass; no new warnings introduced. * fix(desktop): use re-exported DisplayInfo for cross-platform build screenshots::DisplayInfo is private on linux/windows; switch to the already-imported screenshots::display_info::DisplayInfo to fix CI. --------- Co-authored-by: bowen628 <bowen628@noreply.gitcode.com> * feat(control-hub): expose BitFun self-introspection to the agent (#445) * fix max input box ux * update screenshot ability * feat(control-hub): expose BitFun self-introspection to the agent The `domain: "app"` surface previously had no way for the model to learn what BitFun itself ships with (mini-apps, scenes, settings tabs). When the user asked "what mini-apps are installed?" the agent fell back to `Bash ls` against the workspace and mistook user files for BitFun features. Backend (Rust): - ControlHub `handle_app` adds 4 pure-Rust, no-round-trip introspection actions: `list_miniapps`, `list_scenes`, `list_settings_tabs`, `app_self_describe`. - `execute_task` catalog gains `open_miniapp_gallery` and `open_miniapp` recipes. - SelfControl tool description / schema synced (new `open_miniapp` action and `miniAppId` field). - New `bitfun_self_provider` builds a markdown self-describe block injected into the system prompt at a new `{BITFUN_SELF}` placeholder so the model knows the catalog with zero tool calls. Rebuilt every prompt build (manager.list is in-memory; no cache to invalidate). Frontend (TS): - SelfControlService adds `open_miniapp` action + matching task branches; validates against `useMiniAppStore` and surfaces the installed catalog as hints when the id is unknown. Prompt: - claw_mode.md `domain: "app"` section rewritten: introspection FIRST, HARD RULE forbidding `Bash ls` against the workspace to answer questions about BitFun's own capabilities. Tests: - 5 new unit tests cover the new pure-Rust action paths (list_scenes, list_settings_tabs, list_miniapps gracefully reports unavailable without a manager, app_self_describe shape, list_tasks contains the new mini-app recipes). All pass. --------- Co-authored-by: bowen628 <bowen628@noreply.gitcode.com> * feat(ai): import local Codex / Gemini CLI accounts as models (#447) * feat(ai): support reusing local Codex/Gemini CLI credentials Introduce a `cli_credentials` module under core/infrastructure that discovers and resolves credentials from local Codex CLI (`~/.codex/auth.json`) and Gemini CLI (`~/.gemini/{.env,oauth_creds.json}`) sessions, with automatic OAuth token refresh. `AIModelConfig` now carries an `auth` discriminator (api_key | codex_cli | gemini_cli) and the AI client factory injects the resolved credential (api key / bearer / custom headers / overridden request URL) at runtime, so users can switch any model entry to a local CLI login without re-pasting an API key. The ai-adapters layer gains two dedicated request adapters: - `providers/openai/codex_chatgpt.rs` for the Codex CLI ChatGPT backend (`chatgpt.com/backend-api/codex`), centralising its quirks (mandatory `instructions`, `store: false`, no `max_output_tokens`, flat tool schema, `parallel_tool_calls`, encrypted reasoning include). - `providers/gemini/code_assist.rs` (new `ApiFormat::GeminiCodeAssist`) for the `cloudcode-pa.googleapis.com` endpoint used by Gemini CLI OAuth, which wraps the request body as `{ model, project, request }`. The Codex backend's model listing is fetched with the upstream client version so the full model catalogue is returned, and entries collapse to a single canonical slug to avoid duplicate-looking display names. New Tauri commands `discover_cli_credentials` / `refresh_cli_credential` expose the discovery + refresh actions to the desktop app. * feat(web-ui): import local CLI accounts from the model settings page Surface discovered Codex / Gemini CLI logins inside the AI model settings as a dedicated "Local CLI accounts" section that mirrors the visual style of the default-model rows (one `ConfigPageRow` per detected credential, no raw filesystem paths leaked to the user). Each row exposes "Refresh token" and "Use this account" actions; the import flow leaves model name / request URL blank so the user must explicitly pick a model fetched live from the corresponding CLI rather than inheriting any hard-coded default slug. The provider form now offers an `Authentication` selector (API key / Codex CLI account / Gemini CLI account) and the model discovery flow no longer requires an API key when running in CLI auth mode. Adds the matching i18n entries (en-US / zh-CN) and the typed AIApi bindings for the new `discover_cli_credentials` / `refresh_cli_credential` commands. * fix(component-library): show loading state in Select while options load When a `Select` is asked to render with `loading={true}` and an empty options list, the dropdown previously displayed the generic empty text ("No data" / "暂无可用模型..."), which read as a hard error during the brief window where the caller is still fetching options asynchronously (e.g. fetching a remote model catalogue). Render a spinner + the existing `select.loading` localised string in that case instead, so users see a clear "loading…" affordance until options arrive (or until loading flips back to false and the real empty-state message is shown). * feat(browser-control): improve Windows browser detection and tighten UX copy On Windows, probe a curated list of common install locations (Program Files, Program Files (x86), per-user LocalAppData) and fall back to the registry "App Paths" entry before defaulting to the bare executable name. This dramatically improves the chance of locating Chrome / Edge / Brave / Chromium / Arc on real installations instead of failing because of a hard-coded path. In the desktop session settings, fetch the runtime platform via `systemAPI.getSystemInfo()` and shorten the browser-control copy ("Browser control", "Connect", "Connection", etc.) so the section reads like a product surface rather than a debugging panel. * fix(web-ui): wrap resetRemoteModelDiscovery in useCallback to satisfy lint --------- Co-authored-by: bowen628 <bowen628@noreply.gitcode.com> * feat: builtin miniapps, IM bot UX overhaul, disabled-model safeguards Bundles three built-in MiniApps and reseeds them on launch when their schema version changes (gomoku, daily-divination, regex-playground), with user storage preserved across upgrades. Rebuilds the IM bot UX around a shared locale/menu model so Telegram, Feishu, and WeChat adapters render the same MenuView through their native primitives, and rewrites the command router on top of it. Adds disabled-model safeguards across the agentic stack: the AI client factory rejects disabled models with a clear error, and the session manager subscribes to config updates and auto-migrates active sessions back to "auto" when their bound model is disabled or removed (with a new SessionModelAutoMigrated event so the UI can refresh). FlowChat receives scroll-stability fixes in VirtualMessageList / useFlowChatFollowOutput, plus minor Tooltip and AgentAPI additions and locale updates. * fix(miniapp/builtin): honor HTML hidden attribute in builtin apps CSS rules like `.result-overlay { display: flex }` were overriding the UA's `[hidden] { display: none }`, which made initially-hidden panels (gomoku result overlay, divination intro card, regex empty state) show up immediately on first paint. Add a global `[hidden]` enforcement to each builtin's stylesheet and bump their schema version so existing installs reseed the fixed sources. * fix(miniapp/regex-playground): make match details usable Match details were stuck in a side column that competed with the pattern library and the spec ref, so when the library card was tall the matches body collapsed to its title and users could not see any hits. Move the matches card into the main column right under the test text, switch to a responsive grid with capped height + internal scroll, surface line/column locations, mark zero-width matches explicitly, and add prev/next navigation that syncs the active mark in the highlight overlay. Bump builtin schema version to reseed. * feat(miniapp/gomoku): default to PvE mode * feat(miniapp/builtin): align each app's visual identity with its function Each builtin had a strong concept on the hero element but generic SaaS chrome elsewhere, breaking immersion. Re-skin all three end to end so the chrome reinforces the function: - divination: arcane tarot — deep indigo + antique gold + serif display + gilded corner ornaments + starfield, all panels (fortune matrix, do/don't suits, lucky cells) carry the same ritual language - gomoku: traditional game-room — rosewood plank topbar, parchment side cards with serif + 4-character spacing, vermilion accents in place of generic blue, ink-on-paper result overlay with seal frame - regex-playground: IDE / terminal — Tokyo-Night-ish palette, monospace-first chrome, prompt symbols ($ /) on input rows, syntax-color accents (blue/green/orange/purple/pink) on flags, matches, library and ref cards Bump all three builtin schema versions so existing installs reseed. * feat(miniapp): i18n framework + Daily Coding Snapshot built-in app (#453) Adds first-class internationalization to the MiniApp framework so built-in and AI-generated MiniApps can ship multi-locale strings and react to host language switches at runtime, plus a fourth built-in MiniApp ("Daily Coding Snapshot") that scans the active workspace's git repo and renders a single-screen Bento dashboard. Also overhauls IM bot UX with a shared locale layer (Feishu / Telegram / Weixin). MiniApp i18n framework - Backend: add `MiniAppI18n` / `MiniAppLocaleStrings` and an optional `i18n` field on `MiniAppMeta` / `MiniApp`; serde keeps the field optional so legacy meta.json files load unchanged. Bridge script gains `app.locale`, `app.onLocaleChange(fn)` and `app.t(table, fallback)`; iframe proactively asks the host for the current locale on boot via `bitfun/request-locale`. - Host: `useMiniAppBridge` answers `bitfun/request-locale` and pushes `localeChange` events whenever the UI language changes. New `pickLocalizedString` / `pickLocalizedTags` helpers resolve the best-match string with a `current → en-US → zh-CN → top-level` fallback chain, used by Gallery cards, search/filter, the detail modal and Scene tab titles. - All four built-in apps adopt the convention: `meta.json` declares per-locale `name` / `description` / `tags`; `index.html` marks static text with `data-i18n` (and `data-i18n-attr` for attributes); `ui.js` keeps a local `I18N` table + `applyStaticI18n()` and re-renders on `onLocaleChange`. Daily Coding Snapshot (4th built-in) - New `coding-selfie` MiniApp with Bento dashboard: today commits / lines / files / languages, weekly language donut, 24h activity rhythm and an adaptive 52-week heatmap that picks 1..6 stacked 7-row bands to fully fill the tile regardless of aspect ratio. Backed by a `worker.js` that shells out to `git` against the active workspace. Built-in app polish & fixes - Daily Divination: rewrite content to be locale-keyed (cards / suits / colors / hours / mantras / insights kept parallel across locales so the daily-seeded random keeps its identity); persist `cardIdx` instead of translated names; move "Today's Insight" label out of CSS `::before` so it can be translated; let fortune-matrix labels grow to `max-content` so longer English words like "Inspiration" no longer clip. - Regex Playground: switch sample text to a single English snippet so the playground scratchpad doesn't flip when the UI language changes. - Gomoku: full string table + dynamic re-render of turn / history / result panels on locale change. Bot locale layer - Centralize bot UX strings in `bot/locale.rs`; Feishu / Telegram / Weixin adapters consume the same locale-aware menu / command / reply helpers. Skill docs - `SKILL.md` and `api-reference.md` document the new `meta.json` `i18n` block, `app.locale` / `app.onLocaleChange` / `app.t`, `data-i18n` conventions and a self-check list so AI-generated MiniApps default to multi-locale. Bumps all four built-in `version` markers so existing installs reseed. Co-authored-by: bowen628 <bowen628@noreply.gitcode.com> * feat(miniapp): host-side dispatch for `node.enabled = false` apps (#454) Adds an in-process Rust dispatcher so a MiniApp can use framework primitives (`fs.*`, `shell.exec`, `os.info`, `net.fetch`) without booting a Bun/Node worker. Apps that only need to shell out (e.g. `builtin-coding-selfie` calling `git`) no longer fail with "JS Worker pool not initialized" in bundled builds, and gain a faster cold start. Highlights: - New `miniapp::host_dispatch` mirrors `worker_host.js` permission policy (path canonicalization, shell allowlist, net domain allowlist) and is invoked via the new `miniapp_host_call` Tauri command. - `useMiniAppBridge` now routes by `permissions.node.enabled`: framework primitives + `storage.*` go to the host; only `app.call('myCustomMethod')` requires a worker. - `builtin-coding-selfie` migrated to `node.enabled: false` and runs its git scan directly from `ui.js` via `app.shell.exec`. - Bundled-build hardening: `worker_host.js` is now declared in `tauri.conf.json` resources and resolved at runtime; runtime detection scans common Bun/Node install locations so GUI launches on macOS find the binary even with a minimal PATH. - MiniApp skill docs (`SKILL.md`, `api-reference.md`) gain an explicit "capability boundary" section so generated apps stop assuming non-existent `app.bitfun.*` / `app.workspace.*` channels. - Minor: `regex-playground` library list gets its own scroll so the side column no longer overflows when the pattern list is long. * feat(controlhub): cross-platform hardening for Windows / Linux (#455) Audit-driven fixes so ControlHub behaves consistently across macOS, Windows and Linux. Highlights: System domain - system.open_url / open_file (Windows): switch from `cmd /C start "" <url>` to `rundll32 url.dll,FileProtocolHandler` so URLs containing `&`, `%`, `^` or long query strings are no longer truncated by cmd's metachar parsing. - system.open_app (Linux): replace the misuse of `xdg-open` (which is for files/URLs) with `gtk-launch` -> direct exec -> `xdg-open` fallback chain; result now exposes `via_command` for telemetry. - system.open_app: skip the ComputerUseHost probe on non-macOS where it is not implemented, saving a round-trip. - system.run_script: route `script_type=shell` on Windows to PowerShell with forced UTF-8 OutputEncoding, eliminating GBK / CP936 garbling of CJK and emoji output. Add explicit `bash`, `powershell`, `cmd` script types with structured `NOT_AVAILABLE` errors when the interpreter is missing. - system.get_os_info: include `script_types[]`, plus `display_server` and `desktop_environment` on Linux so the model can pick the right helper without an extra round-trip. - system.clipboard_get / clipboard_set: emit Linux-session-aware install hints (Wayland -> wl-clipboard, X11 -> xclip/xsel). - hostname(): prefer `COMPUTERNAME` / `HOSTNAME` env / `/etc/hostname` before spawning `hostname.exe`, avoiding non-UTF-8 byte streams on Windows running CJK code pages. Browser domain - browser.connect: new `user_data_dir` option. When the user's main browser is already running without CDP, the model can launch a parallel isolated instance instead of asking the user to quit. New `BrowserLauncher::launch_with_cdp_opts` API; `launch_with_cdp` preserved for backward compat. - browser.evaluate: bound returned value with `max_value_bytes` (default 16 KiB, clamp 1 KiB-256 KiB) and surface a `truncated` flag, preventing huge DOM dumps from exhausting model context. Meta domain - meta.capabilities: bumped `schema_version` to 1.1. New fields: `system.script_types`, `browser.default_browser`, `browser.cdp_supported`, `host.display_server`, `host.desktop_environment`. Tests - 7 new unit tests covering script_types / get_os_info / run_script variants / which_exists / shell stdout end-to-end. Total ControlHub tests: 23 -> 30. `cargo test -p bitfun-core --lib`: 267 passed. * fix(im-bot): wire correct agent type, drop noise, fix WeChat file delivery (#456) A grab bag of IM-bot polish driven by real WeChat / Feishu / Telegram sessions. All fixes share one theme: stop sending stuff the user can't act on, and make the things we DO send actually work end-to-end. Bug fixes - WeChat file attachments showed up but every download failed with "下载失败". Outbound `aes_key` was `base64(raw 16-byte key)`, but the official `@tencent-weixin/openclaw-weixin@2.x` reference plugin emits `base64(hex_string.as_utf8_bytes())` (32-byte ASCII form). WeChat client decodes the value, sees 32 hex chars, and hex-decodes back to the 16-byte AES key. Match the reference quirk so CDN decryption succeeds. Locked in by `media_aes_key_b64_matches_openclaw_hex_ascii_format`. - Assistant-mode replies silently dropped attachments because `notify_files_ready` only consulted `current_workspace`. Add `BotChatState::active_workspace_path()` (Pro workspace OR assistant workspace) and use it in all three platform adapters. Regression test in `bot/mod.rs`. - Forwarded turns hardcoded `agent_type = "agentic"`, so Claw assistant sessions (created by the pairing bootstrap) were silently re-routed to the Code agent on every user message. `handle_chat` now reads the session's real `agent_type` from `SessionManager` and falls back to "agentic" only when the session is not hot in memory. - Long agent replies were truncated at 4000 chars with a stray `... (truncated)` suffix. Drop the global cap; each adapter chunks according to its own platform limit (WeChat already had `chunk_text_for_weixin`; add `chunk_text_for_telegram` for Telegram's 4096-char `sendMessage` limit). - WeChat typing indicator persisted forever / showed for trivial menu taps. Switch the cancel signal from `tokio::sync::Notify` to an `AtomicBool` polled every 100ms so cancellation is deterministic, and only call `start_typing` when a message actually triggers an agentic turn (`forward_to_session.is_some()`). - WeChat `post_ilink` now parses application-level `ret`/`errcode` for `sendmessage`, `sendtyping`, and `getconfig` so silent server-side failures bubble up as real errors instead of being swallowed. - Cached WeChat `context_token` is now invalidated when `send_message` reports a token-related failure, so the next inbound message can refresh it instead of repeatedly retrying a known-bad token. - Feishu / Telegram adapters now skip empty `MenuView` results (the silent "forward only" reply from `handle_chat` would otherwise post a blank message). UX cleanups (concise mode by default) - Default `verbose_mode` to `false`; even in verbose mode only forward thinking summaries — never per-tool `[Bash] … => OK 627ms` lines. - Remove "正在处理你的消息…… 1 取消任务" interstitial: the scheduler already queues new messages, so the cancel button was pure noise (and on WeChat costs a `context_token` slot per send). - Stop sending "当前会话: <id>" and similar internal IDs to the user. - Assistant mode now shows the human-readable assistant name in "当前助理: …" instead of the workspace directory name (`workspace`). Pro mode still shows the workspace dir. - Drop the "正在为你发送 N 个文件……" intro on all three adapters; the file message itself already shows up in the chat. Tests / verification - `cargo check -p bitfun-core`, `cargo test -p bitfun-core --lib service::remote_connect` all green. - New unit tests cover: agent-type-aware forwarding, assistant-name rendering, relative pptx auto-push against the assistant workspace root, OpenClaw-compatible `aes_key` encoding, and the context-token-error heuristic. * feat(miniapp/divination): polish layout, draw animation, mystic backdrop (#458) * feat(miniapp/divination): polish layout, draw animation, mystic backdrop - Compact result layout so it fits in one viewport (smaller paddings, 4-up lucky cells, tightened typography); remove inner scrollbar. - Add a dramatic draw ceremony: golden burst + ring shockwave, full-screen veil flash, 3D card flip, sibling cards scatter outward. - Add an arcane sigil ring backdrop (dual rotating rune circles + central hexagram halo) sized to fit the viewport, sitting behind text and cards so nothing is clipped. - Bump builtin-daily-divination version (10 -> 13) to trigger reseed. - Fix MiniApp tab label not following UI locale: useSceneManager now picks the localized name via meta.i18n.locales[currentLanguage]. * fix(useSceneManager): drop duplicate i18n imports * polish: miniapp visuals, chat input UX, agent companion defaults (#463) - MiniApp: refresh divination/gomoku/coding-selfie/regex-playground visuals (layout, animations, mystic backdrop, denser controls) and align built-in asset packaging in `miniapp/builtin/mod.rs`. - MiniApp dev skill: add `design-playbook.md` and update `SKILL.md` with the generation/design workflow guidance. - Browser launcher: minor robustness tweaks in `browser_launcher.rs`. - Web UI: restyle ChatInput, ChatInputPixelPet, ShellNav, NavPanel workspace item, AssistantQuickInput, InsightsScene, FlowTextBlock and tool cards (Compact/Default/ModelThinking) for a calmer, more consistent look. - Flow chat: simplify image paste flow (`useMessageSender`, `imageUtils`), drop noisy image-add toasts in locales, add `removeImage` label, and refine `UserMessageItem`. - Font preference: keep `lift` mode at the UI baseline instead of +1, so flow-chat text matches surrounding UI density. - Defaults: enable `enable_agent_companion` by default (Rust + TS) and update session-config copy to "Show BitFun companion". * feat: self-control hardening, coding-selfie range selector, export logo fix, model defaults bump (#464) * feat(self-control): per-action alias table, scoped search, offscreen enumeration, enable/disable/toggle model tasks - Replace the previous global alias table with a per-action one to stop cross-action field bleed (e.g. `text` no longer silently drops on `input`, `deltaY` no longer silently overrides `direction` on scroll). - Add `scope` ('auto' | 'main' | 'document' | <css>) to `click_by_text` and `get_page_state` so callers can avoid the global nav/scene-tab bar as a false-positive source. Default 'auto' tries <main> first then widens. - Add `includeOffscreen` to `get_page_state` (auto-on for the settings scene) so the model list / MCP list rows below the fold are visible. - Emit a stable `selector` on every SimplifiedElement so the model can paste it straight into action="click". - New ControlHub + execute_task tasks: `enable_model`, `disable_model`, `toggle_model` — pure config writes that work from any scene without losing chat context. `disable_model` rolls the primary/fast default forward when the active model is disabled. - INVALID_PARAMS / NOT_FOUND / AMBIGUOUS error hints now surface per-candidate concrete selectors so retries are deterministic. * feat(miniapp/coding-selfie): rename to 编码足迹, add 1d/7d/30d/custom range selector Was a "today only" dashboard; now a footprint over an arbitrary range. - Hero gains a chip group (近 1 天 / 近 7 天 / 近 30 天 / 自定义) and a date-range custom mode. - All stat tiles, the donut, the 24h rhythm hint and the commits list re-render against the selected range. - Rename: 每日编码快照 → 编码足迹 / Daily Coding Snapshot → Coding Footprint (meta + i18n + version bumped to 2). Builtin record bumped to v21 to force the host to re-seed. * fix(flow-chat/export): composite logo via canvas overlay so it always renders html-to-image is unreliable when an <img>/data URL is embedded inside an SVG foreignObject — the logo intermittently disappeared from exported images. Reserve space with a transparent placeholder, capture the page without the logo, then draw the preloaded logo onto the resulting canvas using the placeholder's measured rect (and border-radius clip). PNG path is now primary with toBlob as fallback. * chore(ai-defaults): raise default max_tokens to 32000 and context_window to 200000 8192 was a 2023-era default and routinely truncates modern model responses (Claude/Kimi/GPT-5 etc. all support 32k+ output). 128k context window is similarly stale — current frontier models default to 200k. Touches the Anthropic adapter fallback and every UI default in the AI model config form. * feat: remote SSH resilience, session-path correctness, and explorer/miniapp polish (#465) Remote SSH transport - Add per-connection liveness flag flipped by SSHHandler::disconnected, so is_connected/get_sftp/exec see torn-down sessions immediately instead of waiting for the next failed I/O. - Widen inactivity timeout to 180s and keepalive_max to 6 to tolerate brief network blips (NAT timeouts, Wi-Fi roaming). - Transparently reconnect on the next SFTP/exec call using the saved config and the encrypted password vault, serialized by a per-connection mutex to prevent reconnect stampedes. - sftp_read_dir retries once after invalidating the cached SFTP session and forcing a reconnect, so a stale channel left over from a network blip no longer permanently breaks the remote folder picker. - RemoteFileBrowser does a one-shot client-side retry plus an inline retry button on the error banner. Session storage path correctness for remote workspaces - PersistenceManager treats already-resolved mirror paths under ~/.bitfun/remote_ssh/{host}/{path}/sessions as the sessions root directly, preventing them from being re-slugified into ~/.bitfun/projects/<slug>/. - ConversationCoordinator pre-resolves the on-disk session storage path on the main task and passes it to the safety-net writer, so recovered turns no longer fall back to a slugified raw remote POSIX path. - AppState runs a one-time, idempotent migration on startup that scans ~/.bitfun/projects/*/sessions/ for sessions whose metadata records a non-localhost workspaceHostname and relocates them to the canonical ~/.bitfun/remote_ssh/{host}/{path}/sessions/ mirror dir. File explorer UX - Add ExplorerController.expandFolderEnsure / useFileSystem.expandFolderEnsure that awaits lazy resolution before resolving, so navigation can chain expansions deterministically. - FilesPanel "navigate to path" now awaits each expansion before scrolling the target into view, fixing the race where the highlight fired before deeply nested folders had loaded. - File search results route directory hits through onFolderNavigate, which switches back to tree view and reveals the folder in place instead of trying to open it as a file. Coding-selfie miniapp (built-in) - Bump version to 27. - Language legend now renders a per-language ranking bar normalized to the dominant slice (so the leading language reads as a full bar), with safe HTML/attr escaping for language names. - Heatmap aligns the data to a clean 52-week (2 × 26) grid by dropping the partial leading week, replaces native cell tooltips with a shared overlay that activates on hover, and clarifies the "not a Git repo / remote workspace" empty-state copy in both en-US and zh-CN. --------- Co-authored-by: bowen628 <bowen628@noreply.gitcode.com> Co-authored-by: CWing <302787376@qq.com> Co-authored-by: wsp1911 <mr.wanger2018@outlook.com> Co-authored-by: Zakir Jiwani <108548454+JiwaniZakir@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: wgqqqqq <wgq0617@gmail.com> Co-authored-by: ylyl10 <ylyl10@noreply.gitcode.com> Co-authored-by: Guanqi <51046187+wgqqqqq@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
miniapp::host_dispatch) that mirrorsworker_host.jspermission policy and exposes the framework primitivesfs.*/shell.exec/os.info/net.fetchdirectly to MiniApps that declarepermissions.node.enabled = false. A new Tauri commandminiapp_host_callroutes calls into it.useMiniAppBridge) soworker.callis dispatched bypermissions.node.enabled: framework primitives +storage.*go through the host path;app.call('myCustomMethod')still requires a worker and now errors loudly when the app opted out of Node.builtin-coding-selfietonode.enabled: false. Its git scan moved fromworker.jsintoui.jsand runs throughapp.shell.exec, eliminating the "JS Worker pool not initialized" failure on bundled macOS builds.worker_host.jsis now declared intauri.conf.jsonbundle.resourcesand located at runtime byresolve_worker_host_path().runtime_detectscans common Bun/Node install locations and version managers so the GUI launcher finds the binary even with a minimal PATH.MiniApp/Skills/miniapp-dev/SKILL.mdandapi-reference.mdgain an explicit capability boundary section listing exactly whatwindow.app.*exposes and what BitFun internal services are deliberately NOT proxied, so generated MiniApps stop assuming anapp.bitfun.*/app.workspace.*channel exists.builtin-regex-playgroundlibrary list its own bounded scroll so the side column no longer overflows when the pattern list grows; bump its version for reseed.Test plan
cargo check -p bitfun-core -p bitfun-desktop— cleanpnpm -C src/web-ui lint— cleanbuiltin-coding-selfiein a packaged build → git scan completes without touching the JS worker poolbuiltin-regex-playgroundwith a long custom pattern list → only the library card scrolls, ref / replace cards stay visiblenode.enabled = trueMiniApps still call into the worker (no behavioral regression forfs/shell/net/os/storage)