[release] v0.118.4 - #6923
Merged
Merged
[release] v0.118.4#6923
Conversation
Onboarding created the agent first and left connections to the builder, which asked for them mid-run via request_connection — one per turn, several turns in. Add a setup step between describing an agent (or picking a template) and creating it: the accounts it will need, connected while it is still a draft. Template-declared integrations gate Create; accounts detected from free text never do. The frontend can only string-match a description, so a guess is allowed to offer and never to obstruct — requiredAccounts() returns only template-declared entries, so the rule holds in the types, not just the UI. Detection is pure and network-free (detectAccounts), so a backend that plans the account list pre-commit can replace the text half behind the same return type. Word boundaries alone were not enough: "linear algebra", "the notion that" and "cut some slack" are all whole-word hits, so a small per-slug negative-context table rejects the idiomatic readings. The step's answers reach the agent through the seed message, written in the user's voice — it renders in the transcript as their own first turn. The config-write alternative does not exist for this step: a gateway tool is per-action, and choosing actions is the builder's job via discover_tools. AccountRow is extracted from TemplateSetupDrawer's IntegrationRow rather than duplicated, so the drawer and the new card render one row. Behind NEXT_PUBLIC_AGENT_CONNECT_STEP (default on); off restores instant create on every path. Mid-run request_connection is unchanged and remains the safety net for anything skipped. Design workspace: docs/design/onboarding-connect-step/ Closes #6043
…its first run Wires the pre-create connect step into /m behind the same NEXT_PUBLIC_AGENT_CONNECT_STEP flag the desktop reads, via lib/connectStep.ts (the browseLayout.ts precedent — mobile may not import @/oss/*). /m's first run offered three plain text chips and a "Browse templates" button where the desktop offers the real template strip. It now renders the shared TemplateCard with the category filter and the desktop's composer placeholder: a snap scroller on a phone, a three-across grid from lg up, so /m at desktop width is a desktop layout rather than a phone scroller with cards running off the right edge. Four defects live QA caught that the unit tests did not: - The footnote read "Nothing to do here." directly under two Connect buttons; setupStatus returns "ready" there and the copy fell through to the all-set line. - Row subtitles truncated mid-word and every detected row repeated the same sentence. A detected row now carries no subtitle at all; the card's lead says where the rows came from once. Template rows keep their real scope line. - Edit lost the description. The step REPLACES the composer, so setMarkdown ran against an unmounted editor; the text is parked and refilled on the render that remounts it. - The lead claimed "From your description." for a template's declared accounts, which is false — that "description" is the builder message the user never wrote. setupLead now takes fromTemplate.
The desktop's first run redirects into a project-scoped playground on an ephemeral agent (OnboardingEntry -> useAgentOnboarding) so the config pane is live before anything exists: you see and change the model, instructions and tools of the agent you are about to build. /m had none of that machinery — its first run was a plain document that minted and committed on submit, so there was nothing to inspect and nothing to change. /m now mints the same local-only agent up front (useEphemeralAgent) and mounts the real SessionWorkspace around it, with the create surface in the conversation slot until the agent exists. The ephemeral is a normal entry in the workflow molecule, so every entity-id-driven pane renders against it with no special casing; only useAgentEntity's two queries cannot resolve a `local-*` id, which is why the id is passed in rather than resolved from the session. Submitting commits THAT ephemeral (createFromPrompt now takes entityId) instead of minting a second one, so the agent the user configured is the agent they get. The session id is minted once by the screen and shared with the composer, which stages attachments against it, and with the workspace, which keys its panes off it. A failed mint reports itself with a retry that releases the once-guard, rather than leaving the surface spinning — the desktop's equivalent path currently hard-fails on a user-preference lookup and shows only "Couldn't set up your agent".
Four defects in the playground-native port, all found in the browser. The config pane showed Advanced alone — no Model, Instructions, Tools or Skills. The cause is not the mint: the ephemeral is fully seeded and `/services/agent/v0/inspect` returns the right schema, whose `properties.agent` carries `x-ag-type-ref: "agent-template"`. `parametersSchema` enriches such a node by merging in that type's schema, but its query atom sits `pending` forever on this surface — mounted, no request, no error — so the node stays a bare stub with no properties and there are no fields to render. Seeding the type schema under the same cache key gives the enrichment its data; the request now fires (200, 5.9KB) and the pane renders Model and Instructions. `deferInspect` is also dropped: the config pane is the point of this surface and its sections are schema-driven, so the mint waits for the schema it displays. Two nav rails: `SessionWorkspace` renders its own `AppShell` and Home already wraps first run in one. It takes a `bare` prop now for hosts that provide the shell themselves. Editor placement: the create surface stacked from the top. Hero, then a flex spacer, then templates and the composer docked at the bottom, as the desktop does — with the named "Create agent" action in the composer's trailing slot instead of a bare send arrow, and the desktop's category counts.
Two layout defects in the templates row, both measured in the browser.
The card's monogram overhangs its top edge by 20px and carries a 2px ring, so
`pt-5` left it flush: the ring sat 1px from the row's top and clipped. `pt-7`
gives it 9px of clearance.
The grid overflowed its container by 25px, cutting the cards off on the right.
A grid child defaults to `min-width: auto`, so the card's footer string
("2 GitHub tools · On release") set a min-content floor the track could not
shrink below. `lg:min-w-0` lets the columns size themselves; they now resolve to
three even 285px tracks inside the 880px column.
…track The cards did not line up: in a three-column grid whose tracks measured an even 285.3px each, the cards themselves came out 307 / 295 / 311px, and each one's right edge crossed its neighbour's left. Narrow categories were worse, because the overflow scales with the footer string. `TemplateCard` is a flex container, so it defaults to `min-width: auto` and its own min-content width wins over the track it is placed in. `w-full min-w-0` lets the track govern; the three cards now measure exactly 285px with even 12px gaps, no overlap, and the `truncate`/`line-clamp` inside finally take effect instead of pushing the box wider. Verified in the browser across every category filter (3 cards, identical widths, overlap=false) and in `TemplateGallery`, the other consumer, where all 28 cards render a uniform 435px with no overlap.
There is exactly one draft session before the agent is created and no history to switch to, so the strip was a rail with nothing in it.
The desktop strip can be dismissed ("Don't show again") and restored from a
"Templates hidden · show again" line; /m had neither. Same localStorage key, so
the preference is shared across both surfaces rather than one per app.
…next At lg the cards now page 3-at-a-time behind a "1-3 of 28" counter and chevrons, so the full set is reachable instead of three cards and a Browse link. Every card stays mounted; only the window changes, so the narrow snap scroller is untouched and the pager hides below lg where there are no discrete pages.
…olumn The gallery is already shared, but /m put the page cap and gutters on its header only, so the card grid below ran past the viewport and clipped the right column. Both boxes now carry them, as pageWidth documents and as the desktop's PageLayout already did. /m also never rendered the page's subtitle; the toolbar frame leaves that to the host, so the copy moves into @agenta/home-ui and both hosts read it from there rather than keeping a second literal. Also gives the gallery's toolbar column min-w-0: a flex child defaults to min-width:auto, so its grid could push the row wider than the page regardless of who hosts it.
… row At lg the label, category chips and controls now share one row like the desktop strip, instead of chips wrapping to a second line under them. Below lg there is no width for that, so it stays two rows and the chips keep bleeding to the screen edge; lg:contents is what lets the chips sit between label and controls at lg while those two still share a row of their own on a phone.
…first run First run leads with the question and the composer; a form for an agent that does not exist yet does not need half the screen, and the pane is one " " away. Expressed as a third default in resolveConfigPanelCollapsed rather than a flag in the component, because that function already owns "the default when nothing is stored" — so a stored preference still beats it exactly as it beats the phone default, and opening the pane here never writes over what was chosen elsewhere.
…the tab strip The reveal only ever existed as the tab rail's leadingExtra, so hiding the strip on first run and collapsing the pane by default combined into a one-way door. Extracted as ConfigRevealButton with two homes: the rail, where the pane disappeared from, and the workspace column itself when there is no rail.
…way back A lone chevron on empty canvas reads as decoration, not as a control. Where there is no tab rail to give it context, the reveal now sits in the top bar's actions slot as a labelled "Configuration" button; the rail keeps the compact icon, which its row of neighbours already explains.
…e left behind Reverts the top-bar detour. The empty strip beside the chat IS where the pane was, so it becomes the pane's collapsed edge: a rail that says "Configuration" and takes the whole strip as its target, rather than a chevron floating in dead canvas. md and up only — a phone has no column to spare, and its reveal is unchanged.
…nnect-step # Conflicts: # web/mobile/src/features/chat/SessionWorkspace.tsx # web/mobile/src/features/onboarding/FirstRunComposer.tsx # web/packages/agenta-entity-ui/package.json
…ort and by intent Two reports, one cause: whether the config pane shows was a single sticky global that no context and no action could speak for. #6378 — one localStorage key served every breakpoint. Opening the pane on a desktop stores false, and a stored value beats the per-device default in both directions, so the same browser at phone width opened the pane over the whole screen and hid the playground. The preference is now per breakpoint; the wide one keeps the original key, since a value stored before the split was almost certainly set on a desktop and still means what it meant there. #6381 — the agent overview's Edit navigated to the playground and nothing else, so anyone who had ever collapsed the pane (or left Build/Chat maximized) landed there with no configuration in sight and nothing saying why. Edit asks for the configuration, so it now clears both things that hide it. resolveConfigPanelCollapsed keeps its signature — only the choice of WHICH stored answer to hand it moved — so the host default the onboarding surface layers in is untouched.
The mobile overview passed no onEditConfig, commented 'configuration is edited in the desktop playground'. That stopped being true: a session IS the playground on /m, with the same config pane. The comment outlived the constraint, so the Edit action was missing for no reason. Edit opens a BLANK session for the agent — the id is client-side and nothing reaches the backend until a message lands, so reading the configuration costs no session (verified: the landing session is absent from /sessions/query). The reveal itself moves into revealConfigPaneAtom, shared by both hosts' Edit. Two persisted flags hide the pane and an action promising configuration has to clear both; having written that logic twice was how #6381 could be fixed on one surface and not the other.
…the step opened The connect step docks above the composer and leaves it editable, but Create committed the seed captured when the step opened — an edit made while choosing accounts was silently dropped, template provenance included. Re-read the live composer at Create and resolve the template name against that text.
…nboarding-connect-step
…isibility # Conflicts: # web/mobile/src/features/agents/AgentOverviewScreen.tsx
… tests CodeQL js/insecure-randomness: generateLocalId's Math.random reached the first-run composer's entity id. Same shape, same `local-` prefix, crypto-backed source. The three setup test files also failed the repo-wide prettier check.
…o ask Ashraf's report: writing a description and pressing Create produced a card saying "We didn't spot a specific service in your description" and "Nothing required." — a blocking step announcing it was not needed — with a second "Create agent" button below it. Two changes: - open() now reports whether detection found anything, and every host commits straight through when it did not. The step interrupts only when there is a concrete account to connect, which is when the interruption pays for itself. - the composer is hidden while the card is up, as it already is on /m. Leaving both up put two identically-labelled Create buttons on screen, and the composer's one merely re-opened the step it was already showing, so the button the user reaches for first appeared to do nothing.
A template's providers were two hand-kept lists: requiredIntegrations (what gates) and logoSlugs (what the card draws). Neither could say that GitLab STANDS IN FOR GitHub, so the PR reviewer drew both marks, listed only GitHub, and its setup step demanded GitHub of a GitLab user. TemplateConnection names the slot by what the playbook needs it for and holds the interchangeable options, which is what the playbooks have always said in prose: "GitHub (or GitLab) to read the diff", "Slack or Discord are optional". Card marks are now DERIVED from the slots, so a logo cannot advertise a provider no slot accepts. Additive for now: templateConnections() reads an unmigrated template as one required single-option slot per integration, so the other 27 are untouched until they move over and the legacy fields go.
pr-reviewer now states its slot and nothing else — the legacy requiredIntegrations twin is gone, because keeping both let a template disagree with itself: a test fixture overrode the legacy field on a migrated template and the override was silently ignored. Every consumer reads templateConnections() instead, so a migrated and an unmigrated template are the same thing to a caller. - the detail page labels a slot with every provider that satisfies it — GitHub or GitLab — and lists optional slots separately instead of dropping them - detectAccountGroupsFromTemplate exposes the options so the setup card can offer the choice; the flat view keeps returning the primary, since an alternative rendered as a second row reads as more work, not a substitute - tools front the primary option only, for the same reason
A new session from `+` or the shortcut, and a switch to an existing one, put the caret in the composer once it can take input. Not while the caret is already in another field: a self-commit remounts the screen mid-edit in the config pane.
The composer already knew it had no hardware keyboard — it hid the shortcut hints on that — but `submitOnEnter` stayed at its default, so a phone's Enter sent the message with no way to make a newline. It now follows the same test: Enter sends only where Shift/⌘ can be held; on touch the send button sends and Enter inserts the paragraph.
The composer bound the head of a newest-first roster, so a workspace with two agents opened every visit on the one created last, whichever was in use (#6741). The start is what is remembered, per project, on this device; HomeFocus takes it as preferredAgentId and falls back past an agent no longer listed.
…select text A session opened before its row landed rendered a chip with no context menu, so a right-click on it did nothing and the menu read as broken; repeated clicks on any chip painted its label (#6379). The rail's close verbs move to railTabMenu.tsx so the unlisted chip can offer them without a row view-model, and the chip is select-none, with a rename input keeping its own selection.
…le does The composer's export is markdown with Lexical's escapes in it, so a literal render showed hi\_name for a typed hi_name. Through the same pipeline the assistant uses, minus the typewriter.
It was colorTextLightSolid — white on both fills. colorBgContainer is white on the light theme's ink and ink on the dark theme's yellow, the pairing Home's send already uses.
…own branch markdownIcons lives on the files-pane branch, which this one does not sit on; CI's typecheck had no such name.
…lidator useProjectWatch now calls invalidateAgentCommittedRevisionCache on a workflow change; the desktop suite's mock of @agenta/entities/workflow lacked it.
Every mounted sub-app under the services container answered 404 to an
authenticated request. /services/health worked, so the container looked fine,
but /services/agent/v0/* — invoke, inspect, runtime/subscription-status — all
returned {"detail":"Not Found"}. On /m that surfaces as an agent that is
created and then cannot run: the first message comes back "was not sent".
The prefix is handled twice already. Traefik strips /services before the
request reaches the container (services-strip), and the app strips it again
itself for ingresses that cannot rewrite paths
(ServicesPrefixStripMiddleware, added in #6702). Passing --root-path /services
on top of that breaks routing into the Mount()ed sub-apps.
Proved by running the same app inside the same container on a second port
without the flag: the identical authenticated request returns 200 with a live
runner body for both /agent/v0/... and /services/agent/v0/... path shapes.
The api container keeps its --root-path /api: it has no mounted sub-apps, so
the same interaction does not arise there.
Home's template rows bound the composer to a whole template but sent only its NAME on submit, so a template picked there was the one create path the session could not gate: the key never reached the stashed task, and the connect step had nothing to look up. HomeFocus already read binding.template.key a few lines below, so this is that same value through three signatures — HomeFocus, useHomeHandoff, and createFromPrompt, which hands it to run() where templateKey was already supported and already stashed. Free text on Home stays ungated on purpose. It declares no accounts, the builder decides its tools during the very turn being held, and the mid-run connect dock covers what it turns out to need. All four create paths now behave the same: template entries ask for the template's accounts in the session, free text does not, and the step runs in exactly one place.
Six cases for useSessionSetupStep, the one piece of this flow with no coverage. The step's own rules live in useAgentSetupStep and are tested in entity-ui; what is this hook's own is narrower and is what these assert: it reads the template key off the stashed task, waits for the connections query before deciding, and reports blocking so the held first message is not sent under it. The two that would bite in production: a session with no template never holds, and a step that declines to open releases at once rather than parking a message behind a card that never appears. Note for anyone running these: use `pnpm exec vitest`, not `npx vitest`. npx resolves the workspace-root vitest, which has no jsdom, and the seven jsdom suites are then skipped silently — 28 files instead of 35.
Retargets off release/v0.118.1, which is finished — zero commits ahead of main, 39 behind, nothing open on it. release/v0.118.2 is the live one. One conflict, in SessionWorkspace.tsx, and both sides were keepers. Ashraf's "automation row actions run and open history on /m" added useTriggerTestRun; ours replaced the plain configPanelCollapsedAtom read with the resolved collapse state (override, preference, viewport). Kept the hook and kept the resolved state, since it supersedes the read the other side still used. pnpm install: the release branch added sonner, which the app-message store and the toast component now import.
Contributor
|
Important Review skippedBot user detected. To trigger a single review, invoke the ⚙️ Run configurationConfiguration used: Repository YAML (base), Organization UI (inherited) Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
[feat] Fold each mobile turn into one activity timeline
… draws a landed chip twice Review: keepPreviousData held the previous set's pages while a new set loaded, so a tab closed a moment ago could leave useSessionTabRows. And the commit a row landed in drew its chip from both the rows and the unlisted state, one effect late. The rows filter at the hook; the rail derives what it renders synchronously.
…he task Review: a start whose navigation was cancelled restored the draft but had already written the memory.
Contributor
Author
Railway Preview Environment
Updated at 2026-09-17T12:12:49.462Z |
[fix] Session tabs on /m stay put, follow renames and revisions, and close cleanly
… into fix/config-pane-visibility # Conflicts: # web/mobile/src/features/agents/AgentOverviewScreen.tsx
… into fix/config-pane-visibility
[feat] Ask for an agent's connections when it is created [AGE-4134]
Contributor
Author
📘 Docs preview
This comment updates in place on every push. |
ashrafchowdury
approved these changes
Sep 17, 2026
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.
New version v0.118.4 in