Flow inputs carry an origin hint, run or panel
The Inputs editor and the canvas label show it, and the run forms leave panel inputs out.
This commit is contained in:
@@ -1355,6 +1355,13 @@ export const FlowInput_InputSchema = {
|
||||
}
|
||||
],
|
||||
title: 'Initial'
|
||||
},
|
||||
origin: {
|
||||
type: 'string',
|
||||
enum: ['run', 'panel'],
|
||||
title: 'Origin',
|
||||
description: 'What writes it. A run input is a parameter a run passes in, a panel input is written by a dashboard or panel control. A hint only: run forms leave panel inputs out, the engine treats both the same.',
|
||||
default: 'run'
|
||||
}
|
||||
},
|
||||
type: 'object',
|
||||
@@ -1376,6 +1383,13 @@ export const FlowInput_OutputSchema = {
|
||||
}
|
||||
],
|
||||
title: 'Initial'
|
||||
},
|
||||
origin: {
|
||||
type: 'string',
|
||||
enum: ['run', 'panel'],
|
||||
title: 'Origin',
|
||||
description: 'What writes it. A run input is a parameter a run passes in, a panel input is written by a dashboard or panel control. A hint only: run forms leave panel inputs out, the engine treats both the same.',
|
||||
default: 'run'
|
||||
}
|
||||
},
|
||||
type: 'object',
|
||||
|
||||
@@ -391,14 +391,27 @@ export type FlowDetail = {
|
||||
export type FlowInput_Input = {
|
||||
spec: MessageSpec;
|
||||
initial?: (unknown | null);
|
||||
/**
|
||||
* What writes it. A run input is a parameter a run passes in, a panel input is written by a dashboard or panel control. A hint only: run forms leave panel inputs out, the engine treats both the same.
|
||||
*/
|
||||
origin?: 'run' | 'panel';
|
||||
};
|
||||
|
||||
/**
|
||||
* What writes it. A run input is a parameter a run passes in, a panel input is written by a dashboard or panel control. A hint only: run forms leave panel inputs out, the engine treats both the same.
|
||||
*/
|
||||
export type origin = 'run' | 'panel';
|
||||
|
||||
/**
|
||||
* A message the flow starts with rather than computes.
|
||||
*/
|
||||
export type FlowInput_Output = {
|
||||
spec: MessageSpec;
|
||||
initial?: (unknown | null);
|
||||
/**
|
||||
* What writes it. A run input is a parameter a run passes in, a panel input is written by a dashboard or panel control. A hint only: run forms leave panel inputs out, the engine treats both the same.
|
||||
*/
|
||||
origin?: 'run' | 'panel';
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,6 +6,7 @@ import { MessagesService } from "@/client"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Checkbox } from "@/components/ui/checkbox"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Segmented } from "@/components/ui/segmented"
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
@@ -160,6 +161,12 @@ function usePublishInput() {
|
||||
})
|
||||
}
|
||||
|
||||
/** What writes an input: a run passing it in, or a control on a panel. */
|
||||
const ORIGINS = [
|
||||
["run", "run"],
|
||||
["panel", "panel"],
|
||||
] as const
|
||||
|
||||
function InputRow({
|
||||
flow,
|
||||
declared,
|
||||
@@ -231,34 +238,44 @@ function InputRow({
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{live && name ? (
|
||||
<div className="flex items-center gap-2 pl-1 text-xs text-muted-foreground">
|
||||
<span className="shrink-0">now</span>
|
||||
{current === undefined ? (
|
||||
<span className="flex-1">—</span>
|
||||
) : (
|
||||
<span className="min-w-0 flex-1">
|
||||
<ValuePreview value={current.value} dtype={spec.dtype} />
|
||||
</span>
|
||||
)}
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon-sm"
|
||||
aria-label="Publish this value now"
|
||||
disabled={publish.isPending || declared.initial === null}
|
||||
onClick={() =>
|
||||
publish.mutate({ message, value: declared.initial })
|
||||
}
|
||||
>
|
||||
<ArrowUpFromLine />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>Put this value into the flow now</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
) : null}
|
||||
<div className="flex items-center gap-2 pl-1 text-xs text-muted-foreground">
|
||||
<Segmented
|
||||
label="Written by"
|
||||
value={declared.origin ?? "run"}
|
||||
options={ORIGINS}
|
||||
onChange={(origin) =>
|
||||
onChange({ ...declared, origin: origin as typeof declared.origin })
|
||||
}
|
||||
/>
|
||||
{live && name ? (
|
||||
<>
|
||||
<span className="shrink-0">now</span>
|
||||
{current === undefined ? (
|
||||
<span className="flex-1">—</span>
|
||||
) : (
|
||||
<span className="min-w-0 flex-1">
|
||||
<ValuePreview value={current.value} dtype={spec.dtype} />
|
||||
</span>
|
||||
)}
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon-sm"
|
||||
aria-label="Publish this value now"
|
||||
disabled={publish.isPending || declared.initial === null}
|
||||
onClick={() =>
|
||||
publish.mutate({ message, value: declared.initial })
|
||||
}
|
||||
>
|
||||
<ArrowUpFromLine />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>Put this value into the flow now</TooltipContent>
|
||||
</Tooltip>
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -338,8 +355,9 @@ export function BoundarySections({
|
||||
<div className="flex items-center justify-between">
|
||||
<span className={PANEL_SECTION}>Inputs</span>
|
||||
<InfoTip label="Inputs">
|
||||
Messages that arrive from outside, such as a dashboard control, a
|
||||
run or the API, and the value the flow starts from.
|
||||
Messages that arrive from outside, and the value the flow starts
|
||||
from. A run passes a run input in, a dashboard or panel control
|
||||
writes a panel input.
|
||||
</InfoTip>
|
||||
<Button
|
||||
variant="ghost"
|
||||
|
||||
@@ -94,9 +94,16 @@ export function initialText(inputs: FlowInput_Input[]): Record<string, string> {
|
||||
)
|
||||
}
|
||||
|
||||
/** The declared inputs worth drawing a field for. */
|
||||
/**
|
||||
* The declared inputs worth drawing a field for.
|
||||
*
|
||||
* A panel input is a control's to write, so a run keeps its starting value
|
||||
* and the form does not offer it as a parameter.
|
||||
*/
|
||||
export function declaredInputs(definition: FlowDef_Input): FlowInput_Input[] {
|
||||
return (definition.inputs ?? []).filter((one) => one.spec?.name)
|
||||
return (definition.inputs ?? []).filter(
|
||||
(one) => one.spec?.name && one.origin !== "panel",
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -91,11 +91,14 @@ export function deriveEdges(nodes: NodeDef_Input[], flow: string): Edge[] {
|
||||
*/
|
||||
export function boundaryKey(doc: {
|
||||
mode?: string | null
|
||||
inputs?: { spec?: MessageSpec | null }[] | null
|
||||
inputs?: { spec?: MessageSpec | null; origin?: string }[] | null
|
||||
outputs?: string[] | null
|
||||
}): string {
|
||||
const inputs = (doc.inputs ?? [])
|
||||
.map((one) => `${one.spec?.name ?? ""}:${one.spec?.dtype ?? ""}`)
|
||||
.map(
|
||||
(one) =>
|
||||
`${one.spec?.name ?? ""}:${one.spec?.dtype ?? ""}:${one.origin ?? ""}`,
|
||||
)
|
||||
.join(",")
|
||||
return `${doc.mode ?? "live"}|${inputs}|${(doc.outputs ?? []).join(",")}`
|
||||
}
|
||||
|
||||
@@ -62,7 +62,8 @@ function boundaryOf(
|
||||
kind: "input",
|
||||
id: `input:${message}`,
|
||||
label: displayName(flow, message),
|
||||
detail: declared.spec?.dtype ?? "float",
|
||||
// What writes it, so a control's input does not read as a run's.
|
||||
detail: `${declared.origin ?? "run"} · ${declared.spec?.dtype ?? "float"}`,
|
||||
provides: [message],
|
||||
requires: [],
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user