feat(composer): move Conversation Mode to the composer, delete the drawer - #1079
Merged
Merged
Conversation
…awer Step 5 of docs/specs/customize-surface.md. The settings drawer and its icon are gone; everything it held now lives where it belongs. Skills and Tools left for Customize in step 1 because they are global. Mode could not follow them: it applies to THIS conversation, and putting it on a global page would have recreated the exact scope lie this epic exists to fix. So it went the other way, into the composer beside the model and effort controls — those three are the same question, how should this conversation run. The old passive chip, which could display an active mode but never select one, is replaced by a picker that does both.⚠️ The plan said retire Modes in step 6 as "a strictly weaker Agent", on the premise they were dormant. The premise was wrong. Prod carries one enabled mode — Guided Learning, a Socratic tutoring prompt — and use is accelerating: 1 session in July, 20 in August, 60 in the first 12 days of September. Deleting the drawer without this would have removed it outright.⚠️ Fixes a latent bug found while verifying the picker. The session page hydrates the active mode twice on load: provisionally, before metadata arrives, then for real. The provisional call claimed the session id, so the clobber guard rejected the real hydration. Because chat-request sends selected_prompt_id from activePromptId(), the mode silently stopped being applied to every turn after a reload while the stored preference still said it was on. The provisional call now passes claim:false; a deliberate "None" still claims, so stale metadata cannot undo it. Fixed here rather than deferred because this change promotes the control to a first-class composer affordance, and shipping it more prominently while knowing it silently drops would be worse than leaving it alone. No composer pointer to Customize: the sidenav entry is the path, which is what the removed icon's replacement would otherwise have been. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Sep 13, 2026
Merged
raoakkineni
pushed a commit
to AuraWorx/auraxai-agentcore-public-stack
that referenced
this pull request
Sep 22, 2026
Clicking a tool in Customize → Tools now drills into `/customize/tools/:toolId`, which carries what a browse card cannot: the full description, an MCP server's tools one by one with their own switches, the prompts and resources the server exposes, and the catalog facts behind it. Step 5 (Boise-State-Development#1079) deleted the composer drawer, so between that merge and this page there is no per-sub-tool surface anywhere in the app — a user who wants 3 of Canvas's 48 tools has nowhere to say so. This closes that. The page descends from the drawer's `ToolDetailComponent` but is a new component, not a port, for the reason the Customize list is not a port of the drawer's list: the drawer was conversation-scoped (`isToolShownEnabled()`, writes through the Agent lock) and this surface is global (`tool.isEnabled`, `respectAgentLock: false`). Reusing it would reopen the agent-lock seam the spec exists to close. The drawer's tab strip did not come along. Tabs existed because the pane was 320px; on a page, Tools / Prompts / Resources / About are stacked sections, so find-in-page reaches all of them. The problem tabs were solving — a 48-tool server — is solved directly: above eight sub-tools the list grows a filter box. Prompts and resources stay a read of the stored capability snapshot rather than a live probe (probing opens an MCP session per server, and a 3LO server needs a consent token the browser does not hold), and stay read-only (acting needs `prompts/get` / `resources/read`, which this surface has no endpoint for). The snapshot is fetched only for `mcp_external` tools — nothing else has a server that could be asked. Colored text uses `text-primary-accessible dark:text-primary-accessible-dark`. The numbered ramp fails WCAG AA here: with the brand primary at #0033a0, `dark:text-primary-400` measures 2.59:1 against the dark page background, where the accessible alias measures 4.52:1. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
raoakkineni
pushed a commit
to AuraWorx/auraxai-agentcore-public-stack
that referenced
this pull request
Sep 22, 2026
`dark:text-primary-400` resolves to #1e53c1, which fails WCAG AA in dark
mode. The repo already generates `--color-primary-accessible-dark`
(#437cee) for exactly this, and src/branding/README.md §7 documents the
pairing: `text-primary-accessible dark:text-primary-accessible-dark`.
Swaps the 6 remaining legacy occurrences across 4 files. Measured with
getComputedStyle against each site's real composited backdrop, in both
themes (light is unaffected: all 6 sit at 10.6:1 on white, except the KB
tint at 6.7:1).
before after threshold
agent-form +Add (text) 2.23 3.90 4.5 ⚠
agent-form Show details (text) 2.23 3.90 4.5 ⚠
create-training-job check (icon) 2.59 4.53 3.0 ok
knowledge-base sparkles (icon) 2.48 4.31 3.0 ok
mode-picker check (icon) 2.14 3.74 3.0 ok
⚠ The two agent-form buttons are the only real *text* of the six, and
they sit on a `dark:bg-gray-800/80` card rather than the page background.
The token is generated by findAccessibleLightnessDelta against the
resolved dark *surface* (gray-900, #101828), where it clears AA at
4.53:1. On the lighter card it lands at 3.90:1 — better than the 2.23:1
it replaces, and past AA-large, but still short of AA for text-xs/5.
Flagged rather than silently accepted: the fix belongs in the generator
(a card-surface variant), not in a one-off override here, since every
accessible-dark text on a gray-800 card has the same ~0.6 shortfall.
The four icon sites all clear the 3:1 non-text bar; three of them are
aria-hidden decorative anyway, with state carried by aria-checked.
The 5 other occurrences named in the original sweep are already gone:
71a8901 (Boise-State-Development#1079) deleted the model-settings drawer and the chat-input
attachment button along with it.
Co-Authored-By: Claude Opus 5 <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.
Step 5 of
docs/specs/customize-surface.md. The settings drawer and its icon are gone. −2293 / +461.The spec had Modes retired in step 6 as "a strictly weaker Agent", on the premise they were dormant (untouched since PR #411). They are not. Measured against the prod account:
Deleting the drawer as written would have removed a growing, pedagogically-meaningful feature outright.
This is the second time "git history says dormant" has misled on this epic — step 3's
thinkingparam was the inverse, declared incurated-models.tsand absent from the deployed records. Check the data in the environment that matters.Where Mode went
Skills and Tools left for Customize because they're global. Mode couldn't follow: it applies to this conversation, and putting it on a global page would recreate the exact scope lie this epic exists to fix.
So it went the other way — into the composer, beside the model and effort controls. Those three are the same question: how should this conversation run. The old passive chip (which could display an active mode but never select one) is replaced by a picker that does both, with "None" carrying the chip's dismiss role. It renders nothing until an admin authors a mode, so most deployments see no new control.
That also reframes step 6 as reconsider, not execute: retiring Modes is hard to justify against growing use, and the migration isn't clean — a Mode applies to the conversation you're in; an Agent is a separate thing you start a chat with.
The session page hydrates the active mode twice on load — provisionally (before session metadata arrives) and then for real. The provisional call claimed the session id, so the clobber guard in
hydrateFromSessionrejected the real hydration.Not cosmetic:
chat-request.servicesendsselected_prompt_idfromactivePromptId(), so after any reload the mode silently stopped being applied to every later turn while the stored preference still said it was on. On prod that's every Guided Learning user who reloaded mid-conversation.The provisional call now passes
claim: false. A deliberate "None" still claims, so stale metadata can't undo it — that edge has its own test. Fixed here rather than deferred because this change promotes the control to a first-class affordance; shipping it more prominently while knowing it silently drops would be worse than leaving it alone.Open question, resolved
No composer pointer to Customize. The sidenav entry is the path — always visible, one click, the same shape Claude uses. Adding one would have reintroduced an icon to replace the one this removes.
Verification
ng test— 2805 passed; 14 new (8 picker, 6 hydration regression including the "None isn't clobbered" edge).tsc --noEmitclean.aria-label→ "None" returns it → selection persists to session preferences ({"selectedPromptId":"zz-picker-test"}) → survives a reload (the bug above, before and after). Test record deleted and local.envrestored afterwards; dev is back to zero modes.Note
DYNAMODB_SYSTEM_PROMPTS_TABLE_NAMEis unset in the local.env, so the repository disables itself and returns[]silently — worth adding to.env.example, not done here.🤖 Generated with Claude Code