Skip to content

chore(brew): bump Homebrew formula to 0.23.1 - #4

Open
github-actions[bot] wants to merge 1 commit into
mainfrom
chore/brew-bump-0.23.1
Open

chore(brew): bump Homebrew formula to 0.23.1#4
github-actions[bot] wants to merge 1 commit into
mainfrom
chore/brew-bump-0.23.1

Conversation

@github-actions

@github-actions github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown

Auto-generated by .github/workflows/brew-formula-bump.yml.

  • Previous: 0.21.0
  • New: 0.23.1
  • sha256: 713b6107d8d36acaa668f4e01a06e0629cfb25fd8d10acce3cd27abccefc576e

Heads up: the formula's --min-release-age=1 (npm's 1-day
supply-chain delay) means brew install agor-live against this
version will fail with a notarget error until ~24h after the
npm 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).

@github-actions
github-actions Bot force-pushed the chore/brew-bump-0.23.1 branch 2 times, most recently from 162718f to ab2c976 Compare July 6, 2026 16:49
@github-actions
github-actions Bot force-pushed the chore/brew-bump-0.23.1 branch from ab2c976 to 07ef1dc Compare July 7, 2026 16:24
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant