Skip to content

Choose model and effort for mentioned agents - #856

Merged
matt2e merged 2 commits into
mainfrom
baxen/model
Oct 12, 2026
Merged

matt2e merged 2 commits into
mainfrom
baxen/model

Conversation

@baxen

@baxen baxen commented Oct 11, 2026 •

Copy link
Copy Markdown
Collaborator

Merge stack, bottom to top: #838 → #855 → #856 → #858 → #859 → #860 → #865 → #867 → #871. Each PR targets the one before it. Earlier stack notes here are superseded.

Mentioning your own Claude Code or Codex agent exposes a model/effort control for its next run. The control appears immediately while discovery fills in a loading state. Choices are sent as owner-scoped message tags; an unpicked turn returns to the agent defaults, and unsupported model/effort choices are rejected by the existing service/runtime boundaries.

The picker uses the existing IconButton, Menu and Popover owners with the effort slider. Codex discovery reuses #852’s shared server. Claude discovery reads an existing session or uses a temporary process that is released after reading; it never assigns the shared warm spare to an agent merely to inspect settings. Cached own-model metadata survives a first-turn override.

Validation: 124 runtime/hook tests passed, 268 composer tests passed, TypeScript passed. Independent integration review found two lifecycle/default-discovery defects; both were fixed with regressions. Manual automated-browser harness exercised pending → ready, keyboard focus, slider changes and popup bounds in Chromium and WebKit, both themes, narrow/wide widths and enlarged text (12 combinations). No permanent browser cases added; pending-state assertions use held promises in the existing component tests. Native and human acceptance of the combined stack remain pending.

Browser integration validation

The shared popup token test now identifies the Completions surface by its data-mention variant, so the model picker’s separate popup class cannot change which surface is checked. The failure reproduced before the correction; the full spec passes in Chromium and WebKit (2 cases), with all CSS assertions retained.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-12T00:08:51.919144Z c41320f Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c41320fdbc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +347 to +348
...(delivery.model ? { model: delivery.model } : {}),
...(delivery.effort ? { effort: delivery.effort } : {}),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Queue tuned Codex messages behind the active turn

When this conversation already has lane.active, these captured values never reach execute: the active branch sends only turn/steer, while the model and effort are consulted only when starting or resuming a fresh turn. A user who selects a different model or effort while Codex is working therefore has the message steered into the existing turn under its old settings. Queue a picked message as a new turn, or make the picker unavailable while the conversation is active.

Useful? React with 👍 / 👎.

const changed = JSON.stringify(next) !== JSON.stringify(valueRef.current);
valueRef.current = next;
updateDraft(next);
setPicks({});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restore run picks with failed attachment sends

When attachment upload or preparation fails after sendInBackground begins, this clears the selected model and effort immediately, but the recovery callback restores only the draft and attachments. The recovered composer therefore looks ready to retry while silently sending the agent at its default settings. Store the captured picks in the recovery record or restore them alongside the captured draft.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Follow-up fix for this: #887 — the recovery record now carries the captured model/effort picks and restores them alongside the draft and attachments (also covers the user-initiated Cancel path, which recovers through the same callback). No new persistence; picks still do not survive reload by design.

Comment on lines +93 to +94
<Popover.Popup
className={styles.popup}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use the shared bounded popover frame

When several tunable agents are mentioned or text is enlarged, this raw Base UI popup uses local styling with no max-height or scrolling, so lower model/effort controls can extend beyond the available viewport and become unreachable. The shared PopoverPopup already owns viewport bounds, overflow, placement motion, and focus restoration; use it with the appropriate padding rather than recreating the frame locally.

AGENTS.md reference: AGENTS.md:L35-L41

Useful? React with 👍 / 👎.

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes needed: keep model-discovery failures visible and retryable (new P2 inline). I also corroborated the existing Codex steering, attachment-retry, and popup-bounds findings at this head; linking rather than duplicating them.

Star Lord’s automated source review via Wes’s account. Head ba91a8bf23ab1d70e0d09df3932d31adea6d6e75; base 430392dd1e5dcc23adaf5343e0cac8bb02a96ab4. Source-only: no tests, app/runtime execution, rendered UI inspection, or CI verification. Public diff, commit messages, and PR description checked; the description has no attached images. Non-blocking COMMENT, not approval.

