Skip to content

feat(miniapp): i18n framework + Daily Coding Snapshot built-in app#453

Merged
bobleer merged 1 commit intoGCWing:mainfrom
bobleer:feat/miniapp-i18n-framework-and-coding-selfie
Apr 18, 2026
Merged

feat(miniapp): i18n framework + Daily Coding Snapshot built-in app#453
bobleer merged 1 commit intoGCWing:mainfrom
bobleer:feat/miniapp-i18n-framework-and-coding-selfie

Conversation

@bobleer
Copy link
Copy Markdown
Collaborator

@bobleer bobleer commented Apr 18, 2026

Summary

  • MiniApp i18n framework: optional i18n block on MiniAppMeta for name / description / tags, plus runtime app.locale / app.onLocaleChange(fn) / app.t(table, fallback) exposed through the bridge. Host (useMiniAppBridge) answers bitfun/request-locale and pushes localeChange events when the UI language changes; new pickLocalizedString helper resolves strings with a current → en-US → zh-CN → top-level fallback chain and is wired into Gallery cards, search/filter, the detail modal and Scene tab titles.
  • Daily Coding Snapshot (4th built-in MiniApp): scans the active workspace's git repo via a Node worker and renders a single-screen 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 so it fully fills the tile regardless of aspect ratio.
  • Built-in app i18n + polish: all four built-ins (Gomoku, Daily Divination, Regex Playground, Daily Coding Snapshot) ship full zh-CN / en-US strings in meta.json and ui.js. Daily Divination's content datasets (cards / suits / colors / hours / mantras / insights) are kept parallel across locales so the daily-seeded random keeps its identity; "Today's Insight" label moved out of CSS ::before so it can be translated; fortune-matrix labels grow to max-content so longer English words (e.g. "Inspiration") no longer clip. Regex Playground's sample text is now a single English snippet so the scratchpad doesn't flip with the UI language.
  • Bot locale layer: shared bot/locale.rs powers Feishu / Telegram / Weixin adapters with a single locale-aware menu / command / reply surface.
  • Skill docs: SKILL.md and api-reference.md document the new meta.json i18n block, app.locale / app.onLocaleChange / app.t, the data-i18n convention, and a self-check list so AI-generated MiniApps default to multi-locale.

Built-in version markers bumped so existing installs reseed.

Test plan

  • `cargo check -p bitfun-core` clean
  • `tsc --noEmit` clean
  • Manually switch UI language in Gallery — card name / description / tags / scene tab title and search match all update
  • Open each built-in MiniApp and toggle language at runtime — static labels, dynamic lists, aria-labels, and titles all re-render
  • Open Daily Coding Snapshot on a real git workspace — heatmap fills the tile across various aspect ratios, today/yesterday delta and streak read correctly
  • Reopen Daily Divination after a language switch — same daily card / fortunes / lucky omens, just translated; persisted reading restores correctly
  • Regex Playground sample text stays English in both languages
  • IM bots (Feishu / Telegram / Weixin) menus and replies follow the configured locale

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.
@bobleer bobleer merged commit 48c49a7 into GCWing:main Apr 18, 2026
4 checks passed
@bobleer bobleer deleted the feat/miniapp-i18n-framework-and-coding-selfie branch April 18, 2026 15:00
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant