Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
566 changes: 566 additions & 0 deletions apps/sim/app/playground/page.tsx

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ export { Panel } from './panel/panel'
export { SkeletonLoading } from './skeleton-loading/skeleton-loading'
export { SubflowNodeComponent } from './subflows/subflow-node'
export { Terminal } from './terminal/terminal'
export { TrainingControls } from './training-controls/training-controls'
export { WandPromptBar } from './wand-prompt-bar/wand-prompt-bar'
export { WorkflowBlock } from './workflow-block/workflow-block'
export { WorkflowEdge } from './workflow-edge/workflow-edge'
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,19 @@ import {
Check,
ChevronDown,
Clipboard,
Database,
Filter,
FilterX,
MoreHorizontal,
Palette,
Pause,
RepeatIcon,
Search,
SplitIcon,
Trash2,
X,
} from 'lucide-react'
import Link from 'next/link'
import { useShallow } from 'zustand/react/shallow'
import {
Button,
Expand All @@ -30,6 +34,7 @@ import {
PopoverTrigger,
Tooltip,
} from '@/components/emcn'
import { getEnv, isTruthy } from '@/lib/core/config/env'
import { useRegisterGlobalCommands } from '@/app/workspace/[workspaceId]/providers/global-commands-provider'
import { createCommands } from '@/app/workspace/[workspaceId]/utils/commands-utils'
import {
Expand All @@ -38,6 +43,8 @@ import {
useTerminalResize,
} from '@/app/workspace/[workspaceId]/w/[workflowId]/components/terminal/hooks'
import { getBlock } from '@/blocks'
import { useCopilotTrainingStore } from '@/stores/copilot-training/store'
import { useGeneralStore } from '@/stores/settings/general/store'
import type { ConsoleEntry } from '@/stores/terminal'
import { useTerminalConsoleStore, useTerminalStore } from '@/stores/terminal'
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
Expand Down Expand Up @@ -331,6 +338,14 @@ export function Terminal() {
const outputSearchInputRef = useRef<HTMLInputElement>(null)
const outputContentRef = useRef<HTMLDivElement>(null)

// Training controls state
const [isTrainingEnvEnabled, setIsTrainingEnvEnabled] = useState(false)
const showTrainingControls = useGeneralStore((state) => state.showTrainingControls)
const { isTraining, toggleModal: toggleTrainingModal, stopTraining } = useCopilotTrainingStore()

// Playground state
const [isPlaygroundEnabled, setIsPlaygroundEnabled] = useState(false)

// Terminal resize hooks
const { handleMouseDown } = useTerminalResize()
const { handleMouseDown: handleOutputPanelResizeMouseDown } = useOutputPanelResize()
Expand Down Expand Up @@ -612,6 +627,26 @@ export function Terminal() {
[activeWorkflowId, exportConsoleCSV]
)

/**
* Handle training button click - toggle training state or open modal
*/
const handleTrainingClick = useCallback(
(e: React.MouseEvent) => {
e.stopPropagation()
if (isTraining) {
stopTraining()
} else {
toggleTrainingModal()
}
},
[isTraining, stopTraining, toggleTrainingModal]
)

/**
* Whether training controls should be visible
*/
const shouldShowTrainingButton = isTrainingEnvEnabled && showTrainingControls

/**
* Register global keyboard shortcuts for the terminal:
* - Mod+D: Clear terminal console for the active workflow
Expand Down Expand Up @@ -640,6 +675,14 @@ export function Terminal() {
setHasHydrated(true)
}, [setHasHydrated])

/**
* Check environment variables on mount
*/
useEffect(() => {
setIsTrainingEnvEnabled(isTruthy(getEnv('NEXT_PUBLIC_COPILOT_TRAINING_ENABLED')))
setIsPlaygroundEnabled(isTruthy(getEnv('NEXT_PUBLIC_ENABLE_PLAYGROUND')))
}, [])

/**
* Adjust showInput when selected entry changes
* Stay on input view if the new entry has input data
Expand Down Expand Up @@ -1104,6 +1147,48 @@ export function Terminal() {
)}
{!selectedEntry && (
<div className='ml-auto flex items-center gap-[8px]'>
{isPlaygroundEnabled && (
<Tooltip.Root>
<Tooltip.Trigger asChild>
<Link href='/playground'>
<Button
variant='ghost'
aria-label='Component Playground'
className='!p-1.5 -m-1.5'
>
<Palette className='h-3 w-3' />
</Button>
</Link>
</Tooltip.Trigger>
<Tooltip.Content>
<span>Component Playground</span>
</Tooltip.Content>
</Tooltip.Root>
)}
{shouldShowTrainingButton && (
<Tooltip.Root>
<Tooltip.Trigger asChild>
<Button
variant='ghost'
onClick={handleTrainingClick}
aria-label={isTraining ? 'Stop training' : 'Train Copilot'}
className={clsx(
'!p-1.5 -m-1.5',
isTraining && 'text-orange-600 dark:text-orange-400'
)}
>
{isTraining ? (
<Pause className='h-3 w-3' />
) : (
<Database className='h-3 w-3' />
)}
</Button>
</Tooltip.Trigger>
<Tooltip.Content>
<span>{isTraining ? 'Stop Training' : 'Train Copilot'}</span>
</Tooltip.Content>
</Tooltip.Root>
)}
{hasActiveFilters && (
<Tooltip.Root>
<Tooltip.Trigger asChild>
Expand Down Expand Up @@ -1426,6 +1511,50 @@ export function Terminal() {
</Tooltip.Root>
)}

{isPlaygroundEnabled && (
<Tooltip.Root>
<Tooltip.Trigger asChild>
<Link href='/playground'>
<Button
variant='ghost'
aria-label='Component Playground'
className='!p-1.5 -m-1.5'
>
<Palette className='h-[12px] w-[12px]' />
</Button>
</Link>
</Tooltip.Trigger>
<Tooltip.Content>
<span>Component Playground</span>
</Tooltip.Content>
</Tooltip.Root>
)}

{shouldShowTrainingButton && (
<Tooltip.Root>
<Tooltip.Trigger asChild>
<Button
variant='ghost'
onClick={handleTrainingClick}
aria-label={isTraining ? 'Stop training' : 'Train Copilot'}
className={clsx(
'!p-1.5 -m-1.5',
isTraining && 'text-orange-600 dark:text-orange-400'
)}
>
{isTraining ? (
<Pause className='h-[12px] w-[12px]' />
) : (
<Database className='h-[12px] w-[12px]' />
)}
</Button>
</Tooltip.Trigger>
<Tooltip.Content>
<span>{isTraining ? 'Stop Training' : 'Train Copilot'}</span>
</Tooltip.Content>
</Tooltip.Root>
)}

<Tooltip.Root>
<Tooltip.Trigger asChild>
<Button
Expand Down

This file was deleted.

This file was deleted.

Loading