* fix(web): add close button to dialog so modals are dismissable on mobile
The shared DialogContent had no close affordance — desktop users could
press Escape or click the overlay, but on mobile (no Escape key, dialog
spans calc(100vw-24px) leaving almost no tappable overlay) there was no
way to dismiss it. Add a DialogPrimitive.Close X button in the top-right,
fixing every dialog that uses this component at once.
* fix(web): reserve header space for dialog close button
Address review feedback: the absolutely-positioned close button overlaps
the top-right of every dialog. Long/breaking titles (e.g. DiffView's
break-all filename) could wrap underneath the 32px tap target. Add pr-12
to DialogHeader rather than padding DialogContent globally, so the title
row clears the button while body content (code blocks, diffs) keeps full
width.
* fix(web): localize dialog close button aria-label
Use the existing button.close locale string instead of a hardcoded
"Close" so screen-reader users get the label in their language (zh-CN: 关闭).
* feat(web): polish chat rendering
Refresh the web chat presentation across user messages, tool cards, code blocks, diffs, reasoning, and Mermaid diagrams.\n\nAdd focused regression coverage for bubble/status behavior, code and diff rendering, clipboard output, Mermaid theming, and message-window updates.
* fix(web): stabilize chat tool rendering
Preserve manual scroll anchors while older messages and tool dialogs update, and align code, diff, and tool result rendering with chat typography.
Add chat font-weight settings, ignore local Playwright CLI artifacts, document the Angular commit-message convention, and cover the scroll, result, code, diff, and settings behavior with focused tests.
Constraint: User requested committing all current workspace diffs with Angular-style commit messaging
Tested: bun run typecheck:web && bun run test:web && git diff --check
Co-authored-by: OmX <omx@oh-my-codex.dev>
* style(tool-card): polish question and permission card styles
Align AskUserQuestion option surfaces and permission action hierarchy with the existing tool card visual language while preserving interaction logic. Extract shared option presentation helpers and theme-driven hover/muted colors to reduce duplication.
Constraint: Frontend style-only polish; preserve existing permission and answer submission behavior
Rejected: Keep screenshot artifacts in the repo | they are local visual review output, not source
Confidence: high
Scope-risk: narrow
Tested: git diff --check; bun run typecheck:web; bun run test:web; bun run build:web
Not-tested: manual cross-browser visual QA beyond local Playwright inspection
Co-authored-by: OmX <omx@oh-my-codex.dev>
* fix(cli): keep Claude remote plan prompts actionable
Handle Claude remote /plan locally so HAPI switches plan permission mode before forwarding any prompt text. This avoids Claude Code treating /plan as an unknown skill and ending with only a ready event.
Constraint: Claude SDK result messages are not conversation log entries, so command handling must happen before the prompt reaches Claude.\nRejected: surfacing SDK result summaries in web chat | would expose transport-level summaries broadly instead of fixing the slash-command path.\nConfidence: high\nScope-risk: narrow\nDirective: Keep Claude remote slash commands that alter runtime mode in the CLI special-command parser.\nTested: bun test cli/src/parsers/specialCommands.test.ts; bun typecheck; git diff --check\nNot-tested: Manual GitHub-hosted runner deployment.
* fix(web): polish tool result rendering
* fix(web): preserve collapsed session order
* fix(chat): settle initial thread scroll
* fix(settings): remove chat font weight option
* fix(web): remove font weight bootstrap code
* chore: remove unrelated branch artifacts
* test(web): update consumed message invocation test
* fix(chat): cancel initial scroll settling on manual scroll
---------
Co-authored-by: huhaoyu.hahahu <huhaoyu.hahahu@bytedance.com>
Co-authored-by: OmX <omx@oh-my-codex.dev>
Implement a visibility-aware notification system that delivers toast messages via SSE to visible browser tabs instead of sending push notifications, reducing unnecessary push requests. Includes VisibilityTracker for monitoring connection visibility, toast UI components, and enhanced SSEManager with toast delivery capability.
Implements comprehensive session lifecycle management with user-friendly interactions:
Rename: Update session metadata.name via PATCH endpoint with conflict detection
Archive: Abort active sessions via DELETE endpoint with validation
Delete: Permanently remove inactive sessions with cascade cleanup
Backend:
- Store.deleteSession() removes session and cascade-deletes messages
- SyncEngine.renameSession() with concurrency error handling
- SyncEngine.deleteSession() with active session validation
- PATCH /sessions/:id for rename, DELETE /sessions/:id for delete
Frontend Components:
- RenameSessionDialog: Text input with auto-focus and error display
- SessionActionMenu: Modal with rename, archive, delete buttons
- ConfirmDialog: Reusable confirmation with error feedback
- SessionHeader: Menu button (⋮) triggering action menu
- SessionList: Long-press detection triggering item actions
Interactions:
- Long-press on session list items (500ms threshold) opens action menu
- Menu button in session header (non-Telegram environments only)
- Confirmation dialogs with descriptive warnings for destructive actions
- Real-time error display in dialogs on operation failure
- Haptic feedback on long-press via usePlatform hook
Accessibility:
- Keyboard support (Enter/Space) for long-press handler
- Focus management in RenameSessionDialog
- Proper ARIA labels and semantic HTML