Merged
Conversation
Expo Router app with WebSocket bridge to AionUi desktop backend. Includes: - Connection screen with JWT auth - Conversation list with create/delete support - Chat screen with streaming responses and markdown rendering - File browser via REST API - Settings screen with connection management - i18n support (en-US, zh-CN) - Bridge service for WS request-response protocol - Message adapter ported from desktop chatLib
Wire file tap in the browser to navigate to a new preview screen that supports markdown, code, HTML, diff, and image files via the existing bridge WebSocket protocol. Includes size guard (>1 MB), unsupported type message, loading/error states with retry, and i18n for en/zh.
Set up Jest + jest-expo testing with 71 tests covering utils and services (uuid, messageAdapter, api, websocket, bridge). Add EAS Build profiles for development/preview/production and integrate expo-dev-client.
- Add versions/version.json for centralized version tracking - Add scripts/build.js with auto buildNumber bump and rollback on failure - Configure eas.json with local version source, real device support, and Apple credentials - Wire up build/prebuild/device scripts in package.json - Add .easignore to reduce cloud build upload size - Add placeholder app icon (1024x1024) - Update app.config.ts with dynamic version, EAS project ID, and iOS compliance flags
Add index.tsx as the root route gateway that redirects based on connection state. Refactor _layout.tsx to declare all routes statically instead of conditionally rendering Stack.Screen (which breaks production builds). Add isRestoring state to ConnectionContext to keep splash screen visible during SecureStore restoration. Add auth guard in tabs layout to redirect back when disconnected.
Use expo-camera to scan QR codes from AionUi desktop for one-tap server authentication, replacing the manual host/port/token form.
The mobile BridgeService was sending raw event names but the server
expects the @office-ai/platform subscribe protocol (subscribe-{key}
with unique request IDs). This caused all requests to silently fail
and time out, leaving the app stuck in loading state.
- Update request() to send subscribe-{name} and listen for
subscribe.callback-{name}{id} responses
- Update emit() to wrap fire-and-forget calls in subscribe protocol
- Add proper loading state tracking in NewConversationModal
- Apply formatting fixes across mobile components
Replace the conversations list tab + push navigation with a drawer sidebar for quick session switching. Fix all hardcoded light-mode colors across chat components (MarkdownContent, ToolCallBlock, ConfirmationCard, MessageBubble, ChatInputBar, ChatScreen, ThemedText) by using dynamic theme tokens.
…r and files tab Associate Files with Chat sessions through a shared WorkspaceContext so switching sessions automatically shows the relevant project files. Chat sidebar now groups conversations by workspace and timeline (pinned, today, yesterday, etc.). Files tab is rebuilt as a drawer-based layout with multi-file tabs, tree sidebar, and inline file preview. New contexts: WorkspaceContext (derives workspace from active session), FilesTabContext (multi-tab state with AsyncStorage persistence). New utils: workspace, timeline, groupingHelpers (ported from desktop). New components: WorkspaceGroup, WorkspaceFilesSidebar, MobileFileTabHeader, FileContentView. Chat header shows workspace name with tap-to-navigate.
The WorkspaceFilesSidebar was using REST API (/api/directory/browse) for directory listing, which caused path mismatches with workspace paths stored in conversations. Switch to bridge protocol (conversation.get-workspace) to align with the desktop data flow. - Replace REST API with bridge.request for workspace tree fetching - Adapt data types from flat DirEntry to nested IDirOrFile - Simplify tree logic: full tree is pre-loaded, no lazy folder expansion - Add client-side sorting (dirs first, then alphabetical) - Fix unnecessary refetch on language change
Settings page, ToolCallBlock confirming status, and theme.ts updated to use semantic color tokens instead of hardcoded hex values.
…on and listing
- Map agentBackend to correct conversation type ('acp' for most agents)
instead of passing raw backend name, matching WebUI's useGuidSend behavior
- Fix 0-based pagination offset (page: 0) to avoid skipping all conversations
- Switch chat.send.message from emit to request for proper error handling
…ersation creation - Switch chat.stop.stream and confirmation.confirm from emit (fire-and-forget) to request (request-response) to match WebUI provider protocol - Add workspace and model fields to CreateConversationParams, auto-infer workspace from most recent conversation so new chats get file tree access
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
The fetchAgents call was treating the full bridge response as the agent array directly. Now correctly checks response.success and reads response.data, matching the IBridgeResponse protocol used by the backend.
The mobile/ directory is an independent Expo project with its own tsconfig. Root ESLint cannot parse its files, causing 55 errors in CI.
…itle Move workspace indicator from a right header button to a subtitle below the conversation title, reducing header overlap on small screens.
…reation until first message Instead of creating an empty conversation immediately when selecting an agent, introduce a pendingAgent state that waits for the user's first message. On send, the conversation is created atomically with the message as its name, matching the desktop behavior.
…gChatScreen Align PendingChatScreen with desktop Guid page by adding option pills for workspace selection, server-side file attachment, model switching, and session mode selection. Workspace and files are mutually exclusive. Mode/model pills conditionally render based on backend capabilities.
…& diff display - Add search bar to chat sidebar for filtering conversations by name/agent - Add rename option to conversation long-press menu (iOS Alert.prompt, Android inline input) - Add copy button to code blocks in markdown with expo-clipboard - Add web search display for codex_tool_call web_search_begin/end subtypes - Add diff display for codex_tool_call turn_diff subtype with expandable colored diff - Add i18n keys for all new features in en-US and zh-CN
…token refresh, dead connection detection - Support thought messages: transform, merge by msg_id, collapsible ThoughtBlock UI - Fix confirmation system: populate confirmation.add handler, add update/remove listeners, restore on reconnect, use confirmation.id for confirm requests - Handle acp_context_usage metadata in stream listener - Add files parameter to sendMessage for future file attachment support - Add client-side dead connection detection (50s ping timeout, 15s check interval) - Reconnect WebSocket when app returns to foreground - Add token refresh: decode JWT exp, schedule refresh 1hr before expiry - Auto-refresh conversation list on foreground, 30s polling, and chat finish events
… block Group consecutive tool call messages into a single ToolCallSummary that auto-expands during streaming and collapses to a one-line summary when complete. Also refactor thought messages to ephemeral state instead of injecting into the message list.
…tion banner, and data retention Add auth challenge callback to WebSocketService so ConnectionContext can attempt token refresh before falling back to auth_failed. Preserve conversation data during transient disconnects (only clear on explicit server change). Delay auth_failed redirect by 5s to allow auto-recovery. Add ConnectionBanner component showing connection status with tap-to-retry.
…request The server destructures `msg_id` but mobile was sending `id`, causing the value to be silently ignored. No functional bug (matching uses `callId`), but aligning the field name prevents future issues.
…settings reconnect - Wrap TabLayout in SafeAreaView with top edge and zero out top inset for child navigators to prevent double safe area padding - Add headerStatusBarHeight: 0 to chat Drawer for consistent header - Replace wrapping TouchableOpacity in ToolStepRow with dedicated StepRowHeader to prevent touch event bubbling from ToolCallBlock - Add reconnect button in Settings connection card when disconnected
Remove redundant paddingTop: 60 from sidebar drawers (parent SafeAreaView already handles safe area) and extract DrawerMenuButton so useNavigation() runs inside the drawer navigator context.
…echanism setTimeout-based token refresh fails when the app is backgrounded because the OS kills timers. Use WebSocket heartbeat (ping/pong) to check token expiry on every heartbeat and refresh proactively when < 1 hour remains. Also pre-check token expiry before connect to avoid useless reconnects.
kaizhou-lab
previously approved these changes
Mar 23, 2026
- Accept deletion of .eslintignore (main migrated to oxc toolchain) - Add mobile/ to .oxlintrc.json ignorePatterns to exclude standalone RN project
added 4 commits
March 23, 2026 21:08
- Create .prettierignore to exclude mobile/ from oxfmt checks - Auto-fix formatting in fix-sentry SKILL.md
Remove non-existent src/types from metro watchFolders and extraNodeModules. Add paste-link mode to connect screen for simulator debugging without camera.
b0fe394 to
2efcad9
Compare
ringringlin
approved these changes
Mar 24, 2026
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.
very basic RN