chore(brew): bump Homebrew formula to 0.23.1 - #4
Open
github-actions[bot] wants to merge 1 commit into
Open
Conversation
github-actions
Bot
force-pushed
the
chore/brew-bump-0.23.1
branch
2 times, most recently
from
July 6, 2026 16:49
162718f to
ab2c976
Compare
github-actions
Bot
force-pushed
the
chore/brew-bump-0.23.1
branch
from
July 7, 2026 16:24
ab2c976 to
07ef1dc
Compare
richardfogaca
pushed a commit
that referenced
this pull request
Aug 7, 2026
…t-io#2022) * feat(user-settings): redesign settings modal to Kasia's mockup Rebuild UserSettingsModal around a searchable, grouped sidebar and one panel per selection, with a context-aware footer, while preserving every piece of real backend wiring, permission gating, and save behavior. - Sidebar: search box + AntD Menu groups (Account / AI Providers / Environment / Admin). Providers are the real enabled-tool list with a per-tool status dot; menu items and filtered results are memoized. - Panels: Profile, Preferences (audio + live event stream under an Interface divider), Security, API Tokens, per-provider (Authentication + Session Defaults tabs), Environment Variables, and admin-only Groups & Access (with force-password in a Danger zone when editing another user). - Footer is context-aware: inline-save panels (env vars, tokens, provider auth) show "Changes save automatically" + Done; batch panels show Close + Save wired to the real per-panel save. - Preserves: dynamic provider list incl. claude-code-cli, real ApiKeyFields / CodexAuthSettings flows, effective-source resolution, dirty session-defaults batching across tools, env var scopes, and permission gating (admin / self-vs-other). - Adds an "Editing <user>" identity indicator when an admin edits another user, and keeps the claude-code-cli provider entry (both approved). - Legacy `initialTab` deep links are normalized onto the new panel keys. Tests updated for the new structure; added coverage for the edit-user banner and sidebar search. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(user-settings): address Codex review of the settings modal redesign Correctness fixes from the Codex review pass: - Search that hides the active panel no longer swaps to Profile and discards in-progress edits — the active panel keeps rendering; search only de-highlights its nav row. - Force-render the provider Session Defaults tab so its form is mounted and connected (kills the "useForm is not connected" warning from the hydration effect). - Hide the caller-scoped "API Tokens" entry when an admin edits another user (the tokens API is scoped to the signed-in caller). - Add a modal-level saving guard: Save/Done show loading, Close disables, and re-entry is blocked to prevent duplicate patches / group syncs (removes the now-redundant per-tool saving state). - Resolve an "Unavailable" provider to not_connected before considering workspace-managed, so the status dot and the panel alert agree. - Give each provider status dot a visually-hidden text label so status is not conveyed by color alone. - Gate onboarding restart on an explicit self check (was shown when currentUser was absent). - Trim two unused fields from resolveProvider's return. Codex #4 (Option A): CodexAuthSettings gains allowChatgptLogin. When an admin edits another user it is false, so only the API-key path (which targets the edited user) is shown; the ChatGPT sign-in, import-login-file, connection probe, and remove-login controls — which act on the caller's own server login — are hidden and the probe no longer fires. Tests updated + extended (API-tokens hidden, Codex controls hidden for other-user editing). Full pnpm check and modal tests green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * refactor(user-settings): visual-fidelity pass via shared panel primitives Route every settings panel through three shared, token-driven primitives so the whole modal keeps one vertical rhythm, matching Kasia's mockup. Behavior, gating, save, hydration, and the form-connector machinery are unchanged. New apps/agor-ui/src/components/SettingsModal/panelPrimitives.tsx: - PanelHeader (absorbs the provider icon + status-tag variant — one header shape) - FieldRow (thin Form.Item wrapper: bold label, always-visible help caption, required '*' after label, uniform row rhythm) - SectionDivider (left, muted, tertiary section break) Chrome: one uniform transparent surface — Layout/Sider transparent, Sider border/padding removed, and the custom Modal header/footer/wrapper/container style overrides (title border, footer band, top offset) dropped for default modal chrome. Footer is now the default button array (Done / Close+Save). Sidebar + content rhythm nudged to the mockup (search 4px/16px, content 28px). Panels: Profile/Security/Preferences/Access/Env/Tokens/Providers now use PanelHeader + FieldRow + SectionDivider. Collapsed the dead effectiveKey/ effectiveTool indirection onto activeKey/activeTool. Alerts de-escalated: env-vars is a one-line info; provider effective-source is a caption unless Unavailable (one-line warning) or workspace-managed (one-line info). Polish: Profile name uses a fused Space.Compact; Role restores the two-line optionRender at maxWidth 320; API tokens description moved to PanelHeader (and the duplicate intro removed from PersonalApiKeysTab); provider Session Defaults gets the intro caption + divider + danger-text Clear defaults; claude-code Sign-in method is a labelled FieldRow with solid buttons; always-visible help replaces the tooltip gating; panel headers are sentence case (nav stays Title Case). AudioSettingsTab (single caller) restyled in place to single-column FieldRows, dropping the Row/Col grid and the note Card; all logic preserved (permission probe, preview, chime util, min-duration bounds, permission Alert, shared form). Tests updated for the sentence-cased headings; 10/10 green. Full pnpm check (workspace tsc + biome + build) green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(user-settings): pixel-fidelity pass (nav rail, spacing, provider/codex) Rendered-vs-rendered fixes to close the gap with Kasia's mockup. Behavior, gating, save, hydration, and the #4 Codex self-gating are unchanged. Nav rail (root cause 1): drop background:transparent from the Menu so it paints its default itemBg (the darker rail); wrap the modal body in a scoped ConfigProvider that mutes v6's over-bright selected pill (Menu.itemSelectedBg = token.colorFillTertiary, itemSelectedColor = colorPrimary) and tightens form label padding (Form.verticalLabelPadding 0 0 6px). Spacing (root cause 2): FieldRow now renders its caption via Form.Item `extra` instead of `help`, which was applying Ant's explain margin-offset (-22) and eating the row rhythm after every captioned field (and suppressing validation). Email/Role validation still shows; the 22px gap returns. Also: PanelHeader gains paddingTop token.marginLG, SectionDivider gets orientationMargin 0, Modal body drops minHeight, and the footer hint uses fontSizeSM + marginSM. Preferences: remove the volume Slider marks (keep the hover tooltip), restore the '🔊 Task Completion Chimes' sub-heading, drop the extra Chime-sound caption, and wrap the Note back in a Card type="inner". Provider panel: 'Session defaults' tab casing; the effective-source line moves below the credential fields as a caption (actionable Unavailable / workspace states stay as one-line Alerts above); Connected tag uses CheckCircleFilled. Codex sign-in (item 15, single-caller confirmed): CodexAuthSettings swaps its unlabeled block Segmented for a labelled 'Sign-in method' FieldRow with a solid Radio.Group (API key / Sign in with ChatGPT / Import login file); all three auth flows and the probe/remove behavior are preserved. Slack-avatar help restored to the mockup wording. Tests updated (Session defaults casing); UserSettingsModal + CodexAuthSettings suites green (26). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(user-settings): align sidebar search width with the tab rows Reduce the search wrapper's horizontal padding from 16px to 4px so the input's left/right edges line up with the Menu item rows (which inset 4px each side via itemMarginInline). Keeps top/bottom padding; tokenised as `${marginXXS}px ${marginXXS}px ${marginSM}px`. Menu and Sider unchanged. Deliberate deviation from the mockup (search was inset 16px) per Kamil. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(user-settings): elevated left panel, tooltip help, global content search Consistency-with-the-app pass (supersedes earlier 'seamless sider' and 'all-help-visible' choices). Behavior, gating, save, and hydration unchanged. Left panel: restore the master look — the Sider is a distinct elevated surface (colorBgElevated + right border, padding 20px 0) with the Menu transparent inside it; content stays colorBgContainer. Width 220 so the grouped labels (e.g. Environment Variables) and status-dot rows don't clip. The search input now lives inside the elevated sider, above the Menu, still aligned to the tab rows. Keeps the round-3 scoped selected-pill override. Help clutter: move non-essential always-visible captions into an info-icon Tooltip next to the label (FieldRow gains a `tooltip` prop) — Slack avatar, Role (non-admin), Unix username, Live event stream, Groups, Codex/Claude sign-in method, and the audio min-duration note. Only the security-sensitive 'Leave blank to keep your current password' stays inline. Captions still render via `extra`, so absent-help rows keep correct spacing. Global search: a maintained flat SETTINGS_INDEX ({label, keywords, panelKey}) covers every setting across all panels (provider rows appended per enabled tool). Typing now searches setting contents + keywords, not just nav names; hits render as clickable sidebar rows ('Setting · Panel') that navigate to the hosting panel and clear the query. Empty-state and the active-panel-render guard are preserved; the filter is memoized. Reuses filterBySettingsSearch + HighlightMatch. New settings must be added to the index (noted in code). Tests updated for the new sidebar/search; added a global-search content test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * refactor(user-settings): match master content styling + rank search results Content/right panel now matches origin/main's form styling while keeping the new structure/features. Left panel (round-4) is unchanged. Master styling: - PanelHeader is title-only (Typography.Title level 4, marginBottom 20; the provider variant keeps its ToolIcon + status tag). Removed the redesign-added panel descriptions (Profile/Security/Preferences); restored master's plain secondary paragraphs for Environment variables / Groups & access / API tokens. - FieldRow now renders as a plain app Form.Item: regular-weight label, default vertical spacing and label padding, Ant's native `help`/`tooltip`, and the default required mark. Dropped requiredMark={false} across the forms and the scoped Form.verticalLabelPadding override. - help vs tooltip follow master: persistent notes (Password, Role, Unix username, Groups) use `help`; details (Slack avatar, Live event stream, Codex/Claude sign-in method, audio min-duration) use the label tooltip icon. Search ranking (case-insensitive, deterministic tiebreak by index): a matched tab name first (prefix over substring), then that tab's own matching settings, then label matches in other tabs (prefix over substring), and finally keyword-only hits where the visible label doesn't contain the query. SETTINGS_ INDEX already separates `label` from `keywords`, so keyword-only aliases sink. Worked example — 'sec': Security (tab) ranks first; 'Minimum task duration' (matches only via the 'seconds' keyword) ranks last. Tests: added a 'sec' ranking assertion; UserSettingsModal + CodexAuthSettings suites green (28). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(user-settings): correct search ranking + divide pages from settings Ranking now sorts by, most significant first: (1) a matched page/tab name; (2) tab-membership — a setting whose panel's name matched ranks above settings in non-matched tabs, even if the setting itself only matched via a keyword; (3) label match over keyword/alias-only match; (4) prefix over mid-substring; (5) index for a stable tie. This fixes 'sec', which now returns Security → Password (a Security-tab setting) → Minimum task duration → Environment variables, instead of floating the keyword-only min-duration hit above Password. Search results also drop an AntD Menu { type: 'divider' } between the matched page hits and the setting hits, rendered only when both kinds are present (no dangling divider; nothing when the normal grouped nav is showing). Tests: assert the 'sec' order (Security, then Password, then min-duration after Password) and that the divider renders for mixed results but not for a settings-only query. 28 passing. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(user-settings): flush dirty panels on Save + search/header polish Data-loss fix (primary): Profile/Security/Preferences/Access share one Form instance, but Save only committed the active panel, silently dropping edits on panels the user had navigated away from. Track which main-form panels went dirty and flush them all into a single combined patch, building one preferences object so profile/preferences contributions don't clobber each other. Also in this file, AntD-v6-first: - Search index mirrors on-screen labels (kind: page|setting derived from navGroups) and covers per-provider credential/policy settings. - Multi-token search classifies a page/label hit only when every token matches; the full query is kept for the prefix tier. - Alert `message` -> `title` (v6 API). - Removed the modal header bar: title and "Editing <user>" indicator now live at the top of the full-height elevated Sider; a floating close button remains. Covered by cross-panel-save, multi-token, and rendered-label search tests. * refactor(user-settings): adopt AntD v6 Divider styles API Replace the deprecated `orientationMargin` prop on SectionDivider with the v6 `styles.content.margin` equivalent. * refactor(user-settings): drop AudioSettingsTab double-seed and unused user prop The parent modal already hydrates the shared audio form on the preferences effect, so AudioSettingsTab's own `initialValues` were a redundant second seed. Remove them along with the now-unused `user` prop (and its type/constant imports), letting the shared-form hydration be the single source of truth. * refactor(user-settings): adopt AntD v6 Alert API in Codex/audio panes Replace the deprecated Alert `message` prop with `title` across CodexAuthSettings (connection/error banners) and the boolean `closable`+`onClose` pair with the v6 `closable={{ onClose }}` object in AudioSettingsTab's permission alert. * refactor(settings-search): tokenize once + export model label helper Add `matchesSettingsSearchTokens` so callers holding precomputed tokens don't re-tokenize per candidate, and export `modelLabelForTool` so the settings search index can label provider model entries with the real rendered label. * fix(user-settings): flush main edits on provider Save, gate content, fix MCP save Two save-path data-loss fixes plus authorization and search hardening, all in the settings modal: - Provider Save dropped dirty main-form edits: handleModalSave saved agentic config and closed before committing the shared Profile/Security/Preferences/ Access form. Unify the path so dirty main panels commit FIRST (aborting the close on validation failure), then agentic configs persist once — symmetric with the non-provider path. - User-level default_mcp_server_ids was read from the dirty set's first tool, dropping a newer edit made on a different tool. Track the tool that most recently changed the MCP list and source the saved value from it. - Authorization now gates CONTENT, not just nav: an unauthorized/stale deep link (access for a non-admin; tokens while editing another user — which would expose the CALLER's tokens under the target heading) redirects to Profile. The force-password checkbox is also gated with isAdmin && isEditingOther. - Restore legacy initialTab aliases (general/audio/groups/personal-api-keys) so pre-redesign deep links land on the right panel instead of Profile. - Provider search entries mirror what each tool actually renders: no Authentication entry when a tool has no credential fields, the always-present "Default for new configurations" control is indexed, and the model entry uses the real rendered label (e.g. "OpenCode LLM Provider"). - Reuse precomputed search tokens instead of re-tokenizing per candidate. - Cleanup: one PANEL_META record feeds nav labels, icons, headers, and search page keywords (no more casing drift); drop the post-CLI canonicalTool/ credentialToolName aliases; remove the redundant emoji Form.Item wrapper. Adds tests for provider-tab main-flush, MCP-source-of-last-edit, and the unauthorized deep-link redirect. * fix(user-settings): flush modal chrome so the sider sits in the card At wider/taller viewports the modal read as two detached panels: the card slot kept AntD's default 20px 24px padding (background colorBgElevated), so the elevated Sider merged into that frame while the darker colorBgContainer Layout looked like an inset card. Round-6's header removal had dropped the flush-card styles master relies on. Zero the card frame and clip to its rounded corners via `styles.container` (the v6 `.ant-modal-container` slot) with `{ padding: 0, overflow: 'hidden' }`, so the inner Layout fills the card edge-to-edge and the Sider is flush to the rounded left/top/bottom edges. Since the frame is gone, the footer now supplies its own `12px 24px` padding, top border, and container background; the body regains master's `minHeight: 450`. Content and Sider keep their own padding. Chrome-only — no behavior change. * test(user-settings): disable AntD cssinjs hashing to keep modal tests under CI timeout The 'saves dirty agentic defaults across tabs' test (and the other heavy provider-navigation cases) timed out at 60s on CI. Root-caused: it is NOT a hang and NOT a save-path bug — in isolation the test passes in ~9s and the unified handleModalSave fires onUpdate + onClose exactly once with the asserted payload even when no main-form panel is dirty and client is null. Profiling showed exactly one re-render per navigation, each taking ~2.6-3.2s of pure synchronous render, dominated by AntD's CSS-in-JS hash computation when mounting the Form/Menu/Modal-heavy tree in jsdom (the config already notes this "CSS parse + getComputedStyle" cold cost). Under contended CI parallelism the heaviest cases exceeded even the 60s override. Wrap the shared test render in `<ConfigProvider theme={{ hashed: false }}>`, which removes only the `css-dev-only-*` hash suffix — semantic `.ant-*` classes and every component's behaviour are unchanged, so the tests exercise exactly what they did before. Per-render cost drops ~42-46%: the target test 9.8s→5.7s, the heaviest (MCP) 13.3s→7.3s, and the whole file 89s→50s, restoring ample CI margin without bumping the timeout or weakening any assertion. * fix(codex-auth): correct sign-in-method help copy Selecting a method here only changes which pane is shown; the effective auth method changes when a key is saved or a login/import completes. Reword the help text so it no longer implies selection alone activates a method. * fix(user-settings): synchronous panel authz, audio draft, search sub-tab, a11y Addresses Richard's review: - Authorize the active panel SYNCHRONOUSLY during render instead of correcting it in an effect. Previously an unauthorized deep link (e.g. an admin opening API Tokens while editing ANOTHER user) mounted the caller-scoped panel once before the effect redirected, so PersonalApiKeysTab began loading the caller's keys under the edited user's identity. The active key is now derived from the permission-filtered nav so unauthorized content never mounts. This also gates provider keys: a deep link to a tenant-disabled `provider:<tool>` falls back to Profile once tool settings load. - Preserve the audio form draft across navigation: hydrate it from persisted values only while the Preferences panel is still pristine, mirroring the agentic-config draft contract (same class as the preset-io#1769 revert). Editing audio, navigating away, and returning no longer drops the edit on Save. - Provider search hits carry their destination sub-tab, so a "Session defaults" result opens the defaults pane rather than the default Authentication view. - Give the (header-hidden) dialog an accessible name via a `title`, which becomes rc-dialog's `aria-labelledby` target so screen readers announce it. Tests: never-load-caller-keys, disabled-provider fallback, audio draft round trip, search-hit sub-tab, and dialog accessible name. The audio test mocks AudioSettingsTab (its real AntD Slider trips a jsdom/cssstyle `border: var()` crash) with a form-connected stand-in so the parent's draft logic is exercised. * feat(store): track agentic-tool-settings hydration Add an `agenticToolSettingsHydrated` flag, set the first time the background agentic-tool-settings load applies (empty result included), mirroring the existing mcp-servers / gateway-channels hydration gates. Lets consumers tell "not loaded yet" apart from "loaded and empty" instead of treating a missing tenant tool setting as enabled. * fix(user-settings): fail closed on provider authz during hydration + search fixes Addresses Richard's follow-up review: - Provider deep links no longer fail OPEN while tenant tool settings hydrate. Until `agenticToolSettingsHydrated`, an empty store reports every tool as enabled, so a `provider:<tool>` deep link for a tenant-DISABLED tool briefly mounted its credential/default controls. The synchronous authz now resolves a provider key to Profile until availability is KNOWN, then applies the enabled filter. Test: a disabled-provider deep link never mounts its content or hits its services across the hydration window (settings arrive after mount). - The pending search sub-tab is scoped to its provider key, so a hit for the ALREADY-active provider can no longer leak its sub-tab onto the next provider opened. Test: search a Session-defaults setting for the active provider, open a different provider, assert it opens on its own default (Authentication). - The search index only lists credential fields actually rendered for the effective auth method (`resolveProvider().toolFields`), so every credential hit lands on a visible control (e.g. no OpenAI-key hit while Codex is on a ChatGPT login). Test: the hidden field is not indexed on a subscription. * fix(store): only mark tool-settings hydrated on a complete snapshot The round-10 hydration gate flipped `agenticToolSettingsHydrated` on every `setAgenticToolSettings` call — including realtime single-row updates. A `patched`/`created` event landing before the background full fetch would mark a PARTIAL map authoritative, so disabled providers missing from that partial map fail open again. Split the store action: - `setAgenticToolSettings(fullList)` — replace the whole map from a complete snapshot AND set hydrated=true (only a full snapshot may flip the gate). - `upsertAgenticToolSetting(row)` — merge one row, leaving the hydrated flag untouched (a partial row never establishes the complete set). Also clear BOTH the tool-settings map and the hydration flag in `resetMaps()` (they are meta, not data maps, so they previously survived logout/tenant switch and leaked cross-tenant fail-open + stale rows into the next tenant). Tests: patch-before-fetch keeps the gate closed until the full snapshot lands; upsert leaves an already-set flag alone; resetMaps clears map + flag. * fix(agentic-tool-settings): route incremental updates through the upsert Point the realtime `patched`/`created` handler and the admin single-tool edit at `upsertAgenticToolSetting` so an incremental row can't flip the hydration gate. Subscribe to `created` (and tear it down) alongside `patched`. * fix(agentic-tool-settings): route full fetch through the shared hydration lifecycle The full `agentic-tool-settings` snapshot was an unguarded fire-and-forget promise — the only background collection not using `runHydration`. That caused two lifecycle races: - a stale older snapshot could resolve after (and overwrite) a fresher realtime upsert; - a request started before logout could resolve after it, repopulating the previous tenant's settings with the hydration gate open (cross-tenant leak). Reuse the existing skip-apply-on-race / generation mechanism the other realtime-backed collections already use (`runHydration` + `liveRevisions`/`hydrationGeneration`, apps/agor-ui/src/store/agorHydration.ts): - register `agenticToolSettings` as a `HydratedCollection` (revision + generation counter); - load the full snapshot via `runHydration(...)` so it applies WHOLESALE only in a quiet, still-current window — otherwise it's discarded/refetched, and a loop superseded by logout's `cancelAndFailAllHydrations` never applies; - bump the collection's revision in the realtime `patched`/`created` handler so a raced full fetch discards its stale snapshot. The apply is `setAgenticToolSettings` (the complete-snapshot action that sets the hydration gate), so the gate still only flips on a quiet, current snapshot. Tests (agorStore.test.ts): a stale snapshot resolving after a realtime upsert is dropped (upserted value survives); a fetch resolving after logout is ignored (no repopulation, hydrated stays false). --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.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.
Auto-generated by
.github/workflows/brew-formula-bump.yml.0.21.00.23.1713b6107d8d36acaa668f4e01a06e0629cfb25fd8d10acce3cd27abccefc576eHeads up: the formula's
--min-release-age=1(npm's 1-daysupply-chain delay) means
brew install agor-liveagainst thisversion will fail with a
notargeterror until ~24h after thenpm publish. That's intentional. By the time this PR is reviewed
and merged the cooldown will almost always have lapsed; if you
merge early, the next install attempt within that window will
surface the npm error verbatim (no harm done — re-run succeeds).