Commit Graph
8981 Commits
Author SHA1 Message Date
Diego ImbertandClaude Opus 5 5b99cce175 fix(drafts): finish settling a write before anything reads it, and follow late landings
Timing the fan-out against the settle was the wrong direction. The settle now
sends its own delete and resolves when it has gone out, so the editors report —
and the schedule host remounts — on a cell that is already resolved: a stalled
delete used to let that remount load the draft the save had just replaced, and
restore it over the deployed value.

A write can still land after all of that, when an edit made during the save is
kept. A list frame reads its rows from a store of its own and nothing reloads it
again, so it now reloads on the write landing rather than on our guess about
when it will.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-06 14:27:08 +02:00
Diego ImbertandClaude Opus 5 08386433aa fix(sessions): send a write's settled draft before the list frame re-reads it
The settle that follows a write parks its draft delete on the autosave debounce,
so the list frame reloaded straight after read the row's `*` and kept it: its
markers come from a store inside the iframe, and nothing reloads it a second
time when the delete lands. The fan-out sends what is parked for the key first.

That needed the variable save to report after settling rather than before —
reporting first meant there was nothing parked yet to send, and the flush passed
over a cell about to queue a delete. Every editor now resolves its cell before
saying so.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-06 13:51:09 +02:00
Diego ImbertandClaude Opus 5 8b99650d4b fix(sessions): reload a list tab a hosted editor's write changed, and treat a restore as one
The fan-out matched only tabs holding the item, so a bare list frame — which has
no row in its location to match — was skipped, and a save, rename or removal made
in a hosted editor left it showing the old rows and draft markers. It reloads,
the way a chat mutation on that page already made it.

Restoring a version replaces the deployed value as squarely as a save does, but
only the reporting editor heard: the other tabs kept the pre-restore value and a
baseline that would write it back over the restored one. It reports too, under
the workspace the history was pointed at.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-06 10:51:21 +02:00
Diego ImbertandClaude Opus 5 35ca2da8c9 docs(drafts): trim the create-enabled comment and close the gap a removed method left
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-06 10:24:56 +02:00
Diego ImbertandClaude Opus 5 bfc9db5dfd fix(drafts): settle what a schedule toggle queues, and void a removal marker any write outlives
Toggling enable writes the form before awaiting the deploy, so the autosave
queues a draft against the pre-toggle baseline. Advancing the baseline on
success then made that draft equal to it — invisible to the banner, still a row
on the server and a `*` on the list. It is settled now, keeping an unrelated
edit made during the request the way a save does.

A draft-only removal marker was only ever voided by a chat write, so one left
unread — discarded outside a session, where nothing consumes it — could be spent
by an ordinary discard on a path since recreated, sending live editors away from
an item that exists. Every write that gives the item a draft again voids it,
which is also what `persistGlobalDraft` was doing by hand.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-06 10:08:35 +02:00
Diego ImbertandClaude Opus 5 069d66627d fix(schedules): let the create's enabled state reach the form only if nothing changed it
Adopting it unconditionally overwrote whatever the field held by then, so a
write landing during the request — the chat seeding the cell — was erased before
anything could notice it had, and settled away as if it were the save's own.
What was written still records `true`, since that is what the create sent; the
form follows only while it still holds the value that went with it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-06 09:41:47 +02:00
Diego ImbertandClaude Opus 5 fcb25ce416 fix(schedules): adopt the enabled state a create deploys
Creating a schedule sends `enabled: true` whatever the form held, so a
draft-only save left the form and its new baseline recording a state the server
does not have — visible once a kept edit skips the remount that used to hide it.

Also moves the settle comment in VariableEditor back onto its call.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-06 09:21:21 +02:00
Diego ImbertandClaude Opus 5 ba654d594f fix(sessions): identify the reporting tab by its session too
Tab ids are unique within a session, but the seeded first tab is `session` in
every one of them — so a same-path save made from one skipped the refresh in all
the others, leaving those editors on the baseline the deploy replaced. The
exclusion carries the session it came from.

Also drops the acting-workspace explanation left above `written`, which reports
every workspace the save wrote.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-06 09:00:01 +02:00
Diego ImbertandClaude Opus 5 9c20945ad4 fix(schedules): report what a write actually left diverging, and adopt what it deployed
The enable/disable request carries the enabled flag alone, but claimed to leave
nothing behind — so the host remounted, and a summary or args edit still sitting
on the autosave debounce went with it. It now reports the form's real divergence
from the baseline it just moved.

A save also left `edit` and `draftOnly` to the remount, which is exactly what a
kept edit skips: a draft-only schedule created while the user typed stayed in
draft-only mode, with its path still editable and its next save a create. They
follow the write that deployed it instead.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-06 08:39:41 +02:00
Diego ImbertandClaude Opus 5 0dd7508eb6 fix(editors): restore the failed-save guard the widened return broke, and stop remounting over a kept edit
`save()` now answers with the workspaces it wrote, and an empty array is truthy —
so the MCP section's `if (!(await save())) return` stopped guarding, and a failed
save ran the enablement bookkeeping its own comment says must not run. It asks
for the length.

The page declined to remount the tab that reported a save, but that tab was
remounting itself: the resource host on every save, the schedule host likewise.
The resource never needed it — its editor adopts the written value as its own
baseline — and the schedule remounts only when the save kept no edit, which is
the one case where re-reading is what the editor wants.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-06 08:11:09 +02:00
Diego ImbertandClaude Opus 5 c7faaf1956 fix(sessions): report a write per workspace, and leave the reporting editor alone
The same-path refresh reached the tab that did the save, remounting it over the
edit its own settle had just preserved — the teardown's flush and the fresh
editor's read race, and the older value can win. The reporting tab is skipped:
it has settled its own state, which is what the report is telling everyone else.

A save can also write several workspaces while only one event went out, labelled
with the acting one, and a discard deletes the draft of whichever workspace the
form is showing while claiming the acting one — so a linked workspace's tabs kept
a replaced baseline and the wrong tabs were closed. Each write now reports its
own workspace and the path it wrote there, which retires the acting-workspace
bookkeeping that stood in for it.

A tab re-pointed mid-write no longer swallows the report either: only the local
remount was ever its to suppress.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-06 07:23:13 +02:00
Diego ImbertandClaude Opus 5 21ca77e415 fix(sessions): tell every tab on an item about any save, not only one that moved it
Editors on the same item share its draft cell but each keeps its own deployed
baseline, so a save made in one left the others offering to discard back to the
value it replaced — over a deployment. A save now reports the path it wrote to
whether or not that moved the item, and the tabs on it that stayed put are
re-read instead of re-pointed.

The variable drawer reopens on the committed path after a partial multi-workspace
failure rather than re-keying: re-keying brought its handles back from the values
the drawer opened on, which describe neither what the committed workspace has
deployed nor the draft the failed one still holds.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-06 06:48:17 +02:00
Diego ImbertandClaude Opus 5 345f40affb fix(sessions): move every tab on an item the editor renamed or removed, not just its own
Warm sessions share one draft cell and one server row per item, so a rename or a
draft-only discard made in one left the others editing a path that is gone. The
editor's report now goes to the page, which re-points every tab on that item in
that workspace — the same fan-out the chat tools already use.

Matching on the item is also what the host's own staleness check was for: a
report that lands after its tab has been re-pointed simply finds nothing to
match, so `stillShowing` goes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-06 06:18:45 +02:00
Diego ImbertandClaude Opus 5 9d7b06ecc4 fix(drafts): stop the landed-delete fact from outliving the server state it described
The fact is sticky by design, so a delete that landed earlier for a key kept
answering after the server moved out from under it: a discard that conflicted
left it standing, and the conflict itself is tracked apart from the state the
verdict reads, so both said the draft was gone. It is dropped now wherever the
server stops being ours to describe — on a conflict, and on a remote resync.

Also corrects what the partial-save comments claim. Following the committed
rename re-keys every workspace's handle, so a workspace whose write never
happened does lose sight of its draft in this editor; the draft is still on the
server under the path that workspace holds the item at, which is where it stays
reachable. Saying it stayed reachable here was wrong.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-06 05:39:17 +02:00
Diego ImbertandClaude Opus 5 7a7e30de87 fix(drafts): decide a delete landed from the response handler, and from nothing being queued behind it
The draft hint has a second writer: every editor clears it from an effect as
soon as a workspace sits at its baseline, which a discard does synchronously —
so a delete that then failed read as one that landed, and the host left on an
item still there. `postSave` now records which payload last landed for a key,
a fact only it can write, and the verdict reads that.

A delete winning is also not enough on its own. The form stays editable while
the flush is in flight and a flush only submits what it read at its start, so an
edit made in between sits on the debouncer and would recreate the draft behind
the host's back. The key has to be idle too.

The variable drawer no longer closes when a save failed partway: that is the
case where the workspace still needing one is retried from it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-06 05:19:32 +02:00
Diego ImbertandClaude Opus 5 83cd40a6dd fix(editors): confirm a draft is gone from what landed, and follow a rename that committed
The discard verdict read the sync pipeline's own state, which settles whichever
write it ends up sending: the form stays editable after Discard, so typing then
replaces the queued delete with an upsert and the pipeline reports success for
it. The draft-state hint is written by the POST that actually landed, so it
answers what the pipeline cannot — whether the draft is still there.

A multi-workspace save writes in sequence and a later workspace throwing aborts
the rest, but what the acting workspace wrote is deployed either way. Both saves
now report that path, so a host is never left pointing at one the item has
already moved off.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-06 04:55:50 +02:00
Diego ImbertandClaude Opus 5 1381536ec6 fix(editors): report a removal only once its delete lands, and a rename only from the acting workspace
A discard queues its delete through the autosave debouncer and returns, so the
host left for the list while the row was still there — and left just the same
when the delete failed outright. The three callbacks now wait for it and report
removal only when it landed; a delete that didn't means the item is still there.