Comment on lines +91 to +96
} catch (error) {
console.warn(
`Agent type ${type.key} could not list its models`,
error,
);
return [];

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Preserve a failed discovery state with a retry action

If the model lookup rejects (for example, Codex config/read/model/list times out or the CLI fails to start), this catch returns the same empty result as an agent with no configurable models. With one mentioned agent, ComposerModels then returns null, removing both the gauge and any open popup; the user sees no failure and has no retry control. Editing the message or the runtime clearing its failed cache does not change this effect’s snapshot/types/key dependencies, so discovery is not retried for the unchanged mention. Keep a per-agent error choice mounted and expose retry, preserving any usable choices and popup focus. This follows DESIGN.md’s “States, feedback, and motion” requirement to distinguish failed loading from absence and put recovery beside the failed operation. Add a rejected-lookup → retry-success regression, including keyboard focus.

Base automatically changed from baxen/session-debug to main October 12, 2026 02:40
@matt2e
matt2e requested a review from a team as a code owner October 12, 2026 02:40
baxen and others added 2 commits October 12, 2026 13:46
Mentioning your own Claude Code or Codex agent shows a gauge in the
composer. Its popover is an effort slider with the model name in the
slider's tab; the name opens a compact menu of the agent's models. The
pick rides on that message as `model` and `effort` tags for that agent,
and the host honors them only from the owner and only for listed models
and levels.

- Codex passes the pick to `turn/start` for that turn only.
- Claude Code lists models from `initialize`, sends `set_model` and
  `apply_flag_settings` ahead of the picked turn, and restores its own
  on the next unpicked one.
- The slider opens at the effort an unpicked run uses (Claude Code's
  session effort, Codex's configured effort or the model's default);
  moving back to it is no pick.
- A configured Codex model its CLI does not list keeps the picker, with
  the listed models still pickable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Squashed-from: baxen/model
Squashed-head: 053cee0dba93bb946f544c0c87804ceee90a49ef
Signed-off-by: Bradley Axen <baxen@squareup.com>
Co-authored-by: Codex <noreply@openai.com>
Signed-off-by: Matt Toohey <contact@matttoohey.com>
Composer model controls also use a popup class. Select the completion-specific data-mention variant instead of whichever CSS module loads first. Preserves all token and geometry assertions; reproduced before and passed in Chromium and WebKit after.

Co-authored-by: codex00 <6922125dbee102fcf02d2b32441fd56927c1298ac16119167f82f72529d13676@buzz.block.builderlab.xyz>
Signed-off-by: Bradley Axen <baxen@squareup.com>
Signed-off-by: Matt Toohey <contact@matttoohey.com>

@kalvinnchau kalvinnchau left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Two additional P2 findings: revalidate the live community binding after discovery, and preserve picker state across unrelated run-status updates. Existing findings are not repeated.

Promise.resolve().then(async () => {
const pick = await pickFor(job.trigger, agent, type);
signal.throwIfAborted();
return run(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 [P2] Revalidate the live community binding after discovery

If the owner disconnects the community while model discovery is pending, this await can resume after disconnect cleanup and still call run using the captured agent/community. The runner signal does not include the community binding, and the Claude runtime can recreate its disposed entry, starting local work after the explicit disconnect. A bounded fake-process check using the production discovery/session/runtime classes and extracted drain logic observed a new process and user message after disconnect; a post-discovery readiness guard prevented both. Revalidate the current binding/generation, agent/type and cancellation before launching, preserving the intended reconnect/queue policy. Add a held-discovery → disconnect → resolve regression that asserts no launch, plus reconnect coverage.

]
: [];
});
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 [P2] Keep resolved choices mounted during unrelated run-status updates

useMentionModels keys its resolved result on the entire Agents2 snapshot. Starting or finishing any owned agent run replaces that snapshot (service.ts:828–837), so resolved?.snapshot === snapshot fails and the picker returns to its loading state until discovery completes again. AgentChoice then unmounts its model menu and effort slider (ComposerModels.tsx:137–143), closing an open menu and losing slider focus even when the mentioned agent configuration has not changed. Key discovery on the relevant agent/configuration identities, or retain resolved choices while refreshing and reserve the loading replacement for the initial lookup. Add a regression that keeps an open picker/focused slider stable while an unrelated agent starts or finishes.

@matt2e
matt2e merged commit f9a5e6f into main Oct 12, 2026
23 checks passed
@matt2e
matt2e deleted the baxen/model branch October 12, 2026 03:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants