feat(desktop): side conversation dock and /side#1
Closed
taekchef wants to merge 2575 commits into
Closed
Conversation
Extend the Chinese rename to the remaining 7 locales. Applies only to user-facing strings — i18n keys, storage fields, and system workDir stay untouched. Per-language term: - en-US: Workspace → Project (home-page button reads 'Chat in Project') - zh-TW: 工作空間/工作區 → 專案 - ja-JP: ワークスペース → プロジェクト - ko-KR: 워크스페이스/작업 공간 → 프로젝트 - ru-RU: Рабочая область → Проект - tr-TR: Çalışma Alanı → Proje - uk-UA: Робоча область → Проєкт Also drop stale references to the removed 'workspace migration' feature in export-dialog hints.
iOfficeAI#2891) Problem: opening /guid fired 13 GET /api/agents + 3 POST /api/agents/refresh because 17+ call sites bypassed SWR by calling `ipcBridge.acpConversation.getAvailableAgents.invoke()` directly, and useCustomAgentsLoader ran a refresh-on-mount effect that cascaded into mutate-driven refetches. Changes: - Add renderer/hooks/agent/useAgents.ts exposing useAgents()/getAgents()/ refreshAgents(), all reading/writing the DETECTED_AGENTS_SWR_KEY cache. - Migrate 11 components and 4 hooks (MCP, channels, settings, team) from direct .invoke() to the new entry points. Non-React callers use getAgents(). - Replace useCustomAgentsLoader's own fetch+mount-refresh with a subscription to the shared cache; refreshCustomAgents is now explicit-only. - Drop useMultiAgentDetection and the multiAgentModeEnabled i18n key — agent detection is handled by aionui-backend, the toast was redundant. - Add scripts/check-agents-invoke.js and a pre-commit hook that forbids direct getAvailableAgents.invoke outside the canonical entry points. - Remove an unused destructured prop in AcpChat.tsx that was breaking tsc. - Update windowBounds.test.ts to match the new 0.95 default height ratio. Expected: /guid issues 1 GET /api/agents and 0 POST /api/agents/refresh. Co-authored-by: zk <zk@users.noreply.local>
… appear in leader dropdown (iOfficeAI#2893) teamCapableKeys only collected id and backend from team-capable CLI agents, but Aion CLI has no backend field — only agent_type: "aionrs". This caused all preset assistants (preset_agent_type: "aionrs") to fail the capability check and be filtered out of the team leader selector. Co-authored-by: zhuqingyu <zhuqingyu@bituniverse.org>
New backend does not implement WeChat Work (WeCom) plugin yet. Mark the channel as coming_soon to disable the toggle and show a placeholder message, consistent with Slack and Discord.
…fficeAI#2894) ACP cron jobs store the literal string "acp" in `agent_type`; the actual vendor id (claude/gemini/codex/…) and display name live in `agent_config.backend` / `agent_config.name`. The existing helper passed `agent_type` straight to the logo map and agent lookup, so ACP tasks rendered as "acp" with no logo on the scheduled-tasks list and detail pages. Extract the resolver into `jobAgentMeta.ts` with a dedicated ACP branch, and share it between `ScheduledTasksPage` and `TaskDetailPage`. Non-ACP agents (aionrs, remote, nanobot, …) keep using `agent_type` directly, since aionrs reuses `agent_config.backend` for provider_id. Co-authored-by: zk <zk@users.noreply.local>
…go immediately (iOfficeAI#2895) - AssistantEditDrawer's Main Agent Select was writing the AgentMetadata row id (e.g. "2d23ff1c") into `preset_agent_type` because useDetectedAgents exposed `a.id` as the option value. Align the option id with the storage contract by using `a.backend || a.agent_type`, so selecting Claude Code persists "claude" — matching the slug every downstream consumer (config keys, agent resolution, logo lookup) expects. - GuidPage.handlePresetAgentTypeSwitch only revalidated the detected agents SWR cache, not `assistants.list`, so selectedAssistantRecord (and the derived effectiveAgentLogo) lagged a network roundtrip behind the click. Optimistically patch `assistants.list` before the PUT and revalidate after, so the hero logo updates on the same frame as the user action. Co-authored-by: zk <zk@users.noreply.local>
- replace hand-drawn vertical dots with MoreOne icon across team/conversation/project-folder rows - give more buttons a persistent bg-fill-3 with hover bg-fill-2 (vs row hover bg-fill-3) - lift menu buttons to text-t-secondary -> text-t-primary on hover; unify rd-4px size-20px shell - always show team create button; add tooltips for team create (+) and project-folder create (+) - widen project-folder trailing gap from 2px to 6px - rewrite project-folder row: fixed trailing slot (w-22px) + flex-1 header so the name truncates before the button area - increase conversation row right reserve to pr-16px so the name truncates before the hover menu - trim team row right reserve from pr-24px to pr-12px for a bit more room - en-US: 'New conversation in this project' -> 'New chat in this project'
… color - light mode: --text-primary and Arco --color-text-1 to #000000 - dark mode: --text-primary and Arco --color-text-1 to #ffffff - keep the override in sync across both themes/default-color-scheme.css and DisplaySettings/presets/default.css (the latter is injected at runtime) - add sider-section-title hook; dark mode sider/settings section titles pick a mid-gray (#9098a1) so they remain legible on #0e0e0e without being as bright as --text-secondary
…xt bleed - introduce .sider-action-btn hook on more/plus buttons across sider rows - light mode: --bg-2 default, --bg-1 on hover - dark mode: --bg-5 default, --bg-6 on hover (lean toward white) Arco's --color-fill-* tokens are semi-transparent in dark mode, which let the row text show through when the button sat on top of a hovered row.
…, default gemini→aionrs (iOfficeAI#2897) * fix(migration): tolerate retired built-in ids and add word-form-creator - `applyBuiltinOverrides` treated any non-2xx as failure, including the 404 the backend returns when a legacy `enabled=false` override names a built-in id that the current manifest no longer ships (e.g. the retired `pdf-to-ppt` / `pptx-generator`). One dead preference kept the whole migration flag false, so every launch retried forever and the `assistants` key was never removed from the Electron config. Treat 404 as a skip (the assistant is gone, the preference is moot) while still failing on real errors. - `PRESET_ID_WHITELIST` drifted from the backend manifest: the newer `word-form-creator` built-in was only protected by the `builtin-` prefix check. An unprefixed user row named `word-form-creator` would have been imported and then shadowed by the built-in of the same id. Added the missing entry. Backend `preset-id-whitelist.json` is updated to match in a separate PR. Tests: added two regression cases for the 404 skip path — one asserting the migration finalizes (and removes the key) despite a retired id, one asserting a 500 still keeps the flag false. * feat(migration): preserve explicit preset_agent_type and default gemini→aionrs Two related changes layered onto the assistant migration: 1. `legacyAssistantToCreateRequest` treats the legacy default `'gemini'` (and absent / non-string values) as "no explicit choice" and rewrites to `'aionrs'`. The internal Gemini engine was removed from the current build — what remains with that name is a distinct ACP backend the user must install. Old legacy rows were stamped with `'gemini'` by default, so importing them verbatim would leave every migrated user assistant pointing at a backend that isn't there on boot. Users who explicitly picked `'codex' / 'claude' / 'qwen' / …` keep their choice verbatim. 2. New Phase 3 in `migrateAssistantsToBackend`: replay the user's explicit `presetAgentType` pick for legacy built-ins via PUT /api/assistants/{id}. Live manifest (via `GET /api/assistants`) is the source of truth for the current default, so an identical choice is filtered out (no no-op override rows) and retired built-in ids are also filtered ahead of the network call. 404 at call time still skips (same rationale as Phase 2). Net behaviour for the three interesting legacy states: - `presetAgentType: 'gemini'` or missing → current default (`aionrs`) - `presetAgentType: 'aionrs'` → no-op (matches default) - `presetAgentType: 'codex' / 'claude' / …` → PUT override, pick survives Tests: added 3 unit cases around the `'gemini' → 'aionrs'` rewrite, and 4 integration cases covering Phase 3 — explicit pick preserved, legacy default collapsed, already-matching default skipped, retired id filtered. --------- Co-authored-by: zk <zk@users.noreply.local>
…/AionUi into feat/backend-migration
…iceAI#2898) Backend refactor (aionui-backend#254) moved session-scoped ACP operations from /api/acp/* and ai-agent-owned handlers into the conversation domain. Sync the frontend to the new contract: - POST /api/conversations/{id}/stop → /cancel (conversation.stop keeps its name; only the underlying URL changed) - /api/acp/health-check → /api/agents/health-check - Drop /api/acp/detect-cli and /api/acp/env (unused by the UI) - Drop /api/conversations/{id}/config and /api/conversations/{id}/reload-context — frontend never called the config endpoints and reloadContext had no call sites - Rename acpConversation.getModelInfo → getModel to match the backend handler name; update AcpModelSelector call sites - Remove cached_config_options from AcpChat destructure (already broken tsc, the prop was never declared)
…#2899) * refactor(ipcBridge): align ACP endpoints with backend migration Backend refactor (aionui-backend#254) moved session-scoped ACP operations from /api/acp/* and ai-agent-owned handlers into the conversation domain. Sync the frontend to the new contract: - POST /api/conversations/{id}/stop → /cancel (conversation.stop keeps its name; only the underlying URL changed) - /api/acp/health-check → /api/agents/health-check - Drop /api/acp/detect-cli and /api/acp/env (unused by the UI) - Drop /api/conversations/{id}/config and /api/conversations/{id}/reload-context — frontend never called the config endpoints and reloadContext had no call sites - Rename acpConversation.getModelInfo → getModel to match the backend handler name; update AcpModelSelector call sites - Remove cached_config_options from AcpChat destructure (already broken tsc, the prop was never declared) * chore(docs): remove completed migration and archived specs - Removed team MCP and backend migration documentation (Phase 1 complete) - Removed ACP rewrite specs (superseded by current implementation) - Removed archived feature specs (extension-market, remote-agent, wake-prompt) - Removed E2E audit reports and handoff documents - Cleaned up 156 obsolete documentation files (65,398 lines)
Gemini CLI has been removed; only Aion CLI supports custom models now.
Backend now receives work_dir as explicit CLI argument instead of relying solely on AIONUI_WORK_DIR env var. Env var kept as fallback.
cacheDir is no longer meaningful in the new backend-separated architecture. The setting is removed from the UI while preserving the underlying IPC contract — existing custom paths are passed through unchanged to avoid breaking users who previously modified it.
…gent ready
- Fix ipcBridge type to match actual backend response (array, not object)
- Map backend { command, description } to frontend SlashCommandItem format
- Defer slash-commands fetch until agentStatus is non-null to avoid 404
on newly created conversations before the agent is warmed up
Slash commands fetch was racing against agent startup — the API returned 404 because the agent task did not exist yet. Call warmup on conversation entry and only trigger the slash-commands fetch after it succeeds.
…iOfficeAI#2914) * fix(acp): use WebSocket-pushed available_commands for slash menu The backend already pushes available_commands via WebSocket during session bootstrap. Instead of polling the HTTP API (which was broken because the session aggregate never stored commands), consume the WebSocket event directly in useAcpMessage and pass the commands to AcpSendBox. * fix(acp): fetch slash commands via HTTP on hydration WebSocket push of available_commands arrives during warmup when no StreamRelay is listening, so the event gets dropped. Add an HTTP fetch via /slash-commands after conversation hydration completes to populate the initial command list. Runtime updates still flow through the existing WebSocket available_commands handler. * fix(acp): warmup before fetching slash commands Change the HTTP fetch timing from 'after hydration' to 'after warmup completes'. This mirrors the aionrs pattern: call warmup API first (which ensures the session aggregate has available_commands data from the CLI notification), then fetch /slash-commands. Previous approach fetched on hasHydratedRunningState which could race with warmup - the agent task might not be ready yet. --------- Co-authored-by: zynx <>
* Use backend MCP servers as settings source * Fix builtin MCP bootstrap config sync * Fix image MCP provider resolution * Hide internal AionUi MCP status source * Lock MCP toggle while syncing agents --------- Co-authored-by: zynx <>
Co-authored-by: zynx <>
…3078) Co-authored-by: zynx <>
Co-authored-by: zynx <>
Co-authored-by: zynx <>
Co-authored-by: zynx <>
* fix(settings): use provider health check probe * fix(settings): add aws credential health error type --------- Co-authored-by: zynx <>
Co-authored-by: zynx <>
…ces (iOfficeAI#3084) When re-entering a conversation, the ACP model selector silently rolled back to the model that was pinned on conversation creation (`extra.current_model_id`), even after the user had switched models — the actual session was on the new model, but the UI lied about it (ELECTRON-1RV). Root cause: `useAcpModelInfo.reloadModelInfo` and the `acp_model_info` stream handler used the conversation's stale `initialModelId` to override the backend's authoritative `current_model_id` whenever `hasUserChangedModel` had been reset (i.e. on every conversation switch). Fix: - Treat backend `getModel().current_model_id` as the source of truth. Only fall back to `initialModelId` when the backend has no current model yet (genuine pre-handshake case). - On every conversation-side model switch, persist `acp.config[backend].preferredModelId` and write the chosen id back into `conversation.extra.current_model_id`, so the home page picks up the new default and the same conversation's `initialModelId` stops shadowing the backend. - Mirror the same persistence for mode switches (AgentModeSelector + ACP/Aionrs mobile sheets) and aionrs model switches in the conversation header and team views, so any change to model/mode — whether from the home page or a conversation — becomes the next session's default.
Co-authored-by: zynx <>
…ficeAI#3091) * fix(settings): avoid blue switch during image generation loading * fix(ci): remove unsupported setup-bun cache input * Revert "fix(ci): remove unsupported setup-bun cache input" This reverts commit 8338fb3. --------- Co-authored-by: zk <zk@users.noreply.local>
Co-authored-by: zynx <>
Co-authored-by: zynx <>
Co-authored-by: zynx <>
Co-authored-by: zynx <>
Co-authored-by: zk <zk@users.noreply.local>
* test(web-host): cover backend crash restart port and logs * fix(web-host): reuse backend port after crash restart * style(web-host): format backend restart changes --------- Co-authored-by: zynx <>
* feat(mcp): move MCP management to conversation scope * test(mcp): align tests after session MCP refactor * fix(mcp): clean up agent process trees on shutdown * fix(mcp): clarify runtime hints and test status copy * fix(mcp): tighten edit validation and status messaging * fix(mcp): refine conversation MCP helper layout * fix(mcp): clarify test status hint copy --------- Co-authored-by: zk <zk@users.noreply.local>
* fix(conversation): show structured agent errors * fix(conversation): always allow feedback on error tips * feat(agent): preserve error resolution metadata * feat(agent): show error resolution guidance * style(agent): format error normalization test * fix(conversation): localize agent error codes - Add friendly title and body copy for newly classified agent error codes in every locale - Update MessageTips tests to use the real billing-required code and guard against fallback copy - Regenerate typed i18n keys for the new conversation agent error entries * fix(conversation): expand agent error details by default * fix(conversation): label agent error suggestions * fix(conversation): localize agent error copy
Co-authored-by: zynx <>
…AI#3121) * fix(desktop): classify missing backend binary installs * fix(desktop): add backend install diagnostics --------- Co-authored-by: zynx <>
Co-authored-by: zynx <>
Co-authored-by: zk <zk@users.noreply.local>
Introduce multi-turn side threads with a resizable right dock, Cmd+Shift+S and /side entry points, Phase 1 create params with POST /side fallback, history filtering for ephemeral side chats, and unit tests. Co-authored-by: Cursor <cursoragent@cursor.com>
Owner
Author
|
Superseded by upstream PR: iOfficeAI#3196 |
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
createSide→ POST/api/conversations/:id/sidewith Phase 1 fallback/btwunchanged; 16 unit testsTest plan
bun run testPair with iOfficeAI/AionCore#383 for Phase 2 backend.
Made with Cursor