`WsSpecificVersions` can point a form at a linked workspace, where a rename is
that workspace's alone. Both editors took the saved path from whichever version
was selected and handed it to a host acting on another one, and settled every
workspace's draft against that single path. The reported path now comes from the
acting workspace's own write, and each workspace settles against its own.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-06 04:36:18 +02:00
Diego ImbertandClaude Opus 5 67c1faed53 fix(editors): read what a save sends before it is sent, and settle its draft in one place
The resource save read its snapshot back out of the live form after the request
returned, so the "did anything change meanwhile" test compared the edit against
itself and always said no — the mid-request edit became the deployed baseline
instead. Its payloads, its submitted path and the schedule's config are now all
pinned before the first await, which also makes the schedule's test see edits to
`args`, `retry` and `labels` rather than only its scalar fields.

The three copies of the settling rule become `settleDraftAfterWrite`. A save
that moved the item resets the cell rather than keeping a diverged one: the edit
cannot follow — a freshly acquired cell reads only its own default — and the
alternative is a draft stranded under a path the item no longer occupies.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-06 04:07:20 +02:00
Diego ImbertandClaude Opus 5 0635901e7f fix(editors): keep an edit made while a save is in flight, and land baselines per workspace
The forms stay editable during a save, and the post-write reset dropped the
local draft back to the state that was sent — so anything typed in between
vanished when the request returned. The draft is now dropped only while it
still holds what was written; an edit on top of the save survives as the
unsaved change it is, and the hosts that remount pick it back up.

A multi-workspace variable save also adopted its baselines only after every
write had succeeded, so a later workspace throwing left an earlier one's draft
dropped below a baseline that never moved: dirty forever, and retried as a
create it had already made. Each lands as its own write does.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-06 03:32:53 +02:00
Diego ImbertandClaude Opus 5 8df960ebd2 docs(sessions): trim three comments and drop a claim the per-item keying made false
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-06 03:15:36 +02:00
Diego ImbertandClaude Opus 5 8202413bb9 fix(sessions): mount a hosted entity editor per item, and scope its reports to its workspace
The schedule and variable views re-pointed one live editor at each new path, so
the previous item's load — `openEdit`, `editVariable` and everything they await
— finished into the new item's form, baseline, draft cell and permissions,
last response winning. Keying each on its path gives every item its own
instance, with nothing of the next one's to land on. The resource host already
worked this way.

A report's guard also matched kind and path but not workspace, so re-scoping an
unsent session left a rename from the old workspace free to retarget the new
one's tab onto a path that exists only where it was written.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-06 03:02:34 +02:00
Diego ImbertandClaude Opus 5 5373cc2984 fix(sessions): stop a stale write from landing on the item the editor moved to
Guarding the host was not enough: an editor's own continuation runs first, and
every piece of state it touches after the await belongs to whatever the editor
shows by then. The variable save now pins its payloads, its saved path and its
draft key before the first write and only adopts a baseline while it is still
the variable it saved; the resource save and the schedule remount stop at the
same check.

The host guard also matched on path alone, so a late report about a schedule
reached a resource or variable that happened to share its path. It now matches
the entity kind too, bound at the branch that mounts each editor.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-06 02:42:26 +02:00
Diego ImbertandClaude Opus 5 9b37f57503 fix(sessions): act on an entity callback only while the tab still shows its item
A tab id outlives what the tab points at. An editor reports a removal or a
rename after the write it awaited, and by then the tab may have been re-pointed
onto another item — so the report was applied to whatever the tab held, and the
URL built out of that unrelated location: discarding schedule A and opening
schedule B sent B back to the list. Every such report now carries the path it
started from, read before the await, and the host acts only while the tab is
still showing that entity.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-06 01:58:39 +02:00
Diego ImbertandClaude Opus 5 3f8485060d fix(sessions): send the removed item's own tab back to the list, not the active one
A discard resolves asynchronously — the schedule's awaits a fetch of the
runnable — so by the time it lands the user may be looking at another tab.
Routing removal through `onBack` moved whichever tab was active, taking that
one to the list while the tab whose item was gone stayed on it. Removal now
retargets by tab id, as the deletion and rename paths already do.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-06 01:09:15 +02:00
Diego ImbertandClaude Opus 5 420beeadd2 fix(sessions): leave a hosted editor whose item a direct discard removed, and follow a renamed save
The inline draft banner's Discard calls UserDraft.discard straight off, not the
discard_local_draft tool, so nothing told the tab about it. For a draft-only
item the draft IS the item: discarding deletes its only representation and the
tab kept editing a synthesized stand-in for something that no longer exists.
Each editor now reports whether the item survived, and the session views hand
that back to the tab, which returns to the list it was opened from.

