Skip to content

Commit 4cd8323

Browse files
feat(workflow): removed varinat creation and hide deployment
- reframe default variant as history, nothing else changed - hide the deployment option for the agent
1 parent 35c6259 commit 4cd8323

9 files changed

Lines changed: 74 additions & 37 deletions

File tree

web/oss/src/components/Playground/Components/AgentRevisionSelector/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ const AgentRevisionSelector = ({variantId}: {variantId: string}) => {
6363
onChange={(value) => handleSwitchVariant(value)}
6464
value={_variantId ?? undefined}
6565
borderlessTrigger
66+
versioning="linear"
6667
/>
6768
{variantRevision !== null && variantRevision !== undefined && (
6869
<Tooltip

web/oss/src/components/Playground/Components/Menus/SelectVariant/components/RevisionChildTitle.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ interface RevisionChildTitleProps {
1010
isDisabled: boolean
1111
showLatestTag: boolean
1212
showAsCompare: boolean
13+
showBadges?: boolean
1314
onCreateLocalCopy: (revisionId: string, e: React.MouseEvent) => void
1415
latestRevisionId?: string | null
1516
}
@@ -22,6 +23,7 @@ const RevisionChildTitle = ({
2223
isDisabled,
2324
showLatestTag,
2425
showAsCompare,
26+
showBadges = true,
2527
onCreateLocalCopy,
2628
latestRevisionId,
2729
}: RevisionChildTitleProps) => {
@@ -37,7 +39,7 @@ const RevisionChildTitle = ({
3739
revision={version}
3840
variant={variant as any}
3941
hideName
40-
showBadges
42+
showBadges={showBadges}
4143
showLatestTag={showLatestTag}
4244
isLatest={isLatest}
4345
/>

web/oss/src/components/Playground/Components/Menus/SelectVariant/index.tsx

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,10 @@ const SelectVariant = ({
5757
customBrowseAdapter,
5858
style,
5959
borderlessTrigger = false,
60+
versioning = "branching",
6061
...props
6162
}: SelectVariantProps) => {
63+
const isLinearVersioning = versioning === "linear"
6264
const selectedVariants = useAtomValue(playgroundController.selectors.entityIds())
6365
const setSelectedVariants = useSetAtom(playgroundController.actions.setEntityIds)
6466
const selectedAppId = useAtomValue(selectedAppIdAtom)
@@ -122,13 +124,14 @@ const SelectVariant = ({
122124
selectedExistsInAppList,
123125
])
124126

125-
const selectPlaceholder =
126-
!showAsCompare &&
127-
!!singleSelectedValue &&
128-
selectedRevisionQuery.isPending &&
129-
!hasSelectedDisplayName
130-
? "Loading variant..."
131-
: "Select variant"
127+
const selectPlaceholder = isLinearVersioning
128+
? "History"
129+
: !showAsCompare &&
130+
!!singleSelectedValue &&
131+
selectedRevisionQuery.isPending &&
132+
!hasSelectedDisplayName
133+
? "Loading variant..."
134+
: "Select variant"
132135

133136
// Scoped adapter: 2-level (Variant → Revision), scoped to the current app
134137
const scopedAdapter = useMemo(
@@ -260,12 +263,20 @@ const SelectVariant = ({
260263
isDisabled={disabledIds.has(c.id)}
261264
showLatestTag={showLatestTag}
262265
showAsCompare={showAsCompare}
266+
showBadges={!isLinearVersioning}
263267
onCreateLocalCopy={handleCreateLocalCopy}
264268
latestRevisionId={latestRevisionId}
265269
/>
266270
)
267271
},
268-
[showLatestTag, showAsCompare, handleCreateLocalCopy, disabledIds, latestRevisionId],
272+
[
273+
showLatestTag,
274+
showAsCompare,
275+
handleCreateLocalCopy,
276+
disabledIds,
277+
latestRevisionId,
278+
isLinearVersioning,
279+
],
269280
)
270281

271282
const renderSelectedLabel = useCallback(
@@ -363,6 +374,7 @@ const SelectVariant = ({
363374
// Uses singleSelectedValue directly (not selectedValueForControl which
364375
// may be undefined while the existence check resolves).
365376
const triggerLabel = useMemo(() => {
377+
if (isLinearVersioning && mode === "scoped") return "History"
366378
if (!singleSelectedValue) return selectPlaceholder
367379
if (isLocalDraftId(singleSelectedValue)) {
368380
return selectedVariantName ?? selectedRevisionData?.name ?? "Draft"
@@ -388,6 +400,7 @@ const SelectVariant = ({
388400
selectPlaceholder,
389401
mode,
390402
workflowName,
403+
isLinearVersioning,
391404
])
392405

393406
// Initial expanded keys for browse mode — expand the parent workflow of the selected revision
@@ -503,11 +516,15 @@ const SelectVariant = ({
503516
onSelect={handleSingleSelect}
504517
selectedValue={selectedValueForControl}
505518
disabledChildIds={disabledIds}
506-
renderParentTitle={renderParentTitle}
519+
renderParentTitle={
520+
isLinearVersioning ? undefined : renderParentTitle
521+
}
507522
renderChildTitle={renderChildTitle}
508523
renderSelectedLabel={renderSelectedLabel}
509524
popupMinWidth={280}
510525
maxHeight={400}
526+
showSearch={!isLinearVersioning}
527+
flattenSingleParent={isLinearVersioning}
511528
/>
512529
)}
513530
</div>

web/oss/src/components/Playground/Components/Menus/SelectVariant/types.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ export interface SelectVariantProps extends TreeSelectProps {
2424
* header so the revision picker reads as an identity, not a form switch.
2525
*/
2626
borderlessTrigger?: boolean
27+
/**
28+
* Controls how revisions are presented. Linear versioning hides the persisted
29+
* variant level and deployment badges and labels the control as History.
30+
*/
31+
versioning?: "linear" | "branching"
2732
}
2833

2934
export interface TreeSelectItemRendererProps {

web/oss/src/components/Playground/Components/Modals/CommitVariantChangesModal/index.tsx

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
clearRegistryVariantNameCache,
2323
} from "@/oss/components/VariantsComponents/store/registryStore"
2424
import {selectedAppIdAtom} from "@/oss/state/app"
25+
import {currentWorkflowAtom} from "@/oss/state/workflow"
2526

2627
import {CommitVariantChangesModalProps} from "./assets/types"
2728

@@ -43,6 +44,8 @@ const CommitVariantChangesModal: React.FC<CommitVariantChangesModalProps> = ({
4344
const isEphemeral = useAtomValue(workflowMolecule.selectors.isEphemeral(variantId || ""))
4445
const isEvaluator = useAtomValue(workflowMolecule.selectors.isEvaluator(variantId || ""))
4546
const isApplication = useAtomValue(workflowMolecule.selectors.isApplication(variantId || ""))
47+
const isAgent = useAtomValue(workflowMolecule.selectors.isAgent(variantId || ""))
48+
const currentWorkflow = useAtomValue(currentWorkflowAtom)
4649

4750
const appId = useAtomValue(selectedAppIdAtom)
4851
const commitRevision = useSetAtom(playgroundController.actions.commitRevision)
@@ -51,6 +54,7 @@ const CommitVariantChangesModal: React.FC<CommitVariantChangesModalProps> = ({
5154
const {mutateAsync: publish} = useAtomValue(publishMutationAtom)
5255

5356
const variantName = runnableData?.name || "Variant"
57+
const commitTargetName = isAgent ? currentWorkflow?.name || "Agent" : variantName
5458
const variantSlug = runnableData?.slug
5559

5660
// Environments offered in the footer's "Commit & deploy to …" split-button dropdown.
@@ -73,7 +77,7 @@ const CommitVariantChangesModal: React.FC<CommitVariantChangesModalProps> = ({
7377
deployEnvironments: string[] | undefined,
7478
deployMessage?: string,
7579
) => {
76-
if (!deployEnvironments || deployEnvironments.length === 0) return
80+
if (isAgent || !deployEnvironments || deployEnvironments.length === 0) return
7781
const newRevisionData = workflowMolecule.get.data(newRevisionId)
7882
const refs = {
7983
revisionId: newRevisionId,
@@ -105,7 +109,7 @@ const CommitVariantChangesModal: React.FC<CommitVariantChangesModalProps> = ({
105109
message.error(`Couldn't publish ${label} to ${failed.join(", ")}`)
106110
}
107111
},
108-
[publish, runnableData, appId],
112+
[publish, runnableData, appId, isAgent],
109113
)
110114

111115
const handleSubmit = useCallback(
@@ -145,7 +149,9 @@ const CommitVariantChangesModal: React.FC<CommitVariantChangesModalProps> = ({
145149
return {success: true, newRevisionId: result.newRevisionId}
146150
}
147151

148-
const selectedMode = mode === "variant" ? "variant" : "version"
152+
// Agents always append to their one persisted timeline. Ignore a stale
153+
// or externally supplied branching mode as a mechanical guardrail.
154+
const selectedMode = !isAgent && mode === "variant" ? "variant" : "version"
149155
const note = commitMessage ?? undefined
150156

151157
if (selectedMode === "variant") {
@@ -221,6 +227,7 @@ const CommitVariantChangesModal: React.FC<CommitVariantChangesModalProps> = ({
221227
},
222228
[
223229
isEphemeral,
230+
isAgent,
224231
createFromEphemeral,
225232
createVariant,
226233
variantId,
@@ -234,13 +241,13 @@ const CommitVariantChangesModal: React.FC<CommitVariantChangesModalProps> = ({
234241

235242
const commitModes = useMemo(
236243
() =>
237-
isEvaluator
244+
isEvaluator || isAgent
238245
? [{id: "version", label: "As a new version"}]
239246
: [
240247
{id: "version", label: `Update ${variantName}`},
241248
{id: "variant", label: "Save as a new variant"},
242249
],
243-
[isEvaluator, variantName],
250+
[isEvaluator, isAgent, variantName],
244251
)
245252

246253
// For ephemeral entities, render a simplified "Create" modal with editable name.
@@ -284,11 +291,11 @@ const CommitVariantChangesModal: React.FC<CommitVariantChangesModalProps> = ({
284291
entity={{
285292
type: "variant",
286293
id: variantId,
287-
name: variantName,
294+
name: commitTargetName,
288295
}}
289296
commitModes={commitModes}
290297
defaultCommitMode="version"
291-
commitDeployOptions={isEvaluator ? undefined : commitDeployOptions}
298+
commitDeployOptions={isEvaluator || isAgent ? undefined : commitDeployOptions}
292299
canSubmit={({mode, entityName}) => {
293300
if (mode === "variant") {
294301
if (!entityName?.trim()) return false

web/oss/src/components/Playground/Components/PlaygroundVariantConfig/assets/PlaygroundVariantConfigHeader.tsx

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -296,16 +296,8 @@ const PlaygroundVariantConfigHeader = ({
296296
</>
297297
) : (
298298
<>
299-
{!embedded && !isEvaluatorEntity && (
300-
// Agents get a labeled secondary "Deploy" so the action row reads as a
301-
// hierarchy (primary Commit, secondary Deploy, ghost kebab); other
302-
// surfaces keep the icon-only deploy.
303-
<DeployVariantButton
304-
revisionId={variantId}
305-
{...(isAgentEffective
306-
? ({label: "Deploy", type: "default", size: "small"} as const)
307-
: {})}
308-
/>
299+
{!embedded && !isEvaluatorEntity && !isAgentEffective && (
300+
<DeployVariantButton revisionId={variantId} />
309301
)}
310302

311303
<CommitVariantChangesButton

web/oss/src/components/Sidebar/hooks/useSidebarConfig/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ export const useSidebarConfig = (): MainSidebarItems => {
169169
icon: <LightningIcon size={14} />,
170170
disabled: !hasProjectURL,
171171
dataTour: "registry-nav",
172-
workflowCategories: ["app", "agent"],
172+
workflowCategories: ["app"],
173173
},
174174
{
175175
key: "app-evaluations-link",

web/oss/src/state/workflow/hooks.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ export const useWorkflowsData = () => {
8282
currentWorkflow: currentWorkflow ?? null,
8383
workflowKind: ctx.workflowKind,
8484
isApp: ctx.workflowKind === "app",
85+
isAgent: ctx.workflowKind === "app" && currentWorkflow?.flags?.is_agent === true,
8586
isEvaluator: ctx.workflowKind === "evaluator",
8687
isSnippet: ctx.workflowKind === "snippet",
8788
// Terminal states (mutually exclusive).

web/packages/agenta-entity-ui/src/selection/components/UnifiedEntityPicker/variants/TreeSelectPopupContent.tsx

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ export type TreeSelectPopupContentProps<TSelection = EntitySelectionResult> = Om
4444
* Children for these parents will be fetched on mount.
4545
*/
4646
initialExpandedKeys?: string[]
47+
/** Hide a sole structural parent and render its children as a flat list. */
48+
flattenSingleParent?: boolean
4749
}
4850

4951
// ============================================================================
@@ -77,6 +79,7 @@ export function TreeSelectPopupContent<TSelection = EntitySelectionResult>({
7779
width = 280,
7880
showDate = false,
7981
initialExpandedKeys,
82+
flattenSingleParent = false,
8083
}: TreeSelectPopupContentProps<TSelection>) {
8184
const generatedId = useId()
8285
const instanceId = providedInstanceId ?? generatedId
@@ -150,6 +153,8 @@ export function TreeSelectPopupContent<TSelection = EntitySelectionResult>({
150153
// Get display messages
151154
const displayEmptyMessage = emptyMessage ?? resolvedAdapter.emptyMessage ?? "No items found"
152155
const displayLoadingMessage = loadingMessage ?? resolvedAdapter.loadingMessage ?? "Loading..."
156+
const displayTreeData =
157+
flattenSingleParent && treeData.length === 1 ? (treeData[0].children ?? []) : treeData
153158

154159
// Handle tree node selection
155160
const handleTreeSelect = useCallback(
@@ -195,7 +200,7 @@ export function TreeSelectPopupContent<TSelection = EntitySelectionResult>({
195200
{popupHeader}
196201

197202
{/* Loading state — only shown when no tree data is available yet */}
198-
{(isLoadingParents || isLoadingChildren) && treeData.length === 0 && (
203+
{(isLoadingParents || isLoadingChildren) && displayTreeData.length === 0 && (
199204
<div className="flex items-center justify-center py-4">
200205
<Spin size="small" />
201206
<span className="ml-2 text-sm text-gray-500">{displayLoadingMessage}</span>
@@ -208,22 +213,29 @@ export function TreeSelectPopupContent<TSelection = EntitySelectionResult>({
208213
)}
209214

210215
{/* Empty state */}
211-
{!isLoadingParents && !parentsError && treeData.length === 0 && (
212-
<div className="px-3 py-4 text-sm text-gray-500 text-center">
213-
{displayEmptyMessage}
214-
</div>
215-
)}
216+
{!isLoadingParents &&
217+
!isLoadingChildren &&
218+
!parentsError &&
219+
displayTreeData.length === 0 && (
220+
<div className="px-3 py-4 text-sm text-gray-500 text-center">
221+
{displayEmptyMessage}
222+
</div>
223+
)}
216224

217225
{/* Tree list */}
218-
{!isLoadingParents && !parentsError && treeData.length > 0 && (
226+
{!isLoadingParents && !parentsError && displayTreeData.length > 0 && (
219227
<div
220228
ref={scrollContainerRef}
221229
style={{maxHeight, overflow: "auto"}}
222-
className="tree-popup-compact px-2 pb-2"
230+
className={cn(
231+
"tree-popup-compact pb-2",
232+
flattenSingleParent ? "tree-popup-flat px-1.5 pt-2.5" : "px-2",
233+
)}
223234
>
224235
<style>{`
225236
.tree-popup-compact .ant-tree-treenode-leaf .ant-tree-indent { display: none !important; }
226237
.tree-popup-compact .ant-tree-treenode-leaf { padding-left: 24px !important; }
238+
.tree-popup-compact.tree-popup-flat .ant-tree-treenode-leaf { padding-left: 0 !important; width: 100%; }
227239
.tree-popup-compact .ant-tree-checkbox { display: none; }
228240
.tree-popup-compact .ant-tree-treenode-selected > .ant-tree-node-content-wrapper { background: var(--ant-blue-1, #e6f4ff); opacity: 0.8; }
229241
.tree-popup-compact .ant-tree-node-content-wrapper { padding-left: 4px !important; display: flex; align-items: center; justify-content: space-between; border-radius: 6px; }
@@ -244,7 +256,7 @@ export function TreeSelectPopupContent<TSelection = EntitySelectionResult>({
244256
.tree-popup-compact .ant-tree-treenode-leaf { background: var(--ant-color-bg-elevated, #fff); }
245257
`}</style>
246258
<Tree
247-
treeData={treeData}
259+
treeData={displayTreeData}
248260
expandedKeys={expandedKeys}
249261
onExpand={handleTreeExpand}
250262
onSelect={handleTreeSelect}

0 commit comments

Comments
 (0)