mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-12 16:02:56 +00:00
fix(sessions): take no writes on a relocated form under plan mode
A password field mints an ephemeral workspace variable as it is typed, so withholding the dynamic-select helper was half the promise: the field itself has to be unwritable. One flag now covers both, as the card's own form already did. The hand-back is keyed on the call rather than on the object naming it, which is rebuilt whenever the draft or the posture changes — its own write to that draft is what would have re-run it. It also hands back only what its own form held: the next call for this item re-points the same tab without remounting, and its seeding can land first. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
88457fbe16
commit
2fe3579f75
@@ -146,10 +146,12 @@
|
||||
* if the press then ends before `runAction`, so a guard that counts presses can stop
|
||||
* counting this one. */
|
||||
claimRun?: { claim: () => boolean; release: () => void }
|
||||
/** Withhold the dynamic-select helper, which runs the `dynselect-` entrypoint on mount
|
||||
* rather than on Run. For a form standing in for a chat call while plan mode is on:
|
||||
* nothing about pressing Run gates it, and plan mode promised no runs. */
|
||||
noHelperScript?: boolean
|
||||
/** Take no writes from the reader: no edits, and no dynamic-select helper. Both write
|
||||
* before Run is ever pressed — a `password` field mints an ephemeral variable as it is
|
||||
* typed, and the helper runs the `dynselect-` entrypoint when the field mounts — so
|
||||
* nothing about gating Run can stop them. For a form standing in for a chat card while
|
||||
* plan mode is on, which promised neither. */
|
||||
argsReadonly?: boolean
|
||||
buttonText?: string
|
||||
schedulable?: boolean
|
||||
detailed?: boolean
|
||||
@@ -178,7 +180,7 @@
|
||||
runnable,
|
||||
runAction,
|
||||
claimRun = undefined,
|
||||
noHelperScript = false,
|
||||
argsReadonly = false,
|
||||
buttonText = 'Run',
|
||||
schedulable = true,
|
||||
detailed = true,
|
||||
@@ -369,13 +371,14 @@
|
||||
{#key reloadArgs}
|
||||
<div bind:clientHeight={schemaHeight}>
|
||||
<SchemaForm
|
||||
helperScript={noHelperScript
|
||||
helperScript={argsReadonly
|
||||
? undefined
|
||||
: {
|
||||
source: 'deployed',
|
||||
path: runnable.path!,
|
||||
runnable_kind: runnable.hash ? 'script' : 'flow'
|
||||
}}
|
||||
disabled={argsReadonly}
|
||||
prettifyHeader
|
||||
{noVariablePicker}
|
||||
{autofocus}
|
||||
|
||||
@@ -403,10 +403,21 @@
|
||||
// goes back to the card — the card would then offer, and run, the arguments this page
|
||||
// opened with. Written on the way out rather than per keystroke: one hand-back, whether
|
||||
// the tab closed, was re-pointed, or the reader picked a version.
|
||||
//
|
||||
// Keyed on the call rather than the object naming it, which is rebuilt whenever the draft
|
||||
// or the posture changes: this must not re-run on either, since its own write to that
|
||||
// draft would be what re-ran it.
|
||||
$effect(() => {
|
||||
const call = pendingRun
|
||||
if (!call) return
|
||||
return () => call.handBack(args ?? {})
|
||||
const id = pendingRun?.toolCallId
|
||||
if (!id) return
|
||||
const call = untrack(() => pendingRun)
|
||||
return () =>
|
||||
untrack(() => {
|
||||
// Only what this call's own form held. The next call for this item re-points the
|
||||
// same tab without remounting, and its seeding may land first — handing this one
|
||||
// the arguments of a proposal that was never on screen for it.
|
||||
if (seededCallId === id) call?.handBack(args ?? {})
|
||||
})
|
||||
})
|
||||
|
||||
// The dev workspace's editor is not one the session panel can host, so from a preview tab
|
||||
@@ -946,7 +957,7 @@
|
||||
runnable={flow}
|
||||
{runAction}
|
||||
claimRun={pendingRun}
|
||||
noHelperScript={pendingRun?.planModeActive}
|
||||
argsReadonly={pendingRun?.planModeActive}
|
||||
bind:args
|
||||
schedulable={!pendingRun}
|
||||
bind:this={runForm}
|
||||
|
||||
@@ -452,10 +452,21 @@
|
||||
// goes back to the card — the card would then offer, and run, the arguments this page
|
||||
// opened with. Written on the way out rather than per keystroke: one hand-back, whether
|
||||
// the tab closed, was re-pointed, or the reader picked a version.
|
||||
//
|
||||
// Keyed on the call rather than the object naming it, which is rebuilt whenever the draft
|
||||
// or the posture changes: this must not re-run on either, since its own write to that
|
||||
// draft would be what re-ran it.
|
||||
$effect(() => {
|
||||
const call = pendingRun
|
||||
if (!call) return
|
||||
return () => call.handBack(args ?? {})
|
||||
const id = pendingRun?.toolCallId
|
||||
if (!id) return
|
||||
const call = untrack(() => pendingRun)
|
||||
return () =>
|
||||
untrack(() => {
|
||||
// Only what this call's own form held. The next call for this item re-points the
|
||||
// same tab without remounting, and its seeding may land first — handing this one
|
||||
// the arguments of a proposal that was never on screen for it.
|
||||
if (seededCallId === id) call?.handBack(args ?? {})
|
||||
})
|
||||
})
|
||||
|
||||
// Read once on purpose: these args seed the form, so tracking the fragment would
|
||||
@@ -1154,7 +1165,7 @@
|
||||
runnable={script}
|
||||
{runAction}
|
||||
claimRun={pendingRun}
|
||||
noHelperScript={pendingRun?.planModeActive}
|
||||
argsReadonly={pendingRun?.planModeActive}
|
||||
bind:args
|
||||
schedulable={!pendingRun}
|
||||
bind:this={runForm}
|
||||
|
||||
Reference in New Issue
Block a user