A draft-only schedule also opens with its path editable — saving CREATEs — so
the save can land somewhere other than where the tab points. The schedule host
discarded onUpdate's saved path and only remounted, re-opening the old path;
it now retargets the tab like the resource and variable hosts do.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-06 00:35:37 +02:00
Diego ImbertandClaude Opus 5 947fd6b1cb fix(sessions): spend each write marker only on the tool that wrote it
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-05 21:44:07 +02:00
Diego ImbertandClaude Opus 5 c9c3b23585 fix(sessions): publish the removal marker only once the discard lands
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-05 21:11:16 +02:00
Diego ImbertandClaude Opus 5 98e30f0878 fix(sessions): leave a hosted editor whose draft-only item was discarded
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-05 20:39:01 +02:00
Diego ImbertandClaude Opus 5 82cf519606 fix(sessions): record a missed seed when it happens, not after the write
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-05 20:25:15 +02:00
Diego ImbertandClaude Opus 5 a939a12d11 fix(sessions): refresh a hosted editor a write could not reach
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-05 20:07:49 +02:00
Diego ImbertandClaude Opus 5 f154863061 fix(sessions): keep the tab put when a resource save fails
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-05 19:49:33 +02:00
Diego ImbertandClaude Opus 5 f79160e598 fix(sessions): rebind hosted entity editors on rescope, rename and save
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-05 19:24:05 +02:00
Diego ImbertandClaude Opus 5 ba1ae123fe fix(sessions): scope entity-tab effects to the mutated item, tab and workspace
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-05 18:57:23 +02:00
Diego ImbertandClaude Opus 5 9deb95a63e fix(sessions): keep hosted entity editors correct across retarget, restore and non-write tools
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-05 18:42:36 +02:00
Diego ImbertandClaude Opus 5 1b840dbd7f feat(sessions): offer the way back to the list from an entity editor tab
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-05 15:26:27 +02:00
Diego ImbertandClaude Opus 5 4d9ec4b816 fix(sessions): follow a row opened inside the list frame onto the hosted editor
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-05 14:57:29 +02:00
Diego ImbertandClaude Opus 5 cc8d55eb57 feat(sessions): host schedule, resource and variable editors in process
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
2026-09-05 14:10:40 +02:00
Ruben Fiszelandrubenfiszel c37f59e22a chore(main): release 1.804.0 (#10963)
* chore(main): release 1.804.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-09-05 11:11:54 +00:00
9f7908e262 fix(oauth): show the account chooser on an explicit Google/Microsoft login (#10961)
* fix(oauth): show the account chooser on Google/Microsoft login

Without `prompt=select_account`, Google and Microsoft silently reuse the single
active browser session, so a user with more than one account has no way to pick
which one to sign in with.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0196aV8v36ukoQcD7L2scvmH

* chore: pin ee ref for the oauth login extra_params fix

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0196aV8v36ukoQcD7L2scvmH

* fix(oauth): only ask for the account chooser on an explicit login click

The login page now sends `user_initiated=true` when someone clicks a
provider button, and the backend applies the provider's `extra_params`
only for those requests.

Someone whose browser holds a single Google session whose email is
already registered under a different login type hits
"an user with the email associated to this login exists but with a
different login type" and, with no account chooser, has no way to offer
a different account. The chooser belongs on that click.

It does not belong on the `auto_login_provider` redirect, whose whole
purpose is to sign a public-app or approval-page visitor in without
interaction.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0196aV8v36ukoQcD7L2scvmH

* fix(oauth): make the account chooser the default, not the opt-in

The login page now flags only the `auto_login_provider` redirect, with
`auto=true`; every other login — a click on a provider button, or the
endpoint opened as a plain URL — gets the provider's extra params.

`/api/oauth/login/*` is whitelisted in `public_app_layer` and reachable
directly, so an opt-in flag would silently drop the account chooser for
every caller that is not our own button.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0196aV8v36ukoQcD7L2scvmH

* chore: update ee-repo-ref to f5d6b6b8dd00b0141308337ac97f4685781f2b1c

This commit updates the EE repository reference after PR #776 was merged in windmill-ee-private.

Previous ee-repo-ref: 5684bb0f63dce08d6ce9ab0183072c8b4fce4b2e

New ee-repo-ref: f5d6b6b8dd00b0141308337ac97f4685781f2b1c

Automated by sync-ee-ref workflow.

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
2026-09-05 11:08:27 +00:00
Ruben FiszelandClaude Opus 5 d2019d7b5d only warn about manual action when the username actually changes (#10991)
* fix: only warn about manual action when the username actually changes

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015QT712GyPPXD24rgTdLd9a

* fix: block the rename until the current usernames are known

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015QT712GyPPXD24rgTdLd9a

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-05 11:08:12 +00:00
Diego ImbertandClaude Opus 5 a0295b20c4 fix(frontend): render ordered lists in markdown descriptions (#10973)
* fix(frontend): render ordered lists in markdown descriptions

`GfmMarkdown` defaulted to `prose-xs`, which Tailwind Typography does not
define — the class only ever matched four hand-rolled rules in app.css, all
scoped to `ul`. Every surface on that default (script and flow descriptions,
flow-graph notes, markdown job results) therefore rendered `<ol>` with
Preflight's `list-style: none` and no typography at all: no numbers, no
heading or paragraph rhythm.

Route the default through the shared `markdownProse` stacks instead, and cut
the app.css list rules down to the dash glyph so ordered and unordered lists
share Tailwind Typography's indentation and rhythm.

Fixes #10971

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S6G5gDXJnm6uqch4uCPkPE

* fix(frontend): address review nits on the markdown prose fix

- default `GfmMarkdown` to the `sm` stack rather than `xs`: the AI-agent tool
  Message pane takes the default and has no ancestor font size, so `xs` left it
  smaller than its own label. The group note, whose wrapper is `text-2xs`, opts
  down explicitly.
- regenerate `static/tailwind_full.css`, which raw apps are served and which
  still carried the deleted list rules.
- correct the marker-color rationale: the typography config already maps markers
  to tertiary, so the rule steps them up rather than rescuing them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S6G5gDXJnm6uqch4uCPkPE

* fix(frontend): make the note color override an arbitrary value

`text-inherit` is not generated: this config replaces the Tailwind color palette
outright and defines no `inherit` key, so `[&_*]:!text-inherit` compiled to
nothing and notes still rendered in the prose stack's `text-primary`. Verified in
the browser: a yellow note's list items now compute to `text-yellow-900`, matching
the wrapper and the edit-mode textarea, in both themes.

Also drop the `static/tailwind_full.css` regeneration. That file was generated with
tailwind 3.4.1 against a config predating the typography theme overrides; rebuilding
it today sweeps in 250KB of unrelated churn and would flip every raw app's `.prose`
palette from stock gray to Windmill tokens. Its staleness predates this PR and is
its own change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S6G5gDXJnm6uqch4uCPkPE

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-05 10:39:44 +00:00
GuilhemandClaude Opus 5 1901d3193b fix: keep the instance user editor popover inside the viewport (#10979)
* fix: keep the instance user editor popover inside the viewport

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A5v4NFqdTaZdkR8Ua1nr13

* fix: drop inert flex and min-h-0 classes from the user editor popover

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A5v4NFqdTaZdkR8Ua1nr13

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-05 10:38:44 +00:00
130a2f7408 feat: instrument sandbox isolation, data tables and in-flow script edits (#10981)
* feat: instrument sandbox isolation, data tables and in-flow script edits

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GLnp4v49BozkDd3KeWn5Q3

* fix: address review findings on the new telemetry counters

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GLnp4v49BozkDd3KeWn5Q3

* refactor: inline single-site telemetry helpers and trim what is collected

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GLnp4v49BozkDd3KeWn5Q3

* docs: tighten the telemetry disclosure copy

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GLnp4v49BozkDd3KeWn5Q3

* chore: update ee-repo-ref to 5921c03c8e28642efd1c390f590c0dab9834fa99

This commit updates the EE repository reference after PR #780 was merged in windmill-ee-private.

Previous ee-repo-ref: 548b5e0421a04a2d9a76cce6efc6c91b1d8560ee

New ee-repo-ref: 5921c03c8e28642efd1c390f590c0dab9834fa99

Automated by sync-ee-ref workflow.

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
2026-09-05 10:38:20 +00:00
8aab5034a6 feat: guest JWT entry for embedded apps (#10954)
* feat: guest JWT entry for embedded apps (jwt_guest_)

A second way in for a guest, alongside the signed-in guest session: a JWT the
embedding customer's backend mints and signs, verified per request against a
per-workspace key (a PEM public key or a JWKS URL), resolving to the same
seatless guest identity confined to the one app its app_path claim names.
Bearer prefix jwt_guest_, stateless (no token row). See PR #10954.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat: surface guest JWT as the embed method in the app deploy drawer

The deploy drawer explained the secret-URL embed but not the guest JWT path, so
the primary way to embed an app for a customer's own authenticated users was
undiscoverable. For a guest-mode app with guests enabled, show how to mint a
`jwt_guest_` token and append `guest.<jwt>` to the app URL, with a copyable
iframe template pre-filled with this app's workspace_id and app_path, and a note
that new guest emails are refused past the instance's free allowance (the live
count is shown just above).

Also log a guest JWT allowance refusal at warn, not info: the caller gets a bare
401 (the reason must not leak to an unauthenticated caller), so the log is the
admin's signal that the instance hit its guest cap.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix: correct the guest JWT minting instructions in the embed block

The block said "sign it with the workspace's guest JWT key", but that setting
holds the public verification key. Clarify the keypair relationship (configure
the public key or a JWKS URL in the workspace; sign with the matching private
key), name the accepted algorithms (RS/PS/ES; HS* refused), and keep the
required claims, so an embedder knows how to actually mint the token.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat: fall back to the instance JWT issuer for guest verification (off on cloud)

A workspace with no guest key of its own now verifies guest JWTs against the
instance issuer (JWT_EXT_JWKS_URL, already used by jwt_ext_), so an operator
running one issuer configures it once. Verification and the guest grant are CE;
granting a full login from that issuer stays EE (jwt_ext_, unchanged). Disabled
under CLOUD_HOSTED, where one instance issuer must not be trusted to mint guests
in every tenant's workspace — there the per-workspace key is the only source,
which also stays the override everywhere. The workspace settings note (hidden on
cloud) explains the fallback.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix: embed instructions cover both the workspace key and instance issuer

The embed block said to set the workspace's guest JWT key; now it says Windmill
verifies against the workspace key or, off cloud, the instance issuer
(JWT_EXT_JWKS_URL) when no workspace key is set. The instance clause is hidden
under isCloudHosted().

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix: show the guest JWT embed block only when Embed is toggled

It belongs with the iframe snippet, not the plain-URL view, so gate it on
embedMode alongside the guest-mode / guests-enabled checks.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix: trust the instance issuer in the guest fallback; refresh stale docs

P1 (CI review): the fallback wrapped JWT_EXT_JWKS_URL as a workspace JwksUrl, so
it hit validate_guest_jwks_url and was refused for http/private issuers unless
ALLOW_PRIVATE_GUEST_JWKS_URLS was also set — a self-hosted internal issuer that
works for jwt_ext_ failed for guests, though the UI says setting the env var is
enough. fetch_jwks now fetches the instance issuer without the https/private
restriction (matching the jwt_ext_ loader; it stays operator-trusted), while a
workspace-admin URL is validated and pinned as before. All the size/key/URL
bounds still apply to both.

P2 (CI review): refresh the stale docs that said a missing workspace key always
refuses a guest JWT — the module, bearer, key-source, and EditGuestJwtKey field
docs now describe the workspace key with the off-cloud instance-issuer fallback.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix: fetch the trusted instance issuer like the jwt_ext_ loader

P1 (CI review): the instance-issuer fetch skipped SSRF validation but still
disabled redirects and default cert validation, so an instance issuer that works
for jwt_ext_ through a redirect or an operator-approved self-signed cert failed
the guest fallback. Fetch it with HTTP_CLIENT_PERMISSIVE (follows redirects,
honors ACCEPT_INVALID_CERTS) — the same behavior jwt_ext_ has — while a
workspace-admin URL stays validated, DNS-pinned and redirect-free. The body size
cap still bounds both.

P2 (CI review): the WorkspaceSettings field doc still said None/None means no JWT
guests; it now names the off-cloud instance-issuer fallback.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs: schema summary + OpenAPI cover the guest JWT columns and fallback

P2 (CI review): summarized_schema.txt was missing guest_activity.jwt_entry and
the two workspace_settings guest-JWT key columns (required by docs/validation.md
after a schema change). The edit_guest_jwt_key OpenAPI description now notes that
clearing the workspace key falls back to the instance issuer (JWT_EXT_JWKS_URL)
off cloud rather than necessarily stopping guest JWTs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix: keep JWKS single-flight locks in a self-cleaning map, not a bounded cache

P1 (CI review): JWKS_FETCH_LOCKS was a 200-entry quick_cache. Past 200 cold URLs
it can evict a lock whose fetch is still in flight; the next request for that URL
then mints a fresh lock and starts a second fetch, so cycling configured
workspaces defeats single-flight and can storm the issuers. Replace it with a
plain map guarded by a JwksFetchLock RAII handle that removes each entry once its
last holder drops, so the map only ever holds the fetches in flight and never
evicts an in-flight lock. Add a unit test pinning the shared-lock and
self-cleaning invariants.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: update ee-repo-ref to c2270eb5fe2d9f0968253e6b460c33186363f4e7

This commit updates the EE repository reference after PR #773 was merged in windmill-ee-private.

Previous ee-repo-ref: 5a1d9dee34159512c0823fddcd3d096490edbcce

New ee-repo-ref: c2270eb5fe2d9f0968253e6b460c33186363f4e7

Automated by sync-ee-ref workflow.

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
2026-09-05 10:23:37 +00:00
Ruben FiszelandClaude Opus 5 54287102b2 fix: meter WAC compute per segment, not the whole sleep (#10985)
* fix: clear started_at when a WAC parent suspends

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AzS5d5Dc3GL49kWZPQAQCg

* fix: restore started_at on the WAC dispatch rollback, fail loudly on a no-op suspend

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AzS5d5Dc3GL49kWZPQAQCg

* fix: restore the pulled segment start on the WAC dispatch rollback

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AzS5d5Dc3GL49kWZPQAQCg

* feat: meter WAC execution per segment instead of only the last one

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AzS5d5Dc3GL49kWZPQAQCg

* fix: make the cloud feature self-sufficient per crate

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AzS5d5Dc3GL49kWZPQAQCg

* chore: name windmill-common/cloud directly in the worker cloud feature

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AzS5d5Dc3GL49kWZPQAQCg

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-05 11:11:29 +02:00
Ruben FiszelandClaude Opus 5 ebfac29096 fix: render the MCP OAuth consent page without a workspace (#10988)
Claude-Session: https://claude.ai/code/session_014EeEWKSqcnCEcPKe9uUuHC

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-05 10:05:15 +02:00
fce635d3c4 feat: guest app execution mode, a role that takes no seat (#10929)
* feat: guest app execution mode, a fourth role that takes no seat

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5

* fix: make the guest grant a server-minted label, not a declarable scope

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5

* chore: pin ee-repo-ref to the guest session companion branch

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5

* fix: close the relabel hole, guest embed tokens, read-path switch, custom-path entry

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5

* fix: guest tokens are not rescopable and guest embed tokens keep the sentinel

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5

* fix: guest-derived tokens share one constraint set; gate sign-in on guest discovery

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5

* fix: the label alone governs a guest; refuse guests with accounts; unserialize discovery

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5

* fix: guest discovery fails closed; SAML aborts if the guest cookie write fails

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5

* refactor: enforce the guest switch once at the auth door; sign-in for a guest of another app

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5

* fix: guest app-mode decided once at the on-behalf resolver; clear a stale guest session before offering another app's sign-in

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5

* fix: a guest may use anonymous apps; await the stale-session logout; trim comments

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5

* fix: a guest's path confinement waits for the app's mode, so anonymous apps stay open to it

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5

* fix: guest target survives http (Lax cookie), rides SAML RelayState; tell account holders on arrival

* fix: a guest uses an anonymous app as itself; S3 uploads confined by app mode

* fix: a guest upload needs an app policy; a missing app does not skip the confinement

* fix: guests are gated on the Enterprise plan server-side; pin ee-repo-ref

* fix: the guest plan gate fails closed on non-enterprise builds; settings report the effective switch

* fix: guest controls read the plan, not the key; gate the guest tests on the features they need

* docs: tighten the guest session invariant comments

* feat: 100 free guests per 30 days, then a quarter seat each on Enterprise and a hard cap elsewhere; superadmin guest list; refusals reach the page

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5

* fix: the cap is exact, an account ends a guest session at the door, popups close, and guest mode survives the CLI round trip

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5

* feat: a superadmin switch over guests for the whole instance; the pre-existing-user flag keeps its meaning

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5

* fix: drop the dead guest-access helper, name the instance setting once, guests tab states, CE save order

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5

* fix: a guest app path is refused at the mint if it could widen the scope; the instance toggle waits for its reload

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5

* fix: guests stop at the launched-by-me job grant; canonical app paths at the mint and discovery; the toggle ends on the stored value

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5

* fix: only the scope grammar's own characters bar an app path from guests, refused at deploy as well as at the mint

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5

* fix: the deploy-time guest path guard checks the destination of a rename and refuses a leading slash

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5

* fix: a workspace rename keeps the guest switch; the rename guard reads the deployed mode under the row lock

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5

* fix: guest_activity follows a workspace rename and goes with a workspace delete

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5

* chore: pin ee-repo-ref to the state-bound guest target

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5

* chore: pin ee-repo-ref; the guest cookie is never cleared by a callback

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5

* docs: the workspace-scoped guest_activity delete moves an instance-wide count; assert the mint records the guest

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5

* test: the seeded allowance is a day old, so only the mint can write today's guest_activity row

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5

* chore: update ee-repo-ref to 1a10132e4f3cb442c7d0c2cf6e5d92d150bf6e07

This commit updates the EE repository reference after PR #769 was merged in windmill-ee-private.

Previous ee-repo-ref: 32841072aa396bff91d30bd91854fa348cb3c439

New ee-repo-ref: 1a10132e4f3cb442c7d0c2cf6e5d92d150bf6e07

Automated by sync-ee-ref workflow.

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
2026-09-04 22:47:28 +02:00
hugocasaandClaude Opus 5 f037c73d10 feat(frontend): group the agent form and edit saved agents as drafts (#10880)
* feat(frontend): group the AI agent step form and edit saved agents in a modal

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat: edit a saved AI agent through its own resource draft

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* refactor: drop the agent fork-for-edit session now that edits live in a draft

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat: edit ai_agent resources from the resources page with the agent editor

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix: send a standalone agent's brain from the module when testing a step

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix: keep the agent draft faithful to the resource it deploys to

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* chore: add the sqlx cache entry for the eval subject rename

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* refactor: share the module insert between the graph and the agent editor

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(frontend): open evals inside the agent editor, actions in its header

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(frontend): add tools from the agent editor and lighten its test pane

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(frontend): open an ai_agent deep link in the agent editor

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(frontend): drop the failed result badge on a step that never ran

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(frontend): head the agent editor's levels with a back control

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(frontend): drop connect and fill inputs from the agent editor

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(frontend): lighten the agent editor's run panel

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(frontend): stop a nested agent tool's config reading as AI-filled

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(frontend): offer only AI or static on an agent tool's inputs

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(frontend): give a saved agent's tool editor a static-only surface

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(frontend): open an agent tool in a drawer beside the agent

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(frontend): hide unset agent config in the run form

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* refactor(frontend): share the input forms' pickers and s3 lookup

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* chore(frontend): drop a dead agent-editor export and fix two stale comments

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(frontend): reach an ai_agent's resource-level settings and copilot

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(frontend): open an ai_agent's resource view as JSON, not the generic form

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(frontend): address review findings on the agent editor's draft and streaming

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(frontend): close the agent editor on a version restore, as the resource editor does

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(frontend): stop the provider picker auto-writing a kind, and clear review nits

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* refactor(frontend): drop the fork-for-edit leftovers from the agent card

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(frontend): mount the agent editor in the dev flow editor and guard the deep-link race

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(frontend): deploy the agent config that was submitted, and refuse one no run could use

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* refactor(frontend): build the agent editor's rows from the design-system button

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(frontend): keep a draft-only agent's draft, and let a blank MCP summary deploy

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(frontend): guard read-only agents, incomplete MCP tools and duplicate editor mounts

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix: read-only agent editor, linked-card refresh, atomic eval rename

* fix: eval rename needs the privileged pool, per-workspace write access

* fix(frontend): drop the agent editor target when its mount goes away

* refactor: drop the agent rename work from this PR, unban the bindable defaults

* fix(frontend): refuse a renaming deploy and drop the copilot from static-only fields

* fix(frontend): mirror the worker's streaming rule and scope agent writes to their target

* fix(frontend): read runtime streaming as off and reset the drawer's json view

* fix(frontend): read an unsettled output_type as non-streaming too

* fix(frontend): let the showing modal claim an agent opened from inside it

* fix(frontend): keep in-flight edits, tool replacements and every linked step in sync

* fix(frontend): keep attachments in the run form and bind the agent ref to its tools

* fix(frontend): preview the agent as authored and re-evaluate step args on run

* fix(frontend): scope agent-editor ownership to the flow's workspace

* fix(frontend): drop the tool drill-in where there is no graph to select on

* fix(frontend): require a provider kind and keep one resource editor open at a time

* fix(frontend): keep legacy nulls, static-only text literal, and the handover anchor

* test(worker): pin the agent streaming default

* fix(frontend): let an AI-fillable input be switched to static

* fix(frontend): report agent editor background failures instead of floating them

* fix(frontend): keep the version pane's path alive while the editor closes

* fix(frontend): clear the anchor-keep flag at the start of each drawer session

* fix(frontend): preview the agent without its synthetic path, refresh the baseline on external writes

* refactor(frontend): drop the unverifiable baseline refresh, state the synthetic-path rule

* fix(frontend): keep the synthetic path out of agent tool test runs too

* refactor(frontend): host the agent editor under the agent's own path

* fix(frontend): mark an agent editor's host explicitly instead of inferring it from the path

* fix(frontend): discard linked-agent responses from before a deploy

* fix(frontend): keep a flow mount from claiming an agent editor's nested target

* feat(frontend): keep an agent used as a tool inside the agent being edited

* fix(frontend): reserve the agent editor's root module id

* docs(frontend): record why the agent editor previews under the agent's path

* fix(frontend): refuse to open or deploy a resource that is not an agent

* docs(frontend): put the scope-migration comment on the function it describes

* fix(frontend): refuse an agent path whose resource type is not proven

* fix(frontend): recheck the resource type before deploying, and keep expressions off static-only inputs

* fix(frontend): lazy-load the agent editor and slide its levels like the evals pane

* refactor: drop unreachable non-list tools check from agent deploy

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(frontend): clear text-only agent fields on image output, reserve the root id

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(frontend): keep the agent editor usable for a non-list tools value

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(frontend): stop the parked eval run list from taking arrow keys

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(frontend): report a non-list tools value on deploy instead of throwing

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(frontend): keep temperature editable for image output

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(frontend): skip non-object tool entries when rendering an agent

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(frontend): guard tool entry reads instead of copying the tool array

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(frontend): key tool rows by position so duplicate ids render

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 16:32:17 +02:00
Diego ImbertandClaude Opus 5 2257b05b28 feat: make S3 permission rules reorderable by drag and drop (#10958)
Claude-Session: https://claude.ai/code/session_01DkKR3V3rWDyh1tDZCxmGLT

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-04 13:58:26 +02:00
Alexander PetricandClaude Fable 5.1 d232d57f0d offer known Google scopes as checkboxes in the oauth connect dialog (#10945)
* feat: offer known Google scopes as checkboxes in the oauth connect dialog

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kv72vdCDggCZEjJSmNCwnX

* fix: keep custom oauth scope rows apart from checked options while typing

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kv72vdCDggCZEjJSmNCwnX

* fix: drop the rust scope_options field and render checkboxes from the ticked set

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kv72vdCDggCZEjJSmNCwnX

* fix: keep ticked oauth scope options independent of free-text rows

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kv72vdCDggCZEjJSmNCwnX

* fix: toggle oauth scope checkboxes from component state, not the reverted input

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kv72vdCDggCZEjJSmNCwnX

* fix: keep the legacy gforms default scope so pre-migration accounts still refresh

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kv72vdCDggCZEjJSmNCwnX

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 13:55:20 +02:00