From 4079d71bf8b2b1047ccd78726bb083b887cbda49 Mon Sep 17 00:00:00 2001 From: Shaun Berryman Date: Tue, 14 Apr 2026 15:28:30 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20UI=20Refresh?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/ui/src/components/Header.tsx | 424 +++++++++-- apps/ui/src/components/IDEFooter.tsx | 96 ++- apps/ui/src/components/NavBar.tsx | 265 ------- .../src/components/builder/AddBlockMenu.tsx | 4 +- apps/ui/src/components/builder/BlockCard.tsx | 8 +- .../src/components/builder/BuilderCanvas.tsx | 10 +- .../src/components/builder/CommentEditor.tsx | 4 +- .../src/components/builder/NamedBlockCard.tsx | 8 +- .../src/components/builder/NamedBlockList.tsx | 4 +- .../builder/ReasoningActionCard.tsx | 14 +- .../src/components/builder/TypedMapEditor.tsx | 15 +- .../components/builder/fields/EnumField.tsx | 4 +- .../builder/statements/AddStatementMenu.tsx | 4 +- .../builder/statements/StatementCard.tsx | 4 +- .../src/components/cst-debug/cstNodeIcons.tsx | 120 ++- apps/ui/src/components/explorer/TreeView.tsx | 48 +- .../graph/nodes/DiagnosticHoverCard.tsx | 14 +- apps/ui/src/components/layouts/IDELayout.tsx | 135 +++- .../src/components/panels/ExplorerPanel.tsx | 9 +- apps/ui/src/components/panels/OutputPanel.tsx | 417 +++++++---- apps/ui/src/components/panels/PanelHeader.tsx | 10 +- .../components/panels/TreeInspectorPanel.tsx | 29 +- .../src/components/shared/DiagnosticBadge.tsx | 14 +- apps/ui/src/components/ui/resizable.tsx | 2 +- apps/ui/src/index.css | 41 +- apps/ui/src/pages/AgentsList.tsx | 2 +- apps/ui/src/pages/Component.tsx | 681 ++++-------------- apps/ui/src/pages/Graph.tsx | 34 +- apps/ui/src/pages/Script.tsx | 80 +- apps/ui/src/pages/Simulate.tsx | 4 +- packages/vscode/package.json | 1 - tsconfig.tsbuildinfo | 1 + 32 files changed, 1192 insertions(+), 1314 deletions(-) delete mode 100644 apps/ui/src/components/NavBar.tsx create mode 100644 tsconfig.tsbuildinfo diff --git a/apps/ui/src/components/Header.tsx b/apps/ui/src/components/Header.tsx index f9dd464..ce73738 100644 --- a/apps/ui/src/components/Header.tsx +++ b/apps/ui/src/components/Header.tsx @@ -6,40 +6,97 @@ */ import { useEffect, useState } from 'react'; -import { Link, useParams, useLocation } from 'react-router'; -import { PiMagnifyingGlass } from 'react-icons/pi'; +import { Link, useParams, useLocation, useNavigate } from 'react-router'; +import { + Search, + PanelLeft, + PanelRight, + PanelBottom, + Code2, + ListTree, + Network, + Play, + Package, + Settings, + Sun, + Moon, + Laptop, + Info, + Palette, + ChevronRight, +} from 'lucide-react'; import { useAgentStore } from '~/store/agentStore'; import { useAppStore } from '~/store'; import { Button } from './ui/button'; import { - VscLayoutSidebarLeft, - VscLayoutSidebarLeftOff, - VscLayoutPanel, - VscLayoutPanelOff, -} from 'react-icons/vsc'; + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuSeparator, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuTrigger, +} from '~/components/ui/dropdown-menu'; +import { Dialog } from '~/components/ui/dialog'; import logo from '~/assets/logo.png'; import { AgentCommandBar } from './AgentCommandBar'; +import { SettingsDialogContent } from '~/components/SettingsDialog'; +import { AboutDialogContent } from '~/components/AboutDialog'; +import { nodeIdToBuilderPath } from '~/components/explorer/astToTreeData'; +import { featureFlags } from '~/lib/feature-flags'; +import { cn } from '~/lib/utils'; + +const allNavTabs = [ + { route: '/script', icon: Code2, label: 'Script', flag: null }, + { + route: '/builder', + icon: ListTree, + label: 'Builder', + flag: 'builder' as const, + }, + { route: '/graph', icon: Network, label: 'Graph', flag: null }, + { + route: '/simulate', + icon: Play, + label: 'Simulate', + flag: 'simulate' as const, + }, + { route: '/component', icon: Package, label: 'Component', flag: null }, +]; + +const navTabs = allNavTabs.filter(t => t.flag === null || featureFlags[t.flag]); export function Header() { const { agentId } = useParams(); const location = useLocation(); + const navigate = useNavigate(); const isStandaloneComponent = !agentId && location.pathname.includes('/component'); - // Subscribe to the specific agent so the header updates when the name changes + const isScriptView = location.pathname.includes('/script'); + const isComponentView = location.pathname.includes('/component'); const agent = useAgentStore(state => agentId ? state.agents[agentId] : null ); const [commandBarOpen, setCommandBarOpen] = useState(false); + const [activeDialog, setActiveDialog] = useState<'settings' | 'about' | null>( + null + ); - // Panel state const showLeftPanel = useAppStore(state => state.layout.showLeftPanel); + const showRightPanel = useAppStore(state => state.layout.showRightPanel); const showBottomPanel = useAppStore(state => state.layout.showBottomPanel); const toggleLeftPanel = useAppStore(state => state.toggleLeftPanel); + const toggleRightPanel = useAppStore(state => state.toggleRightPanel); const toggleBottomPanel = useAppStore(state => state.toggleBottomPanel); + const selectedNodeId = useAppStore(state => state.layout.selectedNodeId); + const theme = useAppStore(state => state.theme.theme); + const setTheme = useAppStore(state => state.setTheme); + const uiTheme = useAppStore(state => state.theme.uiTheme); + const setUiTheme = useAppStore(state => state.setUiTheme); const currentAgentName = agent?.name || 'Untitled Agent'; - // Update browser tab title with agent name useEffect(() => { if (agentId && agent?.name) { document.title = `${agent.name} - AgentScript`; @@ -51,7 +108,6 @@ export function Header() { }; }, [agentId, agent?.name]); - // Keyboard shortcut for command bar (Cmd/Ctrl + P) useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { if ((event.metaKey || event.ctrlKey) && event.key === 'p') { @@ -64,22 +120,158 @@ export function Header() { return () => window.removeEventListener('keydown', handleKeyDown); }, []); + const getRouteWithSelection = (baseRoute: string) => { + if (baseRoute === '/component') { + return agentId + ? `/agents/${agentId}/component/actions` + : '/agents/component/actions'; + } + if (!agentId) return baseRoute; + + if (!selectedNodeId) return `/agents/${agentId}${baseRoute}`; + + if (baseRoute === '/builder') { + return `/agents/${agentId}/builder/${nodeIdToBuilderPath(selectedNodeId)}`; + } + + if (baseRoute === '/graph') { + let topicName: string | undefined; + if ( + selectedNodeId.startsWith('topic-') || + selectedNodeId.startsWith('start_agent-') + ) { + topicName = selectedNodeId.replace(/^(topic|start_agent)-/, ''); + } else if (selectedNodeId.includes('-action-')) { + topicName = selectedNodeId.split('-action-')[0]; + } + if (topicName) return `/agents/${agentId}/graph/${topicName}`; + } + + return `/agents/${agentId}${baseRoute}`; + }; + + const themeOptions = [ + { value: 'system', label: 'System', icon: Laptop }, + { value: 'light', label: 'Light', icon: Sun }, + { value: 'dark', label: 'Dark', icon: Moon }, + ] as const; + + const uiThemeOptions = [ + { value: 'code', label: 'IDE' }, + { value: 'visual', label: 'Visual' }, + ] as const; + + const showNavTabs = Boolean(agentId) || isStandaloneComponent; + return ( -
- {/* Left side - Branding */} - - AgentScript Logo - AgentScript +
+ {/* Brand + breadcrumb */} + + + + AgentScript + - {/* Center - Command Bar Trigger */} -
+ {agentId && ( +
+ + + {currentAgentName} + +
+ )} + + {/* Nav tabs as segmented control */} + {showNavTabs && ( + + )} + + {/* Spacer */} +
+ + {/* Command pill */} +
- {/* Right side - Panel toggles (or spacer for balance) */} - {agentId || isStandaloneComponent ? ( -
- {/* Left Panel Toggle (agent pages only) */} - {agentId && ( - - )} - - {/* Bottom Panel Toggle */} - -
- ) : ( - // Spacer to balance the header layout when on agents list -
-
-
-
-
- )} + + + )} + {(isScriptView || isComponentView) && ( + + + + )} + + { + if (!open) setActiveDialog(null); + }} + > + + + + + + {featureFlags.settingsDialog && ( + <> + setActiveDialog('settings')} + > + + Settings + + + + )} + + + + Brightness + + + {themeOptions.map(option => { + const Icon = option.icon; + const isSelected = theme === option.value; + return ( + setTheme(option.value)} + > + + {option.label} + {isSelected && ( + + )} + + ); + })} + + + {featureFlags.uiThemeSwitcher && ( + + + + UI Theme + + + {uiThemeOptions.map(option => { + const isSelected = uiTheme === option.value; + return ( + setUiTheme(option.value)} + > + {option.label} + {isSelected && ( + + )} + + ); + })} + + + )} + + setActiveDialog('about')}> + + About + + + + {activeDialog === 'settings' && } + {activeDialog === 'about' && } + +
); } + +function IconButton({ + children, + onClick, + title, + active, +}: { + children: React.ReactNode; + onClick: () => void; + title: string; + active?: boolean; +}) { + return ( + + ); +} diff --git a/apps/ui/src/components/IDEFooter.tsx b/apps/ui/src/components/IDEFooter.tsx index 443fb0f..dba3eff 100644 --- a/apps/ui/src/components/IDEFooter.tsx +++ b/apps/ui/src/components/IDEFooter.tsx @@ -6,7 +6,6 @@ */ import { useState, useCallback } from 'react'; -import { VscError, VscWarning } from 'react-icons/vsc'; import { CheckIcon } from 'lucide-react'; import { useLocation } from 'react-router'; import { useAppStore } from '~/store'; @@ -102,55 +101,82 @@ export function IDEFooter() { return ( <> -
- {/* Left section - Diagnostics */} - + + + + + + + + + {/* Right section - Dialect + Cursor position */} -
- + {/* Cursor position */} {isScriptView && editorSelection && ( - <> - - Ln {editorSelection.endLineNumber}, Col{' '} - {editorSelection.endColumn} - - {selectedCount > 0 && ({selectedCount} selected)} - + + Ln {editorSelection.endLineNumber}, Col{' '} + {editorSelection.endColumn} + {selectedCount > 0 && ` · ${selectedCount} sel`} + )}
diff --git a/apps/ui/src/components/NavBar.tsx b/apps/ui/src/components/NavBar.tsx deleted file mode 100644 index 977d606..0000000 --- a/apps/ui/src/components/NavBar.tsx +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (c) 2026, Salesforce, Inc. - * All rights reserved. - * SPDX-License-Identifier: Apache-2.0 - * For full license text, see the LICENSE file in the repo root or https://www.apache.org/licenses/LICENSE-2.0 - */ - -import { useState } from 'react'; -import { useParams, useNavigate, useLocation } from 'react-router'; -import { - VscSymbolNamespace, - VscDebugAltSmall, - VscGear, - VscInfo, - VscColorMode, - VscListFlat, - VscTypeHierarchySub, - VscExtensions, -} from 'react-icons/vsc'; -import { IoLaptop, IoMoon, IoSunny } from 'react-icons/io5'; -import { cn } from '~/lib/utils'; -import { Button } from '~/components/ui/button'; -import { Dialog } from '~/components/ui/dialog'; -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuSeparator, - DropdownMenuSub, - DropdownMenuSubContent, - DropdownMenuSubTrigger, - DropdownMenuTrigger, -} from '~/components/ui/dropdown-menu'; -import { useAppStore } from '~/store'; -import { SettingsDialogContent } from '~/components/SettingsDialog'; -import { AboutDialogContent } from '~/components/AboutDialog'; -import { nodeIdToBuilderPath } from '~/components/explorer/astToTreeData'; -import { featureFlags } from '~/lib/feature-flags'; - -// Default navigation buttons for agent pages -const allNavButtons = [ - { route: '/script', icon: VscSymbolNamespace, label: 'Script', flag: null }, - { - route: '/builder', - icon: VscListFlat, - label: 'Builder', - flag: 'builder' as const, - }, - { route: '/graph', icon: VscTypeHierarchySub, label: 'Graph', flag: null }, - { - route: '/simulate', - icon: VscDebugAltSmall, - label: 'Simulate', - flag: 'simulate' as const, - }, - { route: '/component', icon: VscExtensions, label: 'Component', flag: null }, -]; - -const defaultNavButtons = allNavButtons.filter( - btn => btn.flag === null || featureFlags[btn.flag] -); - -export function NavBar() { - const { agentId } = useParams(); - const navigate = useNavigate(); - const location = useLocation(); - const theme = useAppStore(state => state.theme.theme); - const setTheme = useAppStore(state => state.setTheme); - const uiTheme = useAppStore(state => state.theme.uiTheme); - const setUiTheme = useAppStore(state => state.setUiTheme); - const selectedNodeId = useAppStore(state => state.layout.selectedNodeId); - // Which dialog (if any) is open from the settings menu. - // Using a single state avoids multiple Dialog roots fighting over aria-hidden. - const [activeDialog, setActiveDialog] = useState<'settings' | 'about' | null>( - null - ); - - // Construct routes with agentId when available - const getRoute = (baseRoute: string) => { - if (agentId) { - return `/agents/${agentId}${baseRoute}`; - } - return baseRoute; - }; - - /** - * Build a route that carries the current explorer selection into the target view. - * - Builder: appends the full selectedNodeId as :nodeId - * - Graph: appends the topic name as :topicId (only for topic/start_agent/action nodes) - * - Script / Simulate: base route (Script scrolls to selection on mount) - */ - const getRouteWithSelection = (baseRoute: string) => { - if (!agentId || !selectedNodeId) return getRoute(baseRoute); - - if (baseRoute === '/builder') { - return `/agents/${agentId}/builder/${nodeIdToBuilderPath(selectedNodeId)}`; - } - - if (baseRoute === '/graph') { - // Extract topic name from various node ID formats - let topicName: string | undefined; - if ( - selectedNodeId.startsWith('topic-') || - selectedNodeId.startsWith('start_agent-') - ) { - topicName = selectedNodeId.replace(/^(topic|start_agent)-/, ''); - } else if (selectedNodeId.includes('-action-')) { - topicName = selectedNodeId.split('-action-')[0]; - } - if (topicName) { - return `/agents/${agentId}/graph/${topicName}`; - } - } - - return getRoute(baseRoute); - }; - - const handleThemeChange = (newTheme: 'system' | 'light' | 'dark') => { - setTheme(newTheme); - }; - - const handleUiThemeChange = (newUiTheme: 'code' | 'visual') => { - setUiTheme(newUiTheme); - }; - - const themeOptions = [ - { value: 'system', label: 'System', icon: IoLaptop }, - { value: 'light', label: 'Light', icon: IoSunny }, - { value: 'dark', label: 'Dark', icon: IoMoon }, - ] as const; - - const uiThemeOptions = [ - { value: 'code', label: 'IDE' }, - { value: 'visual', label: 'Visual' }, - ] as const; - - return ( - - ); -} diff --git a/apps/ui/src/components/builder/AddBlockMenu.tsx b/apps/ui/src/components/builder/AddBlockMenu.tsx index 9ca2d4b..66b5367 100644 --- a/apps/ui/src/components/builder/AddBlockMenu.tsx +++ b/apps/ui/src/components/builder/AddBlockMenu.tsx @@ -13,7 +13,7 @@ import { DropdownMenuItem, DropdownMenuTrigger, } from '~/components/ui/dropdown-menu'; -import { VscAdd } from 'react-icons/vsc'; +import { Plus } from 'lucide-react'; import type { FieldType } from '@agentscript/language'; import { getAvailableBlocks, @@ -47,7 +47,7 @@ export function AddBlockMenu({ size="sm" className="gap-1.5 border-dashed text-muted-foreground hover:text-foreground" > - + Add Block diff --git a/apps/ui/src/components/builder/BlockCard.tsx b/apps/ui/src/components/builder/BlockCard.tsx index 8cda81d..6282226 100644 --- a/apps/ui/src/components/builder/BlockCard.tsx +++ b/apps/ui/src/components/builder/BlockCard.tsx @@ -8,7 +8,7 @@ import { useState, useCallback } from 'react'; import { cn } from '~/lib/utils'; import { Button } from '~/components/ui/button'; -import { VscChevronDown, VscChevronRight, VscTrash } from 'react-icons/vsc'; +import { ChevronDown, ChevronRight, Trash2 } from 'lucide-react'; import { PiDotsSixVerticalBold } from 'react-icons/pi'; import { leadingComments, @@ -160,9 +160,9 @@ export function BlockCard({ )} {collapsed ? ( - + ) : ( - + )} {formatFieldName(blockName)} @@ -180,7 +180,7 @@ export function BlockCard({ }} title={`Remove ${formatFieldName(blockName)}`} > - + )} diff --git a/apps/ui/src/components/builder/BuilderCanvas.tsx b/apps/ui/src/components/builder/BuilderCanvas.tsx index 05fe8fe..17e731b 100644 --- a/apps/ui/src/components/builder/BuilderCanvas.tsx +++ b/apps/ui/src/components/builder/BuilderCanvas.tsx @@ -39,7 +39,7 @@ import { ProcedureField } from './fields/ProcedureField'; import { FieldRenderer } from './FieldRenderer'; import { CommentEditor } from './CommentEditor'; import { Button } from '~/components/ui/button'; -import { VscAdd, VscError, VscWarning, VscInfo } from 'react-icons/vsc'; +import { Plus, CircleAlert, TriangleAlert, Info } from 'lucide-react'; import type { StatementKind } from './statements/AddStatementMenu'; // --------------------------------------------------------------------------- @@ -354,7 +354,7 @@ export function BuilderCanvas({ className="h-7 gap-1 text-xs text-muted-foreground" onClick={() => handleAddCompoundBlock(fieldInfo.name)} > - + Add @@ -446,14 +446,14 @@ export function BuilderCanvas({ {blockOnlyDiags.map((d, i) => (
  • {d.severity === DiagnosticSeverity.Error && ( - + )} {d.severity === DiagnosticSeverity.Warning && ( - + )} {(d.severity === DiagnosticSeverity.Information || d.severity === DiagnosticSeverity.Hint) && ( - + )} - + Add comment ); diff --git a/apps/ui/src/components/builder/NamedBlockCard.tsx b/apps/ui/src/components/builder/NamedBlockCard.tsx index c2d11b4..7ce1e3e 100644 --- a/apps/ui/src/components/builder/NamedBlockCard.tsx +++ b/apps/ui/src/components/builder/NamedBlockCard.tsx @@ -9,7 +9,7 @@ import { useState } from 'react'; import { cn } from '~/lib/utils'; import { Button } from '~/components/ui/button'; import { Input } from '~/components/ui/input'; -import { VscChevronDown, VscChevronRight, VscTrash } from 'react-icons/vsc'; +import { ChevronDown, ChevronRight, Trash2 } from 'lucide-react'; import { PiDotsSixVerticalBold } from 'react-icons/pi'; import type { FieldType } from '@agentscript/language'; import type { Diagnostic, Range, Comment } from '@agentscript/types'; @@ -134,9 +134,9 @@ export function NamedBlockCard({ onClick={() => setCollapsed(prev => !prev)} > {collapsed ? ( - + ) : ( - + )} {formatFieldName(blockType)} @@ -181,7 +181,7 @@ export function NamedBlockCard({ onClick={() => onDelete(name)} title={`Remove ${name}`} > - + )} diff --git a/apps/ui/src/components/builder/NamedBlockList.tsx b/apps/ui/src/components/builder/NamedBlockList.tsx index 935fb6d..9d5baae 100644 --- a/apps/ui/src/components/builder/NamedBlockList.tsx +++ b/apps/ui/src/components/builder/NamedBlockList.tsx @@ -9,7 +9,7 @@ import { useState } from 'react'; import { cn } from '~/lib/utils'; import { Button } from '~/components/ui/button'; import { Input } from '~/components/ui/input'; -import { VscAdd } from 'react-icons/vsc'; +import { Plus } from 'lucide-react'; import type { FieldType } from '@agentscript/language'; import type { Diagnostic } from '@agentscript/types'; import { NamedMap } from '@agentscript/language'; @@ -184,7 +184,7 @@ export function NamedBlockList({ className="h-7 gap-1 text-xs text-muted-foreground" onClick={() => setShowAddInput(true)} > - + Add {formatFieldName(blockType)} )} diff --git a/apps/ui/src/components/builder/ReasoningActionCard.tsx b/apps/ui/src/components/builder/ReasoningActionCard.tsx index 4fa06b6..bcb160b 100644 --- a/apps/ui/src/components/builder/ReasoningActionCard.tsx +++ b/apps/ui/src/components/builder/ReasoningActionCard.tsx @@ -17,7 +17,7 @@ import { ComboboxItem, ComboboxEmpty, } from '~/components/ui/combobox'; -import { VscChevronDown, VscChevronRight, VscClose } from 'react-icons/vsc'; +import { ChevronDown, ChevronRight, X } from 'lucide-react'; import { PiDotsSixVerticalBold } from 'react-icons/pi'; import { StringLiteral, isNamedMap, NamedMap } from '@agentscript/language'; import type { Diagnostic, Range } from '@agentscript/types'; @@ -391,7 +391,7 @@ function AvailableWhenRow({ onClick={onRemove} title="Remove available when condition" > - + ); @@ -473,7 +473,7 @@ function AvailableWhenRow({ onClick={onRemove} title="Remove available when condition" > - + ); @@ -533,7 +533,7 @@ function ToClauseRow({ onClick={onRemove} title="Remove transition target" > - + ); @@ -629,7 +629,7 @@ function WithClauseRow({ onClick={onRemove} title="Remove with clause" > - + ); @@ -853,9 +853,9 @@ export function ReasoningActionCard({ onClick={() => setCollapsed(prev => !prev)} > {collapsed ? ( - + ) : ( - + )} Actions diff --git a/apps/ui/src/components/builder/TypedMapEditor.tsx b/apps/ui/src/components/builder/TypedMapEditor.tsx index 308e045..1fb7e1b 100644 --- a/apps/ui/src/components/builder/TypedMapEditor.tsx +++ b/apps/ui/src/components/builder/TypedMapEditor.tsx @@ -10,12 +10,7 @@ import { cn } from '~/lib/utils'; import { Button } from '~/components/ui/button'; import { Input } from '~/components/ui/input'; import { Textarea } from '~/components/ui/textarea'; -import { - VscAdd, - VscTrash, - VscChevronDown, - VscChevronRight, -} from 'react-icons/vsc'; +import { Plus, Trash2, ChevronDown, ChevronRight } from 'lucide-react'; import { PiDotsSixVerticalBold } from 'react-icons/pi'; import type { Diagnostic, Range } from '@agentscript/types'; import { NamedMap } from '@agentscript/language'; @@ -248,9 +243,9 @@ function VariableRow({ {canExpand ? ( expanded ? ( - + ) : ( - + ) ) : ( @@ -306,7 +301,7 @@ function VariableRow({ }} title={`Remove ${name}`} > - + @@ -663,7 +658,7 @@ export function TypedMapEditor({ className="h-7 gap-1 text-xs text-muted-foreground" onClick={() => setShowAdd(true)} > - + Add {itemLabel} )} diff --git a/apps/ui/src/components/builder/fields/EnumField.tsx b/apps/ui/src/components/builder/fields/EnumField.tsx index 32d6fac..f5cd1cc 100644 --- a/apps/ui/src/components/builder/fields/EnumField.tsx +++ b/apps/ui/src/components/builder/fields/EnumField.tsx @@ -13,7 +13,7 @@ import { } from '~/components/ui/dropdown-menu'; import { Button } from '~/components/ui/button'; import { cn } from '~/lib/utils'; -import { VscChevronDown } from 'react-icons/vsc'; +import { ChevronDown } from 'lucide-react'; interface EnumFieldProps { value: string | number | boolean | undefined; @@ -51,7 +51,7 @@ export function EnumField({ )} > {displayValue} - + diff --git a/apps/ui/src/components/builder/statements/AddStatementMenu.tsx b/apps/ui/src/components/builder/statements/AddStatementMenu.tsx index c0a83d9..376b5e2 100644 --- a/apps/ui/src/components/builder/statements/AddStatementMenu.tsx +++ b/apps/ui/src/components/builder/statements/AddStatementMenu.tsx @@ -13,7 +13,7 @@ import { DropdownMenuItem, DropdownMenuTrigger, } from '~/components/ui/dropdown-menu'; -import { VscAdd } from 'react-icons/vsc'; +import { Plus } from 'lucide-react'; export type StatementKind = | 'template' @@ -67,7 +67,7 @@ export function AddStatementMenu({ onAdd, className }: AddStatementMenuProps) { size="sm" className="h-6 gap-1 text-xs text-muted-foreground" > - + Add Statement diff --git a/apps/ui/src/components/builder/statements/StatementCard.tsx b/apps/ui/src/components/builder/statements/StatementCard.tsx index 3031c6e..d4be653 100644 --- a/apps/ui/src/components/builder/statements/StatementCard.tsx +++ b/apps/ui/src/components/builder/statements/StatementCard.tsx @@ -7,7 +7,7 @@ import { cn } from '~/lib/utils'; import { Button } from '~/components/ui/button'; -import { VscTrash } from 'react-icons/vsc'; +import { Trash2 } from 'lucide-react'; import { PiDotsSixVerticalBold } from 'react-icons/pi'; import type { Diagnostic, Range, Comment } from '@agentscript/types'; import { DiagnosticBadge, DiagnosticMessages } from '../DiagnosticBadge'; @@ -150,7 +150,7 @@ export function StatementCard({ className="h-5 w-5 text-muted-foreground opacity-0 group-hover/stmt:opacity-100 hover:text-red-500" onClick={onDelete} > - + diff --git a/apps/ui/src/components/cst-debug/cstNodeIcons.tsx b/apps/ui/src/components/cst-debug/cstNodeIcons.tsx index 25d299b..5c50512 100644 --- a/apps/ui/src/components/cst-debug/cstNodeIcons.tsx +++ b/apps/ui/src/components/cst-debug/cstNodeIcons.tsx @@ -12,36 +12,34 @@ import React from 'react'; import { - VscSymbolClass, - VscSymbolField, - VscSymbolKey, - VscSymbolString, - VscSymbolNumeric, - VscSymbolBoolean, - VscSymbolVariable, - VscSymbolOperator, - VscSymbolInterface, - VscSymbolMethod, - VscSymbolProperty, - VscSymbolFile, - VscSymbolKeyword, - VscSymbolConstant, - VscSymbolSnippet, - VscSymbolRuler, - VscSymbolMisc, - VscComment, - VscArrowRight, - VscGitCompare, - VscBeaker, - VscLink, - VscPlay, - VscEdit, - VscCircleSmallFilled, - VscWarning, - VscError, - VscBracketDot, - VscQuote, -} from 'react-icons/vsc'; + Box, + Hash, + KeyRound, + Quote, + ToggleLeft, + Variable, + Sigma, + PuzzleIcon, + FunctionSquare, + Tag, + FileCode2, + Type, + Snowflake, + Code, + Ruler, + Shapes, + MessageSquare, + ArrowRight, + GitCompare, + Beaker, + Link, + Play, + Pencil, + Circle, + TriangleAlert, + CircleAlert, + Brackets, +} from 'lucide-react'; interface IconConfig { icon: React.ReactElement; @@ -78,7 +76,7 @@ export function getCstNodeIcon( // Error state takes precedence if (hasError) { return { - icon: , + icon: , iconClassName: 'text-red-600 dark:text-red-400', iconBg: '#fee', category: 'other', @@ -88,7 +86,7 @@ export function getCstNodeIcon( // Missing node state if (isMissing) { return { - icon: , + icon: , iconClassName: 'text-orange-600 dark:text-orange-400', iconBg: '#ffedcc', category: 'other', @@ -98,7 +96,7 @@ export function getCstNodeIcon( // Structural nodes if (nodeType === 'source_file') { return { - icon: , + icon: , iconClassName: 'text-blue-600', iconBg: '#e3f2fd', category: 'structural', @@ -107,7 +105,7 @@ export function getCstNodeIcon( if (nodeType === 'block') { return { - icon: , + icon: , iconClassName: 'text-purple-600', iconBg: '#f3e5f5', category: 'structural', @@ -116,7 +114,7 @@ export function getCstNodeIcon( if (nodeType === 'field') { return { - icon: , + icon: , iconClassName: 'text-blue-500', iconBg: '#e3f2fd', category: 'structural', @@ -125,7 +123,7 @@ export function getCstNodeIcon( if (nodeType === 'statement') { return { - icon: , + icon: , iconClassName: 'text-green-600', iconBg: '#e8f5e9', category: 'structural', @@ -134,7 +132,7 @@ export function getCstNodeIcon( if (nodeType === 'clause') { return { - icon: , + icon: , iconClassName: 'text-teal-600', iconBg: '#e0f2f1', category: 'structural', @@ -148,7 +146,7 @@ export function getCstNodeIcon( nodeType === 'text' ) { return { - icon: , + icon: , iconClassName: 'text-orange-600', iconBg: '#fff3e0', category: 'literal', @@ -157,7 +155,7 @@ export function getCstNodeIcon( if (nodeType === 'number') { return { - icon: , + icon: , iconClassName: 'text-green-700', iconBg: '#f1f8e9', category: 'literal', @@ -166,7 +164,7 @@ export function getCstNodeIcon( if (nodeType === 'boolean' || nodeType === 'True' || nodeType === 'False') { return { - icon: , + icon: , iconClassName: 'text-blue-700', iconBg: '#e1f5fe', category: 'literal', @@ -175,7 +173,7 @@ export function getCstNodeIcon( if (nodeType === 'null' || nodeType === 'None') { return { - icon: , + icon: , iconClassName: 'text-gray-600', iconBg: '#f5f5f5', category: 'literal', @@ -185,7 +183,7 @@ export function getCstNodeIcon( // Identifiers and references if (nodeType === 'identifier' || nodeType === 'block_type') { return { - icon: , + icon: , iconClassName: 'text-indigo-600', iconBg: '#e8eaf6', category: 'other', @@ -194,7 +192,7 @@ export function getCstNodeIcon( if (nodeType === 'variable_ref') { return { - icon: , + icon: , iconClassName: 'text-purple-500', iconBg: '#f3e5f5', category: 'other', @@ -204,7 +202,7 @@ export function getCstNodeIcon( // Expressions if (nodeType === 'expression' || nodeType === 'value') { return { - icon: , + icon: , iconClassName: 'text-amber-600', iconBg: '#fff8e1', category: 'other', @@ -216,7 +214,7 @@ export function getCstNodeIcon( nodeType === 'logical_expression' ) { return { - icon: , + icon: , iconClassName: 'text-cyan-600', iconBg: '#e0f7fa', category: 'other', @@ -232,7 +230,7 @@ export function getCstNodeIcon( nodeType === 'logical_operator' ) { return { - icon: , + icon: , iconClassName: 'text-pink-600', iconBg: '#fce4ec', category: 'operator', @@ -248,7 +246,7 @@ export function getCstNodeIcon( nodeType === 'and' ) { return { - icon: , + icon: , iconClassName: 'text-pink-700', iconBg: '#fce4ec', category: 'keyword', @@ -257,7 +255,7 @@ export function getCstNodeIcon( if (nodeType === 'transition' || nodeType === 'to') { return { - icon: , + icon: , iconClassName: 'text-blue-600', iconBg: '#e3f2fd', category: 'keyword', @@ -266,7 +264,7 @@ export function getCstNodeIcon( if (nodeType === 'run' || nodeType === 'set') { return { - icon: , + icon: , iconClassName: 'text-green-600', iconBg: '#e8f5e9', category: 'keyword', @@ -276,7 +274,7 @@ export function getCstNodeIcon( // Type system if (nodeType === 'type' || nodeType === 'simple_type') { return { - icon: , + icon: , iconClassName: 'text-teal-700', iconBg: '#e0f2f1', category: 'other', @@ -290,7 +288,7 @@ export function getCstNodeIcon( nodeType === 'available' ) { return { - icon: , + icon: , iconClassName: 'text-amber-700', iconBg: '#fff8e1', category: 'keyword', @@ -300,7 +298,7 @@ export function getCstNodeIcon( // Special features if (nodeType === 'linked' || nodeType === 'with') { return { - icon: , + icon: , iconClassName: 'text-blue-500', iconBg: '#e3f2fd', category: 'keyword', @@ -309,7 +307,7 @@ export function getCstNodeIcon( if (nodeType === 'slot_filled') { return { - icon: , + icon: , iconClassName: 'text-purple-600', iconBg: '#f3e5f5', category: 'keyword', @@ -318,7 +316,7 @@ export function getCstNodeIcon( if (nodeType === 'placeholder') { return { - icon: , + icon: , iconClassName: 'text-gray-500', iconBg: '#fafafa', category: 'other', @@ -328,7 +326,7 @@ export function getCstNodeIcon( // Comments if (nodeType === 'comment') { return { - icon: , + icon: , iconClassName: 'text-gray-500', iconBg: '#f5f5f5', category: 'other', @@ -338,7 +336,7 @@ export function getCstNodeIcon( // Special arrow token if (nodeType === 'ARROW') { return { - icon: , + icon: , iconClassName: 'text-gray-400', iconBg: '#fafafa', category: 'token', @@ -348,7 +346,7 @@ export function getCstNodeIcon( // Quote marks if (nodeType === '"') { return { - icon: , + icon: , iconClassName: 'text-orange-400', iconBg: '#fafafa', category: 'token', @@ -358,7 +356,7 @@ export function getCstNodeIcon( // Indentation tokens if (nodeType === 'INDENT' || nodeType === 'DEDENT') { return { - icon: , + icon: , iconClassName: 'text-gray-300', iconBg: '#fafafa', category: 'token', @@ -375,7 +373,7 @@ export function getCstNodeIcon( nodeType === '@' ) { return { - icon: , + icon: , iconClassName: 'text-gray-400', iconBg: '#fafafa', category: 'token', @@ -385,7 +383,7 @@ export function getCstNodeIcon( // Default for unnamed nodes or unknown types if (!isNamed) { return { - icon: , + icon: , iconClassName: 'text-gray-400', iconBg: '#fafafa', category: 'token', @@ -394,7 +392,7 @@ export function getCstNodeIcon( // Default fallback for named nodes return { - icon: , + icon: , iconClassName: 'text-gray-600', iconBg: '#f5f5f5', category: 'other', diff --git a/apps/ui/src/components/explorer/TreeView.tsx b/apps/ui/src/components/explorer/TreeView.tsx index ab00ce6..76873f9 100644 --- a/apps/ui/src/components/explorer/TreeView.tsx +++ b/apps/ui/src/components/explorer/TreeView.tsx @@ -5,9 +5,8 @@ * For full license text, see the LICENSE file in the repo root or https://www.apache.org/licenses/LICENSE-2.0 */ -import { ChevronRight, Folder } from 'lucide-react'; +import { ChevronRight, Folder, FileCode2 } from 'lucide-react'; import * as React from 'react'; -import { VscSymbolFile } from 'react-icons/vsc'; import { getBlockTypeConfig } from '~/lib/block-type-config'; import { cn } from '~/lib/utils'; import { @@ -51,7 +50,7 @@ export function TreeView({ - + No Blocks Available @@ -141,10 +140,23 @@ function TreeNodeItem({
    { + if (!selected) { + e.currentTarget.style.background = 'var(--ide-surface-hover)'; + } + }} + onMouseLeave={e => { + if (!selected) { + e.currentTarget.style.background = ''; + } + }} onClick={() => { onNodeSelect(blockType, node.id); if (hasChildren) { @@ -158,13 +170,20 @@ function TreeNodeItem({ e.stopPropagation(); setIsExpanded(!isExpanded); }} - className="shrink-0 rounded p-0.5 hover:bg-gray-300 dark:hover:bg-[#3e3e42]" + className="shrink-0 rounded p-0.5 transition-colors" + onMouseEnter={e => { + e.currentTarget.style.background = 'var(--ide-surface-sunken)'; + }} + onMouseLeave={e => { + e.currentTarget.style.background = ''; + }} > )} @@ -183,17 +202,16 @@ function TreeNodeItem({
    {node.data.label} {node.data.secondaryLabel && ( - + {node.data.secondaryLabel} )} diff --git a/apps/ui/src/components/graph/nodes/DiagnosticHoverCard.tsx b/apps/ui/src/components/graph/nodes/DiagnosticHoverCard.tsx index 1e57fa5..0939291 100644 --- a/apps/ui/src/components/graph/nodes/DiagnosticHoverCard.tsx +++ b/apps/ui/src/components/graph/nodes/DiagnosticHoverCard.tsx @@ -8,7 +8,7 @@ import { DiagnosticSeverity } from '@agentscript/types'; import type { Diagnostic } from '@agentscript/types'; import { cn } from '~/lib/utils'; -import { VscError, VscWarning, VscInfo } from 'react-icons/vsc'; +import { CircleAlert, TriangleAlert, Info } from 'lucide-react'; interface DiagnosticHoverCardProps { diagnostics: Diagnostic[]; @@ -43,19 +43,19 @@ export function DiagnosticHoverCard({ diagnostics }: DiagnosticHoverCardProps) {
    {errors.length > 0 && ( - + {errors.length} )} {warnings.length > 0 && ( - + {warnings.length} )} {infos.length > 0 && ( - + {infos.length} )} @@ -69,14 +69,14 @@ export function DiagnosticHoverCard({ diagnostics }: DiagnosticHoverCardProps) {
  • {d.severity === DiagnosticSeverity.Error && ( - + )} {d.severity === DiagnosticSeverity.Warning && ( - + )} {(d.severity === DiagnosticSeverity.Information || d.severity === DiagnosticSeverity.Hint) && ( - + )} state.layout.showLeftPanel); + const showRightPanel = useAppStore(state => state.layout.showRightPanel); const showBottomPanel = useAppStore(state => state.layout.showBottomPanel); const setShowLeftPanel = useAppStore(state => state.setShowLeftPanel); + const setShowRightPanel = useAppStore(state => state.setShowRightPanel); const setShowBottomPanel = useAppStore(state => state.setShowBottomPanel); const agentscript = useAppStore(state => state.source.agentscript); const setAgentScript = useAppStore(state => state.setAgentScript); @@ -43,6 +45,7 @@ function IDELayoutContent() { // Refs to imperatively control panel collapse state const leftPanelRef = useRef(null); + const rightPanelRef = useRef(null); const bottomPanelRef = useRef(null); // Imperatively control panel collapse state based on store @@ -56,6 +59,16 @@ function IDELayoutContent() { } }, [showLeftPanel]); + useEffect(() => { + if (rightPanelRef.current) { + if (showRightPanel) { + rightPanelRef.current.expand(); + } else { + rightPanelRef.current.collapse(); + } + } + }, [showRightPanel]); + useEffect(() => { if (bottomPanelRef.current) { if (showBottomPanel) { @@ -72,6 +85,9 @@ function IDELayoutContent() { const isAgentsList = !agentId && !location.pathname.includes('/component'); const isStandaloneComponent = !agentId && location.pathname.includes('/component'); + const isScriptView = location.pathname.includes('/script'); + const isComponentView = location.pathname.includes('/component'); + const canShowRightPanel = isScriptView || isComponentView; // Load agent content from localStorage when agentId changes useEffect(() => { @@ -128,46 +144,86 @@ function IDELayoutContent() { const content = ( <> -
    +
    -
    - +
    {isAgentsList ? ( // Agents list page - no panels, just render the outlet
    ) : isStandaloneComponent ? ( - // Standalone component page - no explorer, but keep bottom panel + // Standalone component page - no explorer, but keep bottom + right panels - - + + +
    + +
    +
    - + - setShowBottomPanel(false)} - onExpand={() => setShowBottomPanel(true)} - > - + setShowBottomPanel(false)} + onExpand={() => setShowBottomPanel(true)} + > + + +
    + + {canShowRightPanel && showRightPanel && } + + {canShowRightPanel && ( + setShowRightPanel(false)} + onExpand={() => setShowRightPanel(true)} + > + {showRightPanel && } + + )}
    ) : ( // Agent editor - with resizable panels @@ -207,7 +263,15 @@ function IDELayoutContent() { defaultSize={80} minSize={40} > - +
    + +
    @@ -228,6 +292,29 @@ function IDELayoutContent() { + + {canShowRightPanel ? ( + + ) : ( +
    + )} + + {canShowRightPanel && ( + setShowRightPanel(false)} + onExpand={() => setShowRightPanel(true)} + > + {showRightPanel && } + + )} )}
    diff --git a/apps/ui/src/components/panels/ExplorerPanel.tsx b/apps/ui/src/components/panels/ExplorerPanel.tsx index 75bfe3b..9406cc7 100644 --- a/apps/ui/src/components/panels/ExplorerPanel.tsx +++ b/apps/ui/src/components/panels/ExplorerPanel.tsx @@ -192,12 +192,17 @@ export function ExplorerPanel({ className }: ExplorerPanelProps) { return (
    {/* Header */} - + {/* Tree View - Shows AST block structure */}
    diff --git a/apps/ui/src/components/panels/OutputPanel.tsx b/apps/ui/src/components/panels/OutputPanel.tsx index b16ab81..50ee8e9 100644 --- a/apps/ui/src/components/panels/OutputPanel.tsx +++ b/apps/ui/src/components/panels/OutputPanel.tsx @@ -6,25 +6,10 @@ */ import { type Diagnostic, DiagnosticSeverity } from '~/store/diagnostics'; -import { - VscError, - VscWarning, - VscInfo, - VscClose, - VscWand, - VscCopy, -} from 'react-icons/vsc'; -import { Badge } from '~/components/ui/badge'; +import { X, Wand2, Copy, Sparkles } from 'lucide-react'; import { useMonacoEditor } from '~/contexts/MonacoEditorContext'; import { useAppStore } from '~/store'; -import { - Empty, - EmptyDescription, - EmptyHeader, - EmptyMedia, - EmptyTitle, -} from '~/components/ui/empty'; -import { cn, copyToClipboard } from '~/lib/utils'; +import { copyToClipboard } from '~/lib/utils'; import { useCallback, useState } from 'react'; import { featureFlags } from '~/lib/feature-flags'; import type { CodeAction } from 'vscode-languageserver-protocol'; @@ -44,11 +29,12 @@ export const OutputPanel = () => { const bottomPanelTab = useAppStore(state => state.layout.bottomPanelTab); const setBottomPanelTab = useAppStore(state => state.setBottomPanelTab); - // Count errors and warnings for badge - const problemCount = diagnostics.filter( - diag => - diag.severity === DiagnosticSeverity.Error || - diag.severity === DiagnosticSeverity.Warning + // Count errors and warnings separately + const errorCount = diagnostics.filter( + d => d.severity === DiagnosticSeverity.Error + ).length; + const warningCount = diagnostics.filter( + d => d.severity === DiagnosticSeverity.Warning ).length; const { editor, lspClient } = useMonacoEditor(); @@ -156,140 +142,257 @@ export const OutputPanel = () => { } }, [editor, lspClient, diagnostics]); - // Panel content - shared between expanded and normal views - const panelContent = ( -
    -
    -
    - + const sortedDiagnostics = [...diagnostics].sort((a, b) => { + const sevDiff = (a.severity ?? 0) - (b.severity ?? 0); + if (sevDiff !== 0) return sevDiff; + const aLine = + (a as unknown as { range?: { start?: { line: number } } }).range?.start + ?.line ?? 0; + const bLine = + (b as unknown as { range?: { start?: { line: number } } }).range?.start + ?.line ?? 0; + return aLine - bLine; + }); + + return ( +
    + {/* Header — title + counts on the left, actions on the right */} +
    +
    +

    + {bottomPanelTab === 'suggestions' ? 'Suggestions' : 'Issues'} +

    + {bottomPanelTab === 'problems' && ( +
    + + +
    + )} {featureFlags.suggestionsTab && ( )}
    -
    + +
    {bottomPanelTab === 'problems' && hasFixableDiagnostics && ( - + + Fix all + )} {bottomPanelTab === 'problems' && diagnostics.length > 0 && ( - + + )} - + +
    -
    - {/* Problems Tab */} + {/* Body */} +
    {bottomPanelTab === 'problems' && ( <> - {/* No problems message */} - {diagnostics.length === 0 && ( -

    - No problems have been detected in the agent. -

    - )} - - {/* Problems list - ungrouped */} - {diagnostics.length > 0 && ( -
    - {[...diagnostics] - .sort((a, b) => { - const sevDiff = (a.severity ?? 0) - (b.severity ?? 0); - if (sevDiff !== 0) return sevDiff; - const aLine = - (a as unknown as { range?: { start?: { line: number } } }) - .range?.start?.line ?? 0; - const bLine = - (b as unknown as { range?: { start?: { line: number } } }) - .range?.start?.line ?? 0; - return aLine - bLine; - }) - .map((diag, idx) => ( - - ))} + {diagnostics.length === 0 ? ( +
    + No issues detected in this agent.
    + ) : ( +
      + {sortedDiagnostics.map((diag, idx) => ( + + ))} +
    )} )} - {/* Suggestions Tab */} {featureFlags.suggestionsTab && bottomPanelTab === 'suggestions' && ( -
    - - - - - -
    - AI Suggestions Coming Soon - - Smart suggestions will help you improve your agent code and - catch potential issues. - -
    -
    -
    -
    + } + title="AI suggestions coming soon" + description="Smart suggestions will surface improvements and likely bugs as you work." + /> )}
    ); - - return panelContent; }; +/** Small severity-dot count, e.g. "● 2" for errors. */ +function CountChip({ + color, + count, + label, +}: { + color: string; + count: number; + label: string; +}) { + return ( + 0 ? 'var(--ide-text-primary)' : undefined }} + aria-label={`${count} ${label}`} + > + 0 ? color : 'var(--ide-border-strong)' }} + /> + {count} + + ); +} + +function PanelActionButton({ + children, + onClick, + disabled, + title, +}: { + children: React.ReactNode; + onClick: () => void; + disabled?: boolean; + title: string; +}) { + return ( + + ); +} + +function IconButton({ + children, + onClick, + title, +}: { + children: React.ReactNode; + onClick: () => void; + title: string; +}) { + return ( + + ); +} + +function EmptyState({ + icon, + title, + description, +}: { + icon: React.ReactNode; + title: string; + description: string; +}) { + return ( +
    + + {icon} + +
    +

    + {title} +

    +

    + {description} +

    +
    +
    + ); +} + /** * Individual diagnostic item */ @@ -318,22 +421,16 @@ function DiagnosticItem({ diagnostic }: { diagnostic: Diagnostic }) { const sourceLabel = source; - // Determine icon and color based on severity - const getSeverityIcon = () => { + const severityColor = (() => { switch (severity) { case DiagnosticSeverity.Error: - return ; + return 'var(--ide-danger)'; case DiagnosticSeverity.Warning: - return ( - - ); - case DiagnosticSeverity.Information: - case DiagnosticSeverity.Hint: - return ; + return 'var(--ide-warning)'; default: - return ; + return 'var(--ide-text-subtle)'; } - }; + })(); const handleClick = () => { if (!editor) return; @@ -365,22 +462,44 @@ function DiagnosticItem({ diagnostic }: { diagnostic: Diagnostic }) { : undefined; return ( -
    -
    {getSeverityIcon()}
    - - {message} - - {formattedSource && ( - - {formattedSource} +
  • +
  • + {formattedSource && ( + + {formattedSource} + + )} + + {line}:{col} + + +
  • ); } diff --git a/apps/ui/src/components/panels/PanelHeader.tsx b/apps/ui/src/components/panels/PanelHeader.tsx index 6857f0b..b67ee59 100644 --- a/apps/ui/src/components/panels/PanelHeader.tsx +++ b/apps/ui/src/components/panels/PanelHeader.tsx @@ -25,8 +25,14 @@ export function PanelHeader({ actions, }: PanelHeaderProps) { return ( -
    -

    +
    +

    {title}

    diff --git a/apps/ui/src/components/panels/TreeInspectorPanel.tsx b/apps/ui/src/components/panels/TreeInspectorPanel.tsx index 5a791d2..f26a353 100644 --- a/apps/ui/src/components/panels/TreeInspectorPanel.tsx +++ b/apps/ui/src/components/panels/TreeInspectorPanel.tsx @@ -20,7 +20,7 @@ import { detectDialectId } from '~/lib/detect-dialect'; import { cn, copyToClipboard } from '~/lib/utils'; import { useAppStore } from '~/store'; import { useMonacoEditor } from '~/contexts/MonacoEditorContext'; -import { VscClose, VscCopy } from 'react-icons/vsc'; +import { X, Copy } from 'lucide-react'; import { emitDocument } from '@agentscript/language'; import { findGeneratedPosition, buildCursorMap } from '@agentscript/compiler'; import type { SourceMapping, CursorMap } from '@agentscript/compiler'; @@ -476,9 +476,22 @@ export function TreeInspectorPanel() { }, [cstTreeData]); return ( -
    +
    {/* Header with CST/AST toggle */} -
    +
    Debug: @@ -539,7 +552,7 @@ export function TreeInspectorPanel() { title="Copy CST as S-expression" aria-label="Copy CST as S-expression" > - + )} {treeInspectorMode === 'ast' && ast && ( @@ -550,7 +563,7 @@ export function TreeInspectorPanel() { title="Copy AST as JSON" aria-label="Copy AST as JSON" > - + )} {treeInspectorMode === 'emit' && ( @@ -576,7 +589,7 @@ export function TreeInspectorPanel() { title="Copy emitted source" aria-label="Copy emitted source" > - + )} {treeInspectorMode === 'compiled' && compiledData.text && ( @@ -587,7 +600,7 @@ export function TreeInspectorPanel() { title="Copy compiled JSON" aria-label="Copy compiled JSON" > - + )}
    diff --git a/apps/ui/src/components/shared/DiagnosticBadge.tsx b/apps/ui/src/components/shared/DiagnosticBadge.tsx index e2222f8..596e768 100644 --- a/apps/ui/src/components/shared/DiagnosticBadge.tsx +++ b/apps/ui/src/components/shared/DiagnosticBadge.tsx @@ -8,7 +8,7 @@ import { DiagnosticSeverity } from '@agentscript/types'; import type { Diagnostic } from '@agentscript/types'; import { cn } from '~/lib/utils'; -import { VscError, VscWarning, VscInfo } from 'react-icons/vsc'; +import { CircleAlert, TriangleAlert, Info } from 'lucide-react'; interface DiagnosticBadgeProps { diagnostics: Diagnostic[]; @@ -37,19 +37,19 @@ export function DiagnosticBadge({
    {errors.length > 0 && ( - + {errors.length} )} {warnings.length > 0 && ( - + {warnings.length} )} {infos.length > 0 && ( - + {infos.length} )} @@ -82,14 +82,14 @@ export function DiagnosticMessages({ )} > {d.severity === DiagnosticSeverity.Error && ( - + )} {d.severity === DiagnosticSeverity.Warning && ( - + )} {(d.severity === DiagnosticSeverity.Information || d.severity === DiagnosticSeverity.Hint) && ( - + )} {d.message}

    diff --git a/apps/ui/src/components/ui/resizable.tsx b/apps/ui/src/components/ui/resizable.tsx index a01fdf2..9d376d8 100644 --- a/apps/ui/src/components/ui/resizable.tsx +++ b/apps/ui/src/components/ui/resizable.tsx @@ -46,7 +46,7 @@ function ResizableHandle({ div]:rotate-90', + 'bg-transparent focus-visible:ring-ring focus-visible:outline-hidden relative flex w-2 items-center justify-center after:absolute after:inset-y-0 after:left-1/2 after:w-2 after:-translate-x-1/2 after:bg-transparent focus-visible:ring-1 focus-visible:ring-offset-1 data-[panel-group-direction=vertical]:h-2 data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-2 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 dark:bg-transparent [&[data-panel-group-direction=vertical]>div]:rotate-90', className )} {...props} diff --git a/apps/ui/src/index.css b/apps/ui/src/index.css index ba6508a..28fbacd 100644 --- a/apps/ui/src/index.css +++ b/apps/ui/src/index.css @@ -184,7 +184,7 @@ --background: oklch(0.145 0 0); --foreground: oklch(0.985 0 0); - --card: oklch(0.205 0 0); + --card: rgb(34, 38, 46); --card-foreground: oklch(0.985 0 0); --popover: oklch(0.205 0 0); @@ -228,6 +228,45 @@ --sidebar-ring: oklch(0.556 0 0); } +/* ── IDE Chrome Design Tokens ──────────────────────────────────────────── */ +/* Distinct from VSCode (no flat panels, no #007acc status bar) and from */ +/* Agentforce Builder (no uniform white plane). Soft-elevated surfaces, */ +/* a single restrained Salesforce-blue accent used sparingly. */ + +:root { + --ide-surface: #f4f5f8; + --ide-surface-elevated: #ffffff; + --ide-surface-sunken: #ebecef; + --ide-surface-hover: #eef0f4; + --ide-border-subtle: #e3e5ea; + --ide-border-strong: #d0d3da; + --ide-text-primary: #1a1f2a; + --ide-text-muted: #5a6271; + --ide-text-subtle: #8b93a3; + --ide-accent: #0176d3; + --ide-accent-soft: rgba(1, 118, 211, 0.1); + --ide-accent-fg: #ffffff; + --ide-danger: #ba1a1a; + --ide-warning: #b96d00; +} + +.dark { + --ide-surface: #1a1d23; + --ide-surface-elevated: #22262e; + --ide-surface-sunken: #14161b; + --ide-surface-hover: #2a2e37; + --ide-border-subtle: #2c313a; + --ide-border-strong: #3a414d; + --ide-text-primary: #e6e8ec; + --ide-text-muted: #9aa1ad; + --ide-text-subtle: #6b7280; + --ide-accent: #1b96ff; + --ide-accent-soft: rgba(27, 150, 255, 0.16); + --ide-accent-fg: #061121; + --ide-danger: #ff8a8a; + --ide-warning: #f5c97a; +} + /* ── Graph Design Tokens ────────────────────────────────────────────────── */ :root { diff --git a/apps/ui/src/pages/AgentsList.tsx b/apps/ui/src/pages/AgentsList.tsx index 1b586fd..fe15bf5 100644 --- a/apps/ui/src/pages/AgentsList.tsx +++ b/apps/ui/src/pages/AgentsList.tsx @@ -98,7 +98,7 @@ export function AgentsList() { }; return ( -
    +
    {/* Header */}
    diff --git a/apps/ui/src/pages/Component.tsx b/apps/ui/src/pages/Component.tsx index 830fb76..6b93120 100644 --- a/apps/ui/src/pages/Component.tsx +++ b/apps/ui/src/pages/Component.tsx @@ -8,8 +8,12 @@ /** * Component page — parseComponent() playground. * - * Left: Monaco editor (agentscript language, agentforce dialect) + kind selector. - * Right: CST / AST / Emit debug tabs showing the parsed component output. + * Renders only the Monaco editor + kind selector. CST / AST / Emit output is + * surfaced through the shared right-side TreeInspectorPanel (see IDELayout + + * the header's right-panel toggle). We push the component's parse result into + * the source store so the inspector has something to render, and we + * save/restore the previous source-store contents on unmount so returning to + * an agent view does not lose its data. */ import { useState, useMemo, useCallback, useEffect, useRef } from 'react'; @@ -21,19 +25,9 @@ import { parseComponentDebug, getComponentKindOptions, } from '@agentscript/agentforce'; -import type { SerializedCSTNode } from '@agentscript/agentforce'; -import { - cstToDebugTree, - convertCstToTreeViewNode, -} from '~/components/cst-debug/cstToDebugTree'; -import { useCursorSync } from '~/hooks/useCursorSync'; -import { cstToSExpr } from '~/lib/cst-to-sexpr'; -import { TreeView } from '~/components/explorer/TreeView'; -import { ObjectInspector } from '~/components/inspector/ObjectInspector'; import { PanelHeader } from '~/components/panels/PanelHeader'; -import { cn, copyToClipboard } from '~/lib/utils'; import { useAppStore } from '~/store'; -import { VscCopy, VscDiscard } from 'react-icons/vsc'; +import { Undo2 } from 'lucide-react'; import { Dialog, DialogContent, @@ -43,15 +37,8 @@ import { DialogFooter, } from '~/components/ui/dialog'; import { Button } from '~/components/ui/button'; -import { - ResizablePanelGroup, - ResizablePanel, - ResizableHandle, -} from '~/components/ui/resizable'; - -// --------------------------------------------------------------------------- -// Component kind options (from @agentscript/agentforce package) -// --------------------------------------------------------------------------- +import type { AgentScriptAST } from '~/lib/parser'; +import type { SerializedNode } from '~/store/source'; const KIND_OPTIONS = getComponentKindOptions(); @@ -71,70 +58,47 @@ const DEFAULT_SOURCES: Record = { modality: `modality voice:\n config:\n voice_id: "EQx6HGDYjkDpcli6vorJ"\n outbound_speed: 1.0\n outbound_stability: 0.5\n outbound_similarity: 0.75\n outbound_filler_sentences:\n - "Let me look into it..."\n - "Give me a moment..."`, }; -// --------------------------------------------------------------------------- -// Debug tab types -// --------------------------------------------------------------------------- - -type DebugTab = 'cst' | 'ast' | 'emit' | 'code'; - -// --------------------------------------------------------------------------- -// Component page -// --------------------------------------------------------------------------- - -function CopyButton({ - visible, - onClick, - title, -}: { - visible: boolean; - onClick: () => void; - title: string; -}) { - if (!visible) return null; - return ( - - ); -} +type DebugTab = 'cst' | 'ast' | 'emit'; export function Component() { const { kind: kindParam, agentId } = useParams(); const navigate = useNavigate(); const [searchParams] = useSearchParams(); - // Derive kind from URL param, default to 'actions' const validKinds = KIND_OPTIONS.map(o => o.value); const selectedKind = kindParam && validKinds.includes(kindParam) ? kindParam : 'actions'; - // Derive debug tab from ?debug= query param (default: cst = no param) - const debugParam = searchParams.get('debug'); - const debugTab: DebugTab = - debugParam === 'cst' || - debugParam === 'ast' || - debugParam === 'emit' || - debugParam === 'code' - ? debugParam - : 'cst'; - - // Navigate to set debug tab via URL (cst = default, omit param) - const setDebugTab = useCallback( - (tab: DebugTab) => { - const basePath = agentId - ? `/agents/${agentId}/component` - : '/agents/component'; - const qs = tab !== 'cst' ? `?debug=${tab}` : ''; - void navigate(`${basePath}/${selectedKind}${qs}`); - }, - [agentId, navigate, selectedKind] + // Sync ?debug= <-> treeInspectorMode store + const treeInspectorMode = useAppStore( + state => state.layout.treeInspectorMode ); + const setTreeInspectorMode = useAppStore(state => state.setTreeInspectorMode); + + useEffect(() => { + const debugParam = searchParams.get('debug'); + const next: DebugTab | undefined = + debugParam === 'cst' || debugParam === 'ast' || debugParam === 'emit' + ? (debugParam as DebugTab) + : undefined; + if (next && next !== treeInspectorMode) { + setTreeInspectorMode(next); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [searchParams]); + + useEffect(() => { + const current = searchParams.get('debug'); + const desired = treeInspectorMode === 'cst' ? null : treeInspectorMode; + if (desired === current) return; + if (treeInspectorMode === 'compiled') return; // not applicable here + const basePath = agentId + ? `/agents/${agentId}/component` + : '/agents/component'; + const qs = desired ? `?debug=${desired}` : ''; + void navigate(`${basePath}/${selectedKind}${qs}`, { replace: true }); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [treeInspectorMode]); // Redirect to canonical URL if kind param is missing/invalid useEffect(() => { @@ -150,34 +114,48 @@ export function Component() { // eslint-disable-next-line react-hooks/exhaustive-deps }, [kindParam]); - // Persisted sources per kind from Zustand store const componentSources = useAppStore( state => state.component.componentSources ); const resetComponentSource = useAppStore(state => state.resetComponentSource); - // Current source: persisted value or default const source = componentSources[selectedKind] ?? DEFAULT_SOURCES[selectedKind] ?? ''; - const [parsedComponent, setParsedComponent] = useState(undefined); - const [cstRoot, setCstRoot] = useState(null); const [parseError, setParseError] = useState(null); const setDiagnostics = useAppStore(state => state.setDiagnostics); - - // Save/restore main script diagnostics when entering/leaving Component page - const savedDiagnosticsRef = useRef( - useAppStore.getState().diagnostics.diagnostics - ); + const setParseResult = useAppStore(state => state.setParseResult); + const setAgentScript = useAppStore(state => state.setAgentScript); + + // Save/restore source-store + diagnostics on mount/unmount so returning to + // an agent view does not lose its parsed state. + const savedRef = useRef({ + diagnostics: useAppStore.getState().diagnostics.diagnostics, + agentscript: useAppStore.getState().source.agentscript, + cst: useAppStore.getState().source.cst, + ast: useAppStore.getState().source.ast, + lintStore: useAppStore.getState().source.lintStore, + }); useEffect(() => { - savedDiagnosticsRef.current = - useAppStore.getState().diagnostics.diagnostics; + const s = useAppStore.getState(); + savedRef.current = { + diagnostics: s.diagnostics.diagnostics, + agentscript: s.source.agentscript, + cst: s.source.cst, + ast: s.source.ast, + lintStore: s.source.lintStore, + }; return () => { - // Restore the main script's diagnostics on unmount - setDiagnostics(savedDiagnosticsRef.current); + setDiagnostics(savedRef.current.diagnostics); + setAgentScript(savedRef.current.agentscript); + setParseResult({ + cst: savedRef.current.cst, + ast: savedRef.current.ast, + lintStore: savedRef.current.lintStore, + }); }; - }, [setDiagnostics]); + }, [setDiagnostics, setAgentScript, setParseResult]); const theme = useAppStore(state => state.theme.theme); const actualTheme = useMemo(() => { @@ -190,24 +168,12 @@ export function Component() { return theme; }, [theme]); - // -- Cursor position tracking (0-based, in editor coordinates) -- - const [cursorPosition, setCursorPosition] = useState<{ - line: number; - column: number; - } | null>(null); - const [selectedCstNodeId, setSelectedCstNodeId] = useState< - string | undefined - >(); - const isNavigatingFromInspector = useRef(false); - - // -- Left side: Monaco editor -- const editorContainerRef = useRef(null); const editorRef = useRef(null); const selectedKindRef = useRef(selectedKind); selectedKindRef.current = selectedKind; const [languageInitialized, setLanguageInitialized] = useState(false); - // Initialize language (themes, tokenization) + agentforce parser useEffect(() => { const setup = async () => { try { @@ -222,7 +188,6 @@ export function Component() { void setup(); }, []); - // Create Monaco editor after language is ready useEffect(() => { if (!editorContainerRef.current || !languageInitialized) return; @@ -248,45 +213,32 @@ export function Component() { }); editorRef.current = editor; + useAppStore.getState().setMonacoEditor(editor); - // Sync editor changes to persisted store editor.onDidChangeModelContent(() => { const value = editor.getValue(); useAppStore.getState().setComponentSource(selectedKindRef.current, value); }); - // Track cursor position for CST/AST sync - editor.onDidChangeCursorSelection(e => { - if (isNavigatingFromInspector.current) { - isNavigatingFromInspector.current = false; - return; - } - setCursorPosition({ - line: e.selection.endLineNumber - 1, - column: e.selection.endColumn - 1, - }); - }); - - // Track cursor position for CST/AST sync editor.onDidChangeCursorSelection(e => { - if (isNavigatingFromInspector.current) { - isNavigatingFromInspector.current = false; - return; - } - setCursorPosition({ - line: e.selection.endLineNumber - 1, - column: e.selection.endColumn - 1, + useAppStore.getState().setEditorSelection({ + startLineNumber: e.selection.startLineNumber, + startColumn: e.selection.startColumn, + endLineNumber: e.selection.endLineNumber, + endColumn: e.selection.endColumn, + positionRow: e.selection.endLineNumber - 1, + positionColumn: e.selection.endColumn - 1, }); }); return () => { editor.dispose(); editorRef.current = null; + useAppStore.getState().setMonacoEditor(null); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [languageInitialized]); - // Update editor theme when it changes useEffect(() => { if (editorRef.current) { const themeName = @@ -298,7 +250,6 @@ export function Component() { } }, [actualTheme]); - // When kind changes, navigate to new URL and update editor const handleKindChange = useCallback( (kind: string) => { const basePath = agentId @@ -311,7 +262,6 @@ export function Component() { [agentId, navigate, searchParams] ); - // Reset confirmation dialog const [resetDialogOpen, setResetDialogOpen] = useState(false); const handleReset = useCallback(() => { @@ -319,10 +269,8 @@ export function Component() { setResetDialogOpen(false); }, [resetComponentSource, selectedKind]); - // Whether the source has been modified from default const isModified = selectedKind in componentSources; - // Sync editor content when source changes (e.g. kind change via URL, reset) useEffect(() => { if (editorRef.current) { const model = editorRef.current.getModel(); @@ -332,8 +280,9 @@ export function Component() { } }, [source]); - // -- Parsing logic -- - const parseTimerRef = useRef>(); + const parseTimerRef = useRef | undefined>( + undefined + ); const doParse = useCallback(() => { if (!languageInitialized) return; @@ -341,19 +290,32 @@ export function Component() { setParseError(null); try { - const result = parseComponentDebug(source, selectedKind); - setCstRoot(result.cst); - setParsedComponent(result.component ?? undefined); + const result = parseComponentDebug( + source, + selectedKind as Parameters[1] + ); + setParseResult({ + cst: result.cst as unknown as SerializedNode | null, + ast: (result.component ?? null) as unknown as AgentScriptAST | null, + lintStore: null, + }); + setAgentScript(source); setDiagnostics(result.diagnostics); } catch (e) { setParseError(e instanceof Error ? e.message : String(e)); - setCstRoot(null); - setParsedComponent(undefined); + setParseResult({ cst: null, ast: null, lintStore: null }); + setAgentScript(source); setDiagnostics([]); } - }, [source, selectedKind, languageInitialized, setDiagnostics]); + }, [ + source, + selectedKind, + languageInitialized, + setDiagnostics, + setParseResult, + setAgentScript, + ]); - // Auto-parse with debounce useEffect(() => { clearTimeout(parseTimerRef.current); parseTimerRef.current = setTimeout(() => { @@ -362,403 +324,54 @@ export function Component() { return () => clearTimeout(parseTimerRef.current); }, [doParse]); - // -- Right side: CST tree data -- - const cstTreeData = useMemo(() => { - if (!cstRoot) return []; - return cstToDebugTree(cstRoot); - }, [cstRoot]); - - const cstTreeViewData = useMemo(() => { - return cstTreeData.map(node => convertCstToTreeViewNode(node)); - }, [cstTreeData]); - - // -- Cursor ↔ CST/AST sync (shared hook) -- - const navigateEditor = useCallback( - (pos: { line: number; character: number }) => { - const editor = editorRef.current; - if (!editor) return; - - isNavigatingFromInspector.current = true; - - const lineNumber = pos.line + 1; - const column = pos.character + 1; - - editor.setPosition({ lineNumber, column }); - editor.revealPositionInCenter({ lineNumber, column }); - editor.focus(); - }, - [] - ); - - const { - selectedCstNodeAtCursor, - astHighlightPath, - expandedKeys, - navigateToCstNode, - navigateToRange, - } = useCursorSync({ - cursorPosition, - mode: debugTab, - cstTreeData, - ast: parsedComponent, - astRootName: 'Component', - navigateEditor, - }); - - // Cursor-derived CST node takes priority; fall back to last-clicked node - const effectiveCstNodeId = - debugTab === 'cst' && selectedCstNodeAtCursor - ? selectedCstNodeAtCursor - : selectedCstNodeId; - - // CST node click → navigate editor cursor - const handleCstNodeSelect = useCallback( - (_kind: string, id: string) => { - setSelectedCstNodeId(id); - navigateToCstNode(id); - }, - [navigateToCstNode] - ); - - // AST node click → navigate editor cursor - const handleInspectorNavigate = useCallback( - (range: { start: { line: number; character: number } }) => { - navigateToRange(range); - }, - [navigateToRange] - ); - - // -- Right side: Emit text -- - const emittedText = useMemo(() => { - if (parsedComponent == null) return ''; - try { - const obj = parsedComponent as Record; - if (typeof obj.__emit === 'function') { - return ( - obj.__emit as (ctx: { indent: number; tabSize: number }) => string - )({ indent: 0, tabSize: 4 }); - } - return JSON.stringify( - parsedComponent, - (k, v) => - k === '__cst' || k === 'parent' ? undefined : (v as unknown), - 2 - ); - } catch { - return '// Could not emit'; - } - }, [parsedComponent]); - - // -- Right side: Code example text -- - const codeExampleText = useMemo(() => { - // Escape backticks and backslashes for template literal - const escaped = source - .replace(/\\/g, '\\\\') - .replace(/`/g, '\\`') - .replace(/\$\{/g, '\\${'); - return `import { parseComponent } from '@agentscript/agentforce'; - -const result = parseComponent(\`${escaped}\`, '${selectedKind}');`; - }, [source, selectedKind]); - - // -- Copy handlers -- - const handleCopyCst = useCallback(() => { - if (!cstRoot) return; - const sexpr = cstToSExpr(cstRoot); - copyToClipboard(sexpr, 'CST copied to clipboard'); - }, [cstRoot]); - - const handleCopyAst = useCallback(() => { - if (parsedComponent == null) return; - const json = JSON.stringify( - parsedComponent, - (key, value: unknown) => - key === '__cst' || key === 'parent' ? undefined : value, - 2 - ); - copyToClipboard(json, 'AST copied to clipboard'); - }, [parsedComponent]); - - const handleCopyEmit = useCallback(() => { - if (!emittedText) return; - copyToClipboard(emittedText, 'Emitted text copied to clipboard'); - }, [emittedText]); - - const handleCopyCode = useCallback(() => { - if (!codeExampleText) return; - copyToClipboard(codeExampleText, 'Code copied to clipboard'); - }, [codeExampleText]); - - // -- Right side: Emit Monaco editor -- - const emitEditorContainerRef = useRef(null); - const emitEditorRef = useRef( - null - ); - - useEffect(() => { - if (debugTab !== 'emit' || !emitEditorContainerRef.current) { - if (emitEditorRef.current) { - emitEditorRef.current.dispose(); - emitEditorRef.current = null; - } - return; - } - - const themeName = - actualTheme === 'dark' ? 'agentscript-dark' : 'agentscript-light'; - - const editor = monaco.editor.create(emitEditorContainerRef.current, { - value: emittedText, - language: 'agentscript', - theme: themeName, - readOnly: true, - domReadOnly: true, - minimap: { enabled: false }, - fontSize: 14, - lineNumbers: 'on', - wordWrap: 'on', - scrollBeyondLastLine: false, - automaticLayout: true, - 'semanticHighlighting.enabled': true, - renderLineHighlight: 'none', - cursorStyle: 'line-thin', - }); - - emitEditorRef.current = editor; - requestAnimationFrame(() => editor.layout()); - - return () => { - editor.dispose(); - emitEditorRef.current = null; - }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [debugTab, actualTheme]); - - // Update emit editor content - useEffect(() => { - if (emitEditorRef.current && debugTab === 'emit') { - const model = emitEditorRef.current.getModel(); - if (model && model.getValue() !== emittedText) { - model.setValue(emittedText); - } - } - }, [emittedText, debugTab]); - - // -- Right side: Code example Monaco editor -- - const codeEditorContainerRef = useRef(null); - const codeEditorRef = useRef( - null - ); - - useEffect(() => { - if (debugTab !== 'code' || !codeEditorContainerRef.current) { - if (codeEditorRef.current) { - codeEditorRef.current.dispose(); - codeEditorRef.current = null; - } - return; - } - - const themeName = actualTheme === 'dark' ? 'vs-dark' : 'vs'; - - const editor = monaco.editor.create(codeEditorContainerRef.current, { - value: codeExampleText, - language: 'typescript', - theme: themeName, - readOnly: true, - domReadOnly: true, - minimap: { enabled: false }, - fontSize: 14, - lineNumbers: 'on', - wordWrap: 'on', - scrollBeyondLastLine: false, - automaticLayout: true, - renderLineHighlight: 'none', - cursorStyle: 'line-thin', - }); - - codeEditorRef.current = editor; - requestAnimationFrame(() => editor.layout()); - - return () => { - editor.dispose(); - codeEditorRef.current = null; - }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [debugTab, actualTheme]); - - // Update code editor content - useEffect(() => { - if (codeEditorRef.current && debugTab === 'code') { - const model = codeEditorRef.current.getModel(); - if (model && model.getValue() !== codeExampleText) { - model.setValue(codeExampleText); - } - } - }, [codeExampleText, debugTab]); - return ( -
    +
    -
    - - {/* Left: Editor + kind selector */} - -
    - {/* Kind selector bar */} -
    -
    - - -
    -
    - {parseError && ( - - {parseError.slice(0, 50)} - - )} - {isModified && ( -
    - -
    - )} -
    -
    - {/* Monaco editor */} -
    -
    - - - - - {/* Right: Debug output */} - -
    - {/* Debug tab header */} -
    - - Output: - - {(['cst', 'ast', 'emit', 'code'] as const).map(tab => ( - - ))} -
    - - - - -
    -
    - - {/* Debug content */} -
    +
    +
    + + +
    +
    + {parseError && ( + - {debugTab === 'cst' ? ( - cstTreeViewData.length > 0 ? ( - - ) : ( - - ) - ) : debugTab === 'ast' ? ( - parsedComponent != null ? ( - - ) : ( - - ) - ) : debugTab === 'emit' ? ( -
    - ) : debugTab === 'code' ? ( -
    - ) : null} + {parseError.slice(0, 50)} + + )} + {isModified && ( +
    +
    -
    - - + )} +
    +
    +
    - {/* Reset confirmation dialog */} @@ -785,15 +398,3 @@ const result = parseComponent(\`${escaped}\`, '${selectedKind}');`;
    ); } - -// --------------------------------------------------------------------------- -// Helpers -// --------------------------------------------------------------------------- - -function EmptyState({ text }: { text: string }) { - return ( -
    - {text} -
    - ); -} diff --git a/apps/ui/src/pages/Graph.tsx b/apps/ui/src/pages/Graph.tsx index e76f0c4..da107eb 100644 --- a/apps/ui/src/pages/Graph.tsx +++ b/apps/ui/src/pages/Graph.tsx @@ -35,6 +35,7 @@ import { graphNodeTypes } from '~/components/graph/nodes'; import { graphEdgeTypes } from '~/components/graph/edges'; import { ErrorBoundary } from '~/components/shared/ErrorBoundary'; import { ChevronLeft } from 'lucide-react'; +import { PanelHeader } from '~/components/panels/PanelHeader'; import { Button } from '~/components/ui/button'; import { findPathEdges } from '~/lib/graph-path'; import { GraphDrawer } from '~/components/graph/GraphDrawer'; @@ -228,23 +229,22 @@ function GraphInner() { return (
    - {/* Header */} -
    - {isTopicDetail && ( - - )} -

    - {isTopicDetail ? `Topic: ${topicId}` : 'Agent Graph'} -

    -
    + + + + ) : null + } + /> {/* Graph Canvas */}
    diff --git a/apps/ui/src/pages/Script.tsx b/apps/ui/src/pages/Script.tsx index 4c00a51..4c60585 100644 --- a/apps/ui/src/pages/Script.tsx +++ b/apps/ui/src/pages/Script.tsx @@ -11,14 +11,6 @@ import { MonacoEditor } from '~/components/MonacoEditor'; import { useMemo, useEffect, useRef } from 'react'; import { useAppStore } from '~/store'; import { PanelHeader } from '~/components/panels/PanelHeader'; -import { TreeInspectorPanel } from '~/components/panels/TreeInspectorPanel'; -import { - ResizablePanelGroup, - ResizablePanel, - ResizableHandle, -} from '~/components/ui/resizable'; -import { Button } from '~/components/ui/button'; -import { IoBug, IoBugOutline } from 'react-icons/io5'; import { astToTreeData, findTreeNodeById, @@ -34,10 +26,6 @@ export function Script() { const toggleScriptEditorExpand = useAppStore( state => state.toggleScriptEditorExpand ); - const showTreeInspector = useAppStore( - state => state.layout.showTreeInspector - ); - const toggleTreeInspector = useAppStore(state => state.toggleTreeInspector); const agent = useAgentStore(state => agentId ? state.agents[agentId] : null ); @@ -67,19 +55,11 @@ export function Script() { } }, [agentId, agent]); - // Use initialSelection ONLY on first mount to restore saved cursor position - // DO NOT track agent.editorSelection changes after mount - that causes unwanted scrolling - // when the debounced selection save fires after cursor movements const initialSelection = useMemo(() => { - // Only return the selection if we're mounting for the first time - // We can't easily detect "first mount" here, so we rely on the MonacoEditor - // component to only use initialSelection once when it first renders return agent?.editorSelection ?? null; // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); // Empty deps = only run once on mount + }, []); - // On mount, scroll to the currently selected explorer node (e.g. when - // navigating from Builder/Graph back to Script). const monacoEditor = useAppStore(state => state.source.monacoEditor); const ast = useAppStore(state => state.source.ast) as AgentScriptAST | null; const selectedNodeId = useAppStore(state => state.layout.selectedNodeId); @@ -105,7 +85,6 @@ export function Script() { } }, [selectedNodeId, monacoEditor, ast]); - // Resolve system theme to actual theme const systemTheme = typeof window !== 'undefined' && window.matchMedia('(prefers-color-scheme: dark)').matches @@ -114,64 +93,19 @@ export function Script() { const actualTheme = theme === 'system' ? systemTheme : theme; return ( -
    +
    - - - } />
    - - - - - {showTreeInspector && ( - <> - - - - - - )} - +
    ); diff --git a/apps/ui/src/pages/Simulate.tsx b/apps/ui/src/pages/Simulate.tsx index 2bbdd6c..13e4904 100644 --- a/apps/ui/src/pages/Simulate.tsx +++ b/apps/ui/src/pages/Simulate.tsx @@ -5,7 +5,7 @@ * For full license text, see the LICENSE file in the repo root or https://www.apache.org/licenses/LICENSE-2.0 */ -import { VscDebugAltSmall } from 'react-icons/vsc'; +import { Play } from 'lucide-react'; import { Empty, EmptyContent, @@ -21,7 +21,7 @@ export function Simulate() { - + Simulator diff --git a/packages/vscode/package.json b/packages/vscode/package.json index 602aa55..0578a5c 100644 --- a/packages/vscode/package.json +++ b/packages/vscode/package.json @@ -6,7 +6,6 @@ "private": true, "publisher": "Salesforce", "license": "Apache-2.0", - "engines": { "vscode": "^1.98.0" }, diff --git a/tsconfig.tsbuildinfo b/tsconfig.tsbuildinfo new file mode 100644 index 0000000..43df711 --- /dev/null +++ b/tsconfig.tsbuildinfo @@ -0,0 +1 @@ +{"root":["./apps/docs/docusaurus.config.ts","./apps/docs/extract-types.ts","./apps/docs/generate-sidebar.ts","./apps/docs/sidebars.ts","./apps/docs/validate-code-blocks.ts","./apps/docs/src/components/TypeDefinition.tsx","./apps/docs/src/plugins/remark-code-import.ts","./apps/ui/vite.config.ts","./apps/ui/src/App.tsx","./apps/ui/src/main.tsx","./apps/ui/src/components/AboutDialog.tsx","./apps/ui/src/components/AgentCommandBar.tsx","./apps/ui/src/components/DialectSelector.tsx","./apps/ui/src/components/Footer.tsx","./apps/ui/src/components/Header.tsx","./apps/ui/src/components/IDEFooter.tsx","./apps/ui/src/components/MarketingHeader.tsx","./apps/ui/src/components/MonacoEditor.tsx","./apps/ui/src/components/NavBar.d.ts","./apps/ui/src/components/SettingsDialog.tsx","./apps/ui/src/components/ThemeSwitch.tsx","./apps/ui/src/components/builder/AddBlockMenu.tsx","./apps/ui/src/components/builder/BlockCard.tsx","./apps/ui/src/components/builder/BuilderCanvas.tsx","./apps/ui/src/components/builder/CommentEditor.tsx","./apps/ui/src/components/builder/DiagnosticBadge.tsx","./apps/ui/src/components/builder/FieldRenderer.tsx","./apps/ui/src/components/builder/NamedBlockCard.tsx","./apps/ui/src/components/builder/NamedBlockList.tsx","./apps/ui/src/components/builder/ReasoningActionCard.tsx","./apps/ui/src/components/builder/ReasoningActionList.tsx","./apps/ui/src/components/builder/TypedMapEditor.tsx","./apps/ui/src/components/builder/fields/BooleanField.tsx","./apps/ui/src/components/builder/fields/EnumField.tsx","./apps/ui/src/components/builder/fields/NumberField.tsx","./apps/ui/src/components/builder/fields/ProcedureField.tsx","./apps/ui/src/components/builder/fields/ReferenceField.tsx","./apps/ui/src/components/builder/fields/StringField.tsx","./apps/ui/src/components/builder/fields/TemplateEditor.tsx","./apps/ui/src/components/builder/hooks/useBuilderMutation.ts","./apps/ui/src/components/builder/hooks/useFieldDiagnostics.ts","./apps/ui/src/components/builder/hooks/useSchemaIntrospection.ts","./apps/ui/src/components/builder/statements/AddStatementMenu.tsx","./apps/ui/src/components/builder/statements/AvailableWhenEditor.tsx","./apps/ui/src/components/builder/statements/IfStatementEditor.tsx","./apps/ui/src/components/builder/statements/RunStatementEditor.tsx","./apps/ui/src/components/builder/statements/SetClauseEditor.tsx","./apps/ui/src/components/builder/statements/StatementCard.tsx","./apps/ui/src/components/builder/statements/StatementList.tsx","./apps/ui/src/components/builder/statements/TemplateStatement.tsx","./apps/ui/src/components/builder/statements/TransitionEditor.tsx","./apps/ui/src/components/builder/statements/WithClauseEditor.tsx","./apps/ui/src/components/cst-debug/cstNodeIcons.tsx","./apps/ui/src/components/cst-debug/cstToDebugTree.ts","./apps/ui/src/components/explorer/CstDebugPanel.tsx","./apps/ui/src/components/explorer/TreeView.tsx","./apps/ui/src/components/explorer/astToTreeData.ts","./apps/ui/src/components/explorer/cstToTreeData.ts","./apps/ui/src/components/explorer/loroTreeToExplorerData.ts","./apps/ui/src/components/graph/ActionDrawerContent.tsx","./apps/ui/src/components/graph/ConditionalBuilderView.tsx","./apps/ui/src/components/graph/ConditionalCodeView.tsx","./apps/ui/src/components/graph/ConditionalDrawerContent.tsx","./apps/ui/src/components/graph/GraphDrawer.tsx","./apps/ui/src/components/graph/NodeDrawerContent.tsx","./apps/ui/src/components/graph/edges/AnimatedEdge.tsx","./apps/ui/src/components/graph/edges/ConditionalEdge.tsx","./apps/ui/src/components/graph/edges/LoopBackEdge.tsx","./apps/ui/src/components/graph/edges/index.ts","./apps/ui/src/components/graph/nodes/ActionNode.tsx","./apps/ui/src/components/graph/nodes/BuildInstructionsNode.tsx","./apps/ui/src/components/graph/nodes/CompoundTopicNode.tsx","./apps/ui/src/components/graph/nodes/ConditionalNode.tsx","./apps/ui/src/components/graph/nodes/DiagnosticHoverCard.tsx","./apps/ui/src/components/graph/nodes/LlmNode.tsx","./apps/ui/src/components/graph/nodes/NodeHandles.tsx","./apps/ui/src/components/graph/nodes/PhaseNode.tsx","./apps/ui/src/components/graph/nodes/ReasoningGroupNode.tsx","./apps/ui/src/components/graph/nodes/RunNode.tsx","./apps/ui/src/components/graph/nodes/SetNode.tsx","./apps/ui/src/components/graph/nodes/StartNode.tsx","./apps/ui/src/components/graph/nodes/TemplateNode.tsx","./apps/ui/src/components/graph/nodes/TopicNode.tsx","./apps/ui/src/components/graph/nodes/TransitionNode.tsx","./apps/ui/src/components/graph/nodes/diagnosticBorder.ts","./apps/ui/src/components/graph/nodes/index.ts","./apps/ui/src/components/inspector/ObjectInspector.tsx","./apps/ui/src/components/inspector/findAstPath.ts","./apps/ui/src/components/layouts/IDELayout.tsx","./apps/ui/src/components/panels/ExplorerPanel.tsx","./apps/ui/src/components/panels/OutputPanel.tsx","./apps/ui/src/components/panels/PanelHeader.tsx","./apps/ui/src/components/panels/TreeInspectorPanel.tsx","./apps/ui/src/components/shared/DiagnosticBadge.tsx","./apps/ui/src/components/shared/ErrorBoundary.tsx","./apps/ui/src/components/ui/badge.tsx","./apps/ui/src/components/ui/button.tsx","./apps/ui/src/components/ui/combobox.tsx","./apps/ui/src/components/ui/command.tsx","./apps/ui/src/components/ui/dialog.tsx","./apps/ui/src/components/ui/dropdown-menu.tsx","./apps/ui/src/components/ui/empty.tsx","./apps/ui/src/components/ui/icon.tsx","./apps/ui/src/components/ui/input-group.tsx","./apps/ui/src/components/ui/input.tsx","./apps/ui/src/components/ui/kbd.tsx","./apps/ui/src/components/ui/label.tsx","./apps/ui/src/components/ui/popover.tsx","./apps/ui/src/components/ui/resizable.tsx","./apps/ui/src/components/ui/sheet.tsx","./apps/ui/src/components/ui/sonner.tsx","./apps/ui/src/components/ui/switch.tsx","./apps/ui/src/components/ui/textarea.tsx","./apps/ui/src/components/ui/toggle.tsx","./apps/ui/src/components/ui/icons/types.ts","./apps/ui/src/contexts/MonacoEditorContext.tsx","./apps/ui/src/hooks/useCursorSync.ts","./apps/ui/src/hooks/useTheme.ts","./apps/ui/src/lib/ast-schemas.ts","./apps/ui/src/lib/ast-to-graph.ts","./apps/ui/src/lib/ast-utils.ts","./apps/ui/src/lib/block-type-config.tsx","./apps/ui/src/lib/cst-builder-queries.ts","./apps/ui/src/lib/cst-helpers.ts","./apps/ui/src/lib/cst-mutator.ts","./apps/ui/src/lib/cst-serializer.ts","./apps/ui/src/lib/cst-to-sexpr.ts","./apps/ui/src/lib/detect-dialect.ts","./apps/ui/src/lib/dev-helpers.ts","./apps/ui/src/lib/dialects.ts","./apps/ui/src/lib/feature-flags.ts","./apps/ui/src/lib/graph-layout.ts","./apps/ui/src/lib/graph-path.ts","./apps/ui/src/lib/graph-tokens.ts","./apps/ui/src/lib/load-test-scripts.ts","./apps/ui/src/lib/lsp-client.ts","./apps/ui/src/lib/monaco-diff-handler.ts","./apps/ui/src/lib/monaco-language.ts","./apps/ui/src/lib/monaco-lsp-providers.ts","./apps/ui/src/lib/parser.ts","./apps/ui/src/lib/schema-introspection.ts","./apps/ui/src/lib/storage.ts","./apps/ui/src/lib/utils.ts","./apps/ui/src/lib/examples/index.ts","./apps/ui/src/lib/loro-cst/parser.ts","./apps/ui/src/pages/AgentsList.tsx","./apps/ui/src/pages/Builder.tsx","./apps/ui/src/pages/Component.tsx","./apps/ui/src/pages/Graph.tsx","./apps/ui/src/pages/NotFound.tsx","./apps/ui/src/pages/Script.tsx","./apps/ui/src/pages/Simulate.tsx","./apps/ui/src/pages/Welcome.tsx","./apps/ui/src/store/agentStore.ts","./apps/ui/src/store/component.ts","./apps/ui/src/store/counterStore.ts","./apps/ui/src/store/diagnostics.ts","./apps/ui/src/store/index.ts","./apps/ui/src/store/layout.ts","./apps/ui/src/store/source.ts","./apps/ui/src/store/themeStore.ts","./apps/ui/src/store/userStore.ts","./apps/ui/src/workers/agentscript-lsp.worker.ts","./dialect/agentfabric/dist/index.d.ts","./dialect/agentfabric/dist/pkg-meta.d.ts","./dialect/agentfabric/dist/schema.d.ts","./dialect/agentfabric/dist/lint/index.d.ts","./dialect/agentfabric/dist/lint/utils.d.ts","./dialect/agentfabric/dist/lint/passes/agentfabric-semantic.d.ts","./dialect/agentfabric/dist/lint/passes/index.d.ts","./dialect/agentfabric/dist/lint/passes/suppress-tools-namespace-undefined-reference.d.ts","./dialect/agentfabric/dist/lint/passes/rules/agentic-llm-rules.d.ts","./dialect/agentfabric/dist/lint/passes/rules/connection-rules.d.ts","./dialect/agentfabric/dist/lint/passes/rules/echo-rules.d.ts","./dialect/agentfabric/dist/lint/passes/rules/on-exit-rules.d.ts","./dialect/agentfabric/dist/lint/passes/rules/output-structure-rules.d.ts","./dialect/agentfabric/dist/lint/passes/rules/reasoning-instructions-rules.d.ts","./dialect/agentfabric/dist/lint/passes/rules/shared.d.ts","./dialect/agentfabric/dist/lint/passes/rules/switch-rules.d.ts","./dialect/agentfabric/dist/lint/passes/rules/trigger-rules.d.ts","./dialect/agentfabric/dist/tests/dialect.test.d.ts","./dialect/agentfabric/dist/tests/lint.test.d.ts","./dialect/agentfabric/dist/tests/test-utils.d.ts","./dialect/agentfabric/src/index.ts","./dialect/agentfabric/src/pkg-meta.ts","./dialect/agentfabric/src/schema.ts","./dialect/agentfabric/src/lint/index.ts","./dialect/agentfabric/src/lint/utils.ts","./dialect/agentfabric/src/lint/passes/agentfabric-semantic.ts","./dialect/agentfabric/src/lint/passes/index.ts","./dialect/agentfabric/src/lint/passes/suppress-tools-namespace-undefined-reference.ts","./dialect/agentfabric/src/lint/passes/rules/agentic-llm-rules.ts","./dialect/agentfabric/src/lint/passes/rules/connection-rules.ts","./dialect/agentfabric/src/lint/passes/rules/echo-rules.ts","./dialect/agentfabric/src/lint/passes/rules/on-exit-rules.ts","./dialect/agentfabric/src/lint/passes/rules/output-structure-rules.ts","./dialect/agentfabric/src/lint/passes/rules/reasoning-instructions-rules.ts","./dialect/agentfabric/src/lint/passes/rules/shared.ts","./dialect/agentfabric/src/lint/passes/rules/switch-rules.ts","./dialect/agentfabric/src/lint/passes/rules/trigger-rules.ts","./dialect/agentfabric/src/tests/test-utils.ts","./dialect/agentforce/dist/index.d.ts","./dialect/agentforce/dist/pkg-meta.d.ts","./dialect/agentforce/dist/schema.d.ts","./dialect/agentforce/dist/lint/index.d.ts","./dialect/agentforce/dist/lint/passes/action-target.d.ts","./dialect/agentforce/dist/lint/passes/complex-data-type.d.ts","./dialect/agentforce/dist/lint/passes/config-validation.d.ts","./dialect/agentforce/dist/lint/passes/connection-validation.d.ts","./dialect/agentforce/dist/lint/passes/hyperclassifier.d.ts","./dialect/agentforce/dist/lint/passes/index.d.ts","./dialect/agentforce/dist/lint/passes/system-message-variables.d.ts","./dialect/agentforce/dist/lint/passes/variable-validation.d.ts","./dialect/agentforce/dist/lint/passes/connected-agents/bound-inputs.d.ts","./dialect/agentforce/dist/lint/passes/connected-agents/index.d.ts","./dialect/agentforce/dist/lint/passes/connected-agents/no-transition.d.ts","./dialect/agentforce/dist/lint/passes/connected-agents/target-validation.d.ts","./dialect/agentforce/dist/lint/passes/connected-agents/template-reference.d.ts","./dialect/agentforce/dist/tests/additional-parameter.test.d.ts","./dialect/agentforce/dist/tests/anonymous-topic.test.d.ts","./dialect/agentforce/dist/tests/backwards-compat.test.d.ts","./dialect/agentforce/dist/tests/connected-subagent-validation.test.d.ts","./dialect/agentforce/dist/tests/connection-block.test.d.ts","./dialect/agentforce/dist/tests/lint.test.d.ts","./dialect/agentforce/dist/tests/modality.test.d.ts","./dialect/agentforce/dist/tests/security.test.d.ts","./dialect/agentforce/dist/tests/template-restrictions.test.d.ts","./dialect/agentforce/dist/tests/test-utils.d.ts","./dialect/agentforce/src/index.ts","./dialect/agentforce/src/pkg-meta.ts","./dialect/agentforce/src/schema.ts","./dialect/agentforce/src/lint/index.ts","./dialect/agentforce/src/lint/passes/action-target.ts","./dialect/agentforce/src/lint/passes/complex-data-type.ts","./dialect/agentforce/src/lint/passes/config-validation.ts","./dialect/agentforce/src/lint/passes/connection-validation.ts","./dialect/agentforce/src/lint/passes/hyperclassifier.ts","./dialect/agentforce/src/lint/passes/index.ts","./dialect/agentforce/src/lint/passes/system-message-variables.ts","./dialect/agentforce/src/lint/passes/variable-validation.ts","./dialect/agentforce/src/lint/passes/connected-agents/bound-inputs.ts","./dialect/agentforce/src/lint/passes/connected-agents/index.ts","./dialect/agentforce/src/lint/passes/connected-agents/no-transition.ts","./dialect/agentforce/src/lint/passes/connected-agents/target-validation.ts","./dialect/agentforce/src/lint/passes/connected-agents/template-reference.ts","./dialect/agentforce/src/tests/test-utils.ts","./dialect/agentscript/dist/index.d.ts","./dialect/agentscript/dist/pkg-meta.d.ts","./dialect/agentscript/dist/schema.d.ts","./dialect/agentscript/dist/lint/index.d.ts","./dialect/agentscript/dist/lint/passes/action-io.d.ts","./dialect/agentscript/dist/lint/passes/action-type-check.d.ts","./dialect/agentscript/dist/lint/passes/index.d.ts","./dialect/agentscript/dist/lint/passes/reasoning-actions.d.ts","./dialect/agentscript/dist/lint/passes/type-map.d.ts","./dialect/agentscript/dist/tests/blocks.test.d.ts","./dialect/agentscript/dist/tests/codegen-conformance.test.d.ts","./dialect/agentscript/dist/tests/completions.test.d.ts","./dialect/agentscript/dist/tests/discriminant.test.d.ts","./dialect/agentscript/dist/tests/emit-fuzz.test.d.ts","./dialect/agentscript/dist/tests/error-recovery.test.d.ts","./dialect/agentscript/dist/tests/expressions.test.d.ts","./dialect/agentscript/dist/tests/extra_emit.test.d.ts","./dialect/agentscript/dist/tests/field-builder.test.d.ts","./dialect/agentscript/dist/tests/lint.test.d.ts","./dialect/agentscript/dist/tests/primitives.test.d.ts","./dialect/agentscript/dist/tests/references.test.d.ts","./dialect/agentscript/dist/tests/reserved-name.test.d.ts","./dialect/agentscript/dist/tests/roundtrip.test.d.ts","./dialect/agentscript/dist/tests/sequences.test.d.ts","./dialect/agentscript/dist/tests/statements.test.d.ts","./dialect/agentscript/dist/tests/symbols.test.d.ts","./dialect/agentscript/dist/tests/template-restrictions.test.d.ts","./dialect/agentscript/dist/tests/test-utils.d.ts","./dialect/agentscript/dist/tests/type-safety.test.d.ts","./dialect/agentscript/src/index.ts","./dialect/agentscript/src/pkg-meta.ts","./dialect/agentscript/src/schema.ts","./dialect/agentscript/src/test.ts","./dialect/agentscript/src/lint/index.ts","./dialect/agentscript/src/lint/passes/action-io.ts","./dialect/agentscript/src/lint/passes/action-type-check.ts","./dialect/agentscript/src/lint/passes/index.ts","./dialect/agentscript/src/lint/passes/reasoning-actions.ts","./dialect/agentscript/src/lint/passes/type-map.ts","./dialect/agentscript/src/tests/test-utils.ts","./packages/agentforce/vitest.config.ts","./packages/agentforce/dist/index.d.ts","./packages/agentforce/src/browser-iife.ts","./packages/agentforce/src/browser-js-iife.ts","./packages/agentforce/src/browser.ts","./packages/agentforce/src/children-sync.ts","./packages/agentforce/src/compile.ts","./packages/agentforce/src/component-kind.ts","./packages/agentforce/src/document.ts","./packages/agentforce/src/emit-component.ts","./packages/agentforce/src/index.ts","./packages/agentforce/src/mutate-component.ts","./packages/agentforce/src/parse-component.ts","./packages/agentforce/src/parse.ts","./packages/agentforce/src/parser.ts","./packages/agentforce/src/semantic-tokens.ts","./packages/agentforce/src/types.ts","./packages/agentforce/src/validate.ts","./packages/agentforce/src/wasm-constants-generated.d.ts","./packages/agentforce/src/wasm-constants.d.ts","./packages/agentforce/tests/test-utils.ts","./packages/compiler/vitest.config.ts","./packages/compiler/dist/ast-helpers.d.ts","./packages/compiler/dist/compile.d.ts","./packages/compiler/dist/compiler-context.d.ts","./packages/compiler/dist/constants.d.ts","./packages/compiler/dist/diagnostics.d.ts","./packages/compiler/dist/index.d.ts","./packages/compiler/dist/parsed-types.d.ts","./packages/compiler/dist/sourced.d.ts","./packages/compiler/dist/types.d.ts","./packages/compiler/dist/utils.d.ts","./packages/compiler/dist/agent-version/compile-agent-version.d.ts","./packages/compiler/dist/config/agent-configuration.d.ts","./packages/compiler/dist/config/compile-security.d.ts","./packages/compiler/dist/config/context-variables.d.ts","./packages/compiler/dist/config/model-config.d.ts","./packages/compiler/dist/context/compile-context.d.ts","./packages/compiler/dist/expressions/compile-expression.d.ts","./packages/compiler/dist/expressions/compile-template.d.ts","./packages/compiler/dist/generated/agent-dsl.d.ts","./packages/compiler/dist/modality/compile-modality.d.ts","./packages/compiler/dist/modality/extract-sequence.d.ts","./packages/compiler/dist/nodes/compile-actions.d.ts","./packages/compiler/dist/nodes/compile-connected-agent-node.d.ts","./packages/compiler/dist/nodes/compile-directives.d.ts","./packages/compiler/dist/nodes/compile-escalate.d.ts","./packages/compiler/dist/nodes/compile-node.d.ts","./packages/compiler/dist/nodes/compile-reasoning-actions.d.ts","./packages/compiler/dist/nodes/compile-router-node.d.ts","./packages/compiler/dist/nodes/compile-set-variables.d.ts","./packages/compiler/dist/nodes/compile-subagent-node.d.ts","./packages/compiler/dist/nodes/compile-supervision.d.ts","./packages/compiler/dist/nodes/compile-tool.d.ts","./packages/compiler/dist/nodes/compile-transition.d.ts","./packages/compiler/dist/nodes/compile-utils.d.ts","./packages/compiler/dist/nodes/resolve-action-type.d.ts","./packages/compiler/dist/source-map/range-mappings.d.ts","./packages/compiler/dist/source-map/source-map-serializer.d.ts","./packages/compiler/dist/source-map/source-map-utils.d.ts","./packages/compiler/dist/surfaces/compile-surfaces.d.ts","./packages/compiler/dist/system-messages/compile-system-messages.d.ts","./packages/compiler/dist/validation/validate-knowledge-refs.d.ts","./packages/compiler/dist/validation/validate-output.d.ts","./packages/compiler/dist/variables/state-variables.d.ts","./packages/compiler/dist/variables/variable-utils.d.ts","./packages/compiler/scripts/generate-comparison-report.ts","./packages/compiler/scripts/generate-outputs.ts","./packages/compiler/src/ast-helpers.ts","./packages/compiler/src/compile.ts","./packages/compiler/src/compiler-context.ts","./packages/compiler/src/constants.ts","./packages/compiler/src/diagnostics.ts","./packages/compiler/src/index.ts","./packages/compiler/src/parsed-types.ts","./packages/compiler/src/sourced.ts","./packages/compiler/src/types.ts","./packages/compiler/src/utils.ts","./packages/compiler/src/agent-version/compile-agent-version.ts","./packages/compiler/src/config/agent-configuration.ts","./packages/compiler/src/config/compile-security.ts","./packages/compiler/src/config/context-variables.ts","./packages/compiler/src/config/model-config.ts","./packages/compiler/src/context/compile-context.ts","./packages/compiler/src/expressions/compile-expression.ts","./packages/compiler/src/expressions/compile-template.ts","./packages/compiler/src/generated/agent-dsl.ts","./packages/compiler/src/modality/compile-modality.ts","./packages/compiler/src/modality/extract-sequence.ts","./packages/compiler/src/nodes/compile-actions.ts","./packages/compiler/src/nodes/compile-connected-agent-node.ts","./packages/compiler/src/nodes/compile-directives.ts","./packages/compiler/src/nodes/compile-escalate.ts","./packages/compiler/src/nodes/compile-node.ts","./packages/compiler/src/nodes/compile-reasoning-actions.ts","./packages/compiler/src/nodes/compile-router-node.ts","./packages/compiler/src/nodes/compile-set-variables.ts","./packages/compiler/src/nodes/compile-subagent-node.ts","./packages/compiler/src/nodes/compile-supervision.ts","./packages/compiler/src/nodes/compile-tool.ts","./packages/compiler/src/nodes/compile-transition.ts","./packages/compiler/src/nodes/compile-utils.ts","./packages/compiler/src/nodes/resolve-action-type.ts","./packages/compiler/src/source-map/range-mappings.ts","./packages/compiler/src/source-map/source-map-serializer.ts","./packages/compiler/src/source-map/source-map-utils.ts","./packages/compiler/src/surfaces/compile-surfaces.ts","./packages/compiler/src/system-messages/compile-system-messages.ts","./packages/compiler/src/validation/validate-knowledge-refs.ts","./packages/compiler/src/validation/validate-output.ts","./packages/compiler/src/variables/state-variables.ts","./packages/compiler/src/variables/variable-utils.ts","./packages/compiler/test/compare-outputs.ts","./packages/compiler/test/test-utils.ts","./packages/compiler/test/validate-batch.ts","./packages/language/dist/blocks.d.ts","./packages/language/dist/dialect-annotation.d.ts","./packages/language/dist/dialect-annotation.test.d.ts","./packages/language/dist/dialect-config.d.ts","./packages/language/dist/dialect-resolution.d.ts","./packages/language/dist/dialect-resolution.test.d.ts","./packages/language/dist/index.d.ts","./packages/language/dist/parse-and-lint.d.ts","./packages/language/dist/semantic-tokens.d.ts","./packages/language/dist/service.d.ts","./packages/language/dist/core/block-factory.d.ts","./packages/language/dist/core/block.d.ts","./packages/language/dist/core/children.d.ts","./packages/language/dist/core/collection-block-factory.d.ts","./packages/language/dist/core/comment-attacher.d.ts","./packages/language/dist/core/diagnostics.d.ts","./packages/language/dist/core/dialect.d.ts","./packages/language/dist/core/emit.d.ts","./packages/language/dist/core/error-recovery.d.ts","./packages/language/dist/core/expressions.d.ts","./packages/language/dist/core/factory-types.d.ts","./packages/language/dist/core/factory-utils.d.ts","./packages/language/dist/core/field-builder.d.ts","./packages/language/dist/core/guards.d.ts","./packages/language/dist/core/indentation.d.ts","./packages/language/dist/core/indentation.test.d.ts","./packages/language/dist/core/index.d.ts","./packages/language/dist/core/named-block-factory.d.ts","./packages/language/dist/core/named-map.d.ts","./packages/language/dist/core/primitives-constants.d.ts","./packages/language/dist/core/primitives.d.ts","./packages/language/dist/core/runtime-contracts.test.d.ts","./packages/language/dist/core/sequence.d.ts","./packages/language/dist/core/statements.d.ts","./packages/language/dist/core/typed-declarations.d.ts","./packages/language/dist/core/typed-map-factory.d.ts","./packages/language/dist/core/types.d.ts","./packages/language/dist/core/analysis/ast-utils.d.ts","./packages/language/dist/core/analysis/ast-walkers.d.ts","./packages/language/dist/core/analysis/completions.d.ts","./packages/language/dist/core/analysis/hover-resolver.d.ts","./packages/language/dist/core/analysis/index.d.ts","./packages/language/dist/core/analysis/lint.d.ts","./packages/language/dist/core/analysis/position-index.d.ts","./packages/language/dist/core/analysis/references.d.ts","./packages/language/dist/core/analysis/schema-hover.d.ts","./packages/language/dist/core/analysis/schema-hover.test.d.ts","./packages/language/dist/core/analysis/scope.d.ts","./packages/language/dist/core/analysis/snippet-gen.d.ts","./packages/language/dist/core/analysis/snippet-gen.test.d.ts","./packages/language/dist/core/analysis/symbols.d.ts","./packages/language/dist/lint/constraint-validation.d.ts","./packages/language/dist/lint/duplicate-keys.d.ts","./packages/language/dist/lint/duplicate-keys.test.d.ts","./packages/language/dist/lint/empty-block.d.ts","./packages/language/dist/lint/expression-validation.d.ts","./packages/language/dist/lint/index.d.ts","./packages/language/dist/lint/lint-utils.d.ts","./packages/language/dist/lint/position-index.d.ts","./packages/language/dist/lint/required-fields.d.ts","./packages/language/dist/lint/schema-walker.d.ts","./packages/language/dist/lint/singular-collection.d.ts","./packages/language/dist/lint/singular-collection.test.d.ts","./packages/language/dist/lint/symbol-table.d.ts","./packages/language/dist/lint/undefined-reference.d.ts","./packages/language/dist/lint/unreachable-code.d.ts","./packages/language/dist/lint/unused-variable.d.ts","./packages/language/src/blocks.ts","./packages/language/src/dialect-annotation.ts","./packages/language/src/dialect-config.ts","./packages/language/src/dialect-resolution.ts","./packages/language/src/index.ts","./packages/language/src/parse-and-lint.ts","./packages/language/src/semantic-tokens.ts","./packages/language/src/service.ts","./packages/language/src/core/block-factory.ts","./packages/language/src/core/block.ts","./packages/language/src/core/children.ts","./packages/language/src/core/collection-block-factory.ts","./packages/language/src/core/comment-attacher.ts","./packages/language/src/core/diagnostics.ts","./packages/language/src/core/dialect.ts","./packages/language/src/core/emit.ts","./packages/language/src/core/error-recovery.ts","./packages/language/src/core/expressions.ts","./packages/language/src/core/factory-types.ts","./packages/language/src/core/factory-utils.ts","./packages/language/src/core/field-builder.ts","./packages/language/src/core/guards.ts","./packages/language/src/core/indentation.ts","./packages/language/src/core/index.ts","./packages/language/src/core/named-block-factory.ts","./packages/language/src/core/named-map.ts","./packages/language/src/core/primitives-constants.ts","./packages/language/src/core/primitives.ts","./packages/language/src/core/sequence.ts","./packages/language/src/core/statements.ts","./packages/language/src/core/typed-declarations.ts","./packages/language/src/core/typed-map-factory.ts","./packages/language/src/core/types.ts","./packages/language/src/core/analysis/ast-utils.ts","./packages/language/src/core/analysis/ast-walkers.ts","./packages/language/src/core/analysis/completions.ts","./packages/language/src/core/analysis/hover-resolver.ts","./packages/language/src/core/analysis/index.ts","./packages/language/src/core/analysis/lint.ts","./packages/language/src/core/analysis/position-index.ts","./packages/language/src/core/analysis/references.ts","./packages/language/src/core/analysis/schema-hover.ts","./packages/language/src/core/analysis/scope.ts","./packages/language/src/core/analysis/snippet-gen.ts","./packages/language/src/core/analysis/symbols.ts","./packages/language/src/lint/constraint-validation.ts","./packages/language/src/lint/duplicate-keys.ts","./packages/language/src/lint/empty-block.ts","./packages/language/src/lint/expression-validation.ts","./packages/language/src/lint/index.ts","./packages/language/src/lint/lint-utils.ts","./packages/language/src/lint/position-index.ts","./packages/language/src/lint/required-fields.ts","./packages/language/src/lint/schema-walker.ts","./packages/language/src/lint/singular-collection.ts","./packages/language/src/lint/symbol-table.ts","./packages/language/src/lint/undefined-reference.ts","./packages/language/src/lint/unreachable-code.ts","./packages/language/src/lint/unused-variable.ts","./packages/lsp/vitest.config.ts","./packages/lsp/dist/dialect-annotation.d.ts","./packages/lsp/dist/dialect-registry.d.ts","./packages/lsp/dist/document-store.d.ts","./packages/lsp/dist/index.d.ts","./packages/lsp/dist/lsp-config.d.ts","./packages/lsp/dist/pipeline.d.ts","./packages/lsp/dist/server-core.d.ts","./packages/lsp/dist/adapters/types.d.ts","./packages/lsp/dist/providers/code-actions.d.ts","./packages/lsp/dist/providers/completion.d.ts","./packages/lsp/dist/providers/definition.d.ts","./packages/lsp/dist/providers/hover.d.ts","./packages/lsp/dist/providers/references.d.ts","./packages/lsp/dist/providers/rename.d.ts","./packages/lsp/dist/providers/semantic-tokens.d.ts","./packages/lsp/dist/providers/symbols.d.ts","./packages/lsp/src/dialect-annotation.ts","./packages/lsp/src/dialect-registry.ts","./packages/lsp/src/document-store.ts","./packages/lsp/src/index.ts","./packages/lsp/src/lsp-config.ts","./packages/lsp/src/pipeline.ts","./packages/lsp/src/server-core.ts","./packages/lsp/src/test-utils.ts","./packages/lsp/src/adapters/types.ts","./packages/lsp/src/providers/code-actions.ts","./packages/lsp/src/providers/completion.ts","./packages/lsp/src/providers/definition.ts","./packages/lsp/src/providers/hover.ts","./packages/lsp/src/providers/references.ts","./packages/lsp/src/providers/rename.ts","./packages/lsp/src/providers/semantic-tokens.ts","./packages/lsp/src/providers/symbols.ts","./packages/lsp-browser/dist/index.d.ts","./packages/lsp-browser/src/index.ts","./packages/lsp-server/vitest.config.ts","./packages/lsp-server/dist/config.d.ts","./packages/lsp-server/dist/index.d.ts","./packages/lsp-server/src/config.ts","./packages/lsp-server/src/index.ts","./packages/monaco/src/hover-provider.ts","./packages/monaco/src/index.ts","./packages/monaco/src/monaco-agentscript.ts","./packages/monaco/src/parser-api.ts","./packages/monaco/src/parser-worker.ts","./packages/monaco/src/schema-resolver.ts","./packages/monaco/src/theme.ts","./packages/monaco/src/vite-env.d.ts","./packages/monaco/src/worker-parser.ts","./packages/parser/dist/adapter.d.ts","./packages/parser/dist/api.d.ts","./packages/parser/dist/index.d.ts","./packages/parser/dist/index.tree-sitter.d.ts","./packages/parser/dist/tree-sitter-backend.d.ts","./packages/parser/dist/ts-backend.d.ts","./packages/parser/dist/types.d.ts","./packages/parser/dist/wasm-backend.d.ts","./packages/parser/src/adapter.ts","./packages/parser/src/api.ts","./packages/parser/src/index.tree-sitter.ts","./packages/parser/src/index.ts","./packages/parser/src/tree-sitter-backend.ts","./packages/parser/src/ts-backend.ts","./packages/parser/src/types.ts","./packages/parser/src/wasm-backend.ts","./packages/parser-javascript/vitest.config.ts","./packages/parser-javascript/dist/cst-node.d.ts","./packages/parser-javascript/dist/errors.d.ts","./packages/parser-javascript/dist/expressions.d.ts","./packages/parser-javascript/dist/highlighter.d.ts","./packages/parser-javascript/dist/index.d.ts","./packages/parser-javascript/dist/lexer.d.ts","./packages/parser-javascript/dist/parser.d.ts","./packages/parser-javascript/dist/token.d.ts","./packages/parser-javascript/src/cst-node.ts","./packages/parser-javascript/src/errors.ts","./packages/parser-javascript/src/expressions.ts","./packages/parser-javascript/src/highlighter.ts","./packages/parser-javascript/src/index.ts","./packages/parser-javascript/src/lexer.ts","./packages/parser-javascript/src/parser.ts","./packages/parser-javascript/src/token.ts","./packages/parser-javascript/test/error-recovery-metrics.ts","./packages/parser-javascript/test/fuzz-utils.ts","./packages/parser-javascript/test/perf-generators.ts","./packages/parser-javascript/test/perf.bench.ts","./packages/parser-javascript/test/run-perf.ts","./packages/parser-javascript/test/test-utils.ts","./packages/parser-tree-sitter/bindings/node/index.d.ts","./packages/types/dist/comment.d.ts","./packages/types/dist/cst.d.ts","./packages/types/dist/diagnostic.d.ts","./packages/types/dist/index.d.ts","./packages/types/dist/position.d.ts","./packages/types/dist/syntax-node.d.ts","./packages/types/src/comment.ts","./packages/types/src/cst.ts","./packages/types/src/diagnostic.ts","./packages/types/src/index.ts","./packages/types/src/position.ts","./packages/types/src/syntax-node.ts","./packages/vscode/src/coreExtensionUtils.ts","./packages/vscode/src/extension.ts","./packages/vscode/src/telemetry.ts","./scripts/extract-diagnostics.ts","./scripts/sync-vscode-theme.ts"],"errors":true,"version":"5.9.3"} \ No newline at end of file