@polderlabs/bizar 4.4.12 → 4.4.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bizar-dash/dist/assets/main-BB5mJurD.js +352 -0
- package/bizar-dash/dist/assets/main-BB5mJurD.js.map +1 -0
- package/bizar-dash/dist/assets/{main-BKXEqU1w.css → main-BsnQLXdh.css} +1 -1
- package/bizar-dash/dist/index.html +2 -2
- package/bizar-dash/src/server/minimax.mjs +231 -105
- package/bizar-dash/src/server/providers-store.mjs +10 -6
- package/bizar-dash/src/server/routes/minimax.mjs +50 -57
- package/bizar-dash/src/web/styles/minimax-usage.css +136 -0
- package/bizar-dash/src/web/views/MiniMaxUsage.tsx +387 -22
- package/cli/bin.mjs +263 -3
- package/package.json +1 -1
- package/bizar-dash/dist/assets/main-EK_fzXn_.js +0 -352
- package/bizar-dash/dist/assets/main-EK_fzXn_.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"mappings":"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","names":["ArchiveRestore","createLucideIcon","ArrowDown","ArrowLeft","ArrowUp","Book","Brain","Calendar","Check","ChevronLeft","CircleCheckBig","CirclePause","CirclePlay","CircleX","Circle","Coins","Cpu","Database","Diamond","Download","Ellipsis","EyeOff","Eye","FileCode2","FileCode","File","Filter","FlaskConical","FolderOpen","FolderPlus","FolderSearch","GitBranch","Globe","House","Inbox","KeyRound","Layers","LayoutDashboard","LayoutTemplate","Link2","LoaderCircle","MapPin","Map","Maximize2","Minus","OctagonAlert","Palette","PanelLeftClose","PanelLeftOpen","PanelsTopLeft","Plug","PowerOff","Puzzle","Radio","Redo2","Settings2","Share2","ShieldCheck","Shield","SquarePen","Square","Stethoscope","Tag","Target","Undo2","User","Wrench","Zap","MAX_CACHE","TTL_MS","_cache","cacheGet","path","entry","cacheSet","data","a","b","k","pathSegments","p","parts","result","accumulated","i","sortEntries","entries","validateDirName","name","trimmed","FileBrowser","value","onChange","initialPath","projectsDirectory","rootLabel","height","currentPath","setCurrentPath","useState","expanded","setExpanded","selectedRow","setSelectedRow","listing","setListing","childrenMap","setChildrenMap","loading","setLoading","error","setError","mkdirOpen","setMkdirOpen","mkdirName","setMkdirName","mkdirError","setMkdirError","mkdirLoading","setMkdirLoading","mkdirInputRef","useRef","fetchListing","useCallback","cached","api","load","err","msg","_a","useEffect","dirs","e","allEntries","navigateInto","navigateUp","navigateTo","goHome","home","goProjects","pd","openMkdir","cancelMkdir","submitMkdir","v","apiErr","handleMkdirKeyDown","toggleExpand","prev","next","handleKeyDown","x","files","selectable","r","sel","segments","parentPath","canGoUp","basename","jsx","seg","jsxs","RefreshCw","Home","AlertCircle","TreeSkeleton","TreeNode","FlatSkeleton","Fragment","idx","isDir","isSelected","isActive","Folder","onToggle","onNavigate","level","isExpanded","kids","ChevronDown","ChevronRight","w","TABS","MessageSquare","Bot","CheckSquare","Activity","Sparkles","Clock","HistoryIcon","Sliders","Topbar","activeTab","onTabChange","wsStatus","version","activeProject","projects","onProjectChange","onProjectsRefresh","onOpenSearch","settings","rightSlot","notificationsSlot","showTabs","extraTabs","ProjectSelector","SearchIcon","cn","tab","Icon","active","onRefresh","open","setOpen","modal","useModal","onClick","onAdd","TopbarAddProjectDialog","Button","Plus","setPath","setName","preflighting","setPreflighting","preflightError","setPreflightError","handleAdd","_b","Sidebar","tabs","builtIn","t","modTabs","SCOPES","RESULT_TYPE_BY_SCOPE","SearchModal","onClose","onSelect","toast","useToast","q","setQ","scope","setScope","results","setResults","activeIdx","setActiveIdx","inputRef","previousFocusRef","focusTimer","previous","cancelled","grouped","type","flat","s","resultType","onKey","Search","X","list","flatIdx","summarize","val","ICONS","Info","CheckCircle2","AlertTriangle","Notifications","onCountChange","wsSubscribe","items","setItems","stats","setStats","rootRef","unreadRef","reload","incoming","cur","n","onDocClick","onKeyDown","onMarkAllRead","onMarkRead","id","onRemove","removed","statsCur","unread","Bell","formatRelative","VisualPlanDialog","enabled","mode","defaultTemplate","lastUsedSlug","wasToggled","KNOWN_TEMPLATES","ArtifactCreateDialog","templates","slug","setSlug","selectedTemplate","setSelectedTemplate","creating","setCreating","handleCreate","ArtifactListDialog","plans","count","handleOpen","HelpDialog","commands","statuses","AuditDialog","running","setRunning","setResult","handleRunAudit","res","f","GenericDialog","dialog","message","detail","url","CommandDialog","Card","variant","interactive","className","children","rest","CardTitle","CardMeta","EmptyState","icon","title","action","Overview","snapshot","setActiveTab","refreshSnapshot","overview","setOverview","setProjects","activeId","setActiveId","mods","setMods","submitting","setSubmitting","activityItems","setActivityItems","activityExpanded","setActivityExpanded","hiddenKeys","setHiddenKeys","itemKey","it","h","onHide","key","rollback","onClearAll","all","onRestoreAll","es","tok","parsed","onAddProject","AddProjectDialog","onUseCurrentDir","newActive","onActivate","Spinner","text","Send","ActivityFeedItem","_c","ProjectCard","m","formatTime","project","onOpen","statusColor","Trash2","Power","sentenceCase","humanizeKind","kind","normalized","scopeRaw","actionRaw","scopeMap","actionMap","firstString","keys","formatActivitySummary","direct","agent","status","formatRelativeTime","ts","activitySeverity","activityIcon","AlertOctagon","activityNavTarget","item","activityKey","severity","navTarget","accentColor","SessionRowMenu","session","anchor","renameDraft","setRenameDraft","onEdit","onDeleteRequest","onConfirmDelete","onConfirmRename","ref","top","right","onDown","input","body","Edit","createPortal","AgentNode","node","depth","collapsible","isLast","controlledOpen","internalOpen","setInternalOpen","isControlled","hasChildren","headContent","child","isFullTree","props","AgentTree","SubAgentList","DEFAULT_GROUPS","isSameDay","dayDiff","ms","defaultGroupBy","sessions","now","yesterday","weekAgo","groups","mtime","SessionStateIndicator","state","ChatRail","opencodeSessions","activeSessionId","activeOpencodeSessionId","onCreateSession","onSelectSession","onSelectOpencodeSession","onRenameSession","onDeleteSession","groupBy","allSessions","useMemo","sorted","openTree","setOpenTree","isTreeOpen","openMenuId","setOpenMenuId","menuMode","setMenuMode","menuAnchor","setMenuAnchor","rowRefs","openMenuFor","row","target","closeMenu","handleSelect","handleConfirmRename","sid","handleConfirmDelete","orderedGroups","g","group","isOpencode","tree","treeOpen","el","ExternalLink","ChatComposer","sending","onSend","takingOff","setTakingOff","handleSend","Composer","formatNumber","ChatInfoPanel","sessionId","messages","pinned","model","agents","mcps","allCommands","msgCount","pinnedCount","tokensUsed","tokensTotal","Server","Terminal","JumpToLatest","streaming","newMessageCount","streamingLabel","Chat","initialTaskId","onClearTaskId","chat","useChat","setText","setAgent","setModel","attachments","setAttachments","fileInputRef","suggestions","setQuery","useSlashCommands","onAttach","onFiles","newNames","handleCreateSession","created","handleDelete","displaySessions","displayOpencodeSessions","activeSessionDisplay","threadSubtitle","base","ChatTopBar","ChatThread","cmd","StatusBadge","dot","TOOL_OPTIONS","MODELS","CATEGORIES","categoryColor","cat","c","StatusDot","isStuck","color","StatusPill","Agents","setAgents","categoryFilter","setCategoryFilter","search","setSearch","d","out","allTags","set","onCreate","nameEl","descEl","modelEl","modeEl","colorEl","promptEl","toolsContainer","tagsEl","categoryEl","tools","cb","tags","Save","full","updated","onDelete","onInvoke","prompt","Play","onRestart","onSetStatus","TagIcon","AgentCard","catColor","isWorking","Pencil","RotateCw","RichText","proseStyle","ReactMarkdown","remarkGfm","CALLOUT_TONE","XCircle","Callout","tone","Checklist","Table","columns","rows","ri","cell","ci","CodeTabs","selected","Decision","question","options","opt","isRec","OpenQuestions","questions","answers","setAnswers","setAnswer","qid","inputStyle","current","checked","o","FILE_CHANGE","FileTree","Diff","filename","language","before","after","beforeLines","afterLines","header","codeStyle","lineRow","sign","content","colors","signColor","l","TREND_STYLE","Stat","label","trend","hint","STEP_COLORS","BOX_W","BOX_H","GAP_X","GAP_Y","Workflow","steps","connections","Empty","byId","layout","layoutSteps","cols","width","nodeCenter","stepId","pos","from","to","dx","dy","fromX","toX","fromY","toY","midX","midY","y","cx","cy","points","isNote","StickyNote","Mockup","html","BlockErrorBoundary","React","__publicField","info","validateBlock","SECTION_MAP","groupBlocksIntoSections","blocks","sections","heading","GlyphRenderer","onCommentAdded","compiled","setCompiled","comments","setComments","loadError","setLoadError","fullscreen","setFullscreen","ctxMenu","setCtxMenu","addingComment","setAddingComment","commentDraft","setCommentDraft","activePin","setActivePin","blockErrors","setBlockErrors","reportBlockError","blockId","blockType","canvasRef","TIMEOUT_MS","timeoutPromise","_","reject","renderData","artifactData","fromFile","onContainerContextMenu","rect","submitComment","submitFeedback","toggleFullscreen","renderBlock","validation","renderBlockInner","commentCount","MoreHorizontal","_d","section","planStatusKind","Artifacts","artifacts","setPlans","activeSlug","setActiveSlug","filter","setFilter","showArchived","setShowArchived","filtered","artifact","MapIcon","Archive","NewPlanCard","PlanCard","setTitle","STATUS_KIND","STATUS_LABELS","BgStatusBadge","KillConfirmDialog","instanceId","instanceName","onConfirm","openKillConfirmDialog","onSuccess","getArtifactContentUrl","artifactId","openArtifactViewer","_modal","BacklogItem","task","onPromote","handlePromote","priorityDot","BacklogPanel","tasks","setTasks","handleEdit","_task","handlePromoteAll","ok","COLUMNS","matchesColumn","colId","isArchived","PRIORITIES","SORTS","Tasks","assigneeFilter","setAssigneeFilter","priorityFilter","setPriorityFilter","tagFilter","setTagFilter","sortKey","setSortKey","setSelected","tick","setTick","opts","params","tag","desc","priorityWeight","ax","bx","moveTask","taskId","newStatus","deleteTask","archiveTask","unarchiveTask","onBulkAction","ids","failed","onAssignMe","onMarkWorkedBy","complete","toggleSelect","toggleSelectAll","onOpenTaskChat","onOpenTaskArtifact","showBacklog","setShowBacklog","backlogCount","XIcon","openSubmitTaskModal","openTaskModal","CheckSquareIcon","col","KanbanColumn","openTaskDetail","column","onToggleSelect","onToggleSelectAll","allTaskIdsInCol","onMove","onArchive","onUnarchive","onOpenChat","onOpenArtifact","isArchivedView","dragOver","setDragOver","allSelected","TaskCard","dir","focused","onFocus","isTimer","metadata","hasChatSession","primaryArtifactId","priorityColors","formatDuration","Paperclip","FileText","event","seconds","initialStatus","titleEl","priorityEl","statusEl","assigneeEl","recurEl","cronEl","dueEl","submit","description","priority","tagsRaw","assignee","recurFreq","cron","recurring","dueDate","commentEl","depEl","agentEl","onComment","onStartTimer","onStopTimer","onAddDep","timerSeconds","PlayCircle","PauseCircle","onSubmit","autoTitleFromContent","onTitleKeyDown","enhanced","enhancePrompt","ZOOM_RANGES","LANE_HEIGHT","TIME_AXIS_HEIGHT","EVENTS_STRIP_HEIGHT","MIN_BAR_WIDTH","REANCHOR_RATIO","STATUS_COLORS","shortLabel","parseTs","taskStartMs","taskEndMs","bgStartMs","bgEndMs","chooseTickStep","rangeMs","formatTickLabel","canvasWrapRef","setMode","zoom","setZoom","streamOpen","setStreamOpen","bgInstances","setBgInstances","events","setEvents","refreshTick","setRefreshTick","nowTick","setNowTick","viewStart","setViewStart","canvasSize","setCanvasSize","selectedItem","setSelectedItem","commentText","setCommentText","taskTitle","setTaskTitle","taskPriority","setTaskPriority","bgMessage","setBgMessage","bgOutput","setBgOutput","creatingTask","setCreatingTask","postingComment","setPostingComment","bgArtifactIds","setBgArtifactIds","rangeStart","rangeEnd","reloadAll","bgRes","evRes","useLayoutEffect","ro","lanes","bg","start","end","taskLaneEnds","assigned","laneById","timeToX","ticks","step","startAligned","bars","lane","visibleStart","visibleEnd","xEnd","statusClass","eventMarkers","ev","laneRects","nowX","onSelectBar","bar","bgData","artR","onAddComment","onCreateTaskFromNode","onSendBgMessage","onKillBg","refetchOutput","refresh","contentHeight","ActivityIcon","Pause","z","History","lr","fillColor","NAV_ITEMS","ServerIcon","Config","initial","activeNav","setActiveNav","original","setOriginal","setParsed","dirty","setDirty","saving","setSaving","taRef","diagnostics","setDiagnostics","lightragStatus","setLightragStatus","lightragLog","setLightragLog","providers","setProviders","setMcps","originalHash","hashText","reloadConfig","raw","reloadProviders","reloadMcps","loadDiagnostics","loadLightragStatus","applyEdit","onChangeDebounced","debounce","save","loadLightragLog","onDownloadDiagnostics","bundle","blob","ConfigEditorPanel","ProvidersPanel","McpsPanel","DiagnosticsPanel","MemoryLightragPanel","ExportPanel","OC_SECTIONS","onReload","onSave","textareaRef","setSection","cfg","apply","patch","ModelForm","PluginsForm","ToolsForm","PermissionsForm","HooksForm","plugins","editing","setEditing","draft","setDraft","addPlugin","removePlugin","updatePlugin","toggle","addTool","removeTool","permissions","setTab","allow","deny","addRule","removeRule","rule","inp","hooks","updateHook","hookName","hook","openProviderModal","existing","idEl","baseEl","keyEl","modelsEl","enabledEl","isEdit","initialId","initialName","initialBase","initialKey","initialModels","initialEnabled","baseURL","apiKey","models","payload","AutoDetectBanner","EmptyProviders","parseEnv","line","eq","parseHeaders","sep","openMcpModal","typeRemoteEl","commandEl","argsEl","envEl","urlEl","headersEl","oauthEl","initialType","initialCommand","initialArgs","initialEnv","initialUrl","initialHeaders","initialOauth","isRemote","command","argsStr","args","env","headers","oauth","onDownload","LLM_BINDING_OPTIONS","EMBEDDING_BINDING_OPTIONS","logLines","onReloadLog","starting","setStarting","stopping","setStopping","loadingLog","setLoadingLog","showLog","setShowLog","handleSave","handleStart","handleStop","handleRestart","handleShowLog","run","probe","configured","statusIcon","other","THEMES","Moon","Sun","Monitor","PRESET_THEMES","FONT_FAMILIES","formatCountdown","PairDeviceCard","pair","setPair","pairing","setPairing","pairError","setPairError","setNow","remaining","expired","Smartphone","QRCodeSVG","QrCode","LAYOUTS","UpdatesCard","setStatus","ws","Ws","check","applyUpdate","restart","packages","isBusy","lat","isOutdated","pkgStatus","CheckCircle","SettingsView","setSettings","tailscale","setTailscale","tailscaleDraft","setTailscaleDraft","pluginOptions","setPluginOptions","applyThemeTokens","patchTheme","patchUi","patchTop","patchNotifications","patchAgents","SECTION_LINKS","activeSection","setActiveSection","hash","onJumpSection","patchDashboard","applyTheme","onReset","onTailscaleToggle","about","authToken","setAuthToken","authStatus","setAuthStatus","revealedToken","setRevealedToken","onCopyToken","onRegenerateToken","onSaveToken","RotateCcw","LayoutIcon","Copy","lines","rawLines","warnings","_e","_f","_g","ActivityLogCard","hidden","setHidden","showHidden","setShowHidden","log","hid","keyOf","onRestoreOne","isHidden","Mods","modViews","setModViews","iframeUrl","setIframeUrl","registryOpen","setRegistryOpen","registry","setRegistry","registryLoading","setRegistryLoading","installing","setInstalling","loadRegistry","onInstallFromRegistry","onUpgradeFromRegistry","backup","backupNote","onInstall","pathEl","onUninstall","onToggleEnabled","mod","ModDetails","rm","installed","isInstalling","instructions","setInstructions","instructionsLoading","setInstructionsLoading","instructionsOpen","setInstructionsOpen","expandedFile","setExpandedFile","loadInstructions","onReinstallInstructions","BookOpen","ModView","viewId","reloadKey","view","setView","iframeReload","setIframeReload","found","src","componentPath","modId","ModComponent","lazy","__vitePreload","ErrorBoundary","Suspense","ReactComponent","TYPES","ACTIONS","TIMEZONES","MINUTE_OPTIONS","HOUR_OPTIONS","DOW_OPTIONS","INTERVAL_UNITS","parseCronFields","expr","dow","minNum","hourNum","dowClean","parseIntervalParts","buildInitialState","parsedInterval","tz","tzKnown","toDatetimeLocal","iso","pad","composeSchedule","dowName","hourLabel","minute","human","unit","u","Schedules","schedules","setSchedules","openEditor","ScheduleEditorModal","saved","copy","onRun","humanizeSchedule","resultTagClass","truncate","formatNextRun","onSubmitted","onError","setState","tzSelectValue","update","handleSubmit","trimmedName","composed","actionPayload","max","Code","Skills","skills","setSkills","categories","setCategories","activeCategory","setActiveCategory","searchQ","setSearchQ","searchResults","setSearchResults","searching","setSearching","expandedCategories","setExpandedCategories","filteredInstalled","onShowDetails","SkillCard","catSkills","isOpen","tgt","skill","onShow","TIME_RANGES","setData","rangeId","setRangeId","since","range","eventsByProject","pid","toggleProject","onExportJson","MiniMaxUsage","remains","setRemains","onboarding","setOnboarding","refreshing","setRefreshing","testResult","setTestResult","testing","setTesting","wizardStep","setWizardStep","wizardVerifying","setWizardVerifying","wizardVerifyResult","setWizardVerifyResult","keyDraft","setKeyDraft","showKey","setShowKey","savingKey","setSavingKey","dismissWizard","verifyKeyBeforeSave","clearRemainsCacheClient","saveKey","sendTest","OnboardingWizard","Loader2","relativeTime","ModelQuotaCard","fivePct","clamp","weekPct","fiveConsumed","weekConsumed","QuotaBar","remainingPct","consumedPct","used","total","resetIn","resetISO","lo","hi","setStep","verifying","verifyResult","onVerify","onSkip","onManualKeySave","CircleCheck","TmuxAttachCard","instance","opening","setOpening","sessionName","attachCommand","copyCommand","openTerminal","POLL_INTERVAL_MS","OUTPUT_REFRESH_MS","PROMPT_TRUNCATE","BackgroundAgents","_props","instances","setInstances","off","onOpenOutput","openOutputModal","onOpenTmux","openTmuxModal","onKill","BackgroundAgentCard","inst","onViewOutput","startedMs","startedLabel","durationMs","OutputModalBody","output","setOutput","available","setAvailable","refBottom","refAutoscroll","onScroll","atBottom","TmuxModalBody","copied","setCopied","onCopy","VIEW_MAP","VERSION","renderActiveView","viewProps","V","mv","App","ToastProvider","ModalProvider","Shell","modalApi","isModalOpen","isModalOpenRef","setSnapshot","setWsStatus","bootError","setBootError","searchOpen","setSearchOpen","stuckAgents","setStuckAgents","stuckBannerDismissed","setStuckBannerDismissed","modViewsReloadKey","setModViewsReloadKey","wsRef","setWs","mql","handler","loadBootData","applyBootData","snap","stuck","auth","resolve","retrySnap","retrySet","retryStuck","defaultTab","offStatus","offMsg","file","exists","subscribeToWs","safeUntilRef","bump","map","activeEl","isFormControl","inForm","mergedTabs","renderedView","refreshProjects","onActivateProject","onSearchSelect","settingId","tryScroll","tries","showHeader","Root","isMobile","setIsMobile","MobileApp","root","createRoot","StrictMode"],"ignoreList":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66],"sources":["../../../node_modules/lucide-react/dist/esm/icons/archive-restore.js","../../../node_modules/lucide-react/dist/esm/icons/arrow-down.js","../../../node_modules/lucide-react/dist/esm/icons/arrow-left.js","../../../node_modules/lucide-react/dist/esm/icons/arrow-up.js","../../../node_modules/lucide-react/dist/esm/icons/book.js","../../../node_modules/lucide-react/dist/esm/icons/brain.js","../../../node_modules/lucide-react/dist/esm/icons/calendar.js","../../../node_modules/lucide-react/dist/esm/icons/check.js","../../../node_modules/lucide-react/dist/esm/icons/chevron-left.js","../../../node_modules/lucide-react/dist/esm/icons/circle-check-big.js","../../../node_modules/lucide-react/dist/esm/icons/circle-pause.js","../../../node_modules/lucide-react/dist/esm/icons/circle-play.js","../../../node_modules/lucide-react/dist/esm/icons/circle-x.js","../../../node_modules/lucide-react/dist/esm/icons/circle.js","../../../node_modules/lucide-react/dist/esm/icons/coins.js","../../../node_modules/lucide-react/dist/esm/icons/cpu.js","../../../node_modules/lucide-react/dist/esm/icons/database.js","../../../node_modules/lucide-react/dist/esm/icons/diamond.js","../../../node_modules/lucide-react/dist/esm/icons/download.js","../../../node_modules/lucide-react/dist/esm/icons/ellipsis.js","../../../node_modules/lucide-react/dist/esm/icons/eye-off.js","../../../node_modules/lucide-react/dist/esm/icons/eye.js","../../../node_modules/lucide-react/dist/esm/icons/file-code-2.js","../../../node_modules/lucide-react/dist/esm/icons/file-code.js","../../../node_modules/lucide-react/dist/esm/icons/file.js","../../../node_modules/lucide-react/dist/esm/icons/filter.js","../../../node_modules/lucide-react/dist/esm/icons/flask-conical.js","../../../node_modules/lucide-react/dist/esm/icons/folder-open.js","../../../node_modules/lucide-react/dist/esm/icons/folder-plus.js","../../../node_modules/lucide-react/dist/esm/icons/folder-search.js","../../../node_modules/lucide-react/dist/esm/icons/git-branch.js","../../../node_modules/lucide-react/dist/esm/icons/globe.js","../../../node_modules/lucide-react/dist/esm/icons/house.js","../../../node_modules/lucide-react/dist/esm/icons/inbox.js","../../../node_modules/lucide-react/dist/esm/icons/key-round.js","../../../node_modules/lucide-react/dist/esm/icons/layers.js","../../../node_modules/lucide-react/dist/esm/icons/layout-dashboard.js","../../../node_modules/lucide-react/dist/esm/icons/layout-template.js","../../../node_modules/lucide-react/dist/esm/icons/link-2.js","../../../node_modules/lucide-react/dist/esm/icons/loader-circle.js","../../../node_modules/lucide-react/dist/esm/icons/map-pin.js","../../../node_modules/lucide-react/dist/esm/icons/map.js","../../../node_modules/lucide-react/dist/esm/icons/maximize-2.js","../../../node_modules/lucide-react/dist/esm/icons/minus.js","../../../node_modules/lucide-react/dist/esm/icons/octagon-alert.js","../../../node_modules/lucide-react/dist/esm/icons/palette.js","../../../node_modules/lucide-react/dist/esm/icons/panel-left-close.js","../../../node_modules/lucide-react/dist/esm/icons/panel-left-open.js","../../../node_modules/lucide-react/dist/esm/icons/panels-top-left.js","../../../node_modules/lucide-react/dist/esm/icons/plug.js","../../../node_modules/lucide-react/dist/esm/icons/power-off.js","../../../node_modules/lucide-react/dist/esm/icons/puzzle.js","../../../node_modules/lucide-react/dist/esm/icons/radio.js","../../../node_modules/lucide-react/dist/esm/icons/redo-2.js","../../../node_modules/lucide-react/dist/esm/icons/settings-2.js","../../../node_modules/lucide-react/dist/esm/icons/share-2.js","../../../node_modules/lucide-react/dist/esm/icons/shield-check.js","../../../node_modules/lucide-react/dist/esm/icons/shield.js","../../../node_modules/lucide-react/dist/esm/icons/square-pen.js","../../../node_modules/lucide-react/dist/esm/icons/square.js","../../../node_modules/lucide-react/dist/esm/icons/stethoscope.js","../../../node_modules/lucide-react/dist/esm/icons/tag.js","../../../node_modules/lucide-react/dist/esm/icons/target.js","../../../node_modules/lucide-react/dist/esm/icons/undo-2.js","../../../node_modules/lucide-react/dist/esm/icons/user.js","../../../node_modules/lucide-react/dist/esm/icons/wrench.js","../../../node_modules/lucide-react/dist/esm/icons/zap.js","../../src/web/components/FileBrowser.tsx","../../src/web/components/Topbar.tsx","../../src/web/components/Sidebar.tsx","../../src/web/components/SearchModal.tsx","../../src/web/components/Notifications.tsx","../../src/web/components/VisualPlanDialog.tsx","../../src/web/components/ArtifactCreateDialog.tsx","../../src/web/components/ArtifactListDialog.tsx","../../src/web/components/HelpDialog.tsx","../../src/web/components/AuditDialog.tsx","../../src/web/components/CommandDialog.tsx","../../src/web/components/Card.tsx","../../src/web/components/EmptyState.tsx","../../src/web/views/Overview.tsx","../../src/web/components/chat/SessionRowMenu.tsx","../../src/web/components/chat/AgentNode.tsx","../../src/web/components/chat/AgentTree.tsx","../../src/web/components/chat/ChatRail.tsx","../../src/web/components/chat/ChatComposer.tsx","../../src/web/components/chat/ChatInfoPanel.tsx","../../src/web/components/chat/JumpToLatest.tsx","../../src/web/views/Chat.tsx","../../src/web/components/StatusBadge.tsx","../../src/web/views/Agents.tsx","../../src/web/views/glyphs/components.tsx","../../src/web/views/glyphs/GlyphRenderer.tsx","../../src/web/views/Artifacts.tsx","../../src/web/components/Tag.tsx","../../src/web/components/BgStatusBadge.tsx","../../src/web/components/KillConfirmDialog.tsx","../../src/web/components/ArtifactViewer.tsx","../../src/web/components/tasks/BacklogPanel.tsx","../../src/web/views/Tasks.tsx","../../src/web/views/Activity.tsx","../../src/web/views/Config.tsx","../../src/web/views/Settings.tsx","../../src/web/views/Mods.tsx","../../src/web/views/ModView.tsx","../../src/web/views/Schedules.tsx","../../src/web/views/Skills.tsx","../../src/web/views/History.tsx","../../src/web/views/MiniMaxUsage.tsx","../../src/web/components/background/TmuxAttachCard.tsx","../../src/web/views/BackgroundAgents.tsx","../../src/web/App.tsx","../../src/web/main.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ArchiveRestore = createLucideIcon(\"ArchiveRestore\", [\n [\"rect\", { width: \"20\", height: \"5\", x: \"2\", y: \"3\", rx: \"1\", key: \"1wp1u1\" }],\n [\"path\", { d: \"M4 8v11a2 2 0 0 0 2 2h2\", key: \"tvwodi\" }],\n [\"path\", { d: \"M20 8v11a2 2 0 0 1-2 2h-2\", key: \"1gkqxj\" }],\n [\"path\", { d: \"m9 15 3-3 3 3\", key: \"1pd0qc\" }],\n [\"path\", { d: \"M12 12v9\", key: \"192myk\" }]\n]);\n\nexport { ArchiveRestore as default };\n//# sourceMappingURL=archive-restore.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ArrowDown = createLucideIcon(\"ArrowDown\", [\n [\"path\", { d: \"M12 5v14\", key: \"s699le\" }],\n [\"path\", { d: \"m19 12-7 7-7-7\", key: \"1idqje\" }]\n]);\n\nexport { ArrowDown as default };\n//# sourceMappingURL=arrow-down.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ArrowLeft = createLucideIcon(\"ArrowLeft\", [\n [\"path\", { d: \"m12 19-7-7 7-7\", key: \"1l729n\" }],\n [\"path\", { d: \"M19 12H5\", key: \"x3x0zl\" }]\n]);\n\nexport { ArrowLeft as default };\n//# sourceMappingURL=arrow-left.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ArrowUp = createLucideIcon(\"ArrowUp\", [\n [\"path\", { d: \"m5 12 7-7 7 7\", key: \"hav0vg\" }],\n [\"path\", { d: \"M12 19V5\", key: \"x0mq9r\" }]\n]);\n\nexport { ArrowUp as default };\n//# sourceMappingURL=arrow-up.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Book = createLucideIcon(\"Book\", [\n [\n \"path\",\n {\n d: \"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20\",\n key: \"k3hazp\"\n }\n ]\n]);\n\nexport { Book as default };\n//# sourceMappingURL=book.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Brain = createLucideIcon(\"Brain\", [\n [\n \"path\",\n {\n d: \"M12 5a3 3 0 1 0-5.997.125 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588A4 4 0 1 0 12 18Z\",\n key: \"l5xja\"\n }\n ],\n [\n \"path\",\n {\n d: \"M12 5a3 3 0 1 1 5.997.125 4 4 0 0 1 2.526 5.77 4 4 0 0 1-.556 6.588A4 4 0 1 1 12 18Z\",\n key: \"ep3f8r\"\n }\n ],\n [\"path\", { d: \"M15 13a4.5 4.5 0 0 1-3-4 4.5 4.5 0 0 1-3 4\", key: \"1p4c4q\" }],\n [\"path\", { d: \"M17.599 6.5a3 3 0 0 0 .399-1.375\", key: \"tmeiqw\" }],\n [\"path\", { d: \"M6.003 5.125A3 3 0 0 0 6.401 6.5\", key: \"105sqy\" }],\n [\"path\", { d: \"M3.477 10.896a4 4 0 0 1 .585-.396\", key: \"ql3yin\" }],\n [\"path\", { d: \"M19.938 10.5a4 4 0 0 1 .585.396\", key: \"1qfode\" }],\n [\"path\", { d: \"M6 18a4 4 0 0 1-1.967-.516\", key: \"2e4loj\" }],\n [\"path\", { d: \"M19.967 17.484A4 4 0 0 1 18 18\", key: \"159ez6\" }]\n]);\n\nexport { Brain as default };\n//# sourceMappingURL=brain.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Calendar = createLucideIcon(\"Calendar\", [\n [\"path\", { d: \"M8 2v4\", key: \"1cmpym\" }],\n [\"path\", { d: \"M16 2v4\", key: \"4m81vk\" }],\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"4\", rx: \"2\", key: \"1hopcy\" }],\n [\"path\", { d: \"M3 10h18\", key: \"8toen8\" }]\n]);\n\nexport { Calendar as default };\n//# sourceMappingURL=calendar.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Check = createLucideIcon(\"Check\", [[\"path\", { d: \"M20 6 9 17l-5-5\", key: \"1gmf2c\" }]]);\n\nexport { Check as default };\n//# sourceMappingURL=check.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ChevronLeft = createLucideIcon(\"ChevronLeft\", [\n [\"path\", { d: \"m15 18-6-6 6-6\", key: \"1wnfg3\" }]\n]);\n\nexport { ChevronLeft as default };\n//# sourceMappingURL=chevron-left.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst CircleCheckBig = createLucideIcon(\"CircleCheckBig\", [\n [\"path\", { d: \"M21.801 10A10 10 0 1 1 17 3.335\", key: \"yps3ct\" }],\n [\"path\", { d: \"m9 11 3 3L22 4\", key: \"1pflzl\" }]\n]);\n\nexport { CircleCheckBig as default };\n//# sourceMappingURL=circle-check-big.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst CirclePause = createLucideIcon(\"CirclePause\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"line\", { x1: \"10\", x2: \"10\", y1: \"15\", y2: \"9\", key: \"c1nkhi\" }],\n [\"line\", { x1: \"14\", x2: \"14\", y1: \"15\", y2: \"9\", key: \"h65svq\" }]\n]);\n\nexport { CirclePause as default };\n//# sourceMappingURL=circle-pause.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst CirclePlay = createLucideIcon(\"CirclePlay\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"polygon\", { points: \"10 8 16 12 10 16 10 8\", key: \"1cimsy\" }]\n]);\n\nexport { CirclePlay as default };\n//# sourceMappingURL=circle-play.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst CircleX = createLucideIcon(\"CircleX\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"m15 9-6 6\", key: \"1uzhvr\" }],\n [\"path\", { d: \"m9 9 6 6\", key: \"z0biqf\" }]\n]);\n\nexport { CircleX as default };\n//# sourceMappingURL=circle-x.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Circle = createLucideIcon(\"Circle\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }]\n]);\n\nexport { Circle as default };\n//# sourceMappingURL=circle.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Coins = createLucideIcon(\"Coins\", [\n [\"circle\", { cx: \"8\", cy: \"8\", r: \"6\", key: \"3yglwk\" }],\n [\"path\", { d: \"M18.09 10.37A6 6 0 1 1 10.34 18\", key: \"t5s6rm\" }],\n [\"path\", { d: \"M7 6h1v4\", key: \"1obek4\" }],\n [\"path\", { d: \"m16.71 13.88.7.71-2.82 2.82\", key: \"1rbuyh\" }]\n]);\n\nexport { Coins as default };\n//# sourceMappingURL=coins.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Cpu = createLucideIcon(\"Cpu\", [\n [\"rect\", { width: \"16\", height: \"16\", x: \"4\", y: \"4\", rx: \"2\", key: \"14l7u7\" }],\n [\"rect\", { width: \"6\", height: \"6\", x: \"9\", y: \"9\", rx: \"1\", key: \"5aljv4\" }],\n [\"path\", { d: \"M15 2v2\", key: \"13l42r\" }],\n [\"path\", { d: \"M15 20v2\", key: \"15mkzm\" }],\n [\"path\", { d: \"M2 15h2\", key: \"1gxd5l\" }],\n [\"path\", { d: \"M2 9h2\", key: \"1bbxkp\" }],\n [\"path\", { d: \"M20 15h2\", key: \"19e6y8\" }],\n [\"path\", { d: \"M20 9h2\", key: \"19tzq7\" }],\n [\"path\", { d: \"M9 2v2\", key: \"165o2o\" }],\n [\"path\", { d: \"M9 20v2\", key: \"i2bqo8\" }]\n]);\n\nexport { Cpu as default };\n//# sourceMappingURL=cpu.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Database = createLucideIcon(\"Database\", [\n [\"ellipse\", { cx: \"12\", cy: \"5\", rx: \"9\", ry: \"3\", key: \"msslwz\" }],\n [\"path\", { d: \"M3 5V19A9 3 0 0 0 21 19V5\", key: \"1wlel7\" }],\n [\"path\", { d: \"M3 12A9 3 0 0 0 21 12\", key: \"mv7ke4\" }]\n]);\n\nexport { Database as default };\n//# sourceMappingURL=database.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Diamond = createLucideIcon(\"Diamond\", [\n [\n \"path\",\n {\n d: \"M2.7 10.3a2.41 2.41 0 0 0 0 3.41l7.59 7.59a2.41 2.41 0 0 0 3.41 0l7.59-7.59a2.41 2.41 0 0 0 0-3.41l-7.59-7.59a2.41 2.41 0 0 0-3.41 0Z\",\n key: \"1f1r0c\"\n }\n ]\n]);\n\nexport { Diamond as default };\n//# sourceMappingURL=diamond.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Download = createLucideIcon(\"Download\", [\n [\"path\", { d: \"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\", key: \"ih7n3h\" }],\n [\"polyline\", { points: \"7 10 12 15 17 10\", key: \"2ggqvy\" }],\n [\"line\", { x1: \"12\", x2: \"12\", y1: \"15\", y2: \"3\", key: \"1vk2je\" }]\n]);\n\nexport { Download as default };\n//# sourceMappingURL=download.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Ellipsis = createLucideIcon(\"Ellipsis\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"1\", key: \"41hilf\" }],\n [\"circle\", { cx: \"19\", cy: \"12\", r: \"1\", key: \"1wjl8i\" }],\n [\"circle\", { cx: \"5\", cy: \"12\", r: \"1\", key: \"1pcz8c\" }]\n]);\n\nexport { Ellipsis as default };\n//# sourceMappingURL=ellipsis.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst EyeOff = createLucideIcon(\"EyeOff\", [\n [\n \"path\",\n {\n d: \"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49\",\n key: \"ct8e1f\"\n }\n ],\n [\"path\", { d: \"M14.084 14.158a3 3 0 0 1-4.242-4.242\", key: \"151rxh\" }],\n [\n \"path\",\n {\n d: \"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143\",\n key: \"13bj9a\"\n }\n ],\n [\"path\", { d: \"m2 2 20 20\", key: \"1ooewy\" }]\n]);\n\nexport { EyeOff as default };\n//# sourceMappingURL=eye-off.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Eye = createLucideIcon(\"Eye\", [\n [\n \"path\",\n {\n d: \"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0\",\n key: \"1nclc0\"\n }\n ],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"3\", key: \"1v7zrd\" }]\n]);\n\nexport { Eye as default };\n//# sourceMappingURL=eye.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst FileCode2 = createLucideIcon(\"FileCode2\", [\n [\"path\", { d: \"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4\", key: \"1pf5j1\" }],\n [\"path\", { d: \"M14 2v4a2 2 0 0 0 2 2h4\", key: \"tnqrlb\" }],\n [\"path\", { d: \"m5 12-3 3 3 3\", key: \"oke12k\" }],\n [\"path\", { d: \"m9 18 3-3-3-3\", key: \"112psh\" }]\n]);\n\nexport { FileCode2 as default };\n//# sourceMappingURL=file-code-2.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst FileCode = createLucideIcon(\"FileCode\", [\n [\"path\", { d: \"M10 12.5 8 15l2 2.5\", key: \"1tg20x\" }],\n [\"path\", { d: \"m14 12.5 2 2.5-2 2.5\", key: \"yinavb\" }],\n [\"path\", { d: \"M14 2v4a2 2 0 0 0 2 2h4\", key: \"tnqrlb\" }],\n [\"path\", { d: \"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7z\", key: \"1mlx9k\" }]\n]);\n\nexport { FileCode as default };\n//# sourceMappingURL=file-code.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst File = createLucideIcon(\"File\", [\n [\"path\", { d: \"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z\", key: \"1rqfz7\" }],\n [\"path\", { d: \"M14 2v4a2 2 0 0 0 2 2h4\", key: \"tnqrlb\" }]\n]);\n\nexport { File as default };\n//# sourceMappingURL=file.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Filter = createLucideIcon(\"Filter\", [\n [\"polygon\", { points: \"22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3\", key: \"1yg77f\" }]\n]);\n\nexport { Filter as default };\n//# sourceMappingURL=filter.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst FlaskConical = createLucideIcon(\"FlaskConical\", [\n [\n \"path\",\n {\n d: \"M10 2v7.527a2 2 0 0 1-.211.896L4.72 20.55a1 1 0 0 0 .9 1.45h12.76a1 1 0 0 0 .9-1.45l-5.069-10.127A2 2 0 0 1 14 9.527V2\",\n key: \"pzvekw\"\n }\n ],\n [\"path\", { d: \"M8.5 2h7\", key: \"csnxdl\" }],\n [\"path\", { d: \"M7 16h10\", key: \"wp8him\" }]\n]);\n\nexport { FlaskConical as default };\n//# sourceMappingURL=flask-conical.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst FolderOpen = createLucideIcon(\"FolderOpen\", [\n [\n \"path\",\n {\n d: \"m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2\",\n key: \"usdka0\"\n }\n ]\n]);\n\nexport { FolderOpen as default };\n//# sourceMappingURL=folder-open.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst FolderPlus = createLucideIcon(\"FolderPlus\", [\n [\"path\", { d: \"M12 10v6\", key: \"1bos4e\" }],\n [\"path\", { d: \"M9 13h6\", key: \"1uhe8q\" }],\n [\n \"path\",\n {\n d: \"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z\",\n key: \"1kt360\"\n }\n ]\n]);\n\nexport { FolderPlus as default };\n//# sourceMappingURL=folder-plus.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst FolderSearch = createLucideIcon(\"FolderSearch\", [\n [\n \"path\",\n {\n d: \"M10.7 20H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v4.1\",\n key: \"1bw5m7\"\n }\n ],\n [\"path\", { d: \"m21 21-1.9-1.9\", key: \"1g2n9r\" }],\n [\"circle\", { cx: \"17\", cy: \"17\", r: \"3\", key: \"18b49y\" }]\n]);\n\nexport { FolderSearch as default };\n//# sourceMappingURL=folder-search.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst GitBranch = createLucideIcon(\"GitBranch\", [\n [\"line\", { x1: \"6\", x2: \"6\", y1: \"3\", y2: \"15\", key: \"17qcm7\" }],\n [\"circle\", { cx: \"18\", cy: \"6\", r: \"3\", key: \"1h7g24\" }],\n [\"circle\", { cx: \"6\", cy: \"18\", r: \"3\", key: \"fqmcym\" }],\n [\"path\", { d: \"M18 9a9 9 0 0 1-9 9\", key: \"n2h4wq\" }]\n]);\n\nexport { GitBranch as default };\n//# sourceMappingURL=git-branch.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Globe = createLucideIcon(\"Globe\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20\", key: \"13o1zl\" }],\n [\"path\", { d: \"M2 12h20\", key: \"9i4pu4\" }]\n]);\n\nexport { Globe as default };\n//# sourceMappingURL=globe.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst House = createLucideIcon(\"House\", [\n [\"path\", { d: \"M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8\", key: \"5wwlr5\" }],\n [\n \"path\",\n {\n d: \"M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z\",\n key: \"1d0kgt\"\n }\n ]\n]);\n\nexport { House as default };\n//# sourceMappingURL=house.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Inbox = createLucideIcon(\"Inbox\", [\n [\"polyline\", { points: \"22 12 16 12 14 15 10 15 8 12 2 12\", key: \"o97t9d\" }],\n [\n \"path\",\n {\n d: \"M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z\",\n key: \"oot6mr\"\n }\n ]\n]);\n\nexport { Inbox as default };\n//# sourceMappingURL=inbox.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst KeyRound = createLucideIcon(\"KeyRound\", [\n [\n \"path\",\n {\n d: \"M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z\",\n key: \"1s6t7t\"\n }\n ],\n [\"circle\", { cx: \"16.5\", cy: \"7.5\", r: \".5\", fill: \"currentColor\", key: \"w0ekpg\" }]\n]);\n\nexport { KeyRound as default };\n//# sourceMappingURL=key-round.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Layers = createLucideIcon(\"Layers\", [\n [\n \"path\",\n {\n d: \"m12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83Z\",\n key: \"8b97xw\"\n }\n ],\n [\"path\", { d: \"m22 17.65-9.17 4.16a2 2 0 0 1-1.66 0L2 17.65\", key: \"dd6zsq\" }],\n [\"path\", { d: \"m22 12.65-9.17 4.16a2 2 0 0 1-1.66 0L2 12.65\", key: \"ep9fru\" }]\n]);\n\nexport { Layers as default };\n//# sourceMappingURL=layers.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst LayoutDashboard = createLucideIcon(\"LayoutDashboard\", [\n [\"rect\", { width: \"7\", height: \"9\", x: \"3\", y: \"3\", rx: \"1\", key: \"10lvy0\" }],\n [\"rect\", { width: \"7\", height: \"5\", x: \"14\", y: \"3\", rx: \"1\", key: \"16une8\" }],\n [\"rect\", { width: \"7\", height: \"9\", x: \"14\", y: \"12\", rx: \"1\", key: \"1hutg5\" }],\n [\"rect\", { width: \"7\", height: \"5\", x: \"3\", y: \"16\", rx: \"1\", key: \"ldoo1y\" }]\n]);\n\nexport { LayoutDashboard as default };\n//# sourceMappingURL=layout-dashboard.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst LayoutTemplate = createLucideIcon(\"LayoutTemplate\", [\n [\"rect\", { width: \"18\", height: \"7\", x: \"3\", y: \"3\", rx: \"1\", key: \"f1a2em\" }],\n [\"rect\", { width: \"9\", height: \"7\", x: \"3\", y: \"14\", rx: \"1\", key: \"jqznyg\" }],\n [\"rect\", { width: \"5\", height: \"7\", x: \"16\", y: \"14\", rx: \"1\", key: \"q5h2i8\" }]\n]);\n\nexport { LayoutTemplate as default };\n//# sourceMappingURL=layout-template.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Link2 = createLucideIcon(\"Link2\", [\n [\"path\", { d: \"M9 17H7A5 5 0 0 1 7 7h2\", key: \"8i5ue5\" }],\n [\"path\", { d: \"M15 7h2a5 5 0 1 1 0 10h-2\", key: \"1b9ql8\" }],\n [\"line\", { x1: \"8\", x2: \"16\", y1: \"12\", y2: \"12\", key: \"1jonct\" }]\n]);\n\nexport { Link2 as default };\n//# sourceMappingURL=link-2.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst LoaderCircle = createLucideIcon(\"LoaderCircle\", [\n [\"path\", { d: \"M21 12a9 9 0 1 1-6.219-8.56\", key: \"13zald\" }]\n]);\n\nexport { LoaderCircle as default };\n//# sourceMappingURL=loader-circle.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst MapPin = createLucideIcon(\"MapPin\", [\n [\n \"path\",\n {\n d: \"M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0\",\n key: \"1r0f0z\"\n }\n ],\n [\"circle\", { cx: \"12\", cy: \"10\", r: \"3\", key: \"ilqhr7\" }]\n]);\n\nexport { MapPin as default };\n//# sourceMappingURL=map-pin.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Map = createLucideIcon(\"Map\", [\n [\n \"path\",\n {\n d: \"M14.106 5.553a2 2 0 0 0 1.788 0l3.659-1.83A1 1 0 0 1 21 4.619v12.764a1 1 0 0 1-.553.894l-4.553 2.277a2 2 0 0 1-1.788 0l-4.212-2.106a2 2 0 0 0-1.788 0l-3.659 1.83A1 1 0 0 1 3 19.381V6.618a1 1 0 0 1 .553-.894l4.553-2.277a2 2 0 0 1 1.788 0z\",\n key: \"169xi5\"\n }\n ],\n [\"path\", { d: \"M15 5.764v15\", key: \"1pn4in\" }],\n [\"path\", { d: \"M9 3.236v15\", key: \"1uimfh\" }]\n]);\n\nexport { Map as default };\n//# sourceMappingURL=map.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Maximize2 = createLucideIcon(\"Maximize2\", [\n [\"polyline\", { points: \"15 3 21 3 21 9\", key: \"mznyad\" }],\n [\"polyline\", { points: \"9 21 3 21 3 15\", key: \"1avn1i\" }],\n [\"line\", { x1: \"21\", x2: \"14\", y1: \"3\", y2: \"10\", key: \"ota7mn\" }],\n [\"line\", { x1: \"3\", x2: \"10\", y1: \"21\", y2: \"14\", key: \"1atl0r\" }]\n]);\n\nexport { Maximize2 as default };\n//# sourceMappingURL=maximize-2.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Minus = createLucideIcon(\"Minus\", [[\"path\", { d: \"M5 12h14\", key: \"1ays0h\" }]]);\n\nexport { Minus as default };\n//# sourceMappingURL=minus.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst OctagonAlert = createLucideIcon(\"OctagonAlert\", [\n [\"path\", { d: \"M12 16h.01\", key: \"1drbdi\" }],\n [\"path\", { d: \"M12 8v4\", key: \"1got3b\" }],\n [\n \"path\",\n {\n d: \"M15.312 2a2 2 0 0 1 1.414.586l4.688 4.688A2 2 0 0 1 22 8.688v6.624a2 2 0 0 1-.586 1.414l-4.688 4.688a2 2 0 0 1-1.414.586H8.688a2 2 0 0 1-1.414-.586l-4.688-4.688A2 2 0 0 1 2 15.312V8.688a2 2 0 0 1 .586-1.414l4.688-4.688A2 2 0 0 1 8.688 2z\",\n key: \"1fd625\"\n }\n ]\n]);\n\nexport { OctagonAlert as default };\n//# sourceMappingURL=octagon-alert.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Palette = createLucideIcon(\"Palette\", [\n [\"circle\", { cx: \"13.5\", cy: \"6.5\", r: \".5\", fill: \"currentColor\", key: \"1okk4w\" }],\n [\"circle\", { cx: \"17.5\", cy: \"10.5\", r: \".5\", fill: \"currentColor\", key: \"f64h9f\" }],\n [\"circle\", { cx: \"8.5\", cy: \"7.5\", r: \".5\", fill: \"currentColor\", key: \"fotxhn\" }],\n [\"circle\", { cx: \"6.5\", cy: \"12.5\", r: \".5\", fill: \"currentColor\", key: \"qy21gx\" }],\n [\n \"path\",\n {\n d: \"M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z\",\n key: \"12rzf8\"\n }\n ]\n]);\n\nexport { Palette as default };\n//# sourceMappingURL=palette.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst PanelLeftClose = createLucideIcon(\"PanelLeftClose\", [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M9 3v18\", key: \"fh3hqa\" }],\n [\"path\", { d: \"m16 15-3-3 3-3\", key: \"14y99z\" }]\n]);\n\nexport { PanelLeftClose as default };\n//# sourceMappingURL=panel-left-close.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst PanelLeftOpen = createLucideIcon(\"PanelLeftOpen\", [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M9 3v18\", key: \"fh3hqa\" }],\n [\"path\", { d: \"m14 9 3 3-3 3\", key: \"8010ee\" }]\n]);\n\nexport { PanelLeftOpen as default };\n//# sourceMappingURL=panel-left-open.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst PanelsTopLeft = createLucideIcon(\"PanelsTopLeft\", [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M3 9h18\", key: \"1pudct\" }],\n [\"path\", { d: \"M9 21V9\", key: \"1oto5p\" }]\n]);\n\nexport { PanelsTopLeft as default };\n//# sourceMappingURL=panels-top-left.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Plug = createLucideIcon(\"Plug\", [\n [\"path\", { d: \"M12 22v-5\", key: \"1ega77\" }],\n [\"path\", { d: \"M9 8V2\", key: \"14iosj\" }],\n [\"path\", { d: \"M15 8V2\", key: \"18g5xt\" }],\n [\"path\", { d: \"M18 8v5a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V8Z\", key: \"osxo6l\" }]\n]);\n\nexport { Plug as default };\n//# sourceMappingURL=plug.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst PowerOff = createLucideIcon(\"PowerOff\", [\n [\"path\", { d: \"M18.36 6.64A9 9 0 0 1 20.77 15\", key: \"dxknvb\" }],\n [\"path\", { d: \"M6.16 6.16a9 9 0 1 0 12.68 12.68\", key: \"1x7qb5\" }],\n [\"path\", { d: \"M12 2v4\", key: \"3427ic\" }],\n [\"path\", { d: \"m2 2 20 20\", key: \"1ooewy\" }]\n]);\n\nexport { PowerOff as default };\n//# sourceMappingURL=power-off.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Puzzle = createLucideIcon(\"Puzzle\", [\n [\n \"path\",\n {\n d: \"M15.39 4.39a1 1 0 0 0 1.68-.474 2.5 2.5 0 1 1 3.014 3.015 1 1 0 0 0-.474 1.68l1.683 1.682a2.414 2.414 0 0 1 0 3.414L19.61 15.39a1 1 0 0 1-1.68-.474 2.5 2.5 0 1 0-3.014 3.015 1 1 0 0 1 .474 1.68l-1.683 1.682a2.414 2.414 0 0 1-3.414 0L8.61 19.61a1 1 0 0 0-1.68.474 2.5 2.5 0 1 1-3.014-3.015 1 1 0 0 0 .474-1.68l-1.683-1.682a2.414 2.414 0 0 1 0-3.414L4.39 8.61a1 1 0 0 1 1.68.474 2.5 2.5 0 1 0 3.014-3.015 1 1 0 0 1-.474-1.68l1.683-1.682a2.414 2.414 0 0 1 3.414 0z\",\n key: \"w46dr5\"\n }\n ]\n]);\n\nexport { Puzzle as default };\n//# sourceMappingURL=puzzle.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Radio = createLucideIcon(\"Radio\", [\n [\"path\", { d: \"M4.9 19.1C1 15.2 1 8.8 4.9 4.9\", key: \"1vaf9d\" }],\n [\"path\", { d: \"M7.8 16.2c-2.3-2.3-2.3-6.1 0-8.5\", key: \"u1ii0m\" }],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"2\", key: \"1c9p78\" }],\n [\"path\", { d: \"M16.2 7.8c2.3 2.3 2.3 6.1 0 8.5\", key: \"1j5fej\" }],\n [\"path\", { d: \"M19.1 4.9C23 8.8 23 15.1 19.1 19\", key: \"10b0cb\" }]\n]);\n\nexport { Radio as default };\n//# sourceMappingURL=radio.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Redo2 = createLucideIcon(\"Redo2\", [\n [\"path\", { d: \"m15 14 5-5-5-5\", key: \"12vg1m\" }],\n [\"path\", { d: \"M20 9H9.5A5.5 5.5 0 0 0 4 14.5A5.5 5.5 0 0 0 9.5 20H13\", key: \"6uklza\" }]\n]);\n\nexport { Redo2 as default };\n//# sourceMappingURL=redo-2.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Settings2 = createLucideIcon(\"Settings2\", [\n [\"path\", { d: \"M20 7h-9\", key: \"3s1dr2\" }],\n [\"path\", { d: \"M14 17H5\", key: \"gfn3mx\" }],\n [\"circle\", { cx: \"17\", cy: \"17\", r: \"3\", key: \"18b49y\" }],\n [\"circle\", { cx: \"7\", cy: \"7\", r: \"3\", key: \"dfmy0x\" }]\n]);\n\nexport { Settings2 as default };\n//# sourceMappingURL=settings-2.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Share2 = createLucideIcon(\"Share2\", [\n [\"circle\", { cx: \"18\", cy: \"5\", r: \"3\", key: \"gq8acd\" }],\n [\"circle\", { cx: \"6\", cy: \"12\", r: \"3\", key: \"w7nqdw\" }],\n [\"circle\", { cx: \"18\", cy: \"19\", r: \"3\", key: \"1xt0gg\" }],\n [\"line\", { x1: \"8.59\", x2: \"15.42\", y1: \"13.51\", y2: \"17.49\", key: \"47mynk\" }],\n [\"line\", { x1: \"15.41\", x2: \"8.59\", y1: \"6.51\", y2: \"10.49\", key: \"1n3mei\" }]\n]);\n\nexport { Share2 as default };\n//# sourceMappingURL=share-2.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ShieldCheck = createLucideIcon(\"ShieldCheck\", [\n [\n \"path\",\n {\n d: \"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\",\n key: \"oel41y\"\n }\n ],\n [\"path\", { d: \"m9 12 2 2 4-4\", key: \"dzmm74\" }]\n]);\n\nexport { ShieldCheck as default };\n//# sourceMappingURL=shield-check.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Shield = createLucideIcon(\"Shield\", [\n [\n \"path\",\n {\n d: \"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\",\n key: \"oel41y\"\n }\n ]\n]);\n\nexport { Shield as default };\n//# sourceMappingURL=shield.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst SquarePen = createLucideIcon(\"SquarePen\", [\n [\"path\", { d: \"M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\", key: \"1m0v6g\" }],\n [\n \"path\",\n {\n d: \"M18.375 2.625a1 1 0 0 1 3 3l-9.013 9.014a2 2 0 0 1-.853.505l-2.873.84a.5.5 0 0 1-.62-.62l.84-2.873a2 2 0 0 1 .506-.852z\",\n key: \"ohrbg2\"\n }\n ]\n]);\n\nexport { SquarePen as default };\n//# sourceMappingURL=square-pen.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Square = createLucideIcon(\"Square\", [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }]\n]);\n\nexport { Square as default };\n//# sourceMappingURL=square.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Stethoscope = createLucideIcon(\"Stethoscope\", [\n [\"path\", { d: \"M11 2v2\", key: \"1539x4\" }],\n [\"path\", { d: \"M5 2v2\", key: \"1yf1q8\" }],\n [\"path\", { d: \"M5 3H4a2 2 0 0 0-2 2v4a6 6 0 0 0 12 0V5a2 2 0 0 0-2-2h-1\", key: \"rb5t3r\" }],\n [\"path\", { d: \"M8 15a6 6 0 0 0 12 0v-3\", key: \"x18d4x\" }],\n [\"circle\", { cx: \"20\", cy: \"10\", r: \"2\", key: \"ts1r5v\" }]\n]);\n\nexport { Stethoscope as default };\n//# sourceMappingURL=stethoscope.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Tag = createLucideIcon(\"Tag\", [\n [\n \"path\",\n {\n d: \"M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z\",\n key: \"vktsd0\"\n }\n ],\n [\"circle\", { cx: \"7.5\", cy: \"7.5\", r: \".5\", fill: \"currentColor\", key: \"kqv944\" }]\n]);\n\nexport { Tag as default };\n//# sourceMappingURL=tag.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Target = createLucideIcon(\"Target\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"6\", key: \"1vlfrh\" }],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"2\", key: \"1c9p78\" }]\n]);\n\nexport { Target as default };\n//# sourceMappingURL=target.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Undo2 = createLucideIcon(\"Undo2\", [\n [\"path\", { d: \"M9 14 4 9l5-5\", key: \"102s5s\" }],\n [\"path\", { d: \"M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5a5.5 5.5 0 0 1-5.5 5.5H11\", key: \"f3b9sd\" }]\n]);\n\nexport { Undo2 as default };\n//# sourceMappingURL=undo-2.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst User = createLucideIcon(\"User\", [\n [\"path\", { d: \"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2\", key: \"975kel\" }],\n [\"circle\", { cx: \"12\", cy: \"7\", r: \"4\", key: \"17ys0d\" }]\n]);\n\nexport { User as default };\n//# sourceMappingURL=user.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Wrench = createLucideIcon(\"Wrench\", [\n [\n \"path\",\n {\n d: \"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z\",\n key: \"cbrjhi\"\n }\n ]\n]);\n\nexport { Wrench as default };\n//# sourceMappingURL=wrench.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Zap = createLucideIcon(\"Zap\", [\n [\n \"path\",\n {\n d: \"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z\",\n key: \"1xq2db\"\n }\n ]\n]);\n\nexport { Zap as default };\n//# sourceMappingURL=zap.js.map\n","// src/components/FileBrowser.tsx — Interactive directory browser with tree + flat pane.\n// Replaces raw path text inputs in Add Project dialogs.\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { ChevronRight, ChevronDown, FolderOpen, Folder, File, RefreshCw, ArrowLeft, Home, AlertCircle, FolderPlus } from 'lucide-react';\nimport { api } from '../lib/api';\nimport type { DirectoryEntry, DirectoryListing, MkdirRequest, MkdirResponse } from '../lib/types';\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport type FileBrowserProps = {\n /** Currently selected directory (absolute path). */\n value: string;\n /** Fires when the user selects a directory. */\n onChange: (path: string) => void;\n /** Where the browser starts (default: homedir via GET /api/fs with no path). */\n initialPath?: string;\n /** If set, used as default initialPath and shown as a quick-jump chip. */\n projectsDirectory?: string;\n /** Label for the filesystem-root breadcrumb (default: \"Home\"). */\n rootLabel?: string;\n /** Scroll viewport height in px (default: 360). */\n height?: number;\n};\n\n// ─── Cache (LRU-ish, 200 entries max, 5-minute TTL) ───────────────────────────\n\nconst MAX_CACHE = 200;\nconst TTL_MS = 5 * 60 * 1000;\n\ntype CacheEntry = { data: DirectoryListing; ts: number };\n\nconst _cache = new Map<string, CacheEntry>();\n\nfunction cacheGet(path: string): DirectoryListing | null {\n const entry = _cache.get(path);\n if (!entry) return null;\n if (Date.now() - entry.ts > TTL_MS) { _cache.delete(path); return null; }\n return entry.data;\n}\n\nfunction cacheSet(path: string, data: DirectoryListing) {\n if (_cache.size >= MAX_CACHE) {\n // Evict oldest 50\n const oldest = [..._cache.entries()]\n .sort((a, b) => a[1].ts - b[1].ts)\n .slice(0, 50)\n .map(([k]) => k);\n oldest.forEach((k) => _cache.delete(k));\n }\n _cache.set(path, { data, ts: Date.now() });\n}\n\n// ─── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction pathSegments(p: string): { label: string; path: string }[] {\n if (!p || p === '/') return [{ label: '/', path: '/' }];\n const parts = p.split('/').filter(Boolean);\n const result: { label: string; path: string }[] = [];\n let accumulated = '';\n for (let i = 0; i < parts.length; i++) {\n accumulated += '/' + parts[i];\n result.push({ label: parts[i], path: accumulated });\n }\n return result;\n}\n\nfunction sortEntries(entries: DirectoryEntry[]): DirectoryEntry[] {\n return [...entries].sort((a, b) => {\n if (a.isDir !== b.isDir) return a.isDir ? -1 : 1;\n return a.name.localeCompare(b.name, undefined, { sensitivity: 'base' });\n });\n}\n\n/**\n * Validates a directory name against the same denylist the server enforces.\n * Returns an ok object or { ok: false, reason }.\n * Mirrors the validation in POST /api/fs/mkdir on the server side.\n */\nexport function validateDirName(name: string): { ok: true } | { ok: false; reason: string } {\n const trimmed = name.trim();\n if (!trimmed) return { ok: false, reason: 'Name cannot be empty.' };\n if (trimmed !== name) return { ok: false, reason: 'Name cannot have leading or trailing whitespace.' };\n if (trimmed === '.') return { ok: false, reason: \"Name cannot be '.'.\" };\n if (trimmed === '..') return { ok: false, reason: \"Name cannot be '..'.\" };\n if (trimmed.startsWith('-')) return { ok: false, reason: \"Name cannot start with '-'.\" };\n if (trimmed.length > 255) return { ok: false, reason: 'Name cannot be longer than 255 characters.' };\n if (/[/\\0:*?\"<>|]/.test(trimmed)) {\n return { ok: false, reason: \"Name cannot contain / \\\\ : * ? \\\" < > |\" };\n }\n return { ok: true };\n}\n\n// ─── Component ─────────────────────────────────────────────────────────────────\n\nexport function FileBrowser({\n value,\n onChange,\n initialPath,\n projectsDirectory,\n rootLabel = 'Home',\n height = 360,\n}: FileBrowserProps) {\n const [currentPath, setCurrentPath] = useState<string>(\n initialPath ?? projectsDirectory ?? '',\n );\n const [expanded, setExpanded] = useState<Set<string>>(new Set());\n const [selectedRow, setSelectedRow] = useState<number>(-1);\n const [listing, setListing] = useState<DirectoryListing | null>(null);\n const [childrenMap, setChildrenMap] = useState<Record<string, DirectoryEntry[]>>({});\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [mkdirOpen, setMkdirOpen] = useState(false);\n const [mkdirName, setMkdirName] = useState('');\n const [mkdirError, setMkdirError] = useState<string | null>(null);\n const [mkdirLoading, setMkdirLoading] = useState(false);\n const mkdirInputRef = useRef<HTMLInputElement | null>(null);\n\n const fetchListing = useCallback(async (path: string): Promise<DirectoryListing | null> => {\n try {\n const cached = cacheGet(path);\n if (cached) return cached;\n const data = await api.get<DirectoryListing>('/fs?path=' + encodeURIComponent(path));\n cacheSet(path, data);\n return data;\n } catch {\n return null;\n }\n }, []);\n\n const load = useCallback(async (path: string) => {\n setLoading(true);\n setError(null);\n try {\n const data = await api.get<DirectoryListing>('/fs?path=' + encodeURIComponent(path));\n cacheSet(path, data);\n setListing(data);\n setSelectedRow(-1);\n } catch (err) {\n const msg = (err as { data?: { message?: string }; message?: string }).data?.message\n ?? (err as Error).message\n ?? 'Failed to load directory';\n setError(msg);\n } finally {\n setLoading(false);\n }\n }, []);\n\n // Load current path on mount or when currentPath changes\n useEffect(() => {\n if (!currentPath) {\n // Default to homedir by fetching empty-path listing\n api.get<DirectoryListing>('/fs').then((data) => {\n cacheSet('', data);\n setListing(data);\n setCurrentPath(data.path);\n if (data.path !== value) onChange(data.path);\n }).catch(() => {\n setError('Could not determine home directory.');\n setLoading(false);\n });\n } else {\n load(currentPath);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [currentPath]);\n\n // Keep selected path in sync when value changes externally (e.g. breadcrumb click)\n useEffect(() => {\n if (value && value !== currentPath) {\n setCurrentPath(value);\n }\n }, [value]);\n\n const entries = listing ? sortEntries(listing.entries) : [];\n\n const dirs = entries.filter((e) => e.isDir);\n const allEntries = entries;\n\n // ─── Navigation helpers ──────────────────────────────────────────────────────\n\n const navigateInto = (entry: DirectoryEntry) => {\n if (!entry.isDir) return;\n setCurrentPath(entry.path);\n onChange(entry.path);\n };\n\n const navigateUp = () => {\n if (!listing?.parent) return;\n setCurrentPath(listing.parent);\n onChange(listing.parent);\n };\n\n const navigateTo = (path: string) => {\n if (path === currentPath) return;\n setCurrentPath(path);\n onChange(path);\n };\n\n const goHome = async () => {\n const home = await fetchListing('');\n if (home) {\n setCurrentPath(home.path);\n onChange(home.path);\n }\n };\n\n const goProjects = async () => {\n if (!projectsDirectory) return;\n const pd = await fetchListing(projectsDirectory);\n if (pd) {\n setCurrentPath(pd.path);\n onChange(pd.path);\n }\n };\n\n // ─── New folder ────────────────────────────────────────────────────────────\n\n // Open the inline mkdir input, focusing it on the next tick\n const openMkdir = () => {\n setMkdirOpen(true);\n setMkdirName('');\n setMkdirError(null);\n // Autofocus after the input renders\n setTimeout(() => mkdirInputRef.current?.focus(), 0);\n };\n\n const cancelMkdir = () => {\n setMkdirOpen(false);\n setMkdirName('');\n setMkdirError(null);\n };\n\n const submitMkdir = async () => {\n const v = validateDirName(mkdirName);\n if (!v.ok) {\n setMkdirError(v.reason);\n return;\n }\n setMkdirLoading(true);\n setMkdirError(null);\n try {\n const result = await api.post<MkdirResponse>('/fs/mkdir', {\n parent: currentPath,\n name: mkdirName.trim(),\n } as MkdirRequest);\n // Invalidate cache for the current path so the new folder appears\n _cache.delete(currentPath);\n await load(currentPath);\n // Select the new directory\n onChange(result.path);\n setMkdirOpen(false);\n setMkdirName('');\n } catch (err) {\n const apiErr = err as { data?: { message?: string }; status?: number };\n if (apiErr.status === 409) {\n setMkdirError(`A folder named \"${mkdirName.trim()}\" already exists.`);\n } else {\n setMkdirError(\n apiErr.data?.message ??\n (err as Error).message ??\n 'Failed to create folder.',\n );\n }\n } finally {\n setMkdirLoading(false);\n }\n };\n\n const handleMkdirKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n submitMkdir();\n } else if (e.key === 'Escape') {\n e.preventDefault();\n cancelMkdir();\n }\n };\n\n const toggleExpand = (path: string) => {\n setExpanded((prev) => {\n const next = new Set(prev);\n if (next.has(path)) next.delete(path);\n else next.add(path);\n return next;\n });\n // Lazy-load children when expanding\n if (!childrenMap[path]) {\n fetchListing(path).then((data) => {\n if (data) setChildrenMap((prev) => ({ ...prev, [path]: data.entries.filter((e) => e.isDir) }));\n });\n }\n };\n\n // ─── Keyboard handler ────────────────────────────────────────────────────────\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (!listing) return;\n const dirs = allEntries.filter((x) => x.isDir);\n const files = allEntries.filter((x) => !x.isDir);\n const selectable = [...dirs, ...files];\n\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n setSelectedRow((r) => Math.min(r + 1, selectable.length - 1));\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n setSelectedRow((r) => Math.max(r - 1, 0));\n } else if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n const sel = selectable[selectedRow];\n if (sel) {\n if (e.key === 'Enter' && sel.isDir) navigateInto(sel);\n else if (!sel.isDir) { /* files are not selectable */ }\n else onChange(sel.path);\n }\n } else if (e.key === 'Backspace') {\n e.preventDefault();\n navigateUp();\n }\n };\n\n // ─── Render ─────────────────────────────────────────────────────────────────\n\n const segments = pathSegments(listing?.path ?? currentPath ?? '/');\n const parentPath = listing?.parent;\n const canGoUp = parentPath !== null && parentPath !== undefined;\n\n const basename = currentPath.split('/').filter(Boolean).at(-1) ?? '/';\n\n return (\n <div className=\"file-browser\" onKeyDown={handleKeyDown} tabIndex={-1}>\n {/* Breadcrumb */}\n <div className=\"file-browser-breadcrumb\" role=\"navigation\" aria-label=\"Path breadcrumb\">\n {segments.map((seg, i) => (\n <span key={seg.path} className=\"file-browser-breadcrumb-item\">\n {i > 0 && <span className=\"file-browser-breadcrumb-sep\" aria-hidden>/</span>}\n <button\n type=\"button\"\n className=\"file-browser-breadcrumb-btn\"\n onClick={() => navigateTo(seg.path)}\n title={seg.path}\n >\n {i === 0 ? (seg.path === '/' ? '/' : rootLabel) : seg.label}\n </button>\n </span>\n ))}\n </div>\n\n {/* Toolbar */}\n <div className=\"file-browser-toolbar\">\n <div className=\"file-browser-toolbar-left\">\n <button\n type=\"button\"\n className=\"file-browser-tool-btn\"\n onClick={navigateUp}\n disabled={!canGoUp}\n title=\"Go up (Backspace)\"\n aria-label=\"Go up one level\"\n >\n <ArrowLeft size={13} />\n </button>\n\n <button\n type=\"button\"\n className=\"file-browser-tool-btn\"\n onClick={() => load(currentPath)}\n disabled={loading}\n title=\"Refresh\"\n aria-label=\"Refresh\"\n >\n <RefreshCw size={13} className={loading ? 'spin' : ''} />\n </button>\n\n <button\n type=\"button\"\n className=\"file-browser-tool-btn\"\n onClick={openMkdir}\n title=\"New folder\"\n aria-label=\"Create new folder\"\n >\n <FolderPlus size={13} />\n </button>\n\n <div className=\"file-browser-chips\">\n <button type=\"button\" className=\"file-browser-chip\" onClick={goHome}>\n <Home size={11} /> {rootLabel}\n </button>\n {projectsDirectory && (\n <button type=\"button\" className=\"file-browser-chip\" onClick={goProjects} title={projectsDirectory}>\n <FolderOpen size={11} /> {projectsDirectory.split('/').filter(Boolean).at(-1) ?? 'Projects'}\n </button>\n )}\n </div>\n </div>\n\n {mkdirOpen ? (\n <div className=\"file-browser-mkdir\">\n <input\n ref={mkdirInputRef}\n type=\"text\"\n className=\"file-browser-mkdir-input\"\n placeholder=\"Folder name\"\n value={mkdirName}\n onChange={(e) => {\n setMkdirName(e.target.value);\n setMkdirError(null);\n }}\n onKeyDown={handleMkdirKeyDown}\n aria-label=\"New folder name\"\n aria-invalid={mkdirError ? 'true' : undefined}\n aria-describedby={mkdirError ? 'mkdir-error' : undefined}\n disabled={mkdirLoading}\n maxLength={255}\n />\n {mkdirError ? (\n <span id=\"mkdir-error\" className=\"file-browser-mkdir-error\" role=\"alert\">\n {mkdirError}\n </span>\n ) : (\n <span className=\"file-browser-mkdir-hint\">\n Enter to create, Esc to cancel\n </span>\n )}\n </div>\n ) : (\n <span className=\"file-browser-count-hint\">\n {loading ? '…' : `${entries.length} in ${basename}`}\n </span>\n )}\n </div>\n\n {/* Error banner */}\n {error && (\n <div className=\"file-browser-error\">\n <AlertCircle size={13} />\n <span>{error}</span>\n <button type=\"button\" className=\"file-browser-retry\" onClick={() => load(currentPath)}>\n Retry\n </button>\n </div>\n )}\n\n {/* Body: tree (left) + flat (right) */}\n <div className=\"file-browser-body\" style={{ height }}>\n {/* Left: tree */}\n <div className=\"file-browser-pane file-browser-tree\" aria-label=\"Folder tree\">\n {loading && !listing ? (\n <TreeSkeleton />\n ) : (\n <TreeNode\n path={currentPath}\n entries={dirs}\n expanded={expanded}\n childrenMap={childrenMap}\n onToggle={toggleExpand}\n onNavigate={navigateInto}\n level={0}\n />\n )}\n </div>\n\n {/* Right: flat listing */}\n <div className=\"file-browser-pane file-browser-flat\" aria-label=\"Directory contents\">\n <div className=\"file-browser-flat-header\">\n <span>Name</span>\n <span>Type</span>\n </div>\n\n {loading && !listing ? (\n <FlatSkeleton />\n ) : (\n <>\n {/* Truncation notice */}\n {listing?.truncated && (\n <div className=\"file-browser-truncated-banner\" role=\"status\">\n Showing first 500 of {listing.totalEntries} entries.\n Navigate into a subfolder to see more.\n </div>\n )}\n\n {allEntries.length === 0 ? (\n <div className=\"file-browser-empty\">This folder is empty</div>\n ) : (\n <div className=\"file-browser-flat-list\">\n {allEntries.map((entry, idx) => {\n const isDir = entry.isDir;\n const isSelected = idx === selectedRow;\n const isActive = entry.path === value;\n return (\n <div\n key={entry.path}\n role=\"option\"\n aria-selected={isActive}\n className={[\n 'file-browser-row',\n isDir ? 'file-browser-row--dir' : 'file-browser-row--file',\n isSelected && 'file-browser-row--selected',\n isActive && isDir && 'file-browser-row--active',\n !isDir && 'file-browser-row--disabled',\n ].filter(Boolean).join(' ')}\n onClick={() => {\n if (isDir) {\n setSelectedRow(idx);\n onChange(entry.path);\n }\n }}\n onDoubleClick={() => {\n if (isDir) navigateInto(entry);\n }}\n title={entry.path}\n >\n <span className=\"file-browser-row-icon\">\n {isDir ? <Folder size={13} /> : <File size={13} />}\n </span>\n <span className=\"file-browser-row-name\">{entry.name}</span>\n <span className=\"file-browser-row-type\">\n {isDir ? 'Folder' : ''}\n </span>\n </div>\n );\n })}\n </div>\n )}\n </>\n )}\n </div>\n </div>\n\n {/* Footer hint */}\n <div className=\"file-browser-footer-hint\">\n Select a folder, then click Add. Use <kbd>↑</kbd> <kbd>↓</kbd> to navigate, <kbd>Enter</kbd> to confirm.\n </div>\n </div>\n );\n}\n\n// ─── TreeNode ─────────────────────────────────────────────────────────────────\n\nfunction TreeNode({\n path,\n entries,\n expanded,\n childrenMap,\n onToggle,\n onNavigate,\n level,\n}: {\n path: string;\n entries: DirectoryEntry[];\n expanded: Set<string>;\n childrenMap: Record<string, DirectoryEntry[]>;\n onToggle: (p: string) => void;\n onNavigate: (e: DirectoryEntry) => void;\n level: number;\n}) {\n return (\n <ul className=\"file-browser-tree-list\" role=\"group\">\n {entries.map((entry) => {\n const isExpanded = expanded.has(entry.path);\n const kids = childrenMap[entry.path] ?? [];\n return (\n <li key={entry.path} className=\"file-browser-tree-node\">\n <div\n className={[\n 'file-browser-tree-row',\n isExpanded && 'file-browser-tree-row--expanded',\n ].filter(Boolean).join(' ')}\n style={{ paddingLeft: `${level * 16 + 8}px` }}\n >\n <button\n type=\"button\"\n className=\"file-browser-tree-toggle\"\n onClick={(e) => { e.stopPropagation(); onToggle(entry.path); }}\n aria-label={isExpanded ? 'Collapse' : 'Expand'}\n >\n {kids.length > 0 || true ? (\n isExpanded ? <ChevronDown size={11} /> : <ChevronRight size={11} />\n ) : (\n <span style={{ width: 11 }} />\n )}\n </button>\n\n <button\n type=\"button\"\n className=\"file-browser-tree-name\"\n onClick={() => onNavigate(entry)}\n title={entry.path}\n >\n <Folder size={12} />\n <span>{entry.name}</span>\n </button>\n </div>\n\n {isExpanded && kids.length > 0 && (\n <TreeNode\n path={entry.path}\n entries={kids}\n expanded={expanded}\n childrenMap={childrenMap}\n onToggle={onToggle}\n onNavigate={onNavigate}\n level={level + 1}\n />\n )}\n </li>\n );\n })}\n </ul>\n );\n}\n\n// ─── Skeletons ────────────────────────────────────────────────────────────────\n\nfunction TreeSkeleton() {\n return (\n <div className=\"file-browser-skeleton-wrap\">\n {[80, 60, 90, 55, 70].map((w, i) => (\n <div key={i} className=\"file-browser-skeleton-row\" style={{ width: w }} />\n ))}\n </div>\n );\n}\n\nfunction FlatSkeleton() {\n return (\n <div className=\"file-browser-skeleton-wrap\">\n {[60, 90, 70, 50, 80, 65].map((w, i) => (\n <div key={i} className=\"file-browser-skeleton-row\" style={{ width: w }} />\n ))}\n </div>\n );\n}\n","// src/components/Topbar.tsx — header with brand, project selector, search, tabs, ws status.\nimport { useEffect, useState } from 'react';\nimport type { ReactNode } from 'react';\nimport {\n LayoutDashboard,\n MessageSquare,\n Bot,\n Map,\n Folder,\n CheckSquare,\n Settings2,\n Sliders,\n Puzzle,\n Clock,\n History as HistoryIcon,\n Search as SearchIcon,\n ChevronDown,\n Plus,\n RefreshCw,\n Power,\n Sparkles,\n Activity,\n Radio,\n Coins,\n type LucideIcon,\n} from 'lucide-react';\nimport { cn } from '../lib/utils';\nimport type { ProjectRecord, WsStatus, WsMessage, Settings, DirectoryListing } from '../lib/types';\nimport { api } from '../lib/api';\nimport { useModal } from './Modal';\nimport { FileBrowser } from './FileBrowser';\nimport { Button } from './Button';\n\nexport type TabDef = {\n id: string;\n label: string;\n icon: LucideIcon;\n};\n\nexport const TABS: TabDef[] = [\n { id: 'overview', label: 'Overview', icon: LayoutDashboard },\n { id: 'chat', label: 'Chat', icon: MessageSquare },\n { id: 'agents', label: 'Agents', icon: Bot },\n { id: 'artifacts', label: 'Glyphs', icon: Map },\n { id: 'tasks', label: 'Tasks', icon: CheckSquare },\n { id: 'activity', label: 'Activity', icon: Activity },\n { id: 'background', label: 'Active', icon: Radio },\n { id: 'skills', label: 'Skills', icon: Sparkles },\n { id: 'mods', label: 'Mods', icon: Puzzle },\n { id: 'schedules', label: 'Schedules', icon: Clock },\n { id: 'history', label: 'History', icon: HistoryIcon },\n { id: 'minimax', label: 'Usage', icon: Coins },\n { id: 'config', label: 'Config', icon: Settings2 },\n { id: 'settings', label: 'Settings', icon: Sliders },\n];\n\nexport type TopbarProps = {\n activeTab: string;\n onTabChange: (id: string) => void;\n wsStatus: WsStatus;\n version: string;\n activeProject: ProjectRecord | null;\n projects: ProjectRecord[];\n onProjectChange: (id: string) => void;\n onProjectsRefresh: () => void;\n onOpenSearch: () => void;\n settings?: Settings | null;\n rightSlot?: ReactNode;\n /**\n * v3.3.0 — Optional slot for the notifications bell. The host\n * (App.tsx) mounts the Notifications component here so it can\n * subscribe to the same WebSocket the rest of the app uses.\n */\n notificationsSlot?: ReactNode;\n /**\n * Whether to render the tabs row. In sidebar/both layouts the sidebar\n * carries navigation, so we hide this row to keep the topbar slim.\n */\n showTabs?: boolean;\n /**\n * v3.20.3 — Optional extra tabs (mod views) appended after the built-in\n * tabs. Each entry is the same shape as TabDef with an `id` matching\n * the mod view id (e.g. 'graphify:web').\n */\n extraTabs?: TabDef[];\n};\n\nexport function Topbar({\n activeTab,\n onTabChange,\n wsStatus,\n version,\n activeProject,\n projects,\n onProjectChange,\n onProjectsRefresh,\n onOpenSearch,\n settings,\n rightSlot,\n notificationsSlot,\n showTabs = true,\n extraTabs,\n}: TopbarProps) {\n return (\n <header className=\"topbar\">\n <div className=\"topbar-row\">\n <div className=\"brand\">\n <span className=\"brand-logo\" aria-hidden=\"true\">ᛒ</span>\n <span className=\"brand-title\">Bizar</span>\n <span className=\"brand-version\">{version}</span>\n </div>\n <ProjectSelector\n activeProject={activeProject}\n projects={projects}\n onChange={onProjectChange}\n onRefresh={onProjectsRefresh}\n settings={settings ?? null}\n />\n <button\n type=\"button\"\n className=\"topbar-search\"\n onClick={onOpenSearch}\n title=\"Search (Ctrl/Cmd+K)\"\n aria-label=\"Open search\"\n >\n <SearchIcon size={14} />\n <span className=\"muted\">Search…</span>\n <kbd>⌘K</kbd>\n </button>\n <div className=\"topbar-spacer\" />\n <div className=\"topbar-right\">\n {notificationsSlot}\n {rightSlot}\n <div className={cn('ws-status', `ws-${wsStatus}`)} title={`WebSocket: ${wsStatus}`}>\n <span className=\"ws-dot\" />\n <span className=\"ws-label\">{wsStatus}</span>\n </div>\n </div>\n </div>\n {showTabs && (\n <nav className=\"tabs-row\" role=\"tablist\">\n {TABS.map((tab) => {\n const Icon = tab.icon;\n const active = tab.id === activeTab;\n return (\n <button\n key={tab.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={active}\n className={cn('tab', active && 'tab-active')}\n onClick={() => onTabChange(tab.id)}\n title={tab.label}\n >\n <Icon size={14} className=\"tab-icon\" />\n <span className=\"tab-label\">{tab.label}</span>\n </button>\n );\n })}\n {extraTabs && extraTabs.length > 0 && (\n <>\n <span className=\"tab-separator\" aria-hidden=\"true\" />\n {extraTabs.map((tab) => {\n const Icon = tab.icon;\n const active = tab.id === activeTab;\n return (\n <button\n key={tab.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={active}\n className={cn('tab', 'tab-mod', active && 'tab-active')}\n onClick={() => onTabChange(tab.id)}\n title={`${tab.label} (mod)`}\n >\n <Icon size={14} className=\"tab-icon\" />\n <span className=\"tab-label\">{tab.label}</span>\n <span className=\"tab-badge\">mod</span>\n </button>\n );\n })}\n </>\n )}\n </nav>\n )}\n </header>\n );\n}\n\nfunction ProjectSelector({\n activeProject,\n projects,\n onChange,\n onRefresh,\n settings,\n}: {\n activeProject: ProjectRecord | null;\n projects: ProjectRecord[];\n onChange: (id: string) => void;\n onRefresh: () => void;\n settings: Settings | null;\n}) {\n const [open, setOpen] = useState(false);\n const modal = useModal();\n\n useEffect(() => {\n if (!open) return;\n const onClick = () => setOpen(false);\n document.addEventListener('click', onClick);\n return () => document.removeEventListener('click', onClick);\n }, [open]);\n\n const onAdd = () => {\n modal.open({\n title: 'Add project',\n children: (\n <TopbarAddProjectDialog\n settings={settings}\n onAdd={async (path: string, name: string | null) => {\n try {\n await api.post('/projects', { path, name });\n onRefresh();\n setOpen(false);\n modal.close();\n } catch (err) {\n alert(`Add failed: ${(err as Error).message}`);\n }\n }}\n />\n ),\n footer: (\n <div className=\"modal-footer-actions\">\n <Button variant=\"ghost\" onClick={() => modal.close()}>Cancel</Button>\n </div>\n ),\n });\n };\n\n return (\n <div className=\"project-selector\" onClick={(e) => e.stopPropagation()}>\n <button\n type=\"button\"\n className=\"project-selector-btn\"\n onClick={() => setOpen((v) => !v)}\n title=\"Switch active project\"\n aria-haspopup=\"menu\"\n aria-expanded={open}\n >\n <Folder size={14} />\n <span className=\"project-selector-name\">\n {activeProject?.name || '(no project)'}\n </span>\n <ChevronDown size={12} />\n </button>\n {open && (\n <div className=\"project-selector-menu\">\n <div className=\"project-selector-menu-head\">\n <span className=\"muted\">{projects.length} project{projects.length === 1 ? '' : 's'}</span>\n <div className=\"project-selector-menu-actions\">\n <button type=\"button\" className=\"icon-btn\" onClick={onRefresh} title=\"Refresh\" aria-label=\"Refresh projects\">\n <RefreshCw size={12} />\n </button>\n <button type=\"button\" className=\"icon-btn\" onClick={onAdd} title=\"Add project\" aria-label=\"Add project\">\n <Plus size={12} />\n </button>\n </div>\n </div>\n <ul className=\"project-selector-list\">\n {projects.length === 0 && (\n <li className=\"muted project-selector-empty\">No projects. Add one to start.</li>\n )}\n {projects.map((p) => (\n <li key={p.id}>\n <button\n type=\"button\"\n className={cn('project-selector-item', activeProject?.id === p.id && 'active')}\n onClick={() => {\n onChange(p.id);\n setOpen(false);\n }}\n >\n <span className=\"project-selector-item-name\">{p.name}</span>\n <span className=\"project-selector-item-status\">{p.status}</span>\n </button>\n </li>\n ))}\n </ul>\n </div>\n )}\n </div>\n );\n}\n\n// ─── TopbarAddProjectDialog ───────────────────────────────────────────────────\n\nfunction TopbarAddProjectDialog({\n settings,\n onAdd,\n}: {\n settings: Settings | null;\n onAdd: (path: string, name: string | null) => void;\n}) {\n const [path, setPath] = useState(settings?.dashboard?.projectsDirectory ?? '');\n const [name, setName] = useState('');\n const [preflighting, setPreflighting] = useState(false);\n const [preflightError, setPreflightError] = useState<string | null>(null);\n\n const handleAdd = async () => {\n if (!path) return;\n setPreflighting(true);\n setPreflightError(null);\n try {\n // Pre-flight: verify the path still exists\n await api.get<DirectoryListing>('/fs?path=' + encodeURIComponent(path));\n onAdd(path, name || null);\n } catch (err) {\n const apiErr = err as { status?: number; data?: { message?: string } };\n if (apiErr.status === 404) {\n setPreflightError('That folder no longer exists. Pick another.');\n } else {\n setPreflightError(\n apiErr.data?.message ?? (err as Error).message ?? 'Validation failed.',\n );\n }\n } finally {\n setPreflighting(false);\n }\n };\n\n return (\n <div>\n <label className=\"field-label\">Folder</label>\n <FileBrowser\n value={path}\n onChange={(p) => {\n setPath(p);\n setPreflightError(null);\n }}\n projectsDirectory={settings?.dashboard?.projectsDirectory}\n height={320}\n />\n {preflightError && (\n <p className=\"field-help\" style={{ color: 'var(--error)', marginTop: 4 }}>\n {preflightError}\n </p>\n )}\n <div style={{ marginTop: 'var(--space-3)' }}>\n <label className=\"field-label\" htmlFor=\"topbar-add-project-name\">Name (optional)</label>\n <input\n id=\"topbar-add-project-name\"\n className=\"input\"\n type=\"text\"\n placeholder=\"My App\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n />\n </div>\n <div style={{ marginTop: 'var(--space-3)', display: 'flex', justifyContent: 'flex-end' }}>\n <Button\n variant=\"primary\"\n onClick={handleAdd}\n disabled={!path || preflighting}\n >\n {preflighting ? <span className=\"btn-spinner\" /> : null}\n {preflighting ? 'Checking…' : 'Add'}\n </Button>\n </div>\n </div>\n );\n}\n","// src/components/Sidebar.tsx — vertical navigation rail for sidebar/both layouts.\nimport type { TabDef } from './Topbar';\nimport { cn } from '../lib/utils';\n\nexport type SidebarProps = {\n tabs: TabDef[];\n activeTab: string;\n onTabChange: (id: string) => void;\n};\n\nexport function Sidebar({ tabs, activeTab, onTabChange }: SidebarProps) {\n // Split tabs into built-in (no `isMod` flag) and mod-added entries.\n // Render a separator + small \"Mods\" label between them so users can\n // tell what's part of Bizar vs what an installed mod contributed.\n const builtIn = tabs.filter((t) => !(t as TabDef & { isMod?: boolean }).isMod);\n const modTabs = tabs.filter((t) => (t as TabDef & { isMod?: boolean }).isMod);\n\n return (\n <aside className=\"sidebar\" aria-label=\"Primary navigation\">\n <nav className=\"sidebar-nav\" role=\"tablist\">\n {builtIn.map((t) => {\n const Icon = t.icon;\n const active = t.id === activeTab;\n return (\n <button\n key={t.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={active}\n className={cn('sidebar-tab', active && 'sidebar-tab-active')}\n onClick={() => onTabChange(t.id)}\n title={t.label}\n >\n <Icon size={18} aria-hidden />\n <span className=\"sidebar-tab-label\">{t.label}</span>\n </button>\n );\n })}\n {modTabs.length > 0 && (\n <>\n <div className=\"sidebar-section-divider\" aria-hidden=\"true\" />\n <div className=\"sidebar-section-label\">Mods</div>\n {modTabs.map((t) => {\n const Icon = t.icon;\n const active = t.id === activeTab;\n return (\n <button\n key={t.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={active}\n className={cn('sidebar-tab', 'sidebar-tab-mod', active && 'sidebar-tab-active')}\n onClick={() => onTabChange(t.id)}\n title={`${t.label} (mod)`}\n >\n <Icon size={18} aria-hidden />\n <span className=\"sidebar-tab-label\">{t.label}</span>\n </button>\n );\n })}\n </>\n )}\n </nav>\n </aside>\n );\n}\n","// src/components/SearchModal.tsx — fuzzy search modal opened by / or Cmd/Ctrl+K.\nimport { useEffect, useRef, useState } from 'react';\nimport { Search, X } from 'lucide-react';\nimport { useToast } from './Toast';\nimport { api } from '../lib/api';\nimport type { SearchResult } from '../lib/types';\nimport { cn } from '../lib/utils';\n\ntype Props = {\n open: boolean;\n onClose: () => void;\n onSelect: (r: SearchResult) => void;\n};\n\nconst SCOPES = [\n { id: 'all', label: 'All' },\n { id: 'projects', label: 'Projects' },\n { id: 'agents', label: 'Agents' },\n { id: 'tasks', label: 'Tasks' },\n { id: 'mods', label: 'Mods' },\n { id: 'schedules', label: 'Schedules' },\n { id: 'commands', label: 'Commands' },\n { id: 'settings', label: 'Settings' },\n] as const;\n\nconst RESULT_TYPE_BY_SCOPE: Record<(typeof SCOPES)[number]['id'], string | null> = {\n all: null,\n projects: 'project',\n agents: 'agent',\n tasks: 'task',\n mods: 'mod',\n schedules: 'schedule',\n commands: 'command',\n settings: 'setting',\n};\n\nexport function SearchModal({ open, onClose, onSelect }: Props) {\n const toast = useToast();\n const [q, setQ] = useState('');\n const [scope, setScope] = useState<typeof SCOPES[number]['id']>('all');\n const [results, setResults] = useState<SearchResult[]>([]);\n const [loading, setLoading] = useState(false);\n const [activeIdx, setActiveIdx] = useState(0);\n const inputRef = useRef<HTMLInputElement>(null);\n const previousFocusRef = useRef<HTMLElement | null>(null);\n\n useEffect(() => {\n let focusTimer: number | undefined;\n if (open) {\n previousFocusRef.current = document.activeElement instanceof HTMLElement\n ? document.activeElement\n : null;\n setQ('');\n setResults([]);\n setActiveIdx(0);\n focusTimer = window.setTimeout(() => inputRef.current?.focus(), 30);\n }\n return () => {\n if (focusTimer) window.clearTimeout(focusTimer);\n if (!open) return;\n const previous = previousFocusRef.current;\n if (previous && previous.isConnected) previous.focus();\n };\n }, [open]);\n\n useEffect(() => {\n if (!open) return;\n if (!q.trim()) {\n setResults([]);\n setActiveIdx(0);\n return;\n }\n let cancelled = false;\n setLoading(true);\n const t = setTimeout(() => {\n api\n .get<{ results: SearchResult[] }>(`/search?q=${encodeURIComponent(q)}&scope=${scope}`)\n .then((r) => {\n if (cancelled) return;\n setResults(r.results || []);\n setActiveIdx(0);\n })\n .catch((err) => {\n if (cancelled) return;\n toast.error(`Search failed: ${(err as Error).message}`);\n })\n .finally(() => !cancelled && setLoading(false));\n }, 150);\n return () => {\n cancelled = true;\n clearTimeout(t);\n };\n }, [q, scope, open, toast]);\n\n if (!open) return null;\n\n const grouped: Record<string, SearchResult[]> = {};\n for (const r of results) {\n const type = r.type.toLowerCase();\n grouped[type] = grouped[type] || [];\n grouped[type].push(r);\n }\n\n const flat: SearchResult[] = [];\n for (const scope of SCOPES.map((s) => s.id)) {\n const resultType = RESULT_TYPE_BY_SCOPE[scope];\n if (resultType && grouped[resultType]) flat.push(...grouped[resultType]);\n }\n\n const onKey = (e: React.KeyboardEvent) => {\n if (e.key === 'Escape') {\n onClose();\n } else if (e.key === 'ArrowDown') {\n e.preventDefault();\n if (flat.length === 0) return;\n setActiveIdx((i) => Math.min(i + 1, flat.length - 1));\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n if (flat.length === 0) return;\n setActiveIdx((i) => Math.max(i - 1, 0));\n } else if (e.key === 'Enter' && flat[activeIdx]) {\n e.preventDefault();\n onSelect(flat[activeIdx]);\n onClose();\n }\n };\n\n return (\n <div className=\"search-modal-backdrop\" onClick={onClose}>\n <div className=\"search-modal\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"search-modal-title\" onClick={(e) => e.stopPropagation()}>\n <div className=\"search-modal-head\">\n <Search size={14} />\n <span id=\"search-modal-title\" className=\"sr-only\">Search</span>\n <input\n ref={inputRef}\n className=\"search-modal-input\"\n placeholder=\"Search tasks, agents, settings, projects…\"\n value={q}\n onChange={(e) => setQ(e.target.value)}\n onKeyDown={onKey}\n />\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label=\"Close\"\n onClick={onClose}\n >\n <X size={14} />\n </button>\n </div>\n <div className=\"search-modal-scopes\">\n {SCOPES.map((s) => (\n <button\n key={s.id}\n type=\"button\"\n className={cn('search-scope', scope === s.id && 'search-scope-active')}\n onClick={() => setScope(s.id)}\n >\n {s.label}\n </button>\n ))}\n </div>\n <div className=\"search-modal-body\">\n {loading && <div className=\"muted\">Searching…</div>}\n {!loading && q && flat.length === 0 && <div className=\"muted\">No results.</div>}\n {!loading && !q && <div className=\"muted\">Type to search…</div>}\n {SCOPES.map((s) => {\n const resultType = RESULT_TYPE_BY_SCOPE[s.id];\n if (!resultType) return null;\n const list = grouped[resultType];\n if (!list || list.length === 0) return null;\n return (\n <div key={s.id} className=\"search-group\">\n <div className=\"search-group-head\">{s.label}</div>\n {list.map((r) => {\n const flatIdx = flat.indexOf(r);\n return (\n <button\n type=\"button\"\n key={`${r.type}-${flatIdx}`}\n className={cn('search-result', flatIdx === activeIdx && 'search-result-active')}\n onMouseEnter={() => setActiveIdx(flatIdx)}\n onClick={() => {\n onSelect(r);\n onClose();\n }}\n >\n <span className=\"search-result-type\">{r.type}</span>\n <span className=\"search-result-label\">\n {summarize(r)}\n </span>\n </button>\n );\n })}\n </div>\n );\n })}\n </div>\n <div className=\"search-modal-foot\">\n <span className=\"muted\">↑↓ navigate · ↵ open · esc close</span>\n </div>\n </div>\n </div>\n );\n}\n\nfunction summarize(r: SearchResult): string {\n const i = r.item || {};\n if (r.type === 'project') return `${i.name} — ${i.path}`;\n if (r.type === 'agent') return `${i.name} — ${i.description || i.model || ''}`;\n if (r.type === 'task') return `${i.title} — ${(i.status || '')}`;\n if (r.type === 'mod') return `${i.name} v${i.version} — ${i.description || ''}`;\n if (r.type === 'schedule') return `${i.name} (${i.type}: ${i.schedule})`;\n if (r.type === 'command') return `${i.name} — ${i.description || ''}`;\n if (r.type === 'setting') {\n const val = i.value === null || i.value === undefined\n ? ''\n : typeof i.value === 'string'\n ? ` = ${i.value}`\n : ` = ${JSON.stringify(i.value)}`;\n return `${i.label}${val} — ${i.desc || ''}`.trim();\n }\n return JSON.stringify(i).slice(0, 80);\n}\n","// src/components/Notifications.tsx — v3.3.0 bell icon + dropdown panel.\n\nimport { useEffect, useRef, useState } from 'react';\nimport { Bell, Check, X, Info, AlertTriangle, AlertCircle, CheckCircle2 } from 'lucide-react';\nimport { Button } from './Button';\nimport { useToast } from './Toast';\nimport { api } from '../lib/api';\nimport { cn, formatRelative } from '../lib/utils';\nimport type { Notification, NotificationStats, WsMessage } from '../lib/types';\n\nconst ICONS: Record<string, typeof Info> = {\n info: Info,\n success: CheckCircle2,\n warning: AlertTriangle,\n error: AlertCircle,\n};\n\ntype Props = {\n /** Setter for unread count so the rest of the app can react. */\n onCountChange?: (unread: number) => void;\n /** Optional hook to subscribe to incoming WS messages. */\n wsSubscribe?: (cb: (msg: WsMessage) => void) => () => void;\n};\n\nexport function Notifications({ onCountChange, wsSubscribe }: Props) {\n const toast = useToast();\n const [open, setOpen] = useState(false);\n const [items, setItems] = useState<Notification[]>([]);\n const [stats, setStats] = useState<NotificationStats | null>(null);\n const [loading, setLoading] = useState(false);\n const rootRef = useRef<HTMLDivElement | null>(null);\n const unreadRef = useRef(0);\n\n const reload = async () => {\n try {\n setLoading(true);\n const r = await api.get<{ notifications: Notification[]; stats: NotificationStats }>(\n '/notifications?limit=200',\n );\n setItems(r.notifications || []);\n setStats(r.stats || null);\n unreadRef.current = r.stats?.unread || 0;\n onCountChange?.(unreadRef.current);\n } catch (err) {\n // Soft-fail: the bell just shows no items.\n // eslint-disable-next-line no-console\n console.warn('[notifications] reload failed:', (err as Error).message);\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n reload();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Subscribe to incoming notification:new events.\n useEffect(() => {\n if (!wsSubscribe) return;\n const off = wsSubscribe((msg) => {\n if (msg.type === 'notification:new') {\n const incoming = msg.notification;\n setItems((cur) => [incoming, ...cur.filter((n) => n.id !== incoming.id)]);\n // Bump unread count.\n if (!incoming.read) {\n unreadRef.current += 1;\n setStats((cur) =>\n cur ? { ...cur, unread: (cur.unread || 0) + 1 } : { total: 1, unread: 1, lastTs: incoming.ts, counts: { [incoming.severity || 'info']: 1 } },\n );\n onCountChange?.(unreadRef.current);\n }\n } else if (msg.type === 'notifications:change') {\n // External change (mark-all-read, etc.) — refresh from server.\n reload();\n }\n });\n return off;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [wsSubscribe]);\n\n // Close the panel on outside click.\n useEffect(() => {\n if (!open) return;\n const onDocClick = (e: MouseEvent) => {\n if (!rootRef.current) return;\n if (!rootRef.current.contains(e.target as Node)) {\n setOpen(false);\n }\n };\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') setOpen(false);\n };\n document.addEventListener('mousedown', onDocClick);\n document.addEventListener('keydown', onKeyDown);\n return () => {\n document.removeEventListener('mousedown', onDocClick);\n document.removeEventListener('keydown', onKeyDown);\n };\n }, [open]);\n\n const onMarkAllRead = async () => {\n try {\n await api.post('/notifications/read-all', {});\n setItems((cur) => cur.map((n) => ({ ...n, read: true })));\n setStats((cur) => (cur ? { ...cur, unread: 0 } : cur));\n unreadRef.current = 0;\n onCountChange?.(0);\n toast.success('All notifications marked as read.', 1500);\n } catch (err) {\n toast.error(`Failed: ${(err as Error).message}`);\n }\n };\n\n const onMarkRead = async (id: string) => {\n try {\n await api.post(`/notifications/${encodeURIComponent(id)}/read`, {});\n setItems((cur) => cur.map((n) => (n.id === id ? { ...n, read: true } : n)));\n setStats((cur) => (cur ? { ...cur, unread: Math.max(0, (cur.unread || 1) - 1) } : cur));\n unreadRef.current = Math.max(0, unreadRef.current - 1);\n onCountChange?.(unreadRef.current);\n } catch (err) {\n toast.error(`Failed: ${(err as Error).message}`);\n }\n };\n\n const onRemove = async (id: string) => {\n try {\n await api.del(`/notifications/${encodeURIComponent(id)}`);\n setItems((cur) => {\n const removed = cur.find((n) => n.id === id);\n if (removed && !removed.read) {\n unreadRef.current = Math.max(0, unreadRef.current - 1);\n setStats((statsCur) => (statsCur ? { ...statsCur, unread: Math.max(0, statsCur.unread - 1) } : statsCur));\n onCountChange?.(unreadRef.current);\n }\n return cur.filter((n) => n.id !== id);\n });\n } catch (err) {\n toast.error(`Failed: ${(err as Error).message}`);\n }\n };\n\n const unread = stats?.unread || 0;\n\n return (\n <div className=\"notifications-root\" ref={rootRef}>\n <button\n type=\"button\"\n className={cn('topbar-icon-btn notifications-bell', open && 'is-open')}\n onClick={() => setOpen((v) => !v)}\n title=\"Notifications\"\n aria-label=\"Notifications\"\n aria-haspopup=\"true\"\n aria-expanded={open}\n >\n <Bell size={16} />\n {unread > 0 && <span className=\"notifications-badge\">{unread > 99 ? '99+' : unread}</span>}\n </button>\n {open && (\n <div className=\"notifications-panel\" role=\"dialog\" aria-label=\"Notifications\">\n <header className=\"notifications-panel-head\">\n <div>\n <strong>Notifications</strong>\n {unread > 0 && <span className=\"muted text-sm\"> · {unread} unread</span>}\n </div>\n <div className=\"notifications-panel-head-actions\">\n <Button size=\"sm\" variant=\"ghost\" onClick={onMarkAllRead} disabled={unread === 0}>\n <Check size={12} /> Mark all read\n </Button>\n <button\n type=\"button\"\n className=\"icon-btn\"\n onClick={() => setOpen(false)}\n aria-label=\"Close\"\n title=\"Close\"\n >\n <X size={14} />\n </button>\n </div>\n </header>\n <div className=\"notifications-list\">\n {loading && items.length === 0 ? (\n <div className=\"notifications-empty muted\">Loading…</div>\n ) : items.length === 0 ? (\n <div className=\"notifications-empty muted\">No notifications yet.</div>\n ) : (\n items.map((n) => {\n const Icon = ICONS[n.severity] || Info;\n return (\n <div\n key={n.id}\n className={cn('notification-item', !n.read && 'is-unread', `severity-${n.severity}`)}\n >\n <Icon size={14} className={`notification-icon severity-${n.severity}`} />\n <div className=\"notification-body\">\n {n.title && <div className=\"notification-title\">{n.title}</div>}\n <div className=\"notification-msg\">{n.message}</div>\n <div className=\"notification-meta muted\">\n <span className=\"mono\">{n.source}</span>\n <span>·</span>\n <span>{formatRelative(n.ts)}</span>\n </div>\n </div>\n <div className=\"notification-actions\">\n {!n.read && (\n <button\n type=\"button\"\n className=\"icon-btn\"\n onClick={() => onMarkRead(n.id)}\n title=\"Mark as read\"\n aria-label=\"Mark as read\"\n >\n <Check size={12} />\n </button>\n )}\n <button\n type=\"button\"\n className=\"icon-btn icon-btn-danger\"\n onClick={() => onRemove(n.id)}\n title=\"Remove\"\n aria-label=\"Remove\"\n >\n <X size={12} />\n </button>\n </div>\n </div>\n );\n })\n )}\n </div>\n <footer className=\"notifications-panel-foot\">\n <span className=\"muted text-sm\">\n {stats ? `${stats.total} total · last ${formatRelative(stats.lastTs || new Date().toISOString())}` : ''}\n </span>\n </footer>\n </div>\n )}\n </div>\n );\n}\n","// src/components/VisualPlanDialog.tsx — Dialog for /visual-plan command.\n\nimport { Button } from './Button';\n\ntype VisualPlanDialogProps = {\n data?: Record<string, unknown>;\n onClose: () => void;\n};\n\nexport function VisualPlanDialog({ data, onClose }: VisualPlanDialogProps) {\n const enabled = data?.enabled as boolean | undefined;\n const previousEnabled = data?.previousEnabled as boolean | undefined;\n const mode = data?.mode as string | undefined;\n const defaultTemplate = data?.defaultTemplate as string | undefined;\n const lastUsedSlug = data?.lastUsedSlug as string | null | undefined;\n\n const wasToggled = mode === 'toggle';\n\n return (\n <div>\n {wasToggled ? (\n <p style={{ marginBottom: 16, lineHeight: 1.6 }}>\n Visual plan mode has been <strong>{enabled ? 'enabled' : 'disabled'}</strong>.\n {enabled\n ? ' The agent will create a plan and wait for your feedback on complex tasks.'\n : ' The agent will work without a visual plan canvas.'}\n </p>\n ) : (\n <div style={{ marginBottom: 16 }}>\n <p style={{ marginBottom: 8, fontWeight: 600 }}>\n Visual Plan: <span style={{ color: enabled ? 'var(--color-success)' : 'var(--color-muted)' }}>\n {enabled ? 'ON' : 'OFF'}\n </span>\n </p>\n <p style={{ lineHeight: 1.6, color: 'var(--color-muted)', fontSize: 13 }}>\n When enabled, the agent creates a visual plan and waits for your feedback before proceeding with complex tasks.\n </p>\n {defaultTemplate && (\n <p style={{ marginTop: 8, fontSize: 13, color: 'var(--color-muted)' }}>\n Default template: <code>{defaultTemplate}</code>\n </p>\n )}\n {lastUsedSlug && (\n <p style={{ fontSize: 13, color: 'var(--color-muted)' }}>\n Last used plan: <code>{lastUsedSlug}</code>\n </p>\n )}\n <p style={{ marginTop: 12, fontSize: 13, color: 'var(--color-muted)' }}>\n Use <code>/visual-plan on</code> or <code>/visual-plan off</code> to toggle.\n </p>\n </div>\n )}\n <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>\n <Button variant=\"ghost\" onClick={onClose}>Close</Button>\n </div>\n </div>\n );\n}\n","// src/components/ArtifactCreateDialog.tsx — Dialog for /artifact new command.\n\nimport { useState } from 'react';\nimport { Button } from './Button';\nimport { api } from '../lib/api';\n\ntype ArtifactCreateDialogProps = {\n data?: Record<string, unknown>;\n onClose: () => void;\n};\n\nconst KNOWN_TEMPLATES = [\n 'blank',\n 'feature-design',\n 'bug-investigation',\n 'decision-record',\n 'horizontal',\n 'vertical',\n];\n\nexport function ArtifactCreateDialog({ data, onClose }: ArtifactCreateDialogProps) {\n const templates = (data?.templates as string[]) ?? KNOWN_TEMPLATES;\n const defaultTemplate = (data?.defaultTemplate as string) ?? 'blank';\n\n const [slug, setSlug] = useState('');\n const [selectedTemplate, setSelectedTemplate] = useState(defaultTemplate);\n const [creating, setCreating] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const handleCreate = async () => {\n if (!slug.trim()) {\n setError('Slug is required.');\n return;\n }\n if (!/^[a-z0-9][a-z0-9-]{0,63}$/.test(slug)) {\n setError('Invalid slug. Use lowercase letters, numbers, and hyphens. Must start with an alphanumeric character.');\n return;\n }\n setCreating(true);\n setError(null);\n try {\n await api.post('/artifacts', { slug, template: selectedTemplate });\n onClose();\n } catch (err) {\n setError((err as Error).message);\n setCreating(false);\n }\n };\n\n return (\n <div>\n <p style={{ marginBottom: 16, color: 'var(--color-muted)', fontSize: 13 }}>\n Create a new visual plan. Plans are stored in <code>artifacts/</code> in your worktree.\n </p>\n\n <div style={{ marginBottom: 12 }}>\n <label className=\"field-label\" htmlFor=\"plan-slug\">Plan slug</label>\n <input\n id=\"plan-slug\"\n className=\"input\"\n type=\"text\"\n placeholder=\"e.g. my-feature\"\n value={slug}\n onChange={(e) => { setSlug(e.target.value); setError(null); }}\n autoFocus\n />\n </div>\n\n <div style={{ marginBottom: 16 }}>\n <label className=\"field-label\" htmlFor=\"plan-template\">Template</label>\n <select\n id=\"plan-template\"\n className=\"select\"\n value={selectedTemplate}\n onChange={(e) => setSelectedTemplate(e.target.value)}\n >\n {templates.map((t) => (\n <option key={t} value={t}>{t}</option>\n ))}\n </select>\n </div>\n\n {error && (\n <p style={{ marginBottom: 12, color: 'var(--color-danger)', fontSize: 13 }}>{error}</p>\n )}\n\n <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>\n <Button variant=\"ghost\" onClick={onClose} disabled={creating}>Cancel</Button>\n <Button variant=\"primary\" onClick={handleCreate} disabled={creating || !slug.trim()}>\n {creating ? 'Creating…' : 'Create'}\n </Button>\n </div>\n </div>\n );\n}\n","// src/components/ArtifactListDialog.tsx — Dialog for /plan list command.\n\nimport { Button } from './Button';\n\ntype ArtifactListDialogProps = {\n data?: Record<string, unknown>;\n onClose: () => void;\n};\n\nexport function ArtifactListDialog({ data, onClose }: ArtifactListDialogProps) {\n const plans = (data?.plans as string[]) ?? [];\n const count = (data?.count as number) ?? plans.length;\n\n const handleOpen = (slug: string) => {\n window.open(`/artifacts/${slug}/`, '_blank');\n };\n\n return (\n <div>\n {plans.length === 0 ? (\n <p style={{ marginBottom: 16, color: 'var(--color-muted)' }}>\n No plans found in this worktree. Use <code>/artifact new <slug></code> to create one.\n </p>\n ) : (\n <div style={{ marginBottom: 16 }}>\n <p style={{ marginBottom: 12, fontSize: 13, color: 'var(--color-muted)' }}>\n {count} plan{count !== 1 ? 's' : ''} in this worktree:\n </p>\n <ul style={{ listStyle: 'none', padding: 0, margin: 0 }}>\n {plans.map((slug) => (\n <li\n key={slug}\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: '6px 0',\n borderBottom: '1px solid var(--color-border)',\n }}\n >\n <code style={{ fontSize: 13 }}>{slug}</code>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => handleOpen(slug)}>\n Open\n </Button>\n </li>\n ))}\n </ul>\n </div>\n )}\n <div style={{ display: 'flex', justifyContent: 'flex-end' }}>\n <Button variant=\"ghost\" onClick={onClose}>Close</Button>\n </div>\n </div>\n );\n}\n","// src/components/HelpDialog.tsx — Dialog for /help and /bizar commands.\n\nimport { Button } from './Button';\n\ntype HelpDialogProps = {\n data?: Record<string, unknown>;\n onClose: () => void;\n};\n\ntype CmdEntry = { cmd: string; desc: string };\n\nexport function HelpDialog({ data, onClose }: HelpDialogProps) {\n const commands = (data?.commands as CmdEntry[]) ?? [];\n const templates = (data?.templates as string[]) ?? [];\n const statuses = (data?.statuses as string[]) ?? [];\n\n return (\n <div>\n {commands.length > 0 ? (\n <table style={{ width: '100%', borderCollapse: 'collapse', marginBottom: 16, fontSize: 13 }}>\n <tbody>\n {commands.map((entry) => (\n <tr key={entry.cmd} style={{ borderBottom: '1px solid var(--color-border)' }}>\n <td style={{ padding: '5px 8px 5px 0', whiteSpace: 'nowrap' }}>\n <code style={{ fontSize: 12 }}>{entry.cmd}</code>\n </td>\n <td style={{ padding: '5px 0', color: 'var(--color-muted)' }}>{entry.desc}</td>\n </tr>\n ))}\n </tbody>\n </table>\n ) : (\n <p style={{ marginBottom: 16, color: 'var(--color-muted)' }}>No commands available.</p>\n )}\n\n {templates.length > 0 && (\n <div style={{ marginBottom: 12 }}>\n <p style={{ fontSize: 12, color: 'var(--color-muted)', marginBottom: 4 }}>Available templates:</p>\n <p style={{ fontSize: 13 }}>{templates.join(', ')}</p>\n </div>\n )}\n\n {statuses.length > 0 && (\n <div style={{ marginBottom: 12 }}>\n <p style={{ fontSize: 12, color: 'var(--color-muted)', marginBottom: 4 }}>Available statuses:</p>\n <p style={{ fontSize: 13 }}>{statuses.join(', ')}</p>\n </div>\n )}\n\n <div style={{ display: 'flex', justifyContent: 'flex-end' }}>\n <Button variant=\"ghost\" onClick={onClose}>Close</Button>\n </div>\n </div>\n );\n}\n","// src/components/AuditDialog.tsx — Dialog for /audit command.\n\nimport { useState } from 'react';\nimport { Button } from './Button';\nimport { api } from '../lib/api';\n\ntype AuditDialogProps = {\n data?: Record<string, unknown>;\n onClose: () => void;\n};\n\ntype AuditResult = {\n ok: boolean;\n findings: string[];\n error?: string;\n};\n\nexport function AuditDialog({ data, onClose }: AuditDialogProps) {\n const [running, setRunning] = useState(false);\n const [result, setResult] = useState<AuditResult | null>(null);\n\n const handleRunAudit = async () => {\n setRunning(true);\n setResult(null);\n try {\n // The audit is run by posting to /api/chat with an /audit message,\n // which forwards to the opencode serve child where the plugin handles it.\n // We poll for a response via the chat session.\n const res = await api.post<AuditResult>('/chat/audit', {});\n setResult(res);\n } catch (err) {\n setResult({ ok: false, findings: [], error: (err as Error).message });\n } finally {\n setRunning(false);\n }\n };\n\n return (\n <div>\n {result === null ? (\n <>\n <p style={{ marginBottom: 16, lineHeight: 1.6 }}>\n Run a security audit of your Bizar agent configuration. The audit checks for common misconfigurations, exposed secrets, and insecure defaults.\n </p>\n <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>\n <Button variant=\"ghost\" onClick={onClose}>Cancel</Button>\n <Button variant=\"primary\" onClick={handleRunAudit} disabled={running}>\n {running ? 'Running…' : 'Run Audit'}\n </Button>\n </div>\n </>\n ) : (\n <>\n {result.ok ? (\n <div>\n <p style={{ marginBottom: 12, fontWeight: 600, color: 'var(--color-success)' }}>\n Audit passed — no issues found.\n </p>\n {result.findings.length > 0 && (\n <ul style={{ marginBottom: 16, paddingLeft: 20 }}>\n {result.findings.map((f, i) => (\n <li key={i} style={{ marginBottom: 4, fontSize: 13 }}>{f}</li>\n ))}\n </ul>\n )}\n </div>\n ) : (\n <p style={{ marginBottom: 16, color: 'var(--color-danger)' }}>\n Audit failed: {result.error ?? 'unknown error'}\n </p>\n )}\n <div style={{ display: 'flex', justifyContent: 'flex-end' }}>\n <Button variant=\"ghost\" onClick={onClose}>Close</Button>\n </div>\n </>\n )}\n </div>\n );\n}\n","// src/components/CommandDialog.tsx — Generic dialog wrapper that routes to the\n// correct specific dialog component based on the DialogDescriptor's `component` field.\n\nimport { VisualPlanDialog } from './VisualPlanDialog';\nimport { ArtifactCreateDialog } from './ArtifactCreateDialog';\nimport { ArtifactListDialog } from './ArtifactListDialog';\nimport { HelpDialog } from './HelpDialog';\nimport { AuditDialog } from './AuditDialog';\nimport type { DialogDescriptor } from '../lib/types';\n\nexport type { DialogDescriptor };\n\nfunction GenericDialog({ dialog, onClose }: { dialog: DialogDescriptor; onClose: () => void }) {\n if (!dialog.data) {\n return (\n <div>\n <p style={{ marginBottom: 16, lineHeight: 1.6 }}>\n {`Command: ${dialog.command}`}\n </p>\n <div style={{ display: 'flex', justifyContent: 'flex-end' }}>\n <button type=\"button\" className=\"btn\" onClick={onClose}>Close</button>\n </div>\n </div>\n );\n }\n\n const { message, detail, url } = dialog.data as { message?: string; detail?: string; url?: string };\n\n return (\n <div>\n <p style={{ marginBottom: 16, lineHeight: 1.6 }}>\n {message ?? `Command: ${dialog.command}`}\n </p>\n {detail && (\n <p style={{ marginBottom: 16, color: 'var(--color-muted)', fontSize: 13 }}>\n {detail}\n </p>\n )}\n {url && (\n <p style={{ marginBottom: 16 }}>\n <a href={url} target=\"_blank\" rel=\"noopener noreferrer\">{url}</a>\n </p>\n )}\n <div style={{ display: 'flex', justifyContent: 'flex-end' }}>\n <button type=\"button\" className=\"btn\" onClick={onClose}>Close</button>\n </div>\n </div>\n );\n}\n\nexport function CommandDialog({ dialog, onClose }: { dialog: DialogDescriptor; onClose: () => void }) {\n switch (dialog.component) {\n case 'visual-artifact':\n return <VisualPlanDialog data={dialog.data} onClose={onClose} />;\n case 'artifact-create':\n return <ArtifactCreateDialog data={dialog.data} onClose={onClose} />;\n case 'artifact-list':\n return <ArtifactListDialog data={dialog.data} onClose={onClose} />;\n case 'help':\n return <HelpDialog data={dialog.data} onClose={onClose} />;\n case 'audit':\n return <AuditDialog data={dialog.data} onClose={onClose} />;\n default:\n return <GenericDialog dialog={dialog} onClose={onClose} />;\n }\n}\n","// src/components/Card.tsx — wrapper card.\n\nimport type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../lib/utils';\n\nexport type CardProps = HTMLAttributes<HTMLDivElement> & {\n variant?: 'elevated' | 'outlined' | 'filled';\n interactive?: boolean;\n children?: ReactNode;\n};\n\nexport function Card({\n variant = 'elevated',\n interactive = false,\n className,\n children,\n ...rest\n}: CardProps) {\n return (\n <div\n className={cn(\n 'card',\n `card-${variant}`,\n interactive && 'card-interactive',\n className,\n )}\n {...rest}\n >\n {children}\n </div>\n );\n}\n\nexport function CardTitle({ children, className }: { children: ReactNode; className?: string }) {\n return <h3 className={cn('card-title', className)}>{children}</h3>;\n}\n\nexport function CardMeta({ children, className }: { children: ReactNode; className?: string }) {\n return <div className={cn('card-meta', className)}>{children}</div>;\n}\n","// src/components/EmptyState.tsx — friendly empty / error placeholder.\n\nimport type { ReactNode } from 'react';\nimport { Inbox } from 'lucide-react';\nimport { cn } from '../lib/utils';\n\nexport type EmptyStateProps = {\n icon?: ReactNode;\n title: string;\n message?: ReactNode;\n action?: ReactNode;\n className?: string;\n};\n\nexport function EmptyState({\n icon,\n title,\n message,\n action,\n className,\n}: EmptyStateProps) {\n return (\n <div className={cn('empty-state', className)}>\n <div className=\"empty-icon\">{icon ?? <Inbox size={32} />}</div>\n <div className=\"empty-title\">{title}</div>\n {message && <div className=\"empty-message\">{message}</div>}\n {action && <div className=\"empty-action\">{action}</div>}\n </div>\n );\n}\n","// src/views/Overview.tsx — v3.7.0 activity cards + SSE stream.\nimport { useEffect, useRef, useState } from 'react';\nimport {\n Bot,\n CheckSquare,\n Folder,\n LayoutDashboard,\n Map,\n MessageSquare,\n RefreshCw,\n PlayCircle,\n ShieldCheck,\n FileText,\n Zap,\n Plus,\n Trash2,\n Power,\n Send,\n Sparkles,\n AlertOctagon,\n AlertTriangle,\n CheckCircle2,\n Activity,\n Puzzle,\n Clock,\n FolderSearch,\n EyeOff,\n Eye,\n X,\n} from 'lucide-react';\nimport { Card, CardTitle, CardMeta } from '../components/Card';\nimport { Button } from '../components/Button';\nimport { EmptyState } from '../components/EmptyState';\nimport { Spinner } from '../components/Spinner';\nimport { useToast } from '../components/Toast';\nimport { useModal } from '../components/Modal';\nimport { FileBrowser } from '../components/FileBrowser';\nimport { api } from '../lib/api';\nimport { formatRelative, formatTime } from '../lib/utils';\nimport type { Overview, Settings, Snapshot, ActivityItem, ProjectRecord, Mod, ScanResult, DirectoryListing } from '../lib/types';\nimport { cn } from '../lib/utils';\n\ntype Props = {\n snapshot: Snapshot;\n settings: Settings;\n activeTab: string;\n setActiveTab: (id: string) => void;\n refreshSnapshot: () => Promise<void>;\n};\n\nexport function Overview({\n snapshot,\n settings,\n setActiveTab,\n refreshSnapshot,\n}: Props) {\n const toast = useToast();\n const modal = useModal();\n const inputRef = useRef<HTMLTextAreaElement | null>(null);\n const [overview, setOverview] = useState<Overview | null>(\n snapshot.overview ?? null,\n );\n const [loading, setLoading] = useState(!snapshot.overview);\n const [projects, setProjects] = useState<ProjectRecord[]>(snapshot.projects || []);\n const [activeId, setActiveId] = useState<string | null>(\n snapshot.activeProject?.id || null,\n );\n const [mods, setMods] = useState<Mod[]>(snapshot.mods || []);\n const [submitting, setSubmitting] = useState(false);\n // v3.7.0 — Live activity feed via SSE\n const [activityItems, setActivityItems] = useState<ActivityItem[]>(\n snapshot.overview?.recentActivity ?? [],\n );\n const [activityExpanded, setActivityExpanded] = useState(false);\n // v3.15.0 — Hidden event keys are stored server-side; we just track\n // the set in client state. Hiding does NOT delete — see Settings →\n // Activity Log for the full feed.\n const [hiddenKeys, setHiddenKeys] = useState<Set<string>>(new Set());\n\n // v3.15.0 — Load hidden set once on mount\n useEffect(() => {\n let cancelled = false;\n (async () => {\n try {\n const r = await api.get<{ hidden: string[] }>('/activity/hidden');\n if (!cancelled) setHiddenKeys(new Set(r.hidden || []));\n } catch { /* non-fatal */ }\n })();\n return () => { cancelled = true; };\n }, []);\n\n // v3.15.0 — Helper: stable key per activity item\n const itemKey = (it: ActivityItem, idx: number): string => {\n const k = `${it.kind || ''}|${it.ts || ''}|${(it.slug as string) || (it.title as string) || ''}|${idx}`;\n // hash to a short key (matches server-side activityKey derivation)\n let h = 0;\n for (let i = 0; i < k.length; i++) h = ((h << 5) - h + k.charCodeAt(i)) | 0;\n return Math.abs(h).toString(16).padStart(8, '0').slice(0, 16);\n };\n\n const onHide = async (key: string) => {\n const next = new Set(hiddenKeys);\n next.add(key);\n setHiddenKeys(next);\n try {\n await api.post('/activity/hide', { keys: [key] });\n } catch (err) {\n // rollback on failure\n const rollback = new Set(hiddenKeys);\n setHiddenKeys(rollback);\n toast.error(`Hide failed: ${(err as Error).message}`);\n }\n };\n\n const onClearAll = async () => {\n if (!confirm('Hide every recent activity item from the overview? The full log stays in Settings → Activity Log.')) return;\n const all = activityItems.map((it, idx) => itemKey(it, idx));\n const next = new Set(hiddenKeys);\n all.forEach((k) => next.add(k));\n setHiddenKeys(next);\n try {\n await api.post('/activity/hide', { keys: all });\n toast.success(`Hidden ${all.length} item(s). Restore them in Settings → Activity Log.`);\n } catch (err) {\n toast.error(`Clear failed: ${(err as Error).message}`);\n }\n };\n\n const onRestoreAll = async () => {\n setHiddenKeys(new Set());\n try {\n await api.del('/activity/hide');\n toast.success('All hidden activity restored to the overview.');\n } catch (err) {\n toast.error(`Restore failed: ${(err as Error).message}`);\n }\n };\n\n // v3.7.0 — Sync initial snapshot data\n useEffect(() => {\n if (snapshot.overview) {\n setOverview(snapshot.overview);\n setActivityItems(snapshot.overview.recentActivity ?? []);\n setLoading(false);\n }\n setProjects(snapshot.projects || []);\n setActiveId(snapshot.activeProject?.id || null);\n setMods(snapshot.mods || []);\n }, [snapshot.overview, snapshot.projects, snapshot.activeProject, snapshot.mods]);\n\n // v3.7.0 — Subscribe to SSE activity stream\n // v3.6.0 — Append ?token=… for auth. EventSource can't set custom\n // headers, so the server accepts the token via query string too.\n useEffect(() => {\n let es: EventSource;\n try {\n const tok = api.getToken();\n const url = tok\n ? `/api/activity/stream?token=${encodeURIComponent(tok)}`\n : '/api/activity/stream';\n es = new EventSource(url);\n es.addEventListener('snapshot', (e) => {\n try {\n const parsed = JSON.parse((e as MessageEvent).data) as { events: ActivityItem[]; generatedAt?: string };\n setActivityItems(Array.isArray(parsed.events) ? parsed.events.slice(0, 50) : []);\n } catch { /* ignore parse errors */ }\n });\n es.addEventListener('activity', (e) => {\n try {\n const entry = JSON.parse((e as MessageEvent).data) as ActivityItem;\n setActivityItems((cur) => [entry, ...cur].slice(0, 50));\n } catch { /* ignore parse errors */ }\n });\n } catch { /* SSE not available — fallback to snapshot data */ }\n return () => { try { es?.close(); } catch { /* ignore */ } };\n }, []);\n\n const onRefresh = async () => {\n toast.info('Refreshing…', 1500);\n await refreshSnapshot();\n try {\n const data = await api.get<{ projects: ProjectRecord[]; active: string | null }>('/projects');\n setProjects(data.projects || []);\n setActiveId(data.active || null);\n } catch { /* ignore */ }\n };\n\n const onAddProject = () => {\n modal.open({\n title: 'Add project',\n children: (\n <AddProjectDialog\n settings={settings}\n onAdd={async (path: string, name: string | null) => {\n try {\n const r = await api.post<ProjectRecord>('/projects', { path, name });\n setProjects((cur) => [...cur.filter((p) => p.id !== r.id), r]);\n toast.success('Project added.');\n modal.close();\n } catch (err) {\n toast.error(`Add failed: ${(err as Error).message}`);\n }\n }}\n />\n ),\n footer: (\n <div className=\"modal-footer-actions\">\n <Button variant=\"ghost\" onClick={() => modal.close()}>Cancel</Button>\n </div>\n ),\n });\n };\n\n const onUseCurrentDir = async () => {\n try {\n const data = await api.post<{ projects: ProjectRecord[]; active: string | null }>(\n '/projects/auto-detect',\n );\n setProjects(data.projects || []);\n setActiveId(data.active || null);\n const newActive = data.projects?.find((p) => p.id === data.active);\n toast.success(newActive ? `Active: ${newActive.name}` : 'Projects refreshed.');\n await refreshSnapshot();\n } catch (err) {\n toast.error(`Auto-detect failed: ${(err as Error).message}`);\n }\n };\n\n const onActivate = async (id: string) => {\n try {\n await api.post(`/projects/${encodeURIComponent(id)}/activate`);\n setActiveId(id);\n toast.success('Project activated.');\n await refreshSnapshot();\n } catch (err) {\n toast.error(`Activate failed: ${(err as Error).message}`);\n }\n };\n\n const onRemove = async (id: string) => {\n if (!confirm(`Remove project \"${id}\" from the registry?`)) return;\n try {\n await api.del(`/projects/${encodeURIComponent(id)}`);\n setProjects((cur) => cur.filter((p) => p.id !== id));\n if (activeId === id) setActiveId(null);\n toast.success('Project removed.');\n } catch (err) {\n toast.error(`Remove failed: ${(err as Error).message}`);\n }\n };\n\n if (loading || !overview) {\n return (\n <div className=\"view-loading\">\n <Spinner size=\"lg\" />\n <p>Loading overview…</p>\n </div>\n );\n }\n\n return (\n <div className=\"view view-overview\">\n {/* v3.4.0 — Hero takes the spotlight. No card wrapper. */}\n <div className=\"overview-hero-noframe\">\n <h1>What do you want to do?</h1>\n <p className=\"overview-hero-subtitle\">\n Describe what you want — Odin will split it into tasks, create a plan,\n delegate to background agents, and track progress in real time.\n </p>\n <form\n className=\"overview-hero-form-noframe\"\n onSubmit={async (e) => {\n e.preventDefault();\n const text = (inputRef.current?.value || '').trim();\n if (!text) return;\n setSubmitting(true);\n try {\n const r = await api.post<{ subtasks?: unknown[] }>('/tasks/submit', { title: text });\n toast.success(`Odin split it into ${(r.subtasks?.length || 1)} task(s)`);\n if (inputRef.current) inputRef.current.value = '';\n await refreshSnapshot();\n } catch (err) {\n toast.error(`Failed: ${(err as Error).message}`);\n } finally {\n setSubmitting(false);\n }\n }}\n >\n <textarea\n ref={inputRef}\n className=\"overview-input-hero\"\n placeholder=\"e.g. Implement user authentication with email + password, including registration, login, password reset, and integration tests. Use Bcrypt, JWT tokens, and the existing API style.\"\n disabled={submitting}\n />\n <div style={{ display: 'flex', gap: 'var(--space-2)', alignItems: 'center', flexWrap: 'wrap' }}>\n <Button\n type=\"submit\"\n variant=\"primary\"\n size=\"lg\"\n disabled={submitting}\n >\n {submitting ? <Spinner size=\"sm\" /> : <Send size={16} />}\n Submit to Odin\n </Button>\n <span className=\"muted\" style={{ fontSize: 12 }}>\n <Sparkles size={12} style={{ display: 'inline', verticalAlign: -2, color: 'var(--accent)' }} />\n {' '}Odin + 12 specialist agents available\n </span>\n </div>\n </form>\n\n <div className=\"overview-quick-actions-row\">\n {['Implement feature', 'Fix bug', 'Refactor', 'Investigate', 'Add tests', 'Document', 'Optimize', 'Deploy'].map((action) => (\n <button\n key={action}\n type=\"button\"\n className=\"overview-quick-chip\"\n onClick={() => {\n if (inputRef.current) {\n inputRef.current.value = action;\n inputRef.current.focus();\n }\n }}\n >\n {action}\n </button>\n ))}\n </div>\n </div>\n\n <div className=\"overview-feed\">\n <div className=\"overview-feed-head\">\n <h2>Recent activity</h2>\n <div className=\"overview-feed-head-actions\">\n {hiddenKeys.size > 0 && (\n <Button variant=\"ghost\" size=\"sm\" onClick={onRestoreAll} title=\"Restore hidden items to this overview\">\n <Eye size={12} /> Show {hiddenKeys.size} hidden\n </Button>\n )}\n {activityItems.length > 8 && (\n <Button variant=\"ghost\" size=\"sm\" onClick={() => setActivityExpanded((v) => !v)}>\n {activityExpanded ? 'Show less' : 'Show all'}\n </Button>\n )}\n {activityItems.length > 0 && (\n <Button variant=\"ghost\" size=\"sm\" onClick={onClearAll} title=\"Hide every item from the overview (full log kept)\">\n <EyeOff size={12} /> Hide all\n </Button>\n )}\n </div>\n </div>\n {hiddenKeys.size > 0 && (\n <div className=\"activity-hidden-banner\" role=\"status\">\n <span>\n <EyeOff size={12} style={{ verticalAlign: -2, marginRight: 6 }} />\n {hiddenKeys.size} item{hiddenKeys.size === 1 ? '' : 's'} hidden from the overview.\n </span>\n <Button variant=\"ghost\" size=\"sm\" onClick={onRestoreAll}>\n <Eye size={12} /> Show them again\n </Button>\n </div>\n )}\n {activityItems.length === 0 ? (\n <div className=\"muted\" style={{ padding: '24px 0', fontSize: 13 }}>\n No activity yet. Use the chat above or invoke a Bizar command to start a feed.\n </div>\n ) : (\n <div className={cn('activity-feed-list-wrap', !activityExpanded && 'activity-feed-list-wrap-collapsed')}>\n <div className=\"activity-feed-list\">\n {activityItems.slice(0, 30).map((it, idx) => {\n const k = itemKey(it, idx);\n if (hiddenKeys.has(k)) return null;\n return (\n <ActivityFeedItem\n key={`${it.ts}-${idx}`}\n item={it}\n activityKey={k}\n onNavigate={setActiveTab}\n onHide={onHide}\n />\n );\n })}\n </div>\n {!activityExpanded && activityItems.length > 8 && <div className=\"activity-feed-fade\" aria-hidden=\"true\" />}\n </div>\n )}\n </div>\n\n {/* v3.4.0 — Below-the-fold: projects + meta (compact) */}\n <Card className=\"project-picker\">\n <CardTitle>\n <Folder size={14} /> Projects\n <Button variant=\"ghost\" size=\"sm\" style={{ marginLeft: 'auto' }} onClick={onAddProject}>\n <Plus size={12} /> Add\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={onUseCurrentDir} title=\"Use the server's working directory\">\n <Plus size={12} /> Auto-detect\n </Button>\n {settings?.dashboard?.projectsDirectory && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n title={`Scan ${settings.dashboard.projectsDirectory} for projects`}\n onClick={async () => {\n try {\n const r = await api.post<ScanResult>('/projects/scan');\n if (r.error) {\n toast.error(r.error);\n } else {\n toast.success(`Added ${r.added.length}, skipped ${r.skipped}.`);\n }\n await refreshSnapshot();\n const data = await api.get<{ projects: ProjectRecord[]; active: string | null }>('/projects');\n setProjects(data.projects || []);\n setActiveId(data.active || null);\n } catch (err) {\n toast.error(`Scan failed: ${(err as Error).message}`);\n }\n }}\n >\n <FolderSearch size={12} /> Scan\n </Button>\n )}\n <Button variant=\"ghost\" size=\"sm\" onClick={onRefresh} title=\"Refresh\">\n <RefreshCw size={12} />\n </Button>\n </CardTitle>\n <CardMeta>\n {projects.length} project{projects.length === 1 ? '' : 's'} ·\n {' '}{overview.counts.agents} agents ·\n {' '}{overview.counts.sessions} session{overview.counts.sessions === 1 ? '' : 's'}\n </CardMeta>\n {projects.length === 0 ? (\n <EmptyState\n icon={<Folder size={32} />}\n title=\"No projects yet\"\n message=\"Add a project to start tracking its tasks, plans, and schedules.\"\n action={\n <div className=\"empty-state-actions\">\n <Button variant=\"primary\" onClick={onUseCurrentDir}>\n <Plus size={14} /> Use current directory\n </Button>\n <Button variant=\"secondary\" onClick={onAddProject}>\n Add by path…\n </Button>\n </div>\n }\n />\n ) : (\n <div className=\"project-grid\">\n {projects.map((p) => (\n <ProjectCard\n key={p.id}\n project={p}\n active={activeId === p.id}\n onOpen={() => onActivate(p.id)}\n onRemove={() => onRemove(p.id)}\n />\n ))}\n </div>\n )}\n </Card>\n\n <div className=\"overview-cols\">\n <Card>\n <CardTitle>Mods</CardTitle>\n <CardMeta>Extensions installed under <code>~/.config/bizar/mods/</code></CardMeta>\n {mods.length === 0 ? (\n <div className=\"muted\">No mods installed.</div>\n ) : (\n <ul className=\"mod-mini-list\">\n {mods.map((m) => (\n <li key={m.id} className=\"mod-mini\">\n <span className=\"mod-mini-name\">{m.name}</span>\n <span className=\"mod-mini-meta\">v{m.version} · {m.type}</span>\n <span className={`mod-mini-pill ${m.enabled ? 'mod-mini-pill-on' : 'mod-mini-pill-off'}`}>\n {m.enabled ? 'on' : 'off'}\n </span>\n </li>\n ))}\n </ul>\n )}\n </Card>\n\n <Card>\n <CardTitle>Environment</CardTitle>\n <CardMeta>Runtime + paths</CardMeta>\n <dl className=\"env-table\">\n <dt>Node</dt>\n <dd className=\"mono\">{overview.versions.node}</dd>\n <dt>Platform</dt>\n <dd className=\"mono\">{overview.versions.platform}</dd>\n <dt>Project root</dt>\n <dd className=\"mono ellipsis\" title={overview.versions.projectRoot}>\n {overview.versions.projectRoot}\n </dd>\n <dt>Bizar root</dt>\n <dd className=\"mono ellipsis\" title={overview.versions.bizarRoot}>\n {overview.versions.bizarRoot}\n </dd>\n <dt>Generated</dt>\n <dd className=\"mono tabular-nums\">\n {formatTime(overview.generatedAt)}\n </dd>\n </dl>\n </Card>\n </div>\n </div>\n );\n}\n\n// ─── AddProjectDialog ─────────────────────────────────────────────────────────\n\n/**\n * Pre-flight approach: before POST /projects we verify the selected path\n * still exists (GET /fs?path=...). This avoids the ugly 404 toast when a\n * directory is deleted between selection and submit.\n */\nfunction AddProjectDialog({\n settings,\n onAdd,\n}: {\n settings: Settings;\n onAdd: (path: string, name: string | null) => void;\n}) {\n const [path, setPath] = useState(settings?.dashboard?.projectsDirectory ?? '');\n const [name, setName] = useState('');\n const [preflighting, setPreflighting] = useState(false);\n const [preflightError, setPreflightError] = useState<string | null>(null);\n\n const handleAdd = async () => {\n if (!path) return;\n setPreflighting(true);\n setPreflightError(null);\n try {\n // Pre-flight: verify the path still exists\n await api.get<DirectoryListing>('/fs?path=' + encodeURIComponent(path));\n // Path is valid — proceed with the POST\n onAdd(path, name || null);\n } catch (err) {\n const apiErr = err as { status?: number; data?: { message?: string } };\n if (apiErr.status === 404) {\n setPreflightError('That folder no longer exists. Pick another.');\n } else {\n setPreflightError(\n apiErr.data?.message ?? (err as Error).message ?? 'Validation failed.',\n );\n }\n } finally {\n setPreflighting(false);\n }\n };\n\n return (\n <div>\n <label className=\"field-label\">Folder</label>\n <FileBrowser\n value={path}\n onChange={(p) => {\n setPath(p);\n setPreflightError(null);\n }}\n projectsDirectory={settings?.dashboard?.projectsDirectory}\n height={320}\n />\n {preflightError && (\n <p className=\"field-help\" style={{ color: 'var(--error)', marginTop: 4 }}>\n {preflightError}\n </p>\n )}\n <div style={{ marginTop: 'var(--space-3)' }}>\n <label className=\"field-label\" htmlFor=\"add-project-name\">Name (optional)</label>\n <input\n id=\"add-project-name\"\n className=\"input\"\n type=\"text\"\n placeholder=\"My App\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n />\n <p className=\"field-help\" style={{ marginTop: 4 }}>\n Display name for this project. Defaults to the folder name.\n </p>\n </div>\n <div style={{ marginTop: 'var(--space-3)', display: 'flex', justifyContent: 'flex-end' }}>\n <Button\n variant=\"primary\"\n onClick={handleAdd}\n disabled={!path || preflighting}\n >\n {preflighting ? <span className=\"btn-spinner\" /> : null}\n {preflighting ? 'Checking…' : 'Add'}\n </Button>\n </div>\n </div>\n );\n}\n\nfunction ProjectCard({\n project,\n active,\n onOpen,\n onRemove,\n}: {\n project: ProjectRecord;\n active: boolean;\n onOpen: () => void;\n onRemove: () => void;\n}) {\n const statusColor = {\n active: 'status-on',\n inactive: 'status-neutral',\n error: 'status-error',\n }[project.status] || 'status-neutral';\n return (\n <div className={`project-card ${active ? 'project-card-active' : ''}`}>\n <div className=\"project-card-head\">\n <span className={`project-card-status ${statusColor}`}>\n {project.status}\n </span>\n <div className=\"project-card-name\">{project.name}</div>\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label=\"Remove project\"\n title=\"Remove\"\n onClick={(e) => {\n e.stopPropagation();\n onRemove();\n }}\n >\n <Trash2 size={12} />\n </button>\n </div>\n <div className=\"project-card-path mono ellipsis\" title={project.path}>\n {project.path}\n </div>\n <div className=\"project-card-meta\">\n {project.lastAccessed && (\n <span className=\"muted\">Last opened {formatRelative(project.lastAccessed)}</span>\n )}\n </div>\n <div className=\"project-card-actions\">\n <Button variant={active ? 'ghost' : 'primary'} size=\"sm\" onClick={onOpen}>\n {active ? <><Power size={12} /> Active</> : <>Open</>}\n </Button>\n </div>\n </div>\n );\n}\n\nfunction sentenceCase(s: string): string {\n if (!s) return s;\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n\nfunction humanizeKind(kind: string): string {\n const normalized = (kind || 'activity').trim().toLowerCase().replace(/[:_]/g, '.');\n const [scopeRaw, actionRaw = 'updated'] = normalized.split('.');\n const scopeMap: Record<string, string> = {\n settings: 'Settings',\n task: 'Task',\n tasks: 'Task',\n agent: 'Agent',\n agents: 'Agent',\n plan: 'Plan',\n plans: 'Plan',\n bg: 'Background job',\n background: 'Background job',\n session: 'Session',\n mod: 'Mod',\n mods: 'Mod',\n provider: 'Provider',\n providers: 'Provider',\n };\n const actionMap: Record<string, string> = {\n create: 'created', created: 'created',\n add: 'added', added: 'added',\n update: 'updated', updated: 'updated',\n delegate: 'delegated', delegated: 'delegated',\n invoke: 'invoked', invoked: 'invoked',\n restart: 'restarted', restarted: 'restarted',\n delete: 'deleted', deleted: 'deleted',\n remove: 'removed', removed: 'removed',\n archive: 'archived', archived: 'archived',\n restore: 'restored', restored: 'restored',\n complete: 'completed', completed: 'completed',\n fail: 'failed', failed: 'failed',\n error: 'errored', stuck: 'marked stuck',\n };\n const scope = scopeMap[scopeRaw] || sentenceCase(scopeRaw.replace(/-/g, ' '));\n const action = actionMap[actionRaw] || actionRaw.replace(/-/g, ' ');\n return `${scope} ${action}`.trim();\n}\n\nfunction firstString(it: ActivityItem, keys: string[]): string {\n for (const key of keys) {\n const value = it[key];\n if (typeof value === 'string' && value.trim()) return value.trim();\n }\n return '';\n}\n\nfunction formatActivitySummary(it: ActivityItem): string {\n const direct = firstString(it, ['message', 'text', 'prompt', 'title', 'name']);\n if (direct) return direct;\n const parts: string[] = [];\n const slug = firstString(it, ['slug']);\n const agent = firstString(it, ['agent', 'author']);\n const status = firstString(it, ['status']);\n if (slug) parts.push(`Plan ${slug}`);\n if (agent) parts.push(agent);\n if (status) parts.push(status);\n return parts.length ? parts.join(' · ') : 'No additional details.';\n}\n\n// v3.7.0 — Format a timestamp as a relative string (\"2m ago\", \"1h ago\")\nfunction formatRelativeTime(ts: string): string {\n return formatRelative(ts);\n}\n\n// v3.7.0 — Get severity color token from kind or status field\nfunction activitySeverity(it: ActivityItem): 'error' | 'warning' | 'success' | 'info' {\n const k = ((it.kind as string) || '').toLowerCase();\n const s = ((it.status as string) || '').toLowerCase();\n if (k.includes('error') || s === 'error' || s === 'failure') return 'error';\n if (k.includes('warn') || s === 'blocked') return 'warning';\n if (k.includes('done') || k.includes('success') || s === 'done') return 'success';\n return 'info';\n}\n\n// v3.7.0 — Map activity kind to icon\nfunction activityIcon(kind: string) {\n const k = kind.toLowerCase();\n if (k === 'task') return CheckSquare;\n if (k === 'agent') return Bot;\n if (k === 'plan') return Map;\n if (k.includes('bg') || k.includes('background') || k.includes('job')) return Zap;\n if (k === 'mod') return Puzzle;\n if (k === 'skill') return Sparkles;\n if (k.includes('error') || k.includes('failure')) return AlertOctagon;\n if (k.includes('warn')) return AlertTriangle;\n return Activity;\n}\n\n// v3.7.0 — Navigate to the relevant tab when a card is clicked\nfunction activityNavTarget(kind: string): string | null {\n const k = kind.toLowerCase();\n if (k === 'task') return 'tasks';\n if (k === 'agent') return 'agents';\n if (k === 'plan') return 'artifacts';\n if (k.includes('bg') || k.includes('background')) return 'activity';\n if (k === 'mod') return 'mods';\n if (k === 'skill') return 'skills';\n return null;\n}\n\n// v3.7.0 — Activity card component\nfunction ActivityFeedItem({\n item,\n activityKey,\n onNavigate,\n onHide,\n}: {\n item: ActivityItem;\n activityKey: string;\n onNavigate: (tab: string) => void;\n onHide: (key: string) => void;\n}) {\n const severity = activitySeverity(item);\n const Icon = activityIcon(item.kind || '');\n const title = humanizeKind(item.kind || 'activity');\n const msg = formatActivitySummary(item);\n const navTarget = activityNavTarget(item.kind || '');\n\n const accentColor =\n severity === 'error' ? 'var(--error)' :\n severity === 'warning' ? 'var(--warning)' :\n severity === 'success' ? 'var(--success)' :\n 'var(--accent)';\n\n return (\n <div className={cn('activity-feed-row', `activity-feed-row-${severity}`)}>\n <button\n type=\"button\"\n className=\"activity-feed-row-main\"\n onClick={() => { if (navTarget) onNavigate(navTarget); }}\n title={navTarget ? `Open ${navTarget}` : title}\n >\n <div className=\"activity-feed-icon\" style={{ color: accentColor }}>\n <Icon size={14} />\n </div>\n <div className=\"activity-feed-body\">\n <div className=\"activity-feed-title-row\">\n <div className=\"activity-feed-title\">{title}</div>\n <div className=\"activity-feed-time text-xs muted tabular-nums\">{formatRelativeTime(item.ts)}</div>\n </div>\n <div className=\"activity-feed-summary text-sm\">{msg}</div>\n </div>\n </button>\n <button\n type=\"button\"\n className=\"activity-feed-hide-btn\"\n onClick={() => onHide(activityKey)}\n title=\"Hide this from the overview (kept in Settings → Activity Log)\"\n aria-label=\"Hide from overview\"\n >\n <X size={12} />\n </button>\n </div>\n );\n}\n","// src/components/chat/SessionRowMenu.tsx — three-mode popover for a session rail row.\n//\n// Three modes:\n// 'main' — Rename + Delete buttons\n// 'rename' — Inline input with Cancel/Save\n// 'confirm-delete' — Inline confirmation with Cancel/Delete\n//\n// Rendered via createPortal on document.body so it isn't clipped by\n// the rail's overflow:auto scroll container. The parent row supplies\n// the anchor's bounding rect (or the menu uses an anchor prop).\n\nimport { useEffect, useRef } from 'react';\nimport { createPortal } from 'react-dom';\nimport { Edit, Trash2 } from 'lucide-react';\n\nexport type SessionMenuMode = 'main' | 'rename' | 'confirm-delete';\n\nexport interface SessionRowMenuAnchor {\n /** Bounding rect of the trigger / row used to position the popover. */\n rect: DOMRect;\n}\n\nexport interface SessionRowMenuProps {\n session: { id: string; title: string };\n mode: SessionMenuMode;\n anchor: SessionRowMenuAnchor;\n renameDraft: string;\n setRenameDraft: (s: string) => void;\n onEdit: () => void;\n onDeleteRequest: () => void;\n onConfirmDelete: () => void;\n onConfirmRename: () => void;\n onClose: () => void;\n}\n\nexport function SessionRowMenu({\n session,\n mode,\n anchor,\n renameDraft,\n setRenameDraft,\n onEdit,\n onDeleteRequest,\n onConfirmDelete,\n onConfirmRename,\n onClose,\n}: SessionRowMenuProps) {\n const ref = useRef<HTMLDivElement | null>(null);\n\n // Position the popover just below the row's right edge.\n const top = Math.round(anchor.rect.bottom + 2);\n const right = Math.max(8, Math.round(window.innerWidth - anchor.rect.right));\n\n // Close on outside click + Esc.\n useEffect(() => {\n const onDown = (e: MouseEvent) => {\n const t = e.target as Node | null;\n if (!ref.current || !t) return;\n if (ref.current.contains(t)) return;\n onClose();\n };\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onClose();\n };\n // Defer attaching the outside-click handler so the click that opened\n // the menu doesn't immediately close it.\n const id = window.setTimeout(() => {\n document.addEventListener('mousedown', onDown);\n document.addEventListener('keydown', onKey);\n }, 0);\n return () => {\n window.clearTimeout(id);\n document.removeEventListener('mousedown', onDown);\n document.removeEventListener('keydown', onKey);\n };\n }, [onClose]);\n\n // Auto-focus the rename input when entering rename mode.\n useEffect(() => {\n if (mode !== 'rename') return;\n const id = window.setTimeout(() => {\n const input = ref.current?.querySelector<HTMLInputElement>('input.session-row-menu-input');\n input?.focus();\n input?.select();\n }, 0);\n return () => window.clearTimeout(id);\n }, [mode]);\n\n const body = (\n <div\n ref={ref}\n className=\"session-row-menu\"\n role=\"menu\"\n aria-label={`Options for ${session.title}`}\n style={{ position: 'fixed', top, right }}\n onClick={(e) => e.stopPropagation()}\n >\n {mode === 'main' && (\n <>\n <button\n type=\"button\"\n className=\"session-row-menu-item\"\n role=\"menuitem\"\n onClick={(e) => {\n e.stopPropagation();\n onEdit();\n }}\n >\n <Edit size={13} aria-hidden />\n <span>Rename</span>\n <kbd>R</kbd>\n </button>\n <button\n type=\"button\"\n className=\"session-row-menu-item session-row-menu-item-danger\"\n role=\"menuitem\"\n onClick={(e) => {\n e.stopPropagation();\n onDeleteRequest();\n }}\n >\n <Trash2 size={13} aria-hidden />\n <span>Delete</span>\n <kbd>⌫</kbd>\n </button>\n </>\n )}\n {mode === 'rename' && (\n <div className=\"session-row-menu-inline\">\n <div className=\"session-row-menu-inline-label chat-mono\">Rename session</div>\n <input\n type=\"text\"\n className=\"session-row-menu-input\"\n value={renameDraft}\n onChange={(e) => setRenameDraft(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n onConfirmRename();\n } else if (e.key === 'Escape') {\n e.preventDefault();\n onClose();\n }\n }}\n onClick={(e) => e.stopPropagation()}\n aria-label=\"New session name\"\n />\n <div className=\"session-row-menu-inline-actions\">\n <button\n type=\"button\"\n className=\"btn btn-ghost\"\n onClick={(e) => {\n e.stopPropagation();\n onClose();\n }}\n >\n Cancel\n </button>\n <button\n type=\"button\"\n className=\"btn btn-primary\"\n onClick={(e) => {\n e.stopPropagation();\n onConfirmRename();\n }}\n >\n Save\n </button>\n </div>\n </div>\n )}\n {mode === 'confirm-delete' && (\n <div className=\"session-row-menu-inline\">\n <div className=\"session-row-menu-inline-label chat-mono\">Delete this session?</div>\n <div className=\"session-row-menu-inline-message\">\n \"{session.title}\" and its sub-agents will be removed.\n </div>\n <div className=\"session-row-menu-inline-actions\">\n <button\n type=\"button\"\n className=\"btn btn-ghost\"\n onClick={(e) => {\n e.stopPropagation();\n onClose();\n }}\n >\n Cancel\n </button>\n <button\n type=\"button\"\n className=\"btn btn-danger\"\n onClick={(e) => {\n e.stopPropagation();\n onConfirmDelete();\n }}\n >\n Delete\n </button>\n </div>\n </div>\n )}\n </div>\n );\n\n return createPortal(body, document.body);\n}","// src/components/chat/AgentNode.tsx — single card in the agent orchestration tree.\n//\n// Two modes:\n// collapsible=true — header is a button with a chevron; toggles its\n// own summary + children visibility.\n// collapsible=false — header is a static div (no chevron / no toggle).\n// Children render if present but cannot be\n// collapsed by the user.\n//\n// FIX #1 (session-collapsed-by-default) is handled at the *parent*\n// (SubAgentList / AgentTree) which decides whether to mount this\n// node's children at all. This component is purely presentational.\n\nimport { useState } from 'react';\n\nexport type AgentStatus = 'idle' | 'streaming' | 'done' | 'blocked' | 'awaiting';\n\nexport interface AgentTreeNode {\n id: string;\n name: string;\n role?: string;\n status: AgentStatus;\n summary?: string;\n children?: AgentTreeNode[];\n}\n\ninterface Props {\n node: AgentTreeNode;\n depth?: number;\n collapsible?: boolean;\n isLast?: boolean;\n /** Controlled open state — used by SubAgentList so the parent rail\n * row's tree-chevron is the single source of truth for collapse. */\n open?: boolean;\n onToggle?: (next: boolean) => void;\n}\n\nexport function AgentNode({\n node,\n depth = 0,\n collapsible = false,\n isLast = true,\n open: controlledOpen,\n onToggle,\n}: Props) {\n const [internalOpen, setInternalOpen] = useState<boolean>(collapsible);\n const isControlled = controlledOpen !== undefined;\n const open = isControlled ? controlledOpen : internalOpen;\n const setOpen = (next: boolean) => {\n if (!isControlled) setInternalOpen(next);\n onToggle?.(next);\n };\n\n const hasChildren = (node.children?.length ?? 0) > 0;\n\n const headContent = (\n <>\n {collapsible && (\n <span\n className={`agent-node-chevron ${open ? 'open' : ''}`}\n aria-hidden\n >\n ›\n </span>\n )}\n <span\n className={`agent-node-dot status-${node.status}`}\n aria-hidden\n />\n <span className=\"agent-node-name\">{node.name}</span>\n {node.role && <span className=\"agent-node-role chat-mono\">{node.role}</span>}\n <span className={`agent-node-pill status-${node.status}`}>{node.status}</span>\n </>\n );\n\n return (\n <div\n className={[\n 'agent-node',\n `depth-${depth}`,\n `status-${node.status}`,\n open ? 'open' : 'closed',\n isLast ? 'last' : '',\n ]\n .filter(Boolean)\n .join(' ')}\n >\n {collapsible ? (\n <button\n type=\"button\"\n className={`agent-node-head status-${node.status} collapsible`}\n onClick={(e) => {\n e.stopPropagation();\n setOpen(!open);\n }}\n aria-expanded={open}\n >\n {headContent}\n </button>\n ) : (\n <div className={`agent-node-head status-${node.status}`}>\n {headContent}\n </div>\n )}\n {open && (\n <>\n {node.summary && (\n <div className=\"agent-node-summary\">{node.summary}</div>\n )}\n {hasChildren && (\n <div className=\"agent-node-children\">\n {node.children!.map((child, i) => (\n <AgentNode\n key={child.id}\n node={child}\n depth={depth + 1}\n collapsible={false}\n isLast={i === node.children!.length - 1}\n />\n ))}\n </div>\n )}\n </>\n )}\n </div>\n );\n}","// src/components/chat/AgentTree.tsx — vertical chain of session cards connected by\n// backbone+L-stub connectors. Two modes:\n//\n// full tree (variant=\"full\") — renders the root card and all its children.\n// Used inside the thread head when the active session has sub-agents.\n//\n// children-only (variant=\"rail\" via SubAgentList) — renders only the children\n// of the root; the rail row above already shows the root card, so\n// re-rendering it would duplicate. Children hang directly off the\n// rail row via standard backbone + L-stub connectors.\n//\n// FIX #1 — the parent (ChatRail) passes `open=false` by default for a\n// freshly-clicked session so the tree is collapsed on first click; the\n// user can open it via the chevron in the row.\n\nimport { Fragment } from 'react';\nimport { AgentNode, type AgentTreeNode } from './AgentNode';\n\ninterface FullTreeProps {\n tree: { root: AgentTreeNode };\n variant?: 'full';\n open?: boolean;\n}\n\ninterface ChildrenOnlyProps {\n children: AgentTreeNode[];\n variant: 'rail' | 'thread';\n open?: boolean;\n}\n\nfunction isFullTree(props: FullTreeProps | ChildrenOnlyProps): props is FullTreeProps {\n return (props as FullTreeProps).tree !== undefined;\n}\n\nexport function AgentTree(props: FullTreeProps | ChildrenOnlyProps) {\n const open = props.open ?? true;\n\n if (isFullTree(props)) {\n return (\n <div className={`agent-tree variant-${props.variant ?? 'full'}`}>\n <AgentNode node={props.tree.root} depth={0} open={open} />\n </div>\n );\n }\n\n // Children-only path (used by SubAgentList hanging off the rail row).\n const list = props.children ?? [];\n return (\n <div className={`agent-tree variant-${props.variant} agent-tree-children-only`}>\n <div className=\"agent-tree-children-body\">\n {list.map((child, i) => (\n <Fragment key={child.id}>\n <AgentNode\n node={child}\n depth={0}\n collapsible={false}\n open={open}\n isLast={i === list.length - 1}\n />\n </Fragment>\n ))}\n </div>\n </div>\n );\n}\n\n/* ── SubAgentList — convenience wrapper used by the ChatRail to render\n the children of a session's tree directly under the active row. ── */\nexport function SubAgentList({\n children,\n variant = 'rail',\n open = true,\n}: {\n children: AgentTreeNode[];\n variant?: 'rail' | 'thread';\n open?: boolean;\n}) {\n if (!open) return null;\n return <AgentTree variant={variant} open={open} children={children} />;\n}","// src/components/chat/ChatRail.tsx — redesigned session rail (v3.22).\n//\n// Replaces the original SessionList. Layout follows the design HTML:\n// - sessions grouped by recency (Today / Yesterday / This week / Earlier)\n// - each row carries: status dot, title (with pin star), time + unread\n// badge, 3-dot menu trigger (hover-visible, top-right), and (when\n// active + has children) a collapse chevron (vertical-center,\n// right: 28px — to the LEFT of the 3-dot trigger so they never\n// overlap — see chat.css for the exact positioning).\n// - per-row 3-dot popover menu with three modes: main (rename/delete),\n// rename (inline input), confirm-delete (inline confirmation).\n// - active row hangs the agent orchestration tree below it (collapsed\n// by default on first click per FIX #1 — the user opens it via the\n// chevron).\n//\n// Props match the original SessionList so it can be swapped into\n// Chat.tsx without any further wiring. The new props are optional and\n// augment the rail with state + tree + menu behavior when supplied.\n\nimport { Fragment, useMemo, useRef, useState } from 'react';\nimport { Plus, ExternalLink } from 'lucide-react';\nimport type { ChatSession } from '../../lib/types';\nimport { EmptyState } from './EmptyState';\nimport { SessionRowMenu, type SessionMenuMode } from './SessionRowMenu';\nimport { SubAgentList } from './AgentTree';\nimport type { AgentTreeNode } from './AgentNode';\n\n/* ------------------------------------------------------------------ *\n * Display-augmented session shape. The data coming from the API is\n * a bare `ChatSession`; the rail overlays optional display fields.\n * ------------------------------------------------------------------ */\nexport type SessionState = 'idle' | 'streaming' | 'awaiting';\n\nexport interface DisplaySession extends ChatSession {\n state?: SessionState;\n unread?: number;\n pinned?: boolean;\n /** HH:MM display string; defaults derived from mtime */\n time?: string;\n /** Agent name shown in the row subtitle / status dot */\n agent?: string;\n /** Sub-agent tree for this session (root may have children). */\n tree?: { root: AgentTreeNode };\n}\n\ninterface Props {\n sessions: DisplaySession[];\n opencodeSessions?: DisplaySession[];\n activeSessionId: string;\n activeOpencodeSessionId: string | null;\n activeProject: { name: string } | null;\n creating: boolean;\n onCreateSession: () => void;\n onSelectSession: (id: string) => void;\n onSelectOpencodeSession: (s: DisplaySession) => void;\n /** Optional: rename / delete handlers. When omitted, those buttons\n * in the menu fall back to no-op + toast hint. */\n onRenameSession?: (id: string, title: string) => void;\n onDeleteSession?: (id: string) => void;\n /** Optional: group predicate. By default groups by day buckets. */\n groupBy?: (sessions: DisplaySession[]) => Record<string, DisplaySession[]>;\n}\n\nconst DEFAULT_GROUPS = ['Today', 'Yesterday', 'This week', 'Earlier'];\n\nfunction isSameDay(a: Date, b: Date) {\n return (\n a.getFullYear() === b.getFullYear() &&\n a.getMonth() === b.getMonth() &&\n a.getDate() === b.getDate()\n );\n}\n\nfunction dayDiff(a: Date, b: Date) {\n const ms = a.getTime() - b.getTime();\n return Math.floor(ms / (1000 * 60 * 60 * 24));\n}\n\nfunction defaultGroupBy(sessions: DisplaySession[]): Record<string, DisplaySession[]> {\n const now = new Date();\n const yesterday = new Date(now);\n yesterday.setDate(yesterday.getDate() - 1);\n const weekAgo = new Date(now);\n weekAgo.setDate(weekAgo.getDate() - 7);\n\n const groups: Record<string, DisplaySession[]> = {\n Today: [],\n Yesterday: [],\n 'This week': [],\n Earlier: [],\n };\n\n for (const s of sessions) {\n const d = new Date(Number(s.mtime) || Date.now());\n if (isSameDay(d, now)) groups.Today.push(s);\n else if (isSameDay(d, yesterday)) groups.Yesterday.push(s);\n else if (dayDiff(now, d) < 7) groups['This week'].push(s);\n else groups.Earlier.push(s);\n }\n return groups;\n}\n\nfunction formatTime(mtime: number): string {\n const d = new Date(Number(mtime) || Date.now());\n return d.toLocaleTimeString(undefined, {\n hour: '2-digit',\n minute: '2-digit',\n hour12: false,\n });\n}\n\nfunction SessionStateIndicator({\n state,\n agent,\n}: {\n state: SessionState;\n agent?: string;\n}) {\n if (state === 'streaming') {\n return (\n <span\n className=\"session-state session-state-streaming\"\n title={`${agent || 'Odin'} is typing…`}\n />\n );\n }\n if (state === 'awaiting') {\n return (\n <span\n className=\"session-state session-state-awaiting\"\n title=\"Awaiting your reply\"\n aria-hidden\n />\n );\n }\n if (state === 'idle') {\n return <span className=\"session-state session-state-idle\" aria-hidden />;\n }\n return null;\n}\n\nexport function ChatRail({\n sessions,\n opencodeSessions = [],\n activeSessionId,\n activeOpencodeSessionId,\n activeProject,\n creating,\n onCreateSession,\n onSelectSession,\n onSelectOpencodeSession,\n onRenameSession,\n onDeleteSession,\n groupBy,\n}: Props) {\n const allSessions = useMemo<DisplaySession[]>(\n () => [...sessions, ...opencodeSessions],\n [sessions, opencodeSessions],\n );\n const sorted = useMemo(\n () => [...allSessions].sort((a, b) => Number(b.mtime ?? 0) - Number(a.mtime ?? 0)),\n [allSessions],\n );\n\n const grouped = useMemo(\n () => (groupBy ? groupBy(sorted) : defaultGroupBy(sorted)),\n [groupBy, sorted],\n );\n\n // FIX #1 — collapse-by-default for the active session's sub-agent\n // tree. State is per-session-id so toggling one session doesn't\n // reset the others.\n const [openTree, setOpenTree] = useState<Record<string, boolean>>({});\n const isTreeOpen = (id: string) => openTree[id] === true;\n\n // Per-row menu state (which session's menu is open + which mode).\n const [openMenuId, setOpenMenuId] = useState<string | null>(null);\n const [menuMode, setMenuMode] = useState<SessionMenuMode>('main');\n const [renameDraft, setRenameDraft] = useState('');\n const [menuAnchor, setMenuAnchor] = useState<{ id: string; rect: DOMRect } | null>(null);\n const rowRefs = useRef<Record<string, HTMLDivElement | null>>({});\n\n const openMenuFor = (id: string, mode: SessionMenuMode = 'main') => {\n const row = rowRefs.current[id];\n if (!row) return;\n const target =\n mode === 'main'\n ? row\n : row.querySelector<HTMLElement>('.chat-rail-item-menu-trigger') ?? row;\n setMenuAnchor({ id, rect: target.getBoundingClientRect() });\n setOpenMenuId(id);\n setMenuMode(mode);\n if (mode === 'rename') {\n const s = [...sessions, ...opencodeSessions].find((x) => x.id === id);\n setRenameDraft(s?.title ?? s?.id ?? '');\n }\n };\n const closeMenu = () => {\n setOpenMenuId(null);\n setMenuMode('main');\n setRenameDraft('');\n setMenuAnchor(null);\n };\n\n const handleSelect = (s: DisplaySession) => {\n if (s.source === 'opencode') {\n onSelectOpencodeSession(s);\n return;\n }\n onSelectSession(s.id);\n };\n\n const handleConfirmRename = () => {\n if (!menuAnchor) return;\n const sid = menuAnchor.id;\n const next = renameDraft.trim();\n if (!next) {\n closeMenu();\n return;\n }\n onRenameSession?.(sid, next);\n closeMenu();\n };\n\n const handleConfirmDelete = () => {\n if (!menuAnchor) return;\n onDeleteSession?.(menuAnchor.id);\n closeMenu();\n };\n\n const orderedGroups: Array<[string, DisplaySession[]]> = groupBy\n ? Object.entries(grouped)\n : DEFAULT_GROUPS.filter((g) => grouped[g]?.length).map(\n (g) => [g, grouped[g]] as [string, DisplaySession[]],\n );\n\n return (\n <aside className=\"chat-rail\">\n <div className=\"chat-rail-head\">\n <button\n type=\"button\"\n className=\"chat-new-btn\"\n onClick={onCreateSession}\n disabled={creating || !activeProject}\n title={activeProject ? 'Create new session' : 'Pick a project first'}\n aria-label=\"Create new session\"\n >\n <Plus size={14} aria-hidden />\n <span>{creating ? 'Creating…' : 'New session'}</span>\n </button>\n </div>\n\n {sorted.length === 0 ? (\n <div className=\"chat-sessions-empty\">\n <EmptyState\n icon={<Plus size={20} aria-hidden />}\n title={activeProject ? 'No sessions yet' : 'No project'}\n message={\n activeProject\n ? 'Create your first session to start chatting.'\n : 'Pick a project in Overview to scope chat sessions.'\n }\n />\n </div>\n ) : (\n <div className=\"chat-rail-list\">\n {orderedGroups.map(([group, items]) => (\n <div key={group} className=\"chat-rail-group\">\n <div className=\"chat-rail-group-label\">{group}</div>\n {items.map((s) => {\n const isOpencode = s.source === 'opencode';\n const isActive = isOpencode\n ? activeOpencodeSessionId === s.id\n : activeSessionId === s.id;\n const tree = s.tree;\n const hasChildren = !!(tree?.root?.children && tree.root.children.length > 0);\n const treeOpen = isTreeOpen(s.id);\n return (\n <Fragment key={isOpencode ? `oc-${s.id}` : s.id}>\n <div\n ref={(el) => {\n rowRefs.current[s.id] = el;\n }}\n role=\"button\"\n tabIndex={0}\n className={`chat-rail-item state-${s.state ?? 'idle'}${isActive ? ' active' : ''}`}\n onClick={() => handleSelect(s)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleSelect(s);\n }\n }}\n aria-current={isActive ? 'true' : undefined}\n >\n <SessionStateIndicator state={s.state ?? 'idle'} agent={s.agent} />\n <div className=\"chat-rail-item-title\">\n {s.pinned && (\n <span className=\"chat-rail-pin\" aria-hidden>\n ★\n </span>\n )}\n {isOpencode && (\n <ExternalLink\n size={11}\n style={{ color: 'var(--text-muted)', flexShrink: 0 }}\n aria-hidden\n />\n )}\n <span className=\"chat-ellipsis\">{s.title || s.id}</span>\n </div>\n <div className=\"chat-rail-item-meta\">\n <span className=\"chat-rail-item-meta-time\">\n {s.time ?? formatTime(s.mtime)}\n </span>\n {(s.unread ?? 0) > 0 && (\n <span className=\"chat-rail-badge\">{s.unread}</span>\n )}\n </div>\n <button\n type=\"button\"\n className={`chat-rail-item-menu-trigger${openMenuId === s.id ? ' open' : ''}`}\n aria-label={`Session options for ${s.title || s.id}`}\n aria-haspopup=\"menu\"\n aria-expanded={openMenuId === s.id}\n onClick={(e) => {\n e.stopPropagation();\n if (openMenuId === s.id) closeMenu();\n else openMenuFor(s.id, 'main');\n }}\n >\n <svg viewBox=\"0 0 14 14\" aria-hidden>\n <circle cx=\"3\" cy=\"7\" r=\"1.2\" fill=\"currentColor\" />\n <circle cx=\"7\" cy=\"7\" r=\"1.2\" fill=\"currentColor\" />\n <circle cx=\"11\" cy=\"7\" r=\"1.2\" fill=\"currentColor\" />\n </svg>\n </button>\n {isActive && hasChildren && (\n <button\n type=\"button\"\n className={`chat-rail-tree-chevron${treeOpen ? ' open' : ''}`}\n aria-label={treeOpen ? 'Collapse sub-agents' : 'Expand sub-agents'}\n aria-expanded={treeOpen}\n onClick={(e) => {\n e.stopPropagation();\n setOpenTree((cur) => ({ ...cur, [s.id]: !cur[s.id] }));\n }}\n >\n <svg viewBox=\"0 0 10 10\" aria-hidden>\n <polyline points=\"3,1.5 7,5 3,8.5\" />\n </svg>\n </button>\n )}\n </div>\n {isActive && hasChildren && treeOpen && tree?.root?.children && (\n <SubAgentList children={tree.root.children} variant=\"rail\" open />\n )}\n </Fragment>\n );\n })}\n </div>\n ))}\n </div>\n )}\n\n {openMenuId && menuAnchor && (\n <SessionRowMenu\n session={{\n id: menuAnchor.id,\n title:\n [...sessions, ...opencodeSessions].find((x) => x.id === menuAnchor.id)\n ?.title ?? menuAnchor.id,\n }}\n mode={menuMode}\n anchor={menuAnchor}\n renameDraft={renameDraft}\n setRenameDraft={setRenameDraft}\n onEdit={() => openMenuFor(openMenuId, 'rename')}\n onDeleteRequest={() => openMenuFor(openMenuId, 'confirm-delete')}\n onConfirmDelete={handleConfirmDelete}\n onConfirmRename={handleConfirmRename}\n onClose={closeMenu}\n />\n )}\n </aside>\n );\n}","// src/components/chat/ChatComposer.tsx — bottom composer pill (v3.22 design).\n//\n// Replaces FloatingComposer. Visual layout follows the design HTML:\n//\n// [agent chip] [model badge] [──── textarea ────] [📎] [✨] [➤]\n//\n// All wrapped in a single pill (chat-composer-pill) with rounded ends\n// and a focus-within accent border. The legacy Composer component\n// already provides the textarea, agent chip menu, attachment tags,\n// and slash-command suggestion dropdown — the redesign simply nests\n// the Composer inside the new pill chrome and adds the hint row\n// (⏎ / ⇧⏎ / /) underneath.\n//\n// Props match the original FloatingComposer EXACTLY (so Chat.tsx +\n// MobileChat.tsx don't need any changes).\n\nimport { useState } from 'react';\nimport { Composer } from './Composer';\n\ninterface Props {\n agent: string;\n setAgent: (a: string) => void;\n model: string;\n setModel: (m: string) => void;\n text: string;\n setText: (t: string) => void;\n sending: boolean;\n onSend: () => void;\n attachments: string[];\n setAttachments: (a: string[] | ((prev: string[]) => string[])) => void;\n suggestions: Array<{ cmd: string; desc: string }>;\n onPickSuggestion: (cmd: string) => void;\n agents: Array<{ name: string }>;\n onAttach: () => void;\n /** Backward-compat — used to be page-level panel toggles. Ignored in\n * the redesign (rail + info are always visible). */\n sessionsOpen?: boolean;\n /** Backward-compat — see sessionsOpen. */\n infoOpen?: boolean;\n}\n\nexport function ChatComposer(props: Props) {\n const { text, sending, onSend } = props;\n const [takingOff, setTakingOff] = useState(false);\n\n // Wrap onSend with a brief takeoff animation — a small CSS hook on\n // the wrapper pill. We don't animate a specific element here; the\n // pill itself gets the brief `takeoff` class so the send button\n // (the last child of Composer) gets the animation if the design\n // wants it.\n const handleSend = () => {\n if (!text.trim()) return;\n setTakingOff(true);\n onSend();\n window.setTimeout(() => setTakingOff(false), 320);\n };\n\n return (\n <div className=\"chat-composer-wrap\">\n <div className={`chat-composer-pill${takingOff ? ' takeoff' : ''}`}>\n <Composer {...props} onSend={handleSend} />\n </div>\n <div className=\"chat-composer-hint chat-muted\">\n <span>\n <kbd>⏎</kbd> send\n </span>\n <span>\n <kbd>⇧⏎</kbd> newline\n </span>\n <span>\n <kbd>/</kbd> commands\n </span>\n </div>\n </div>\n );\n}","// src/components/chat/ChatInfoPanel.tsx — right info panel (v3.22 design).\n//\n// Replaces InfoPanel. Layout follows the design HTML's sectioned\n// info panel: Session / Project / Model / Tokens / Cost / Attached\n// agents / Linked.\n//\n// Props match the original InfoPanel EXACTLY (so Chat.tsx doesn't need\n// any changes).\n\nimport { MessageSquare, Bot, Server, Terminal } from 'lucide-react';\n\ninterface Props {\n sessionId: string;\n messages: Array<unknown>;\n pinned: Set<number>;\n agent: string;\n model: string;\n agents: Array<{ name: string; model?: string; mode?: string }>;\n mcps: Array<{ id: string; command?: string; enabled?: boolean }>;\n allCommands: Array<{ cmd: string; desc: string; mod?: string }>;\n}\n\nfunction formatNumber(n: number): string {\n return n.toLocaleString();\n}\n\nexport function ChatInfoPanel({\n sessionId,\n messages,\n pinned,\n agent,\n model,\n agents,\n mcps,\n allCommands,\n}: Props) {\n // Tokens + cost are stubbed — the dashboard doesn't currently\n // surface these from the chat backend. Show the count of messages\n // + pinned as a sensible default and leave token/cost placeholders\n // clearly marked so it's obvious they're not yet wired.\n const msgCount = messages?.length ?? 0;\n const pinnedCount = pinned?.size ?? 0;\n const tokensUsed = 0;\n const tokensTotal = 128_000;\n const costUsd = 0;\n\n return (\n <aside className=\"chat-info\">\n <div className=\"chat-info-section\">\n <h4>Session</h4>\n <div>{sessionId || 'Live'}</div>\n <div className=\"chat-info-mono\">\n {formatNumber(msgCount)} message{msgCount === 1 ? '' : 's'}\n {pinnedCount > 0 && ` · ${pinnedCount} pinned`}\n </div>\n </div>\n\n <div className=\"chat-info-section\">\n <h4>Agent</h4>\n <div>{agent || '—'}</div>\n </div>\n\n <div className=\"chat-info-section\">\n <h4>Model</h4>\n <div className=\"chat-mono chat-ellipsis\" title={model}>\n {model || '—'}\n </div>\n </div>\n\n <div className=\"chat-info-section\">\n <h4>Tokens</h4>\n <div className=\"chat-mono\">\n {formatNumber(tokensUsed)} / {formatNumber(tokensTotal)}\n </div>\n <div className=\"chat-info-bar\" aria-hidden>\n <div\n className=\"chat-info-bar-fill\"\n style={{ width: `${Math.min(100, (tokensUsed / Math.max(1, tokensTotal)) * 100)}%` }}\n />\n </div>\n </div>\n\n <div className=\"chat-info-section\">\n <h4>Cost</h4>\n <div className=\"chat-mono\">${costUsd.toFixed(4)}</div>\n </div>\n\n <div className=\"chat-info-section\">\n <h4>\n <Bot size={11} style={{ marginRight: 4, verticalAlign: -1 }} aria-hidden /> Attached\n agents\n </h4>\n {agents?.length ? (\n <div className=\"chat-info-agents\">\n {agents.map((a) => (\n <span key={a.name} className=\"chat-info-agent\">\n {a.name}\n </span>\n ))}\n </div>\n ) : (\n <div className=\"chat-info-mono\">None attached</div>\n )}\n </div>\n\n <div className=\"chat-info-section\">\n <h4>\n <Server size={11} style={{ marginRight: 4, verticalAlign: -1 }} aria-hidden /> MCPs\n </h4>\n {mcps?.length ? (\n <div className=\"chat-info-agents\">\n {mcps.map((m) => (\n <span key={m.id} className=\"chat-info-agent\">\n {m.id}\n </span>\n ))}\n </div>\n ) : (\n <div className=\"chat-info-mono\">No MCPs configured</div>\n )}\n </div>\n\n <div className=\"chat-info-section\">\n <h4>\n <Terminal size={11} style={{ marginRight: 4, verticalAlign: -1 }} aria-hidden /> Slash\n commands\n </h4>\n <div className=\"chat-info-mono\">{allCommands?.length ?? 0} available</div>\n </div>\n\n <div className=\"chat-info-section\">\n <h4>\n <MessageSquare\n size={11}\n style={{ marginRight: 4, verticalAlign: -1 }}\n aria-hidden\n />{' '}\n Linked\n </h4>\n <div className=\"chat-info-mono\">No links yet</div>\n </div>\n </aside>\n );\n}","// src/components/chat/JumpToLatest.tsx — floating pill above the composer.\n//\n// Two visual variants:\n// - streaming (current session is being replied to): pulsing indigo\n// border + 3-dot bounce + green \"live\" badge\n// - idle: neutral pill + down-arrow icon + \"N new\" badge\n//\n// Hidden entirely when the user is already at the bottom of the thread\n// (controlled by the parent's `stickToBottom` flag).\n\nimport { ArrowDown } from 'lucide-react';\n\ninterface Props {\n streaming: boolean;\n newMessageCount: number;\n onClick: () => void;\n /** Optional label override (e.g. \"Odin is replying\"). */\n streamingLabel?: string;\n}\n\nexport function JumpToLatest({\n streaming,\n newMessageCount,\n onClick,\n streamingLabel = 'Odin is replying',\n}: Props) {\n return (\n <button\n type=\"button\"\n className={`jump-to-latest${streaming ? ' is-streaming' : ''}`}\n onClick={onClick}\n aria-label=\"Jump to latest message\"\n title=\"Jump to latest (⌘/Ctrl+End)\"\n >\n {streaming ? (\n <>\n <span className=\"jump-dots\" aria-hidden>\n <span />\n <span />\n <span />\n </span>\n <span>{streamingLabel}</span>\n {newMessageCount > 0 && (\n <span className=\"jump-badge jump-badge-live\">live</span>\n )}\n </>\n ) : (\n <>\n <ArrowDown size={14} aria-hidden />\n <span>Jump to latest</span>\n {newMessageCount > 0 && (\n <span className=\"jump-badge\">{newMessageCount} new</span>\n )}\n </>\n )}\n </button>\n );\n}","// src/views/Chat.tsx — Gemini-inspired dark chat orchestrator (v3.22).\n//\n// v3.22 — redesigned layout: 3-column grid (rail / thread / info).\n// The legacy `.chat-shell / .chat-body / .chat-sessions / .chat-main /\n// .chat-info` wrapper classes are still available for MobileChat (which\n// uses its own view); this file uses the new `.chat-page` grid.\n//\n// The `chat-thread` section is a vertical grid (head / scroll / composer).\n// The scrollable message list lives inside the legacy `ChatThread`\n// component (still wrapped in its own `.chat-thread` div with className\n// `legacy` to opt into the original styles — see chat.css).\n\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport { ChatTopBar } from '../components/chat/ChatTopBar';\nimport { ChatRail } from '../components/chat/ChatRail';\nimport { ChatThread } from '../components/chat/ChatThread';\nimport { ChatComposer } from '../components/chat/ChatComposer';\nimport { ChatInfoPanel } from '../components/chat/ChatInfoPanel';\nimport { JumpToLatest } from '../components/chat/JumpToLatest';\nimport { useChat } from '../components/chat/useChat';\nimport { useSlashCommands } from '../components/chat/useSlashCommands';\nimport { useToast } from '../components/Toast';\nimport { useModal } from '../components/Modal';\nimport { Button } from '../components/Button';\nimport type { Snapshot, Settings } from '../lib/types';\n\ninterface Props {\n snapshot: Snapshot;\n settings: Settings;\n setActiveTab?: (id: string) => void;\n refreshSnapshot?: () => Promise<void>;\n initialTaskId?: string | null;\n onClearTaskId?: () => void;\n}\n\nexport function Chat({ snapshot, settings, setActiveTab, initialTaskId, onClearTaskId }: Props) {\n const toast = useToast();\n const modal = useModal();\n\n const chat = useChat(snapshot, settings, initialTaskId ?? '');\n\n // ── Composer state (local) ───────────────────────────────────────────────\n const [text, setText] = useState('');\n const [agent, setAgent] = useState(settings.defaultAgent || 'odin');\n const [model, setModel] = useState(settings.defaultModel || '');\n const [attachments, setAttachments] = useState<string[]>([]);\n const [creating, setCreating] = useState(false);\n\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n // ── Slash commands ───────────────────────────────────────────────────────\n const { allCommands, suggestions, setQuery } = useSlashCommands(snapshot);\n\n useEffect(() => {\n setQuery(text);\n }, [text, setQuery]);\n\n // ── File attach ──────────────────────────────────────────────────────────\n const onAttach = () => fileInputRef.current?.click();\n\n const onFiles = (e: React.ChangeEvent<HTMLInputElement>) => {\n const files = e.target.files;\n if (!files) return;\n const next: string[] = [];\n for (let i = 0; i < files.length; i++) next.push(files[i].name);\n setAttachments((cur) => {\n const newNames = next.filter((n) => !cur.includes(n));\n return [...cur, ...newNames];\n });\n if (fileInputRef.current) fileInputRef.current.value = '';\n };\n\n // ── Send ─────────────────────────────────────────────────────────────────\n const handleSend = () => {\n const msg = text.trim();\n if (!msg) return;\n setText('');\n setQuery('');\n chat.onSend(msg, agent, model, attachments);\n chat.jumpToLatest();\n };\n\n // ── Create session ───────────────────────────────────────────────────────\n const handleCreateSession = async () => {\n if (creating) return;\n if (!snapshot.activeProject) {\n toast.warning('Pick a project in Overview to scope chat sessions.', 4000);\n return;\n }\n setCreating(true);\n try {\n const created = await fetch('/chat/sessions', { method: 'POST' }).then((r) => r.json());\n chat.loadChat(created.id);\n toast.success(`Session ${created.id} created.`);\n } catch (err) {\n toast.error(`Create failed: ${(err as Error).message}`);\n } finally {\n setCreating(false);\n }\n };\n\n // ── Delete message (via modal) ───────────────────────────────────────────\n const handleDelete = (idx: number) => {\n modal.open({\n title: 'Delete message?',\n children: <p style={{ margin: 0 }}>This action cannot be undone.</p>,\n footer: (\n <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>\n <Button variant=\"secondary\" size=\"sm\" onClick={() => modal.close()}>\n Cancel\n </Button>\n <Button\n variant=\"danger\"\n size=\"sm\"\n onClick={() => {\n modal.close();\n chat.deleteMessage(idx);\n }}\n >\n Delete\n </Button>\n </div>\n ),\n });\n };\n\n // ── Derived: sessions with display state overlaid ────────────────────────\n const displaySessions = useMemo(\n () => chat.sessions.map((s) => chat.getSessionDisplay(s)),\n [chat.sessions, chat.getSessionDisplay],\n );\n const displayOpencodeSessions = useMemo(\n () => chat.opencodeSessions.map((s) => chat.getSessionDisplay(s)),\n [chat.opencodeSessions, chat.getSessionDisplay],\n );\n\n // ── Current session for the thread head subtitle ────────────────────────\n const activeSessionDisplay = useMemo(() => {\n const id = chat.activeSource === 'opencode'\n ? chat.activeOpencodeSessionId ?? ''\n : chat.sessionId;\n if (!id) return null;\n return (\n displaySessions.find((s) => s.id === id) ??\n displayOpencodeSessions.find((s) => s.id === id) ??\n null\n );\n }, [\n chat.activeSource,\n chat.activeOpencodeSessionId,\n chat.sessionId,\n displaySessions,\n displayOpencodeSessions,\n ]);\n\n const threadSubtitle = (() => {\n const base = `${agent || 'Odin'} · ${snapshot.activeProject?.name ?? 'no project'}`;\n const state = activeSessionDisplay?.state ?? 'idle';\n if (state === 'streaming') return `Replying · ${base}`;\n if (state === 'awaiting') return `Your turn · ${base}`;\n return `${base} · idle`;\n })();\n\n return (\n <div className=\"chat-shell\">\n <ChatTopBar\n activeProject={snapshot.activeProject}\n sessionCount={chat.sessions.length}\n sessionsOpen={true}\n infoOpen={true}\n onToggleSessions={() => {}}\n onToggleInfo={() => {}}\n onOpenOverview={() => setActiveTab?.('overview')}\n />\n <div className=\"chat-page\">\n {/* ── rail ──────────────────────────────────────────────────────── */}\n <ChatRail\n sessions={displaySessions}\n opencodeSessions={displayOpencodeSessions}\n activeSessionId={chat.sessionId}\n activeOpencodeSessionId={chat.activeOpencodeSessionId}\n activeProject={snapshot.activeProject}\n creating={creating}\n onCreateSession={handleCreateSession}\n onSelectSession={chat.selectBizarSession}\n onSelectOpencodeSession={(s) => chat.loadOpencodeSession(s.id)}\n onRenameSession={(id, title) => chat.renameSession(id, title)}\n onDeleteSession={(id) => chat.deleteSession(id)}\n />\n\n {/* ── thread ───────────────────────────────────────────────────── */}\n <section className=\"chat-thread-section\">\n <div className=\"chat-thread-head\">\n <div>\n <div className=\"chat-thread-title\">\n {activeSessionDisplay?.title ?? chat.sessionId ?? 'New chat'}\n </div>\n <div\n className={`chat-thread-sub chat-muted state-${activeSessionDisplay?.state ?? 'idle'}`}\n >\n <span className=\"chat-thread-dot\" />\n {threadSubtitle}\n </div>\n </div>\n <div className=\"chat-thread-actions\">\n <button className=\"btn btn-ghost\" title=\"Rename\" type=\"button\">\n <span className=\"mono\">rename</span>\n </button>\n </div>\n </div>\n\n <div className=\"chat-thread-scroll\" ref={chat.listRef} onScroll={chat.handleScroll}>\n <ChatThread\n messages={chat.activeSource === 'opencode' ? chat.opencodeMessages : chat.bizarMessages}\n loading={chat.loading}\n activeProject={snapshot.activeProject}\n sessionId={\n chat.activeSource === 'opencode'\n ? (chat.activeOpencodeSessionId ?? chat.sessionId)\n : chat.sessionId\n }\n pinned={chat.pinned}\n onPickSuggestion={(t) => setText(t)}\n onCopy={(m) => chat.copyMessage(m as Parameters<typeof chat.copyMessage>[0])}\n onDelete={handleDelete}\n onTogglePin={chat.togglePin}\n onRegenerate={chat.onRegenerate}\n />\n </div>\n\n {!chat.stickToBottom && (\n <JumpToLatest\n streaming={activeSessionDisplay?.state === 'streaming'}\n newMessageCount={chat.newMessageCount}\n onClick={chat.jumpToLatest}\n />\n )}\n\n <ChatComposer\n agent={agent}\n setAgent={setAgent}\n model={model}\n setModel={setModel}\n text={text}\n setText={setText}\n sending={chat.sending}\n onSend={handleSend}\n attachments={attachments}\n setAttachments={setAttachments}\n suggestions={suggestions}\n onPickSuggestion={(cmd) => setText(`${cmd.split(' ')[0]} `)}\n agents={snapshot.agents || []}\n onAttach={onAttach}\n />\n <input\n ref={fileInputRef}\n type=\"file\"\n multiple\n style={{ display: 'none' }}\n onChange={onFiles}\n />\n </section>\n\n {/* ── info panel ──────────────────────────────────────────────── */}\n <ChatInfoPanel\n sessionId={\n chat.activeSource === 'opencode'\n ? (chat.activeOpencodeSessionId ?? chat.sessionId)\n : chat.sessionId\n }\n messages={chat.activeSource === 'opencode' ? chat.opencodeMessages : chat.bizarMessages}\n pinned={chat.pinned}\n agent={agent}\n model={model}\n agents={snapshot.agents || []}\n mcps={snapshot.mcps || []}\n allCommands={allCommands}\n />\n </div>\n </div>\n );\n}","// src/components/StatusBadge.tsx — small colored pill.\n\nimport type { ReactNode } from 'react';\nimport { cn } from '../lib/utils';\n\nexport type StatusBadgeProps = {\n kind?: 'success' | 'warning' | 'error' | 'info' | 'accent' | 'neutral';\n children: ReactNode;\n className?: string;\n dot?: boolean;\n};\n\nexport function StatusBadge({\n kind = 'neutral',\n children,\n className,\n dot = false,\n}: StatusBadgeProps) {\n return (\n <span className={cn('badge', `badge-${kind}`, className)}>\n {dot && <span className=\"badge-dot\" />}\n {children}\n </span>\n );\n}\n","// src/views/Agents.tsx — v3.1.0 agents with tags, categories, real-time status.\nimport { useEffect, useMemo, useState } from 'react';\nimport {\n Bot,\n Plus,\n RefreshCw,\n Pencil,\n Trash2,\n Play,\n Save,\n X,\n RotateCw,\n Activity,\n Tag as TagIcon,\n Folder,\n CheckCircle2,\n Clock,\n AlertTriangle,\n Circle,\n ChevronDown,\n ChevronRight,\n} from 'lucide-react';\nimport { Button } from '../components/Button';\nimport { Card, CardTitle } from '../components/Card';\nimport { EmptyState } from '../components/EmptyState';\nimport { Spinner } from '../components/Spinner';\nimport { StatusBadge } from '../components/StatusBadge';\nimport { useModal } from '../components/Modal';\nimport { useToast } from '../components/Toast';\nimport { api } from '../lib/api';\nimport { cn, formatRelative, truncate } from '../lib/utils';\nimport type { Agent, Settings, Snapshot } from '../lib/types';\n\ntype Props = {\n snapshot: Snapshot;\n settings: Settings;\n activeTab: string;\n setActiveTab: (id: string) => void;\n refreshSnapshot: () => Promise<void>;\n};\n\nconst TOOL_OPTIONS = ['bash', 'read', 'edit', 'write', 'webfetch', 'websearch', 'task', 'glob', 'grep'];\nconst MODELS = [\n 'anthropic/claude-3-5-sonnet',\n 'anthropic/claude-3-5-haiku',\n 'openai/gpt-4o',\n 'openai/gpt-4o-mini',\n 'openrouter/minimax/minimax-m3',\n 'openrouter/minimax/minimax-m2.7',\n];\n\nconst CATEGORIES = [\n { id: 'reasoning', label: 'Reasoning', color: 'var(--accent)' },\n { id: 'code', label: 'Code', color: 'var(--info)' },\n { id: 'design', label: 'Design', color: 'var(--success)' },\n { id: 'planning', label: 'Planning', color: 'var(--warning)' },\n { id: 'gitops', label: 'GitOps', color: 'var(--error)' },\n { id: 'analysis', label: 'Analysis', color: 'var(--text-dim)' },\n];\n\nfunction categoryColor(cat: string | undefined): string {\n return CATEGORIES.find((c) => c.id === cat)?.color || 'var(--text-dim)';\n}\n\nfunction StatusDot({ status, isStuck }: { status?: string; isStuck?: boolean }) {\n const color =\n isStuck ? 'var(--error)'\n : status === 'working' ? 'var(--info)'\n : status === 'error' ? 'var(--error)'\n : 'var(--text-dim)';\n return <span className=\"agent-status-dot\" style={{ background: color }} />;\n}\n\nfunction StatusPill({ agent }: { agent: Agent }) {\n if (agent.isStuck) {\n return <StatusBadge kind=\"error\" dot>stuck</StatusBadge>;\n }\n const status = agent.status || 'idle';\n if (status === 'working') return <StatusBadge kind=\"info\" dot>working</StatusBadge>;\n if (status === 'error') return <StatusBadge kind=\"error\" dot>error</StatusBadge>;\n return <StatusBadge kind=\"neutral\" dot>idle</StatusBadge>;\n}\n\nexport function Agents({ snapshot, refreshSnapshot }: Props) {\n const toast = useToast();\n const modal = useModal();\n const [agents, setAgents] = useState<Agent[]>(snapshot.agents || []);\n const [loading, setLoading] = useState(!snapshot.agents);\n const [categoryFilter, setCategoryFilter] = useState<string>('');\n const [search, setSearch] = useState('');\n\n useEffect(() => {\n setAgents(snapshot.agents || []);\n setLoading(!snapshot.agents);\n }, [snapshot.agents]);\n\n const reload = async () => {\n try {\n const d = await api.get<{ agents: Agent[] }>('/agents');\n setAgents(d.agents || []);\n } catch (err) {\n toast.error(`Agents load failed: ${(err as Error).message}`);\n } finally {\n setLoading(false);\n }\n };\n\n const sorted = useMemo(() => {\n let out = [...agents];\n if (categoryFilter) {\n out = out.filter((a) => categoryFilter === '__none__' ? !(a.category || '') : (a.category || '') === categoryFilter);\n }\n if (search) {\n const q = search.toLowerCase();\n out = out.filter(\n (a) =>\n a.name.toLowerCase().includes(q) ||\n (a.description || '').toLowerCase().includes(q) ||\n (a.tags || []).some((t) => t.toLowerCase().includes(q)),\n );\n }\n return out.sort((a, b) => a.name.localeCompare(b.name));\n }, [agents, categoryFilter, search]);\n\n const allTags = useMemo(() => {\n const set = new Set<string>();\n for (const a of agents) for (const t of a.tags || []) set.add(t);\n return Array.from(set).sort();\n }, [agents]);\n\n const onCreate = () => {\n let nameEl: HTMLInputElement | null = null;\n let descEl: HTMLInputElement | null = null;\n let modelEl: HTMLSelectElement | null = null;\n let modeEl: HTMLSelectElement | null = null;\n let colorEl: HTMLInputElement | null = null;\n let promptEl: HTMLTextAreaElement | null = null;\n let toolsContainer: HTMLDivElement | null = null;\n let tagsEl: HTMLInputElement | null = null;\n let categoryEl: HTMLSelectElement | null = null;\n\n modal.open({\n title: 'New agent',\n width: 640,\n children: (\n <div className=\"agent-form\">\n <label className=\"field-label\">Name (a-z, 0-9, dashes)</label>\n <input\n ref={(el) => (nameEl = el)}\n className=\"input\"\n type=\"text\"\n placeholder=\"my-agent\"\n autoFocus\n />\n <label className=\"field-label\">Description</label>\n <input\n ref={(el) => { descEl = el; }}\n className=\"input\"\n type=\"text\"\n placeholder=\"What does this agent do?\"\n />\n <div className=\"task-form-row\">\n <div className=\"task-form-field\">\n <label className=\"field-label\">Model</label>\n <select ref={(el) => (modelEl = el)} className=\"select\" defaultValue=\"\">\n <option value=\"\">(provider default)</option>\n {MODELS.map((m) => (\n <option key={m} value={m}>{m}</option>\n ))}\n </select>\n </div>\n <div className=\"task-form-field\">\n <label className=\"field-label\">Mode</label>\n <select ref={(el) => (modeEl = el)} className=\"select\" defaultValue=\"subagent\">\n <option value=\"primary\">primary</option>\n <option value=\"subagent\">subagent</option>\n <option value=\"all\">all</option>\n </select>\n </div>\n <div className=\"task-form-field\" style={{ flex: '0 0 80px' }}>\n <label className=\"field-label\">Color</label>\n <input ref={(el) => (colorEl = el)} className=\"input\" type=\"color\" defaultValue=\"#8b5cf6\" />\n </div>\n </div>\n <div className=\"task-form-row\">\n <div className=\"task-form-field\" style={{ flex: 1 }}>\n <label className=\"field-label\">Category</label>\n <select ref={(el) => (categoryEl = el)} className=\"select\" defaultValue=\"\">\n <option value=\"\">(none)</option>\n {CATEGORIES.map((c) => (\n <option key={c.id} value={c.id}>{c.label}</option>\n ))}\n </select>\n </div>\n <div className=\"task-form-field\" style={{ flex: 2 }}>\n <label className=\"field-label\">Tags (comma-separated)</label>\n <input ref={(el) => (tagsEl = el)} className=\"input\" type=\"text\" placeholder=\"reasoning, code, planning\" />\n </div>\n </div>\n <label className=\"field-label\">Tools</label>\n <div ref={(el) => (toolsContainer = el)} className=\"agent-tools\">\n {TOOL_OPTIONS.map((t) => (\n <label key={t} className=\"checkbox-row\">\n <input type=\"checkbox\" value={t} />\n <span>{t}</span>\n </label>\n ))}\n </div>\n <label className=\"field-label\">System prompt</label>\n <textarea\n ref={(el) => (promptEl = el)}\n className=\"textarea\"\n rows={6}\n placeholder=\"You are a...\"\n />\n </div>\n ),\n footer: (\n <div className=\"modal-footer-actions\">\n <Button variant=\"ghost\" onClick={() => modal.close()}>Cancel</Button>\n <Button\n variant=\"primary\"\n onClick={async () => {\n const name = (nameEl?.value || '').trim();\n if (!/^[a-z0-9][a-z0-9-]{0,63}$/i.test(name)) {\n toast.warning('Invalid name (a-z, 0-9, dashes).');\n return;\n }\n const tools: string[] = [];\n if (toolsContainer) {\n toolsContainer.querySelectorAll<HTMLInputElement>('input[type=\"checkbox\"]:checked').forEach((cb) => {\n tools.push(cb.value);\n });\n }\n const tags = (tagsEl?.value || '').split(',').map((t) => t.trim()).filter(Boolean);\n try {\n const created = await api.post<Agent>('/agents', {\n name,\n description: (descEl?.value || '').trim(),\n model: modelEl?.value || '',\n mode: modeEl?.value || 'subagent',\n color: colorEl?.value || '',\n tools,\n tags,\n category: categoryEl?.value || '',\n prompt: promptEl?.value || '',\n });\n setAgents((cur) => [...cur, created]);\n toast.success('Agent created.');\n modal.close();\n await refreshSnapshot();\n } catch (err) {\n toast.error(`Create failed: ${(err as Error).message}`);\n }\n }}\n >\n <Save size={12} /> Create\n </Button>\n </div>\n ),\n });\n };\n\n const onEdit = async (a: Agent) => {\n let descEl: HTMLInputElement | null = null;\n let modelEl: HTMLSelectElement | null = null;\n let modeEl: HTMLSelectElement | null = null;\n let colorEl: HTMLInputElement | null = null;\n let promptEl: HTMLTextAreaElement | null = null;\n let toolsContainer: HTMLDivElement | null = null;\n let tagsEl: HTMLInputElement | null = null;\n let categoryEl: HTMLSelectElement | null = null;\n try {\n const full = await api.get<Agent>(`/agents/${encodeURIComponent(a.name)}`);\n modal.open({\n title: `Edit ${a.name}`,\n width: 640,\n children: (\n <div className=\"agent-form\">\n <div className=\"muted\">\n File: <code>{full.path}</code>\n </div>\n <label className=\"field-label\">Description</label>\n <input\n ref={(el) => { descEl = el; }}\n className=\"input\"\n type=\"text\"\n defaultValue={full.description}\n />\n <div className=\"task-form-row\">\n <div className=\"task-form-field\">\n <label className=\"field-label\">Model</label>\n <select ref={(el) => (modelEl = el)} className=\"select\" defaultValue={full.model}>\n <option value=\"\">(provider default)</option>\n {MODELS.map((m) => (\n <option key={m} value={m}>{m}</option>\n ))}\n </select>\n </div>\n <div className=\"task-form-field\">\n <label className=\"field-label\">Mode</label>\n <select ref={(el) => (modeEl = el)} className=\"select\" defaultValue={full.mode || 'subagent'}>\n <option value=\"primary\">primary</option>\n <option value=\"subagent\">subagent</option>\n <option value=\"all\">all</option>\n </select>\n </div>\n <div className=\"task-form-field\" style={{ flex: '0 0 80px' }}>\n <label className=\"field-label\">Color</label>\n <input ref={(el) => (colorEl = el)} className=\"input\" type=\"color\" defaultValue={full.color || '#8b5cf6'} />\n </div>\n </div>\n <div className=\"task-form-row\">\n <div className=\"task-form-field\" style={{ flex: 1 }}>\n <label className=\"field-label\">Category</label>\n <select ref={(el) => (categoryEl = el)} className=\"select\" defaultValue={full.category || ''}>\n <option value=\"\">(none)</option>\n {CATEGORIES.map((c) => (\n <option key={c.id} value={c.id}>{c.label}</option>\n ))}\n </select>\n </div>\n <div className=\"task-form-field\" style={{ flex: 2 }}>\n <label className=\"field-label\">Tags (comma-separated)</label>\n <input\n ref={(el) => (tagsEl = el)}\n className=\"input\"\n type=\"text\"\n defaultValue={(full.tags || []).join(', ')}\n />\n </div>\n </div>\n <label className=\"field-label\">Tools</label>\n <div ref={(el) => (toolsContainer = el)} className=\"agent-tools\">\n {TOOL_OPTIONS.map((t) => (\n <label key={t} className=\"checkbox-row\">\n <input type=\"checkbox\" value={t} defaultChecked={full.tools?.includes(t)} />\n <span>{t}</span>\n </label>\n ))}\n </div>\n <label className=\"field-label\">System prompt</label>\n <textarea\n ref={(el) => (promptEl = el)}\n className=\"textarea\"\n rows={8}\n defaultValue={full.prompt || ''}\n />\n </div>\n ),\n footer: (\n <div className=\"modal-footer-actions\">\n <Button variant=\"ghost\" onClick={() => modal.close()}>Cancel</Button>\n <Button\n variant=\"primary\"\n onClick={async () => {\n const tools: string[] = [];\n if (toolsContainer) {\n toolsContainer.querySelectorAll<HTMLInputElement>('input[type=\"checkbox\"]:checked').forEach((cb) => {\n tools.push(cb.value);\n });\n }\n const tags = (tagsEl?.value || '').split(',').map((t) => t.trim()).filter(Boolean);\n try {\n const updated = await api.put<Agent>(\n `/agents/${encodeURIComponent(a.name)}`,\n {\n description: (descEl?.value || '').trim(),\n model: modelEl?.value || '',\n mode: modeEl?.value || 'subagent',\n color: colorEl?.value || '',\n tools,\n tags,\n category: categoryEl?.value || '',\n prompt: promptEl?.value || '',\n },\n );\n setAgents((cur) => cur.map((x) => (x.name === a.name ? updated : x)));\n toast.success('Agent saved.');\n modal.close();\n await refreshSnapshot();\n } catch (err) {\n toast.error(`Save failed: ${(err as Error).message}`);\n }\n }}\n >\n <Save size={12} /> Save\n </Button>\n </div>\n ),\n });\n } catch (err) {\n toast.error(`Load failed: ${(err as Error).message}`);\n }\n };\n\n const onDelete = async (a: Agent) => {\n if (!confirm(`Delete agent \"${a.name}\"? This removes ${a.path}.`)) return;\n try {\n await api.del(`/agents/${encodeURIComponent(a.name)}`);\n setAgents((cur) => cur.filter((x) => x.name !== a.name));\n toast.success('Agent deleted.');\n } catch (err) {\n toast.error(`Delete failed: ${(err as Error).message}`);\n }\n };\n\n const onInvoke = async (a: Agent) => {\n let promptEl: HTMLTextAreaElement | null = null;\n modal.open({\n title: `Invoke ${a.name}`,\n children: (\n <div className=\"invoke-form\">\n <p className=\"muted invoke-form-meta mono\">{a.model || '—'} · {a.path}</p>\n <p className=\"invoke-form-desc\">{a.description}</p>\n <label className=\"field-label\" htmlFor=\"invoke-prompt\">Prompt</label>\n <textarea\n ref={(el) => (promptEl = el)}\n id=\"invoke-prompt\"\n className=\"textarea\"\n rows={5}\n placeholder=\"What should this agent do?\"\n autoFocus\n />\n </div>\n ),\n footer: (\n <div className=\"modal-footer-actions\">\n <Button variant=\"ghost\" onClick={() => modal.close()}>Cancel</Button>\n <Button\n variant=\"primary\"\n onClick={async () => {\n const prompt = (promptEl?.value || '').trim();\n if (!prompt) {\n toast.warning('Prompt is required.');\n return;\n }\n try {\n await api.post(`/agents/${encodeURIComponent(a.name)}/invoke`, { prompt });\n toast.success(`Invoked ${a.name}.`);\n modal.close();\n } catch (err) {\n toast.error(`Invoke failed: ${(err as Error).message}`);\n }\n }}\n >\n <Play size={14} /> Invoke\n </Button>\n </div>\n ),\n });\n };\n\n const onRestart = async (a: Agent) => {\n try {\n const updated = await api.post<Agent>(`/agents/${encodeURIComponent(a.name)}/restart`);\n setAgents((cur) => cur.map((x) => (x.name === a.name ? updated : x)));\n toast.success(`${a.name} restarted.`);\n } catch (err) {\n toast.error(`Restart failed: ${(err as Error).message}`);\n }\n };\n\n const onSetStatus = async (a: Agent, status: 'idle' | 'working' | 'error') => {\n try {\n const updated = await api.post<Agent>(`/agents/${encodeURIComponent(a.name)}/status`, { status });\n setAgents((cur) => cur.map((x) => (x.name === a.name ? updated : x)));\n } catch (err) {\n toast.error(`Status update failed: ${(err as Error).message}`);\n }\n };\n\n return (\n <div className=\"view view-agents\">\n <header className=\"view-header\">\n <div className=\"view-header-text\">\n <h2 className=\"view-title\">\n <Bot size={18} /> Agents ({sorted.length})\n </h2>\n <p className=\"view-subtitle\">\n The Norse pantheon — click <kbd>Edit</kbd> to modify or <kbd>Invoke</kbd> to dispatch.\n </p>\n </div>\n <div className=\"view-actions\">\n <div className=\"search-input\">\n <input\n className=\"input\"\n type=\"text\"\n placeholder=\"Search…\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n />\n </div>\n <select\n className=\"select select-sm\"\n value={categoryFilter}\n onChange={(e) => setCategoryFilter(e.target.value)}\n >\n <option value=\"\">All categories</option>\n {CATEGORIES.map((c) => (\n <option key={c.id} value={c.id}>{c.label}</option>\n ))}\n <option value=\"__none__\">(no category)</option>\n </select>\n <Button variant=\"secondary\" size=\"sm\" onClick={reload}>\n <RefreshCw size={14} /> Refresh\n </Button>\n <Button variant=\"primary\" size=\"sm\" onClick={onCreate}>\n <Plus size={14} /> New agent\n </Button>\n </div>\n </header>\n\n {allTags.length > 0 && (\n <div className=\"agent-tags-row\">\n <TagIcon size={12} />\n {allTags.map((t) => (\n <span key={t} className=\"tag\">{t}</span>\n ))}\n </div>\n )}\n\n {loading ? (\n <div className=\"view-loading\"><Spinner size=\"lg\" /></div>\n ) : sorted.length === 0 ? (\n <EmptyState\n icon={<Bot size={32} />}\n title=\"No agents found\"\n message=\"Run bizar in the terminal to install Bizar.\"\n />\n ) : (\n <div className=\"agent-grid\">\n {sorted.map((a) => (\n <AgentCard\n key={a.name}\n agent={a}\n onInvoke={() => onInvoke(a)}\n onEdit={() => onEdit(a)}\n onDelete={() => onDelete(a)}\n onRestart={() => onRestart(a)}\n onSetStatus={(s) => onSetStatus(a, s)}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction AgentCard({\n agent,\n onInvoke,\n onEdit,\n onDelete,\n onRestart,\n onSetStatus,\n}: {\n agent: Agent;\n onInvoke: () => void;\n onEdit: () => void;\n onDelete: () => void;\n onRestart: () => void;\n onSetStatus: (s: 'idle' | 'working' | 'error') => void;\n}) {\n const [expanded, setExpanded] = useState(false);\n const catColor = categoryColor(agent.category);\n const isWorking = (agent.status === 'working' || !!agent.currentTaskId) && !agent.isStuck;\n return (\n <Card\n variant=\"elevated\"\n interactive\n className={cn(\n 'agent-card',\n isWorking && 'is-working',\n agent.isStuck && 'is-stuck',\n )}\n >\n <div className=\"agent-card-head\">\n <div className=\"agent-card-name\">\n <StatusDot status={agent.status} isStuck={agent.isStuck} />\n {agent.name}\n </div>\n <div className=\"agent-card-badges\">\n {agent.category && (\n <span\n className=\"agent-card-category\"\n style={{ background: `color-mix(in srgb, ${catColor} 18%, transparent)`, color: catColor }}\n >\n {agent.category}\n </span>\n )}\n <StatusPill agent={agent} />\n </div>\n </div>\n <p className=\"agent-card-desc\">{truncate(agent.description, 200)}</p>\n <div className=\"agent-card-meta\">\n <span className=\"mono\" title={agent.model || ''}>\n {agent.model || '—'}\n </span>\n <span className=\"tabular-nums muted\">{formatRelative(agent.mtime)}</span>\n </div>\n {agent.tags && agent.tags.length > 0 && (\n <div className=\"agent-card-tags\">\n {agent.tags.map((t) => (\n <span key={t} className=\"agent-card-tag\">{t}</span>\n ))}\n </div>\n )}\n {(isWorking || agent.lastTask) && (\n <div className=\"agent-card-activity\">\n {agent.currentTaskId && (\n <div className=\"agent-card-row\">\n <Activity size={12} />\n <span className=\"muted\">Working on</span>\n <code className=\"mono\">{agent.currentTaskId}</code>\n </div>\n )}\n {agent.lastTask && !agent.currentTaskId && (\n <div className=\"agent-card-row\">\n <CheckCircle2 size={12} />\n <span className=\"muted\">Last</span>\n <code className=\"mono\">{agent.lastTask.id}</code>\n <span className=\"muted tabular-nums\">{formatRelative(agent.lastTask.finishedAt)}</span>\n </div>\n )}\n {agent.tasksTotal != null && agent.tasksTotal > 0 && (\n <div className=\"agent-card-row\">\n <Circle size={12} />\n <span className=\"muted\">Success rate</span>\n <span className=\"tabular-nums\">{Math.round((agent.successRate || 0) * 100)}%</span>\n <span className=\"muted tabular-nums\">({agent.tasksSucceeded}/{agent.tasksTotal})</span>\n </div>\n )}\n </div>\n )}\n {agent.lastError && (\n <div className=\"agent-card-error\">\n <AlertTriangle size={12} />\n <span className=\"muted\">Last error: {agent.lastError.message}</span>\n </div>\n )}\n <div className=\"agent-card-actions\">\n <Button variant=\"primary\" size=\"sm\" onClick={onInvoke}>\n <Play size={12} /> Invoke\n </Button>\n <Button variant=\"secondary\" size=\"sm\" onClick={onEdit}>\n <Pencil size={12} /> Edit\n </Button>\n {(agent.isStuck || agent.status === 'working' || agent.status === 'error') && (\n <Button variant=\"ghost\" size=\"sm\" onClick={onRestart} title=\"Reset agent status\">\n <RotateCw size={12} /> Restart\n </Button>\n )}\n <Button variant=\"ghost\" size=\"sm\" onClick={onDelete}>\n <Trash2 size={12} />\n </Button>\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label={expanded ? 'Collapse' : 'Expand'}\n onClick={() => setExpanded((v) => !v)}\n style={{ marginLeft: 'auto' }}\n >\n {expanded ? <ChevronDown size={12} /> : <ChevronRight size={12} />}\n </button>\n </div>\n {expanded && (\n <div className=\"agent-card-expanded\">\n <div className=\"agent-card-status-actions\">\n <span className=\"muted text-sm\">Set status:</span>\n <Button\n variant={agent.status === 'idle' ? 'primary' : 'ghost'}\n size=\"sm\"\n onClick={() => onSetStatus('idle')}\n >\n Idle\n </Button>\n <Button\n variant={agent.status === 'working' ? 'primary' : 'ghost'}\n size=\"sm\"\n onClick={() => onSetStatus('working')}\n >\n Working\n </Button>\n <Button\n variant={agent.status === 'error' ? 'primary' : 'ghost'}\n size=\"sm\"\n onClick={() => onSetStatus('error')}\n >\n Error\n </Button>\n </div>\n <div className=\"agent-card-meta\">\n <Folder size={11} />\n <code className=\"mono agent-card-path\">{agent.path}</code>\n </div>\n </div>\n )}\n </Card>\n );\n}\n","// Glyphs block vocabulary — renders MDX blocks from plan.mdx\n\nimport { useMemo, useState } from 'react';\nimport ReactMarkdown from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport {\n AlertTriangle,\n Check,\n CheckCircle2,\n ChevronDown,\n Diamond,\n FileCode2,\n Info,\n Minus,\n StickyNote,\n XCircle,\n} from 'lucide-react';\nimport { cn } from '../../lib/utils';\n\nexport interface RichTextProps {\n id: string;\n children: string;\n}\n\nexport function RichText({ id, children }: RichTextProps) {\n return (\n <div\n id={id}\n data-block-id={id}\n className={cn('glyph-richtext')}\n style={proseStyle}\n >\n <ReactMarkdown remarkPlugins={[remarkGfm]}>{children}</ReactMarkdown>\n </div>\n );\n}\n\nexport interface CalloutProps {\n id: string;\n tone?: 'info' | 'warn' | 'success' | 'danger';\n children: string;\n}\n\nconst CALLOUT_TONE: Record<NonNullable<CalloutProps['tone']>, {\n bg: string; border: string; fg: string; icon: typeof Info; label: string;\n}> = {\n info: { bg: 'var(--info-soft, rgba(96, 165, 250, 0.12))', border: 'var(--info)', fg: 'var(--info)', icon: Info, label: 'Note' },\n warn: { bg: 'var(--warning-soft, rgba(251, 191, 36, 0.15))', border: 'var(--warning)', fg: 'var(--warning)', icon: AlertTriangle, label: 'Warning' },\n success: { bg: 'var(--success-soft, rgba(52, 211, 153, 0.15))', border: 'var(--success)', fg: 'var(--success)', icon: CheckCircle2, label: 'Success' },\n danger: { bg: 'var(--error-soft, rgba(248, 113, 113, 0.12))', border: 'var(--error)', fg: 'var(--error)', icon: XCircle, label: 'Danger' },\n};\n\nexport function Callout({ id, tone = 'info', children }: CalloutProps) {\n const t = CALLOUT_TONE[tone];\n const Icon = t.icon;\n return (\n <div\n id={id}\n data-block-id={id}\n className={cn('glyph-callout', `glyph-callout-${tone}`)}\n style={{\n display: 'flex',\n gap: 12,\n padding: '12px 16px',\n margin: '12px 0',\n borderLeft: `3px solid ${t.border}`,\n background: t.bg,\n borderRadius: 8,\n color: 'var(--text)',\n }}\n role={tone === 'danger' || tone === 'warn' ? 'alert' : undefined}\n >\n <div style={{ flexShrink: 0, color: t.fg, paddingTop: 2 }}>\n <Icon size={18} />\n </div>\n <div style={{ flex: 1, minWidth: 0 }}>\n <div style={{ fontWeight: 600, fontSize: 13, color: t.fg, marginBottom: 4 }}>\n {t.label}\n </div>\n <div className=\"glyph-richtext\" style={{ ...proseStyle, fontSize: 14 }}>\n <ReactMarkdown remarkPlugins={[remarkGfm]}>{children}</ReactMarkdown>\n </div>\n </div>\n </div>\n );\n}\n\nexport interface ChecklistItem {\n id: string;\n label: string;\n checked: boolean;\n}\nexport interface ChecklistProps {\n id: string;\n items: ChecklistItem[];\n}\n\nexport function Checklist({ id, items }: ChecklistProps) {\n return (\n <ul\n id={id}\n data-block-id={id}\n className=\"glyph-checklist\"\n style={{\n listStyle: 'none',\n padding: 0,\n margin: '12px 0',\n display: 'flex',\n flexDirection: 'column',\n gap: 6,\n }}\n >\n {items.map((item) => (\n <li\n key={item.id}\n style={{\n display: 'flex',\n alignItems: 'flex-start',\n gap: 10,\n padding: '6px 10px',\n borderRadius: 6,\n background: 'var(--bg-elev)',\n border: '1px solid var(--border)',\n fontSize: 14,\n }}\n >\n <span\n aria-hidden\n style={{\n flexShrink: 0,\n marginTop: 1,\n width: 16,\n height: 16,\n borderRadius: 4,\n border: `1.5px solid ${item.checked ? 'var(--success)' : 'var(--border-strong)'}`,\n background: item.checked ? 'var(--success)' : 'transparent',\n color: 'var(--bg)',\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n {item.checked ? <Check size={12} strokeWidth={3} /> : null}\n </span>\n <span style={{\n color: item.checked ? 'var(--text-dim)' : 'var(--text)',\n textDecoration: item.checked ? 'line-through' : 'none',\n wordBreak: 'break-word',\n }}>\n {item.label}\n </span>\n </li>\n ))}\n </ul>\n );\n}\n\nexport interface TableProps {\n id: string;\n columns: string[];\n rows: string[][];\n}\n\nexport function Table({ id, columns, rows }: TableProps) {\n return (\n <div\n id={id}\n data-block-id={id}\n className=\"glyph-table-wrap\"\n style={{\n margin: '12px 0',\n border: '1px solid var(--border)',\n borderRadius: 8,\n overflow: 'auto',\n background: 'var(--bg-elev)',\n }}\n >\n <table\n style={{\n width: '100%',\n borderCollapse: 'collapse',\n fontSize: 13,\n }}\n >\n <thead>\n <tr>\n {columns.map((c, i) => (\n <th\n key={i}\n style={{\n textAlign: 'left',\n padding: '8px 12px',\n borderBottom: '1px solid var(--border-strong)',\n background: 'var(--bg)',\n color: 'var(--text-dim)',\n fontWeight: 600,\n fontSize: 12,\n textTransform: 'uppercase',\n letterSpacing: 0.3,\n whiteSpace: 'nowrap',\n }}\n >\n {c}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rows.map((row, ri) => (\n <tr key={ri} style={{ borderTop: ri === 0 ? 'none' : '1px solid var(--border)' }}>\n {row.map((cell, ci) => (\n <td\n key={ci}\n style={{\n padding: '8px 12px',\n color: 'var(--text)',\n verticalAlign: 'top',\n wordBreak: 'break-word',\n }}\n >\n {cell}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n\nexport interface CodeTab {\n id: string;\n label: string;\n language: string;\n code: string;\n caption?: string;\n}\nexport interface CodeTabsProps {\n id: string;\n tabs: CodeTab[];\n}\n\nexport function CodeTabs({ id, tabs }: CodeTabsProps) {\n const [activeId, setActiveId] = useState<string>(tabs[0]?.id ?? '');\n const active = useMemo(\n () => tabs.find((t) => t.id === activeId) ?? tabs[0],\n [tabs, activeId],\n );\n\n return (\n <div\n id={id}\n data-block-id={id}\n className=\"glyph-codetabs\"\n style={{\n margin: '12px 0',\n border: '1px solid var(--border)',\n borderRadius: 8,\n overflow: 'hidden',\n background: 'var(--bg-elev)',\n }}\n >\n <div\n role=\"tablist\"\n style={{\n display: 'flex',\n gap: 2,\n padding: 4,\n background: 'var(--bg)',\n borderBottom: '1px solid var(--border)',\n overflowX: 'auto',\n }}\n >\n {tabs.map((t) => {\n const selected = t.id === active?.id;\n return (\n <button\n key={t.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={selected}\n onClick={() => setActiveId(t.id)}\n style={{\n padding: '6px 12px',\n fontSize: 12,\n fontFamily: 'var(--font-mono)',\n borderRadius: 6,\n border: 'none',\n cursor: 'pointer',\n background: selected ? 'var(--bg-elev)' : 'transparent',\n color: selected ? 'var(--text-strong)' : 'var(--text-dim)',\n boxShadow: selected ? '0 0 0 1px var(--border)' : 'none',\n whiteSpace: 'nowrap',\n }}\n >\n <span>{t.label}</span>\n {t.language && (\n <span style={{ marginLeft: 6, color: 'var(--text-dim)', fontSize: 11 }}>\n {t.language}\n </span>\n )}\n </button>\n );\n })}\n </div>\n {active && (\n <>\n <pre\n style={{\n margin: 0,\n padding: 14,\n overflowX: 'auto',\n fontFamily: 'var(--font-mono)',\n fontSize: 12.5,\n lineHeight: 1.55,\n color: 'var(--text)',\n background: 'var(--bg-elev)',\n }}\n >\n <code>{active.code}</code>\n </pre>\n {active.caption && (\n <div\n style={{\n padding: '8px 14px',\n borderTop: '1px solid var(--border)',\n fontSize: 12,\n color: 'var(--text-dim)',\n background: 'var(--bg)',\n }}\n >\n {active.caption}\n </div>\n )}\n </>\n )}\n </div>\n );\n}\n\nexport interface DecisionOption {\n id: string;\n label: string;\n detail: string;\n recommended?: boolean;\n}\nexport interface DecisionProps {\n id: string;\n title?: string;\n question?: string;\n options: DecisionOption[];\n}\n\nexport function Decision({ id, title, question, options }: DecisionProps) {\n return (\n <div\n id={id}\n data-block-id={id}\n className=\"glyph-decision\"\n style={{\n margin: '16px 0',\n padding: 16,\n border: '1px solid var(--border)',\n borderRadius: 10,\n background: 'var(--bg-elev)',\n }}\n >\n {title && (\n <h3 style={{ margin: 0, marginBottom: 4, fontSize: 15, fontWeight: 600, color: 'var(--text-strong)' }}>\n {title}\n </h3>\n )}\n {question && (\n <p style={{ margin: 0, marginBottom: 12, fontSize: 13, color: 'var(--text-dim)' }}>\n {question}\n </p>\n )}\n <div style={{ display: 'grid', gap: 10, gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))' }}>\n {options.map((opt) => {\n const isRec = !!opt.recommended;\n return (\n <div\n key={opt.id}\n style={{\n position: 'relative',\n padding: 12,\n borderRadius: 8,\n border: isRec ? '2px solid var(--success)' : '1px solid var(--border)',\n background: isRec ? 'var(--success-soft)' : 'var(--bg)',\n }}\n >\n {isRec && (\n <span\n style={{\n position: 'absolute',\n top: -10,\n right: 10,\n padding: '2px 8px',\n fontSize: 11,\n fontWeight: 600,\n color: 'var(--bg)',\n background: 'var(--success)',\n borderRadius: 999,\n }}\n >\n Recommended\n </span>\n )}\n <div style={{ fontWeight: 600, fontSize: 14, color: 'var(--text-strong)', marginBottom: 4 }}>\n {opt.label}\n </div>\n <div style={{ fontSize: 13, color: 'var(--text)' }}>\n {opt.detail}\n </div>\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n\nexport interface OpenQuestion {\n id: string;\n label: string;\n kind: 'choice' | 'text' | 'multi';\n options?: string[];\n}\nexport interface OpenQuestionsProps {\n id: string;\n questions: OpenQuestion[];\n}\n\nexport function OpenQuestions({ id, questions }: OpenQuestionsProps) {\n const [answers, setAnswers] = useState<Record<string, string | string[]>>({});\n\n function setAnswer(qid: string, value: string | string[]) {\n setAnswers((prev) => ({ ...prev, [qid]: value }));\n }\n\n return (\n <div\n id={id}\n data-block-id={id}\n className=\"glyph-openquestions\"\n style={{\n margin: '16px 0',\n padding: 16,\n border: '1px solid var(--border)',\n borderRadius: 10,\n background: 'var(--bg-elev)',\n display: 'flex',\n flexDirection: 'column',\n gap: 14,\n }}\n >\n <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--text-strong)' }}>\n Open questions\n </div>\n {questions.map((q) => (\n <div key={q.id} style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>\n <label\n htmlFor={`oq-${q.id}`}\n style={{ fontSize: 13, color: 'var(--text)', fontWeight: 500 }}\n >\n {q.label}\n </label>\n {q.kind === 'choice' && (\n <select\n id={`oq-${q.id}`}\n value={(answers[q.id] as string) ?? ''}\n onChange={(e) => setAnswer(q.id, e.target.value)}\n style={inputStyle}\n >\n <option value=\"\">— select —</option>\n {(q.options ?? []).map((opt) => (\n <option key={opt} value={opt}>{opt}</option>\n ))}\n </select>\n )}\n {q.kind === 'text' && (\n <input\n id={`oq-${q.id}`}\n type=\"text\"\n value={(answers[q.id] as string) ?? ''}\n onChange={(e) => setAnswer(q.id, e.target.value)}\n style={inputStyle}\n />\n )}\n {q.kind === 'multi' && (\n <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>\n {(q.options ?? []).map((opt) => {\n const current = (answers[q.id] as string[]) ?? [];\n const checked = current.includes(opt);\n return (\n <label\n key={opt}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n fontSize: 13,\n color: 'var(--text)',\n cursor: 'pointer',\n }}\n >\n <input\n type=\"checkbox\"\n checked={checked}\n onChange={() => {\n const next = checked\n ? current.filter((o) => o !== opt)\n : [...current, opt];\n setAnswer(q.id, next);\n }}\n />\n <span>{opt}</span>\n </label>\n );\n })}\n </div>\n )}\n </div>\n ))}\n </div>\n );\n}\n\nconst inputStyle: React.CSSProperties = {\n padding: '6px 10px',\n fontSize: 13,\n borderRadius: 6,\n border: '1px solid var(--border-strong)',\n background: 'var(--bg)',\n color: 'var(--text)',\n fontFamily: 'inherit',\n};\n\nexport interface FileTreeEntry {\n path: string;\n change: 'added' | 'modified' | 'removed' | 'renamed';\n note?: string;\n}\nexport interface FileTreeProps {\n id: string;\n title?: string;\n entries: FileTreeEntry[];\n}\n\nconst FILE_CHANGE: Record<FileTreeEntry['change'], { bg: string; fg: string; label: string }> = {\n added: { bg: 'var(--success-soft)', fg: 'var(--success)', label: 'A' },\n modified: { bg: 'var(--info-soft, rgba(96, 165, 250, 0.12))', fg: 'var(--info)', label: 'M' },\n removed: { bg: 'var(--error-soft)', fg: 'var(--error)', label: 'D' },\n renamed: { bg: 'rgba(139, 92, 246, 0.15)', fg: 'var(--accent)', label: 'R' },\n};\n\nexport function FileTree({ id, title, entries }: FileTreeProps) {\n return (\n <div\n id={id}\n data-block-id={id}\n className=\"glyph-filetree\"\n style={{\n margin: '12px 0',\n padding: title ? 14 : 8,\n border: '1px solid var(--border)',\n borderRadius: 8,\n background: 'var(--bg-elev)',\n }}\n >\n {title && (\n <div\n style={{\n fontSize: 12,\n fontWeight: 600,\n color: 'var(--text-dim)',\n textTransform: 'uppercase',\n letterSpacing: 0.4,\n marginBottom: 8,\n }}\n >\n {title}\n </div>\n )}\n <ul style={{ listStyle: 'none', padding: 0, margin: 0, display: 'flex', flexDirection: 'column', gap: 2 }}>\n {entries.map((e) => {\n const t = FILE_CHANGE[e.change];\n return (\n <li\n key={e.path}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 10,\n padding: '5px 8px',\n borderRadius: 5,\n fontSize: 13,\n }}\n >\n <span\n aria-label={e.change}\n title={e.change}\n style={{\n flexShrink: 0,\n width: 22,\n height: 18,\n borderRadius: 4,\n background: t.bg,\n color: t.fg,\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: 10,\n fontWeight: 700,\n fontFamily: 'var(--font-mono)',\n }}\n >\n {t.label}\n </span>\n <span\n style={{\n fontFamily: 'var(--font-mono)',\n color: 'var(--text)',\n wordBreak: 'break-all',\n flex: 1,\n }}\n >\n {e.path}\n </span>\n {e.note && (\n <span style={{ fontSize: 12, color: 'var(--text-dim)' }}>\n {e.note}\n </span>\n )}\n </li>\n );\n })}\n </ul>\n </div>\n );\n}\n\nexport interface DiffProps {\n id: string;\n filename?: string;\n language?: string;\n mode?: 'split' | 'unified';\n before: string;\n after: string;\n}\n\nexport function Diff({ id, filename, language, mode = 'unified', before, after }: DiffProps) {\n const beforeLines = before.split('\\n');\n const afterLines = after.split('\\n');\n\n const header = (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n padding: '6px 12px',\n background: 'var(--bg)',\n borderBottom: '1px solid var(--border)',\n fontSize: 12,\n color: 'var(--text-dim)',\n fontFamily: 'var(--font-mono)',\n }}\n >\n <FileCode2 size={14} />\n <span style={{ color: 'var(--text)' }}>{filename ?? 'diff'}</span>\n {language && <span>· {language}</span>}\n <span style={{ marginLeft: 'auto', textTransform: 'uppercase', letterSpacing: 0.3 }}>\n {mode}\n </span>\n </div>\n );\n\n const codeStyle: React.CSSProperties = {\n margin: 0,\n padding: 0,\n fontFamily: 'var(--font-mono)',\n fontSize: 12.5,\n lineHeight: 1.55,\n color: 'var(--text)',\n background: 'var(--bg-elev)',\n };\n\n const lineRow = (sign: string, content: string, kind: 'del' | 'add' | 'ctx') => {\n const colors: Record<typeof kind, string> = {\n del: 'var(--error-soft)',\n add: 'var(--success-soft)',\n ctx: 'transparent',\n };\n const signColor: Record<typeof kind, string> = {\n del: 'var(--error)',\n add: 'var(--success)',\n ctx: 'var(--text-dim)',\n };\n return (\n <div\n style={{\n display: 'flex',\n padding: '0 12px',\n background: colors[kind],\n }}\n >\n <span style={{ width: 18, color: signColor[kind], userSelect: 'none', flexShrink: 0 }}>{sign}</span>\n <span style={{ whiteSpace: 'pre', flex: 1, overflowX: 'auto' }}>{content || ' '}</span>\n </div>\n );\n };\n\n return (\n <div\n id={id}\n data-block-id={id}\n className=\"glyph-diff\"\n style={{\n margin: '12px 0',\n border: '1px solid var(--border)',\n borderRadius: 8,\n overflow: 'hidden',\n background: 'var(--bg-elev)',\n }}\n >\n {header}\n {mode === 'unified' ? (\n <pre style={codeStyle}>\n {beforeLines.map((l, i) => (\n <div key={`b${i}`}>{lineRow('-', l, 'del')}</div>\n ))}\n {afterLines.map((l, i) => (\n <div key={`a${i}`}>{lineRow('+', l, 'add')}</div>\n ))}\n </pre>\n ) : (\n <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr' }}>\n <pre style={{ ...codeStyle, borderRight: '1px solid var(--border)' }}>\n {beforeLines.map((l, i) => (\n <div key={i}>{lineRow('-', l, 'del')}</div>\n ))}\n </pre>\n <pre style={codeStyle}>\n {afterLines.map((l, i) => (\n <div key={i}>{lineRow('+', l, 'add')}</div>\n ))}\n </pre>\n </div>\n )}\n </div>\n );\n}\n\nexport interface StatProps {\n id: string;\n label: string;\n value: string | number;\n trend?: 'up' | 'down' | 'flat';\n hint?: string;\n}\n\nconst TREND_STYLE: Record<NonNullable<StatProps['trend']>, { fg: string; Icon: typeof Minus; label: string }> = {\n up: { fg: 'var(--success)', Icon: ChevronDown, label: 'trending up' },\n down: { fg: 'var(--error)', Icon: ChevronDown, label: 'trending down' },\n flat: { fg: 'var(--text-dim)', Icon: Minus, label: 'flat' },\n};\n\nexport function Stat({ id, label, value, trend, hint }: StatProps) {\n const t = trend ? TREND_STYLE[trend] : null;\n return (\n <div\n id={id}\n data-block-id={id}\n className=\"glyph-stat\"\n style={{\n padding: 14,\n border: '1px solid var(--border)',\n borderRadius: 10,\n background: 'var(--bg-elev)',\n display: 'flex',\n flexDirection: 'column',\n gap: 4,\n minWidth: 140,\n }}\n >\n <div style={{ fontSize: 12, color: 'var(--text-dim)', textTransform: 'uppercase', letterSpacing: 0.4 }}>\n {label}\n </div>\n <div style={{ display: 'flex', alignItems: 'baseline', gap: 8 }}>\n <span style={{ fontSize: 24, fontWeight: 700, color: 'var(--text-strong)' }}>\n {value}\n </span>\n {t && (\n <span\n aria-label={t.label}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n color: t.fg,\n transform: t.Icon === ChevronDown && trend === 'up' ? 'rotate(180deg)' : undefined,\n }}\n >\n <t.Icon size={14} />\n </span>\n )}\n </div>\n {hint && (\n <div style={{ fontSize: 12, color: 'var(--text-dim)' }}>\n {hint}\n </div>\n )}\n </div>\n );\n}\n\nexport interface WorkflowStep {\n id: string;\n label: string;\n type: 'task' | 'decision' | 'note';\n}\nexport interface WorkflowConnection {\n from: string;\n to: string;\n label?: string;\n}\nexport interface WorkflowProps {\n id: string;\n steps: WorkflowStep[];\n connections?: WorkflowConnection[];\n}\n\nconst STEP_COLORS: Record<WorkflowStep['type'], { stroke: string; fill: string; fg: string }> = {\n task: { stroke: 'var(--info)', fill: 'var(--bg-elev)', fg: 'var(--text)' },\n decision: { stroke: 'var(--warning)', fill: 'var(--bg-elev)', fg: 'var(--text)' },\n note: { stroke: 'var(--border-strong)', fill: 'var(--bg)', fg: 'var(--text-dim)' },\n};\n\nconst BOX_W = 160;\nconst BOX_H = 56;\nconst GAP_X = 60;\nconst GAP_Y = 80;\n\nexport function Workflow({ id, steps, connections = [] }: WorkflowProps) {\n if (steps.length === 0) {\n return (\n <div id={id} data-block-id={id} className=\"glyph-workflow\">\n <Empty id={id} />\n </div>\n );\n }\n\n const byId = new Map(steps.map((s) => [s.id, s] as const));\n const layout = layoutSteps(steps);\n\n const cols = Math.max(...layout.map((p) => p.col)) + 1;\n const rows = Math.max(...layout.map((p) => p.row)) + 1;\n const width = cols * (BOX_W + GAP_X) + GAP_X;\n const height = rows * (BOX_H + GAP_Y) + GAP_Y;\n\n function nodeCenter(stepId: string): { x: number; y: number } | null {\n const step = byId.get(stepId);\n if (!step) return null;\n const pos = layout.find((p) => p.id === stepId);\n if (!pos) return null;\n return {\n x: GAP_X + pos.col * (BOX_W + GAP_X) + BOX_W / 2,\n y: GAP_Y + pos.row * (BOX_H + GAP_Y) + BOX_H / 2,\n };\n }\n\n return (\n <div\n id={id}\n data-block-id={id}\n className=\"glyph-workflow\"\n style={{\n margin: '12px 0',\n padding: 12,\n border: '1px solid var(--border)',\n borderRadius: 10,\n background: 'var(--bg-elev)',\n overflow: 'auto',\n }}\n >\n <svg\n role=\"img\"\n aria-label=\"Workflow diagram\"\n width={width}\n height={height}\n style={{ display: 'block', maxWidth: '100%' }}\n >\n <defs>\n <marker\n id={`arrow-${id}`}\n viewBox=\"0 0 10 10\"\n refX=\"9\"\n refY=\"5\"\n markerWidth=\"6\"\n markerHeight=\"6\"\n orient=\"auto-start-reverse\"\n >\n <path d=\"M 0 0 L 10 5 L 0 10 z\" fill=\"var(--text-dim)\" />\n </marker>\n </defs>\n\n {connections.map((c, i) => {\n const from = nodeCenter(c.from);\n const to = nodeCenter(c.to);\n if (!from || !to) return null;\n const dx = to.x - from.x;\n const dy = to.y - from.y;\n const fromX = dx >= 0 ? from.x + BOX_W / 2 : from.x - BOX_W / 2;\n const toX = dx >= 0 ? to.x - BOX_W / 2 : to.x + BOX_W / 2;\n const fromY = dy >= 0 ? from.y + BOX_H / 2 : from.y - BOX_H / 2;\n const toY = dy >= 0 ? to.y - BOX_H / 2 : to.y + BOX_H / 2;\n const midX = (fromX + toX) / 2;\n const midY = (fromY + toY) / 2;\n return (\n <g key={i}>\n <line\n x1={fromX}\n y1={fromY}\n x2={toX}\n y2={toY}\n stroke=\"var(--text-dim)\"\n strokeWidth={1.5}\n markerEnd={`url(#arrow-${id})`}\n />\n {c.label && (\n <text\n x={midX}\n y={midY - 4}\n fontSize={10}\n fill=\"var(--text-dim)\"\n textAnchor=\"middle\"\n fontFamily=\"var(--font-mono)\"\n >\n {c.label}\n </text>\n )}\n </g>\n );\n })}\n\n {steps.map((s) => {\n const pos = layout.find((p) => p.id === s.id);\n if (!pos) return null;\n const x = GAP_X + pos.col * (BOX_W + GAP_X);\n const y = GAP_Y + pos.row * (BOX_H + GAP_Y);\n const c = STEP_COLORS[s.type];\n if (s.type === 'decision') {\n const cx = x + BOX_W / 2;\n const cy = y + BOX_H / 2;\n const points = [\n [cx, y],\n [x + BOX_W, cy],\n [cx, y + BOX_H],\n [x, cy],\n ]\n .map((p) => p.join(','))\n .join(' ');\n return (\n <g key={s.id}>\n <polygon\n points={points}\n fill={c.fill}\n stroke={c.stroke}\n strokeWidth={2}\n />\n <foreignObject x={x + 8} y={cy - 14} width={BOX_W - 16} height={28}>\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 4,\n fontSize: 12,\n color: c.fg,\n textAlign: 'center',\n lineHeight: 1.2,\n fontStyle: 'italic',\n height: '100%',\n }}\n >\n <Diamond size={11} />\n {s.label}\n </div>\n </foreignObject>\n </g>\n );\n }\n const isNote = s.type === 'note';\n return (\n <g key={s.id}>\n <rect\n x={x}\n y={y}\n width={BOX_W}\n height={BOX_H}\n rx={8}\n fill={c.fill}\n stroke={c.stroke}\n strokeWidth={isNote ? 1 : 2}\n strokeDasharray={isNote ? '4 3' : undefined}\n />\n <foreignObject x={x + 6} y={y + 6} width={BOX_W - 12} height={BOX_H - 12}>\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 6,\n fontSize: 12,\n color: c.fg,\n textAlign: 'center',\n lineHeight: 1.25,\n fontStyle: isNote ? 'italic' : 'normal',\n height: '100%',\n }}\n >\n {isNote && <StickyNote size={11} />}\n {s.label}\n </div>\n </foreignObject>\n </g>\n );\n })}\n </svg>\n </div>\n );\n}\n\nfunction Empty({ id }: { id: string }) {\n return (\n <div\n id={id}\n style={{\n padding: 20,\n textAlign: 'center',\n color: 'var(--text-dim)',\n fontSize: 13,\n }}\n >\n No workflow steps.\n </div>\n );\n}\n\ntype LayoutPos = { id: string; col: number; row: number };\n\nfunction layoutSteps(steps: WorkflowStep[]): LayoutPos[] {\n if (steps.length === 0) return [];\n return steps.map((s, i) => ({ id: s.id, col: i, row: 0 }));\n}\n\nconst proseStyle: React.CSSProperties = {\n fontSize: 14,\n lineHeight: 1.6,\n color: 'var(--text)',\n};\n\n// ─── Mockup ─────────────────────────────────────────────────────────────────\n\nexport interface MockupProps {\n id: string;\n title?: string;\n x?: number;\n y?: number;\n w?: number;\n h?: number;\n html: string;\n}\n\nexport function Mockup({ id, title, x, y, w, h, html }: MockupProps) {\n return (\n <figure\n id={id}\n data-block-id={id}\n className=\"glyph-mockup\"\n style={{ width: w, minHeight: h }}\n >\n {title && <figcaption className=\"glyph-mockup-title\">{title}</figcaption>}\n <div className=\"glyph-mockup-frame\">\n <div className=\"glyph-mockup-chrome\">\n <span />\n <span />\n <span />\n </div>\n <div\n className=\"glyph-mockup-body\"\n dangerouslySetInnerHTML={{ __html: html }}\n />\n </div>\n </figure>\n );\n}\n","/**\n * GlyphRenderer.tsx — Renders a compiled glyph (from /api/artifacts/:slug/render)\n * with comment pin overlay + right-click to add comments.\n *\n * Uses the agent-native.com \"Visual Plans\" workflow (v3.22.0):\n * - Compiled glyph structure: { frontmatter, blocks: [{id, type, data, childrenMarkdown?}], errors }\n * - Each block renders via the components from ./components\n * - Comment pins from comments.json overlay on top, positioned absolutely\n * - Right-click anywhere → context menu with \"Add comment\" option\n * - Blocks are grouped into sections by id (overview, implementation, …)\n *\n * Layout (v3.22.0 — agent-native /visual-plan inspired, dark dashboard styling):\n * .glyph-canvas ← outer, dotted background\n * .glyph-toolbar-floating ← sticky top-right pill (Send to agent, share, …)\n * .glyph-canvas-content ← centered blocks area\n * .glyph-section ← section card with optional heading\n * .glyph-section-heading ← \"Overview\" / \"Implementation plan\" / …\n * .glyph-section-blocks ← block stack inside the section\n *\n * v3.22.0 — section grouping + floating toolbar rewrite (kept all prior pin/ctx-menu logic).\n */\n\nimport React, { useEffect, useMemo, useState, useRef } from 'react';\nimport {\n MapPin,\n MessageSquare,\n Send,\n Share2,\n Undo2,\n Redo2,\n MoreHorizontal,\n Maximize2,\n X,\n} from 'lucide-react';\nimport { api } from '../../lib/api';\nimport { useToast } from '../../components/Toast';\nimport {\n RichText,\n Callout,\n Checklist,\n Table,\n CodeTabs,\n Decision,\n OpenQuestions,\n FileTree,\n Diff,\n Stat,\n Workflow,\n Mockup,\n} from './components';\n\n// ---------------------------------------------------------------------------\n// BlockErrorBoundary — v4.4.8\n//\n// A single broken block (e.g. a FileTree whose `data.entries` ended up\n// not being an array because the parser silently produced a phantom\n// bareword entry) used to throw inside React, which propagated up and\n// blanked the whole canvas. The boundary catches throws per-block and\n// renders an inline error card instead. The boundary also exposes its\n// errors via a callback so we can surface them in the top-of-page\n// \"render errors\" banner.\n// ---------------------------------------------------------------------------\n\ninterface BlockErrorBoundaryProps {\n blockId: string;\n blockType: string;\n children: React.ReactNode;\n onError: (blockId: string, blockType: string, err: Error, info: React.ErrorInfo) => void;\n}\n\ninterface BlockErrorBoundaryState {\n err: Error | null;\n}\n\nclass BlockErrorBoundary extends React.Component<BlockErrorBoundaryProps, BlockErrorBoundaryState> {\n state: BlockErrorBoundaryState = { err: null };\n static getDerivedStateFromError(err: Error): BlockErrorBoundaryState {\n return { err };\n }\n componentDidCatch(err: Error, info: React.ErrorInfo): void {\n try {\n this.props.onError(this.props.blockId, this.props.blockType, err, info);\n } catch {\n /* ignore — the boundary itself must not throw */\n }\n }\n render(): React.ReactNode {\n if (this.state.err) {\n return (\n <div\n className=\"glyph-block-error\"\n role=\"alert\"\n style={{\n border: '1px solid var(--error, #f85149)',\n background: 'rgba(248, 81, 73, 0.06)',\n borderRadius: 8,\n padding: '12px 14px',\n margin: '12px 0',\n color: 'var(--text)',\n fontFamily: 'var(--font-mono, ui-monospace, monospace)',\n fontSize: 12,\n lineHeight: 1.55,\n }}\n >\n <strong style={{ color: 'var(--error, #f85149)', fontFamily: 'var(--font-sans, system-ui, sans-serif)', display: 'block', marginBottom: 4 }}>\n {this.props.blockType} block crashed\n </strong>\n <div style={{ color: 'var(--text-muted)', marginBottom: 6 }}>\n block id: <code>{this.props.blockId}</code>\n </div>\n <pre style={{ margin: 0, whiteSpace: 'pre-wrap', wordBreak: 'break-word', color: 'var(--text)' }}>\n {this.state.err.message}\n </pre>\n </div>\n );\n }\n return this.props.children;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Block validation — v4.4.8\n//\n// Before handing block data to the component switch, verify that the\n// shape matches the prop contract. Returns `{ ok: true }` when the\n// block can be rendered, or `{ ok: false, error }` when a field is\n// missing or wrong type. The renderer uses the error to skip the\n// component and surface an inline message instead of throwing.\n// ---------------------------------------------------------------------------\n\nfunction validateBlock(b: Block): { ok: true } | { ok: false; error: string } {\n const data = (b.data ?? {}) as Record<string, unknown>;\n switch (b.type) {\n case 'RichText':\n return { ok: true };\n case 'Callout':\n return { ok: true };\n case 'Checklist':\n if (!Array.isArray(data.items)) return { ok: false, error: 'Checklist requires data.items to be an array' };\n return { ok: true };\n case 'Table':\n if (!Array.isArray(data.columns)) return { ok: false, error: 'Table requires data.columns to be an array' };\n if (!Array.isArray(data.rows)) return { ok: false, error: 'Table requires data.rows to be an array' };\n if (data.rows.length > 0 && !Array.isArray(data.rows[0])) return { ok: false, error: 'Table.data.rows[0] must be an array (cell array)' };\n return { ok: true };\n case 'CodeTabs':\n if (!Array.isArray(data.tabs)) return { ok: false, error: 'CodeTabs requires data.tabs to be an array' };\n return { ok: true };\n case 'Decision':\n if (!Array.isArray(data.options)) return { ok: false, error: 'Decision requires data.options to be an array' };\n return { ok: true };\n case 'OpenQuestions':\n if (!Array.isArray(data.questions)) return { ok: false, error: 'OpenQuestions requires data.questions to be an array' };\n return { ok: true };\n case 'FileTree':\n if (!Array.isArray(data.entries)) return { ok: false, error: 'FileTree requires data.entries to be an array' };\n // v4.4.8 — also catch the phantom bareword entry the parser used\n // to emit (the v3-to-v4-consolidation glyph crash). An entry that\n // is not an object means the parser miscounted braces.\n for (const e of data.entries) {\n if (e === null || typeof e !== 'object' || Array.isArray(e)) {\n return { ok: false, error: `FileTree contains a malformed entry: ${JSON.stringify(e)}` };\n }\n }\n return { ok: true };\n case 'Diff':\n if (typeof data.before !== 'string') return { ok: false, error: 'Diff requires data.before to be a string' };\n if (typeof data.after !== 'string') return { ok: false, error: 'Diff requires data.after to be a string' };\n return { ok: true };\n case 'Stat':\n if (data.label === undefined || data.label === null) return { ok: false, error: 'Stat requires data.label' };\n if (data.value === undefined || data.value === null) return { ok: false, error: 'Stat requires data.value' };\n return { ok: true };\n case 'Workflow':\n if (!Array.isArray(data.steps)) return { ok: false, error: 'Workflow requires data.steps to be an array' };\n return { ok: true };\n case 'Mockup':\n if (typeof data.html !== 'string') return { ok: false, error: 'Mockup requires data.html to be a string' };\n return { ok: true };\n case 'Diagram':\n if (typeof data.dataHtml !== 'string') return { ok: false, error: 'Diagram requires data.dataHtml to be a string' };\n return { ok: true };\n default:\n return { ok: false, error: `Unknown block type: ${(b as { type: string }).type}` };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Types — match the server compiler output\n// ---------------------------------------------------------------------------\n\ntype Block =\n | { id: string; type: 'RichText'; data: Record<string, unknown>; childrenMarkdown?: string }\n | { id: string; type: 'Callout'; data: { tone?: 'info' | 'warn' | 'success' | 'danger' }; childrenMarkdown?: string }\n | { id: string; type: 'Checklist'; data: { items: { id: string; label: string; checked: boolean }[] } }\n | { id: string; type: 'Table'; data: { columns: string[]; rows: string[][] } }\n | { id: string; type: 'CodeTabs'; data: { tabs: { id: string; label: string; language: string; code: string; caption?: string }[] } }\n | { id: string; type: 'Decision'; data: { title?: string; question?: string; options: { id: string; label: string; detail: string; recommended?: boolean }[] } }\n | { id: string; type: 'OpenQuestions'; data: { questions: { id: string; label: string; kind: 'choice' | 'text' | 'multi'; options?: string[] }[] } }\n | { id: string; type: 'FileTree'; data: { title?: string; entries: { path: string; change: 'added' | 'modified' | 'removed' | 'renamed'; note?: string }[] } }\n | { id: string; type: 'Diff'; data: { filename?: string; language?: string; mode?: 'split' | 'unified'; before: string; after: string } }\n | { id: string; type: 'Stat'; data: { label: string; value: string | number; trend?: 'up' | 'down' | 'flat'; hint?: string } }\n | { id: string; type: 'Workflow'; data: { steps: { id: string; label: string; type: 'task' | 'decision' | 'note' }[]; connections?: { from: string; to: string; label?: string }[] } }\n | { id: string; type: 'Mockup'; data: { title?: string; x?: number; y?: number; w?: number; h?: number; html: string } }\n | { id: string; type: 'Diagram'; data: { title?: string; dataHtml: string; dataCss?: string } };\n\ninterface CompiledGlyph {\n slug: string;\n frontmatter: Record<string, unknown>;\n blocks: Block[];\n errors: Array<{ line?: number; message: string }>;\n compiledAt: string;\n}\n\ninterface CommentPin {\n id: string;\n elementId?: string | null;\n x: number;\n y: number;\n text: string;\n author?: string;\n created?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Section grouping — block ids → section headings\n// ---------------------------------------------------------------------------\n\nconst SECTION_MAP: Record<string, string> = {\n overview: 'Overview',\n implementation: 'Implementation plan',\n 'implementation-plan': 'Implementation plan',\n questions: 'Open questions',\n 'open-questions': 'Open questions',\n 'open-questions-for-you': 'Open questions',\n comments: 'Comments',\n handoff: 'Handoff',\n};\n\ninterface Section {\n heading: string | null;\n blocks: Block[];\n}\n\nfunction groupBlocksIntoSections(blocks: Block[]): Section[] {\n const sections: Section[] = [];\n let current: Section = { heading: null, blocks: [] };\n\n for (const b of blocks) {\n const heading = SECTION_MAP[b.id] ?? null;\n if (heading) {\n // Push any unheading prelude into a no-heading section so we don't lose it\n if (current.blocks.length > 0 || current.heading !== null) {\n sections.push(current);\n }\n current = { heading, blocks: [b] };\n } else {\n current.blocks.push(b);\n }\n }\n if (current.blocks.length > 0 || current.heading !== null) {\n sections.push(current);\n }\n return sections;\n}\n\n// ---------------------------------------------------------------------------\n// Props\n// ---------------------------------------------------------------------------\n\ninterface Props {\n slug: string;\n onClose?: () => void;\n /** Called after a comment is added so the parent can refresh. */\n onCommentAdded?: () => void;\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport function GlyphRenderer({ slug, onClose, onCommentAdded }: Props) {\n const toast = useToast();\n const [compiled, setCompiled] = useState<CompiledGlyph | null>(null);\n const [comments, setComments] = useState<CommentPin[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n /** Error caught during the loading phase — shown inline so the user knows why. */\n const [loadError, setLoadError] = useState<string | null>(null);\n const [submitting, setSubmitting] = useState(false);\n const [fullscreen, setFullscreen] = useState(false);\n\n // Context-menu state\n const [ctxMenu, setCtxMenu] = useState<{ x: number; y: number; worldX: number; worldY: number } | null>(null);\n const [addingComment, setAddingComment] = useState<{ worldX: number; worldY: number } | null>(null);\n const [commentDraft, setCommentDraft] = useState('');\n\n // Active pin (expanded thread view)\n const [activePin, setActivePin] = useState<string | null>(null);\n\n // v4.4.8 — Per-block render errors caught by BlockErrorBoundary. The\n // boundary calls onError(err) which pushes into this array. We render\n // the array at the top of the canvas in a prominent red banner so the\n // user isn't left staring at a blank screen wondering what happened.\n const [blockErrors, setBlockErrors] = useState<\n Array<{ blockId: string; blockType: string; message: string }>\n >([]);\n const reportBlockError = React.useCallback(\n (blockId: string, blockType: string, err: Error) => {\n setBlockErrors((prev) => {\n // dedupe by blockId so the same block crashing twice doesn't\n // duplicate the entry\n if (prev.some((e) => e.blockId === blockId)) return prev;\n return [...prev, { blockId, blockType, message: err.message || String(err) }];\n });\n },\n [],\n );\n\n const canvasRef = useRef<HTMLDivElement>(null);\n\n // Section grouping — memoized so we don't re-walk the block array on every render\n const sections = useMemo(\n () => (compiled ? groupBlocksIntoSections(compiled.blocks) : []),\n [compiled],\n );\n\n // Load compiled glyph + comments\n useEffect(() => {\n let cancelled = false;\n const TIMEOUT_MS = 5000;\n\n (async () => {\n setLoading(true);\n setError(null);\n try {\n // Race the API calls against a 5-second timeout so the user\n // sees an error rather than a perpetual spinner if the server\n // hangs or the network drops.\n const timeoutPromise = new Promise((_, reject) =>\n setTimeout(() => reject(new Error('Request timed out after 5s')), TIMEOUT_MS)\n );\n\n const [renderData, artifactData] = await Promise.race([\n Promise.all([\n api.get<CompiledGlyph>(`/artifacts/${encodeURIComponent(slug)}/render`),\n api.get<{ comments?: CommentPin[]; commentsJson?: { comments?: CommentPin[] } }>(\n `/artifacts/${encodeURIComponent(slug)}`\n ),\n ]),\n timeoutPromise,\n ]) as [CompiledGlyph, { comments?: CommentPin[]; commentsJson?: { comments?: CommentPin[] } }];\n\n if (cancelled) return;\n setCompiled(renderData);\n const fromFile = (artifactData as any)?.comments ?? [];\n setComments(Array.isArray(fromFile) ? fromFile : []);\n } catch (err) {\n if (!cancelled) {\n const msg = (err as Error).message;\n setError(msg);\n setLoadError(msg);\n }\n } finally {\n if (!cancelled) setLoading(false);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [slug]);\n\n // Right-click context menu\n function onContainerContextMenu(e: React.MouseEvent) {\n if (!canvasRef.current) return;\n e.preventDefault();\n const rect = canvasRef.current.getBoundingClientRect();\n setCtxMenu({\n x: e.clientX,\n y: e.clientY,\n worldX: e.clientX - rect.left,\n worldY: e.clientY - rect.top,\n });\n }\n\n async function submitComment() {\n if (!addingComment || !commentDraft.trim()) return;\n try {\n const created = await api.post<{ id?: string }>(\n `/artifacts/${encodeURIComponent(slug)}/comments`,\n {\n x: addingComment.worldX,\n y: addingComment.worldY,\n text: commentDraft.trim(),\n author: 'drb0rk',\n }\n );\n setComments((prev) => [\n ...prev,\n {\n id: created.id ?? `cmt_${Date.now()}`,\n x: addingComment.worldX,\n y: addingComment.worldY,\n text: commentDraft.trim(),\n author: 'drb0rk',\n created: new Date().toISOString(),\n },\n ]);\n setAddingComment(null);\n setCommentDraft('');\n setCtxMenu(null);\n onCommentAdded?.();\n toast.success('Comment added');\n } catch (err) {\n toast.error(`Failed to add comment: ${(err as Error).message}`);\n }\n }\n\n // \"Send to agent\" — collects free-placed comments and any answers to\n // OpenQuestions, writes `feedback.md` on disk, and marks the artifact\n // `status: review` so the agent picks it up.\n async function submitFeedback() {\n if (submitting) return;\n setSubmitting(true);\n try {\n const result = await api.post<{ ok: boolean; commentCount?: number; questionCount?: number }>(\n `/artifacts/${encodeURIComponent(slug)}/submit`,\n { answers: [], submitter: 'drb0rk' },\n );\n if (result?.ok) {\n toast.success('Sent to agent — feedback.md written, status=review');\n onCommentAdded?.();\n } else {\n toast.error('Submit failed: server did not return ok=true');\n }\n } catch (err) {\n toast.error(`Submit failed: ${(err as Error).message}`);\n } finally {\n setSubmitting(false);\n }\n }\n\n function toggleFullscreen() {\n setFullscreen((v) => !v);\n }\n\n // Render a single block — wrapped in a BlockErrorBoundary so a single\n// broken block (e.g. wrong data shape from a parser bug) shows an inline\n// error card instead of blanking the whole canvas.\n const renderBlock = (b: Block) => {\n const id = b.id;\n const data = (b.data ?? {}) as Record<string, unknown>;\n // Validate data shape BEFORE handing to the component switch. A\n // validation failure shows an inline error card immediately, no\n // need for the boundary to catch it.\n const validation = validateBlock(b);\n if (!validation.ok) {\n return (\n <div\n key={id}\n id={id}\n className=\"glyph-block-error\"\n role=\"alert\"\n style={{\n border: '1px solid var(--error, #f85149)',\n background: 'rgba(248, 81, 73, 0.06)',\n borderRadius: 8,\n padding: '12px 14px',\n margin: '12px 0',\n color: 'var(--text)',\n fontFamily: 'var(--font-mono, ui-monospace, monospace)',\n fontSize: 12,\n lineHeight: 1.55,\n }}\n >\n <strong style={{ color: 'var(--error, #f85149)', fontFamily: 'var(--font-sans, system-ui, sans-serif)', display: 'block', marginBottom: 4 }}>\n {b.type} block invalid\n </strong>\n <div style={{ color: 'var(--text-muted)', marginBottom: 6 }}>\n block id: <code>{id}</code>\n </div>\n <pre style={{ margin: 0, whiteSpace: 'pre-wrap', wordBreak: 'break-word' }}>{validation.error}</pre>\n </div>\n );\n }\n // Wrap the actual render in an error boundary so even runtime\n // errors (bad component props, undefined data, etc.) don't crash\n // the whole canvas.\n return (\n <BlockErrorBoundary key={id} blockId={id} blockType={b.type} onError={reportBlockError}>\n {renderBlockInner(b, id, data)}\n </BlockErrorBoundary>\n );\n };\n\n // Inner renderer — split out so the outer renderBlock can validate +\n // wrap in an error boundary without nesting the switch in the JSX tree.\n const renderBlockInner = (b: Block, id: string, data: Record<string, unknown>) => {\n switch (b.type) {\n case 'RichText':\n return <RichText key={id} id={id}>{b.childrenMarkdown ?? ''}</RichText>;\n case 'Callout':\n return (\n <Callout key={id} id={id} tone={(data.tone as 'info' | 'warn' | 'success' | 'danger' | undefined) ?? 'info'}>\n {b.childrenMarkdown ?? ''}\n </Callout>\n );\n case 'Checklist':\n return (\n <Checklist key={id} id={id} items={(data.items as any) ?? []} />\n );\n case 'Table':\n return (\n <Table key={id} id={id} columns={(data.columns as string[]) ?? []} rows={(data.rows as string[][]) ?? []} />\n );\n case 'CodeTabs':\n return (\n <CodeTabs key={id} id={id} tabs={(data.tabs as any) ?? []} />\n );\n case 'Decision':\n return (\n <Decision\n key={id}\n id={id}\n title={data.title as string | undefined}\n question={data.question as string | undefined}\n options={(data.options as any) ?? []}\n />\n );\n case 'OpenQuestions':\n return (\n <OpenQuestions\n key={id}\n id={id}\n questions={(data.questions as any) ?? []}\n />\n );\n case 'FileTree':\n return (\n <FileTree\n key={id}\n id={id}\n title={data.title as string | undefined}\n entries={(data.entries as any) ?? []}\n />\n );\n case 'Diff':\n return (\n <Diff\n key={id}\n id={id}\n filename={data.filename as string | undefined}\n language={data.language as string | undefined}\n mode={(data.mode as 'split' | 'unified' | undefined) ?? 'unified'}\n before={(data.before as string) ?? ''}\n after={(data.after as string) ?? ''}\n />\n );\n case 'Stat':\n return (\n <Stat\n key={id}\n id={id}\n label={(data.label as string) ?? ''}\n value={data.value as string | number}\n trend={data.trend as 'up' | 'down' | 'flat' | undefined}\n hint={data.hint as string | undefined}\n />\n );\n case 'Workflow':\n return (\n <Workflow\n key={id}\n id={id}\n steps={(data.steps as any) ?? []}\n connections={data.connections as any}\n />\n );\n case 'Mockup':\n return (\n <Mockup\n key={id}\n id={id}\n title={data.title as string | undefined}\n x={data.x as number | undefined}\n y={data.y as number | undefined}\n w={data.w as number | undefined}\n h={data.h as number | undefined}\n html={(data.html as string) ?? ''}\n />\n );\n case 'Diagram':\n return (\n <div key={id} id={id} className=\"glyph-block-placeholder\">\n <em>[Diagram] {id}</em>\n </div>\n );\n }\n };\n\n if (loading) {\n return (\n <div className=\"glyph-renderer glyph-renderer--loading\">\n {loadError ? (\n <>\n <strong>Failed to load glyph.</strong>\n <pre>{loadError}</pre>\n </>\n ) : (\n <>\n <Spinner /> Loading glyph…\n </>\n )}\n </div>\n );\n }\n\n if (error || !compiled) {\n return (\n <div className=\"glyph-renderer glyph-renderer--error\">\n <strong>Failed to load glyph.</strong>\n <pre>{error ?? 'unknown error'}</pre>\n </div>\n );\n }\n\n const title = (compiled.frontmatter?.title as string) ?? slug;\n const status = (compiled.frontmatter?.status as string) ?? 'draft';\n const commentCount = comments.length;\n\n return (\n <div\n className={`glyph-canvas ${fullscreen ? 'glyph-canvas--fullscreen' : ''}`}\n ref={canvasRef}\n onContextMenu={onContainerContextMenu}\n >\n {/* Floating toolbar (sticky top-right pill) */}\n <div className=\"glyph-toolbar-floating\">\n <button\n className=\"glyph-btn glyph-btn--primary glyph-btn--send\"\n onClick={submitFeedback}\n disabled={submitting}\n title=\"Send comments + question answers to the agent — writes feedback.md, status=review\"\n >\n <Send size={14} />\n <span>Send to agent</span>\n <span className=\"glyph-btn-badge\">{commentCount}</span>\n </button>\n\n <span className=\"glyph-toolbar-divider\" />\n\n <button\n className=\"glyph-icon-btn\"\n title=\"Share\"\n onClick={() => {\n if (typeof window !== 'undefined' && navigator.clipboard) {\n navigator.clipboard.writeText(window.location.href).catch(() => {});\n toast.success('Link copied');\n }\n }}\n >\n <Share2 size={15} />\n </button>\n <button className=\"glyph-icon-btn\" title=\"Undo\" disabled>\n <Undo2 size={15} />\n </button>\n <button className=\"glyph-icon-btn\" title=\"Redo\" disabled>\n <Redo2 size={15} />\n </button>\n <button\n className=\"glyph-icon-btn\"\n title={fullscreen ? 'Exit fullscreen' : 'Fullscreen'}\n onClick={toggleFullscreen}\n >\n <Maximize2 size={15} />\n </button>\n <button className=\"glyph-icon-btn\" title=\"More\">\n <MoreHorizontal size={15} />\n </button>\n <span className=\"glyph-toolbar-divider\" />\n <button\n className=\"glyph-icon-btn\"\n title=\"Comment count\"\n aria-label=\"Comment count\"\n >\n <MessageSquare size={15} />\n <span className=\"glyph-icon-btn-count\">{commentCount}</span>\n </button>\n {onClose && (\n <button\n className=\"glyph-icon-btn glyph-icon-btn--close\"\n title=\"Close\"\n onClick={onClose}\n aria-label=\"Close\"\n >\n <X size={15} />\n </button>\n )}\n </div>\n\n {/* Canvas content — centered column of section cards */}\n <div className=\"glyph-canvas-content\">\n {/* Title strip (inside canvas, above sections) */}\n <header className=\"glyph-canvas-title\">\n <h1 className=\"glyph-title\">{title}</h1>\n <div className=\"glyph-meta\">\n <span className={`glyph-status glyph-status--${status}`}>{status}</span>\n <span className=\"glyph-slug\">{slug}</span>\n </div>\n </header>\n\n {/* v4.4.8 — Render errors banner. Two layers:\n 1. Compiler warnings from the MDX parser (e.g. unknown\n tag, unclosed block). Lightweight, yellow border.\n 2. Block render errors caught by BlockErrorBoundary. These\n are the \"one block crashed but the rest still rendered\"\n cases. Red border, prominent, listed first so the user\n sees them before scrolling. */}\n {(blockErrors.length > 0 || compiled.errors?.length > 0) && (\n <div\n className=\"glyph-render-errors\"\n role=\"alert\"\n style={{\n border: '1px solid var(--error, #f85149)',\n background: 'rgba(248, 81, 73, 0.08)',\n borderRadius: 8,\n padding: '12px 16px',\n margin: '0 0 16px 0',\n color: 'var(--text)',\n }}\n >\n <strong style={{ color: 'var(--error, #f85149)', display: 'block', marginBottom: 8 }}>\n {blockErrors.length > 0\n ? `${blockErrors.length} block${blockErrors.length === 1 ? '' : 's'} failed to render`\n : 'Compiler warnings'}\n </strong>\n <ul style={{ margin: 0, paddingLeft: 20, fontFamily: 'var(--font-mono, ui-monospace, monospace)', fontSize: 12, lineHeight: 1.6 }}>\n {blockErrors.map((e, i) => (\n <li key={`be-${i}`}>\n <strong>{e.blockType}</strong> (<code>{e.blockId}</code>): {e.message}\n </li>\n ))}\n {compiled.errors?.map((e, i) => (\n <li key={`ce-${i}`}>\n {e.line ? `line ${e.line}: ` : ''}{e.message}\n </li>\n ))}\n </ul>\n </div>\n )}\n\n {/* Sections */}\n <div className=\"glyph-sections\">\n {sections.map((section, i) => (\n <section\n key={`sec-${i}-${section.heading ?? 'ungrouped'}`}\n className={`glyph-section ${section.heading ? 'glyph-section--headed' : 'glyph-section--plain'}`}\n >\n {section.heading && (\n <h2 className=\"glyph-section-heading\">{section.heading}</h2>\n )}\n <div className=\"glyph-section-blocks\">\n {section.blocks.map(renderBlock)}\n </div>\n </section>\n ))}\n </div>\n </div>\n\n {/* Comment pin overlay */}\n {comments.map((c) => (\n <button\n key={c.id}\n className={`glyph-pin ${activePin === c.id ? 'glyph-pin--active' : ''}`}\n style={{ left: c.x, top: c.y }}\n onClick={(e) => {\n e.stopPropagation();\n setActivePin(activePin === c.id ? null : c.id);\n }}\n title={c.text}\n >\n <MapPin size={14} />\n {activePin === c.id && (\n <div className=\"glyph-pin-thread\">\n <div className=\"glyph-pin-text\">{c.text}</div>\n <div className=\"glyph-pin-meta\">\n {c.author ?? 'anonymous'} · {c.created ? new Date(c.created).toLocaleString() : ''}\n </div>\n </div>\n )}\n </button>\n ))}\n\n {/* Context menu (right-click) */}\n {ctxMenu && (\n <div\n className=\"glyph-ctx-menu\"\n style={{ left: ctxMenu.x, top: ctxMenu.y }}\n onClick={(e) => e.stopPropagation()}\n >\n <button\n className=\"glyph-ctx-item\"\n onClick={() => {\n setAddingComment({ worldX: ctxMenu.worldX, worldY: ctxMenu.worldY });\n setCtxMenu(null);\n }}\n >\n <MapPin size={14} /> Add comment here\n </button>\n </div>\n )}\n\n {/* Add-comment modal */}\n {addingComment && (\n <div className=\"glyph-modal-overlay\" onClick={() => setAddingComment(null)}>\n <div className=\"glyph-modal\" onClick={(e) => e.stopPropagation()}>\n <h3>Add comment at ({Math.round(addingComment.worldX)}, {Math.round(addingComment.worldY)})</h3>\n <textarea\n autoFocus\n value={commentDraft}\n onChange={(e) => setCommentDraft(e.target.value)}\n placeholder=\"What should the agent know about this area?\"\n rows={4}\n className=\"glyph-modal-textarea\"\n />\n <div className=\"glyph-modal-actions\">\n <button className=\"glyph-btn glyph-btn--ghost\" onClick={() => setAddingComment(null)}>\n Cancel\n </button>\n <button className=\"glyph-btn glyph-btn--primary\" onClick={submitComment} disabled={!commentDraft.trim()}>\n Add comment\n </button>\n </div>\n </div>\n </div>\n )}\n </div>\n );\n}\n\n// Tiny inline spinner (no extra dep)\nfunction Spinner() {\n return <span className=\"glyph-spinner\" aria-label=\"loading\">…</span>;\n}","// src/views/Artifacts.tsx — v3.1.0 artifact editor with fullscreen canvas + floating controls.\nimport React from 'react';\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport { GlyphRenderer } from './glyphs/GlyphRenderer';\nimport {\n ArrowLeft,\n Map as MapIcon,\n Plus,\n RefreshCw,\n Settings as SettingsIcon,\n MessageCircle,\n MessageSquare,\n Maximize2,\n Minimize2,\n X,\n Trash2,\n Pencil,\n Link2,\n Send,\n Check,\n Circle,\n StopCircle,\n AlertCircle,\n HelpCircle,\n CheckSquare,\n StickyNote,\n ChevronRight,\n Search,\n Activity,\n Filter,\n Archive,\n ArchiveRestore,\n Copy,\n ArrowUp,\n ArrowDown,\n Layers,\n} from 'lucide-react';\nimport { Button } from '../components/Button';\nimport { Card, CardTitle, CardMeta } from '../components/Card';\nimport { EmptyState } from '../components/EmptyState';\nimport { Spinner } from '../components/Spinner';\nimport { StatusBadge } from '../components/StatusBadge';\nimport { useToast } from '../components/Toast';\nimport { useModal } from '../components/Modal';\nimport { CanvasContextMenu, type ContextMenuState } from '../components/CanvasContextMenu';\nimport { api } from '../lib/api';\nimport { cn, formatRelative, truncate } from '../lib/utils';\nimport type {\n Canvas,\n CanvasComment,\n CanvasConnection,\n CanvasElement,\n Artifact,\n Settings,\n Snapshot,\n} from '../lib/types';\n\ntype Props = {\n snapshot: Snapshot;\n settings: Settings;\n activeTab: string;\n setActiveTab: (id: string) => void;\n refreshSnapshot: () => Promise<void>;\n};\n\nconst ELEMENT_TYPES = [\n { id: 'task', label: 'Task', color: 'var(--info)', Icon: CheckSquare },\n { id: 'note', label: 'Note', color: 'var(--text-dim)', Icon: StickyNote },\n { id: 'decision', label: 'Decision', color: 'var(--accent)', Icon: Check },\n { id: 'question', label: 'Question', color: 'var(--warning)', Icon: HelpCircle },\n];\n\nconst PLAN_STATUSES = ['draft', 'approved', 'in-progress', 'done', 'rejected', 'archived'];\n\nfunction planStatusKind(status: string): 'success' | 'info' | 'error' | 'accent' | 'neutral' | 'warning' {\n switch (status) {\n case 'approved':\n case 'done':\n return 'success';\n case 'in-progress':\n case 'doing':\n return 'info';\n case 'rejected':\n return 'error';\n case 'archived':\n return 'warning';\n case 'draft':\n default:\n return 'neutral';\n }\n}\n\nfunction elementColor(type: string): string {\n return ELEMENT_TYPES.find((t) => t.id === type)?.color || 'var(--text-dim)';\n}\n\nfunction ElementIcon({ type, size = 12 }: { type: string; size?: number }) {\n const def = ELEMENT_TYPES.find((t) => t.id === type) || ELEMENT_TYPES[1];\n const Icon = def.Icon;\n return <Icon size={size} style={{ color: def.color }} />;\n}\n\n// ── List view ──────────────────────────────────────────────────────────\n\nexport function Artifacts({ snapshot, refreshSnapshot }: Props) {\n const toast = useToast();\n const [artifacts, setPlans] = useState<Artifact[]>(snapshot.artifacts || []);\n const [loading, setLoading] = useState(!snapshot.artifacts);\n const [activeSlug, setActiveSlug] = useState<string | null>(null);\n const [filter, setFilter] = useState('');\n const [showArchived, setShowArchived] = useState(false);\n\n useEffect(() => {\n if (snapshot.artifacts) {\n setPlans(snapshot.artifacts);\n setLoading(false);\n }\n }, [snapshot.artifacts]);\n\n const reload = async () => {\n try {\n const d = await api.get<{ artifacts: Artifact[] }>('/artifacts');\n setPlans(d.artifacts || []);\n setLoading(false);\n } catch (err) {\n toast.error(`Artifacts load failed: ${(err as Error).message}`);\n setLoading(false);\n }\n };\n\n const filtered = useMemo(() => {\n let out = artifacts;\n if (filter) {\n const q = filter.toLowerCase();\n out = out.filter(\n (p) =>\n (p.slug || '').toLowerCase().includes(q) ||\n (p.title || '').toLowerCase().includes(q),\n );\n }\n if (!showArchived) {\n out = out.filter((p) => p.status !== 'archived');\n }\n return out;\n }, [artifacts, filter, showArchived]);\n\n const onCreate = async (slug: string, title?: string) => {\n try {\n const artifact = await api.post<{ slug: string }>('/artifacts', { slug, title });\n toast.success(`Artifact \"${artifact.slug}\" created.`);\n setActiveSlug(artifact.slug);\n await reload();\n } catch (err) {\n toast.error(`Create failed: ${(err as Error).message}`);\n }\n };\n\n const onDelete = async (slug: string) => {\n if (!confirm(`Delete artifact \"${slug}\"? This removes the directory permanently.`)) return;\n try {\n await api.del(`/artifacts/${encodeURIComponent(slug)}`);\n toast.success('Artifact deleted.');\n if (activeSlug === slug) setActiveSlug(null);\n await reload();\n } catch (err) {\n toast.error(`Delete failed: ${(err as Error).message}`);\n }\n };\n\n if (activeSlug) {\n // v3.21.0 — Use the new GlyphRenderer (agent-native-style MDX renderer)\n // instead of the hand-rolled PlanEditor canvas. Toggle available via the\n // \"Use MDX\" button in the header (TODO: surface this once stable).\n return (\n <div className=\"artifact-glyph-overlay\">\n <div className=\"artifact-glyph-toolbar\">\n <Button variant=\"ghost\" onClick={() => { setActiveSlug(null); reload(); }}>\n <ArrowLeft size={14} /> Back to artifacts\n </Button>\n </div>\n <GlyphRenderer\n slug={activeSlug}\n onClose={() => { setActiveSlug(null); reload(); }}\n onCommentAdded={() => reload()}\n />\n </div>\n );\n }\n\n return (\n <div className=\"view view-artifacts\">\n <header className=\"view-header\">\n <div className=\"view-header-text\">\n <h2 className=\"view-title\">\n <MapIcon size={18} /> Glyphs ({artifacts.length})\n </h2>\n <p className=\"view-subtitle\">\n Visual artifacts with elements, connections, and threaded comments.\n </p>\n </div>\n <div className=\"view-actions\">\n <div className=\"search-input\">\n <Search size={14} />\n <input\n className=\"input\"\n type=\"text\"\n placeholder=\"Search…\"\n value={filter}\n onChange={(e) => setFilter(e.target.value)}\n />\n </div>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setShowArchived((v) => !v)}\n title={showArchived ? 'Hide archived' : 'Show archived'}\n >\n {showArchived ? <ArchiveRestore size={14} /> : <Archive size={14} />}\n {showArchived ? 'Hide archived' : 'Show archived'}\n </Button>\n <Button variant=\"secondary\" size=\"sm\" onClick={reload}>\n <RefreshCw size={14} /> Refresh\n </Button>\n </div>\n </header>\n\n <NewPlanCard onCreate={onCreate} />\n\n {loading ? (\n <div className=\"view-loading\">\n <Spinner size=\"lg\" />\n </div>\n ) : filtered.length === 0 ? (\n <EmptyState\n icon={<MapIcon size={32} />}\n title={showArchived ? 'No artifacts' : 'No artifacts yet'}\n message={\n showArchived\n ? 'No artifacts match your filter (try Show archived off).'\n : 'Create one above to get started.'\n }\n />\n ) : (\n <div className=\"artifacts-grid\">\n {filtered.map((p) => (\n <PlanCard\n key={p.slug}\n artifact={p}\n onOpen={() => setActiveSlug(p.slug)}\n onDelete={() => onDelete(p.slug)}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction NewPlanCard({ onCreate }: { onCreate: (slug: string, title?: string) => void }) {\n const [slug, setSlug] = useState('');\n const [title, setTitle] = useState('');\n return (\n <Card className=\"new-artifact\">\n <CardTitle>\n <Plus size={14} /> New artifact\n </CardTitle>\n <CardMeta>Slug must be lowercase, may contain hyphens, 1–64 chars.</CardMeta>\n <form\n className=\"new-artifact-form\"\n onSubmit={(e) => {\n e.preventDefault();\n if (!slug.trim()) return;\n onCreate(slug.trim(), title.trim() || undefined);\n setSlug('');\n setTitle('');\n }}\n >\n <input\n className=\"input\"\n type=\"text\"\n placeholder=\"slug (e.g. dashboard-v3.1)\"\n pattern=\"[a-z0-9][a-z0-9-]{0,63}\"\n required\n value={slug}\n onChange={(e) => setSlug(e.target.value)}\n />\n <input\n className=\"input\"\n type=\"text\"\n placeholder=\"Title (optional)\"\n value={title}\n onChange={(e) => setTitle(e.target.value)}\n />\n <Button variant=\"primary\" type=\"submit\">\n Create\n </Button>\n </form>\n </Card>\n );\n}\n\nfunction PlanCard({\n artifact,\n onOpen,\n onDelete,\n}: {\n artifact: Artifact;\n onOpen: () => void;\n onDelete: () => void;\n}) {\n const kind = planStatusKind(artifact.status || 'draft');\n return (\n <Card\n variant=\"elevated\"\n interactive\n className=\"artifact-card\"\n onClick={onOpen}\n >\n <div className=\"artifact-card-head\">\n <div className=\"artifact-card-title\">{artifact.title || artifact.slug}</div>\n <StatusBadge kind={kind}>{artifact.status || 'draft'}</StatusBadge>\n </div>\n <div className=\"artifact-card-slug mono\">{artifact.slug} · {artifact.source}</div>\n <div className=\"artifact-card-meta\">\n {artifact.elementCount != null && <span>{artifact.elementCount} elements</span>}\n {artifact.commentCount != null && <span> · {artifact.commentCount} comments</span>}\n <span> · edited {formatRelative(artifact.mtime)}</span>\n </div>\n <div className=\"artifact-card-actions\">\n <Button variant=\"primary\" size=\"sm\" onClick={(e) => { e.stopPropagation(); onOpen(); }}>\n Open\n <ChevronRight size={12} />\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={(e) => { e.stopPropagation(); onDelete(); }}>\n <Trash2 size={12} /> Delete\n </Button>\n </div>\n </Card>\n );\n}\n\n// ── Artifact editor (fullscreen) ──────────────────────────────────────────\n\nfunction PlanEditor({\n slug,\n onBack,\n onDelete,\n}: {\n slug: string;\n onBack: () => void;\n onDelete: () => void;\n}) {\n const toast = useToast();\n const modal = useModal();\n const [canvas, setCanvas] = useState<Canvas | null>(null);\n const [meta, setMeta] = useState<{ title: string; status: string; tags: string[]; description?: string } | null>(null);\n const [loading, setLoading] = useState(true);\n const [selectedElId, setSelectedElId] = useState<string | null>(null);\n const [fullscreen, setFullscreen] = useState(false);\n const [showComments, setShowComments] = useState(true);\n const [contextMenu, setContextMenu] = useState<ContextMenuState>(null);\n const [contextMenuWorldPos, setContextMenuWorldPos] = useState<{ x: number; y: number } | null>(null);\n // v3.7.0 — Element-specific right-click context menu\n const [elementContextMenu, setElementContextMenu] = useState<ContextMenuState>(null);\n\n const moveElementLocally = (id: string, x: number, y: number) => {\n setCanvas((cur) => {\n if (!cur) return cur;\n return {\n ...cur,\n elements: cur.elements.map((el) => (el.id === id ? { ...el, x, y } : el)),\n };\n });\n };\n\n const reload = async () => {\n setLoading(true);\n try {\n const artifact = await api.get<{ meta: { title: string; status: string; tags: string[]; description?: string }; canvas: Canvas }>(\n `/artifacts/${encodeURIComponent(slug)}`,\n );\n setCanvas(artifact.canvas);\n setMeta(artifact.meta);\n } catch (err) {\n toast.error(`Could not load artifact: ${(err as Error).message}`);\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n setSelectedElId(null);\n reload();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [slug]);\n\n // Issue 3 fix — wire fullscreen state to browser Fullscreen API\n useEffect(() => {\n if (!fullscreen) {\n if (document.fullscreenElement) {\n document.exitFullscreen().catch(() => {});\n }\n return;\n }\n // Sync state when user exits via ESC key — before entering, so we don't\n // double-set on the way in\n const onFullscreenChange = () => {\n if (!document.fullscreenElement) setFullscreen(false);\n };\n document.addEventListener('fullscreenchange', onFullscreenChange);\n // Attempt to enter fullscreen (fails silently if unsupported or blocked)\n document.documentElement.requestFullscreen().catch(() => {});\n return () => {\n document.removeEventListener('fullscreenchange', onFullscreenChange);\n if (document.fullscreenElement) {\n document.exitFullscreen().catch(() => {});\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [fullscreen]);\n\n const totalComments = canvas?.comments.length ?? 0;\n\n const addElement = async (body: { type: string; title: string; content: string; x: number; y: number }, position?: { x: number; y: number }) => {\n try {\n const payload = position ? { ...body, x: position.x, y: position.y } : body;\n await api.post(`/artifacts/${encodeURIComponent(slug)}/elements`, payload);\n await reload();\n toast.success('Element added.');\n } catch (err) {\n toast.error(`Add element failed: ${(err as Error).message}`);\n }\n };\n\n const updateElement = async (id: string, body: Partial<CanvasElement>) => {\n try {\n await api.put(`/artifacts/${encodeURIComponent(slug)}/elements/${encodeURIComponent(id)}`, body);\n await reload();\n } catch (err) {\n toast.error(`Update failed: ${(err as Error).message}`);\n }\n };\n\n const deleteElement = async (id: string) => {\n try {\n await api.del(`/artifacts/${encodeURIComponent(slug)}/elements/${encodeURIComponent(id)}`);\n if (selectedElId === id) setSelectedElId(null);\n await reload();\n toast.success('Element deleted.');\n } catch (err) {\n toast.error(`Delete failed: ${(err as Error).message}`);\n }\n };\n\n // v3.7.0 — Duplicate an element with a small position offset\n const duplicateElement = async (id: string) => {\n const el = canvas?.elements.find((e) => e.id === id);\n if (!el) return;\n try {\n await api.post(`/artifacts/${encodeURIComponent(slug)}/elements`, {\n type: el.type,\n title: el.title ? `${el.title} (copy)` : 'Untitled',\n content: el.content || '',\n x: (el.x || 0) + 24,\n y: (el.y || 0) + 24,\n });\n await reload();\n toast.success('Element duplicated.');\n } catch (err) {\n toast.error(`Duplicate failed: ${(err as Error).message}`);\n }\n };\n\n // v3.7.0 — Change element type\n const changeElementType = async (id: string, newType: string) => {\n try {\n await api.put(`/artifacts/${encodeURIComponent(slug)}/elements/${encodeURIComponent(id)}`, { type: newType });\n await reload();\n toast.success(`Type changed to ${newType}.`);\n } catch (err) {\n toast.error(`Change type failed: ${(err as Error).message}`);\n }\n };\n\n const addConnection = async (from: string, to: string, label?: string) => {\n try {\n await api.post(`/artifacts/${encodeURIComponent(slug)}/connections`, { from, to, label });\n await reload();\n toast.success('Connection added.');\n } catch (err) {\n toast.error(`Connection failed: ${(err as Error).message}`);\n }\n };\n\n const deleteConnection = async (id: string) => {\n try {\n await api.del(`/artifacts/${encodeURIComponent(slug)}/connections/${encodeURIComponent(id)}`);\n await reload();\n } catch (err) {\n toast.error(`Delete failed: ${(err as Error).message}`);\n }\n };\n\n const addComment = async (text: string, elementId: string | null, worldPos?: { x: number; y: number }) => {\n try {\n const path = elementId\n ? `/artifacts/${encodeURIComponent(slug)}/elements/${encodeURIComponent(elementId)}/comments`\n : `/artifacts/${encodeURIComponent(slug)}/comments`;\n const body: { text: string; elementId: string | null; x?: number; y?: number } = { text, elementId };\n if (worldPos) { body.x = worldPos.x; body.y = worldPos.y; }\n await api.post(path, body);\n await reload();\n toast.success('Comment added.');\n } catch (err) {\n toast.error(`Comment failed: ${(err as Error).message}`);\n }\n };\n\n const deleteComment = async (cid: string) => {\n try {\n await api.del(`/artifacts/${encodeURIComponent(slug)}/comments/${encodeURIComponent(cid)}`);\n await reload();\n } catch (err) {\n toast.error(`Delete failed: ${(err as Error).message}`);\n }\n };\n\n const updatePositions = async (positions: { id: string; x: number; y: number }[]) => {\n try {\n await api.put(`/artifacts/${encodeURIComponent(slug)}/position`, { positions });\n } catch (err) {\n // non-fatal\n console.warn('Position update failed', err);\n }\n };\n\n const onConfigure = () => {\n if (!meta) return;\n let titleEl: HTMLInputElement | null = null;\n let descEl: HTMLTextAreaElement | null = null;\n let tagsEl: HTMLInputElement | null = null;\n let statusEl: HTMLSelectElement | null = null;\n modal.open({\n title: 'Configure artifact',\n width: 560,\n children: (\n <div className=\"artifact-config-form\">\n <label className=\"field-label\">Title</label>\n <input ref={(el) => { titleEl = el; }} className=\"input\" type=\"text\" defaultValue={meta.title} />\n <label className=\"field-label\">Description (markdown)</label>\n <textarea ref={(el) => { descEl = el; }} className=\"textarea\" rows={3} defaultValue={meta.description || ''} />\n <label className=\"field-label\">Tags (comma-separated)</label>\n <input ref={(el) => { tagsEl = el; }} className=\"input\" type=\"text\" defaultValue={(meta.tags || []).join(', ')} />\n <label className=\"field-label\">Status</label>\n <select ref={(el) => { statusEl = el; }} className=\"select\" defaultValue={meta.status}>\n {PLAN_STATUSES.map((s) => (\n <option key={s} value={s}>{s}</option>\n ))}\n </select>\n </div>\n ),\n footer: (\n <div className=\"modal-footer-actions\">\n <Button variant=\"ghost\" onClick={() => modal.close()}>Cancel</Button>\n <Button\n variant=\"primary\"\n onClick={async () => {\n try {\n const tags = (tagsEl?.value || '').split(',').map((t) => t.trim()).filter(Boolean);\n await api.put(`/artifacts/${encodeURIComponent(slug)}`, {\n title: (titleEl?.value || '').trim() || meta.title,\n description: descEl?.value || '',\n tags,\n status: statusEl?.value || meta.status,\n });\n await reload();\n toast.success('Artifact updated.');\n modal.close();\n } catch (err) {\n toast.error(`Save failed: ${(err as Error).message}`);\n }\n }}\n >\n Save\n </Button>\n </div>\n ),\n });\n };\n\n const onAddElement = (worldPos?: { x: number; y: number }) => {\n let typeEl: HTMLSelectElement | null = null;\n let titleEl: HTMLInputElement | null = null;\n let contentEl: HTMLTextAreaElement | null = null;\n modal.open({\n title: 'Add element',\n width: 520,\n children: (\n <div className=\"artifact-element-form\">\n <label className=\"field-label\">Type</label>\n <select ref={(el) => { typeEl = el; }} className=\"select\" defaultValue=\"task\">\n {ELEMENT_TYPES.map((t) => (\n <option key={t.id} value={t.id}>{t.label}</option>\n ))}\n </select>\n <label className=\"field-label\">Title</label>\n <input ref={(el) => { titleEl = el; }} className=\"input\" type=\"text\" placeholder=\"Element title\" autoFocus />\n <label className=\"field-label\">Content (markdown)</label>\n <textarea ref={(el) => { contentEl = el; }} className=\"textarea\" rows={4} placeholder=\"Description…\" />\n </div>\n ),\n footer: (\n <div className=\"modal-footer-actions\">\n <Button variant=\"ghost\" onClick={() => modal.close()}>Cancel</Button>\n <Button\n variant=\"primary\"\n onClick={async (e) => {\n e.preventDefault();\n e.stopPropagation();\n if (worldPos) {\n await addElement({\n type: typeEl?.value || 'note',\n title: (titleEl?.value || 'Untitled').trim(),\n content: contentEl?.value || '',\n x: worldPos.x,\n y: worldPos.y,\n });\n } else {\n const maxX = (canvas?.elements || []).reduce((acc, el) => Math.max(acc, el.x || 0), 0);\n const maxY = (canvas?.elements || []).reduce((acc, el) => Math.max(acc, el.y || 0), 0);\n await addElement({\n type: typeEl?.value || 'note',\n title: (titleEl?.value || 'Untitled').trim(),\n content: contentEl?.value || '',\n x: 80 + Math.min(maxX + 40, 200),\n y: 80 + Math.min(maxY + 40, 200),\n });\n }\n modal.close();\n }}\n >\n <Plus size={12} /> Add\n </Button>\n </div>\n ),\n });\n };\n\n const onCanvasComment = (worldPos?: { x: number; y: number }) => {\n let textEl: HTMLTextAreaElement | null = null;\n modal.open({\n title: 'Add canvas comment',\n width: 480,\n children: (\n <div>\n <label className=\"field-label\">Comment</label>\n <textarea ref={(el) => { textEl = el; }} className=\"textarea\" rows={4} placeholder=\"Comment for the whole artifact…\" autoFocus />\n </div>\n ),\n footer: (\n <div className=\"modal-footer-actions\">\n <Button variant=\"ghost\" onClick={() => modal.close()}>Cancel</Button>\n <Button\n variant=\"primary\"\n onClick={async (e) => {\n e.preventDefault();\n e.stopPropagation();\n const text = (textEl?.value || '').trim();\n if (!text) return;\n await addComment(text, null, worldPos);\n modal.close();\n }}\n >\n <Send size={12} /> Post\n </Button>\n </div>\n ),\n });\n };\n\n if (loading || !canvas || !meta) {\n return (\n <div className=\"view view-artifacts view-artifacts-fullscreen\">\n <PlanEditorHeader\n slug={slug}\n meta={meta || { title: slug, status: 'draft', tags: [] }}\n counts={{ elements: 0, comments: 0 }}\n onBack={onBack}\n onConfigure={() => undefined}\n onAddElement={() => undefined}\n onCanvasComment={() => undefined}\n onRefresh={reload}\n onDelete={onDelete}\n fullscreen={fullscreen}\n setFullscreen={setFullscreen}\n />\n <div className=\"view-loading\" style={{ flex: 1 }}>\n <Spinner size=\"lg\" />\n <p>Loading canvas…</p>\n </div>\n </div>\n );\n }\n\n const visibleComments = selectedElId\n ? canvas.comments.filter((c) => c.elementId === selectedElId)\n : canvas.comments;\n\n return (\n <div className={cn('view view-artifacts view-artifacts-fullscreen', !fullscreen && 'view-artifacts-embedded')}>\n {!fullscreen && (\n <PlanEditorHeader\n slug={slug}\n meta={meta}\n counts={{ elements: canvas.elements.length, comments: totalComments }}\n onBack={onBack}\n onConfigure={onConfigure}\n onAddElement={onAddElement}\n onCanvasComment={onCanvasComment}\n onRefresh={reload}\n onDelete={onDelete}\n fullscreen={fullscreen}\n setFullscreen={setFullscreen}\n />\n )}\n\n <div className=\"artifacts-body\">\n {/* Canvas wrapper with floating controls */}\n <div className=\"artifact-canvas-wrapper\">\n {fullscreen && (\n <div className=\"artifact-canvas-floating-controls\">\n <Button variant=\"ghost\" size=\"sm\" onClick={onBack} title=\"Back to artifacts list\">\n <ArrowLeft size={14} /> Back\n </Button>\n <h3>{meta?.title || slug}</h3>\n {meta && <StatusBadge kind={planStatusKind(meta.status)}>{meta.status}</StatusBadge>}\n <Button variant=\"secondary\" size=\"sm\" onClick={() => onAddElement()}>\n <Plus size={14} /> Element\n </Button>\n <Button variant=\"secondary\" size=\"sm\" onClick={() => onCanvasComment()}>\n <MessageCircle size={14} /> Comment\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={onConfigure} title=\"Configure artifact\" aria-label=\"Configure artifact\">\n <SettingsIcon size={14} />\n </Button>\n </div>\n )}\n\n <CanvasViewport\n canvas={canvas}\n selectedElId={selectedElId}\n onSelect={setSelectedElId}\n onMoveElement={moveElementLocally}\n onMoveEnd={updatePositions}\n onDeleteElement={deleteElement}\n onConnect={(from, to) => addConnection(from, to)}\n onDeleteConnection={deleteConnection}\n onEditElement={(el) => editElementInline(modal, slug, el, updateElement, toast)}\n onContextMenu={(e, worldPos) => {\n e.preventDefault();\n setElementContextMenu(null);\n setContextMenuWorldPos(worldPos);\n setContextMenu({\n x: e.clientX,\n y: e.clientY,\n items: [\n { label: 'Add element', icon: Plus, onClick: () => onAddElement(worldPos) },\n { label: 'Add comment', icon: MessageSquare, onClick: () => onCanvasComment(worldPos) },\n { type: 'separator' },\n { label: 'Configure artifact', icon: SettingsIcon, onClick: onConfigure },\n { label: 'Delete artifact', icon: Trash2, onClick: onDelete },\n ],\n });\n }}\n onElementContextMenu={(e, elementId, _worldPos) => {\n const el = canvas?.elements.find((x) => x.id === elementId);\n if (!el) return;\n setContextMenu(null);\n setElementContextMenu({\n x: e.clientX,\n y: e.clientY,\n items: [\n { label: 'Edit', icon: Pencil, onClick: () => { editElementInline(modal, slug, el, updateElement, toast); } },\n { label: 'Duplicate', icon: Copy, onClick: () => duplicateElement(elementId) },\n { type: 'separator' },\n { label: 'Change type', icon: Layers, onClick: () => {\n // Cycle through types: task -> note -> decision -> question -> task\n const types = ['task', 'note', 'decision', 'question'];\n const currentIdx = types.indexOf(el.type);\n const nextType = types[(currentIdx + 1) % types.length];\n changeElementType(elementId, nextType);\n }},\n { type: 'separator' },\n { label: `Delete`, icon: Trash2, onClick: () => { if (confirm(`Delete \"${el.title || el.type}\"?`)) deleteElement(elementId); } },\n ],\n });\n }}\n />\n\n {/* Canvas-level context menu */}\n <CanvasContextMenu menu={contextMenu} onClose={() => setContextMenu(null)} />\n {/* Element-level context menu */}\n <CanvasContextMenu menu={elementContextMenu} onClose={() => setElementContextMenu(null)} />\n </div>\n\n {showComments && (\n <CommentsPanel\n slug={slug}\n comments={visibleComments}\n selectedElId={selectedElId}\n onAdd={(text) => addComment(text, selectedElId)}\n onDelete={deleteComment}\n onClose={() => {\n setShowComments(false);\n setSelectedElId(null);\n }}\n />\n )}\n </div>\n </div>\n );\n}\n\nfunction PlanEditorHeader({\n slug,\n meta,\n counts,\n onBack,\n onConfigure,\n onAddElement,\n onCanvasComment,\n onRefresh,\n onDelete,\n fullscreen,\n setFullscreen,\n}: {\n slug: string;\n meta: { title: string; status: string; tags: string[] };\n counts: { elements: number; comments: number };\n onBack: () => void;\n onConfigure: () => void;\n onAddElement: () => void;\n onCanvasComment: () => void;\n onRefresh: () => void;\n onDelete: () => void;\n fullscreen: boolean;\n setFullscreen: (v: boolean) => void;\n}) {\n const kind = planStatusKind(meta.status);\n return (\n <header className=\"artifacts-editor-bar\">\n <div className=\"artifacts-editor-bar-left\">\n <Button variant=\"ghost\" size=\"sm\" onClick={onBack} title=\"Back to artifacts list\">\n <ArrowLeft size={14} /> Back\n </Button>\n <div className=\"artifacts-editor-meta\">\n <span className=\"artifacts-editor-title\">{meta.title || slug}</span>\n <span className=\"artifacts-editor-slug mono\">{slug}</span>\n <StatusBadge kind={kind}>{meta.status}</StatusBadge>\n </div>\n </div>\n <div className=\"artifacts-editor-bar-right\">\n <span className=\"muted text-sm\">\n {counts.elements} element{counts.elements === 1 ? '' : 's'} · {counts.comments} comment{counts.comments === 1 ? '' : 's'}\n </span>\n <Button variant=\"secondary\" size=\"sm\" onClick={onAddElement}>\n <Plus size={14} /> Element\n </Button>\n <Button variant=\"secondary\" size=\"sm\" onClick={onCanvasComment}>\n <MessageCircle size={14} /> Comment\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={onConfigure} title=\"Configure artifact\" aria-label=\"Configure artifact\">\n <SettingsIcon size={14} />\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={onRefresh} title=\"Refresh canvas\" aria-label=\"Refresh canvas\">\n <RefreshCw size={14} />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setFullscreen(!fullscreen)}\n title={fullscreen ? 'Exit fullscreen' : 'Enter fullscreen'}\n aria-label={fullscreen ? 'Exit fullscreen' : 'Enter fullscreen'}\n >\n {fullscreen ? <Minimize2 size={14} /> : <Maximize2 size={14} />}\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={onDelete} title=\"Delete artifact\" aria-label=\"Delete artifact\">\n <Trash2 size={14} />\n </Button>\n </div>\n </header>\n );\n}\n\nfunction editElementInline(\n modal: ReturnType<typeof useModal>,\n slug: string,\n el: CanvasElement,\n updateElement: (id: string, body: Partial<CanvasElement>) => Promise<void>,\n toast: ReturnType<typeof useToast>,\n) {\n let typeEl: HTMLSelectElement | null = null;\n let titleEl: HTMLInputElement | null = null;\n let contentEl: HTMLTextAreaElement | null = null;\n let statusEl: HTMLInputElement | null = null;\n modal.open({\n title: `Edit ${el.title || el.type}`,\n width: 520,\n children: (\n <div className=\"artifact-element-form\">\n <label className=\"field-label\">Type</label>\n <select ref={(el2) => { typeEl = el2; }} className=\"select\" defaultValue={el.type}>\n {ELEMENT_TYPES.map((t) => (\n <option key={t.id} value={t.id}>{t.label}</option>\n ))}\n </select>\n <label className=\"field-label\">Title</label>\n <input ref={(el2) => { titleEl = el2; }} className=\"input\" type=\"text\" defaultValue={el.title} />\n <label className=\"field-label\">Status</label>\n <input ref={(el2) => { statusEl = el2; }} className=\"input\" type=\"text\" defaultValue={el.status} placeholder=\"open / done / blocked …\" />\n <label className=\"field-label\">Content (markdown)</label>\n <textarea ref={(el2) => { contentEl = el2; }} className=\"textarea\" rows={5} defaultValue={el.content} />\n </div>\n ),\n footer: (\n <div className=\"modal-footer-actions\">\n <Button variant=\"ghost\" onClick={() => modal.close()}>Cancel</Button>\n <Button\n variant=\"primary\"\n onClick={async () => {\n try {\n await updateElement(el.id, {\n type: typeEl?.value || el.type,\n title: titleEl?.value ?? el.title,\n content: contentEl?.value ?? el.content,\n status: statusEl?.value || el.status,\n });\n toast.success('Element saved.');\n modal.close();\n } catch (err) {\n toast.error(`Save failed: ${(err as Error).message}`);\n }\n }}\n >\n Save\n </Button>\n </div>\n ),\n });\n}\n\n// ── Canvas viewport ───────────────────────────────────────────────────\n\ntype ViewportProps = {\n canvas: Canvas;\n selectedElId: string | null;\n onSelect: (id: string | null) => void;\n onMoveElement: (id: string, x: number, y: number) => void;\n onMoveEnd: (positions: { id: string; x: number; y: number }[]) => void;\n onDeleteElement: (id: string) => void;\n onConnect: (from: string, to: string) => void;\n onDeleteConnection: (id: string) => void;\n onEditElement: (el: CanvasElement) => void;\n onContextMenu?: (e: React.MouseEvent, worldPos: { x: number; y: number }) => void;\n // v3.7.0 — Element-specific context menu (right-click on an element)\n onElementContextMenu?: (e: React.MouseEvent, elementId: string, worldPos: { x: number; y: number }) => void;\n fitToView?: () => void;\n};\n\nfunction CanvasViewport({\n canvas,\n selectedElId,\n onSelect,\n onMoveElement,\n onMoveEnd,\n onDeleteElement,\n onConnect,\n onDeleteConnection,\n onEditElement,\n onContextMenu,\n onElementContextMenu,\n}: ViewportProps) {\n const rootRef = useRef<HTMLDivElement>(null);\n const innerRef = useRef<HTMLDivElement>(null);\n const elementsRef = useRef(canvas.elements);\n const stateRef = useRef({\n panning: false,\n startX: 0,\n startY: 0,\n ox: canvas.viewport.x || 0,\n oy: canvas.viewport.y || 0,\n scale: canvas.viewport.zoom || 1,\n dragging: null as null | { id: string; offsetX: number; offsetY: number; moved: boolean; origX: number; origY: number },\n connecting: null as null | { fromId: string; x: number; y: number },\n });\n\n useEffect(() => {\n elementsRef.current = canvas.elements;\n }, [canvas.elements]);\n\n useEffect(() => {\n const root = rootRef.current;\n const inner = innerRef.current;\n if (!root || !inner) return undefined;\n const apply = () => {\n const s = stateRef.current;\n inner.style.transform = `translate(${s.ox}px, ${s.oy}px) scale(${s.scale})`;\n };\n apply();\n\n const screenToWorld = (clientX: number, clientY: number) => {\n const rect = inner.getBoundingClientRect();\n const s = stateRef.current;\n // rect.left/rect.top is the *post-transform* top-left; account for scale\n const x = (clientX - rect.left) / s.scale;\n const y = (clientY - rect.top) / s.scale;\n return { x, y };\n };\n\n const onMouseDown = (e: MouseEvent) => {\n if (e.button === 2) return;\n const t = e.target as HTMLElement;\n if (\n t === root ||\n t.classList.contains('canvas-grid-bg') ||\n t.classList.contains('canvas-inner')\n ) {\n stateRef.current.panning = true;\n stateRef.current.startX = e.clientX - stateRef.current.ox;\n stateRef.current.startY = e.clientY - stateRef.current.oy;\n root.style.cursor = 'grabbing';\n return;\n }\n const elCard = t.closest('.canvas-element') as HTMLElement | null;\n if (elCard) {\n const id = elCard.dataset.elementId;\n if (!id) return;\n const headerHit = !!t.closest('.canvas-element-head');\n const handleHit = !!t.closest('.canvas-element-handle');\n if (headerHit || handleHit) {\n const world = screenToWorld(e.clientX, e.clientY);\n const el = elementsRef.current.find((x) => x.id === id);\n if (!el) return;\n stateRef.current.dragging = {\n id,\n offsetX: world.x - (el.x || 0),\n offsetY: world.y - (el.y || 0),\n moved: false,\n origX: el.x || 0,\n origY: el.y || 0,\n };\n onSelect(id);\n e.preventDefault();\n }\n }\n };\n const onMouseMove = (e: MouseEvent) => {\n const s = stateRef.current;\n if (s.panning) {\n s.ox = e.clientX - s.startX;\n s.oy = e.clientY - s.startY;\n apply();\n return;\n }\n if (s.dragging) {\n const world = screenToWorld(e.clientX, e.clientY);\n const newX = Math.max(0, world.x - s.dragging.offsetX);\n const newY = Math.max(0, world.y - s.dragging.offsetY);\n if (!s.dragging.moved) {\n const dx = Math.abs(newX - s.dragging.origX);\n const dy = Math.abs(newY - s.dragging.origY);\n if (dx < 2 && dy < 2) return;\n }\n s.dragging.moved = true;\n onMoveElement(s.dragging.id, newX, newY);\n return;\n }\n if (s.connecting) {\n const inner2 = innerRef.current;\n if (!inner2) return;\n const world = screenToWorld(e.clientX, e.clientY);\n s.connecting.x = world.x;\n s.connecting.y = world.y;\n // Trigger a custom event so the connecting SVG re-renders.\n inner2.dispatchEvent(new CustomEvent('canvas-move', { detail: { x: world.x, y: world.y } }));\n }\n };\n const onMouseUp = () => {\n const s = stateRef.current;\n if (s.panning) {\n s.panning = false;\n root.style.cursor = '';\n }\n if (s.dragging) {\n if (s.dragging.moved) {\n const el = elementsRef.current.find((x) => x.id === s.dragging?.id);\n if (el) {\n onMoveEnd([{ id: el.id, x: el.x || 0, y: el.y || 0 }]);\n }\n }\n s.dragging = null;\n }\n if (s.connecting) {\n s.connecting = null;\n innerRef.current?.dispatchEvent(new CustomEvent('canvas-move', { detail: { x: 0, y: 0 } }));\n }\n };\n const onWheel = (e: WheelEvent) => {\n e.preventDefault();\n const delta = e.deltaY > 0 ? 0.9 : 1.1;\n const next = Math.min(\n Math.max(stateRef.current.scale * delta, 0.25),\n 2.5,\n );\n stateRef.current.scale = next;\n apply();\n };\n root.addEventListener('mousedown', onMouseDown);\n window.addEventListener('mousemove', onMouseMove);\n window.addEventListener('mouseup', onMouseUp);\n root.addEventListener('wheel', onWheel, { passive: false });\n return () => {\n root.removeEventListener('mousedown', onMouseDown);\n window.removeEventListener('mousemove', onMouseMove);\n window.removeEventListener('mouseup', onMouseUp);\n root.removeEventListener('wheel', onWheel);\n };\n }, [onMoveElement, onMoveEnd, onSelect]);\n\n const fitToView = () => {\n if (!rootRef.current || canvas.elements.length === 0) {\n stateRef.current.ox = 0;\n stateRef.current.oy = 0;\n stateRef.current.scale = 1;\n const inner = innerRef.current;\n if (inner) {\n inner.style.transform = `translate(0px, 0px) scale(1)`;\n }\n return;\n }\n const bbox = canvas.elements.reduce(\n (acc, el) => {\n const ex = el.x || 0;\n const ey = el.y || 0;\n const ex2 = ex + (el.width || 240);\n const ey2 = ey + (el.height || 120);\n return {\n minX: Math.min(acc.minX, ex),\n minY: Math.min(acc.minY, ey),\n maxX: Math.max(acc.maxX, ex2),\n maxY: Math.max(acc.maxY, ey2),\n };\n },\n { minX: Infinity, minY: Infinity, maxX: -Infinity, maxY: -Infinity },\n );\n const pad = 80;\n const root = rootRef.current;\n const w = root.clientWidth - pad * 2;\n const h = root.clientHeight - pad * 2;\n const bw = bbox.maxX - bbox.minX;\n const bh = bbox.maxY - bbox.minY;\n const scale = Math.min(w / Math.max(bw, 1), h / Math.max(bh, 1), 1.5);\n const ox = -bbox.minX * scale + pad;\n const oy = -bbox.minY * scale + pad;\n stateRef.current.ox = ox;\n stateRef.current.oy = oy;\n stateRef.current.scale = scale;\n const inner = innerRef.current;\n if (inner) {\n inner.style.transform = `translate(${ox}px, ${oy}px) scale(${scale})`;\n }\n };\n\n return (\n <div className=\"artifacts-canvas-wrap\">\n <div className=\"canvas-toolbar\">\n <button type=\"button\" className=\"icon-btn\" title=\"Fit to view\" aria-label=\"Fit canvas to view\" onClick={fitToView}>\n <Maximize2 size={14} />\n </button>\n <button\n type=\"button\"\n className=\"icon-btn\"\n title=\"Reset zoom\"\n aria-label=\"Reset canvas zoom\"\n onClick={() => {\n stateRef.current.ox = 0;\n stateRef.current.oy = 0;\n stateRef.current.scale = 1;\n const inner = innerRef.current;\n if (inner) inner.style.transform = 'translate(0px, 0px) scale(1)';\n }}\n >\n <Circle size={14} />\n </button>\n <span className=\"muted text-sm\" style={{ marginLeft: 'auto' }}>\n Pan: drag empty · Zoom: scroll · Drag element header to move · Double-click to edit · Right-click element for actions\n </span>\n </div>\n <div className=\"canvas-root\" ref={rootRef} onContextMenu={(e) => {\n e.preventDefault();\n const rect = innerRef.current?.getBoundingClientRect();\n const s = stateRef.current;\n if (!rect) return;\n const worldPos = { x: (e.clientX - rect.left) / s.scale, y: (e.clientY - rect.top) / s.scale };\n onContextMenu?.(e, worldPos);\n }}>\n <div className=\"canvas-grid-bg\" />\n <div className=\"canvas-inner\" ref={innerRef}>\n {canvas.elements.length === 0 ? (\n <div className=\"canvas-empty\">\n <EmptyState\n icon={<MapIcon size={32} />}\n title=\"No elements yet\"\n message=\"Add an element from the toolbar above to get started.\"\n />\n </div>\n ) : (\n <>\n <ConnectionsLayer\n canvas={canvas}\n onDeleteConnection={onDeleteConnection}\n />\n {canvas.elements.map((el) => (\n <CanvasElementView\n key={el.id}\n element={el}\n selected={selectedElId === el.id}\n commentCount={canvas.comments.filter((c) => c.elementId === el.id).length}\n onSelect={() => onSelect(el.id)}\n onEdit={() => onEditElement(el)}\n onDelete={() => onDeleteElement(el.id)}\n onContextMenu={onElementContextMenu ? (e) => {\n e.preventDefault();\n e.stopPropagation();\n const rect = innerRef.current?.getBoundingClientRect();\n if (!rect) return;\n const s = stateRef.current;\n const worldPos = { x: (e.clientX - rect.left) / s.scale, y: (e.clientY - rect.top) / s.scale };\n onElementContextMenu(e, el.id, worldPos);\n } : undefined}\n />\n ))}\n </>\n )}\n </div>\n </div>\n </div>\n );\n}\n\nfunction CanvasElementView({\n element,\n selected,\n commentCount,\n onSelect,\n onEdit,\n onDelete,\n onContextMenu,\n}: {\n element: CanvasElement;\n selected: boolean;\n commentCount: number;\n onSelect: () => void;\n onEdit: () => void;\n onDelete: () => void;\n onContextMenu?: (e: React.MouseEvent) => void;\n}) {\n const x = element.x || 0;\n const y = element.y || 0;\n const w = element.width || 240;\n const h = element.height || 120;\n const color = elementColor(element.type);\n return (\n <div\n className={cn('canvas-element', selected && 'canvas-element-selected')}\n data-element-id={element.id}\n style={{\n left: x,\n top: y,\n width: w,\n minHeight: h,\n borderColor: color,\n }}\n onClick={(e) => {\n e.stopPropagation();\n onSelect();\n }}\n onDoubleClick={(e) => {\n e.stopPropagation();\n onEdit();\n }}\n onContextMenu={(e) => {\n if (onContextMenu) {\n e.stopPropagation();\n onContextMenu(e);\n } else {\n e.preventDefault();\n if (confirm(`Delete element \"${element.title || element.type}\"?`)) {\n onDelete();\n }\n }\n }}\n >\n <div className=\"canvas-element-head\" style={{ background: `color-mix(in srgb, ${color} 12%, transparent)` }}>\n <div className=\"canvas-element-type\">\n <ElementIcon type={element.type} size={12} />\n <span style={{ color }}>{element.type}</span>\n </div>\n <div className=\"canvas-element-actions\">\n {commentCount > 0 && (\n <span className=\"canvas-element-badge\" title={`${commentCount} comments`}>\n <MessageCircle size={10} />\n {commentCount}\n </span>\n )}\n <button type=\"button\" className=\"canvas-element-handle\" title=\"Drag to move\" aria-label=\"Drag\">\n ⋮⋮\n </button>\n </div>\n </div>\n <div className=\"canvas-element-title\">{element.title || 'Untitled'}</div>\n {element.content && (\n <div className=\"canvas-element-content\">{truncate(element.content, 240)}</div>\n )}\n {element.status && element.status !== 'open' && (\n <div className=\"canvas-element-status\">\n <StatusBadge kind={element.status === 'done' ? 'success' : element.status === 'blocked' ? 'error' : 'info'}>\n {element.status}\n </StatusBadge>\n </div>\n )}\n </div>\n );\n}\n\nfunction ConnectionsLayer({\n canvas,\n onDeleteConnection,\n}: {\n canvas: Canvas;\n onDeleteConnection: (id: string) => void;\n}) {\n if (canvas.connections.length === 0) return null;\n const els = canvas.elements;\n // Compute bounding box\n const bbox = els.reduce(\n (acc, el) => {\n const ex = el.x || 0;\n const ey = el.y || 0;\n const ex2 = ex + (el.width || 240);\n const ey2 = ey + (el.height || 120);\n return {\n minX: Math.min(acc.minX, ex),\n minY: Math.min(acc.minY, ey),\n maxX: Math.max(acc.maxX, ex2),\n maxY: Math.max(acc.maxY, ey2),\n };\n },\n { minX: 0, minY: 0, maxX: 0, maxY: 0 },\n );\n const pad = 80;\n const w = bbox.maxX - bbox.minX + pad * 2;\n const h = bbox.maxY - bbox.minY + pad * 2;\n const ox = -bbox.minX + pad;\n const oy = -bbox.minY + pad;\n return (\n <svg\n className=\"canvas-connections\"\n width={w}\n height={h}\n style={{ left: bbox.minX - pad, top: bbox.minY - pad }}\n >\n <defs>\n <marker id=\"artifact-arrow\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"6\" markerHeight=\"6\" orient=\"auto-start-reverse\">\n <path d=\"M 0 0 L 10 5 L 0 10 z\" fill=\"var(--accent)\" />\n </marker>\n </defs>\n {canvas.connections.map((c) => {\n const from = els.find((e) => e.id === c.from || e.id === c.fromElementId);\n const to = els.find((e) => e.id === c.to || e.id === c.toElementId);\n if (!from || !to) return null;\n const x1 = ox + (from.x || 0) + (from.width || 240) / 2;\n const y1 = oy + (from.y || 0) + (from.height || 120);\n const x2 = ox + (to.x || 0) + (to.width || 240) / 2;\n const y2 = oy + (to.y || 0);\n const midX = (x1 + x2) / 2;\n const midY = (y1 + y2) / 2;\n return (\n <g key={c.id} className=\"canvas-connection\" onClick={() => onDeleteConnection(c.id)}>\n <line x1={x1} y1={y1} x2={x2} y2={y2} stroke=\"var(--accent)\" strokeWidth={1.5} markerEnd=\"url(#artifact-arrow)\" />\n {c.label && (\n <text x={midX} y={midY} className=\"canvas-connection-label\" textAnchor=\"middle\">\n {c.label}\n </text>\n )}\n </g>\n );\n })}\n </svg>\n );\n}\n\n// ── Comments panel ────────────────────────────────────────────────────\n\nfunction CommentsPanel({\n slug,\n comments,\n selectedElId,\n onAdd,\n onDelete,\n onClose,\n}: {\n slug: string;\n comments: CanvasComment[];\n selectedElId: string | null;\n onAdd: (text: string) => void;\n onDelete: (cid: string) => void;\n onClose: () => void;\n}) {\n const [text, setText] = useState('');\n return (\n <aside className=\"artifacts-comments-panel\">\n <header className=\"artifacts-comments-panel-head\">\n <h3 className=\"card-title\">\n <MessageCircle size={14} />\n {selectedElId ? 'Element comments' : 'Canvas comments'}\n </h3>\n <button type=\"button\" className=\"icon-btn\" onClick={onClose} title=\"Close panel\" aria-label=\"Close\">\n <X size={14} />\n </button>\n </header>\n <div className=\"artifacts-comments-panel-list\">\n {comments.length === 0 ? (\n <p className=\"muted text-sm\" style={{ padding: 'var(--space-4)' }}>\n {selectedElId ? 'No comments on this element yet.' : 'No comments on this artifact yet.'}\n </p>\n ) : (\n comments.map((c) => (\n <div key={c.id} className=\"artifact-comment\">\n <div className=\"artifact-comment-head\">\n <span className=\"artifact-comment-author mono\">{c.author}</span>\n <span className=\"artifact-comment-time tabular-nums muted\">{formatRelative(c.created)}</span>\n <button\n type=\"button\"\n className=\"icon-btn icon-btn-danger\"\n aria-label=\"Delete comment\"\n onClick={() => onDelete(c.id)}\n title=\"Delete\"\n >\n <Trash2 size={10} />\n </button>\n </div>\n <div className=\"artifact-comment-text\">{c.text}</div>\n </div>\n ))\n )}\n </div>\n <form\n className=\"artifacts-comments-panel-form\"\n onSubmit={(e) => {\n e.preventDefault();\n if (!text.trim()) return;\n onAdd(text.trim());\n setText('');\n }}\n >\n <textarea\n className=\"textarea\"\n rows={2}\n placeholder={selectedElId ? 'Add a comment to this element…' : 'Add a canvas comment…'}\n value={text}\n onChange={(e) => setText(e.target.value)}\n />\n <Button variant=\"primary\" size=\"sm\" type=\"submit\" disabled={!text.trim()}>\n <Send size={12} /> Post\n </Button>\n </form>\n </aside>\n );\n}\n","// src/components/Tag.tsx — pill for tags.\n\nimport type { ReactNode } from 'react';\nimport { cn } from '../lib/utils';\n\nexport type TagProps = {\n children: ReactNode;\n className?: string;\n onRemove?: () => void;\n};\n\nexport function Tag({ children, className, onRemove }: TagProps) {\n return (\n <span className={cn('tag', className)}>\n {children}\n {onRemove && (\n <button\n type=\"button\"\n className=\"tag-remove\"\n aria-label={`Remove ${typeof children === 'string' ? children : 'tag'}`}\n onClick={onRemove}\n >\n ×\n </button>\n )}\n </span>\n );\n}\n","// src/components/BgStatusBadge.tsx — status pill for background agent instances.\n// Maps BackgroundStatus values to badge kinds from StatusBadge.\n\nimport { StatusBadge, type StatusBadgeProps } from './StatusBadge';\n\nconst STATUS_KIND: Record<string, StatusBadgeProps['kind']> = {\n pending: 'info',\n running: 'accent',\n done: 'success',\n failed: 'error',\n killed: 'neutral',\n timed_out: 'warning',\n};\n\nconst STATUS_LABELS: Record<string, string> = {\n pending: 'Pending',\n running: 'Running',\n done: 'Done',\n failed: 'Failed',\n killed: 'Killed',\n timed_out: 'Timed out',\n};\n\nexport function BgStatusBadge({ status, dot }: { status: string; dot?: boolean }) {\n const kind = STATUS_KIND[status] || 'neutral';\n const label = STATUS_LABELS[status] || status;\n return (\n <StatusBadge kind={kind} dot={dot}>\n {label}\n </StatusBadge>\n );\n}\n","// src/components/KillConfirmDialog.tsx — confirmation dialog for killing bg instances.\n// Provides both a JSX component and a convenience `openKillConfirmDialog` function.\n\nimport { Button } from './Button';\nimport type { ModalApi } from './Modal';\n\nexport type KillConfirmDialogProps = {\n instanceId: string;\n instanceName?: string;\n onConfirm: () => void | Promise<void>;\n onClose: () => void;\n};\n\n/**\n * Render inline inside a modal body. Usage:\n *\n * modal.open({\n * title: 'Kill background instance?',\n * children: (\n * <KillConfirmDialog\n * instanceId=\"bgr_abc\"\n * onConfirm={async () => { await killIt(); modal.close(); }}\n * onClose={() => modal.close()}\n * />\n * ),\n * });\n */\nexport function KillConfirmDialog({ instanceId, instanceName, onConfirm, onClose }: KillConfirmDialogProps) {\n return (\n <div>\n <p style={{ marginBottom: 16, lineHeight: 1.6 }}>\n Instance <code>{instanceId}</code>\n {instanceName ? <> ({instanceName})</> : null} will be terminated.\n This cannot be undone.\n </p>\n <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>\n <Button variant=\"ghost\" onClick={onClose}>Cancel</Button>\n <Button\n variant=\"danger\"\n onClick={async () => {\n await onConfirm();\n onClose();\n }}\n >\n Kill\n </Button>\n </div>\n </div>\n );\n}\n\n/**\n * Convenience wrapper: open a kill-confirmation modal programmatically.\n * Calls `DELETE /api/background/${instanceId}` on confirm and shows a toast.\n */\nexport function openKillConfirmDialog(\n modal: ModalApi,\n toast: { success: (msg: string, duration?: number) => void; error: (msg: string) => void },\n instanceId: string,\n instanceName?: string,\n onSuccess?: () => void,\n) {\n modal.open({\n title: `Kill instance?`,\n width: 400,\n children: (\n <KillConfirmDialog\n instanceId={instanceId}\n instanceName={instanceName}\n onConfirm={async () => {\n try {\n const r = await fetch(`/api/background/${encodeURIComponent(instanceId)}`, { method: 'DELETE' });\n const data = await r.json();\n if (data.ok) {\n toast.success(`Instance ${instanceId} killed.`);\n onSuccess?.();\n } else {\n toast.error(`Kill failed: ${data.error || 'unknown error'}`);\n }\n } catch (err) {\n toast.error(`Kill failed: ${(err as Error).message}`);\n }\n }}\n onClose={() => modal.close()}\n />\n ),\n });\n}\n","// src/web/components/ArtifactViewer.tsx — modal viewer for rendered HTML artifacts.\nimport { useEffect, useState } from 'react';\nimport { X, ExternalLink, Download, FileText } from 'lucide-react';\nimport { useModal } from './Modal';\nimport { Spinner } from './Spinner';\nimport { api } from '../lib/api';\n\ntype ArtifactMeta = {\n id: string;\n name: string;\n contentType: string;\n size: number;\n createdAt: string;\n};\n\ntype Props = {\n artifactId: string;\n onClose: () => void;\n};\n\nexport function ArtifactViewer({ artifactId, onClose }: Props) {\n const [meta, setMeta] = useState<ArtifactMeta | null>(null);\n const [content, setContent] = useState<string>('');\n const [loading, setLoading] = useState(true);\n\n useEffect(() => {\n let cancelled = false;\n (async () => {\n setLoading(true);\n try {\n const [metaData, contentData] = await Promise.all([\n api.get<ArtifactMeta>(`/artifacts/${encodeURIComponent(artifactId)}`),\n fetchRawContent(artifactId),\n ]);\n if (!cancelled) {\n setMeta(metaData);\n setContent(contentData);\n }\n } catch (err) {\n if (!cancelled) {\n console.error('Failed to load artifact:', err);\n }\n } finally {\n if (!cancelled) setLoading(false);\n }\n })();\n return () => { cancelled = true; };\n }, [artifactId]);\n\n return (\n <div className=\"modal-backdrop\" onClick={(e) => { e.stopPropagation(); if (e.target === e.currentTarget) onClose(); }}>\n <div className=\"modal artifact-viewer-modal\" role=\"dialog\" aria-modal=\"true\">\n <header className=\"modal-header\">\n <div className=\"modal-title-group\">\n <FileText size={16} />\n <h2 className=\"modal-title\">{meta?.name || 'Artifact'}</h2>\n {meta && (\n <span className=\"artifact-viewer-meta muted\">\n {meta.contentType} · {formatBytes(meta.size)}\n </span>\n )}\n </div>\n <div className=\"modal-header-actions\">\n {meta && (\n <>\n <a\n href={getArtifactContentUrl(artifactId)}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"icon-btn\"\n aria-label=\"Open artifact in new tab\"\n title=\"Open in new tab\"\n >\n <ExternalLink size={16} />\n </a>\n <a\n href={getArtifactContentUrl(artifactId)}\n download={meta.name || 'artifact.html'}\n className=\"icon-btn\"\n aria-label=\"Download artifact\"\n title=\"Download\"\n >\n <Download size={16} />\n </a>\n </>\n )}\n <button type=\"button\" className=\"icon-btn\" aria-label=\"Close\" onClick={onClose}>\n <X size={16} />\n </button>\n </div>\n </header>\n <div className=\"modal-body artifact-viewer-body\">\n {loading ? (\n <div className=\"artifact-viewer-loading\">\n <Spinner />\n <span className=\"muted\">Loading artifact…</span>\n </div>\n ) : content ? (\n <iframe\n srcDoc={content}\n className=\"artifact-viewer-iframe\"\n sandbox=\"allow-scripts allow-forms allow-popups allow-same-origin\"\n title={meta?.name || 'Artifact'}\n />\n ) : (\n <div className=\"artifact-viewer-empty muted\">\n <FileText size={32} />\n <p>No content available.</p>\n </div>\n )}\n </div>\n </div>\n </div>\n );\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\n// Fetch raw text content — bypasses the JSON api wrapper.\nasync function fetchRawContent(artifactId: string): Promise<string> {\n const r = await fetch(getArtifactContentUrl(artifactId));\n if (!r.ok) throw new Error(`HTTP ${r.status}`);\n return r.text();\n}\n\nfunction getArtifactContentUrl(artifactId: string): string {\n return api.urlWithToken(`/artifacts/${encodeURIComponent(artifactId)}/content`);\n}\n\n// v3.5.7 — Open the artifact in a new browser tab at full window size.\n// The artifact's own HTML renders edge-to-edge, which is what users want\n// for visual artifacts (they're meant to be viewed, not crammed in a modal).\nexport function openArtifactViewer(\n _modal: ReturnType<typeof useModal>,\n artifactId: string,\n): void {\n const url = getArtifactContentUrl(artifactId);\n window.open(url, '_blank', 'noopener,noreferrer');\n}\n","// src/web/components/tasks/BacklogPanel.tsx — v3.22\n// Backlog panel: lists parked tasks, promote individually or all-at-once.\nimport { useEffect, useState } from 'react';\nimport {\n ArrowUp,\n Trash2,\n Sparkles,\n RefreshCw,\n Inbox,\n} from 'lucide-react';\nimport { Button } from '../Button';\nimport { useToast } from '../Toast';\nimport { api } from '../../lib/api';\nimport { formatRelative } from '../../lib/utils';\nimport type { Task, Agent } from '../../lib/types';\n\ntype BacklogItemProps = {\n task: Task;\n agents: Agent[];\n onPromote: (id: string) => void;\n onDelete: (id: string) => void;\n onEdit: (task: Task) => void;\n onRefresh: () => Promise<void>;\n};\n\nfunction BacklogItem({ task, agents, onPromote, onDelete, onEdit, onRefresh }: BacklogItemProps) {\n const toast = useToast();\n\n const handlePromote = async () => {\n try {\n await api.post(`/tasks/${encodeURIComponent(task.id)}/promote`);\n toast.success('Promoted to queued.', 1500);\n onPromote(task.id);\n } catch (err) {\n toast.error(`Promote failed: ${(err as Error).message}`);\n }\n };\n\n const handleDelete = async () => {\n if (!confirm('Delete this task?')) return;\n try {\n await api.del(`/tasks/${encodeURIComponent(task.id)}`);\n toast.success('Deleted.', 1500);\n onDelete(task.id);\n } catch (err) {\n toast.error(`Delete failed: ${(err as Error).message}`);\n }\n };\n\n const priorityDot: Record<string, string> = {\n high: 'var(--warning)',\n normal: 'var(--info)',\n low: 'var(--muted)',\n };\n\n return (\n <div className=\"backlog-item\" data-task-id={task.id}>\n <div className=\"backlog-item-head\">\n <span\n className=\"priority-dot\"\n style={{ background: priorityDot[task.priority] || 'var(--info)' }}\n />\n <span className=\"backlog-item-title\">{task.title}</span>\n {task.assignee && (\n <span className=\"backlog-item-badge\">@{task.assignee}</span>\n )}\n {task.tags?.length > 0 && (\n <span className=\"backlog-item-badge\">{task.tags.join(', ')}</span>\n )}\n </div>\n {task.description && (\n <div className=\"backlog-item-desc\">{task.description.slice(0, 120)}</div>\n )}\n <div className=\"backlog-item-footer\">\n <span className=\"muted text-sm tabular-nums\">\n {formatRelative(task.createdAt)}\n </span>\n <div className=\"backlog-item-actions\">\n <button\n type=\"button\"\n className=\"icon-btn\"\n title=\"Promote to queued\"\n onClick={handlePromote}\n >\n <ArrowUp size={13} />\n </button>\n <button\n type=\"button\"\n className=\"icon-btn\"\n title=\"Edit\"\n onClick={() => onEdit(task)}\n >\n <Sparkles size={13} />\n </button>\n <button\n type=\"button\"\n className=\"icon-btn icon-btn-danger\"\n title=\"Delete\"\n onClick={handleDelete}\n >\n <Trash2 size={13} />\n </button>\n </div>\n </div>\n </div>\n );\n}\n\ntype Props = {\n /** Current list of agents for the edit modal. */\n agents: Agent[];\n /** Called after any mutation so the parent can refresh snapshot. */\n onRefresh: () => Promise<void>;\n};\n\nexport function BacklogPanel({ agents, onRefresh }: Props) {\n const toast = useToast();\n const [tasks, setTasks] = useState<Task[]>([]);\n const [loading, setLoading] = useState(false);\n\n const load = async () => {\n try {\n setLoading(true);\n const r = await api.get<{ tasks: Task[] }>('/tasks/backlog');\n setTasks(Array.isArray(r.tasks) ? r.tasks : []);\n } catch (err) {\n toast.error(`Backlog load failed: ${(err as Error).message}`);\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => { load(); }, []);\n\n const handlePromote = async (id: string) => {\n setTasks((cur) => cur.filter((t) => t.id !== id));\n await onRefresh();\n };\n\n const handleDelete = async (id: string) => {\n setTasks((cur) => cur.filter((t) => t.id !== id));\n await onRefresh();\n };\n\n const handleEdit = (_task: Task) => {\n // Editing is wired through the parent Tasks view's modal helper.\n // Keep this no-op so the icon click is at least visible; the parent\n // provides the real edit affordance via the kanban.\n };\n\n const handlePromoteAll = async () => {\n if (tasks.length === 0) return;\n try {\n const r = await api.post<{ affected: { id: string; ok: boolean }[] }>('/tasks/promote-batch', {\n ids: tasks.map((t) => t.id),\n });\n const ok = r.affected?.filter((a) => a.ok).length ?? 0;\n toast.success(`Promoted ${ok} task(s).`, 2000);\n setTasks([]);\n await onRefresh();\n } catch (err) {\n toast.error(`Promote all failed: ${(err as Error).message}`);\n }\n };\n\n return (\n <div className=\"backlog-panel\">\n <div className=\"backlog-panel-header\">\n <span className=\"backlog-panel-title\">\n <Inbox size={15} />\n Backlog ({tasks.length})\n </span>\n <div className=\"backlog-panel-header-actions\">\n {tasks.length > 0 && (\n <Button variant=\"ghost\" size=\"sm\" onClick={handlePromoteAll} title=\"Promote all to queued\">\n <ArrowUp size={12} /> Promote all\n </Button>\n )}\n <Button variant=\"ghost\" size=\"sm\" onClick={load} title=\"Refresh backlog\" aria-label=\"Refresh backlog\">\n <RefreshCw size={12} className={loading ? 'animate-spin' : ''} />\n </Button>\n </div>\n </div>\n\n {loading ? (\n <div className=\"backlog-empty\">Loading…</div>\n ) : tasks.length === 0 ? (\n <div className=\"backlog-empty\">\n <Inbox size={28} />\n <span>Backlog is empty.</span>\n </div>\n ) : (\n <div className=\"backlog-list\">\n {tasks.map((t) => (\n <BacklogItem\n key={t.id}\n task={t}\n agents={agents}\n onPromote={handlePromote}\n onDelete={handleDelete}\n onEdit={handleEdit}\n onRefresh={onRefresh}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n","// src/views/Tasks.tsx — v3.1.0 task board: archive, filters, sort, bulk, recurring, timers, comments, real-time.\nimport { useEffect, useMemo, useState } from 'react';\nimport {\n CheckSquare,\n Plus,\n Trash2,\n ChevronLeft,\n ChevronRight,\n Search,\n X as XIcon,\n Clock,\n PlayCircle,\n PauseCircle,\n MessageSquare,\n Activity,\n Link2,\n Calendar,\n Paperclip,\n Tag as TagIcon,\n Archive,\n ArchiveRestore,\n Filter,\n ArrowUpDown,\n Square,\n CheckSquare as CheckSquareIcon,\n Bot,\n RotateCw,\n AlertOctagon,\n Sparkles,\n RefreshCw,\n Send,\n FileText,\n Inbox,\n} from 'lucide-react';\nimport { Button } from '../components/Button';\nimport { Card, CardTitle } from '../components/Card';\nimport { EmptyState } from '../components/EmptyState';\nimport { Spinner } from '../components/Spinner';\nimport { StatusBadge } from '../components/StatusBadge';\nimport { Tag } from '../components/Tag';\nimport { useModal } from '../components/Modal';\nimport { useToast } from '../components/Toast';\nimport { BgStatusBadge } from '../components/BgStatusBadge';\nimport { openKillConfirmDialog } from '../components/KillConfirmDialog';\nimport { api, enhancePrompt } from '../lib/api';\nimport { cn, formatRelative, priorityColors, autoTitleFromContent } from '../lib/utils';\nimport type { Agent, Settings, Snapshot, Task } from '../lib/types';\nimport { openArtifactViewer } from '../components/ArtifactViewer';\nimport { BacklogPanel } from '../components/tasks/BacklogPanel';\n\ntype Props = {\n snapshot: Snapshot;\n settings: Settings;\n activeTab: string;\n setActiveTab: (id: string) => void;\n refreshSnapshot: () => Promise<void>;\n};\n\ntype Column = {\n id: Task['status'] | string;\n label: string;\n kind: 'info' | 'accent' | 'success' | 'warning' | 'error';\n};\n\nconst COLUMNS: Column[] = [\n { id: 'queued', label: 'Queued', kind: 'info' },\n { id: 'doing', label: 'Doing', kind: 'accent' },\n { id: 'blocked', label: 'Blocked', kind: 'warning' },\n { id: 'done', label: 'Done', kind: 'success' },\n];\n\n/**\n * v3.7.4 — Decide whether a task belongs in the given kanban column.\n * Archived tasks (any prior session's \"finished and tucked away\" tasks)\n * show up in the DONE column so a fresh dashboard load still surfaces\n * everything that exists on disk.\n */\nfunction matchesColumn(task: Task, colId: string): boolean {\n const isArchived = task.status === 'archived' || task.archived === true;\n if (colId === 'done') return task.status === 'done' || isArchived;\n return !isArchived && task.status === colId;\n}\n\nconst PRIORITIES = ['low', 'normal', 'high'] as const;\ntype Priority = (typeof PRIORITIES)[number];\ntype SortKey = 'priority' | 'due' | 'created' | 'updated';\n\nconst SORTS: { id: SortKey; label: string }[] = [\n { id: 'updated', label: 'Last updated' },\n { id: 'created', label: 'Created' },\n { id: 'priority', label: 'Priority' },\n { id: 'due', label: 'Due date' },\n];\n\nexport function Tasks({ snapshot, refreshSnapshot, setActiveTab }: Props) {\n const toast = useToast();\n const modal = useModal();\n const [tasks, setTasks] = useState<Task[]>(snapshot.tasks || []);\n const [loading, setLoading] = useState(!snapshot.tasks);\n const [filter, setFilter] = useState('');\n const [assigneeFilter, setAssigneeFilter] = useState<string>('');\n const [priorityFilter, setPriorityFilter] = useState<string>('');\n const [tagFilter, setTagFilter] = useState<string>('');\n const [sortKey, setSortKey] = useState<SortKey>('updated');\n const [showArchived, setShowArchived] = useState(false);\n const [selected, setSelected] = useState<Set<string>>(new Set());\n const [tick, setTick] = useState(0); // for live timer re-render\n\n const reload = async (opts: { archived?: boolean } = {}) => {\n try {\n const params = opts.archived ? '?archived=only' : '';\n const data = await api.get<Task[]>(`/tasks${params}`);\n setTasks(Array.isArray(data) ? data : []);\n } catch (err) {\n toast.error(`Tasks load failed: ${(err as Error).message}`);\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n if (snapshot.tasks) {\n setTasks(snapshot.tasks);\n setLoading(false);\n }\n }, [snapshot.tasks]);\n\n // Periodic tick for live timer display.\n useEffect(() => {\n const id = setInterval(() => setTick((t) => t + 1), 1000);\n return () => clearInterval(id);\n }, []);\n\n const allTags = useMemo(() => {\n const set = new Set<string>();\n for (const t of tasks) for (const tag of t.tags || []) set.add(tag);\n return Array.from(set).sort();\n }, [tasks]);\n\n const filtered = useMemo(() => {\n let out = tasks;\n if (assigneeFilter) {\n out = out.filter((t) => (t.assignee || '') === assigneeFilter);\n }\n if (priorityFilter) {\n out = out.filter((t) => (t.priority || 'normal') === priorityFilter);\n }\n if (tagFilter) {\n out = out.filter((t) => (t.tags || []).includes(tagFilter));\n }\n if (filter.trim()) {\n const q = filter.toLowerCase();\n out = out.filter((t) => {\n const title = (t.title || '').toLowerCase();\n const desc = (t.description || '').toLowerCase();\n const tags = (t.tags || []).join(' ').toLowerCase();\n return title.includes(q) || desc.includes(q) || tags.includes(q);\n });\n }\n return out;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [tasks, filter, assigneeFilter, priorityFilter, tagFilter]);\n\n const sorted = useMemo(() => {\n const out = [...filtered];\n const priorityWeight = { high: 0, normal: 1, low: 2 } as Record<string, number>;\n switch (sortKey) {\n case 'priority':\n out.sort((a, b) => (priorityWeight[a.priority] ?? 1) - (priorityWeight[b.priority] ?? 1));\n break;\n case 'created':\n out.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());\n break;\n case 'due':\n out.sort((a, b) => {\n const ax = a.dueDate ? new Date(a.dueDate).getTime() : Infinity;\n const bx = b.dueDate ? new Date(b.dueDate).getTime() : Infinity;\n return ax - bx;\n });\n break;\n case 'updated':\n default:\n out.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());\n break;\n }\n return out;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [filtered, sortKey]);\n\n const moveTask = async (taskId: string, newStatus: string) => {\n const t = tasks.find((x) => x.id === taskId);\n if (!t) return;\n const prev = t.status;\n setTasks((cur) =>\n cur.map((x) => (x.id === taskId ? { ...x, status: newStatus } : x)),\n );\n try {\n await api.patch(`/tasks/${encodeURIComponent(taskId)}/status`, {\n status: newStatus,\n });\n toast.success(`Moved to ${newStatus}.`, 1500);\n } catch (err) {\n setTasks((cur) =>\n cur.map((x) => (x.id === taskId ? { ...x, status: prev } : x)),\n );\n toast.error(`Move failed: ${(err as Error).message}`);\n }\n };\n\n const deleteTask = async (taskId: string) => {\n if (!confirm('Delete this task?')) return;\n try {\n await api.del(`/tasks/${encodeURIComponent(taskId)}`);\n setTasks((cur) => cur.filter((t) => t.id !== taskId));\n toast.success('Task deleted.', 1500);\n } catch (err) {\n toast.error(`Delete failed: ${(err as Error).message}`);\n }\n };\n\n const archiveTask = async (taskId: string) => {\n try {\n const updated = await api.post<Task>(`/tasks/${encodeURIComponent(taskId)}/archive`);\n setTasks((cur) => cur.filter((t) => t.id !== taskId));\n toast.success('Task archived.', 1500);\n } catch (err) {\n toast.error(`Archive failed: ${(err as Error).message}`);\n }\n };\n\n const unarchiveTask = async (taskId: string) => {\n try {\n const updated = await api.post<Task>(`/tasks/${encodeURIComponent(taskId)}/unarchive`);\n setTasks((cur) => cur.map((t) => (t.id === taskId ? updated : t)));\n toast.success('Task restored.', 1500);\n } catch (err) {\n toast.error(`Restore failed: ${(err as Error).message}`);\n }\n };\n\n const onBulkAction = async (action: 'archive' | 'delete' | 'move' | 'priority' | 'assign' | 'tag', params: Record<string, unknown> = {}) => {\n if (selected.size === 0) return;\n const ids = Array.from(selected);\n try {\n const out = await api.post<{ affected: { id: string; ok: boolean; error?: string }[] }>('/tasks/bulk', {\n ids,\n action,\n params,\n });\n const ok = out.affected.filter((r) => r.ok).length;\n const failed = out.affected.length - ok;\n if (action === 'archive' || action === 'delete') {\n setTasks((cur) => cur.filter((t) => !ids.includes(t.id)));\n } else {\n await reload();\n }\n toast.success(`Bulk ${action}: ${ok} ok${failed ? `, ${failed} failed` : ''}.`, 2500);\n setSelected(new Set());\n } catch (err) {\n toast.error(`Bulk failed: ${(err as Error).message}`);\n }\n };\n\n const onAssignMe = async (t: Task) => {\n try {\n const me = 'me';\n const updated = await api.put<Task>(`/tasks/${encodeURIComponent(t.id)}`, { assignee: me });\n setTasks((cur) => cur.map((x) => (x.id === t.id ? updated : x)));\n toast.success('Assigned to me.', 1200);\n } catch (err) {\n toast.error(`Assign failed: ${(err as Error).message}`);\n }\n };\n\n const onMarkWorkedBy = async (t: Task, agent: string, status: 'doing' | 'done' | 'idle', complete: boolean) => {\n try {\n const updated = await api.post<Task>(`/tasks/${encodeURIComponent(t.id)}/work`, {\n agent,\n status,\n complete,\n });\n setTasks((cur) => cur.map((x) => (x.id === t.id ? updated : x)));\n toast.success(`Marked ${status} by ${agent}.`, 1500);\n } catch (err) {\n toast.error(`Mark failed: ${(err as Error).message}`);\n }\n };\n\n const toggleSelect = (id: string) => {\n setSelected((cur) => {\n const next = new Set(cur);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n return next;\n });\n };\n\n const toggleSelectAll = (ids: string[]) => {\n setSelected((cur) => {\n const next = new Set(cur);\n const allSelected = ids.length > 0 && ids.every((id) => next.has(id));\n if (allSelected) {\n ids.forEach((id) => next.delete(id));\n return next;\n }\n ids.forEach((id) => next.add(id));\n return next;\n });\n };\n\n // v3.6.2 — Pipeline: open task chat session.\n const onOpenTaskChat = (taskId: string) => {\n setActiveTab('chat');\n // The Chat view reads crossState.initialChatTaskId to pre-load a session.\n // We set it via a custom event that Chat.tsx listens to on mount.\n window.dispatchEvent(new CustomEvent('bizar:setChatTask', { detail: { taskId } }));\n };\n\n // v3.6.2 — Pipeline: open task artifact viewer.\n const onOpenTaskArtifact = (artifactId: string) => {\n openArtifactViewer(modal, artifactId);\n };\n\n // v3.22 — Backlog panel visibility.\n const [showBacklog, setShowBacklog] = useState(false);\n const backlogCount = (snapshot.tasks || []).filter((t) => t.status === 'backlog').length;\n\n return (\n <div className=\"view view-tasks\">\n <header className=\"view-header\">\n <div className=\"view-header-text\">\n <h2 className=\"view-title\">\n <CheckSquare size={18} /> Tasks ({sorted.length})\n </h2>\n <p className=\"view-subtitle\">\n Personal kanban. Click a card for details (subtasks, deps, timer, comments, activity).\n </p>\n </div>\n </header>\n\n {/* v3.4.0 — Compact single-row toolbar: search + filters + sort + actions */}\n <div className=\"tasks-toolbar\">\n <div className=\"tasks-toolbar-group\">\n <div className=\"search-input\" style={{ width: 200 }}>\n <Search size={12} />\n <input\n className=\"input\"\n type=\"text\"\n placeholder=\"Search…\"\n value={filter}\n onChange={(e) => setFilter(e.target.value)}\n />\n {filter && (\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label=\"Clear search\"\n onClick={() => setFilter('')}\n >\n <XIcon size={12} />\n </button>\n )}\n </div>\n </div>\n\n <div className=\"tasks-toolbar-divider\" />\n\n <div className=\"tasks-toolbar-group\">\n <span className=\"tasks-toolbar-label\">Filter</span>\n <select\n className=\"select select-sm\"\n value={assigneeFilter}\n onChange={(e) => setAssigneeFilter(e.target.value)}\n title=\"Assignee\"\n >\n <option value=\"\">All assignees</option>\n <option value=\"me\">Me</option>\n {(snapshot.agents || []).map((a) => (\n <option key={a.name} value={a.name}>@{a.name}</option>\n ))}\n </select>\n <select\n className=\"select select-sm\"\n value={priorityFilter}\n onChange={(e) => setPriorityFilter(e.target.value)}\n title=\"Priority\"\n >\n <option value=\"\">All priorities</option>\n {PRIORITIES.map((p) => (\n <option key={p} value={p}>{p}</option>\n ))}\n </select>\n {allTags.length > 0 && (\n <select\n className=\"select select-sm\"\n value={tagFilter}\n onChange={(e) => setTagFilter(e.target.value)}\n title=\"Tag\"\n >\n <option value=\"\">All tags</option>\n {allTags.map((t) => (\n <option key={t} value={t}>#{t}</option>\n ))}\n </select>\n )}\n </div>\n\n <div className=\"tasks-toolbar-divider\" />\n\n <div className=\"tasks-toolbar-group\">\n <span className=\"tasks-toolbar-label\">Sort</span>\n <select\n className=\"select select-sm\"\n value={sortKey}\n onChange={(e) => setSortKey(e.target.value as SortKey)}\n title=\"Sort by\"\n >\n {SORTS.map((s) => (\n <option key={s.id} value={s.id}>{s.label}</option>\n ))}\n </select>\n </div>\n\n <div className=\"tasks-toolbar-spacer\" />\n\n <div className=\"tasks-toolbar-group\">\n <Button\n variant={showArchived ? 'primary' : 'ghost'}\n size=\"sm\"\n onClick={() => {\n setShowArchived((v) => !v);\n reload({ archived: !showArchived });\n }}\n title={showArchived ? 'Showing archived' : 'Show archived'}\n >\n {showArchived ? <ArchiveRestore size={14} /> : <Archive size={14} />}\n {showArchived ? 'Active' : 'Archived'}\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => reload()} title=\"Refresh\" aria-label=\"Refresh tasks\">\n <RefreshCw size={14} />\n </Button>\n <Button\n variant=\"accent\"\n size=\"sm\"\n onClick={() => openSubmitTaskModal(modal, toast, setTasks, reload, refreshSnapshot)}\n >\n <Send size={14} /> Odin\n </Button>\n <Button\n variant=\"primary\"\n size=\"sm\"\n onClick={() => openTaskModal(modal, toast, null, 'queued', setTasks, reload, refreshSnapshot, snapshot.agents)}\n >\n <Plus size={14} /> Add\n </Button>\n {backlogCount > 0 && (\n <Button\n variant={showBacklog ? 'accent' : 'ghost'}\n size=\"sm\"\n onClick={() => setShowBacklog((v) => !v)}\n title={showBacklog ? 'Hide backlog' : 'Show backlog'}\n >\n <Inbox size={14} />\n Backlog\n <span className=\"badge\">{backlogCount}</span>\n </Button>\n )}\n </div>\n </div>\n\n {showBacklog && backlogCount > 0 && (\n <BacklogPanel agents={snapshot.agents || []} onRefresh={refreshSnapshot} />\n )}\n\n {selected.size > 0 && (\n <div className=\"task-bulk-bar\">\n <span className=\"text-sm\">\n <CheckSquareIcon size={14} /> {selected.size} selected\n </span>\n <div className=\"task-bulk-bar-actions\">\n <Button size=\"sm\" variant=\"ghost\" onClick={() => onBulkAction('move', { status: 'queued' })}>\n Queued\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => onBulkAction('move', { status: 'doing' })}>\n Doing\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => onBulkAction('move', { status: 'done' })}>\n Done\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => onBulkAction('priority', { priority: 'high' })}>\n High\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => onBulkAction('archive')}>\n <Archive size={12} /> Archive\n </Button>\n <Button size=\"sm\" variant=\"danger\" onClick={() => onBulkAction('delete')}>\n <Trash2 size={12} /> Delete\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => setSelected(new Set())}>\n Clear\n </Button>\n </div>\n </div>\n )}\n\n {loading ? (\n <div className=\"view-loading\"><Spinner size=\"lg\" /></div>\n ) : (\n <div className=\"kanban\">\n {COLUMNS.map((col) => (\n <KanbanColumn\n key={col.id}\n column={col}\n // v3.7.4 — Archived tasks (`status: \"archived\"` OR `archived: true`)\n // surface in the DONE column so earlier-existing tasks are\n // visible from a fresh dashboard load. The TaskCard itself\n // shows an \"Archived\" badge so the user can distinguish them\n // from completed tasks.\n tasks={sorted.filter((t) => matchesColumn(t, col.id))}\n selected={selected}\n onToggleSelect={toggleSelect}\n onToggleSelectAll={toggleSelectAll}\n allTaskIdsInCol={sorted.filter((t) => matchesColumn(t, col.id)).map((t) => t.id)}\n onMove={moveTask}\n onDelete={deleteTask}\n onArchive={archiveTask}\n onUnarchive={unarchiveTask}\n onEdit={(t) => openTaskDetail(modal, toast, t, setTasks, reload, refreshSnapshot, snapshot.agents, tick)}\n onAdd={() => openTaskModal(modal, toast, null, col.id, setTasks, reload, refreshSnapshot, snapshot.agents)}\n onAssignMe={onAssignMe}\n onMarkWorkedBy={onMarkWorkedBy}\n onOpenChat={onOpenTaskChat}\n onOpenArtifact={onOpenTaskArtifact}\n isArchivedView={showArchived}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction KanbanColumn({\n column,\n tasks,\n selected,\n onToggleSelect,\n onToggleSelectAll,\n allTaskIdsInCol,\n onMove,\n onDelete,\n onArchive,\n onUnarchive,\n onEdit,\n onAdd,\n onAssignMe,\n onMarkWorkedBy,\n onOpenChat,\n onOpenArtifact,\n isArchivedView,\n}: {\n column: Column;\n tasks: Task[];\n selected: Set<string>;\n onToggleSelect: (id: string) => void;\n onToggleSelectAll: (ids: string[]) => void;\n allTaskIdsInCol: string[];\n onMove: (id: string, status: string) => void;\n onDelete: (id: string) => void;\n onArchive: (id: string) => void;\n onUnarchive: (id: string) => void;\n onEdit: (task: Task) => void;\n onAdd: () => void;\n onAssignMe: (task: Task) => void;\n onMarkWorkedBy: (task: Task, agent: string, status: 'doing' | 'done' | 'idle', complete: boolean) => void;\n onOpenChat: (taskId: string) => void;\n onOpenArtifact: (artifactId: string) => void;\n isArchivedView: boolean;\n}) {\n const [dragOver, setDragOver] = useState(false);\n const allSelected = tasks.length > 0 && allTaskIdsInCol.every((id) => selected.has(id));\n return (\n <div\n className={cn('kanban-column', dragOver && 'kanban-column-drop')}\n data-column={column.id}\n onDragOver={(e) => {\n e.preventDefault();\n setDragOver(true);\n }}\n onDragLeave={() => setDragOver(false)}\n onDrop={(e) => {\n e.preventDefault();\n setDragOver(false);\n const id = e.dataTransfer.getData('text/task-id');\n if (id) onMove(id, column.id);\n }}\n >\n <div className=\"kanban-col-header\">\n <button\n type=\"button\"\n className=\"icon-btn\"\n onClick={() => onToggleSelectAll(allTaskIdsInCol)}\n title={allSelected ? 'Deselect all' : 'Select all'}\n aria-label={allSelected ? 'Deselect all' : 'Select all'}\n >\n {allSelected ? <CheckSquareIcon size={12} /> : <Square size={12} />}\n </button>\n <CardTitle>\n <StatusBadge kind={column.kind} dot>\n {column.label}\n </StatusBadge>\n </CardTitle>\n <span className=\"kanban-col-count tabular-nums\">{tasks.length}</span>\n </div>\n <div className=\"kanban-col-body\">\n {tasks.length === 0 ? (\n <div className=\"kanban-empty\">No tasks</div>\n ) : (\n tasks.map((t) => (\n <TaskCard\n key={t.id}\n task={t}\n focused={selected.has(t.id)}\n onFocus={() => onToggleSelect(t.id)}\n onMove={(dir) => {\n const idx = COLUMNS.findIndex((c) => c.id === t.status);\n const next = idx + dir;\n if (next >= 0 && next < COLUMNS.length)\n onMove(t.id, COLUMNS[next].id);\n }}\n onEdit={() => onEdit(t)}\n onDelete={() => onDelete(t.id)}\n onArchive={() => onArchive(t.id)}\n onUnarchive={() => onUnarchive(t.id)}\n onAssignMe={() => onAssignMe(t)}\n onMarkWorkedBy={(agent, status, complete) => onMarkWorkedBy(t, agent, status, complete)}\n onOpenChat={onOpenChat}\n onOpenArtifact={onOpenArtifact}\n isArchivedView={isArchivedView}\n />\n ))\n )}\n </div>\n {!isArchivedView && (\n <footer className=\"kanban-col-footer\">\n <Button variant=\"ghost\" size=\"sm\" onClick={onAdd} className=\"w-full\">\n <Plus size={12} /> Add task\n </Button>\n </footer>\n )}\n </div>\n );\n}\n\nfunction TaskCard({\n task,\n focused,\n onFocus,\n onMove,\n onEdit,\n onDelete,\n onArchive,\n onUnarchive,\n onAssignMe,\n onMarkWorkedBy,\n onOpenChat,\n onOpenArtifact,\n isArchivedView,\n}: {\n task: Task;\n focused: boolean;\n onFocus: () => void;\n onMove: (dir: -1 | 1) => void;\n onEdit: () => void;\n onDelete: () => void;\n onArchive: () => void;\n onUnarchive: () => void;\n onAssignMe: () => void;\n onMarkWorkedBy: (agent: string, status: 'doing' | 'done' | 'idle', complete: boolean) => void;\n onOpenChat: (taskId: string) => void;\n onOpenArtifact: (artifactId: string) => void;\n isArchivedView: boolean;\n}) {\n const toast = useToast();\n const modal = useModal();\n const isTimer = task._timerStart;\n const isWorking = (task.workedBy || task.status === 'doing') && !isArchivedView;\n\n // v3.6.2 — Pipeline: determine if task has a chat session or artifact.\n type TaskPipelineMeta = {\n sessionId?: string;\n bgInstanceId?: string;\n status?: string;\n artifactIds?: string[];\n artifactId?: string;\n };\n const metadata = (task.metadata || {}) as TaskPipelineMeta;\n const hasChatSession = !!(metadata.sessionId || metadata.bgInstanceId);\n const artifactIds: string[] = metadata.artifactIds || (metadata.artifactId ? [metadata.artifactId] : []);\n const primaryArtifactId = artifactIds[0];\n return (\n <div\n className={cn(\n 'task-card',\n `priority-${task.priority}`,\n focused && 'task-card-focused',\n isTimer ? 'task-card-timer is-working' : null,\n isWorking && !isTimer ? 'is-working' : null,\n )}\n data-task-id={task.id}\n data-task-parent={task.parent || ''}\n draggable={!isArchivedView}\n onDragStart={(e) => {\n e.dataTransfer.setData('text/task-id', task.id);\n e.dataTransfer.effectAllowed = 'move';\n }}\n onClick={onFocus}\n >\n <div className=\"task-card-head\">\n {/* v3.7.0 — Visible checkbox for bulk select */}\n <button\n type=\"button\"\n className={cn('task-card-checkbox', focused && 'task-card-checkbox-on')}\n aria-label={focused ? 'Deselect task' : 'Select task'}\n title={focused ? 'Deselect' : 'Select'}\n onClick={(e) => {\n e.stopPropagation();\n onFocus();\n }}\n >\n {focused ? <CheckSquareIcon size={13} /> : <Square size={13} />}\n </button>\n <span\n className=\"priority-dot\"\n style={{ background: priorityColors[task.priority] || 'var(--info)' }}\n />\n <div className=\"task-card-title\">{task.title}</div>\n {isTimer && <span className=\"task-card-timer-pill\"><Clock size={10} /> running</span>}\n {task.workedBy && task.status === 'doing' && !isTimer && (\n <span className=\"task-card-timer-pill\" title={`@${task.workedBy}`}>\n <Bot size={10} /> @{task.workedBy}\n </span>\n )}\n {task.recurring && (\n <span className=\"task-card-timer-pill\" title=\"Recurring\">\n <RotateCw size={10} />\n </span>\n )}\n </div>\n {task.description && (\n <div className=\"task-card-desc\">{task.description.slice(0, 160)}</div>\n )}\n <div className=\"task-card-badges\">\n {task.assignee && !task.workedBy && <span className=\"task-card-badge\"><TagIcon size={10} /> @{task.assignee}</span>}\n {task.timeSpent ? <span className=\"task-card-badge\"><Clock size={10} /> {formatDuration(task.timeSpent)}</span> : null}\n {task.dependencies?.length ? <span className=\"task-card-badge\"><Link2 size={10} /> {task.dependencies.length}</span> : null}\n {task.recurring ? <span className=\"task-card-badge\"><Calendar size={10} /> {task.recurring.cron || task.recurring.freq || 'recurring'}</span> : null}\n {task.comments?.length ? <span className=\"task-card-badge\"><MessageSquare size={10} /> {task.comments.length}</span> : null}\n {task.attachments?.length ? <span className=\"task-card-badge\"><Paperclip size={10} /> {task.attachments.length}</span> : null}\n {metadata.bgInstanceId ? (\n <span className=\"task-card-badge\">\n <Activity size={10} /> <BgStatusBadge status={metadata.status || 'pending'} />\n </span>\n ) : null}\n </div>\n {task.tags && task.tags.length > 0 && (\n <div className=\"task-card-tags\">\n {task.tags.map((t) => (\n <Tag key={t}>{t}</Tag>\n ))}\n </div>\n )}\n <div className=\"task-card-footer\">\n <span className=\"task-card-time tabular-nums muted\">\n {formatRelative(task.updatedAt || task.createdAt)}\n </span>\n <div className=\"task-card-actions\" onClick={(e) => e.stopPropagation()}>\n {!isArchivedView && (\n <>\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label=\"Move left\"\n title=\"Move left\"\n onClick={() => onMove(-1)}\n >\n <ChevronLeft size={14} />\n </button>\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label=\"Edit\"\n title=\"Open detail\"\n onClick={onEdit}\n >\n <Sparkles size={14} />\n </button>\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label=\"Assign me\"\n title=\"Assign to me\"\n onClick={onAssignMe}\n >\n <TagIcon size={14} />\n </button>\n {hasChatSession && (\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label=\"Open chat\"\n title=\"Open in chat\"\n onClick={() => onOpenChat(task.id)}\n >\n <MessageSquare size={14} />\n </button>\n )}\n {primaryArtifactId && (\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label=\"Open artifact\"\n title=\"Open artifact\"\n onClick={() => onOpenArtifact(primaryArtifactId)}\n >\n <FileText size={14} />\n </button>\n )}\n {isArchivedView ? (\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label=\"Restore\"\n title=\"Restore\"\n onClick={onUnarchive}\n >\n <ArchiveRestore size={14} />\n </button>\n ) : (\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label=\"Archive\"\n title=\"Archive\"\n onClick={onArchive}\n >\n <Archive size={14} />\n </button>\n )}\n {metadata.bgInstanceId && (\n <button\n type=\"button\"\n className=\"icon-btn icon-btn-danger\"\n aria-label=\"Kill background instance\"\n title=\"Kill background instance\"\n onClick={() => {\n openKillConfirmDialog(modal, toast, metadata.bgInstanceId!, task.title, () => {\n // Optimistically mark task as blocked after kill.\n const event = new CustomEvent('bizar:taskKilled', {\n detail: { taskId: task.id, bgInstanceId: metadata.bgInstanceId },\n });\n window.dispatchEvent(event);\n });\n }}\n >\n <Activity size={14} />\n </button>\n )}\n <button\n type=\"button\"\n className=\"icon-btn icon-btn-danger\"\n aria-label=\"Delete\"\n title=\"Delete\"\n onClick={onDelete}\n >\n <Trash2 size={14} />\n </button>\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label=\"Move right\"\n title=\"Move right\"\n onClick={() => onMove(1)}\n >\n <ChevronRight size={14} />\n </button>\n </>\n )}\n {isArchivedView && (\n <>\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label=\"Restore\"\n title=\"Restore\"\n onClick={onUnarchive}\n >\n <ArchiveRestore size={14} />\n </button>\n <button\n type=\"button\"\n className=\"icon-btn icon-btn-danger\"\n aria-label=\"Delete\"\n title=\"Delete\"\n onClick={onDelete}\n >\n <Trash2 size={14} />\n </button>\n </>\n )}\n </div>\n </div>\n </div>\n );\n}\n\nfunction formatDuration(seconds: number): string {\n if (!seconds) return '0m';\n const h = Math.floor(seconds / 3600);\n const m = Math.floor((seconds % 3600) / 60);\n if (h > 0) return `${h}h ${m}m`;\n return `${m}m`;\n}\n\nexport function openTaskModal(\n modal: ReturnType<typeof useModal>,\n toast: ReturnType<typeof useToast>,\n task: Task | null,\n initialStatus: string,\n setTasks: (updater: (cur: Task[]) => Task[]) => void,\n reload: () => Promise<void>,\n refreshSnapshot: () => Promise<void>,\n agents: Agent[] = [],\n) {\n let titleEl: HTMLInputElement | null = null;\n let descEl: HTMLTextAreaElement | null = null;\n let tagsEl: HTMLInputElement | null = null;\n let priorityEl: HTMLDivElement | null = null;\n let statusEl: HTMLSelectElement | null = null;\n let assigneeEl: HTMLInputElement | null = null;\n let recurEl: HTMLSelectElement | null = null;\n let cronEl: HTMLInputElement | null = null;\n let dueEl: HTMLInputElement | null = null;\n\n const submit = async () => {\n const title = titleEl?.value.trim() || '';\n if (!title) {\n toast.warning('Title is required.');\n titleEl?.focus();\n return;\n }\n const description = descEl?.value.trim() || '';\n const priority =\n (priorityEl?.querySelector<HTMLInputElement>(\n 'input[name=\"task-priority\"]:checked',\n )?.value as Priority) || 'normal';\n const tagsRaw = tagsEl?.value.trim() || '';\n const tags = tagsRaw\n ? tagsRaw.split(',').map((t) => t.trim()).filter(Boolean)\n : [];\n const status = statusEl?.value || initialStatus;\n const assignee = (assigneeEl?.value || '').trim() || null;\n const recurFreq = recurEl?.value || '';\n const cron = cronEl?.value.trim() || '';\n const recurring = recurFreq === 'custom' && cron\n ? { freq: 'custom', cron }\n : recurFreq && recurFreq !== 'none'\n ? { freq: recurFreq }\n : null;\n const dueDate = dueEl?.value || null;\n\n try {\n if (task) {\n const updated = await api.put<Task>(`/tasks/${encodeURIComponent(task.id)}`, {\n title,\n description,\n tags,\n priority,\n status,\n assignee,\n recurring,\n dueDate,\n });\n // v3.3.1 — close modal first, bump safe window, then state.\n modal.close();\n if (typeof window !== 'undefined') {\n window.dispatchEvent(new MouseEvent('mousedown'));\n }\n setTasks((cur) => cur.map((x) => (x.id === task.id ? updated : x)));\n toast.success('Task updated.', 1500);\n } else {\n const created = await api.post<Task>('/tasks', {\n title,\n description,\n status,\n tags,\n priority,\n assignee,\n recurring,\n dueDate,\n });\n // v3.3.1 — close modal first, bump safe window, then state.\n modal.close();\n if (typeof window !== 'undefined') {\n window.dispatchEvent(new MouseEvent('mousedown'));\n }\n setTasks((cur) => [created, ...cur]);\n toast.success('Task created.', 1500);\n }\n await refreshSnapshot();\n } catch (err) {\n toast.error(`Save failed: ${(err as Error).message}`);\n }\n };\n\n modal.open({\n title: task ? 'Edit task' : 'New task',\n width: 560,\n children: (\n <div className=\"task-form\">\n <label className=\"field-label\" htmlFor=\"task-title\">Title *</label>\n <input\n ref={(el) => { titleEl = el; }}\n id=\"task-title\"\n className=\"input\"\n type=\"text\"\n maxLength={200}\n placeholder=\"What needs to be done?\"\n defaultValue={task?.title || ''}\n autoFocus\n />\n <label className=\"field-label\" htmlFor=\"task-desc\">Description (markdown)</label>\n <textarea\n ref={(el) => { descEl = el; }}\n id=\"task-desc\"\n className=\"textarea\"\n rows={3}\n placeholder=\"Markdown supported…\"\n defaultValue={task?.description || ''}\n />\n <div className=\"task-form-row\">\n <div className=\"task-form-field\">\n <label className=\"field-label\" htmlFor=\"task-status\">Status</label>\n <select\n ref={(el) => { statusEl = el; }}\n id=\"task-status\"\n className=\"select\"\n defaultValue={task?.status || initialStatus}\n >\n {COLUMNS.map((c) => (\n <option key={c.id} value={c.id}>{c.label}</option>\n ))}\n </select>\n </div>\n <div className=\"task-form-field\">\n <label className=\"field-label\">Priority</label>\n <div className=\"radio-row\" ref={(el) => { priorityEl = el; }}>\n {PRIORITIES.map((p) => (\n <label key={p} className=\"radio-label\">\n <input\n type=\"radio\"\n name=\"task-priority\"\n value={p}\n defaultChecked={(task?.priority || 'normal') === p}\n />\n <span className=\"capitalize\">{p}</span>\n </label>\n ))}\n </div>\n </div>\n </div>\n <div className=\"task-form-row\">\n <div className=\"task-form-field\">\n <label className=\"field-label\" htmlFor=\"task-assignee\">Assignee</label>\n <input\n ref={(el) => { assigneeEl = el; }}\n id=\"task-assignee\"\n className=\"input\"\n type=\"text\"\n placeholder=\"odin, thor, me, …\"\n list=\"task-assignee-suggestions\"\n defaultValue={task?.assignee || ''}\n />\n <datalist id=\"task-assignee-suggestions\">\n {agents.map((a) => (\n <option key={a.name} value={a.name}>@{a.name}</option>\n ))}\n </datalist>\n </div>\n <div className=\"task-form-field\">\n <label className=\"field-label\" htmlFor=\"task-due\">Due date</label>\n <input\n ref={(el) => { dueEl = el; }}\n id=\"task-due\"\n className=\"input\"\n type=\"date\"\n defaultValue={task?.dueDate?.slice(0, 10) || ''}\n />\n </div>\n </div>\n <label className=\"field-label\" htmlFor=\"task-tags\">Tags</label>\n <input\n ref={(el) => { tagsEl = el; }}\n id=\"task-tags\"\n className=\"input\"\n type=\"text\"\n placeholder=\"comma-separated, e.g. bug, frontend\"\n defaultValue={(task?.tags || []).join(', ')}\n />\n <div className=\"task-form-row\">\n <div className=\"task-form-field\">\n <label className=\"field-label\" htmlFor=\"task-recur\">Recurring</label>\n <select\n ref={(el) => { recurEl = el; }}\n id=\"task-recur\"\n className=\"select\"\n defaultValue={task?.recurring?.freq || 'none'}\n >\n <option value=\"none\">None</option>\n <option value=\"daily\">Daily</option>\n <option value=\"weekly\">Weekly</option>\n <option value=\"monthly\">Monthly</option>\n <option value=\"custom\">Custom (cron)</option>\n </select>\n </div>\n <div className=\"task-form-field\">\n <label className=\"field-label\" htmlFor=\"task-cron\">Cron expression</label>\n <input\n ref={(el) => { cronEl = el; }}\n id=\"task-cron\"\n className=\"input\"\n type=\"text\"\n placeholder=\"0 9 * * *\"\n defaultValue={task?.recurring?.cron || ''}\n />\n </div>\n </div>\n </div>\n ),\n footer: (\n <div className=\"modal-footer-actions\">\n <Button variant=\"ghost\" onClick={() => modal.close()}>Cancel</Button>\n <Button variant=\"primary\" onClick={submit}>{task ? 'Save' : 'Create'}</Button>\n </div>\n ),\n });\n}\n\nfunction openTaskDetail(\n modal: ReturnType<typeof useModal>,\n toast: ReturnType<typeof useToast>,\n task: Task,\n setTasks: (updater: (cur: Task[]) => Task[]) => void,\n reload: () => Promise<void>,\n refreshSnapshot: () => Promise<void>,\n agents: Agent[] = [],\n tick: number = 0,\n) {\n let commentEl: HTMLTextAreaElement | null = null;\n let depEl: HTMLInputElement | null = null;\n let agentEl: HTMLSelectElement | null = null;\n\n const refresh = async () => {\n try {\n const r = await api.get<Task[]>(`/tasks?archived=${task.archived ? 'true' : 'false'}`);\n const found = r.find((t) => t.id === task.id);\n if (found) {\n setTasks((cur) => cur.map((x) => (x.id === found.id ? found : x)));\n }\n } catch { /* ignore */ }\n };\n\n const onComment = async () => {\n const text = (commentEl?.value || '').trim();\n if (!text) return;\n try {\n const updated = await api.post<Task>(`/tasks/${encodeURIComponent(task.id)}/comments`, { text });\n setTasks((cur) => cur.map((x) => (x.id === task.id ? updated : x)));\n if (commentEl) commentEl.value = '';\n toast.success('Comment added.', 1200);\n } catch (err) {\n toast.error(`Comment failed: ${(err as Error).message}`);\n }\n };\n\n const onStartTimer = async () => {\n try {\n const updated = await api.post<Task>(`/tasks/${encodeURIComponent(task.id)}/timer/start`);\n setTasks((cur) => cur.map((x) => (x.id === task.id ? updated : x)));\n toast.success('Timer started.', 1200);\n } catch (err) {\n toast.error(`Start failed: ${(err as Error).message}`);\n }\n };\n\n const onStopTimer = async () => {\n try {\n const updated = await api.post<Task>(`/tasks/${encodeURIComponent(task.id)}/timer/stop`);\n setTasks((cur) => cur.map((x) => (x.id === task.id ? updated : x)));\n toast.success('Timer stopped.', 1200);\n } catch (err) {\n toast.error(`Stop failed: ${(err as Error).message}`);\n }\n };\n\n const onAddDep = async () => {\n const id = (depEl?.value || '').trim();\n if (!id) return;\n const next = [...(task.dependencies || []), id];\n try {\n const updated = await api.put<Task>(`/tasks/${encodeURIComponent(task.id)}`, { dependencies: next });\n setTasks((cur) => cur.map((x) => (x.id === task.id ? updated : x)));\n if (depEl) depEl.value = '';\n toast.success('Dependency added.', 1200);\n } catch (err) {\n toast.error(`Failed: ${(err as Error).message}`);\n }\n };\n\n const onMarkWorkedBy = async (status: 'doing' | 'done' | 'idle', complete: boolean) => {\n const agent = agentEl?.value || '';\n if (!agent) {\n toast.warning('Pick an agent first.');\n return;\n }\n try {\n const updated = await api.post<Task>(`/tasks/${encodeURIComponent(task.id)}/work`, {\n agent,\n status,\n complete,\n });\n setTasks((cur) => cur.map((x) => (x.id === task.id ? updated : x)));\n toast.success(`${status} by @${agent}.`, 1200);\n } catch (err) {\n toast.error(`Failed: ${(err as Error).message}`);\n }\n };\n\n const timerSeconds = task._timerStart\n ? Math.floor((Date.now() - task._timerStart) / 1000) + (task.timeSpent || 0)\n : (task.timeSpent || 0);\n\n modal.open({\n title: `Task — ${task.title}`,\n width: 640,\n children: (\n <div className=\"task-detail\">\n <div className=\"task-detail-meta\">\n <span><strong>Status:</strong> {task.status}</span>\n <span><strong>Priority:</strong> {task.priority}</span>\n {task.assignee && <span><strong>Assignee:</strong> @{task.assignee}</span>}\n {task.workedBy && <span><strong>Working:</strong> <span className=\"is-working\" style={{ display: 'inline-block', padding: '0 6px' }}>@{task.workedBy}</span></span>}\n {task.dueDate && <span><strong>Due:</strong> {task.dueDate.slice(0, 10)}</span>}\n <span><strong>Time:</strong> {formatDuration(timerSeconds)}</span>\n </div>\n {task.description && (\n <Card>\n <CardTitle>Description</CardTitle>\n <div className=\"task-detail-desc\">{task.description}</div>\n </Card>\n )}\n <Card>\n <CardTitle><Bot size={14} /> Mark as worked on by</CardTitle>\n <div className=\"task-detail-row\">\n <select ref={(el) => { agentEl = el; }} className=\"select\" defaultValue={task.workedBy || ''}>\n <option value=\"\">(pick an agent)</option>\n {agents.map((a) => (\n <option key={a.name} value={a.name}>@{a.name}</option>\n ))}\n </select>\n <Button variant=\"primary\" size=\"sm\" onClick={() => onMarkWorkedBy('doing', false)}>\n <PlayCircle size={12} /> Start working\n </Button>\n <Button variant=\"success\" size=\"sm\" onClick={() => onMarkWorkedBy('done', true)}>\n <CheckSquare size={12} /> Complete\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => onMarkWorkedBy('idle', false)}>\n <PauseCircle size={12} /> Stop\n </Button>\n </div>\n </Card>\n <Card>\n <CardTitle><Clock size={14} /> Time tracking</CardTitle>\n <div className=\"task-detail-row\">\n {!task._timerStart ? (\n <Button variant=\"secondary\" size=\"sm\" onClick={onStartTimer}>\n <PlayCircle size={12} /> Start\n </Button>\n ) : (\n <Button variant=\"secondary\" size=\"sm\" onClick={onStopTimer} className=\"is-working\">\n <PauseCircle size={12} /> Stop\n </Button>\n )}\n <span className={cn('muted', task._timerStart ? 'is-working' : null)}>\n {formatDuration(timerSeconds)}\n {task._timerStart && ' (running)'}\n </span>\n </div>\n </Card>\n <Card>\n <CardTitle><Link2 size={14} /> Dependencies</CardTitle>\n <div className=\"task-detail-row\">\n <input\n ref={(el) => { depEl = el; }}\n className=\"input\"\n type=\"text\"\n placeholder=\"task id (e.g. tsk_abc12345)\"\n />\n <Button variant=\"secondary\" size=\"sm\" onClick={onAddDep}>Add</Button>\n </div>\n <ul>\n {(task.dependencies || []).map((d) => (\n <li key={d}><code>{d}</code></li>\n ))}\n {(task.dependencies || []).length === 0 && <li className=\"muted\">No dependencies.</li>}\n </ul>\n </Card>\n {task.recurring && (\n <Card>\n <CardTitle><Calendar size={14} /> Recurring</CardTitle>\n <div className=\"muted\">Frequency: <code>{task.recurring.freq || 'custom'}</code> {task.recurring.cron && <code>{task.recurring.cron}</code>}</div>\n {task.recurring.lastGenerated && (\n <div className=\"muted text-sm\">Last spawned: {formatRelative(task.recurring.lastGenerated)}</div>\n )}\n </Card>\n )}\n <Card>\n <CardTitle><MessageSquare size={14} /> Comments</CardTitle>\n <textarea\n ref={(el) => { commentEl = el; }}\n className=\"textarea\"\n rows={3}\n placeholder=\"Add a comment…\"\n />\n <Button variant=\"primary\" size=\"sm\" onClick={onComment}>Post</Button>\n <ul className=\"task-comments\">\n {(task.comments || []).map((c) => (\n <li key={c.id}>\n <div className=\"muted tabular-nums\">{formatRelative(c.createdAt)}</div>\n <div>{c.text}</div>\n </li>\n ))}\n {(task.comments || []).length === 0 && <li className=\"muted\">No comments.</li>}\n </ul>\n </Card>\n <Card>\n <CardTitle><Activity size={14} /> Activity</CardTitle>\n <ul className=\"task-activity\">\n {(task.activity || []).slice().reverse().slice(0, 20).map((a) => (\n <li key={a.id}>\n <span className=\"muted tabular-nums\">{formatRelative(a.ts)}</span>{' '}\n <span className=\"tag\">{a.type}</span>\n {a.data && typeof a.data === 'object' ? (\n <code className=\"muted\"> {JSON.stringify(a.data)}</code>\n ) : null}\n </li>\n ))}\n {(task.activity || []).length === 0 && <li className=\"muted\">No activity yet.</li>}\n </ul>\n </Card>\n </div>\n ),\n footer: (\n <div className=\"modal-footer-actions\">\n <Button variant=\"ghost\" onClick={() => modal.close()}>Close</Button>\n <Button variant=\"primary\" onClick={() => { modal.close(); openTaskModal(modal, toast, task, task.status, setTasks, reload, refreshSnapshot, agents); }}>\n <Sparkles size={12} /> Edit basics\n </Button>\n </div>\n ),\n });\n}\n\n// v3.2.0 — Submit a task to Odin. Odin splits it into subtasks and\n// assigns each to the best-fit agent. Falls back to a regular task\n// create if the delegator route is unavailable (older dashboards).\nfunction openSubmitTaskModal(\n modal: ReturnType<typeof useModal>,\n toast: ReturnType<typeof useToast>,\n setTasks: (updater: (cur: Task[]) => Task[]) => void,\n reload: () => Promise<void>,\n refreshSnapshot: () => Promise<void>,\n) {\n let titleEl: HTMLInputElement | null = null;\n let descEl: HTMLTextAreaElement | null = null;\n let priorityEl: HTMLSelectElement | null = null;\n let tagsEl: HTMLInputElement | null = null;\n\n // v3.3.0 — Wraps the submit click so we can preventDefault /\n // stopPropagation. Without this, a click on a button could bubble\n // up through the modal portal after the modal closes and either\n // trigger a sibling button or, more importantly, allow a\n // subsequent digit-key event to fire setActiveTab(\"overview\")\n // because the just-closed modal had removed the user's focused\n // form control.\n const onSubmit = async (e?: React.SyntheticEvent) => {\n if (e && typeof e.preventDefault === 'function') e.preventDefault();\n if (e && typeof e.stopPropagation === 'function') e.stopPropagation();\n const description = descEl?.value || '';\n let title = (titleEl?.value || '').trim();\n // v3.7.1 — Title is now optional. Auto-generate from the description\n // when the user left it blank. Reject only if BOTH fields are empty.\n if (!title && description.trim()) {\n title = autoTitleFromContent(description);\n if (titleEl) titleEl.value = title;\n }\n if (!title) {\n toast.warning('Add a description so Odin knows what to do.');\n return;\n }\n const priority = priorityEl?.value || 'normal';\n const tags = (tagsEl?.value || '')\n .split(',')\n .map((t: string) => t.trim())\n .filter(Boolean);\n\n try {\n const result = await api.post<{ main: Task; subtasks: Task[] }>('/tasks/submit', {\n title,\n description,\n priority,\n tags,\n });\n const count = (result.subtasks || []).length;\n toast.success(\n count > 1\n ? `Odin split it into ${count} subtasks.`\n : 'Task submitted to Odin.',\n );\n // v3.3.1 — CRITICAL: close modal FIRST, then bump safe window,\n // then update state. This way the portal unmount + React re-render\n // can't trigger any key handlers in the brief window before state\n // updates. We manually dispatch a synthetic mousedown to extend\n // the safe window so any stray keyboard events during the state-\n // update tick also can't trigger tab switches.\n modal.close();\n if (typeof window !== 'undefined') {\n window.dispatchEvent(new MouseEvent('mousedown'));\n }\n if (setTasks) setTasks((cur: Task[]) => [result.main, ...(result.subtasks || []), ...cur]);\n if (reload) await reload();\n if (refreshSnapshot) await refreshSnapshot();\n } catch (err) {\n toast.error(`Submit failed: ${(err as Error).message}`);\n }\n };\n\n // v3.3.0 — Submit on Enter from the title input. Without an\n // explicit onKeyDown, the implicit form-submit behavior can fire\n // when a user presses Enter. Even though we don't wrap inputs in\n // <form>, this is the safest pattern.\n const onTitleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n onSubmit(e);\n }\n };\n\n modal.open({\n title: 'Submit Task to Odin',\n width: 560,\n children: (\n <div className=\"submit-task-form\">\n <label htmlFor=\"submit-task-title\">\n Title <span className=\"field-hint\">(optional — auto-generated from description)</span>\n <input\n id=\"submit-task-title\"\n ref={(el) => { titleEl = el; }}\n className=\"input\"\n type=\"text\"\n placeholder=\"Leave blank to derive from description\"\n autoFocus\n onKeyDown={onTitleKeyDown}\n />\n <span className=\"field-hint\">\n Odin will analyze this and split it into subtasks assigned to the best agent.\n </span>\n </label>\n <label htmlFor=\"submit-task-desc\">\n Description\n <span style={{ display: 'flex', gap: 6, alignItems: 'flex-start' }}>\n <textarea\n id=\"submit-task-desc\"\n ref={(el) => { descEl = el; }}\n className=\"textarea\"\n rows={5}\n placeholder=\"Provide more detail (markdown ok)…\"\n style={{ flex: 1 }}\n />\n <button\n type=\"button\"\n className=\"btn btn-ghost btn-icon\"\n style={{ marginTop: 0, flexShrink: 0 }}\n title=\"Enhance prompt with AI\"\n onClick={async () => {\n if (!descEl?.value?.trim()) return;\n const enhanced = await enhancePrompt(descEl.value);\n if (enhanced !== descEl.value) descEl.value = enhanced;\n }}\n >\n <Sparkles size={14} />\n </button>\n </span>\n </label>\n <div className=\"task-form-row\">\n <label htmlFor=\"submit-task-priority\" className=\"task-form-field\">\n Priority\n <select\n id=\"submit-task-priority\"\n ref={(el) => { priorityEl = el; }}\n className=\"select\"\n defaultValue=\"normal\"\n >\n {PRIORITIES.map((p) => (\n <option key={p} value={p}>{p}</option>\n ))}\n </select>\n </label>\n <label htmlFor=\"submit-task-tags\" className=\"task-form-field\" style={{ flex: 2 }}>\n Tags <span className=\"field-hint\">(comma-separated)</span>\n <input\n id=\"submit-task-tags\"\n ref={(el) => { tagsEl = el; }}\n className=\"input\"\n type=\"text\"\n placeholder=\"backend, auth\"\n />\n </label>\n </div>\n </div>\n ),\n footer: (\n <div className=\"modal-footer-actions\">\n <Button variant=\"ghost\" onClick={() => modal.close()}>Cancel</Button>\n <Button\n variant=\"primary\"\n type=\"button\"\n onClick={(e) => onSubmit(e)}\n >\n <Send size={14} /> Submit to Odin\n </Button>\n </div>\n ),\n });\n}\n","// src/views/Activity.tsx — v3.5.4: timeline-based activity view (replaces the v3.5.2 graph+strip hybrid).\n// Layout: CSS grid with 3 sibling columns — left event stream, center timeline canvas, right detail panel.\n// X axis is time; Y axis is lanes (BG instances + tasks). Active tasks pulse; queued tasks are translucent\n// dashed; done tasks are faded. A red \"now\" line updates every 1s and re-anchors when it nears the right edge.\n\nimport {\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport {\n Activity as ActivityIcon,\n Bot,\n CheckSquare,\n Cpu,\n RefreshCw,\n Send,\n X,\n Plus,\n Trash2,\n MessageSquare,\n History,\n Pause,\n Play,\n PanelLeftClose,\n PanelLeftOpen,\n Layers,\n Target,\n FileText,\n} from 'lucide-react';\nimport { Button } from '../components/Button';\nimport { Card, CardTitle } from '../components/Card';\nimport { EmptyState } from '../components/EmptyState';\nimport { Spinner } from '../components/Spinner';\nimport { useToast } from '../components/Toast';\nimport { useModal } from '../components/Modal';\nimport { api } from '../lib/api';\nimport { cn } from '../lib/utils';\nimport type { Settings, Snapshot, Task, Agent } from '../lib/types';\nimport { openArtifactViewer } from '../components/ArtifactViewer';\n\ntype Props = {\n snapshot: Snapshot;\n settings: Settings;\n activeTab: string;\n setActiveTab: (id: string) => void;\n refreshSnapshot: () => Promise<void>;\n};\n\ntype BgInstance = {\n instanceId: string;\n agent?: string;\n status?: string;\n startedAt?: number;\n completedAt?: number;\n lastEventAt?: number;\n promptPreview?: string;\n resultPreview?: string;\n error?: string;\n parentAgent?: string;\n parentInstanceId?: string;\n tmuxSession?: string;\n tmuxActive?: boolean;\n taskId?: string; // v3.6.2 — linked task for artifact lookup\n _bgDir?: string;\n};\n\ntype ActivityEvent = {\n ts: string;\n kind: string;\n nodeId?: string;\n text?: string;\n author?: string;\n taskId?: string;\n [k: string]: unknown;\n};\n\n// ─── Time / layout constants ──────────────────────────────────────────\n\nconst ZOOM_RANGES = {\n '1m': 60 * 1000,\n '5m': 5 * 60 * 1000,\n '30m': 30 * 60 * 1000,\n '1h': 60 * 60 * 1000,\n} as const;\ntype ZoomKey = keyof typeof ZOOM_RANGES;\n\nconst LANE_HEIGHT = 56;\nconst TIME_AXIS_HEIGHT = 32;\nconst EVENTS_STRIP_HEIGHT = 22;\nconst MIN_BAR_WIDTH = 4;\nconst REANCHOR_RATIO = 0.9; // when now_x exceeds this fraction of canvas width, re-anchor viewStart\n\n// ─── Status → color ───────────────────────────────────────────────────\n\nconst STATUS_COLORS: Record<string, string> = {\n working: 'var(--success)',\n running: 'var(--success)',\n doing: 'var(--info)',\n queued: 'var(--info)',\n done: 'var(--success)',\n success: 'var(--success)',\n blocked: 'var(--warning)',\n error: 'var(--error)',\n failed: 'var(--error)',\n stuck: 'var(--warning)',\n killed: 'var(--error)',\n idle: 'var(--text-dim)',\n pending: 'var(--info)',\n timed_out: 'var(--warning)',\n};\n\nfunction statusColor(s: string | null | undefined): string {\n if (!s) return STATUS_COLORS.idle;\n return STATUS_COLORS[s] || STATUS_COLORS.idle;\n}\n\nfunction shortLabel(s: string | null | undefined, n = 24): string {\n if (!s) return '';\n if (s.length <= n) return s;\n return s.slice(0, n - 1) + '…';\n}\n\n// ─── Time helpers ─────────────────────────────────────────────────────\n\nfunction parseTs(ts: string | number | null | undefined): number {\n if (ts == null) return 0;\n if (typeof ts === 'number') return ts;\n const t = new Date(ts).getTime();\n return Number.isNaN(t) ? 0 : t;\n}\n\nfunction taskStartMs(t: Task): number {\n // v3.5.4 — prefer _timerStart (set when work begins), fall back to createdAt.\n const ts = (t as { _timerStart?: number })._timerStart;\n if (typeof ts === 'number' && ts > 0) return ts;\n return parseTs(t.createdAt) || Date.now();\n}\n\nfunction taskEndMs(t: Task, now: number): number {\n if (t.status === 'done' || t.status === 'archived' || t.status === 'failed' || t.status === 'killed') {\n return parseTs(t.completedAt) || parseTs(t.updatedAt) || now;\n }\n // Active tasks: pin to now.\n return now;\n}\n\nfunction bgStartMs(b: BgInstance): number {\n return typeof b.startedAt === 'number' && b.startedAt > 0 ? b.startedAt : Date.now();\n}\n\nfunction bgEndMs(b: BgInstance, now: number): number {\n if (\n b.status === 'done'\n || b.status === 'success'\n || b.status === 'killed'\n || b.status === 'failed'\n || b.status === 'error'\n || b.status === 'timed_out'\n ) {\n return b.completedAt || b.lastEventAt || now;\n }\n return now;\n}\n\nfunction chooseTickStep(rangeMs: number): number {\n if (rangeMs <= 60_000) return 10_000;\n if (rangeMs <= 300_000) return 30_000;\n if (rangeMs <= 1_800_000) return 300_000;\n return 600_000;\n}\n\nfunction formatTickLabel(t: number, rangeMs: number): string {\n const d = new Date(t);\n if (rangeMs <= 300_000) {\n return d.toLocaleTimeString('en-GB', { hour12: false });\n }\n return d.toLocaleTimeString('en-GB', { hour12: false, hour: '2-digit', minute: '2-digit' });\n}\n\n// ─── Lane + tick types ────────────────────────────────────────────────\n\ntype Lane =\n | { kind: 'bg'; id: string; index: number; label: string; sub: string; start: number; end: number; data: BgInstance }\n | { kind: 'task'; id: string; index: number; label: string; sub: string; start: number; end: number; data: Task }\n | { kind: 'events'; id: string; index: number; label: string; sub: string; start: number; end: number };\n\ntype SelectedItem = {\n id: string;\n kind: 'task' | 'bg' | 'agent';\n label: string;\n status: string;\n data: Task | BgInstance | Agent;\n};\n\ntype EventMarker = {\n id: string;\n x: number;\n y: number;\n kind: string;\n ts: number;\n text: string;\n author?: string;\n};\n\ntype TaskBar = {\n id: string;\n laneIndex: number;\n x: number;\n y: number;\n w: number;\n h: number;\n label: string;\n statusClass: 'doing' | 'done' | 'queued' | 'blocked' | 'failed';\n selected: boolean;\n data: Task | BgInstance;\n kind: 'task' | 'bg';\n start: number;\n end: number;\n};\n\n// ─── Component ────────────────────────────────────────────────────────\n\nexport function Activity({ snapshot, refreshSnapshot }: Props) {\n const toast = useToast();\n const canvasWrapRef = useRef<HTMLDivElement | null>(null);\n\n // View state\n const [mode, setMode] = useState<'live' | 'pause'>('live');\n const [zoom, setZoom] = useState<ZoomKey>('5m');\n const [streamOpen, setStreamOpen] = useState(() => {\n if (typeof window === 'undefined') return true;\n return window.innerWidth > 900;\n });\n\n // Data\n const [bgInstances, setBgInstances] = useState<BgInstance[]>([]);\n const [events, setEvents] = useState<ActivityEvent[]>([]);\n const [loading, setLoading] = useState(true);\n const [refreshTick, setRefreshTick] = useState(0);\n\n // Time\n const [nowTick, setNowTick] = useState<number>(Date.now());\n const [viewStart, setViewStart] = useState<number>(() => Date.now() - ZOOM_RANGES['5m'] * 0.1);\n\n // Canvas size (observed)\n const [canvasSize, setCanvasSize] = useState<{ width: number; height: number }>({ width: 800, height: 400 });\n\n // Selection / detail\n const [selectedItem, setSelectedItem] = useState<SelectedItem | null>(null);\n\n // Detail panel local state\n const [commentText, setCommentText] = useState('');\n const [comments, setComments] = useState<ActivityEvent[]>([]);\n const [taskTitle, setTaskTitle] = useState('');\n const [taskPriority, setTaskPriority] = useState('normal');\n const [bgMessage, setBgMessage] = useState('');\n const [bgOutput, setBgOutput] = useState('');\n const [creatingTask, setCreatingTask] = useState(false);\n const [postingComment, setPostingComment] = useState(false);\n // v3.6.2 — artifact IDs fetched from the task linked to the selected bg instance.\n const [bgArtifactIds, setBgArtifactIds] = useState<string[]>([]);\n\n const modal = useModal();\n\n const agents = snapshot.agents || [];\n const tasks = snapshot.tasks || [];\n const rangeMs = ZOOM_RANGES[zoom];\n const rangeStart = viewStart;\n const rangeEnd = viewStart + rangeMs;\n\n // ─── Data polling ───────────────────────────────────────────────────\n const reloadAll = useCallback(async () => {\n try {\n const [bgRes, evRes] = await Promise.all([\n api.get<{ instances: BgInstance[] }>('/background').catch(() => ({ instances: [] })),\n api.get<{ events: ActivityEvent[] }>('/activity?limit=200').catch(() => ({ events: [] })),\n ]);\n setBgInstances(bgRes.instances || []);\n setEvents(evRes.events || []);\n } catch (err) {\n console.warn('activity reload failed:', err);\n } finally {\n setLoading(false);\n }\n }, []);\n\n useEffect(() => {\n reloadAll();\n const id = setInterval(reloadAll, 3000);\n return () => clearInterval(id);\n }, [reloadAll]);\n\n // Trigger a re-fetch when the snapshot's task/agent counts change.\n useEffect(() => {\n setRefreshTick((t) => t + 1);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [tasks.length, agents.length]);\n\n // ─── Now tick (1s) — paused when mode === 'pause' ───────────────────\n useEffect(() => {\n if (mode === 'pause') return;\n setNowTick(Date.now());\n const id = setInterval(() => setNowTick(Date.now()), 1000);\n return () => clearInterval(id);\n }, [mode, refreshTick]);\n\n // ─── Re-anchor viewStart when the now line nears the right edge ────\n useEffect(() => {\n if (mode === 'pause') return;\n const nowRatio = (nowTick - viewStart) / rangeMs;\n if (nowRatio > REANCHOR_RATIO) {\n setViewStart(nowTick - rangeMs * 0.1);\n }\n }, [nowTick, viewStart, rangeMs, mode]);\n\n // On zoom change, reset viewStart so now sits at 10% from the left.\n useEffect(() => {\n setViewStart(Date.now() - rangeMs * 0.1);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [zoom]);\n\n // On resume from pause, re-anchor so the now line lands at 10%.\n useEffect(() => {\n if (mode === 'live') {\n setViewStart(Date.now() - rangeMs * 0.1);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [mode]);\n\n // ─── Canvas size observer ───────────────────────────────────────────\n useLayoutEffect(() => {\n const el = canvasWrapRef.current;\n if (!el) return;\n const ro = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const { width, height } = entry.contentRect;\n setCanvasSize({\n width: Math.max(200, Math.floor(width)),\n height: Math.max(120, Math.floor(height)),\n });\n }\n });\n ro.observe(el);\n return () => ro.disconnect();\n }, []);\n\n // ─── Lane allocation ────────────────────────────────────────────────\n const lanes: Lane[] = useMemo(() => {\n const out: Lane[] = [];\n let idx = 0;\n\n // BG instances — one lane each, at the top.\n for (const bg of bgInstances) {\n const start = bgStartMs(bg);\n const end = bgEndMs(bg, nowTick);\n if (end < rangeStart || start > rangeEnd) continue;\n out.push({\n kind: 'bg',\n id: `bg:${bg.instanceId}`,\n index: idx++,\n label: `BG ${shortLabel(bg.promptPreview, 20) || bg.instanceId.slice(0, 10)}`,\n sub: bg.status || 'pending',\n start,\n end,\n data: bg,\n });\n }\n\n // Tasks — greedy lane assignment (fill first lane that has no overlap).\n const sorted = [...tasks].sort((a, b) => taskStartMs(a) - taskStartMs(b));\n const taskLaneEnds: number[] = []; // end-time of last task placed in each lane\n for (const t of sorted) {\n const s = taskStartMs(t);\n const e = taskEndMs(t, nowTick);\n if (e < rangeStart || s > rangeEnd) continue;\n let assigned = -1;\n for (let i = 0; i < taskLaneEnds.length; i++) {\n if (taskLaneEnds[i] <= s) {\n taskLaneEnds[i] = e;\n assigned = i;\n break;\n }\n }\n if (assigned === -1) {\n taskLaneEnds.push(e);\n assigned = taskLaneEnds.length - 1;\n }\n out.push({\n kind: 'task',\n id: `task:${t.id}`,\n index: idx + assigned,\n label: shortLabel(t.title, 32),\n sub: t.status,\n start: s,\n end: e,\n data: t,\n });\n }\n\n return out;\n }, [bgInstances, tasks, nowTick, rangeStart, rangeEnd]);\n\n const laneById = useMemo(() => {\n const m = new Map<string, Lane>();\n for (const l of lanes) m.set(l.id, l);\n return m;\n }, [lanes]);\n\n // ─── Time → X coordinate ────────────────────────────────────────────\n const timeToX = useCallback(\n (t: number): number => {\n if (rangeMs <= 0) return 0;\n return ((t - rangeStart) / rangeMs) * canvasSize.width;\n },\n [rangeStart, rangeMs, canvasSize.width],\n );\n\n // ─── Tick marks for the time axis ───────────────────────────────────\n const ticks = useMemo(() => {\n const step = chooseTickStep(rangeMs);\n const result: { t: number; x: number; label: string }[] = [];\n // Align to step boundary.\n const startAligned = Math.floor(rangeStart / step) * step;\n for (let t = startAligned; t <= rangeEnd + step; t += step) {\n if (t < rangeStart - step) continue;\n if (t > rangeEnd) break;\n const x = timeToX(t);\n if (x < -40 || x > canvasSize.width + 40) continue;\n result.push({ t, x, label: formatTickLabel(t, rangeMs) });\n }\n return result;\n }, [rangeStart, rangeEnd, rangeMs, canvasSize.width, timeToX]);\n\n // ─── Build task/bg bars ─────────────────────────────────────────────\n const bars: TaskBar[] = useMemo(() => {\n const out: TaskBar[] = [];\n for (const lane of lanes) {\n if (lane.kind === 'events') continue;\n const visibleStart = Math.max(lane.start, rangeStart);\n const visibleEnd = Math.min(lane.end, rangeEnd);\n if (visibleEnd < rangeStart || visibleStart > rangeEnd) continue;\n const x = timeToX(visibleStart);\n const xEnd = timeToX(visibleEnd);\n const w = Math.max(MIN_BAR_WIDTH, xEnd - x);\n const y = TIME_AXIS_HEIGHT + EVENTS_STRIP_HEIGHT + lane.index * LANE_HEIGHT + 8;\n const h = LANE_HEIGHT - 16;\n\n let statusClass: TaskBar['statusClass'] = 'doing';\n if (lane.kind === 'bg') {\n const s = lane.data.status || 'pending';\n if (s === 'done' || s === 'success') statusClass = 'done';\n else if (s === 'failed' || s === 'killed' || s === 'error') statusClass = 'failed';\n else if (s === 'queued' || s === 'pending') statusClass = 'queued';\n else if (s === 'blocked' || s === 'stuck') statusClass = 'blocked';\n else statusClass = 'doing';\n } else {\n const s = lane.data.status;\n if (s === 'done' || s === 'archived') statusClass = 'done';\n else if (s === 'failed' || s === 'killed') statusClass = 'failed';\n else if (s === 'queued') statusClass = 'queued';\n else if (s === 'blocked') statusClass = 'blocked';\n else statusClass = 'doing';\n }\n\n const selected = selectedItem?.id === lane.id;\n\n out.push({\n id: lane.id,\n laneIndex: lane.index,\n x,\n y,\n w,\n h,\n label: lane.label,\n statusClass,\n selected,\n data: lane.data,\n kind: lane.kind,\n start: lane.start,\n end: lane.end,\n });\n }\n return out;\n }, [lanes, timeToX, selectedItem, rangeStart, rangeEnd]);\n\n // ─── Build event markers (placed on the lane of their related entity) ─\n const eventMarkers: EventMarker[] = useMemo(() => {\n const out: EventMarker[] = [];\n for (const ev of events) {\n const ts = parseTs(ev.ts);\n if (ts < rangeStart - 5000 || ts > rangeEnd + 5000) continue;\n const x = timeToX(ts);\n\n // Try to find a related lane.\n let y = TIME_AXIS_HEIGHT + 12; // default: events strip\n if (ev.taskId) {\n const lane = laneById.get(`task:${ev.taskId}`);\n if (lane) y = TIME_AXIS_HEIGHT + EVENTS_STRIP_HEIGHT + lane.index * LANE_HEIGHT + LANE_HEIGHT / 2;\n } else if (ev.nodeId) {\n const id = String(ev.nodeId);\n const lane = laneById.get(id.startsWith('task:') || id.startsWith('bg:') ? id : `task:${id}`);\n if (lane) y = TIME_AXIS_HEIGHT + EVENTS_STRIP_HEIGHT + lane.index * LANE_HEIGHT + LANE_HEIGHT / 2;\n }\n\n out.push({\n id: `${ev.ts}-${ev.kind}-${ev.author ?? ''}-${ev.taskId ?? ''}`,\n x,\n y,\n kind: ev.kind || 'event',\n ts,\n text: String(ev.text || ev.kind || ''),\n author: ev.author as string | undefined,\n });\n }\n return out;\n }, [events, rangeStart, rangeEnd, timeToX, laneById]);\n\n // ─── Lane backgrounds (alternating) ─────────────────────────────────\n const laneRects = useMemo(() => {\n return lanes.map((lane) => ({\n id: lane.id,\n y: TIME_AXIS_HEIGHT + EVENTS_STRIP_HEIGHT + lane.index * LANE_HEIGHT,\n h: LANE_HEIGHT,\n }));\n }, [lanes]);\n\n // ─── Now line position ──────────────────────────────────────────────\n const nowX = useMemo(() => {\n const x = timeToX(nowTick);\n return Math.max(0, Math.min(canvasSize.width, x));\n }, [timeToX, nowTick, canvasSize.width]);\n\n // ─── Click on a bar → open detail panel ─────────────────────────────\n const onSelectBar = useCallback((bar: TaskBar) => {\n const id = bar.id; // 'task:xxx' or 'bg:xxx'\n const item: SelectedItem = {\n id,\n kind: bar.kind,\n label: bar.label,\n status: bar.statusClass,\n data: bar.data,\n };\n setSelectedItem(item);\n }, []);\n\n // ─── Detail panel: fetch related data when selection changes ────────\n useEffect(() => {\n if (!selectedItem) {\n setComments([]);\n setBgOutput('');\n setBgArtifactIds([]);\n return;\n }\n setCommentText('');\n setTaskTitle('');\n setBgMessage('');\n setBgArtifactIds([]);\n (async () => {\n try {\n const r = await api.get<{ events: ActivityEvent[] }>(\n `/activity?nodeId=${encodeURIComponent(selectedItem.id)}&limit=50`,\n );\n setComments(r.events || []);\n } catch {\n setComments([]);\n }\n if (selectedItem.kind === 'bg') {\n const bgData = selectedItem.data as BgInstance;\n try {\n const r = await api.get<{ output: string }>(\n `/background/${encodeURIComponent(bgData.instanceId)}/output?lines=80`,\n );\n setBgOutput(r.output || '');\n } catch {\n setBgOutput('');\n }\n // v3.6.2 — If the bg instance has a linked taskId, fetch its artifacts.\n if (bgData.taskId) {\n try {\n const artR = await api.get<{ artifacts: { id: string }[] }>(\n `/tasks/${encodeURIComponent(bgData.taskId)}/artifacts`,\n );\n setBgArtifactIds((artR.artifacts || []).map((a) => a.id));\n } catch {\n setBgArtifactIds([]);\n }\n }\n }\n })();\n }, [selectedItem]);\n\n // ─── Detail actions ─────────────────────────────────────────────────\n const onAddComment = async () => {\n if (!selectedItem || !commentText.trim()) return;\n setPostingComment(true);\n try {\n await api.post('/comments', { nodeId: selectedItem.id, text: commentText, author: 'user' });\n setCommentText('');\n const r = await api.get<{ events: ActivityEvent[] }>(\n `/activity?nodeId=${encodeURIComponent(selectedItem.id)}&limit=50`,\n );\n setComments(r.events || []);\n toast.success('Comment added.');\n } catch (err) {\n toast.error(`Comment failed: ${(err as Error).message}`);\n } finally {\n setPostingComment(false);\n }\n };\n\n const onCreateTaskFromNode = async () => {\n if (!selectedItem || !taskTitle.trim()) return;\n setCreatingTask(true);\n try {\n await api.post(`/nodes/${encodeURIComponent(selectedItem.id)}/tasks`, {\n title: taskTitle,\n description: `Created from timeline selection ${selectedItem.id}.`,\n priority: taskPriority,\n });\n setTaskTitle('');\n toast.success('Task created.');\n await refreshSnapshot();\n } catch (err) {\n toast.error(`Task create failed: ${(err as Error).message}`);\n } finally {\n setCreatingTask(false);\n }\n };\n\n const onSendBgMessage = async () => {\n if (!selectedItem || selectedItem.kind !== 'bg' || !bgMessage.trim()) return;\n const bgData = selectedItem.data as BgInstance;\n try {\n const r = await api.post<{ ok: boolean; error?: string }>(\n `/background/${encodeURIComponent(bgData.instanceId)}/message`,\n { message: bgMessage },\n );\n if (r.ok) {\n toast.success('Message sent.');\n setBgMessage('');\n } else {\n toast.warning(r.error || 'Send failed');\n }\n } catch (err) {\n toast.error(`Send failed: ${(err as Error).message}`);\n }\n };\n\n const onKillBg = async () => {\n if (!selectedItem || selectedItem.kind !== 'bg') return;\n if (!confirm('Kill this bg instance session?')) return;\n const bgData = selectedItem.data as BgInstance;\n try {\n const r = await api.del<{ ok: boolean; error?: string }>(\n `/background/${encodeURIComponent(bgData.instanceId)}`,\n );\n if (r.ok) toast.success('Session killed.');\n else toast.warning(r.error || 'Kill failed');\n await reloadAll();\n } catch (err) {\n toast.error(`Kill failed: ${(err as Error).message}`);\n }\n };\n\n const refetchOutput = async () => {\n if (!selectedItem || selectedItem.kind !== 'bg') return;\n const bgData = selectedItem.data as BgInstance;\n try {\n const r = await api.get<{ output: string }>(\n `/background/${encodeURIComponent(bgData.instanceId)}/output?lines=80`,\n );\n setBgOutput(r.output || '');\n } catch {\n /* ignore */\n }\n };\n\n // ─── Keyboard helpers ───────────────────────────────────────────────\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') setSelectedItem(null);\n };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, []);\n\n // ─── Refresh handler ────────────────────────────────────────────────\n const refresh = () => {\n setRefreshTick((t) => t + 1);\n reloadAll();\n };\n\n // ─── Derived: total content height (for SVG sizing) ─────────────────\n const contentHeight = TIME_AXIS_HEIGHT + EVENTS_STRIP_HEIGHT + lanes.length * LANE_HEIGHT;\n\n // ─── Render ─────────────────────────────────────────────────────────\n return (\n <div className=\"view view-activity\">\n {/* Top header bar — title + live/pause + zoom + refresh */}\n <header className=\"view-header\">\n <div className=\"view-header-text\">\n <h2 className=\"view-title\">\n <ActivityIcon size={18} /> Activity\n </h2>\n <p className=\"view-subtitle\">\n Live timeline of agents, tasks, and background sessions. Active tasks pulse; the red line marks “now”.\n </p>\n </div>\n <div className=\"view-actions\">\n <div className=\"tl-mode-toggle\">\n <Button\n variant={mode === 'live' ? 'primary' : 'secondary'}\n size=\"sm\"\n onClick={() => setMode(mode === 'live' ? 'pause' : 'live')}\n title={mode === 'live' ? 'Pause timeline' : 'Resume timeline'}\n >\n {mode === 'live' ? <Pause size={14} /> : <Play size={14} />}\n {mode === 'live' ? 'Live' : 'Paused'}\n </Button>\n <div className=\"tl-zoom-group\">\n {(['1m', '5m', '30m', '1h'] as ZoomKey[]).map((z) => (\n <button\n type=\"button\"\n key={z}\n className={cn('tl-zoom-btn', zoom === z && 'tl-zoom-btn-active')}\n onClick={() => setZoom(z)}\n title={`Zoom to ${z}`}\n >\n {z}\n </button>\n ))}\n </div>\n <Button variant=\"secondary\" size=\"sm\" onClick={refresh} title=\"Refresh\">\n <RefreshCw size={14} /> Refresh\n </Button>\n </div>\n </div>\n </header>\n\n {loading && (\n <div className=\"view-loading\"><Spinner size=\"lg\" /></div>\n )}\n\n {!loading && agents.length === 0 && tasks.length === 0 && bgInstances.length === 0 && events.length === 0 ? (\n <EmptyState\n icon={<ActivityIcon size={32} />}\n title=\"No activity yet\"\n message=\"Once agents, tasks, or background instances exist, they'll show up here on the timeline.\"\n />\n ) : (\n <div className={cn('tl-view', selectedItem && 'tl-view-detail-open')}>\n <div className={cn('tl-body', !streamOpen && 'tl-body-stream-collapsed')}>\n {/* Left column — event stream (sibling, not overlay) */}\n <aside className={cn('tl-stream', !streamOpen && 'tl-stream-collapsed')}>\n <div className=\"tl-stream-head\">\n <h3>\n <History size={13} /> Live events\n </h3>\n <button\n type=\"button\"\n className=\"icon-btn\"\n onClick={() => setStreamOpen(false)}\n title=\"Hide event stream\"\n aria-label=\"Hide event stream\"\n >\n <PanelLeftClose size={14} />\n </button>\n </div>\n <div className=\"tl-stream-list\">\n {events.length === 0 ? (\n <div className=\"tl-stream-empty\">\n <p>No events yet.</p>\n </div>\n ) : (\n [...events].reverse().map((ev, i) => {\n const Icon =\n ev.author ? Bot : ev.kind === 'task' ? CheckSquare : ev.kind === 'bg' ? Cpu : ActivityIcon;\n return (\n <div key={`${ev.ts}-${i}`} className=\"tl-stream-event\">\n <span className=\"tl-stream-event-time\">\n {new Date(ev.ts).toLocaleTimeString('en-GB', { hour12: false })}\n </span>\n <span className=\"tl-stream-event-icon\" style={{ color: statusColor(ev.kind) }}>\n <Icon size={12} />\n </span>\n <span className=\"tl-stream-event-text\">\n {ev.author || ev.text || ev.kind}\n </span>\n </div>\n );\n })\n )}\n </div>\n </aside>\n\n {/* Center column — timeline canvas */}\n <div className=\"tl-canvas-wrap\" ref={canvasWrapRef}>\n <div className=\"tl-canvas-toolbar\">\n <div className=\"tl-canvas-toolbar-left\">\n {!streamOpen && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setStreamOpen(true)}\n title=\"Show event stream\"\n >\n <PanelLeftOpen size={14} /> Events\n </Button>\n )}\n <span className=\"tl-canvas-mode\">\n {mode === 'live' ? '● Live' : '⏸ Paused'}\n </span>\n <span className=\"tl-canvas-range\">\n {new Date(rangeStart).toLocaleTimeString('en-GB', { hour12: false })} →{' '}\n {new Date(rangeEnd).toLocaleTimeString('en-GB', { hour12: false })}\n </span>\n </div>\n <div className=\"tl-canvas-legend\">\n <span className=\"tl-legend-item\"><span className=\"tl-legend-dot\" style={{ background: 'var(--success)' }} /> active</span>\n <span className=\"tl-legend-item\"><span className=\"tl-legend-dot tl-legend-dot-dashed\" style={{ borderColor: 'var(--info)' }} /> queued</span>\n <span className=\"tl-legend-item\"><span className=\"tl-legend-dot\" style={{ background: 'var(--warning)' }} /> blocked</span>\n <span className=\"tl-legend-item\"><span className=\"tl-legend-dot\" style={{ background: 'var(--error)' }} /> error</span>\n <span className=\"tl-legend-sep\" />\n <span className=\"tl-legend-item\"><Layers size={11} /> agent</span>\n <span className=\"tl-legend-item\"><Target size={11} /> task</span>\n <span className=\"tl-legend-item\"><Cpu size={11} /> bg</span>\n </div>\n </div>\n\n <div className=\"tl-canvas-scroll\">\n <svg\n className=\"tl-canvas\"\n width={canvasSize.width}\n height={Math.max(canvasSize.height, contentHeight)}\n role=\"application\"\n aria-label=\"Activity timeline\"\n >\n <defs>\n <pattern\n id=\"tl-canvas-grid\"\n width={canvasSize.width}\n height={LANE_HEIGHT}\n patternUnits=\"userSpaceOnUse\"\n >\n <path\n d={`M 0 0 L 0 ${LANE_HEIGHT}`}\n fill=\"none\"\n stroke=\"var(--border)\"\n strokeWidth={0.5}\n opacity={0.35}\n />\n </pattern>\n </defs>\n <rect width=\"100%\" height=\"100%\" fill=\"url(#tl-canvas-grid)\" />\n\n {/* Lane backgrounds (alternating) */}\n {laneRects.map((lr) => (\n <rect\n key={`bg-${lr.id}`}\n className=\"tl-lane-bg\"\n x={0}\n y={lr.y}\n width={canvasSize.width}\n height={lr.h}\n fill={lr.id.charCodeAt(lr.id.length - 1) % 2 === 0 ? 'var(--bg-elev-2)' : 'var(--bg-elev)'}\n opacity={0.4}\n />\n ))}\n\n {/* Time axis tick lines + labels */}\n <g className=\"tl-time-axis\">\n {ticks.map((t) => (\n <g key={`tick-${t.t}`}>\n <line\n x1={t.x}\n y1={0}\n x2={t.x}\n y2={contentHeight}\n stroke=\"var(--border)\"\n strokeWidth={0.5}\n strokeDasharray=\"2,4\"\n opacity={0.5}\n />\n <text\n x={t.x + 4}\n y={TIME_AXIS_HEIGHT - 8}\n fontSize={10}\n fontFamily=\"var(--font-mono)\"\n fill=\"var(--text-dim)\"\n >\n {t.label}\n </text>\n </g>\n ))}\n </g>\n\n {/* Lane labels (rendered inside SVG, x=4) */}\n {lanes.map((lane) => {\n const y = TIME_AXIS_HEIGHT + EVENTS_STRIP_HEIGHT + lane.index * LANE_HEIGHT + LANE_HEIGHT / 2;\n return (\n <g key={`label-${lane.id}`} className=\"tl-lane-label-group\">\n <text\n x={6}\n y={y - 2}\n className=\"tl-lane-label\"\n textAnchor=\"start\"\n >\n {shortLabel(lane.label, 28)}\n </text>\n <text\n x={6}\n y={y + 10}\n className=\"tl-lane-label-sub\"\n textAnchor=\"start\"\n >\n {lane.sub}\n </text>\n </g>\n );\n })}\n\n {/* Task / BG bars */}\n {bars.map((bar) => {\n const fillColor = statusColor(bar.statusClass);\n const isSelected = bar.id === selectedItem?.id;\n return (\n <g\n key={`bar-${bar.id}`}\n className={cn('tl-task-bar', `tl-task-bar-${bar.statusClass}`, isSelected && 'tl-task-bar-selected')}\n onClick={() => onSelectBar(bar)}\n >\n <rect\n x={bar.x}\n y={bar.y}\n width={bar.w}\n height={bar.h}\n rx={6}\n fill={fillColor}\n fillOpacity={bar.statusClass === 'done' ? 0.35 : bar.statusClass === 'queued' ? 0.18 : 0.85}\n stroke={fillColor}\n strokeWidth={isSelected ? 2.5 : 1.5}\n strokeOpacity={bar.statusClass === 'done' ? 0.5 : 1}\n strokeDasharray={bar.statusClass === 'queued' ? '4 4' : undefined}\n style={{ cursor: 'pointer' }}\n />\n {bar.w > 36 && (\n <text\n x={bar.x + 8}\n y={bar.y + bar.h / 2 + 4}\n fontSize={11}\n fontFamily=\"var(--font-sans)\"\n fontWeight={500}\n fill=\"var(--text-strong)\"\n style={{ pointerEvents: 'none' }}\n opacity={bar.statusClass === 'done' ? 0.7 : 1}\n >\n {shortLabel(bar.label, Math.max(4, Math.floor(bar.w / 7)))}\n </text>\n )}\n </g>\n );\n })}\n\n {/* Event markers */}\n {eventMarkers.map((m) => {\n const color = statusColor(m.kind);\n return (\n <g key={`ev-${m.id}`} className=\"tl-event-marker-group\">\n <line\n x1={m.x}\n y1={m.y - 6}\n x2={m.x}\n y2={m.y + 6}\n stroke={color}\n strokeWidth={1.2}\n opacity={0.7}\n />\n <circle\n cx={m.x}\n cy={m.y}\n r={4}\n fill={color}\n opacity={0.9}\n >\n <title>\n {`${m.kind}${m.author ? ` · ${m.author}` : ''} · ${new Date(m.ts).toLocaleTimeString('en-GB', { hour12: false })}`}\n </title>\n </circle>\n </g>\n );\n })}\n\n {/* Now line (red, vertical) */}\n <line\n className=\"tl-now-line\"\n x1={nowX}\n y1={0}\n x2={nowX}\n y2={contentHeight}\n stroke=\"var(--error)\"\n strokeWidth={1.5}\n opacity={0.9}\n />\n <g className=\"tl-now-marker\">\n <circle cx={nowX} cy={TIME_AXIS_HEIGHT - 4} r={4} fill=\"var(--error)\" />\n <text\n x={nowX + 6}\n y={TIME_AXIS_HEIGHT - 4}\n fontSize={10}\n fontWeight={700}\n fill=\"var(--error)\"\n fontFamily=\"var(--font-mono)\"\n >\n now\n </text>\n </g>\n </svg>\n </div>\n </div>\n\n {/* Right column — detail panel */}\n {selectedItem && (\n <aside className=\"tl-detail tl-detail-enter\" key={selectedItem.id}>\n <Card>\n <CardTitle>\n {selectedItem.kind === 'agent' && <Bot size={14} />}\n {selectedItem.kind === 'task' && <CheckSquare size={14} />}\n {selectedItem.kind === 'bg' && <Cpu size={14} />}\n {selectedItem.label}\n <button\n type=\"button\"\n className=\"icon-btn\"\n onClick={() => setSelectedItem(null)}\n title=\"Close\"\n aria-label=\"Close activity detail\"\n style={{ marginLeft: 'auto' }}\n >\n <X size={14} />\n </button>\n </CardTitle>\n <div className=\"tl-detail-meta\">\n <div><span className=\"muted\">type</span> {selectedItem.kind}</div>\n <div><span className=\"muted\">status</span> <code>{selectedItem.status}</code></div>\n {selectedItem.kind === 'agent' && (() => {\n const a = selectedItem.data as Agent;\n return (\n <>\n {a.role && <div><span className=\"muted\">role</span> {a.role}</div>}\n {a.model && <div><span className=\"muted\">model</span> {a.model}</div>}\n </>\n );\n })()}\n {selectedItem.kind === 'task' && (() => {\n const t = selectedItem.data as Task;\n return (\n <>\n {t.assignee && <div><span className=\"muted\">assignee</span> @{t.assignee}</div>}\n {t.priority && <div><span className=\"muted\">priority</span> {t.priority}</div>}\n {t.createdAt && <div><span className=\"muted\">created</span> {new Date(t.createdAt).toLocaleString()}</div>}\n </>\n );\n })()}\n {selectedItem.kind === 'bg' && (() => {\n const b = selectedItem.data as BgInstance;\n return (\n <>\n {b.startedAt && <div><span className=\"muted\">started</span> {new Date(b.startedAt).toLocaleString()}</div>}\n {b.tmuxSession && <div><span className=\"muted\">tmux</span> <code>{b.tmuxSession}</code> {b.tmuxActive ? <span className=\"tag tag-success\">active</span> : <span className=\"tag\">inactive</span>}</div>}\n </>\n );\n })()}\n </div>\n {selectedItem.kind === 'task' && (selectedItem.data as Task).description && (\n <div className=\"tl-detail-desc\">{(selectedItem.data as Task).description}</div>\n )}\n {selectedItem.kind === 'bg' && (selectedItem.data as BgInstance).promptPreview && (\n <div className=\"tl-detail-desc\">{(selectedItem.data as BgInstance).promptPreview}</div>\n )}\n\n {selectedItem.kind === 'bg' && (\n <div className=\"tl-detail-bg\">\n <pre className=\"tl-bg-output\">{bgOutput || '(no output — start the session via tmux attach)'}</pre>\n <div className=\"tl-bg-output-actions\">\n <Button variant=\"ghost\" size=\"sm\" onClick={refetchOutput}>\n <RefreshCw size={12} /> Refresh output\n </Button>\n {bgArtifactIds.length > 0 && (\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={() => openArtifactViewer(modal, bgArtifactIds[0])}\n >\n <FileText size={12} /> Open artifact\n </Button>\n )}\n <Button variant=\"danger\" size=\"sm\" onClick={onKillBg}>\n <Trash2 size={12} /> Kill session\n </Button>\n </div>\n <div className=\"tl-form-row\">\n <input\n className=\"input\"\n placeholder=\"Send a message to this bg session…\"\n value={bgMessage}\n onChange={(e) => setBgMessage(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') onSendBgMessage();\n }}\n />\n <Button variant=\"primary\" size=\"sm\" disabled={!bgMessage.trim()} onClick={onSendBgMessage}>\n <Send size={12} /> Send\n </Button>\n </div>\n </div>\n )}\n\n {selectedItem.kind !== 'bg' && (\n <div className=\"tl-detail-create\">\n <div className=\"field-label\">Create follow-up task</div>\n <input\n className=\"input\"\n placeholder=\"Task title\"\n value={taskTitle}\n onChange={(e) => setTaskTitle(e.target.value)}\n />\n <div className=\"tl-form-row\">\n <select\n className=\"select\"\n value={taskPriority}\n onChange={(e) => setTaskPriority(e.target.value)}\n >\n <option value=\"low\">Low</option>\n <option value=\"normal\">Normal</option>\n <option value=\"high\">High</option>\n </select>\n <Button\n variant=\"primary\"\n size=\"sm\"\n disabled={!taskTitle.trim() || creatingTask}\n onClick={onCreateTaskFromNode}\n >\n <Plus size={12} /> Add task\n </Button>\n </div>\n </div>\n )}\n\n <div className=\"tl-detail-comments\">\n <div className=\"field-label\">\n <MessageSquare size={12} /> Comments & activity\n </div>\n <ul className=\"comment-list\">\n {comments.length === 0 && <li className=\"muted\">No comments yet.</li>}\n {comments.map((c, i) => (\n <li key={`c-${i}`} className=\"comment-item\">\n <div className=\"comment-head\">\n <strong>{c.author || 'system'}</strong>\n <span className=\"muted\">\n {c.kind} · {new Date(c.ts).toLocaleString()}\n </span>\n </div>\n {c.text && <div className=\"comment-text\">{c.text}</div>}\n {c.taskId && (\n <div className=\"muted\">\n → task <code>{String(c.taskId)}</code>\n </div>\n )}\n </li>\n ))}\n </ul>\n <div className=\"comment-input-row\">\n <input\n className=\"input\"\n placeholder=\"Add a comment…\"\n value={commentText}\n onChange={(e) => setCommentText(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' && !e.shiftKey) onAddComment();\n }}\n />\n <Button\n variant=\"secondary\"\n size=\"sm\"\n disabled={!commentText.trim() || postingComment}\n onClick={onAddComment}\n >\n <Send size={12} /> Post\n </Button>\n </div>\n </div>\n </Card>\n </aside>\n )}\n </div>\n </div>\n )}\n </div>\n );\n}\n","// src/views/Config.tsx — v3.4.0: sidebar nav + fully editable providers/MCPs.\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport {\n Settings2,\n RefreshCw,\n Save,\n FileCode2,\n Stethoscope,\n Server as ServerIcon,\n Plug,\n Plus,\n Trash2,\n Pencil,\n Download,\n Database,\n History as HistoryIcon,\n X,\n ShieldCheck,\n AlertTriangle,\n ChevronDown,\n ChevronRight,\n} from 'lucide-react';\nimport { Spinner } from '../components/Spinner';\nimport { Button } from '../components/Button';\nimport { Card, CardTitle, CardMeta } from '../components/Card';\nimport { useToast } from '../components/Toast';\nimport { useModal } from '../components/Modal';\nimport { api } from '../lib/api';\nimport { cn, debounce, hashText } from '../lib/utils';\nimport type {\n ConfigResponse,\n Diagnostics,\n McpServer,\n Provider,\n Settings,\n Snapshot,\n} from '../lib/types';\n\ntype LightragStatus = {\n running: boolean;\n pid: number | null;\n host: string;\n port: number;\n llmBinding: string;\n embeddingBinding: string;\n llmBindingHost: string;\n embeddingBindingHost: string;\n llmModel: string;\n embeddingModel: string;\n lastError: string | null;\n logTail: string[];\n};\n\ntype Props = {\n snapshot: Snapshot;\n settings: Settings;\n activeTab: string;\n setActiveTab: (id: string) => void;\n refreshSnapshot: () => Promise<void>;\n};\n\ntype NavId = 'opencode' | 'providers' | 'mcps' | 'diagnostics' | 'memory' | 'export';\n\nconst NAV_ITEMS: { id: NavId; label: string; icon: typeof Settings2; desc: string }[] = [\n { id: 'opencode', label: 'OpenCode config', icon: FileCode2, desc: 'Edit opencode.json directly' },\n { id: 'providers', label: 'Providers', icon: ServerIcon, desc: 'AI providers + API keys' },\n { id: 'mcps', label: 'MCPs', icon: Plug, desc: 'Model Context Protocol servers' },\n { id: 'diagnostics', label: 'Diagnostics', icon: Stethoscope, desc: 'Service health + counts' },\n { id: 'memory', label: 'Memory & LightRAG', icon: Database, desc: 'Configure Bizar Memory Service and the LightRAG embedding server.' },\n { id: 'export', label: 'Export / Import', icon: Download, desc: 'Download diagnostics bundle' },\n];\n\nexport function Config({ snapshot, refreshSnapshot }: Props) {\n const toast = useToast();\n const modal = useModal();\n const initial: ConfigResponse | undefined = snapshot.config;\n const [activeNav, setActiveNav] = useState<NavId>('opencode');\n\n // OpenCode editor state\n const [original, setOriginal] = useState<string>(\n initial?.raw || (initial?.data ? JSON.stringify(initial.data, null, 2) : ''),\n );\n const [parsed, setParsed] = useState({\n raw: initial?.raw || '',\n data: initial?.data ?? null,\n error: null as string | null,\n });\n const [dirty, setDirty] = useState(false);\n const [saving, setSaving] = useState(false);\n const [path, setPath] = useState<string>(initial?.path || '');\n const taRef = useRef<HTMLTextAreaElement>(null);\n\n // Diagnostics state\n const [diagnostics, setDiagnostics] = useState<Diagnostics | null>(null);\n\n // Memory & LightRAG state\n const [lightragStatus, setLightragStatus] = useState<LightragStatus | null>(null);\n const [lightragLog, setLightragLog] = useState<string[]>([]);\n\n // Providers + MCPs state — re-fetch when nav switches so we always have fresh data.\n const [providers, setProviders] = useState<Provider[]>(snapshot.providers || []);\n const [mcps, setMcps] = useState<McpServer[]>(snapshot.mcps || []);\n\n const originalHash = useMemo(() => hashText(original), [original]);\n\n useEffect(() => {\n if (snapshot.providers) setProviders(snapshot.providers);\n if (snapshot.mcps) setMcps(snapshot.mcps);\n }, [snapshot.providers, snapshot.mcps]);\n\n const reloadConfig = async () => {\n try {\n const d = await api.post<ConfigResponse>('/config/reload');\n const raw = d.raw || (d.data ? JSON.stringify(d.data, null, 2) : '');\n setOriginal(raw);\n setParsed({ raw, data: d.data ?? null, error: null });\n setDirty(false);\n setPath(d.path || '');\n toast.info('Config reloaded.', 1500);\n } catch (err) {\n toast.error(`Reload failed: ${(err as Error).message}`);\n }\n };\n\n const reloadProviders = async () => {\n try {\n const r = await api.get<{ providers: Provider[] }>('/config/providers');\n setProviders(r.providers || []);\n } catch (err) {\n toast.error(`Providers load failed: ${(err as Error).message}`);\n }\n };\n\n const reloadMcps = async () => {\n try {\n const r = await api.get<{ mcps: McpServer[] }>('/config/mcps');\n setMcps(r.mcps || []);\n } catch (err) {\n toast.error(`MCPs load failed: ${(err as Error).message}`);\n }\n };\n\n // Reload data when nav changes so each panel shows fresh server data.\n useEffect(() => {\n if (activeNav === 'providers' && providers.length === 0) reloadProviders();\n if (activeNav === 'mcps' && mcps.length === 0) reloadMcps();\n if (activeNav === 'diagnostics' && !diagnostics) loadDiagnostics();\n if (activeNav === 'memory') loadLightragStatus();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [activeNav]);\n\n const applyEdit = (val: string) => {\n setParsed((cur) => {\n const next: typeof parsed = { raw: val, data: cur.data, error: null };\n try {\n next.data = JSON.parse(val);\n next.error = null;\n } catch (e) {\n next.data = null;\n next.error = (e as Error).message;\n }\n return next;\n });\n onChangeDebounced(val);\n };\n\n const onChangeDebounced = useMemo(\n () =>\n debounce((val: string) => {\n setDirty(hashText(val) !== originalHash);\n }, 100),\n [originalHash],\n );\n\n const save = async () => {\n if (!parsed.data || parsed.error || saving) return;\n setSaving(true);\n try {\n const result = await api.put<ConfigResponse>('/config', parsed.data);\n const raw = result.raw || JSON.stringify(result.data, null, 2);\n setOriginal(raw);\n setParsed({ raw, data: result.data ?? null, error: null });\n setDirty(false);\n toast.success('Config saved.');\n await refreshSnapshot();\n // Re-fetch providers + MCPs because config may have changed.\n await reloadProviders();\n await reloadMcps();\n } catch (err) {\n toast.error(`Save failed: ${(err as Error).message}`);\n } finally {\n setSaving(false);\n }\n };\n\n const loadDiagnostics = async () => {\n try {\n const d = await api.get<Diagnostics>('/diagnostics');\n setDiagnostics(d);\n } catch (err) {\n toast.error(`Diagnostics load failed: ${(err as Error).message}`);\n }\n };\n\n const loadLightragStatus = async () => {\n try {\n const d = await api.get<LightragStatus>('/memory/lightrag/status');\n setLightragStatus(d);\n } catch (err) {\n toast.error(`LightRAG status failed: ${(err as Error).message}`);\n }\n };\n\n const loadLightragLog = async () => {\n try {\n const d = await api.get<{ lines: string[] }>('/memory/lightrag/log');\n setLightragLog(d.lines || []);\n } catch {\n setLightragLog([]);\n }\n };\n\n const onDownloadDiagnostics = () => {\n const bundle = {\n generatedAt: new Date().toISOString(),\n diagnostics,\n config: parsed.data,\n opencodeJsonPath: path,\n providers,\n mcps,\n };\n const blob = new Blob([JSON.stringify(bundle, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = `bizar-diagnostics-${new Date().toISOString().replace(/[:.]/g, '-')}.json`;\n a.click();\n URL.revokeObjectURL(url);\n toast.success('Bundle downloaded.');\n };\n\n return (\n <div className=\"view view-config\">\n <header className=\"view-header\">\n <div className=\"view-header-text\">\n <h2 className=\"view-title\">\n <Settings2 size={18} /> Config\n </h2>\n <p className=\"view-subtitle\">\n Manage OpenCode config, providers, MCPs, and diagnostics.\n </p>\n </div>\n </header>\n\n <div className=\"config-layout\">\n <nav className=\"config-nav\" role=\"navigation\" aria-label=\"Config sections\">\n {NAV_ITEMS.map((n) => {\n const Icon = n.icon;\n return (\n <button\n key={n.id}\n type=\"button\"\n className={cn('config-nav-item', activeNav === n.id && 'config-nav-item-active')}\n onClick={() => setActiveNav(n.id)}\n aria-current={activeNav === n.id ? 'page' : undefined}\n >\n <Icon size={14} />\n <div style={{ display: 'flex', flexDirection: 'column', minWidth: 0, flex: 1 }}>\n <span>{n.label}</span>\n <span style={{ fontSize: 10, color: 'var(--text-dim)', fontWeight: 400 }}>\n {n.desc}\n </span>\n </div>\n </button>\n );\n })}\n </nav>\n\n <div className=\"config-content\">\n {activeNav === 'opencode' && (\n <ConfigEditorPanel\n parsed={parsed}\n dirty={dirty}\n saving={saving}\n path={path}\n onReload={reloadConfig}\n onSave={save}\n onChange={applyEdit}\n textareaRef={taRef}\n />\n )}\n\n {activeNav === 'providers' && (\n <ProvidersPanel providers={providers} onChange={setProviders} onReload={reloadProviders} />\n )}\n\n {activeNav === 'mcps' && (\n <McpsPanel mcps={mcps} onChange={setMcps} onReload={reloadMcps} />\n )}\n\n {activeNav === 'diagnostics' && (\n <DiagnosticsPanel diagnostics={diagnostics} loading={!diagnostics} onReload={loadDiagnostics} />\n )}\n\n {activeNav === 'memory' && (\n <MemoryLightragPanel\n status={lightragStatus}\n onReload={loadLightragStatus}\n logLines={lightragLog}\n onReloadLog={loadLightragLog}\n />\n )}\n\n {activeNav === 'export' && (\n <ExportPanel onDownload={onDownloadDiagnostics} />\n )}\n </div>\n </div>\n </div>\n );\n}\n\n// ─── OpenCode config form (v3.5.2) ─────────────────────────────────\n// Structured UI for opencode.json sections: Model, Plugins, Tools,\n// Permissions, Hooks. Raw JSON available via \"Advanced\" toggle.\n\ntype OcSection = 'model' | 'plugins' | 'tools' | 'permissions' | 'hooks' | 'advanced';\n\nconst OC_SECTIONS: { id: OcSection; label: string }[] = [\n { id: 'model', label: 'Model' },\n { id: 'plugins', label: 'Plugins' },\n { id: 'tools', label: 'Tools' },\n { id: 'permissions', label: 'Permissions' },\n { id: 'hooks', label: 'Hooks' },\n { id: 'advanced', label: 'Advanced' },\n];\n\nfunction ConfigEditorPanel({\n parsed,\n dirty,\n saving,\n path,\n onReload,\n onSave,\n onChange,\n textareaRef,\n}: {\n parsed: { raw: string; data: unknown; error: string | null };\n dirty: boolean;\n saving: boolean;\n path: string;\n onReload: () => void;\n onSave: () => void;\n onChange: (val: string) => void;\n textareaRef: React.RefObject<HTMLTextAreaElement>;\n}) {\n const [section, setSection] = useState<OcSection>('model');\n\n const cfg = parsed.data as Record<string, unknown> | null;\n\n const apply = (patch: Record<string, unknown>) => {\n if (!cfg) return;\n const next = { ...cfg, ...patch };\n onChange(JSON.stringify(next, null, 2));\n };\n\n return (\n <Card>\n <CardTitle>\n <FileCode2 size={14} /> OpenCode config\n </CardTitle>\n <CardMeta>\n <code className=\"mono ellipsis\" style={{ fontSize: 11 }}>\n {path || '~/.config/opencode/opencode.json'}\n </code>\n </CardMeta>\n <div className=\"view-actions\" style={{ marginBottom: 12 }}>\n <Button variant=\"secondary\" size=\"sm\" onClick={onReload}>\n <RefreshCw size={14} /> Reload\n </Button>\n <Button\n variant=\"primary\"\n size=\"sm\"\n disabled={!parsed.data || !!parsed.error || !dirty}\n onClick={onSave}\n >\n {saving ? <span className=\"btn-spinner\" /> : <Save size={14} />}\n Save\n </Button>\n </div>\n\n {/* Section tabs */}\n <div className=\"config-section-tabs\" style={{ display: 'flex', gap: 4, marginBottom: 16, flexWrap: 'wrap' }}>\n {OC_SECTIONS.map((s) => (\n <button\n key={s.id}\n type=\"button\"\n className={cn('tab-btn', section === s.id && 'active')}\n onClick={() => setSection(s.id)}\n >\n {s.label}\n </button>\n ))}\n </div>\n\n {/* Model section */}\n {section === 'model' && (\n <ModelForm cfg={cfg} apply={apply} />\n )}\n\n {/* Plugins section */}\n {section === 'plugins' && (\n <PluginsForm cfg={cfg} apply={apply} />\n )}\n\n {/* Tools section */}\n {section === 'tools' && (\n <ToolsForm cfg={cfg} apply={apply} />\n )}\n\n {/* Permissions section */}\n {section === 'permissions' && (\n <PermissionsForm cfg={cfg} apply={apply} />\n )}\n\n {/* Hooks section */}\n {section === 'hooks' && (\n <HooksForm cfg={cfg} apply={apply} />\n )}\n\n {/* Advanced: raw JSON editor */}\n {section === 'advanced' && (\n <div>\n <div className=\"config-grid-label\" style={{ marginBottom: 8 }}>\n {parsed.error ? (\n <span className=\"text-error\">{parsed.error}</span>\n ) : (\n <span className=\"muted\">Raw JSON — edit with care</span>\n )}\n </div>\n <textarea\n ref={textareaRef}\n className={cn('textarea config-textarea', parsed.error && 'invalid')}\n spellCheck={false}\n value={parsed.raw}\n onChange={(e) => onChange(e.target.value)}\n style={{ minHeight: 300 }}\n />\n </div>\n )}\n </Card>\n );\n}\n\n// ── Sub-forms ─────────────────────────────────────────────────────────\n\nfunction ModelForm({ cfg, apply }: { cfg: Record<string, unknown> | null; apply: (p: Record<string, unknown>) => void }) {\n const model = (cfg?.model || {}) as Record<string, unknown>;\n return (\n <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>\n <p className=\"muted text-sm\">Configure the default model used by OpenCode agents.</p>\n <div className=\"field-row\">\n <label className=\"field-label\">Provider</label>\n <input\n className=\"input\"\n value={String(model.provider || '')}\n onChange={(e) => apply({ model: { ...model, provider: e.target.value } })}\n placeholder=\"e.g. openai, anthropic, google\"\n />\n </div>\n <div className=\"field-row\">\n <label className=\"field-label\">Model ID</label>\n <input\n className=\"input\"\n value={String(model.model || '')}\n onChange={(e) => apply({ model: { ...model, model: e.target.value } })}\n placeholder=\"e.g. gpt-4o, claude-sonnet-4-20250514\"\n />\n </div>\n {!!model.apiKey && (\n <div className=\"field-row\">\n <label className=\"field-label\">API Key</label>\n <input\n className=\"input\"\n type=\"password\"\n value={String(model.apiKey || '')}\n onChange={(e) => apply({ model: { ...model, apiKey: e.target.value } })}\n placeholder=\"sk-...\"\n />\n </div>\n )}\n {!!model.baseURL && (\n <div className=\"field-row\">\n <label className=\"field-label\">Base URL</label>\n <input\n className=\"input\"\n value={String(model.baseURL || '')}\n onChange={(e) => apply({ model: { ...model, baseURL: e.target.value } })}\n placeholder=\"https://api.openai.com/v1\"\n />\n </div>\n )}\n </div>\n );\n}\n\nfunction PluginsForm({ cfg, apply }: { cfg: Record<string, unknown> | null; apply: (p: Record<string, unknown>) => void }) {\n const plugins = Array.isArray(cfg?.plugins) ? (cfg.plugins as Record<string, unknown>[]) : [];\n const [editing, setEditing] = useState<number | null>(null);\n const [draft, setDraft] = useState<Record<string, unknown>>({});\n\n const addPlugin = () => {\n const next = [...plugins, { name: '', enabled: true }];\n apply({ plugins: next });\n };\n\n const removePlugin = (i: number) => {\n const next = plugins.filter((_, idx) => idx !== i);\n apply({ plugins: next });\n };\n\n const updatePlugin = (i: number, patch: Record<string, unknown>) => {\n const next = plugins.map((p, idx) => (idx === i ? { ...p, ...patch } : p));\n apply({ plugins: next });\n setEditing(null);\n };\n\n return (\n <div>\n <p className=\"muted text-sm\" style={{ marginBottom: 12 }}>Manage enabled plugins.</p>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>\n {plugins.length === 0 && <p className=\"muted text-sm\">No plugins configured.</p>}\n {plugins.map((p, i) => (\n <div key={i} className=\"config-list-row\">\n {editing === i ? (\n <div style={{ display: 'flex', gap: 8, flex: 1, alignItems: 'center' }}>\n <input\n className=\"input\"\n value={String(draft.name || '')}\n onChange={(e) => setDraft({ ...draft, name: e.target.value })}\n placeholder=\"plugin-name\"\n />\n <label style={{ display: 'flex', gap: 4, fontSize: 12 }}>\n <input\n type=\"checkbox\"\n checked={!!draft.enabled}\n onChange={(e) => setDraft({ ...draft, enabled: e.target.checked })}\n />\n enabled\n </label>\n <Button variant=\"primary\" size=\"sm\" onClick={() => updatePlugin(i, draft)}>Apply</Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => setEditing(null)}><X size={12} /></Button>\n </div>\n ) : (\n <>\n <span style={{ fontFamily: 'var(--font-mono)', fontSize: 13 }}>\n {(p as { name?: string }).name || 'unnamed'}\n </span>\n <span className={cn('tag', (p as { enabled?: boolean }).enabled !== false ? 'tag-success' : 'tag-neutral')}>\n {(p as { enabled?: boolean }).enabled !== false ? 'enabled' : 'disabled'}\n </span>\n <div style={{ marginLeft: 'auto', display: 'flex', gap: 4 }}>\n <button type=\"button\" className=\"icon-btn\" onClick={() => { setEditing(i); setDraft(p as Record<string, unknown>); }} title=\"Edit\">\n <Pencil size={12} />\n </button>\n <button type=\"button\" className=\"icon-btn text-error\" onClick={() => removePlugin(i)} title=\"Remove\">\n <Trash2 size={12} />\n </button>\n </div>\n </>\n )}\n </div>\n ))}\n </div>\n <Button variant=\"secondary\" size=\"sm\" onClick={addPlugin} style={{ marginTop: 8 }}>\n <Plus size={12} /> Add plugin\n </Button>\n </div>\n );\n}\n\nfunction ToolsForm({ cfg, apply }: { cfg: Record<string, unknown> | null; apply: (p: Record<string, unknown>) => void }) {\n const tools = (cfg?.tools as Record<string, boolean> | null) || {};\n\n const toggle = (name: string) => {\n apply({ tools: { ...tools, [name]: !tools[name] } });\n };\n\n const addTool = (name: string) => {\n if (!name || tools[name] !== undefined) return;\n apply({ tools: { ...tools, [name]: true } });\n };\n\n const removeTool = (name: string) => {\n const next = { ...tools };\n delete next[name];\n apply({ tools: next });\n };\n\n return (\n <div>\n <p className=\"muted text-sm\" style={{ marginBottom: 12 }}>Enable or disable built-in tools.</p>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>\n {Object.keys(tools).length === 0 && <p className=\"muted text-sm\">No tools configured.</p>}\n {Object.entries(tools).map(([name, enabled]) => (\n <div key={name} className=\"config-list-row\">\n <span style={{ fontFamily: 'var(--font-mono)', fontSize: 13 }}>{name}</span>\n <label style={{ display: 'flex', gap: 4, alignItems: 'center', fontSize: 12 }}>\n <input type=\"checkbox\" checked={!!enabled} onChange={() => toggle(name)} />\n enabled\n </label>\n <button type=\"button\" className=\"icon-btn text-error\" style={{ marginLeft: 'auto' }} onClick={() => removeTool(name)} title=\"Remove\">\n <Trash2 size={12} />\n </button>\n </div>\n ))}\n </div>\n <div style={{ display: 'flex', gap: 8, marginTop: 8 }}>\n <input\n className=\"input\"\n placeholder=\"tool-name\"\n onKeyDown={(e) => {\n if (e.key === 'Enter') addTool((e.target as HTMLInputElement).value.trim());\n }}\n />\n <Button variant=\"secondary\" size=\"sm\"\n onClick={(e) => addTool((e.currentTarget.closest('div')?.querySelector('input') as HTMLInputElement)?.value.trim() || '')}\n >\n <Plus size={12} /> Add\n </Button>\n </div>\n </div>\n );\n}\n\nfunction PermissionsForm({ cfg, apply }: { cfg: Record<string, unknown> | null; apply: (p: Record<string, unknown>) => void }) {\n const permissions = (cfg?.permissions as Record<string, unknown> | null) || {};\n const [tab, setTab] = useState<'allow' | 'deny'>('allow');\n const allow = Array.isArray(permissions.allow) ? (permissions.allow as string[]) : [];\n const deny = Array.isArray(permissions.deny) ? (permissions.deny as string[]) : [];\n\n const addRule = (list: string[], key: 'allow' | 'deny') => (name: string) => {\n if (!name) return;\n apply({ permissions: { ...permissions, [key]: [...list, name] } });\n };\n\n const removeRule = (key: 'allow' | 'deny', list: string[], i: number) => {\n apply({ permissions: { ...permissions, [key]: list.filter((_, idx) => idx !== i) } });\n };\n\n const list = tab === 'allow' ? allow : deny;\n\n return (\n <div>\n <p className=\"muted text-sm\" style={{ marginBottom: 12 }}>Allow or deny tool/scope rules.</p>\n <div style={{ display: 'flex', gap: 4, marginBottom: 12 }}>\n <button type=\"button\" className={cn('tab-btn', tab === 'allow' && 'active')} onClick={() => setTab('allow')}>Allow ({allow.length})</button>\n <button type=\"button\" className={cn('tab-btn', tab === 'deny' && 'active')} onClick={() => setTab('deny')}>Deny ({deny.length})</button>\n </div>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>\n {list.length === 0 && <p className=\"muted text-sm\">No {tab} rules.</p>}\n {list.map((rule, i) => (\n <div key={i} className=\"config-list-row\">\n <span style={{ fontFamily: 'var(--font-mono)', fontSize: 13 }}>{rule}</span>\n <button type=\"button\" className=\"icon-btn text-error\" style={{ marginLeft: 'auto' }} onClick={() => removeRule(tab, list, i)}>\n <Trash2 size={12} />\n </button>\n </div>\n ))}\n </div>\n <div style={{ display: 'flex', gap: 8, marginTop: 8 }}>\n <input\n className=\"input\"\n placeholder={`${tab} rule (e.g. tool:read, scope:filesystem)`}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n const v = (e.target as HTMLInputElement).value.trim();\n if (v) { addRule(list, tab)(v); (e.target as HTMLInputElement).value = ''; }\n }\n }}\n />\n <Button variant=\"secondary\" size=\"sm\" onClick={(e) => {\n const inp = e.currentTarget.closest('div')?.querySelector('input') as HTMLInputElement;\n const v = inp?.value.trim();\n if (v) { addRule(list, tab)(v); inp.value = ''; }\n }}>\n <Plus size={12} /> Add\n </Button>\n </div>\n </div>\n );\n}\n\nfunction HooksForm({ cfg, apply }: { cfg: Record<string, unknown> | null; apply: (p: Record<string, unknown>) => void }) {\n const hooks = (cfg?.hooks as Record<string, unknown> | null) || {};\n\n const updateHook = (name: string, value: unknown) => {\n apply({ hooks: { ...hooks, [name]: value } });\n };\n\n return (\n <div>\n <p className=\"muted text-sm\" style={{ marginBottom: 12 }}>Configure pre/post tool hooks.</p>\n {Object.keys(hooks).length === 0 && <p className=\"muted text-sm\">No hooks configured.</p>}\n <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>\n {(['preTool', 'postTool', 'preAgent', 'postAgent'] as const).map((hookName) => {\n const hook = hooks[hookName];\n return (\n <div key={hookName} className=\"field-row\" style={{ alignItems: 'flex-start' }}>\n <label className=\"field-label\" style={{ minWidth: 100 }}>{hookName}</label>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 6, flex: 1 }}>\n <input\n className=\"input\"\n value={typeof hook === 'object' && hook !== null && 'command' in hook ? String((hook as { command: string }).command || '') : ''}\n onChange={(e) => updateHook(hookName, { command: e.target.value })}\n placeholder={`${hookName} command (e.g. node /path/to/hook.js)`}\n />\n </div>\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n\nfunction DiagnosticsPanel({\n diagnostics,\n loading,\n onReload,\n}: {\n diagnostics: Diagnostics | null;\n loading: boolean;\n onReload: () => void;\n}) {\n return (\n <Card>\n <CardTitle>\n <Stethoscope size={14} /> Diagnostics\n </CardTitle>\n <CardMeta>\n System health, file counts, recent errors.{' '}\n <button type=\"button\" className=\"link-btn\" onClick={onReload}>Refresh</button>\n </CardMeta>\n {loading && <p className=\"muted\">Loading diagnostics…</p>}\n {diagnostics && (\n <>\n <div className=\"diagnostics-grid\">\n <div className=\"diagnostic-tile\">\n <div className=\"diagnostic-tile-label\">Version</div>\n <div className=\"diagnostic-tile-value mono\">{diagnostics.version}</div>\n </div>\n <div className=\"diagnostic-tile\">\n <div className=\"diagnostic-tile-label\">Uptime</div>\n <div className=\"diagnostic-tile-value mono\">{diagnostics.uptime}s</div>\n </div>\n <div className=\"diagnostic-tile\">\n <div className=\"diagnostic-tile-label\">Node</div>\n <div className=\"diagnostic-tile-value mono\">{diagnostics.nodeVersion}</div>\n </div>\n <div className=\"diagnostic-tile\">\n <div className=\"diagnostic-tile-label\">Platform</div>\n <div className=\"diagnostic-tile-value mono\">{diagnostics.platform}</div>\n </div>\n <div className=\"diagnostic-tile\">\n <div className=\"diagnostic-tile-label\">Memory (heap)</div>\n <div className=\"diagnostic-tile-value mono\">\n {Math.round(diagnostics.memory.heapUsed / 1024 / 1024)}MB\n </div>\n </div>\n <div className=\"diagnostic-tile\">\n <div className=\"diagnostic-tile-label\">Memory (RSS)</div>\n <div className=\"diagnostic-tile-value mono\">\n {Math.round(diagnostics.memory.rss / 1024 / 1024)}MB\n </div>\n </div>\n <div className=\"diagnostic-tile\">\n <div className=\"diagnostic-tile-label\">Service</div>\n <div className=\"diagnostic-tile-value\">\n {diagnostics.service.running ? (\n <span className=\"tag tag-success\">running (pid {diagnostics.service.pid})</span>\n ) : (\n <span className=\"tag tag-neutral\">stopped</span>\n )}\n </div>\n </div>\n <div className=\"diagnostic-tile\">\n <div className=\"diagnostic-tile-label\">Active project</div>\n <div className=\"diagnostic-tile-value mono\">\n {diagnostics.counts.activeProject || '—'}\n </div>\n </div>\n </div>\n <div className=\"diagnostic-counts\">\n <span>agents: <strong>{diagnostics.counts.agents}</strong></span>\n <span>projects: <strong>{diagnostics.counts.projects}</strong></span>\n <span>mods: <strong>{diagnostics.counts.mods}</strong></span>\n <span>schedules: <strong>{diagnostics.counts.schedules}</strong></span>\n <span>tasks: <strong>{diagnostics.counts.tasks}</strong></span>\n <span>providers: <strong>{diagnostics.counts.providers}</strong></span>\n <span>mcps: <strong>{diagnostics.counts.mcps}</strong></span>\n </div>\n <div className=\"diagnostic-errors\">\n <div className=\"muted\">Last {diagnostics.errors.length} errors from service.log</div>\n {diagnostics.errors.length === 0 ? (\n <p className=\"muted\">No errors recorded.</p>\n ) : (\n <ul>\n {diagnostics.errors.map((e, i) => (\n <li key={i} className=\"mono\">\n {e.ts && <span className=\"muted\">[{e.ts}] </span>}\n {e.line}\n </li>\n ))}\n </ul>\n )}\n </div>\n </>\n )}\n </Card>\n );\n}\n\n/* ──────────────────────────────────────────────────────────────\n Providers Panel — fully editable with proper modal forms.\n ────────────────────────────────────────────────────────────── */\n\ntype ProviderDraft = {\n id: string;\n name: string;\n baseURL: string;\n apiKey: string;\n models: string[];\n enabled: boolean;\n};\n\nfunction ProvidersPanel({\n providers,\n onChange,\n onReload,\n}: {\n providers: Provider[];\n onChange: (p: Provider[]) => void;\n onReload: () => Promise<void>;\n}) {\n const toast = useToast();\n const modal = useModal();\n\n const openProviderModal = (existing?: Provider) => {\n let idEl: HTMLInputElement | null = null;\n let nameEl: HTMLInputElement | null = null;\n let baseEl: HTMLInputElement | null = null;\n let keyEl: HTMLInputElement | null = null;\n let modelsEl: HTMLTextAreaElement | null = null;\n let enabledEl: HTMLInputElement | null = null;\n\n const isEdit = !!existing;\n const initialId = existing?.id || '';\n const initialName = existing?.name || '';\n const initialBase = existing?.baseURL || '';\n // Show masked key as-is in edit mode (so user can see what's stored).\n const initialKey = existing?.apiKey || '';\n const initialModels = (existing?.models || []).join(', ');\n const initialEnabled = existing?.enabled !== false;\n\n modal.open({\n title: isEdit ? `Edit provider \"${existing!.id}\"` : 'Add provider',\n children: (\n <div>\n <div className=\"modal-form-row\">\n <label>ID (a-z, 0-9, dashes)</label>\n <input\n ref={(el) => (idEl = el)}\n className=\"input\"\n type=\"text\"\n defaultValue={initialId}\n placeholder=\"anthropic\"\n disabled={isEdit}\n />\n </div>\n <div className=\"modal-form-row\">\n <label>Display name</label>\n <input\n ref={(el) => (nameEl = el)}\n className=\"input\"\n type=\"text\"\n defaultValue={initialName}\n placeholder=\"Anthropic\"\n />\n </div>\n <div className=\"modal-form-row\">\n <label>Base URL</label>\n <input\n ref={(el) => (baseEl = el)}\n className=\"input\"\n type=\"text\"\n defaultValue={initialBase}\n placeholder=\"https://api.anthropic.com\"\n />\n </div>\n <div className=\"modal-form-row\">\n <label>API key{isEdit && ' (leave masked value unchanged to keep)'}</label>\n <input\n ref={(el) => (keyEl = el)}\n className=\"input\"\n type=\"password\"\n defaultValue={initialKey}\n placeholder=\"sk-...\"\n autoComplete=\"off\"\n />\n </div>\n <div className=\"modal-form-row\">\n <label>Models (comma-separated)</label>\n <textarea\n ref={(el) => (modelsEl = el)}\n className=\"textarea\"\n defaultValue={initialModels}\n placeholder=\"claude-sonnet-4-5, claude-opus-4-1\"\n rows={3}\n />\n </div>\n <div className=\"modal-form-row\">\n <label className=\"checkbox-row\">\n <input\n ref={(el) => (enabledEl = el)}\n type=\"checkbox\"\n defaultChecked={initialEnabled}\n />\n Enabled\n </label>\n </div>\n </div>\n ),\n footer: (\n <div className=\"modal-footer-actions\">\n <Button variant=\"ghost\" onClick={() => modal.close()}>Cancel</Button>\n <Button\n variant=\"primary\"\n onClick={async () => {\n const id = (idEl?.value || '').trim();\n const name = (nameEl?.value || '').trim();\n const baseURL = (baseEl?.value || '').trim();\n const apiKey = keyEl?.value || '';\n const modelsRaw = modelsEl?.value || '';\n const models = modelsRaw.split(/[,\\n]/).map((m) => m.trim()).filter(Boolean);\n const enabled = !!enabledEl?.checked;\n\n if (!id) {\n toast.warning('ID is required.');\n return;\n }\n if (!/^[a-z0-9][a-z0-9_-]{0,63}$/i.test(id)) {\n toast.warning('ID must be a-z, 0-9, dashes.');\n return;\n }\n try {\n const payload: ProviderDraft & { id: string } = {\n id,\n name: name || id,\n baseURL,\n apiKey,\n models,\n enabled,\n };\n if (isEdit) {\n const updated = await api.put<Provider>(\n `/config/providers/${encodeURIComponent(id)}`,\n payload,\n );\n onChange(providers.map((p) => (p.id === id ? updated : p)));\n toast.success(`Provider \"${id}\" updated.`);\n } else {\n const created = await api.post<Provider>('/config/providers', payload);\n onChange([...providers, created]);\n toast.success(`Provider \"${id}\" added.`);\n }\n modal.close();\n } catch (err) {\n toast.error(`Save failed: ${(err as Error).message}`);\n }\n }}\n >\n {isEdit ? 'Update' : 'Add'} provider\n </Button>\n </div>\n ),\n });\n };\n\n const onRemove = async (id: string) => {\n if (!confirm(`Remove provider \"${id}\"?`)) return;\n try {\n await api.del(`/config/providers/${encodeURIComponent(id)}`);\n onChange(providers.filter((p) => p.id !== id));\n toast.success('Provider removed.');\n } catch (err) {\n toast.error(`Remove failed: ${(err as Error).message}`);\n }\n };\n\n return (\n <Card>\n <CardTitle>\n <ServerIcon size={14} /> Providers ({providers.length})\n </CardTitle>\n <CardMeta>\n AI providers configured under <code>opencode.json#provider</code>.\n Each provider has a base URL, API key, and a list of model IDs.\n </CardMeta>\n <AutoDetectBanner onAdd={(id, name, baseURL, key) => {\n openProviderModal({ id, name, baseURL, apiKey: key } as Provider);\n }} />\n <div className=\"view-actions\" style={{ marginBottom: 12 }}>\n <Button variant=\"primary\" size=\"sm\" onClick={() => openProviderModal()}>\n <Plus size={14} /> Add provider\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={onReload}>\n <RefreshCw size={14} /> Refresh\n </Button>\n </div>\n {providers.length === 0 ? (\n <EmptyProviders onAdd={() => openProviderModal()} />\n ) : (\n <div className=\"provider-list\">\n {providers.map((p) => (\n <Card key={p.id} className=\"provider-row\">\n <div className=\"provider-row-head\">\n <div style={{ minWidth: 0, flex: 1 }}>\n <div className=\"provider-name\">{p.name || p.id}</div>\n <div className=\"provider-id\">{p.id}</div>\n </div>\n <div className=\"provider-actions\">\n <label className=\"toggle-row\" title=\"Enabled\">\n <input\n type=\"checkbox\"\n checked={p.enabled !== false}\n onChange={async (e) => {\n try {\n const updated = await api.put<Provider>(\n `/config/providers/${encodeURIComponent(p.id)}`,\n { enabled: e.target.checked },\n );\n onChange(providers.map((x) => (x.id === p.id ? updated : x)));\n } catch (err) {\n toast.error(`Toggle failed: ${(err as Error).message}`);\n }\n }}\n />\n {p.enabled !== false ? 'on' : 'off'}\n </label>\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label=\"Edit\"\n title=\"Edit\"\n onClick={() => openProviderModal(p)}\n >\n <Pencil size={12} />\n </button>\n <button\n type=\"button\"\n className=\"icon-btn icon-btn-danger\"\n aria-label=\"Remove\"\n title=\"Remove\"\n onClick={() => onRemove(p.id)}\n >\n <Trash2 size={12} />\n </button>\n </div>\n </div>\n <div className=\"provider-meta\">\n <div><span className=\"muted\">Base URL:</span> <code>{p.baseURL || '—'}</code></div>\n <div><span className=\"muted\">API key:</span> <code>{p.apiKey || '—'}</code></div>\n <div><span className=\"muted\">Models:</span> {(p.models || []).join(', ') || '—'}</div>\n </div>\n </Card>\n ))}\n </div>\n )}\n </Card>\n );\n}\n\nfunction EmptyProviders({ onAdd }: { onAdd: () => void }) {\n return (\n <div style={{\n padding: '32px 16px',\n textAlign: 'center',\n color: 'var(--text-dim)',\n border: '1px dashed var(--border)',\n borderRadius: 'var(--radius-md)',\n display: 'flex',\n flexDirection: 'column',\n gap: 8,\n alignItems: 'center',\n }}>\n <ServerIcon size={28} />\n <div>No providers configured.</div>\n <div style={{ fontSize: 12 }}>Add a provider to connect an AI model.</div>\n <Button variant=\"primary\" size=\"sm\" onClick={onAdd}>\n <Plus size={14} /> Add your first provider\n </Button>\n </div>\n );\n}\n\n/* ──────────────────────────────────────────────────────────────\n MCPs Panel — fully editable with proper modal forms.\n ────────────────────────────────────────────────────────────── */\n\ntype McpDraft = {\n id: string;\n type: 'local' | 'remote';\n command: string;\n args: string[];\n env: Record<string, string>;\n url: string;\n headers: Record<string, string>;\n oauth: boolean;\n enabled: boolean;\n};\n\nfunction parseEnv(s: string): Record<string, string> {\n const out: Record<string, string> = {};\n for (const line of s.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const eq = trimmed.indexOf('=');\n if (eq <= 0) continue;\n const k = trimmed.slice(0, eq).trim();\n const v = trimmed.slice(eq + 1).trim();\n if (k) out[k] = v;\n }\n return out;\n}\n\nfunction parseHeaders(s: string): Record<string, string> {\n const out: Record<string, string> = {};\n for (const line of s.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const sep = trimmed.indexOf(':');\n if (sep <= 0) continue;\n const k = trimmed.slice(0, sep).trim();\n const v = trimmed.slice(sep + 1).trim();\n if (k) out[k] = v;\n }\n return out;\n}\n\nfunction McpsPanel({\n mcps,\n onChange,\n onReload,\n}: {\n mcps: McpServer[];\n onChange: (m: McpServer[]) => void;\n onReload: () => Promise<void>;\n}) {\n const toast = useToast();\n const modal = useModal();\n\n const openMcpModal = (existing?: McpServer) => {\n let idEl: HTMLInputElement | null = null;\n let typeLocalEl: HTMLInputElement | null = null;\n let typeRemoteEl: HTMLInputElement | null = null;\n let commandEl: HTMLInputElement | null = null;\n let argsEl: HTMLInputElement | null = null;\n let envEl: HTMLTextAreaElement | null = null;\n let urlEl: HTMLInputElement | null = null;\n let headersEl: HTMLTextAreaElement | null = null;\n let oauthEl: HTMLInputElement | null = null;\n let enabledEl: HTMLInputElement | null = null;\n\n const isEdit = !!existing;\n const isRemote = existing?.type === 'remote' || (!existing && false);\n const initialType: 'local' | 'remote' = existing?.type === 'remote' ? 'remote' : 'local';\n const initialCommand = existing?.command || '';\n const initialArgs = (existing?.args || []).join(' ');\n const initialEnv = existing?.env ? Object.entries(existing.env).map(([k, v]) => `${k}=${v}`).join('\\n') : '';\n const initialUrl = existing?.url || '';\n const initialHeaders = existing?.headers ? Object.entries(existing.headers).map(([k, v]) => `${k}: ${v}`).join('\\n') : '';\n const initialOauth = !!existing?.oauth;\n const initialEnabled = existing?.enabled !== false;\n\n modal.open({\n title: isEdit ? `Edit MCP \"${existing!.id}\"` : 'Add MCP',\n children: (\n <div>\n <div className=\"modal-form-row\">\n <label>ID (a-z, 0-9, dashes)</label>\n <input\n ref={(el) => (idEl = el)}\n className=\"input\"\n type=\"text\"\n defaultValue={existing?.id || ''}\n placeholder=\"supabase\"\n disabled={isEdit}\n />\n </div>\n <div className=\"modal-form-row\">\n <label>Type</label>\n <div style={{ display: 'flex', gap: 12 }}>\n <label className=\"radio-label\">\n <input\n ref={(el) => (typeLocalEl = el)}\n type=\"radio\"\n name=\"mcp-type\"\n value=\"local\"\n defaultChecked={initialType === 'local'}\n />\n Local (stdio)\n </label>\n <label className=\"radio-label\">\n <input\n ref={(el) => (typeRemoteEl = el)}\n type=\"radio\"\n name=\"mcp-type\"\n value=\"remote\"\n defaultChecked={initialType === 'remote'}\n />\n Remote (HTTP)\n </label>\n </div>\n </div>\n\n <div data-mcp-section=\"local\">\n <div className=\"modal-form-row\">\n <label>Command (binary to invoke)</label>\n <input\n ref={(el) => (commandEl = el)}\n className=\"input\"\n type=\"text\"\n defaultValue={initialCommand}\n placeholder=\"uvx --from semble[mcp] semble\"\n />\n </div>\n <div className=\"modal-form-row\">\n <label>Extra args (space-separated)</label>\n <input\n ref={(el) => (argsEl = el)}\n className=\"input\"\n type=\"text\"\n defaultValue={initialArgs}\n placeholder=\"--port 8080\"\n />\n <div className=\"field-help\">These are appended after the command.</div>\n </div>\n <div className=\"modal-form-row\">\n <label>Environment variables</label>\n <textarea\n ref={(el) => (envEl = el)}\n className=\"textarea\"\n defaultValue={initialEnv}\n placeholder=\"API_KEY=xxx DEBUG=true\"\n rows={3}\n />\n <div className=\"field-help\">One KEY=VALUE per line.</div>\n </div>\n </div>\n\n <div data-mcp-section=\"remote\">\n <div className=\"modal-form-row\">\n <label>URL</label>\n <input\n ref={(el) => (urlEl = el)}\n className=\"input\"\n type=\"text\"\n defaultValue={initialUrl}\n placeholder=\"https://mcp.example.com/mcp\"\n />\n </div>\n <div className=\"modal-form-row\">\n <label>Headers</label>\n <textarea\n ref={(el) => (headersEl = el)}\n className=\"textarea\"\n defaultValue={initialHeaders}\n placeholder=\"Authorization: Bearer xxx Content-Type: application/json\"\n rows={3}\n />\n <div className=\"field-help\">One \"Key: Value\" per line.</div>\n </div>\n <div className=\"modal-form-row\">\n <label className=\"checkbox-row\">\n <input\n ref={(el) => (oauthEl = el)}\n type=\"checkbox\"\n defaultChecked={initialOauth}\n />\n Use OAuth (browser-based auth flow)\n </label>\n </div>\n </div>\n\n <div className=\"modal-form-row\">\n <label className=\"checkbox-row\">\n <input\n ref={(el) => (enabledEl = el)}\n type=\"checkbox\"\n defaultChecked={initialEnabled}\n />\n Enabled\n </label>\n </div>\n </div>\n ),\n footer: (\n <div className=\"modal-footer-actions\">\n <Button variant=\"ghost\" onClick={() => modal.close()}>Cancel</Button>\n <Button\n variant=\"primary\"\n onClick={async () => {\n const id = (idEl?.value || '').trim();\n const isRemote = !!typeRemoteEl?.checked;\n const command = (commandEl?.value || '').trim();\n const argsStr = (argsEl?.value || '').trim();\n const args = argsStr ? argsStr.split(/\\s+/) : [];\n const env = parseEnv(envEl?.value || '');\n const url = (urlEl?.value || '').trim();\n const headers = parseHeaders(headersEl?.value || '');\n const oauth = !!oauthEl?.checked;\n const enabled = !!enabledEl?.checked;\n\n if (!id) {\n toast.warning('ID is required.');\n return;\n }\n if (!/^[a-z0-9][a-z0-9_-]{0,63}$/i.test(id)) {\n toast.warning('ID must be a-z, 0-9, dashes.');\n return;\n }\n try {\n const payload: McpDraft = {\n id,\n type: isRemote ? 'remote' : 'local',\n command,\n args,\n env,\n url,\n headers,\n oauth,\n enabled,\n };\n if (isEdit) {\n const updated = await api.put<McpServer>(\n `/config/mcps/${encodeURIComponent(id)}`,\n payload,\n );\n onChange(mcps.map((m) => (m.id === id ? updated : m)));\n toast.success(`MCP \"${id}\" updated.`);\n } else {\n const created = await api.post<McpServer>('/config/mcps', payload);\n onChange([...mcps, created]);\n toast.success(`MCP \"${id}\" added.`);\n }\n modal.close();\n } catch (err) {\n toast.error(`Save failed: ${(err as Error).message}`);\n }\n }}\n >\n {isEdit ? 'Update' : 'Add'} MCP\n </Button>\n </div>\n ),\n });\n };\n\n const onRemove = async (id: string) => {\n if (!confirm(`Remove MCP \"${id}\"?`)) return;\n try {\n await api.del(`/config/mcps/${encodeURIComponent(id)}`);\n onChange(mcps.filter((m) => m.id !== id));\n toast.success('MCP removed.');\n } catch (err) {\n toast.error(`Remove failed: ${(err as Error).message}`);\n }\n };\n\n return (\n <Card>\n <CardTitle>\n <Plug size={14} /> MCPs ({mcps.length})\n </CardTitle>\n <CardMeta>\n Model Context Protocol servers under <code>opencode.json#mcp</code>.\n Local MCPs run as stdio subprocesses; remote MCPs are HTTP endpoints.\n </CardMeta>\n <div className=\"view-actions\" style={{ marginBottom: 12 }}>\n <Button variant=\"primary\" size=\"sm\" onClick={() => openMcpModal()}>\n <Plus size={14} /> Add MCP\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={onReload}>\n <RefreshCw size={14} /> Refresh\n </Button>\n </div>\n {mcps.length === 0 ? (\n <div style={{\n padding: '32px 16px',\n textAlign: 'center',\n color: 'var(--text-dim)',\n border: '1px dashed var(--border)',\n borderRadius: 'var(--radius-md)',\n display: 'flex',\n flexDirection: 'column',\n gap: 8,\n alignItems: 'center',\n }}>\n <Plug size={28} />\n <div>No MCPs configured.</div>\n <Button variant=\"primary\" size=\"sm\" onClick={() => openMcpModal()}>\n <Plus size={14} /> Add your first MCP\n </Button>\n </div>\n ) : (\n <div className=\"mcp-list\">\n {mcps.map((m) => (\n <Card key={m.id} className=\"mcp-row\">\n <div className=\"mcp-row-head\">\n <div style={{ minWidth: 0, flex: 1 }}>\n <div className=\"mcp-name\">{m.id}</div>\n <div className=\"mcp-id\">\n {m.type === 'remote' ? 'remote' : 'local'} {m.enabled !== false ? '· enabled' : '· disabled'}\n </div>\n </div>\n <div className=\"mcp-actions\">\n <label className=\"toggle-row\" title=\"Enabled\">\n <input\n type=\"checkbox\"\n checked={m.enabled !== false}\n onChange={async (e) => {\n try {\n const updated = await api.put<McpServer>(\n `/config/mcps/${encodeURIComponent(m.id)}`,\n { enabled: e.target.checked },\n );\n onChange(mcps.map((x) => (x.id === m.id ? updated : x)));\n } catch (err) {\n toast.error(`Toggle failed: ${(err as Error).message}`);\n }\n }}\n />\n {m.enabled !== false ? 'on' : 'off'}\n </label>\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label=\"Edit\"\n title=\"Edit\"\n onClick={() => openMcpModal(m)}\n >\n <Pencil size={12} />\n </button>\n <button\n type=\"button\"\n className=\"icon-btn icon-btn-danger\"\n aria-label=\"Remove\"\n title=\"Remove\"\n onClick={() => onRemove(m.id)}\n >\n <Trash2 size={12} />\n </button>\n </div>\n </div>\n <div className=\"mcp-meta\">\n {m.type === 'remote' ? (\n <>\n <div><span className=\"muted\">URL:</span> <code>{m.url || '—'}</code></div>\n {Object.keys(m.headers || {}).length > 0 && (\n <div><span className=\"muted\">Headers:</span> <code>{Object.keys(m.headers || {}).length} header(s)</code></div>\n )}\n {m.oauth && <div><span className=\"muted\">Auth:</span> <code>OAuth</code></div>}\n </>\n ) : (\n <>\n <div><span className=\"muted\">Command:</span> <code>{m.command || '—'}</code></div>\n {m.args && m.args.length > 0 && (\n <div><span className=\"muted\">Args:</span> <code>{m.args.join(' ')}</code></div>\n )}\n {m.env && Object.keys(m.env).length > 0 && (\n <div><span className=\"muted\">Env:</span> <code>{Object.keys(m.env).length} var(s)</code></div>\n )}\n </>\n )}\n </div>\n </Card>\n ))}\n </div>\n )}\n </Card>\n );\n}\n\nfunction ExportPanel({ onDownload }: { onDownload: () => void }) {\n return (\n <Card>\n <CardTitle>\n <Download size={14} /> Export / Import\n </CardTitle>\n <CardMeta>\n Download a JSON bundle of diagnostics, configuration, providers, and MCPs\n for support requests or backup. Server-side imports are not yet implemented.\n </CardMeta>\n <div className=\"view-actions\" style={{ marginTop: 12 }}>\n <Button variant=\"primary\" onClick={onDownload}>\n <Download size={14} /> Download diagnostics bundle\n </Button>\n </div>\n <div style={{ marginTop: 16, fontSize: 12, color: 'var(--text-dim)' }}>\n <Database size={12} style={{ display: 'inline', verticalAlign: -2 }} /> Bundles include:\n opencode.json snapshot, providers list (with masked API keys), MCP list, recent\n service log errors, and active project metadata.\n </div>\n </Card>\n );\n}\n\n/* ──────────────────────────────────────────────────────────────\n Memory & LightRAG Panel\n ────────────────────────────────────────────────────────────── */\n\ntype LightragDraft = {\n enabled: boolean;\n host: string;\n port: number | '';\n workingDir: string;\n llmBinding: string;\n embeddingBinding: string;\n llmBindingHost: string;\n embeddingBindingHost: string;\n llmModel: string;\n embeddingModel: string;\n apiKeySource: 'env' | 'file';\n apiKey: string;\n};\n\nconst LLM_BINDING_OPTIONS = ['ollama', 'openai', 'lollms', 'azure_openai', 'bedrock', 'gemini'];\nconst EMBEDDING_BINDING_OPTIONS = ['ollama', 'openai', 'azure_openai', 'bedrock', 'jina', 'gemini', 'voyageai'];\n\nfunction MemoryLightragPanel({\n status,\n onReload,\n logLines,\n onReloadLog,\n}: {\n status: LightragStatus | null;\n onReload: () => void;\n logLines: string[];\n onReloadLog: () => void;\n}) {\n const toast = useToast();\n const [saving, setSaving] = useState(false);\n const [starting, setStarting] = useState(false);\n const [stopping, setStopping] = useState(false);\n const [loadingLog, setLoadingLog] = useState(false);\n const [showLog, setShowLog] = useState(false);\n\n // Draft form state — initialise from status once loaded\n const [draft, setDraft] = useState<LightragDraft>({\n enabled: true,\n host: '127.0.0.1',\n port: 9621,\n workingDir: '',\n llmBinding: 'ollama',\n embeddingBinding: 'ollama',\n llmBindingHost: '',\n embeddingBindingHost: '',\n llmModel: 'minimax/MiniMax-M3',\n embeddingModel: 'text-embedding-3-small',\n apiKeySource: 'env',\n apiKey: '',\n });\n const [dirty, setDirty] = useState(false);\n\n // Sync draft from status when status loads\n useEffect(() => {\n if (!status) return;\n setDraft((d) => ({\n ...d,\n enabled: true,\n host: status.host,\n port: status.port,\n llmBinding: status.llmBinding,\n embeddingBinding: status.embeddingBinding,\n llmBindingHost: status.llmBindingHost || '',\n embeddingBindingHost: status.embeddingBindingHost || '',\n llmModel: status.llmModel,\n embeddingModel: status.embeddingModel,\n apiKeySource: 'env',\n apiKey: '',\n }));\n setDirty(false);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [status?.running]);\n\n const set = <K extends keyof LightragDraft>(key: K, value: LightragDraft[K]) => {\n setDraft((d) => ({ ...d, [key]: value }));\n setDirty(true);\n };\n\n const handleSave = async () => {\n if (saving) return;\n setSaving(true);\n try {\n // Build patch payload\n const patch: Record<string, unknown> = {\n enabled: draft.enabled,\n host: draft.host,\n port: draft.port === '' ? 9621 : Number(draft.port),\n workingDir: draft.workingDir,\n llmBinding: draft.llmBinding,\n embeddingBinding: draft.embeddingBinding,\n llmBindingHost: draft.llmBindingHost || null,\n embeddingBindingHost: draft.embeddingBindingHost || null,\n llmModel: draft.llmModel,\n embeddingModel: draft.embeddingModel,\n apiKeySource: draft.apiKeySource,\n };\n if (draft.apiKeySource === 'file' && draft.apiKey !== '') {\n patch.apiKey = draft.apiKey;\n }\n if (draft.apiKeySource === 'env') {\n patch.apiKey = '<empty>';\n }\n\n await api.post('/memory/config', { patch: true, lightrag: patch });\n toast.success('LightRAG config saved.');\n setDirty(false);\n onReload();\n } catch (err) {\n toast.error(`Save failed: ${(err as Error).message}`);\n } finally {\n setSaving(false);\n }\n };\n\n const handleStart = async () => {\n if (starting) return;\n setStarting(true);\n try {\n const r = await api.post<{ ok: boolean; error?: string; pid?: number }>('/memory/lightrag/start');\n if (r.ok) {\n toast.success(`LightRAG started (pid ${r.pid}).`);\n } else {\n toast.error(`Start failed: ${r.error}`);\n }\n onReload();\n } catch (err) {\n toast.error(`Start failed: ${(err as Error).message}`);\n } finally {\n setStarting(false);\n }\n };\n\n const handleStop = async () => {\n if (stopping) return;\n setStopping(true);\n try {\n await api.post('/memory/lightrag/stop');\n toast.success('LightRAG stopped.');\n onReload();\n } catch (err) {\n toast.error(`Stop failed: ${(err as Error).message}`);\n } finally {\n setStopping(false);\n }\n };\n\n const handleRestart = async () => {\n await handleStop();\n await handleStart();\n };\n\n const handleShowLog = async () => {\n if (!showLog) {\n setLoadingLog(true);\n await onReloadLog();\n setLoadingLog(false);\n }\n setShowLog((v) => !v);\n };\n\n const running = status?.running ?? false;\n\n return (\n <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>\n {/* Status card */}\n <Card>\n <CardTitle>\n <Database size={14} /> LightRAG Server\n </CardTitle>\n <CardMeta>\n In-process embedding server for semantic memory search.{' '}\n <button type=\"button\" className=\"link-btn\" onClick={onReload}>Refresh</button>\n </CardMeta>\n <div style={{ display: 'flex', gap: 8, marginTop: 8, flexWrap: 'wrap', alignItems: 'center' }}>\n {running ? (\n <span className=\"tag tag-success\">\n running {status?.pid ? `(pid ${status.pid})` : ''}\n </span>\n ) : (\n <span className=\"tag tag-neutral\">stopped</span>\n )}\n {status && (\n <span className=\"mono text-sm muted\">\n {status.host}:{status.port} · {status.llmBinding} · {status.embeddingModel}\n </span>\n )}\n {status?.lastError && (\n <span className=\"text-error text-sm\">⚠ {status.lastError}</span>\n )}\n </div>\n <div style={{ display: 'flex', gap: 8, marginTop: 12, flexWrap: 'wrap' }}>\n {!running ? (\n <Button variant=\"primary\" size=\"sm\" onClick={handleStart} disabled={starting}>\n {starting ? <Spinner size=\"sm\" /> : <RefreshCw size={12} />}\n {starting ? 'Starting…' : 'Start'}\n </Button>\n ) : (\n <>\n <Button variant=\"secondary\" size=\"sm\" onClick={handleRestart} disabled={stopping || starting}>\n <RefreshCw size={12} /> Restart\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={handleStop} disabled={stopping}>\n {stopping ? <Spinner size=\"sm\" /> : null}\n {stopping ? 'Stopping…' : 'Stop'}\n </Button>\n </>\n )}\n <Button variant=\"ghost\" size=\"sm\" onClick={handleShowLog}>\n {showLog ? 'Hide' : 'Show'} log\n </Button>\n </div>\n {showLog && (\n <div style={{ marginTop: 12 }}>\n <div className=\"field-help\" style={{ marginBottom: 6 }}>\n Last {logLines.length} line(s)\n <button type=\"button\" className=\"link-btn\" style={{ marginLeft: 8 }} onClick={onReloadLog}>\n Refresh\n </button>\n </div>\n {loadingLog ? (\n <p className=\"muted text-sm\">Loading…</p>\n ) : logLines.length === 0 ? (\n <p className=\"muted text-sm\">No log output yet.</p>\n ) : (\n <pre className=\"log-pre\">{logLines.join('\\n')}</pre>\n )}\n </div>\n )}\n </Card>\n\n {/* Binding card */}\n <Card>\n <CardTitle>\n <ShieldCheck size={14} /> Bindings\n </CardTitle>\n <CardMeta>Choose the LLM and embedding provider bindings.</CardMeta>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 12, marginTop: 12 }}>\n <div className=\"field-row\">\n <label className=\"field-label\">LLM Binding</label>\n <select\n className=\"input\"\n value={draft.llmBinding}\n onChange={(e) => set('llmBinding', e.target.value)}\n >\n {LLM_BINDING_OPTIONS.map((b) => (\n <option key={b} value={b}>{b}</option>\n ))}\n </select>\n </div>\n <div className=\"field-row\">\n <label className=\"field-label\">Embedding Binding</label>\n <select\n className=\"input\"\n value={draft.embeddingBinding}\n onChange={(e) => set('embeddingBinding', e.target.value)}\n >\n {EMBEDDING_BINDING_OPTIONS.map((b) => (\n <option key={b} value={b}>{b}</option>\n ))}\n </select>\n </div>\n {draft.llmBinding !== 'ollama' && (\n <div className=\"field-row\">\n <label className=\"field-label\">LLM Binding Host</label>\n <input\n className=\"input\"\n type=\"text\"\n value={draft.llmBindingHost}\n onChange={(e) => set('llmBindingHost', e.target.value)}\n placeholder=\"https://api.minimax.chat/v1\"\n />\n </div>\n )}\n {draft.embeddingBinding !== 'ollama' && (\n <div className=\"field-row\">\n <label className=\"field-label\">Embedding Binding Host</label>\n <input\n className=\"input\"\n type=\"text\"\n value={draft.embeddingBindingHost}\n onChange={(e) => set('embeddingBindingHost', e.target.value)}\n placeholder=\"https://api.minimax.chat/v1\"\n />\n </div>\n )}\n </div>\n </Card>\n\n {/* Models card */}\n <Card>\n <CardTitle>\n <ServerIcon size={14} /> Models\n </CardTitle>\n <CardMeta>Model IDs for the LLM and embedding engine.</CardMeta>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 12, marginTop: 12 }}>\n <div className=\"field-row\">\n <label className=\"field-label\">LLM Model</label>\n <input\n className=\"input\"\n type=\"text\"\n value={draft.llmModel}\n onChange={(e) => set('llmModel', e.target.value)}\n placeholder=\"minimax/MiniMax-M3\"\n />\n </div>\n <div className=\"field-row\">\n <label className=\"field-label\">Embedding Model</label>\n <input\n className=\"input\"\n type=\"text\"\n value={draft.embeddingModel}\n onChange={(e) => set('embeddingModel', e.target.value)}\n placeholder=\"text-embedding-3-small\"\n />\n </div>\n </div>\n </Card>\n\n {/* Connection card */}\n <Card>\n <CardTitle>\n <Plug size={14} /> Connection\n </CardTitle>\n <CardMeta>Host, port, and working directory for the LightRAG server.</CardMeta>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 12, marginTop: 12 }}>\n <div className=\"field-row\">\n <label className=\"field-label\">Host</label>\n <input\n className=\"input\"\n type=\"text\"\n value={draft.host}\n onChange={(e) => set('host', e.target.value)}\n placeholder=\"127.0.0.1\"\n />\n </div>\n <div className=\"field-row\">\n <label className=\"field-label\">Port</label>\n <input\n className=\"input\"\n type=\"number\"\n min={1}\n max={65535}\n value={draft.port}\n onChange={(e) => set('port', e.target.value === '' ? '' : Number(e.target.value))}\n placeholder=\"9621\"\n />\n </div>\n <div className=\"field-row\">\n <label className=\"field-label\">Working Dir</label>\n <input\n className=\"input\"\n type=\"text\"\n value={draft.workingDir}\n onChange={(e) => set('workingDir', e.target.value)}\n placeholder=\".bizar/lightrag (default)\"\n />\n </div>\n </div>\n </Card>\n\n {/* Credentials card */}\n <Card>\n <CardTitle>\n <ShieldCheck size={14} /> Credentials\n </CardTitle>\n <CardMeta>API key source — set in your shell env, or stored in .bizar/memory.json.</CardMeta>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 12, marginTop: 12 }}>\n <div className=\"field-row\">\n <label className=\"field-label\">Source</label>\n <select\n className=\"input\"\n value={draft.apiKeySource}\n onChange={(e) => set('apiKeySource', e.target.value as 'env' | 'file')}\n >\n <option value=\"env\">Environment variable (recommended)</option>\n <option value=\"file\">Stored in .bizar/memory.json</option>\n </select>\n </div>\n {draft.apiKeySource === 'env' ? (\n <p className=\"muted text-sm\" style={{ padding: '8px 0' }}>\n Set <code>OPENAI_API_KEY</code> (or provider-specific env var) in your shell before\n running reindex or queries.\n </p>\n ) : (\n <div className=\"field-row\">\n <label className=\"field-label\">API Key</label>\n <input\n className=\"input\"\n type=\"password\"\n value={draft.apiKey}\n onChange={(e) => set('apiKey', e.target.value)}\n placeholder={status?.running ? '(unchanged — leave blank)' : 'sk-…'}\n autoComplete=\"off\"\n />\n </div>\n )}\n </div>\n </Card>\n\n <div className=\"view-actions\">\n <Button variant=\"primary\" disabled={!dirty || saving} onClick={handleSave}>\n {saving ? <Spinner size=\"sm\" /> : <Save size={14} />}\n {saving ? 'Saving…' : 'Save config'}\n </Button>\n </div>\n </div>\n );\n}\n\n// ─── AutoDetectBanner (v3.16.0) ────────────────────────────────────\n// Scans env vars + opencode.json for known provider API keys\n// (Anthropic, OpenAI, Google, Mistral, Groq, Cohere, OpenRouter,\n// DeepSeek, MiniMax). Surfaces status: configured / unknown / no-key.\ntype AutoDetectResult = {\n id: string;\n name: string;\n baseURL?: string;\n status: 'configured' | 'unknown' | 'no-key';\n keySource: string;\n hasKey: boolean;\n probed?: { ok: boolean; status?: number; reason?: string; modelCount?: number } | null;\n};\n\nfunction AutoDetectBanner({\n onAdd,\n}: {\n onAdd: (id: string, name: string, baseURL: string, apiKey?: string) => void;\n}) {\n const toast = useToast();\n const [results, setResults] = useState<AutoDetectResult[] | null>(null);\n const [loading, setLoading] = useState(false);\n const [expanded, setExpanded] = useState(false);\n\n const run = async (probe: boolean) => {\n setLoading(true);\n try {\n const r = await api.get<{ providers: AutoDetectResult[] }>(\n `/providers/auto-detect${probe ? '' : '?probe=0'}`,\n );\n setResults(r.providers || []);\n const configured = (r.providers || []).filter((p) => p.status === 'configured');\n if (configured.length > 0) {\n toast.success(`Detected ${configured.length} configured provider${configured.length === 1 ? '' : 's'}.`);\n } else {\n toast.info('No configured providers detected in env or config.');\n }\n } catch (err) {\n toast.error(`Auto-detect failed: ${(err as Error).message}`);\n } finally {\n setLoading(false);\n }\n };\n\n const statusIcon = (s: string) => {\n if (s === 'configured') return <ShieldCheck size={12} style={{ color: 'var(--success)' }} />;\n if (s === 'unknown') return <AlertTriangle size={12} style={{ color: 'var(--warning)' }} />;\n return <X size={12} style={{ color: 'var(--text-dim)' }} />;\n };\n\n const configured = (results || []).filter((p) => p.status === 'configured');\n const other = (results || []).filter((p) => p.status !== 'configured');\n\n return (\n <Card className=\"autodetect-banner\">\n <div className=\"autodetect-head\" onClick={() => setExpanded((v) => !v)}>\n <ShieldCheck size={14} />\n <span className=\"autodetect-title\">Auto-detect providers</span>\n <span className=\"muted\" style={{ fontSize: 11 }}>\n {results\n ? `${configured.length} configured · ${other.length} other`\n : 'scan env vars + opencode.json for known keys'}\n </span>\n <span className=\"autodetect-spacer\" />\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={(e) => {\n e.stopPropagation();\n run(true);\n }}\n disabled={loading}\n title=\"Probe each provider's /models endpoint\"\n >\n {loading ? <Spinner size=\"sm\" /> : <RefreshCw size={12} />} Detect\n </Button>\n {expanded ? <ChevronDown size={14} /> : <ChevronRight size={14} />}\n </div>\n {expanded && (\n <div className=\"autodetect-body\">\n {!results ? (\n <div className=\"muted\" style={{ padding: 12, fontSize: 12 }}>\n Click <strong>Detect</strong> to scan env vars and opencode.json for known provider keys.\n Probes each provider's <code>/models</code> endpoint with a 1.5s timeout.\n </div>\n ) : (\n <table className=\"autodetect-table\">\n <thead>\n <tr>\n <th>Status</th>\n <th>Provider</th>\n <th>Source</th>\n <th>Probe</th>\n <th></th>\n </tr>\n </thead>\n <tbody>\n {results.map((r) => (\n <tr key={r.id}>\n <td>{statusIcon(r.status)} <span className=\"autodetect-status\">{r.status}</span></td>\n <td><strong>{r.name}</strong> <span className=\"muted mono\">{r.id}</span></td>\n <td className=\"muted\">{r.keySource || '—'}</td>\n <td className=\"muted\">\n {r.probed?.modelCount != null\n ? `${r.probed.modelCount} models`\n : r.probed?.reason\n ? r.probed.reason\n : r.probed?.ok\n ? 'ok'\n : '—'}\n </td>\n <td>\n {r.status === 'configured' && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => onAdd(r.id, r.name, r.baseURL || '')}\n title=\"Add this provider to opencode.json\"\n >\n <Plus size={10} /> Add\n </Button>\n )}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n )}\n </div>\n )}\n </Card>\n );\n}\n","// src/views/Settings.tsx — v3 settings: theme colors, UI layout, defaults, Tailscale, service.\nimport React, { useEffect, useState, useCallback } from 'react';\nimport {\n Sliders,\n Save,\n RefreshCw,\n Sun,\n Moon,\n Monitor,\n Info,\n Globe,\n Palette,\n Layout as LayoutIcon,\n Server as ServerIcon,\n RotateCcw,\n Plug,\n Download,\n AlertTriangle,\n QrCode,\n Smartphone,\n CheckCircle,\n AlertCircle,\n Shield,\n Copy,\n KeyRound,\n Activity,\n EyeOff,\n Eye,\n Trash2,\n Search,\n Sparkles,\n} from 'lucide-react';\nimport { QRCodeSVG } from 'qrcode.react';\nimport { Button } from '../components/Button';\nimport { Card, CardTitle, CardMeta } from '../components/Card';\nimport { useToast } from '../components/Toast';\nimport { api } from '../lib/api';\nimport { cn } from '../lib/utils';\nimport { Ws } from '../lib/ws';\nimport {\n applyTheme,\n applyThemeTokens,\n type Settings,\n type SettingsResponse,\n type Snapshot,\n type ThemeName,\n type TailscaleStatus,\n} from '../lib/types';\n\ntype Props = {\n snapshot: Snapshot;\n settings: Settings;\n activeTab: string;\n setActiveTab: (id: string) => void;\n refreshSnapshot: () => Promise<void>;\n};\n\nconst THEMES: { id: ThemeName; label: string; Icon: typeof Sun }[] = [\n { id: 'dark', label: 'Dark', Icon: Moon },\n { id: 'light', label: 'Light', Icon: Sun },\n { id: 'system', label: 'System', Icon: Monitor },\n];\n\n// v3.3.1 — One-click accent color presets.\nconst PRESET_THEMES = [\n { name: 'Purple', accent: '#8b5cf6' },\n { name: 'Blue', accent: '#3b82f6' },\n { name: 'Green', accent: '#10b981' },\n { name: 'Orange', accent: '#f97316' },\n { name: 'Red', accent: '#ef4444' },\n { name: 'Pink', accent: '#ec4899' },\n { name: 'Cyan', accent: '#06b6d4' },\n { name: 'Mono', accent: '#6b7280' },\n];\n\nconst FONT_FAMILIES = [\n 'Inter',\n 'system-ui',\n 'Segoe UI',\n 'Roboto',\n 'JetBrains Mono',\n 'SF Mono',\n 'Cascadia Code',\n];\n\n// v3.5.2 — Pair-with-mobile companion card.\ntype PairSession = {\n token: string;\n qrPayload: string;\n publicUrl: string;\n expiresAt: number;\n};\n\nfunction formatCountdown(ms: number): string {\n if (ms <= 0) return 'expired';\n const s = Math.floor(ms / 1000);\n const m = Math.floor(s / 60);\n const r = s % 60;\n return `${m}:${String(r).padStart(2, '0')}`;\n}\n\nfunction PairDeviceCard() {\n const toast = useToast();\n const [pair, setPair] = useState<PairSession | null>(null);\n const [pairing, setPairing] = useState(false);\n const [pairError, setPairError] = useState<string | null>(null);\n const [now, setNow] = useState(Date.now());\n\n const start = useCallback(async () => {\n setPairing(true);\n setPairError(null);\n try {\n const res = await api.post<PairSession>('/pair/start');\n setPair(res);\n } catch (err) {\n setPairError((err as Error)?.message || 'Failed to start pairing');\n toast.error('Pairing failed.');\n } finally {\n setPairing(false);\n }\n }, [toast]);\n\n useEffect(() => {\n if (!pair) return;\n const t = setInterval(() => setNow(Date.now()), 1000);\n return () => clearInterval(t);\n }, [pair]);\n\n const remaining = pair ? pair.expiresAt - now : 0;\n const expired = pair != null && remaining <= 0;\n\n return (\n <Card id=\"settings-updates\" data-section=\"updates\">\n <CardTitle>\n <Smartphone size={14} /> Companion App\n </CardTitle>\n <CardMeta>\n Scan the QR with <a href=\"https://github.com/DrB0rk/BizarHarness\" target=\"_blank\" rel=\"noopener noreferrer\">Bizar Companion</a> to pair.\n Tokens expire after 5 minutes.\n </CardMeta>\n\n <div style={{ display: 'flex', gap: 16, alignItems: 'flex-start', flexWrap: 'wrap' }}>\n <div style={{ flex: '0 0 auto' }}>\n {pair && !expired ? (\n <div style={{ background: '#fff', padding: 12, borderRadius: 12 }}>\n <QRCodeSVG value={pair.qrPayload} size={192} level=\"M\" includeMargin={false} />\n </div>\n ) : (\n <div\n style={{\n width: 216,\n height: 216,\n borderRadius: 12,\n background: 'var(--surface-2, #161b22)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n color: 'var(--text-muted, #8b949e)',\n fontSize: 12,\n textAlign: 'center',\n padding: 16,\n border: '1px dashed var(--border, #30363d)',\n }}\n >\n {pair && expired ? 'QR expired' : 'No QR generated yet'}\n </div>\n )}\n </div>\n\n <div style={{ flex: '1 1 240px', minWidth: 220 }}>\n {!pair && (\n <Button variant=\"primary\" onClick={start} disabled={pairing}>\n <QrCode size={14} /> {pairing ? 'Generating…' : 'Generate QR Code'}\n </Button>\n )}\n\n {pair && !expired && (\n <>\n <div style={{ marginBottom: 10 }}>\n <strong>Expires in</strong> <span className=\"mono\">{formatCountdown(remaining)}</span>\n </div>\n <div style={{ marginBottom: 6 }}>\n <strong>URL:</strong> <span className=\"mono\" style={{ wordBreak: 'break-all' }}>{pair.publicUrl}</span>\n </div>\n <div style={{ marginBottom: 12 }}>\n <strong>Token:</strong>{' '}\n <span className=\"mono\" style={{ wordBreak: 'break-all', fontSize: 12 }}>\n {pair.token.slice(0, 16)}…{pair.token.slice(-6)}\n </span>\n </div>\n <Button variant=\"secondary\" onClick={start} disabled={pairing}>\n <RefreshCw size={14} /> Regenerate\n </Button>\n </>\n )}\n\n {pair && expired && (\n <>\n <div style={{ marginBottom: 12, color: 'var(--error, #f85149)' }}>\n Token expired — generate a fresh QR to pair again.\n </div>\n <Button variant=\"primary\" onClick={() => { setPair(null); start(); }}>\n <RefreshCw size={14} /> Generate new QR\n </Button>\n </>\n )}\n\n {pairError && (\n <div style={{ marginTop: 10, color: 'var(--error, #f85149)', fontSize: 12 }}>\n {pairError}\n </div>\n )}\n </div>\n </div>\n </Card>\n );\n}\n\nconst LAYOUTS = [\n { id: 'topnav', label: 'Top nav' },\n { id: 'sidebar', label: 'Sidebar' },\n { id: 'both', label: 'Both' },\n] as const;\n\n// v3.5.3 — Updates card with per-package selection, live progress, and auto-restart\ntype PkgStatus = {\n status: 'idle' | 'starting' | 'installing' | 'done' | 'error';\n error?: string;\n newVersion?: string;\n logs: string[];\n};\n\nfunction UpdatesCard() {\n const toast = useToast();\n const [status, setStatus] = useState<{\n current: Record<string, string | null>;\n latest: Record<string, string | null> | null;\n checking: boolean;\n updating: boolean;\n hasUpdates: boolean;\n requiresRestart: boolean;\n perPackage: Record<string, PkgStatus>;\n error?: string;\n }>({\n current: {},\n latest: null,\n checking: false,\n updating: false,\n hasUpdates: false,\n requiresRestart: false,\n perPackage: {},\n });\n\n // WebSocket subscription for live update progress (auto-reconnect via Ws class)\n useEffect(() => {\n const ws = new Ws();\n ws.on((msg: Record<string, unknown>) => {\n if (msg.type === 'update:progress' || msg.type === 'update:log' || msg.type === 'update:complete') {\n setStatus((s) => {\n if (msg.type === 'update:complete') {\n return {\n ...s,\n updating: false,\n requiresRestart: Boolean((msg as { requiresRestart?: boolean }).requiresRestart),\n };\n }\n if (msg.type === 'update:log') {\n const m = msg as { pkg: string; line: string };\n const existing = s.perPackage[m.pkg] || { logs: [] };\n return {\n ...s,\n perPackage: {\n ...s.perPackage,\n [m.pkg]: {\n ...existing,\n logs: [...(existing.logs || []).slice(-50), m.line],\n },\n },\n };\n }\n // update:progress\n const m = msg as { pkg: string; status: PkgStatus['status']; error?: string; newVersion?: string };\n return {\n ...s,\n perPackage: {\n ...s.perPackage,\n [m.pkg]: {\n ...s.perPackage[m.pkg],\n status: m.status,\n error: m.error,\n newVersion: m.newVersion,\n },\n },\n };\n });\n }\n });\n return () => ws.close();\n }, []);\n\n // Load current versions on mount\n useEffect(() => {\n api.get<{ current: Record<string, string | null> }>('/updates/status')\n .then((r) => setStatus((s) => ({ ...s, current: r.current })))\n .catch((e) => setStatus((s) => ({ ...s, error: e.message })));\n }, []);\n\n const check = async () => {\n setStatus((s) => ({ ...s, checking: true, error: undefined }));\n try {\n const r = await api.get<{\n current: Record<string, string | null>;\n latest: Record<string, string | null>;\n hasUpdates: boolean;\n }>('/updates/check');\n setStatus((s) => ({\n ...s,\n checking: false,\n current: r.current,\n latest: r.latest,\n hasUpdates: r.hasUpdates,\n }));\n } catch (err) {\n setStatus((s) => ({ ...s, checking: false, error: (err as Error).message }));\n }\n };\n\n const applyUpdate = async () => {\n if (!confirm('Update Bizar packages? The dashboard will restart automatically.')) return;\n setStatus((s) => ({\n ...s,\n updating: true,\n requiresRestart: false,\n perPackage: {},\n error: undefined,\n }));\n try {\n await api.post('/updates/apply', { packages: ['bizar', 'bizar-dash', 'bizar-plugin'] });\n // Progress streams via WebSocket\n } catch (err) {\n setStatus((s) => ({ ...s, updating: false, error: (err as Error).message }));\n }\n };\n\n const restart = async () => {\n if (!confirm('Restart the dashboard? You will be disconnected briefly.')) return;\n try {\n await api.post('/restart');\n toast.info('Restarting…', 3000);\n setTimeout(() => window.location.reload(), 3000);\n } catch {\n toast.error('Restart failed');\n }\n };\n\n const packages = [\n { id: 'bizar', name: 'Bizar CLI' },\n { id: 'bizar-dash', name: 'Dashboard' },\n { id: 'bizar-plugin', name: 'Opencode Plugin' },\n ];\n\n const isBusy = status.checking || status.updating;\n\n return (\n <Card id=\"settings-updates\" data-section=\"updates\">\n <CardTitle><Download size={14} /> Updates</CardTitle>\n <CardMeta>Check installed Bizar packages and apply dashboard updates.</CardMeta>\n {/* Current versions */}\n <div className=\"updates-current\">\n <h4>Installed versions</h4>\n <ul>\n {packages.map((p) => (\n <li key={p.id}>\n <span>{p.name}</span>\n <code className=\"mono\">{status.current[p.id] || '—'}</code>\n </li>\n ))}\n </ul>\n </div>\n\n {/* Latest + per-package status */}\n {status.latest && (\n <div className=\"updates-latest\">\n <h4>Latest available</h4>\n <ul>\n {packages.map((p) => {\n const cur = status.current[p.id];\n const lat = status.latest?.[p.id];\n const isOutdated = cur && lat && cur !== lat;\n return (\n <li key={p.id} className={isOutdated ? 'updates-outdated' : 'updates-current-version'}>\n <span>{p.name}</span>\n <code className=\"mono\">\n {lat || '—'}\n {isOutdated && <span className=\"updates-badge\">update available</span>}\n </code>\n </li>\n );\n })}\n </ul>\n </div>\n )}\n\n {/* Per-package progress rows (shown while updating) */}\n {status.updating && (\n <div className=\"updates-progress-rows\">\n {packages.map((p) => {\n const pkgStatus = status.perPackage[p.id] || { status: 'idle', logs: [] as string[] };\n return (\n <div key={p.id} className=\"updates-pkg-row\">\n <div className=\"updates-pkg-row-header\">\n <span className=\"updates-pkg-name\">{p.name}</span>\n <div className=\"updates-pkg-status\">\n {pkgStatus.status === 'starting' && <span className=\"btn-spinner\" />}\n {pkgStatus.status === 'installing' && <span className=\"btn-spinner\" />}\n {pkgStatus.status === 'done' && <CheckCircle size={14} className=\"icon-success\" />}\n {pkgStatus.status === 'error' && <AlertCircle size={14} className=\"icon-error\" />}\n <span>{pkgStatus.status}</span>\n {pkgStatus.newVersion && (\n <code className=\"mono\" style={{ fontSize: 11 }}>→ {pkgStatus.newVersion}</code>\n )}\n </div>\n </div>\n {pkgStatus.logs.length > 0 && (\n <details className=\"updates-pkg-logs\">\n <summary>npm output ({pkgStatus.logs.length} lines)</summary>\n <pre>{pkgStatus.logs.join('\\n')}</pre>\n </details>\n )}\n {pkgStatus.status === 'error' && pkgStatus.error && (\n <div className=\"updates-pkg-error\">\n <AlertTriangle size={12} /> {pkgStatus.error}\n </div>\n )}\n </div>\n );\n })}\n </div>\n )}\n\n {/* Actions */}\n <div className=\"updates-actions\">\n <Button onClick={check} disabled={isBusy}>\n {status.checking ? <span className=\"btn-spinner\" /> : <RefreshCw size={14} />}\n Check for updates\n </Button>\n <Button\n variant=\"primary\"\n onClick={applyUpdate}\n disabled={!status.hasUpdates || status.updating}\n >\n {status.updating ? <span className=\"btn-spinner\" /> : <Download size={14} />}\n {status.updating ? 'Updating…' : (status.hasUpdates ? 'Update now' : 'Up to date')}\n </Button>\n {status.requiresRestart && (\n <Button variant=\"danger\" onClick={restart}>\n <RefreshCw size={14} /> Restart Dashboard\n </Button>\n )}\n </div>\n\n {status.error && (\n <div className=\"updates-error\">\n <AlertTriangle size={14} />\n <span>{status.error}</span>\n </div>\n )}\n </Card>\n );\n}\n\nexport function SettingsView({ settings: initial, refreshSnapshot }: Props) {\n const toast = useToast();\n const [settings, setSettings] = useState<Settings>(initial);\n const [dirty, setDirty] = useState(false);\n const [saving, setSaving] = useState(false);\n const [tailscale, setTailscale] = useState<TailscaleStatus | null>(null);\n const [tailscaleDraft, setTailscaleDraft] = useState({ port: 4321, https: true, hostname: '' });\n const [pluginOptions, setPluginOptions] = useState<Record<string, number>>({});\n\n useEffect(() => {\n setSettings(initial);\n setDirty(false);\n if (initial.theme) applyThemeTokens(initial.theme);\n }, [initial]);\n\n useEffect(() => {\n if (!tailscale) return;\n setTailscaleDraft({\n port: tailscale.settings.port,\n https: tailscale.settings.https !== false,\n hostname: tailscale.settings.hostname || '',\n });\n }, [tailscale]);\n\n useEffect(() => {\n api.get<TailscaleStatus>('/tailscale/status').then(setTailscale).catch(() => undefined);\n }, []);\n\n useEffect(() => {\n api.get<Record<string, number>>('/settings/plugin-options')\n .then(setPluginOptions)\n .catch(() => { /* not persisted yet — use defaults */ });\n }, []);\n\n const patchTheme = (patch: Partial<Settings['theme']>) => {\n setSettings((cur) => {\n const next = { ...cur, theme: { ...cur.theme, ...patch } };\n applyThemeTokens(next.theme);\n return next;\n });\n setDirty(true);\n };\n\n const patchUi = (patch: Partial<Settings['ui']>) => {\n setSettings((cur) => ({ ...cur, ui: { ...cur.ui, ...patch } }));\n setDirty(true);\n };\n\n const patchTop = <K extends keyof Settings>(key: K, value: Settings[K]) => {\n setSettings((cur) => ({ ...cur, [key]: value }));\n setDirty(true);\n };\n\n const patchNotifications = (patch: Partial<Settings['notifications']>) => {\n setSettings((cur) => ({ ...cur, notifications: { ...cur.notifications, ...patch } }));\n setDirty(true);\n };\n\n const patchAgents = (patch: Partial<Settings['agents']>) => {\n setSettings((cur) => ({ ...cur, agents: { ...cur.agents, ...patch } }));\n setDirty(true);\n };\n\n // v3.17.0 — Settings subnav as a filter (not just scroll-to).\n // Clicking a subnav button shows ONLY that section; clicking \"All\"\n // restores the full layout. Anchors still work for deep-links but\n // the visible content is filtered, not just scrolled.\n //\n // v3.18.0 — IDs use the section NAME (not the `settings-X` element id)\n // because the inline-style wrap compares against the section name, not\n // the prefixed DOM id.\n const SECTION_LINKS: Array<{ id: string; label: string }> = [\n { id: 'theme', label: 'Theme' },\n { id: 'layout', label: 'Layout' },\n { id: 'general', label: 'General' },\n { id: 'service', label: 'Service' },\n { id: 'tailscale', label: 'Tailscale' },\n { id: 'notifications', label: 'Notifications' },\n { id: 'auth', label: 'Auth' },\n { id: 'agents', label: 'Agents' },\n { id: 'dashboard', label: 'Dashboard' },\n { id: 'background', label: 'Background' },\n { id: 'system-llm', label: 'System LLM' },\n { id: 'updates', label: 'Updates' },\n { id: 'activity-log', label: 'Activity' },\n { id: 'about', label: 'About' },\n ];\n const [activeSection, setActiveSection] = useState<string | null>(() => {\n // Honour #settings-... deep-link on initial mount, otherwise null = All.\n if (typeof window === 'undefined') return null;\n const hash = window.location.hash.replace(/^#settings-/, '');\n return SECTION_LINKS.some((s) => s.id === hash) ? hash : null;\n });\n const onJumpSection = (id: string | null) => {\n setActiveSection(id);\n try {\n const url = id ? `#settings-${id}` : window.location.pathname;\n history.replaceState(null, '', url);\n if (id) {\n const el = document.getElementById(`settings-${id}`);\n if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' });\n } else {\n window.scrollTo({ top: 0, behavior: 'smooth' });\n }\n } catch { /* ignore */ }\n };\n // The user picks a section via the subnav; their choice is respected.\n // (v3.18.0 — Removed auto-scroll-based detection; with the inline-style\n // filter approach, hidden sections still report bounding rects, so the\n // detector would race the user's explicit selection and switch tabs back.)\n\n const patchDashboard = (patch: Partial<Settings['dashboard']>) => {\n setSettings((cur) => ({ ...cur, dashboard: { ...cur.dashboard, ...patch } }));\n setDirty(true);\n };\n\n const onSave = async () => {\n setSaving(true);\n try {\n const r = await api.put<SettingsResponse>('/settings', settings);\n setSettings(r.data);\n setDirty(false);\n applyTheme(r.data.theme);\n applyThemeTokens(r.data.theme);\n toast.success('Settings saved.');\n await refreshSnapshot();\n } catch (err) {\n toast.error(`Save failed: ${(err as Error).message}`);\n } finally {\n setSaving(false);\n }\n };\n\n const onReload = async () => {\n try {\n const r = await api.get<SettingsResponse>('/settings');\n setSettings(r.data);\n setDirty(false);\n applyTheme(r.data.theme);\n applyThemeTokens(r.data.theme);\n toast.info('Settings reloaded.', 1500);\n } catch (err) {\n toast.error(`Reload failed: ${(err as Error).message}`);\n }\n };\n\n const onReset = async () => {\n if (!confirm('Reset all settings to defaults?')) return;\n try {\n const r = await api.post<SettingsResponse>('/settings/reset');\n setSettings(r.data);\n setDirty(false);\n applyTheme(r.data.theme);\n applyThemeTokens(r.data.theme);\n toast.success('Settings reset.');\n await refreshSnapshot();\n } catch (err) {\n toast.error(`Reset failed: ${(err as Error).message}`);\n }\n };\n\n const onTailscaleToggle = async () => {\n try {\n if (tailscale?.settings.enabled) {\n await api.post('/tailscale/disable');\n toast.success('Tailscale serve disabled.');\n } else {\n await api.post('/tailscale/enable', {\n port: tailscaleDraft.port || 4321,\n https: tailscaleDraft.https,\n hostname: tailscaleDraft.hostname || '',\n });\n toast.success('Tailscale serve enabled.');\n }\n const r = await api.get<TailscaleStatus>('/tailscale/status');\n setTailscale(r);\n } catch (err) {\n toast.error(`Tailscale failed: ${(err as Error).message}`);\n }\n };\n\n const about = settings.about || {\n version: '3.0.4',\n homepage: 'https://github.com/DrB0rk/BizarHarness',\n license: 'MIT',\n };\n\n // v3.6.0 — Auth token UI state. The Settings tab is the only place\n // the operator can read the token back out. We default the input\n // to whatever's already in localStorage so a page reload doesn't\n // wipe the entry.\n const [authToken, setAuthToken] = useState<string>(api.getToken());\n const [authStatus, setAuthStatus] = useState<{ required: boolean; loopback: boolean; peer: string } | null>(null);\n const [revealedToken, setRevealedToken] = useState<string>('');\n\n // Probe the server once on mount so we can show \"auth required\" vs\n // \"auth off\" in the UI. If /api/auth/status itself 401s, the token\n // we're using is bad — surface that distinctly.\n useEffect(() => {\n let cancelled = false;\n (async () => {\n try {\n const r = await api.probeAuthStatus();\n if (!cancelled) setAuthStatus(r);\n } catch {\n if (!cancelled) {\n setAuthStatus({ required: true, loopback: false, peer: '' });\n // Don't toast — the toast spam would be annoying on every\n // Settings tab open. The Copy/Regenerate buttons themselves\n // surface the real error if it happens there.\n }\n }\n })();\n return () => { cancelled = true; };\n }, []);\n\n const onCopyToken = async () => {\n try {\n const r = await api.get<{ token: string }>('/auth/reveal');\n setRevealedToken(r.token);\n setAuthToken(r.token);\n api.setToken(r.token);\n try {\n await navigator.clipboard.writeText(r.token);\n toast.success('Token copied to clipboard.');\n } catch {\n toast.success('Token revealed — copy from the field below.');\n }\n } catch (err) {\n toast.error(`Reveal failed: ${(err as Error).message}`);\n }\n };\n\n const onRegenerateToken = async () => {\n if (!confirm('Regenerate the auth token? Anything still using the old token will start getting 401 errors immediately.')) {\n return;\n }\n try {\n const r = await api.post<{ token: string }>('/auth/regenerate');\n setRevealedToken(r.token);\n setAuthToken(r.token);\n api.setToken(r.token);\n try {\n await navigator.clipboard.writeText(r.token);\n toast.success('New token generated and copied to clipboard.');\n } catch {\n toast.success('New token generated — copy from the field below. Old token is now invalid.');\n }\n } catch (err) {\n toast.error(`Regenerate failed: ${(err as Error).message}`);\n }\n };\n\n const onSaveToken = () => {\n api.setToken(authToken.trim());\n toast.success('Token saved. The dashboard will use it on the next request.');\n };\n\n return (\n <div className=\"view view-settings\">\n <header className=\"view-header\">\n <div className=\"view-header-text\">\n <h2 className=\"view-title\">\n <Sliders size={18} /> Settings\n </h2>\n <p className=\"view-subtitle\">\n Personal preferences. Changes are saved to{' '}\n <code>~/.config/bizar/settings.json</code>.\n </p>\n </div>\n <div className=\"view-actions\">\n <Button variant=\"ghost\" size=\"sm\" onClick={onReset}>\n <RotateCcw size={14} /> Reset\n </Button>\n <Button variant=\"secondary\" size=\"sm\" onClick={onReload}>\n <RefreshCw size={14} /> Reload\n </Button>\n <Button\n variant=\"primary\"\n size=\"sm\"\n disabled={!dirty || saving}\n onClick={onSave}\n >\n {saving ? <span className=\"btn-spinner\" /> : <Save size={14} />}\n {saving ? 'Saving…' : 'Save'}\n </Button>\n </div>\n </header>\n\n <nav className=\"settings-subnav\" aria-label=\"Settings sections\">\n <button\n type=\"button\"\n className={cn('settings-subnav-button', 'settings-subnav-button-all', activeSection === null && 'settings-subnav-button-active')}\n onClick={() => onJumpSection(null)}\n title=\"Show all settings sections\"\n >\n All\n </button>\n {SECTION_LINKS.map((s) => (\n <button\n key={s.id}\n type=\"button\"\n className={cn('settings-subnav-button', activeSection === s.id && 'settings-subnav-button-active')}\n onClick={() => onJumpSection(s.id)}\n >\n {s.label}\n </button>\n ))}\n </nav>\n\n <div\n className={cn('settings-grid', activeSection && 'settings-grid-filtered')}\n data-active-section={activeSection || undefined}\n >\n {/* When a section is active, render a banner above the grid so\n the user knows they're seeing a filtered view. */}\n {activeSection && (\n <div className=\"settings-filter-banner\">\n <span>\n Showing only <strong>{SECTION_LINKS.find((s) => s.id === activeSection)?.label}</strong>.\n </span>\n <button\n type=\"button\"\n className=\"settings-filter-clear\"\n onClick={() => onJumpSection(null)}\n >\n Show all sections\n </button>\n </div>\n )}\n <div data-section=\"theme\" style={{display: (activeSection === null || activeSection === 'theme') ? 'block' : 'none'}}>\n<Card id=\"settings-theme\" data-section=\"theme\">\n <CardTitle><Palette size={14} /> Theme</CardTitle>\n <CardMeta>Mode, accent, and colors. Live preview as you tweak.</CardMeta>\n\n {/* v3.3.1 — Accent color presets */}\n <div className=\"field\" data-setting-id=\"theme.presets\">\n <label className=\"field-label\">Accent presets</label>\n <div className=\"theme-presets\">\n {PRESET_THEMES.map((t) => (\n <button\n key={t.name}\n type=\"button\"\n className={cn(\n 'theme-preset',\n settings.theme.accent === t.accent && 'theme-preset-active',\n )}\n onClick={() => patchTheme({ accent: t.accent })}\n title={t.name}\n >\n <span\n className=\"theme-preset-swatch\"\n style={{ background: t.accent }}\n />\n <span className=\"theme-preset-name\">{t.name}</span>\n </button>\n ))}\n </div>\n </div>\n\n <div className=\"field\" data-setting-id=\"theme.mode\">\n <label className=\"field-label\">Mode</label>\n <div className=\"theme-row\">\n {THEMES.map(({ id, label, Icon }) => {\n const active = settings.theme.mode === id;\n return (\n <button\n key={id}\n type=\"button\"\n className={cn('theme-card', active && 'theme-card-active')}\n onClick={() => patchTheme({ mode: id })}\n >\n <Icon size={16} />\n <span className=\"theme-card-label\">{label}</span>\n <span\n className={cn(\n 'theme-card-swatch',\n `theme-card-swatch-${id}`,\n )}\n />\n </button>\n );\n })}\n </div>\n </div>\n\n <div className=\"theme-colors\">\n <div className=\"field\" data-setting-id=\"theme.accent\">\n <label className=\"field-label\">Accent</label>\n <div className=\"color-row\">\n <input\n type=\"color\"\n className=\"input color-input\"\n value={settings.theme.accent}\n onChange={(e) => patchTheme({ accent: e.target.value })}\n aria-label=\"Accent color\"\n />\n <input\n type=\"text\"\n className=\"input\"\n value={settings.theme.accent}\n onChange={(e) => patchTheme({ accent: e.target.value })}\n />\n </div>\n </div>\n <div className=\"field\" data-setting-id=\"theme.success\">\n <label className=\"field-label\">Success</label>\n <div className=\"color-row\">\n <input\n type=\"color\"\n className=\"input color-input\"\n value={settings.theme.success}\n onChange={(e) => patchTheme({ success: e.target.value })}\n aria-label=\"Success color\"\n />\n <input\n type=\"text\"\n className=\"input\"\n value={settings.theme.success}\n onChange={(e) => patchTheme({ success: e.target.value })}\n />\n </div>\n </div>\n <div className=\"field\" data-setting-id=\"theme.warning\">\n <label className=\"field-label\">Warning</label>\n <div className=\"color-row\">\n <input\n type=\"color\"\n className=\"input color-input\"\n value={settings.theme.warning}\n onChange={(e) => patchTheme({ warning: e.target.value })}\n aria-label=\"Warning color\"\n />\n <input\n type=\"text\"\n className=\"input\"\n value={settings.theme.warning}\n onChange={(e) => patchTheme({ warning: e.target.value })}\n />\n </div>\n </div>\n <div className=\"field\" data-setting-id=\"theme.error\">\n <label className=\"field-label\">Error</label>\n <div className=\"color-row\">\n <input\n type=\"color\"\n className=\"input color-input\"\n value={settings.theme.error}\n onChange={(e) => patchTheme({ error: e.target.value })}\n aria-label=\"Error color\"\n />\n <input\n type=\"text\"\n className=\"input\"\n value={settings.theme.error}\n onChange={(e) => patchTheme({ error: e.target.value })}\n />\n </div>\n </div>\n <div className=\"field\" data-setting-id=\"theme.info\">\n <label className=\"field-label\">Info</label>\n <div className=\"color-row\">\n <input\n type=\"color\"\n className=\"input color-input\"\n value={settings.theme.info}\n onChange={(e) => patchTheme({ info: e.target.value })}\n aria-label=\"Info color\"\n />\n <input\n type=\"text\"\n className=\"input\"\n value={settings.theme.info}\n onChange={(e) => patchTheme({ info: e.target.value })}\n />\n </div>\n </div>\n </div>\n\n <div className=\"field\" data-setting-id=\"theme.fontFamily\">\n <label className=\"field-label\">Font family</label>\n <select\n className=\"select\"\n value={settings.theme.fontFamily}\n onChange={(e) => patchTheme({ fontFamily: e.target.value })}\n >\n {FONT_FAMILIES.map((f) => (\n <option key={f} value={f}>{f}</option>\n ))}\n </select>\n </div>\n <div className=\"field\" data-setting-id=\"theme.fontSize\">\n <label className=\"field-label\">Font size: {settings.theme.fontSize}px</label>\n <input\n type=\"range\"\n min={12}\n max={20}\n value={settings.theme.fontSize}\n onChange={(e) => patchTheme({ fontSize: Number(e.target.value) })}\n />\n </div>\n <label className=\"checkbox-row\" data-setting-id=\"theme.compactMode\">\n <input\n type=\"checkbox\"\n checked={settings.theme.compactMode}\n onChange={(e) => patchTheme({ compactMode: e.target.checked })}\n />\n <span>Compact mode (denser UI)</span>\n </label>\n <label className=\"checkbox-row\" data-setting-id=\"theme.animations\">\n <input\n type=\"checkbox\"\n checked={settings.theme.animations}\n onChange={(e) => patchTheme({ animations: e.target.checked })}\n />\n <span>Enable animations</span>\n </label>\n </Card>\n</div>\n\n <div data-section=\"updates\" style={{display: (activeSection === null || activeSection === 'updates') ? 'block' : 'none'}}>\n <UpdatesCard />\n </div>\n\n <div data-section=\"layout\" style={{display: (activeSection === null || activeSection === 'layout') ? 'block' : 'none'}}>\n<Card id=\"settings-layout\" data-section=\"layout\">\n <CardTitle><LayoutIcon size={14} /> UI layout</CardTitle>\n <CardMeta>Choose how the dashboard's navigation is presented.</CardMeta>\n <div className=\"layout-row\" data-setting-id=\"ui.layout\">\n {LAYOUTS.map((l) => (\n <button\n key={l.id}\n type=\"button\"\n className={cn('layout-card', settings.ui.layout === l.id && 'layout-card-active')}\n onClick={() => patchUi({ layout: l.id })}\n >\n <span className=\"layout-card-label\">{l.label}</span>\n </button>\n ))}\n </div>\n <label className=\"checkbox-row\" data-setting-id=\"ui.showHeader\">\n <input\n type=\"checkbox\"\n checked={settings.ui.showHeader}\n onChange={(e) => patchUi({ showHeader: e.target.checked })}\n />\n <span>Show header</span>\n </label>\n <label className=\"checkbox-row\" data-setting-id=\"ui.showStatusBar\">\n <input\n type=\"checkbox\"\n checked={settings.ui.showStatusBar}\n onChange={(e) => patchUi({ showStatusBar: e.target.checked })}\n />\n <span>Show status bar</span>\n </label>\n <div className=\"field\" data-setting-id=\"ui.defaultTab\">\n <label className=\"field-label\">Default tab</label>\n <select\n className=\"select\"\n value={settings.ui.defaultTab}\n onChange={(e) => patchUi({ defaultTab: e.target.value })}\n >\n <option value=\"overview\">Overview</option>\n <option value=\"chat\">Chat</option>\n <option value=\"agents\">Agents</option>\n <option value=\"artifacts\">Plans</option>\n <option value=\"projects\">Projects</option>\n <option value=\"tasks\">Tasks</option>\n <option value=\"config\">Config</option>\n <option value=\"settings\">Settings</option>\n <option value=\"mods\">Mods</option>\n <option value=\"schedules\">Schedules</option>\n </select>\n </div>\n </Card>\n</div>\n\n <div data-section=\"general\" style={{display: (activeSection === null || activeSection === 'general') ? 'block' : 'none'}}>\n<Card id=\"settings-general\" data-section=\"general\">\n <CardTitle>General</CardTitle>\n <CardMeta>Default agent + model override.</CardMeta>\n <div className=\"field\" data-setting-id=\"defaultAgent\">\n <label className=\"field-label\" htmlFor=\"set-default-agent\">Default agent</label>\n <input\n id=\"set-default-agent\"\n className=\"input\"\n type=\"text\"\n placeholder=\"e.g. odin\"\n value={settings.defaultAgent || ''}\n onChange={(e) => patchTop('defaultAgent', e.target.value)}\n />\n </div>\n <div className=\"field\" data-setting-id=\"defaultModel\">\n <label className=\"field-label\" htmlFor=\"set-default-model\">Model override</label>\n <input\n id=\"set-default-model\"\n className=\"input\"\n type=\"text\"\n placeholder=\"(leave empty for provider default)\"\n value={settings.defaultModel || ''}\n onChange={(e) => patchTop('defaultModel', e.target.value)}\n />\n </div>\n </Card>\n</div>\n\n <div data-section=\"service\" style={{display: (activeSection === null || activeSection === 'service') ? 'block' : 'none'}}>\n<Card id=\"settings-service\" data-section=\"service\">\n <CardTitle><ServerIcon size={14} /> Service</CardTitle>\n <CardMeta>Background daemon that runs schedules.</CardMeta>\n <div data-setting-id=\"service.enabled\">\n {tailscale ? (\n <div className=\"service-card\">\n <p>\n Status: <strong>{tailscale?.settings.enabled ? 'enabled' : 'disabled'}</strong>\n {' '}· Tailscale installed: <strong>{tailscale.installed ? 'yes' : 'no'}</strong>\n {' '}· authenticated: <strong>{tailscale.authenticated ? 'yes' : 'no'}</strong>\n </p>\n <p className=\"muted\">\n Use <code>bizar service start</code> / <code>bizar service stop</code> in\n your terminal to control the daemon.\n </p>\n </div>\n ) : (\n <p className=\"muted\">Loading service status…</p>\n )}\n </div>\n </Card>\n</div>\n\n <div data-section=\"tailscale\" style={{display: (activeSection === null || activeSection === 'tailscale') ? 'block' : 'none'}}>\n<Card id=\"settings-tailscale\" data-section=\"tailscale\">\n <CardTitle><Plug size={14} /> Tailscale serve</CardTitle>\n <CardMeta>Expose the dashboard over your Tailscale network.</CardMeta>\n {tailscale ? (\n <>\n <p>\n Installed: <strong>{tailscale.installed ? 'yes' : 'no'}</strong>{' '}\n {tailscale.version && <span className=\"muted\">({tailscale.version})</span>}\n </p>\n <p>\n Authenticated: <strong>{tailscale.authenticated ? 'yes' : 'no'}</strong>\n </p>\n <p>\n Serve enabled: <strong>{tailscale.settings.enabled ? 'yes' : 'no'}</strong>\n </p>\n <div className=\"task-form-row\">\n <div className=\"task-form-field\">\n <label className=\"field-label\">Port</label>\n <input\n type=\"number\"\n className=\"input\"\n value={tailscaleDraft.port}\n onChange={(e) => setTailscaleDraft((cur) => ({ ...cur, port: Number(e.target.value) || 4321 }))}\n />\n </div>\n <div className=\"task-form-field\">\n <label className=\"field-label\">Use HTTPS</label>\n <input\n type=\"checkbox\"\n checked={tailscaleDraft.https}\n onChange={(e) => setTailscaleDraft((cur) => ({ ...cur, https: e.target.checked }))}\n />\n </div>\n </div>\n <Button variant=\"primary\" onClick={onTailscaleToggle}>\n {tailscale.settings.enabled ? 'Disable serve' : 'Enable serve'}\n </Button>\n </>\n ) : (\n <p className=\"muted\">Loading Tailscale status…</p>\n )}\n </Card>\n</div>\n\n <div data-section=\"notifications\" style={{display: (activeSection === null || activeSection === 'notifications') ? 'block' : 'none'}}>\n<Card id=\"settings-notifications\" data-section=\"notifications\">\n <CardTitle>Notifications</CardTitle>\n <CardMeta>Toast triggers inside the dashboard.</CardMeta>\n <label className=\"checkbox-row\" data-setting-id=\"notifications.onAgentComplete\">\n <input\n type=\"checkbox\"\n checked={!!settings.notifications.onAgentComplete}\n onChange={(e) => patchNotifications({ onAgentComplete: e.target.checked })}\n />\n <span>Notify when an agent invocation completes</span>\n </label>\n <label className=\"checkbox-row\" data-setting-id=\"notifications.onPlanApproval\">\n <input\n type=\"checkbox\"\n checked={!!settings.notifications.onPlanApproval}\n onChange={(e) => patchNotifications({ onPlanApproval: e.target.checked })}\n />\n <span>Notify when a plan needs approval</span>\n </label>\n </Card>\n</div>\n\n {/* v3.6.0 — Auth token management. The Settings tab is the\n only place a human can read the token. The input + Save\n button lets the operator paste a token they got from\n server stderr or from another machine. Copy / Regenerate\n buttons act via the authed /api/auth/* endpoints. */}\n <div data-section=\"auth\" style={{display: (activeSection === null || activeSection === 'auth') ? 'block' : 'none'}}>\n<Card id=\"settings-auth\" data-section=\"auth\">\n <CardTitle><Shield size={14} /> Authentication</CardTitle>\n <CardMeta>\n Localhost and Tailscale browser access are auto-trusted via loopback.\n A bearer token is still available for non-loopback clients and\n forced-auth mode.\n </CardMeta>\n <div className=\"field\" data-setting-id=\"auth.status\">\n <label className=\"field-label\">Server status</label>\n <p style={{ margin: '4px 0' }}>\n Auth required:{' '}\n <strong>{authStatus ? (authStatus.required ? 'yes' : 'no') : 'probing…'}</strong>\n </p>\n <p style={{ margin: '4px 0' }}>\n Connection:{' '}\n <strong>\n {authStatus\n ? (authStatus.loopback ? 'loopback (auto-trusted)' : 'remote')\n : 'probing…'}\n </strong>\n </p>\n <p style={{ margin: '4px 0' }}>\n Peer address:{' '}\n {authStatus?.peer ? <code>{authStatus.peer}</code> : <span className=\"muted\">probing…</span>}\n </p>\n <p className=\"muted\" style={{ fontSize: 12, margin: '4px 0' }}>\n Localhost and Tailscale browser access are auto-trusted because the\n dashboard sees a loopback peer. Paste a token only for non-loopback\n API clients/scripts, or if you force auth for every connection with{' '}\n <code>BIZAR_DASHBOARD_REQUIRE_AUTH=1</code>.\n </p>\n <p className=\"muted\" style={{ fontSize: 12, margin: '4px 0' }}>\n Dashboard tokens are generated on first boot and saved to{' '}\n <code>~/.config/bizar/dashboard-secret</code> (mode 0600).\n </p>\n </div>\n <div className=\"field\" data-setting-id=\"auth.token\">\n <label className=\"field-label\">Token (this browser)</label>\n <input\n type=\"password\"\n className=\"input mono\"\n value={authToken}\n onChange={(e) => setAuthToken(e.target.value)}\n placeholder=\"Paste token from server stderr or another browser\"\n spellCheck={false}\n autoComplete=\"off\"\n />\n <div className=\"task-form-row\" style={{ marginTop: 8 }}>\n <Button variant=\"secondary\" size=\"sm\" onClick={onSaveToken}>\n <KeyRound size={14} /> Save token\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={onCopyToken}>\n <Copy size={14} /> Reveal & copy server token\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={onRegenerateToken}>\n <RotateCcw size={14} /> Regenerate\n </Button>\n </div>\n {revealedToken ? (\n <p className=\"muted\" style={{ fontSize: 12, marginTop: 8 }}>\n Last revealed token (one-time): <code className=\"mono\">{revealedToken}</code>\n </p>\n ) : null}\n <p className=\"muted\" style={{ fontSize: 12, marginTop: 8 }}>\n Regenerating invalidates the current token immediately. Anything\n still using the old token will see 401 until it's updated.\n </p>\n </div>\n </Card>\n</div>\n\n <div data-section=\"agents\" style={{display: (activeSection === null || activeSection === 'agents') ? 'block' : 'none'}}>\n<Card id=\"settings-agents\" data-section=\"agents\">\n <CardTitle><ServerIcon size={14} /> Agent Behavior</CardTitle>\n <CardMeta>Limits and timeouts for background agent dispatch.</CardMeta>\n <div className=\"form-row\">\n <label htmlFor=\"agents-maxParallel\">\n Max parallel agents\n <span className=\"meta-badge\">default: 6</span>\n </label>\n <input\n id=\"agents-maxParallel\"\n type=\"number\"\n min={1}\n max={20}\n value={settings.agents?.maxParallel ?? 6}\n onChange={(e) => patchAgents({ maxParallel: Math.max(1, Math.min(20, parseInt(e.target.value, 10) || 6)) })}\n />\n </div>\n <div className=\"form-row\">\n <label htmlFor=\"agents-stuckThresholdMs\">\n Stuck threshold (ms)\n <span className=\"meta-badge\">default: 600000 (10 min)</span>\n </label>\n <input\n id=\"agents-stuckThresholdMs\"\n type=\"number\"\n min={60000}\n max={3600000}\n step={60000}\n value={settings.agents?.stuckThresholdMs ?? 600000}\n onChange={(e) => patchAgents({ stuckThresholdMs: Math.max(60000, Math.min(3600000, parseInt(e.target.value, 10) || 600000)) })}\n />\n </div>\n <label className=\"checkbox-row\" data-setting-id=\"agents.autoRestart\">\n <input\n type=\"checkbox\"\n checked={!!settings.agents?.autoRestart}\n onChange={(e) => patchAgents({ autoRestart: e.target.checked })}\n />\n <span>Auto-restart stuck agents</span>\n </label>\n </Card>\n</div>\n\n <div data-section=\"dashboard\" style={{display: (activeSection === null || activeSection === 'dashboard') ? 'block' : 'none'}}>\n<Card id=\"settings-dashboard\" data-section=\"dashboard\">\n <CardTitle><Globe size={14} /> Dashboard</CardTitle>\n <CardMeta>Controls how <code>bizar</code> starts up.</CardMeta>\n <label className=\"checkbox-row\" data-setting-id=\"dashboard.autoLaunchWeb\">\n <input\n type=\"checkbox\"\n checked={settings.dashboard.autoLaunchWeb !== false}\n onChange={(e) => patchDashboard({ autoLaunchWeb: e.target.checked })}\n />\n <span>Auto-launch web UI alongside TUI</span>\n </label>\n\n <div className=\"field\" data-setting-id=\"dashboard.projectsDirectory\" style={{ marginTop: 'var(--space-4)' }}>\n <label className=\"field-label\" htmlFor=\"set-projects-directory\">Projects directory</label>\n <input\n id=\"set-projects-directory\"\n className=\"input\"\n type=\"text\"\n placeholder=\"/home/user/projects\"\n value={settings.dashboard.projectsDirectory ?? ''}\n onChange={(e) => patchDashboard({ projectsDirectory: e.target.value })}\n />\n <p className=\"field-help\">\n New projects created via the dashboard will land here, and existing project\n directories inside this folder are auto-recognized on startup.\n </p>\n {settings.dashboard.projectsDirectory && (\n <>\n {!/^\\/|^[A-Za-z]:/.test(settings.dashboard.projectsDirectory) && (\n <p style={{ color: 'var(--warning)', fontSize: 11, marginTop: 4 }}>\n Path should be absolute (start with / on Linux/Mac, or a drive letter on Windows).\n </p>\n )}\n {settings.dashboard.projectsDirectory.includes('..') && (\n <p style={{ color: 'var(--error)', fontSize: 11, marginTop: 4 }}>\n Path traversal not allowed — this will be rejected server-side.\n </p>\n )}\n </>\n )}\n </div>\n\n {/* allowedRoots textarea */}\n <div className=\"field\" data-setting-id=\"dashboard.allowedRoots\" style={{ marginTop: 'var(--space-4)' }}>\n <label className=\"field-label\" htmlFor=\"set-allowed-roots\">\n Additional allowed roots <span className=\"muted\">(advanced)</span>\n </label>\n <textarea\n id=\"set-allowed-roots\"\n className=\"textarea\"\n rows={4}\n placeholder=\"/workspace /srv/projects\"\n value={(settings.dashboard.allowedRoots ?? []).join('\\n')}\n onChange={(e) => {\n const lines = e.target.value\n .split('\\n')\n .map((l) => l.trim())\n .filter(Boolean);\n patchDashboard({ allowedRoots: lines });\n }}\n />\n <p className=\"field-help\">\n Optional. Add filesystem roots beyond your home directory that the file\n browser and project scanner can access. Each path must be inside your\n home directory. One per line.\n </p>\n {(() => {\n const rawLines = (settings.dashboard.allowedRoots ?? []).join('\\n').split('\\n');\n const warnings: { key: string; msg: React.ReactNode }[] = [];\n rawLines.forEach((line, i) => {\n if (!line.trim()) return;\n if (!/^\\/|^[A-Za-z]:/.test(line)) {\n warnings.push({\n key: `noabs-${i}`,\n msg: (\n <p style={{ color: 'var(--warning)', fontSize: 11, marginTop: 2 }}>\n Line {i + 1}: \"{line}\" — should be absolute (start with / or a drive letter).\n </p>\n ),\n });\n }\n if (line.includes('..')) {\n warnings.push({\n key: `dots-${i}`,\n msg: (\n <p style={{ color: 'var(--error)', fontSize: 11, marginTop: 2 }}>\n Line {i + 1}: \"{line}\" — contains '..' (server will reject this).\n </p>\n ),\n });\n }\n });\n return warnings.map((w) => w.msg);\n })()}\n </div>\n </Card>\n</div>\n\n <div data-section=\"background\" style={{display: (activeSection === null || activeSection === 'background') ? 'block' : 'none'}}>\n<Card id=\"settings-background\" data-section=\"background\">\n <CardTitle><ServerIcon size={14} /> Background Agents</CardTitle>\n <CardMeta>Tune plugin options. Changes take effect on next plugin restart.</CardMeta>\n\n <div className=\"form-row\">\n <label htmlFor=\"bg-maxConcurrent\">\n Max concurrent instances\n <span className=\"meta-badge\">default: 8</span>\n </label>\n <input\n id=\"bg-maxConcurrent\"\n type=\"number\"\n min={1}\n max={32}\n value={pluginOptions.maxConcurrentInstances ?? 8}\n onChange={(e) => setPluginOptions((cur) => ({ ...cur, maxConcurrentInstances: Math.max(1, Math.min(32, parseInt(e.target.value, 10) || 8)) }))}\n />\n <small className=\"muted\">Plugin option: <code>maxConcurrentInstances</code></small>\n </div>\n\n <div className=\"form-row\">\n <label htmlFor=\"bg-toolCallCap\">\n Tool-call cap\n <span className=\"meta-badge\">default: 500</span>\n </label>\n <input\n id=\"bg-toolCallCap\"\n type=\"number\"\n min={1}\n max={5000}\n value={pluginOptions.backgroundToolCallCap ?? 500}\n onChange={(e) => setPluginOptions((cur) => ({ ...cur, backgroundToolCallCap: Math.max(1, Math.min(5000, parseInt(e.target.value, 10) || 500)) }))}\n />\n <small className=\"muted\">Plugin option: <code>backgroundToolCallCap</code></small>\n </div>\n\n <div className=\"form-row\">\n <label htmlFor=\"bg-stallTimeout\">\n Stall timeout (ms)\n <span className=\"meta-badge\">default: 180000</span>\n </label>\n <input\n id=\"bg-stallTimeout\"\n type=\"number\"\n min={10000}\n max={600000}\n step={1000}\n value={pluginOptions.backgroundStallTimeoutMs ?? 180000}\n onChange={(e) => setPluginOptions((cur) => ({ ...cur, backgroundStallTimeoutMs: Math.max(10000, Math.min(600000, parseInt(e.target.value, 10) || 180000)) }))}\n />\n <small className=\"muted\">Plugin option: <code>backgroundStallTimeoutMs</code></small>\n </div>\n\n <div className=\"form-row\">\n <label htmlFor=\"bg-thinkingLoopTimeout\">\n Thinking-loop timeout (ms)\n <span className=\"meta-badge\">default: 300000</span>\n </label>\n <input\n id=\"bg-thinkingLoopTimeout\"\n type=\"number\"\n min={30000}\n max={900000}\n step={1000}\n value={pluginOptions.backgroundThinkingLoopTimeoutMs ?? 300000}\n onChange={(e) => setPluginOptions((cur) => ({ ...cur, backgroundThinkingLoopTimeoutMs: Math.max(30000, Math.min(900000, parseInt(e.target.value, 10) || 300000)) }))}\n />\n <small className=\"muted\">Plugin option: <code>backgroundThinkingLoopTimeoutMs</code></small>\n </div>\n\n <div className=\"form-row\">\n <label htmlFor=\"bg-maxInterventions\">\n Max interventions\n <span className=\"meta-badge\">default: 1</span>\n </label>\n <input\n id=\"bg-maxInterventions\"\n type=\"number\"\n min={1}\n max={3}\n value={pluginOptions.backgroundMaxInterventions ?? 1}\n onChange={(e) => setPluginOptions((cur) => ({ ...cur, backgroundMaxInterventions: Math.max(1, Math.min(3, parseInt(e.target.value, 10) || 1)) }))}\n />\n <small className=\"muted\">Plugin option: <code>backgroundMaxInterventions</code></small>\n </div>\n\n <div className=\"form-row\">\n <Button variant=\"secondary\" size=\"sm\" onClick={async () => {\n try {\n await api.put('/settings/plugin-options', pluginOptions);\n toast.success('Saved — restart opencode for changes to take effect.');\n } catch (err) {\n toast.error(`Save failed: ${(err as Error).message}`);\n }\n }}>\n <Save size={14} /> Save plugin options\n </Button>\n\n <Button variant=\"secondary\" size=\"sm\" onClick={async () => {\n try {\n const r = await fetch('/api/background/cleanup', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ maxAgeDays: 7 }),\n });\n const result = await r.json();\n toast.success(`Cleaned up ${result.deleted} old instances.`);\n } catch (err) {\n toast.error(`Cleanup failed: ${(err as Error).message}`);\n }\n }}>\n Cleanup old instances (>7 days)\n </Button>\n </div>\n\n <div className=\"form-row\">\n <small>Plugin options are read at startup. Save changes and run <code>bizar update</code> to apply.</small>\n </div>\n </Card>\n</div>\n </div>\n\n <div data-section=\"system-llm\" style={{display: (activeSection === null || activeSection === 'system-llm') ? 'block' : 'none'}}>\n<Card id=\"settings-system-llm\" data-section=\"system-llm\">\n <CardTitle><Sparkles size={14} /> System LLM API</CardTitle>\n <CardMeta>\n Configures the LLM used for automatic title generation, prompt enhancement,\n summarization, and other system-level calls.\n </CardMeta>\n\n <label className=\"checkbox-row\" data-setting-id=\"systemLlm.enabled\">\n <input\n type=\"checkbox\"\n checked={!!settings.systemLlm?.enabled}\n onChange={(e) => {\n const cur = settings.systemLlm || { enabled: true, provider: 'opencode', model: 'opencode/deepseek-v4-flash-free' };\n patchTop('systemLlm', { ...cur, enabled: e.target.checked });\n }}\n />\n <span>Enable system LLM calls</span>\n </label>\n\n <div className=\"field\" data-setting-id=\"systemLlm.provider\" style={{ marginTop: 'var(--space-3)' }}>\n <label className=\"field-label\" htmlFor=\"set-system-llm-provider\">Provider</label>\n <select\n id=\"set-system-llm-provider\"\n className=\"select\"\n value={settings.systemLlm?.provider || 'opencode'}\n onChange={(e) => {\n const cur = settings.systemLlm || { enabled: true, provider: 'opencode', model: 'opencode/deepseek-v4-flash-free' };\n patchTop('systemLlm', { ...cur, provider: e.target.value });\n }}\n >\n <option value=\"opencode\">Opencode</option>\n <option value=\"openrouter\">OpenRouter</option>\n <option value=\"minimax\">MiniMax</option>\n </select>\n </div>\n\n <div className=\"field\" data-setting-id=\"systemLlm.model\">\n <label className=\"field-label\" htmlFor=\"set-system-llm-model\">Model</label>\n <input\n id=\"set-system-llm-model\"\n className=\"input mono\"\n type=\"text\"\n placeholder=\"opencode/deepseek-v4-flash-free\"\n value={settings.systemLlm?.model || 'opencode/deepseek-v4-flash-free'}\n onChange={(e) => {\n const cur = settings.systemLlm || { enabled: true, provider: 'opencode', model: 'opencode/deepseek-v4-flash-free' };\n patchTop('systemLlm', { ...cur, model: e.target.value });\n }}\n />\n <p className=\"field-help\">\n The API key is read from <code>auth.json</code> for the selected provider.\n Leave the default model for best results.\n </p>\n </div>\n\n <div style={{ marginTop: 'var(--space-4)' }}>\n <h4 style={{ margin: '0 0 var(--space-2)' }}>Features using this API</h4>\n <ul className=\"settings-feature-list\" style={{ margin: 0, paddingLeft: 'var(--space-4)', lineHeight: 1.8 }}>\n <li>Auto-title generation for new chat sessions</li>\n <li>Auto-title generation for new tasks</li>\n <li>\"Enhance prompt\" button in the task input</li>\n <li>\"Enhance prompt\" button in the chat composer</li>\n <li className=\"muted\" style={{ fontSize: 12 }}>Future: summarization, name generation, and more</li>\n </ul>\n </div>\n </Card>\n</div>\n\n <PairDeviceCard />\n\n <div style={{display: (activeSection === null || activeSection === 'activity-log') ? 'block' : 'none'}}>\n <div data-section=\"activity-log\" style={{display: (activeSection === null || activeSection === 'activity-log') ? 'block' : 'none'}}>\n <section id=\"settings-activity-log\" data-section=\"activity-log\" className=\"settings-section-wrap\">\n <ActivityLogCard />\n </section>\n</div>\n</div>\n\n <div style={{display: (activeSection === null || activeSection === 'about') ? 'block' : 'none'}}>\n <div data-section=\"about\" style={{display: (activeSection === null || activeSection === 'about') ? 'block' : 'none'}}>\n <Card id=\"settings-about\" data-section=\"about\">\n <CardTitle><Info size={14} /> About</CardTitle>\n <CardMeta>Build metadata.</CardMeta>\n <dl className=\"about-table\">\n <dt>Version</dt>\n <dd className=\"mono\">{about.version}</dd>\n <dt>Homepage</dt>\n <dd>\n <a href={about.homepage} target=\"_blank\" rel=\"noopener noreferrer\">\n {about.homepage}\n </a>\n </dd>\n <dt>License</dt>\n <dd>{about.license}</dd>\n </dl>\n </Card>\n</div>\n</div>\n </div>\n );\n}\n\n/**\n * v3.15.0 — Full activity log + hidden set management.\n *\n * Two sources of truth:\n * - GET /activity — the full unfiltered log (incl. hidden entries)\n * - GET /activity/hidden — the list of keys the user chose to hide\n *\n * Hiding is non-destructive: hidden items still appear here so the\n * user can review / restore them.\n */\nfunction ActivityLogCard() {\n const toast = useToast();\n const [items, setItems] = useState<Array<{ kind?: string; ts?: string; slug?: string; message?: string }>>([]);\n const [hidden, setHidden] = useState<Set<string>>(new Set());\n const [loading, setLoading] = useState(true);\n const [filter, setFilter] = useState('');\n const [showHidden, setShowHidden] = useState(true);\n\n const refresh = useCallback(async () => {\n setLoading(true);\n try {\n const [log, hid] = await Promise.all([\n api.get<{ items: Array<{ kind?: string; ts?: string; slug?: string; message?: string }> }>('/activity'),\n api.get<{ hidden: string[] }>('/activity/hidden'),\n ]);\n setItems(Array.isArray(log.items) ? log.items : []);\n setHidden(new Set(hid.hidden || []));\n } catch (err) {\n toast.error(`Load failed: ${(err as Error).message}`);\n } finally {\n setLoading(false);\n }\n }, [toast]);\n\n useEffect(() => { refresh(); }, [refresh]);\n\n const keyOf = (it: { kind?: string; ts?: string; slug?: string }, idx: number) => {\n const k = `${it.kind || ''}|${it.ts || ''}|${it.slug || ''}|${idx}`;\n let h = 0;\n for (let i = 0; i < k.length; i++) h = ((h << 5) - h + k.charCodeAt(i)) | 0;\n return Math.abs(h).toString(16).padStart(8, '0').slice(0, 16);\n };\n\n const onRestoreAll = async () => {\n try {\n await api.del('/activity/hide');\n setHidden(new Set());\n toast.success('All hidden activity restored.');\n } catch (err) {\n toast.error(`Restore failed: ${(err as Error).message}`);\n }\n };\n\n const onRestoreOne = async (key: string) => {\n try {\n await api.del(`/activity/hide/${encodeURIComponent(key)}`);\n const next = new Set(hidden);\n next.delete(key);\n setHidden(next);\n } catch (err) {\n toast.error(`Restore failed: ${(err as Error).message}`);\n }\n };\n\n const filtered = items.filter((it, idx) => {\n const k = keyOf(it, idx);\n if (!showHidden && hidden.has(k)) return false;\n if (!filter) return true;\n const q = filter.toLowerCase();\n return [it.kind, it.slug, it.message].some((v) => typeof v === 'string' && v.toLowerCase().includes(q));\n });\n\n return (\n <Card id=\"settings-diagnostics\" data-section=\"diagnostics\">\n <CardTitle>\n <Activity size={14} /> Activity log\n <span className=\"muted\" style={{ fontWeight: 400, marginLeft: 8, fontSize: 12 }}>\n {items.length} total · {hidden.size} hidden\n </span>\n <Button variant=\"ghost\" size=\"sm\" style={{ marginLeft: 'auto' }} onClick={refresh} title=\"Reload\">\n <RefreshCw size={12} />\n </Button>\n </CardTitle>\n <CardMeta>\n Full history from <code>~/.bizar/activity.log</code>. Hiding an item in the Overview only hides it there — the entry stays here.\n </CardMeta>\n\n <div className=\"activity-log-toolbar\">\n <div className=\"activity-log-search\">\n <Search size={12} />\n <input\n type=\"text\"\n className=\"input\"\n placeholder=\"Filter by kind, slug, or message…\"\n value={filter}\n onChange={(e) => setFilter(e.target.value)}\n />\n </div>\n <label className=\"activity-log-toggle\">\n <input\n type=\"checkbox\"\n checked={showHidden}\n onChange={(e) => setShowHidden(e.target.checked)}\n />\n Show hidden\n </label>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n disabled={hidden.size === 0}\n onClick={onRestoreAll}\n title=\"Restore all hidden items to the Overview\"\n >\n <Eye size={12} /> Restore all\n </Button>\n </div>\n\n {loading ? (\n <div className=\"muted\" style={{ padding: '12px 0', fontSize: 12 }}>Loading…</div>\n ) : filtered.length === 0 ? (\n <div className=\"muted\" style={{ padding: '12px 0', fontSize: 12 }}>\n {items.length === 0 ? 'No activity yet.' : 'No items match the current filter.'}\n </div>\n ) : (\n <div className=\"activity-log-table-wrap\">\n <table className=\"activity-log-table\">\n <thead>\n <tr>\n <th>Kind</th>\n <th>Detail</th>\n <th>Time</th>\n <th></th>\n </tr>\n </thead>\n <tbody>\n {filtered.slice(0, 200).map((it, idx) => {\n const k = keyOf(it, idx);\n const isHidden = hidden.has(k);\n return (\n <tr key={`${it.ts}-${idx}`} className={cn(isHidden && 'activity-log-row-hidden')}>\n <td className=\"activity-log-kind\">{it.kind || 'activity'}</td>\n <td className=\"activity-log-detail\">\n {it.message || it.slug || '—'}\n </td>\n <td className=\"activity-log-time mono\">\n {it.ts ? new Date(it.ts).toLocaleString() : '—'}\n </td>\n <td>\n {isHidden ? (\n <Button variant=\"ghost\" size=\"sm\" onClick={() => onRestoreOne(k)} title=\"Restore to Overview\">\n <Eye size={12} />\n </Button>\n ) : (\n <span className=\"activity-log-state-tag\">shown</span>\n )}\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n {filtered.length > 200 && (\n <div className=\"muted\" style={{ fontSize: 11, padding: '8px 0' }}>\n Showing first 200 of {filtered.length}.\n </div>\n )}\n </div>\n )}\n </Card>\n );\n}\n","// src/views/Mods.tsx — list, install, enable/disable mods + mod views.\nimport { useEffect, useState } from 'react';\nimport {\n Puzzle,\n Plus,\n Trash2,\n Power,\n RefreshCw,\n Folder,\n FileText,\n FileCode,\n User,\n Terminal,\n BookOpen,\n X,\n ExternalLink,\n Globe,\n LayoutTemplate,\n Download,\n ChevronDown,\n ChevronRight,\n ShieldCheck,\n} from 'lucide-react';\nimport { Card, CardTitle, CardMeta } from '../components/Card';\nimport { Button } from '../components/Button';\nimport { EmptyState } from '../components/EmptyState';\nimport { Spinner } from '../components/Spinner';\nimport { useToast } from '../components/Toast';\nimport { useModal } from '../components/Modal';\nimport { api } from '../lib/api';\nimport { cn } from '../lib/utils';\nimport type { Mod, Settings, Snapshot } from '../lib/types';\n\ntype Props = {\n snapshot: Snapshot;\n settings: Settings;\n activeTab: string;\n setActiveTab: (id: string) => void;\n refreshSnapshot: () => Promise<void>;\n};\n\ntype ModView = {\n id: string;\n modId: string;\n kind: 'iframe' | 'tab';\n label: string;\n description?: string;\n path?: string;\n};\n\nexport function Mods({ snapshot, refreshSnapshot }: Props) {\n const toast = useToast();\n const modal = useModal();\n // v3.3.0 — Always start by loading from the server, not just the\n // snapshot. The snapshot can be stale if the user installed a mod\n // from the CLI or added files directly to ~/.config/bizar/mods.\n // We seed the initial state from the snapshot for instant paint\n // but always re-fetch on mount and after every mutation.\n const [mods, setMods] = useState<Mod[]>(Array.isArray(snapshot.mods) ? snapshot.mods : []);\n const [loading, setLoading] = useState(true);\n const [selected, setSelected] = useState<string | null>(null);\n const [modViews, setModViews] = useState<ModView[]>([]);\n const [iframeUrl, setIframeUrl] = useState<string | null>(null);\n // v3.16.0 — Registry browser\n const [registryOpen, setRegistryOpen] = useState(false);\n const [registry, setRegistry] = useState<{\n source: string;\n version?: number;\n updatedAt?: string;\n mods: Array<{\n id: string;\n name: string;\n latest?: string;\n description?: string;\n author?: string;\n tags?: string[];\n permissions?: string[];\n homepage?: string;\n installed?: boolean;\n installedVersion?: string | null;\n upgradeAvailable?: string | null;\n }>;\n error?: string;\n } | null>(null);\n const [registryLoading, setRegistryLoading] = useState(false);\n const [installing, setInstalling] = useState<Record<string, boolean>>({});\n\n const loadRegistry = async () => {\n setRegistryLoading(true);\n try {\n const r = await api.get<{\n registry?: { source?: string; version?: number; updatedAt?: string };\n mods?: Array<{\n id: string;\n name: string;\n latest?: string;\n description?: string;\n author?: string;\n tags?: string[];\n permissions?: string[];\n homepage?: string;\n installed?: boolean;\n installedVersion?: string | null;\n upgradeAvailable?: string | null;\n }>;\n }>('/mods/registry');\n setRegistry({\n source: r.registry?.source || '',\n version: r.registry?.version,\n updatedAt: r.registry?.updatedAt,\n mods: r.mods || [],\n });\n } catch (err) {\n setRegistry({ source: '', mods: [], error: (err as Error).message });\n } finally {\n setRegistryLoading(false);\n }\n };\n\n const onInstallFromRegistry = async (id: string) => {\n setInstalling((cur) => ({ ...cur, [id]: true }));\n try {\n const m = await api.post<Mod>('/mods', { id });\n setMods((cur) => [...cur.filter((x) => x.id !== m.id), m]);\n toast.success(`Mod \"${m.id}\" installed from registry.`);\n await refreshSnapshot();\n } catch (err) {\n toast.error(`Install failed: ${(err as Error).message}`);\n } finally {\n setInstalling((cur) => ({ ...cur, [id]: false }));\n }\n };\n\n // v3.20.5 — Upgrade handler. Calls the dedicated `/mods/:id/upgrade`\n // endpoint (the install endpoint refuses if the mod is already on disk).\n // Reports oldVersion → newVersion in the success toast.\n const onUpgradeFromRegistry = async (id: string, backup = false) => {\n setInstalling((cur) => ({ ...cur, [id]: true }));\n try {\n const r = await api.post<{\n ok: boolean;\n from: string;\n to: string;\n backupPath: string | null;\n mod: Mod;\n }>(`/mods/${encodeURIComponent(id)}/upgrade`, { backup });\n setMods((cur) => [...cur.filter((x) => x.id !== r.mod.id), r.mod]);\n const backupNote = r.backupPath ? ` (backup at ${r.backupPath})` : '';\n toast.success(`Mod \"${id}\" upgraded v${r.from} → v${r.to}${backupNote}.`);\n await refreshSnapshot();\n } catch (err) {\n toast.error(`Upgrade failed: ${(err as Error).message}`);\n } finally {\n setInstalling((cur) => ({ ...cur, [id]: false }));\n }\n };\n\n const reload = async () => {\n try {\n // Always pull fresh from the server. snapshot is fine for\n // optimistic initial render, but a fresh fetch makes the page\n // behave correctly even if the snapshot was empty or stale.\n const r = await api.get<{ mods: Mod[] }>('/mods');\n setMods(r.mods || []);\n try {\n const v = await api.get<{ views: ModView[] }>('/mods/views');\n setModViews(v.views || []);\n } catch {\n setModViews([]);\n }\n } catch (err) {\n toast.error(`Mods load failed: ${(err as Error).message}`);\n } finally {\n // v3.3.0 — Always clear loading even on failure so the empty\n // state can render. Without this, a network blip would leave\n // the user staring at a spinner forever.\n setLoading(false);\n }\n };\n\n // Initial load — runs once on mount.\n useEffect(() => {\n reload();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Re-sync from snapshot when it changes (other tabs may have\n // triggered a refreshSnapshot that updated the mod list).\n useEffect(() => {\n if (Array.isArray(snapshot.mods) && snapshot.mods !== mods) {\n setMods(snapshot.mods);\n }\n // eslint-disable-next-line react-hooks-exhaustive-deps\n }, [snapshot.mods]);\n\n const onInstall = () => {\n let pathEl: HTMLInputElement | null = null;\n modal.open({\n title: 'Install mod',\n children: (\n <div>\n <p className=\"muted\">\n Provide the absolute path to a mod folder (one that contains\n a <code>mod.json</code>). The folder will be copied to\n {' '}<code>~/.config/bizar/mods/<id>/</code>.\n </p>\n <label className=\"field-label\">Path</label>\n <input\n ref={(el) => (pathEl = el)}\n className=\"input\"\n type=\"text\"\n placeholder=\"/path/to/my-mod\"\n autoFocus\n />\n </div>\n ),\n footer: (\n <div className=\"modal-footer-actions\">\n <Button variant=\"ghost\" onClick={() => modal.close()}>Cancel</Button>\n <Button\n variant=\"primary\"\n onClick={async () => {\n const path = (pathEl?.value || '').trim();\n if (!path) {\n toast.warning('Path is required.');\n return;\n }\n try {\n const m = await api.post<Mod>('/mods', { path });\n setMods((cur) => [...cur, m]);\n toast.success(`Mod \"${m.id}\" installed.`);\n modal.close();\n await refreshSnapshot();\n } catch (err) {\n toast.error(`Install failed: ${(err as Error).message}`);\n }\n }}\n >\n Install\n </Button>\n </div>\n ),\n });\n };\n\n const onUninstall = async (id: string) => {\n if (!confirm(`Uninstall mod \"${id}\"? This removes the folder from ~/.config/bizar/mods/.`)) return;\n try {\n await api.del(`/mods/${encodeURIComponent(id)}`);\n setMods((cur) => cur.filter((m) => m.id !== id));\n if (selected === id) setSelected(null);\n toast.success('Mod uninstalled.');\n } catch (err) {\n toast.error(`Uninstall failed: ${(err as Error).message}`);\n }\n };\n\n const onToggleEnabled = async (mod: Mod) => {\n try {\n const next = await api.put<Mod>(`/mods/${encodeURIComponent(mod.id)}`, { enabled: !mod.enabled });\n setMods((cur) => cur.map((m) => (m.id === mod.id ? next : m)));\n toast.success(`Mod ${next.enabled ? 'enabled' : 'disabled'}.`);\n } catch (err) {\n toast.error(`Toggle failed: ${(err as Error).message}`);\n }\n };\n\n const sel = mods.find((m) => m.id === selected) || null;\n\n if (loading) {\n return (\n <div className=\"view-loading\">\n <Spinner size=\"lg\" />\n </div>\n );\n }\n\n return (\n <div className=\"view view-mods\">\n <header className=\"view-header\">\n <div className=\"view-header-text\">\n <h2 className=\"view-title\">\n <Puzzle size={18} /> Mods ({mods.length})\n </h2>\n <p className=\"view-subtitle\">\n Extensions installed in <code>~/.config/bizar/mods/</code>.\n Mods can add agents, commands, routes, and views.\n </p>\n </div>\n <div className=\"view-actions\">\n <Button variant=\"secondary\" size=\"sm\" onClick={reload}>\n <RefreshCw size={14} /> Refresh\n </Button>\n <Button variant=\"primary\" size=\"sm\" onClick={onInstall}>\n <Plus size={14} /> Install mod\n </Button>\n </div>\n </header>\n\n {mods.length === 0 ? (\n <EmptyState\n icon={<Puzzle size={32} />}\n title=\"No mods installed\"\n message=\"Mods are folders with a mod.json. Install one to extend Bizar with custom agents, commands, and views.\"\n />\n ) : (\n <div className=\"mods-layout\">\n <div className=\"mods-list\">\n {mods.map((m) => (\n <div\n key={m.id}\n className={cn('mod-list-item', selected === m.id && 'mod-list-item-active')}\n onClick={() => setSelected(m.id)}\n >\n <div className=\"mod-list-item-head\">\n <div>\n <div className=\"mod-list-item-name\">{m.name}</div>\n <div className=\"mod-list-item-meta\">v{m.version} · {m.type} · {m.author}</div>\n </div>\n <div className=\"mod-list-item-actions\" onClick={(e) => e.stopPropagation()}>\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label=\"Toggle enabled\"\n title={m.enabled ? 'Disable' : 'Enable'}\n onClick={() => onToggleEnabled(m)}\n >\n <Power size={12} />\n </button>\n <button\n type=\"button\"\n className=\"icon-btn icon-btn-danger\"\n aria-label=\"Uninstall\"\n title=\"Uninstall\"\n onClick={() => onUninstall(m.id)}\n >\n <Trash2 size={12} />\n </button>\n </div>\n </div>\n <div className=\"mod-list-item-desc ellipsis-2\" title={m.description}>\n {m.description}\n </div>\n <div className=\"mod-list-item-status\">\n <span className={`mod-mini-pill ${m.enabled ? 'mod-mini-pill-on' : 'mod-mini-pill-off'}`}>\n {m.enabled ? 'enabled' : 'disabled'}\n </span>\n </div>\n </div>\n ))}\n </div>\n {sel && <ModDetails mod={sel} />}\n </div>\n )}\n\n {/* v3.16.0 — Registry browser */}\n <Card className=\"mods-registry-card\">\n <div className=\"mods-registry-head\" onClick={() => {\n if (!registry && !registryLoading) loadRegistry();\n setRegistryOpen((v) => !v);\n }}>\n <Globe size={14} />\n <span className=\"mods-registry-title\">Mod registry</span>\n <span className=\"muted\" style={{ fontSize: 11 }}>\n {registry?.mods ? `${registry.mods.length} available` : 'click to browse'}\n </span>\n <span className=\"mods-registry-spacer\" />\n {registryOpen ? <ChevronDown size={14} /> : <ChevronRight size={14} />}\n </div>\n {registryOpen && (\n <div className=\"mods-registry-body\">\n {registryLoading ? (\n <div className=\"muted\" style={{ padding: 12, fontSize: 12 }}>Loading registry…</div>\n ) : registry?.error ? (\n <div className=\"mods-registry-error\">\n <ShieldCheck size={12} /> Could not load registry: {registry.error}\n </div>\n ) : !registry || registry.mods.length === 0 ? (\n <div className=\"muted\" style={{ padding: 12, fontSize: 12 }}>\n No mods listed in the registry yet.\n </div>\n ) : (\n <>\n {registry.source && (\n <div className=\"muted\" style={{ fontSize: 11, marginBottom: 8 }}>\n Source: <code>{registry.source}</code>\n </div>\n )}\n <div className=\"mods-registry-grid\">\n {registry.mods.map((rm) => {\n const installed = mods.some((m) => m.id === rm.id);\n const isInstalling = !!installing[rm.id];\n return (\n <div key={rm.id} className=\"mod-registry-card\">\n <div className=\"mod-registry-card-head\">\n <div className=\"mod-registry-card-name\">{rm.name}</div>\n {rm.latest && (\n <span className={cn('mod-registry-version', rm.upgradeAvailable && 'mod-registry-version-upgrade')}>\n v{rm.latest}{rm.upgradeAvailable ? ' ↑' : ''}\n </span>\n )}\n </div>\n {rm.description && (\n <div className=\"mod-registry-card-desc\">{rm.description}</div>\n )}\n <div className=\"mod-registry-card-meta\">\n {rm.author && <span className=\"muted\">by {rm.author}</span>}\n {rm.homepage && (\n <a href={rm.homepage} target=\"_blank\" rel=\"noopener noreferrer\" className=\"mod-registry-link\">\n homepage\n </a>\n )}\n </div>\n {(rm.permissions || []).length > 0 && (\n <div className=\"mod-registry-perms\">\n <ShieldCheck size={10} />\n {(rm.permissions || []).slice(0, 4).map((p) => (\n <span key={p} className=\"mod-registry-perm\">{p}</span>\n ))}\n {(rm.permissions || []).length > 4 && (\n <span className=\"mod-registry-perm-more\">+{rm.permissions!.length - 4}</span>\n )}\n </div>\n )}\n <div className=\"mod-registry-card-actions\">\n {!installed && (\n <Button\n variant=\"primary\"\n size=\"sm\"\n disabled={isInstalling}\n onClick={() => onInstallFromRegistry(rm.id)}\n title=\"Install from registry\"\n >\n {isInstalling ? <Spinner size=\"sm\" /> : (<><Download size={12} /> Install</>)}\n </Button>\n )}\n {installed && rm.upgradeAvailable && (\n <Button\n variant=\"primary\"\n size=\"sm\"\n disabled={isInstalling}\n onClick={() => onUpgradeFromRegistry(rm.id)}\n title={`Upgrade from v${rm.installedVersion || '?'} to v${rm.upgradeAvailable}`}\n >\n {isInstalling ? <Spinner size=\"sm\" /> : (<><Download size={12} /> Upgrade to v{rm.upgradeAvailable}</>)}\n </Button>\n )}\n {installed && !rm.upgradeAvailable && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n disabled\n title={`Installed v${rm.installedVersion || '?'}`}\n >\n Installed v{rm.installedVersion || '?'}\n </Button>\n )}\n </div>\n </div>\n );\n })}\n </div>\n </>\n )}\n </div>\n )}\n </Card>\n\n {/* v3.20.3 — Mod views now appear in the sidebar nav as first-class\n tabs (handled by App.tsx), so this section is a hint pointing\n users to the sidebar. */}\n {modViews.length > 0 && (\n <Card className=\"mod-views-hint\">\n <CardTitle><Globe size={14} /> Mod views</CardTitle>\n <CardMeta>\n {modViews.length} mod-supplied view{modViews.length === 1 ? '' : 's'} are now available in the sidebar navigation.\n Look for the <strong>Mods</strong> section at the bottom of the sidebar.\n </CardMeta>\n </Card>\n )}\n\n {/* Iframe panel for mod web views */}\n {iframeUrl && (\n <div className=\"mod-iframe-panel\">\n <div className=\"mod-iframe-header\">\n <span>Mod view — <a href={iframeUrl} target=\"_blank\" rel=\"noreferrer\">{iframeUrl}</a></span>\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label=\"Close iframe\"\n onClick={() => setIframeUrl(null)}\n >\n <X size={14} />\n </button>\n </div>\n <iframe\n src={iframeUrl}\n className=\"mod-iframe\"\n title=\"Mod view\"\n sandbox=\"allow-scripts allow-same-origin allow-forms allow-popups\"\n />\n </div>\n )}\n </div>\n );\n}\n\nfunction ModDetails({ mod }: { mod: Mod }) {\n const toast = useToast();\n const [instructions, setInstructions] = useState<{\n modId: string;\n modName: string;\n total: number;\n agents: Array<{ filename: string; path: string; fullPath: string; content: string | null }>;\n commands: Array<{ filename: string; path: string; fullPath: string; content: string | null }>;\n skills: Array<{ name: string; fullPath: string; content: string | null }>;\n } | null>(null);\n const [instructionsLoading, setInstructionsLoading] = useState(false);\n const [instructionsOpen, setInstructionsOpen] = useState(false);\n const [expandedFile, setExpandedFile] = useState<string | null>(null);\n\n const loadInstructions = async () => {\n setInstructionsLoading(true);\n try {\n const r = await api.get<typeof instructions>(`/mods/${mod.id}/instructions`);\n setInstructions(r);\n setInstructionsOpen(true);\n } catch (err) {\n toast.error(`Failed to load instructions: ${(err as Error).message}`);\n } finally {\n setInstructionsLoading(false);\n }\n };\n\n const onReinstallInstructions = async () => {\n try {\n const r = await api.post<{ ok: boolean; counts: { agents: number; commands: number; skills: number; instructions: number } }>(\n `/mods/${mod.id}/instructions/reinstall`,\n {},\n );\n toast.success(`Reinstalled: ${r.counts.agents} agents, ${r.counts.commands} commands, ${r.counts.skills} skills, ${r.counts.instructions} instructions.`);\n await loadInstructions();\n } catch (err) {\n toast.error(`Reinstall failed: ${(err as Error).message}`);\n }\n };\n\n return (\n <Card className=\"mod-details\">\n <CardTitle><FileText size={14} /> Mod details — {mod.name}</CardTitle>\n <CardMeta>\n <code>{mod.path}</code>\n </CardMeta>\n <dl className=\"env-table\">\n <dt>ID</dt>\n <dd className=\"mono\">{mod.id}</dd>\n <dt>Version</dt>\n <dd className=\"mono\">{mod.version}</dd>\n <dt>Type</dt>\n <dd className=\"mono\">{mod.type}</dd>\n <dt>Author</dt>\n <dd className=\"mono\">{mod.author || '—'}</dd>\n <dt>Bizar</dt>\n <dd className=\"mono\">{mod.bizar || '*'}</dd>\n <dt>Enabled</dt>\n <dd>{mod.enabled ? 'yes' : 'no'}</dd>\n <dt>Permissions</dt>\n <dd>\n {(mod.permissions || []).map((p) => (\n <span key={p} className=\"tag\">{p}</span>\n ))}\n {(mod.permissions || []).length === 0 && <span className=\"muted\">(none)</span>}\n </dd>\n </dl>\n <div className=\"mod-files\">\n <div className=\"muted\">Files</div>\n <ul>\n {(mod.files || []).map((f) => (\n <li key={f.path}>\n <span className=\"mod-file-cat\">{f.category}</span>\n <span className=\"mono\">{f.path}</span>\n </li>\n ))}\n </ul>\n </div>\n\n {/* v3.20 — Installed instructions (agents / commands / skills) */}\n <div className=\"mod-instructions\">\n <div className=\"mod-instructions-head\" onClick={() => {\n if (!instructions && !instructionsLoading) loadInstructions();\n setInstructionsOpen((v) => !v);\n }}>\n <FileCode size={14} />\n <span>Installed instructions</span>\n <span className=\"muted\" style={{ fontSize: 11 }}>\n {instructions ? `${instructions.total} files` : 'click to view'}\n </span>\n <span className=\"mod-instructions-spacer\" />\n {instructionsOpen ? <ChevronDown size={14} /> : <ChevronRight size={14} />}\n </div>\n {instructionsOpen && instructions && (\n <div className=\"mod-instructions-body\">\n {instructions.agents.length > 0 && (\n <div className=\"mod-instructions-section\">\n <div className=\"mod-instructions-section-title\">\n <User size={11} /> Agents ({instructions.agents.length})\n </div>\n {instructions.agents.map((f) => (\n <div key={f.filename} className=\"mod-instructions-file\">\n <div\n className=\"mod-instructions-file-head\"\n onClick={() => setExpandedFile((cur) => cur === f.filename ? null : f.filename)}\n >\n <span className=\"mono\">{f.filename}</span>\n <span className=\"muted\" style={{ fontSize: 10 }}>\n installed at {f.fullPath}\n </span>\n </div>\n {expandedFile === f.filename && (\n <pre className=\"mod-instructions-content\">\n {f.content || <em className=\"muted\">(file missing on disk)</em>}\n </pre>\n )}\n </div>\n ))}\n </div>\n )}\n {instructions.commands.length > 0 && (\n <div className=\"mod-instructions-section\">\n <div className=\"mod-instructions-section-title\">\n <Terminal size={11} /> Commands ({instructions.commands.length})\n </div>\n {instructions.commands.map((f) => (\n <div key={f.filename} className=\"mod-instructions-file\">\n <div\n className=\"mod-instructions-file-head\"\n onClick={() => setExpandedFile((cur) => cur === f.filename ? null : f.filename)}\n >\n <span className=\"mono\">{f.filename}</span>\n <span className=\"muted\" style={{ fontSize: 10 }}>\n installed at {f.fullPath}\n </span>\n </div>\n {expandedFile === f.filename && (\n <pre className=\"mod-instructions-content\">\n {f.content || <em className=\"muted\">(file missing on disk)</em>}\n </pre>\n )}\n </div>\n ))}\n </div>\n )}\n {instructions.skills.length > 0 && (\n <div className=\"mod-instructions-section\">\n <div className=\"mod-instructions-section-title\">\n <BookOpen size={11} /> Skills ({instructions.skills.length})\n </div>\n {instructions.skills.map((s) => (\n <div key={s.name} className=\"mod-instructions-file\">\n <div\n className=\"mod-instructions-file-head\"\n onClick={() => setExpandedFile((cur) => cur === s.name ? null : s.name)}\n >\n <span className=\"mono\">{s.name}</span>\n <span className=\"muted\" style={{ fontSize: 10 }}>\n installed at {s.fullPath}\n </span>\n </div>\n {expandedFile === s.name && (\n <pre className=\"mod-instructions-content\">\n {s.content || <em className=\"muted\">(file missing on disk)</em>}\n </pre>\n )}\n </div>\n ))}\n </div>\n )}\n {instructions.total === 0 && (\n <div className=\"muted\" style={{ padding: 8, fontSize: 12 }}>\n This mod did not install any instruction files. Mods install instructions by shipping a top-level <code>INSTRUCTIONS.md</code>, an <code>agents/</code> directory, a <code>commands/</code> directory, or a <code>skills/</code> directory.\n </div>\n )}\n <div className=\"mod-instructions-actions\">\n <Button variant=\"ghost\" size=\"sm\" onClick={onReinstallInstructions}>\n <RefreshCw size={11} /> Reinstall from mod folder\n </Button>\n </div>\n </div>\n )}\n </div>\n </Card>\n );\n}\n","// src/views/ModView.tsx — render an installed mod's view (iframe or TSX tab).\n//\n// Mounted as a top-level tab in App.tsx when a mod contributes a view via\n// `entry.view` or `web/index.html`. Mods become first-class nav items\n// alongside Overview, Chat, Mods, etc.\n\nimport { Suspense, lazy, useEffect, useState } from 'react';\nimport { Card, CardTitle, CardMeta } from '../components/Card';\nimport { EmptyState } from '../components/EmptyState';\nimport { Button } from '../components/Button';\nimport { Spinner } from '../components/Spinner';\nimport { ExternalLink, Globe, LayoutTemplate, RefreshCw, AlertTriangle } from 'lucide-react';\nimport { api } from '../lib/api';\nimport { useToast } from '../components/Toast';\n\nexport type ModView = {\n id: string;\n modId: string;\n kind: 'iframe' | 'tab';\n label: string;\n description?: string;\n path?: string;\n icon?: string;\n component?: string | null;\n};\n\ntype Props = {\n /** Mod view id, e.g. 'graphify:web'. */\n viewId: string;\n /** Force a refresh of the iframe key — bumped when the user clicks Reload. */\n reloadKey?: number;\n /** Currently active tab id — kept on the Props surface so the parent\n * (App.tsx) doesn't have to know which props the mod view consumes. */\n activeTab?: string;\n setActiveTab: (id: string) => void;\n};\n\nexport function ModView({ viewId, reloadKey, setActiveTab }: Props) {\n const toast = useToast();\n const [view, setView] = useState<ModView | null>(null);\n const [loading, setLoading] = useState(true);\n const [iframeReload, setIframeReload] = useState(0);\n\n useEffect(() => {\n let cancelled = false;\n (async () => {\n try {\n const r = await api.get<{ views: ModView[] }>('/mods/views');\n if (cancelled) return;\n const found = (r.views || []).find((v) => v.id === viewId);\n setView(found || null);\n } catch (err) {\n toast.error(`Failed to load mod view: ${(err as Error).message}`);\n } finally {\n if (!cancelled) setLoading(false);\n }\n })();\n return () => { cancelled = true; };\n }, [viewId, toast]);\n\n if (loading) {\n return <EmptyState title=\"Loading mod view…\" />;\n }\n\n if (!view) {\n return (\n <EmptyState\n title=\"Mod view not found\"\n message={`No view with id \"${viewId}\" is currently installed.`}\n action={<Button onClick={() => setActiveTab('mods')} variant=\"primary\" size=\"sm\">\n Open Mods\n </Button>}\n />\n );\n }\n\n // Iframe view: embed the mod's web/index.html in the dashboard.\n if (view.kind === 'iframe') {\n const src = `/api/mods/${view.modId}/web/index.html?t=${iframeReload + (reloadKey || 0)}`;\n return (\n <div className=\"mod-view-iframe-pane\">\n <div className=\"mod-view-iframe-header\">\n <span className=\"mod-view-iframe-label\">\n <Globe size={14} />\n {view.label}\n <span className=\"muted\" style={{ fontSize: 11, fontWeight: 400 }}>by {view.modId}</span>\n </span>\n <div className=\"mod-view-iframe-actions\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setIframeReload((n) => n + 1)}\n title=\"Reload this view\"\n >\n <RefreshCw size={11} /> Reload\n </Button>\n <a\n href={src}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"icon-btn\"\n title=\"Open in new tab\"\n >\n <ExternalLink size={12} />\n </a>\n </div>\n </div>\n <iframe\n key={iframeReload + (reloadKey || 0)}\n src={src}\n className=\"mod-view-iframe\"\n title={view.label}\n />\n </div>\n );\n }\n\n // v3.20.5 — Tab view (React component shipped with the mod). The\n // component is dynamically imported from /api/mods/<id>/views/<file>.\n // Mods ship a pre-built ES module (default export = React component).\n // If the registry declared a component path, we lazy-load it.\n if (view.component) {\n // Capture the narrowed values into locals so the lazy() closure\n // doesn't have to re-check nullability through `view`.\n const componentPath: string = view.component;\n const modId: string = view.modId;\n const ModComponent = lazy(() =>\n import(\n /* @vite-ignore */\n `/api/mods/${encodeURIComponent(modId)}/views/${encodeURIComponent(componentPath)}`\n ).then((m) => ({ default: m.default ?? (() => null) })),\n );\n return (\n <div className=\"mod-view-tab-pane\">\n <div className=\"mod-view-iframe-header\">\n <span className=\"mod-view-iframe-label\">\n <LayoutTemplate size={14} />\n {view.label}\n <span className=\"muted\" style={{ fontSize: 11, fontWeight: 400 }}>by {view.modId}</span>\n </span>\n </div>\n <div className=\"mod-view-tab-body\">\n <ErrorBoundary modId={view.modId} component={view.component}>\n <Suspense fallback={<div style={{ padding: 24 }}><Spinner size=\"md\" /> <span className=\"muted\">Loading mod view…</span></div>}>\n <ModComponent />\n </Suspense>\n </ErrorBoundary>\n </div>\n </div>\n );\n }\n\n // Tab kind with no component path — show a placeholder.\n return (\n <Card>\n <CardTitle>\n <LayoutTemplate size={14} /> {view.label}\n </CardTitle>\n <CardMeta>by {view.modId}</CardMeta>\n {view.description && <p className=\"muted\" style={{ marginTop: 8 }}>{view.description}</p>}\n <p className=\"muted\" style={{ fontSize: 12, marginTop: 12 }}>\n This mod declared a tab view but did not provide a component path in views/registry.json.\n Add a <code>component</code> field (e.g. <code>\"MyView.js\"</code>) and ship the file under <code>views/</code>.\n </p>\n <div style={{ marginTop: 12 }}>\n <Button variant=\"secondary\" size=\"sm\" onClick={() => setActiveTab('mods')}>\n Open Mods page\n </Button>\n </div>\n </Card>\n );\n}\n\n/**\n * Minimal error boundary for dynamically imported mod views. Catches\n * a failure to load the module (404, syntax error in the mod's code,\n * React.render-time throw) and renders a clean fallback instead of\n * crashing the dashboard shell.\n */\nimport { Component as ReactComponent, type ReactNode } from 'react';\n\nclass ErrorBoundary extends ReactComponent<\n { children: ReactNode; modId: string; component: string },\n { error: Error | null }\n> {\n state = { error: null as Error | null };\n static getDerivedStateFromError(error: Error) {\n return { error };\n }\n override componentDidCatch() {\n /* swallow — error surfaced via state */\n }\n override render() {\n if (this.state.error) {\n return (\n <div className=\"mod-view-error\">\n <AlertTriangle size={16} />\n <strong>Failed to render mod view</strong>\n <div className=\"muted\" style={{ fontSize: 12, marginTop: 6 }}>\n {this.props.modId} → {this.props.component}: {this.state.error.message}\n </div>\n </div>\n );\n }\n return this.props.children;\n }\n}\n","// src/views/Schedules.tsx — list, create, edit, run, delete schedules for the active project.\n//\n// v3.9.0 — overhauled with structured DOW/time/TZ pickers, a reusable\n// ScheduleEditorModal that handles both create and edit, a human-readable\n// schedule label on every card, and a timezone-aware next-run display.\nimport { useEffect, useMemo, useState } from 'react';\nimport {\n Clock,\n Plus,\n PlayCircle,\n Pencil,\n Trash2,\n RefreshCw,\n History,\n ChevronDown,\n} from 'lucide-react';\nimport { Card, CardTitle, CardMeta } from '../components/Card';\nimport { Button } from '../components/Button';\nimport { EmptyState } from '../components/EmptyState';\nimport { Spinner } from '../components/Spinner';\nimport { useToast } from '../components/Toast';\nimport { useModal } from '../components/Modal';\nimport { api } from '../lib/api';\nimport { formatRelative } from '../lib/utils';\nimport type { Schedule, Settings, Snapshot } from '../lib/types';\n\ntype Props = {\n snapshot: Snapshot;\n settings: Settings;\n activeTab: string;\n setActiveTab: (id: string) => void;\n refreshSnapshot: () => Promise<void>;\n};\n\nconst TYPES = ['interval', 'cron', 'once'] as const;\nconst ACTIONS = ['command', 'agent', 'webhook'] as const;\n\n// v3.9.0 — Curated IANA timezone list. \"Other…\" lets the operator type\n// any zone croner accepts (the backend passes the string through).\nconst TIMEZONES: Array<{ value: string; label: string }> = [\n { value: 'UTC', label: 'UTC' },\n { value: 'America/New_York', label: 'America/New_York (ET)' },\n { value: 'America/Los_Angeles', label: 'America/Los_Angeles (PT)' },\n { value: 'America/Chicago', label: 'America/Chicago (CT)' },\n { value: 'Europe/London', label: 'Europe/London (UK)' },\n { value: 'Europe/Berlin', label: 'Europe/Berlin (CET)' },\n { value: 'Asia/Tokyo', label: 'Asia/Tokyo (JST)' },\n];\n\nconst MINUTE_OPTIONS = Array.from({ length: 12 }, (_, i) => i * 5); // 0,5,10,…55\nconst HOUR_OPTIONS = Array.from({ length: 24 }, (_, h) => ({\n value: h,\n label: h === 0 ? '12 AM' : h < 12 ? `${h} AM` : h === 12 ? '12 PM' : `${h - 12} PM`,\n}));\nconst DOW_OPTIONS: Array<{ value: string; label: string }> = [\n { value: '*', label: 'Every day' },\n { value: '0', label: 'Sunday' },\n { value: '1', label: 'Monday' },\n { value: '2', label: 'Tuesday' },\n { value: '3', label: 'Wednesday' },\n { value: '4', label: 'Thursday' },\n { value: '5', label: 'Friday' },\n { value: '6', label: 'Saturday' },\n];\n\nconst INTERVAL_UNITS: Array<{ value: string; label: string }> = [\n { value: 's', label: 'seconds' },\n { value: 'm', label: 'minutes' },\n { value: 'h', label: 'hours' },\n { value: 'd', label: 'days' },\n];\n\n/** Best-effort cron parser — used to pre-populate the structured form\n * when editing a schedule the user originally saved with raw cron text. */\nfunction parseCronFields(expr: string): { minute: number; hour: number; dow: string } | null {\n if (typeof expr !== 'string') return null;\n const parts = expr.trim().split(/\\s+/);\n if (parts.length !== 5) return null;\n const [m, h, , , dow] = parts;\n // We only pre-populate when every field is a literal — wildcards and\n // ranges (other than `*`) leave the form blank rather than guess.\n const minNum = parseInt(m, 10);\n const hourNum = parseInt(h, 10);\n if (!Number.isFinite(minNum) || !Number.isFinite(hourNum)) return null;\n if (m !== String(minNum) || h !== String(hourNum)) return null;\n const dowClean = dow === '*' ? '*' : parseInt(dow, 10);\n if (dowClean === null || (dow !== '*' && !Number.isFinite(dowClean))) return null;\n return { minute: minNum, hour: hourNum, dow: dow === '*' ? '*' : String(dowClean) };\n}\n\nfunction parseIntervalParts(s: string): { n: number; unit: string } | null {\n if (typeof s !== 'string') return null;\n const m = /^(\\d+)\\s*([smhd])$/i.exec(s.trim());\n if (!m) return null;\n return { n: parseInt(m[1], 10), unit: m[2].toLowerCase() };\n}\n\ntype EditorState = {\n name: string;\n type: 'cron' | 'interval' | 'once';\n cronMinute: number;\n cronHour: number;\n cronDow: string;\n showAdvanced: boolean;\n rawCron: string;\n intervalN: number;\n intervalUnit: string;\n onceAt: string; // datetime-local string\n timezone: string;\n customTimezone: string;\n actionType: 'command' | 'agent' | 'webhook';\n actionTarget: string;\n actionPrompt: string;\n skipIfBudgetLow: boolean;\n maxConcurrent: number;\n enabled: boolean;\n humanLabel: string;\n};\n\nfunction buildInitialState(initial?: Schedule): EditorState {\n if (!initial) {\n return {\n name: '',\n type: 'cron',\n cronMinute: 0,\n cronHour: 13,\n cronDow: '0',\n showAdvanced: false,\n rawCron: '0 13 * * 0',\n intervalN: 30,\n intervalUnit: 'm',\n onceAt: '',\n timezone: 'UTC',\n customTimezone: '',\n actionType: 'agent',\n actionTarget: '',\n actionPrompt: '',\n skipIfBudgetLow: false,\n maxConcurrent: 6,\n enabled: true,\n humanLabel: '',\n };\n }\n const parsed = initial.type === 'cron' ? parseCronFields(initial.schedule) : null;\n const parsedInterval = initial.type === 'interval' ? parseIntervalParts(initial.schedule) : null;\n const tz = initial.timezone || 'UTC';\n const tzKnown = TIMEZONES.some((t) => t.value === tz);\n return {\n name: initial.name || '',\n type: initial.type,\n cronMinute: parsed?.minute ?? 0,\n cronHour: parsed?.hour ?? 9,\n cronDow: parsed?.dow ?? '*',\n showAdvanced: !parsed,\n rawCron: initial.schedule,\n intervalN: parsedInterval?.n ?? 30,\n intervalUnit: parsedInterval?.unit ?? 'm',\n onceAt: initial.type === 'once' ? toDatetimeLocal(initial.schedule) : '',\n timezone: tzKnown ? tz : 'Other…',\n customTimezone: tzKnown ? '' : tz,\n actionType: initial.action.type,\n actionTarget: initial.action.target || '',\n actionPrompt: initial.action.prompt || '',\n skipIfBudgetLow: !!initial.budgetCheck?.skipIfBudgetLow,\n maxConcurrent: Number.isFinite(initial.budgetCheck?.maxConcurrent)\n ? initial.budgetCheck!.maxConcurrent!\n : 6,\n enabled: initial.enabled !== false,\n humanLabel: '',\n };\n}\n\nfunction toDatetimeLocal(iso: string): string {\n if (!iso) return '';\n try {\n const d = new Date(iso);\n if (Number.isNaN(d.getTime())) return '';\n // datetime-local needs YYYY-MM-DDTHH:mm in *local* time.\n const pad = (n: number) => String(n).padStart(2, '0');\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;\n } catch {\n return '';\n }\n}\n\n/** Compose the cron / interval / once schedule string + a human label. */\nfunction composeSchedule(s: EditorState): { schedule: string; humanLabel: string } {\n if (s.type === 'cron') {\n if (s.showAdvanced) {\n return { schedule: s.rawCron.trim(), humanLabel: s.humanLabel || s.rawCron.trim() };\n }\n const cron = `${s.cronMinute} ${s.cronHour} * * ${s.cronDow}`;\n const dowName = DOW_OPTIONS.find((d) => d.value === s.cronDow)?.label || '';\n const hourLabel = HOUR_OPTIONS.find((h) => h.value === s.cronHour)?.label || `${s.cronHour}`;\n const minute = String(s.cronMinute).padStart(2, '0');\n const human =\n dowName === 'Every day'\n ? `Every day at ${hourLabel.replace(' ', '')} (min ${minute})`\n : `Every ${dowName} at ${hourLabel.replace(' ', '')} (min ${minute})`;\n return { schedule: cron, humanLabel: s.humanLabel || human };\n }\n if (s.type === 'interval') {\n const unit = INTERVAL_UNITS.find((u) => u.value === s.intervalUnit)?.label || s.intervalUnit;\n const schedule = `${s.intervalN}${s.intervalUnit}`;\n return {\n schedule,\n humanLabel: s.humanLabel || `Every ${s.intervalN} ${unit}`,\n };\n }\n // once\n if (!s.onceAt) return { schedule: '', humanLabel: s.humanLabel || '' };\n const iso = new Date(s.onceAt).toISOString();\n return {\n schedule: iso,\n humanLabel: s.humanLabel || new Date(s.onceAt).toLocaleString(),\n };\n}\n\nexport function Schedules({ snapshot, refreshSnapshot }: Props) {\n const toast = useToast();\n const modal = useModal();\n const [schedules, setSchedules] = useState<Schedule[]>(snapshot.schedules || []);\n const [loading, setLoading] = useState(!snapshot.schedules);\n\n const reload = async () => {\n try {\n const r = await api.get<{ schedules: Schedule[]; projectId: string | null }>(\n '/projects/active/schedules',\n );\n setSchedules(r.schedules || []);\n } catch (err) {\n toast.error(`Schedules load failed: ${(err as Error).message}`);\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n if (snapshot.schedules?.length || snapshot.schedules) {\n setSchedules(snapshot.schedules || []);\n setLoading(false);\n return;\n }\n reload();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [snapshot.schedules]);\n\n const openEditor = (initial?: Schedule) => {\n modal.open({\n title: initial ? `Edit schedule: ${initial.name}` : 'New schedule',\n width: 640,\n children: (\n <ScheduleEditorModal\n initial={initial}\n onClose={modal.close}\n onSubmitted={async (saved) => {\n setSchedules((cur) => {\n const idx = cur.findIndex((s) => s.id === saved.id);\n if (idx === -1) return [...cur, saved];\n const copy = cur.slice();\n copy[idx] = saved;\n return copy;\n });\n toast.success(initial ? 'Schedule updated.' : 'Schedule created.');\n modal.close();\n await refreshSnapshot();\n }}\n onError={(msg) => toast.error(msg)}\n />\n ),\n });\n };\n\n const onRun = async (s: Schedule) => {\n try {\n const r = await api.post<{ ok: boolean; schedule: Schedule; runResult: { error?: string; stdout?: string } }>(\n `/schedules/${encodeURIComponent(s.id)}/run`,\n );\n toast.success(r.ok ? 'Schedule ran.' : `Run failed: ${r.runResult?.error || 'unknown'}`);\n await reload();\n } catch (err) {\n toast.error(`Run failed: ${(err as Error).message}`);\n }\n };\n\n const onDelete = async (s: Schedule) => {\n if (!confirm(`Delete schedule \"${s.name}\"?`)) return;\n try {\n await api.del(`/schedules/${encodeURIComponent(s.id)}`);\n setSchedules((cur) => cur.filter((x) => x.id !== s.id));\n toast.success('Schedule deleted.');\n } catch (err) {\n toast.error(`Delete failed: ${(err as Error).message}`);\n }\n };\n\n if (loading) {\n return (\n <div className=\"view-loading\"><Spinner size=\"lg\" /></div>\n );\n }\n\n return (\n <div className=\"view view-schedules\">\n <header className=\"view-header\">\n <div className=\"view-header-text\">\n <h2 className=\"view-title\">\n <Clock size={18} /> Schedules ({schedules.length})\n </h2>\n <p className=\"view-subtitle\">\n Recurring tasks for the active project: <strong>{snapshot.activeProject?.name || '(none)'}</strong>.\n Service daemon runs them at the right time.\n </p>\n </div>\n <div className=\"view-actions\">\n <Button variant=\"secondary\" size=\"sm\" onClick={reload}>\n <RefreshCw size={14} /> Refresh\n </Button>\n <Button variant=\"primary\" size=\"sm\" onClick={() => openEditor()}>\n <Plus size={14} /> New schedule\n </Button>\n </div>\n </header>\n\n {schedules.length === 0 ? (\n <EmptyState\n icon={<Clock size={32} />}\n title=\"No schedules\"\n message={\n snapshot.activeProject\n ? 'Add a schedule to run commands, webhooks, or agent tasks on a cron / interval / one-shot basis.'\n : 'Activate a project first to scope schedules.'\n }\n />\n ) : (\n <div className=\"schedule-grid\">\n {schedules.map((s) => (\n <Card key={s.id} className=\"schedule-card\">\n <div className=\"schedule-card-head\">\n <div>\n <CardTitle>{s.name}</CardTitle>\n <CardMeta>\n <code>{s.type}</code> ·{' '}\n <span title={s.schedule}>{humanizeSchedule(s) || s.schedule}</span>\n {s.timezone && s.timezone !== 'UTC' ? <> · <code>{s.timezone}</code></> : null}\n {' · '}\n <span className={s.enabled ? 'status-on' : 'status-neutral'}>\n {s.enabled ? 'enabled' : 'disabled'}\n </span>\n </CardMeta>\n </div>\n <div className=\"schedule-card-actions\">\n <Button variant=\"secondary\" size=\"sm\" onClick={() => openEditor(s)}>\n <Pencil size={12} /> Edit\n </Button>\n <Button variant=\"secondary\" size=\"sm\" onClick={() => onRun(s)}>\n <PlayCircle size={12} /> Run now\n </Button>\n <button\n type=\"button\"\n className=\"icon-btn icon-btn-danger\"\n aria-label=\"Delete\"\n title=\"Delete\"\n onClick={() => onDelete(s)}\n >\n <Trash2 size={12} />\n </button>\n </div>\n </div>\n <div className=\"schedule-card-action\">\n <span className=\"muted\">action:</span>{' '}\n <code>\n {s.action.type} {s.action.target}\n </code>\n {s.action.type === 'agent' && s.action.prompt && (\n <div className=\"schedule-card-prompt\">\n <span className=\"muted\">prompt:</span> {s.action.prompt}\n </div>\n )}\n </div>\n {s.budgetCheck?.skipIfBudgetLow && (\n <div className=\"schedule-card-budget\">\n <span className=\"muted\">budget gate:</span>{' '}\n skip if concurrent ≥ {s.budgetCheck.maxConcurrent ?? 6}\n </div>\n )}\n <div className=\"schedule-card-times\">\n <div>\n <span className=\"muted\">last</span>{' '}\n {s.lastRun ? formatRelative(s.lastRun) : '—'}\n {s.lastResult && (\n <span className={`tag ${resultTagClass(s.lastResult)}`}>{s.lastResult}</span>\n )}\n {s.lastError && (\n <span className=\"muted schedule-card-error\" title={s.lastError}>\n {' '}— {truncate(s.lastError, 80)}\n </span>\n )}\n </div>\n <div>\n <span className=\"muted\">next</span>{' '}\n {s.nextRun ? (\n <span title={new Date(s.nextRun).toISOString()}>\n {formatNextRun(s.nextRun, s.timezone)}\n </span>\n ) : (\n '—'\n )}\n {s.nextRun && (\n <span className=\"muted\"> · {formatRelative(s.nextRun)}</span>\n )}\n </div>\n </div>\n {s.history && s.history.length > 0 && (\n <details className=\"schedule-card-history\">\n <summary>\n <History size={12} /> {s.history.length} run{s.history.length === 1 ? '' : 's'}\n </summary>\n <ul>\n {s.history.slice(-10).reverse().map((h, i) => (\n <li key={i}>\n <span className=\"tabular-nums muted\">{formatRelative(h.ts)}</span>{' '}\n <span className={`tag ${resultTagClass(h.result)}`}>{h.result}</span>\n {h.error && <span className=\"muted\"> — {truncate(h.error, 80)}</span>}\n </li>\n ))}\n </ul>\n </details>\n )}\n </Card>\n ))}\n </div>\n )}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Editor modal */\n/* ------------------------------------------------------------------ */\n\nfunction ScheduleEditorModal({\n initial,\n onClose,\n onSubmitted,\n onError,\n}: {\n initial?: Schedule;\n onClose: () => void;\n onSubmitted: (saved: Schedule) => void | Promise<void>;\n onError: (msg: string) => void;\n}) {\n const [state, setState] = useState<EditorState>(() => buildInitialState(initial));\n const [submitting, setSubmitting] = useState(false);\n const tzSelectValue = useMemo(() => {\n if (TIMEZONES.some((t) => t.value === state.timezone)) return state.timezone;\n return 'Other…';\n }, [state.timezone]);\n\n const update = <K extends keyof EditorState>(key: K, value: EditorState[K]) => {\n setState((cur) => ({ ...cur, [key]: value }));\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n const trimmedName = state.name.trim();\n if (!trimmedName) {\n onError('Name is required.');\n return;\n }\n const composed = composeSchedule(state);\n if (!composed.schedule) {\n onError('Schedule value is required.');\n return;\n }\n if (!state.actionTarget.trim()) {\n onError('Action target is required.');\n return;\n }\n const tz = state.timezone === 'Other…' ? state.customTimezone.trim() : state.timezone;\n const actionPayload: Record<string, unknown> = {\n type: state.actionType,\n target: state.actionTarget.trim(),\n };\n if (state.actionType === 'agent' && state.actionPrompt.trim()) {\n actionPayload.prompt = state.actionPrompt.trim();\n }\n const payload: Record<string, unknown> = {\n name: trimmedName,\n type: state.type,\n schedule: composed.schedule,\n timezone: tz || 'UTC',\n action: actionPayload,\n budgetCheck: {\n maxConcurrent: state.maxConcurrent,\n skipIfBudgetLow: state.skipIfBudgetLow,\n },\n enabled: state.enabled,\n };\n setSubmitting(true);\n try {\n const saved = initial\n ? await api.put<Schedule>(`/schedules/${encodeURIComponent(initial.id)}`, payload)\n : await api.post<Schedule>('/schedules', payload);\n await onSubmitted(saved);\n } catch (err) {\n onError(`${initial ? 'Update' : 'Create'} failed: ${(err as Error).message}`);\n } finally {\n setSubmitting(false);\n }\n };\n\n return (\n <form className=\"schedule-form\" onSubmit={handleSubmit}>\n <label className=\"field-label\">Name</label>\n <input\n className=\"input\"\n type=\"text\"\n placeholder=\"Weekly code review\"\n value={state.name}\n onChange={(e) => update('name', e.target.value)}\n autoFocus\n />\n\n <div className=\"task-form-row\">\n <div className=\"task-form-field\">\n <label className=\"field-label\">Type</label>\n <select\n className=\"select\"\n value={state.type}\n onChange={(e) => update('type', e.target.value as EditorState['type'])}\n >\n {TYPES.map((t) => (\n <option key={t} value={t}>{t}</option>\n ))}\n </select>\n </div>\n </div>\n\n {state.type === 'cron' && (\n <div className=\"schedule-cron-group\">\n {!state.showAdvanced && (\n <>\n <div className=\"task-form-row\">\n <div className=\"task-form-field\">\n <label className=\"field-label\">Day of week</label>\n <select\n className=\"select\"\n value={state.cronDow}\n onChange={(e) => update('cronDow', e.target.value)}\n >\n {DOW_OPTIONS.map((d) => (\n <option key={d.value} value={d.value}>{d.label}</option>\n ))}\n </select>\n </div>\n <div className=\"task-form-field\">\n <label className=\"field-label\">Hour</label>\n <select\n className=\"select\"\n value={String(state.cronHour)}\n onChange={(e) => update('cronHour', parseInt(e.target.value, 10))}\n >\n {HOUR_OPTIONS.map((h) => (\n <option key={h.value} value={String(h.value)}>{h.label}</option>\n ))}\n </select>\n </div>\n <div className=\"task-form-field\">\n <label className=\"field-label\">Minute</label>\n <select\n className=\"select\"\n value={String(state.cronMinute)}\n onChange={(e) => update('cronMinute', parseInt(e.target.value, 10))}\n >\n {MINUTE_OPTIONS.map((m) => (\n <option key={m} value={String(m)}>{String(m).padStart(2, '0')}</option>\n ))}\n </select>\n </div>\n </div>\n </>\n )}\n {state.showAdvanced && (\n <div className=\"task-form-field\">\n <label className=\"field-label\">Cron expression</label>\n <input\n className=\"input\"\n type=\"text\"\n value={state.rawCron}\n onChange={(e) => update('rawCron', e.target.value)}\n placeholder=\"0 13 * * 0\"\n />\n </div>\n )}\n <button\n type=\"button\"\n className=\"link-btn\"\n onClick={() => update('showAdvanced', !state.showAdvanced)}\n >\n <ChevronDown\n size={12}\n style={{\n transform: state.showAdvanced ? 'rotate(180deg)' : 'none',\n transition: 'transform 0.15s',\n }}\n />\n {state.showAdvanced ? 'Hide advanced' : 'Advanced (raw cron)'}\n </button>\n </div>\n )}\n\n {state.type === 'interval' && (\n <div className=\"task-form-row\">\n <div className=\"task-form-field\" style={{ flex: 1 }}>\n <label className=\"field-label\">Every</label>\n <input\n className=\"input\"\n type=\"number\"\n min={1}\n value={state.intervalN}\n onChange={(e) => update('intervalN', parseInt(e.target.value, 10) || 1)}\n />\n </div>\n <div className=\"task-form-field\" style={{ flex: 1 }}>\n <label className=\"field-label\">Unit</label>\n <select\n className=\"select\"\n value={state.intervalUnit}\n onChange={(e) => update('intervalUnit', e.target.value)}\n >\n {INTERVAL_UNITS.map((u) => (\n <option key={u.value} value={u.value}>{u.label}</option>\n ))}\n </select>\n </div>\n </div>\n )}\n\n {state.type === 'once' && (\n <div className=\"task-form-field\">\n <label className=\"field-label\">Run at</label>\n <input\n className=\"input\"\n type=\"datetime-local\"\n value={state.onceAt}\n onChange={(e) => update('onceAt', e.target.value)}\n />\n </div>\n )}\n\n <div className=\"task-form-row\">\n <div className=\"task-form-field\" style={{ flex: 1 }}>\n <label className=\"field-label\">Timezone</label>\n <select\n className=\"select\"\n value={tzSelectValue}\n onChange={(e) => update('timezone', e.target.value)}\n >\n {TIMEZONES.map((t) => (\n <option key={t.value} value={t.value}>{t.label}</option>\n ))}\n <option value=\"Other…\">Other…</option>\n </select>\n </div>\n {state.timezone === 'Other…' && (\n <div className=\"task-form-field\" style={{ flex: 1 }}>\n <label className=\"field-label\">IANA name</label>\n <input\n className=\"input\"\n type=\"text\"\n placeholder=\"Europe/Paris\"\n value={state.customTimezone}\n onChange={(e) => update('customTimezone', e.target.value)}\n />\n </div>\n )}\n </div>\n\n <div className=\"task-form-row\">\n <div className=\"task-form-field\">\n <label className=\"field-label\">Action</label>\n <select\n className=\"select\"\n value={state.actionType}\n onChange={(e) => update('actionType', e.target.value as EditorState['actionType'])}\n >\n {ACTIONS.map((t) => (\n <option key={t} value={t}>{t}</option>\n ))}\n </select>\n </div>\n <div className=\"task-form-field\" style={{ flex: 2 }}>\n <label className=\"field-label\">Target</label>\n <input\n className=\"input\"\n type=\"text\"\n placeholder={state.actionType === 'webhook' ? 'https://...' : state.actionType === 'agent' ? 'agent name or task ref' : 'echo hi'}\n value={state.actionTarget}\n onChange={(e) => update('actionTarget', e.target.value)}\n />\n </div>\n </div>\n\n {state.actionType === 'agent' && (\n <div className=\"task-form-field\">\n <label className=\"field-label\">Prompt (what to send the agent)</label>\n <textarea\n className=\"input\"\n rows={3}\n placeholder=\"Review open PRs for stale code review comments and nudge reviewers.\"\n value={state.actionPrompt}\n onChange={(e) => update('actionPrompt', e.target.value)}\n />\n </div>\n )}\n\n <fieldset className=\"schedule-budget-card\">\n <legend>Budget pre-flight</legend>\n <label className=\"checkbox-row\">\n <input\n type=\"checkbox\"\n checked={state.skipIfBudgetLow}\n onChange={(e) => update('skipIfBudgetLow', e.target.checked)}\n />\n <span>Skip this run when too many background tasks are already running.</span>\n </label>\n <div className=\"task-form-field\">\n <label className=\"field-label\">Max concurrent bg tasks</label>\n <input\n className=\"input\"\n type=\"number\"\n min={1}\n max={64}\n value={state.maxConcurrent}\n onChange={(e) => update('maxConcurrent', parseInt(e.target.value, 10) || 6)}\n disabled={!state.skipIfBudgetLow}\n />\n </div>\n </fieldset>\n\n <label className=\"checkbox-row\">\n <input\n type=\"checkbox\"\n checked={state.enabled}\n onChange={(e) => update('enabled', e.target.checked)}\n />\n <span>Enabled</span>\n </label>\n\n <div className=\"modal-footer-actions\">\n <Button variant=\"ghost\" type=\"button\" onClick={onClose} disabled={submitting}>\n Cancel\n </Button>\n <Button variant=\"primary\" type=\"submit\" disabled={submitting}>\n {initial ? 'Save' : 'Create'}\n </Button>\n </div>\n </form>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Helpers */\n/* ------------------------------------------------------------------ */\n\nfunction humanizeSchedule(s: Schedule): string {\n if (s.type !== 'cron') return s.schedule;\n const parsed = parseCronFields(s.schedule);\n if (!parsed) return s.schedule;\n const dowName = DOW_OPTIONS.find((d) => d.value === parsed.dow)?.label || '';\n const hourLabel = HOUR_OPTIONS.find((h) => h.value === parsed.hour)?.label || `${parsed.hour}`;\n const minute = String(parsed.minute).padStart(2, '0');\n if (dowName === 'Every day') return `Every day at ${hourLabel} :${minute}`;\n return `Every ${dowName} at ${hourLabel} :${minute}`;\n}\n\nfunction formatNextRun(iso: string, tz?: string | null): string {\n try {\n return new Date(iso).toLocaleString(undefined, {\n timeZone: tz || undefined,\n weekday: 'long',\n hour: 'numeric',\n minute: '2-digit',\n month: 'short',\n day: 'numeric',\n });\n } catch {\n return new Date(iso).toLocaleString();\n }\n}\n\nfunction resultTagClass(result: string): string {\n if (result === 'success') return 'tag-success';\n if (result === 'skipped') return 'tag-warning';\n return 'tag-error';\n}\n\nfunction truncate(s: string, max: number): string {\n if (s.length <= max) return s;\n return s.slice(0, max - 1) + '…';\n}","// src/views/Skills.tsx — v3.1.0 skills registry: installed + search.\nimport { useEffect, useMemo, useState } from 'react';\nimport {\n Sparkles,\n Search,\n RefreshCw,\n Download,\n Power,\n PowerOff,\n Code,\n Layers,\n Wrench,\n FlaskConical,\n Palette,\n Brain,\n Map as MapIcon,\n GitBranch,\n Book,\n CheckCircle2,\n XCircle,\n Tag as TagIcon,\n ExternalLink,\n} from 'lucide-react';\nimport { Button } from '../components/Button';\nimport { Card, CardTitle, CardMeta } from '../components/Card';\nimport { EmptyState } from '../components/EmptyState';\nimport { Spinner } from '../components/Spinner';\nimport { StatusBadge } from '../components/StatusBadge';\nimport { useToast } from '../components/Toast';\nimport { useModal } from '../components/Modal';\nimport { api } from '../lib/api';\nimport { cn } from '../lib/utils';\nimport type { Settings, Snapshot } from '../lib/types';\n\ntype Props = {\n snapshot: Snapshot;\n settings: Settings;\n activeTab: string;\n setActiveTab: (id: string) => void;\n refreshSnapshot: () => Promise<void>;\n};\n\ntype Skill = {\n id: string;\n name: string;\n description: string;\n category: string;\n tags: string[];\n version: string;\n source: string;\n path?: string | null;\n installed?: boolean;\n enabled?: boolean;\n mock?: boolean;\n installCmd?: string;\n};\n\nconst ICONS: Record<string, typeof Sparkles> = {\n all: Sparkles,\n languages: Code,\n frameworks: Layers,\n tools: Wrench,\n testing: FlaskConical,\n design: Palette,\n reasoning: Brain,\n planning: MapIcon,\n gitops: GitBranch,\n docs: Book,\n};\n\nexport function Skills({ snapshot, refreshSnapshot }: Props) {\n const toast = useToast();\n const modal = useModal();\n const [skills, setSkills] = useState<Skill[]>([]);\n const [categories, setCategories] = useState<{ id: string; label: string; icon: string }[]>([]);\n const [loading, setLoading] = useState(true);\n const [activeCategory, setActiveCategory] = useState('all');\n const [searchQ, setSearchQ] = useState('');\n const [searchResults, setSearchResults] = useState<Skill[] | null>(null);\n const [searching, setSearching] = useState(false);\n const [installing, setInstalling] = useState<string | null>(null);\n // v3.3.1 — tracks which category <details> elements are open. Default: first 3.\n const [expandedCategories, setExpandedCategories] = useState<Set<string>>(\n new Set(['all', 'languages', 'frameworks']),\n );\n\n const reload = async () => {\n setLoading(true);\n try {\n const d = await api.get<{ skills: Skill[]; categories: { id: string; label: string; icon: string }[] }>('/skills');\n setSkills(d.skills || []);\n setCategories(d.categories || []);\n } catch (err) {\n toast.error(`Skills load failed: ${(err as Error).message}`);\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n reload();\n }, []);\n\n // Debounce search.\n useEffect(() => {\n if (!searchQ.trim()) {\n setSearchResults(null);\n return;\n }\n setSearching(true);\n const id = setTimeout(async () => {\n try {\n const d = await api.get<{ results: Skill[] }>(`/skills/search?q=${encodeURIComponent(searchQ.trim())}`);\n setSearchResults(d.results || []);\n } catch (err) {\n toast.error(`Search failed: ${(err as Error).message}`);\n } finally {\n setSearching(false);\n }\n }, 280);\n return () => clearTimeout(id);\n }, [searchQ, toast]);\n\n const filteredInstalled = useMemo(() => {\n let out = skills;\n if (activeCategory !== 'all') {\n out = out.filter((s) => (s.category || 'tools') === activeCategory);\n }\n return out;\n }, [skills, activeCategory]);\n\n const onInstall = async (s: Skill) => {\n if (!confirm(`Install skill \"${s.name}\"?\\n\\n${s.installCmd || `skills add ${s.id}`}`)) return;\n setInstalling(s.id);\n try {\n await api.post('/skills/install', { name: s.name, source: s.id });\n toast.success(`Installed ${s.name}.`);\n setSearchResults((cur) => cur?.filter((x) => x.id !== s.id) || cur);\n await reload();\n } catch (err) {\n toast.error(`Install failed: ${(err as Error).message}`);\n } finally {\n setInstalling(null);\n }\n };\n\n const onToggle = async (s: Skill) => {\n try {\n if (s.enabled !== false) {\n await api.post(`/skills/${encodeURIComponent(s.id)}/disable`);\n toast.success(`Disabled ${s.name}.`);\n } else {\n await api.post(`/skills/${encodeURIComponent(s.id)}/enable`);\n toast.success(`Enabled ${s.name}.`);\n }\n await reload();\n } catch (err) {\n toast.error(`Toggle failed: ${(err as Error).message}`);\n }\n };\n\n const onShowDetails = (s: Skill) => {\n let content: React.ReactNode;\n content = (\n <div className=\"skill-detail\">\n <p className=\"muted text-sm mono skill-detail-source\">{s.source}</p>\n <p className=\"skill-detail-desc\">{s.description || 'No description.'}</p>\n <div className=\"skill-detail-meta\">\n <span><strong>Category:</strong> {s.category}</span>\n <span><strong>Version:</strong> <code>{s.version}</code></span>\n {s.path && <span><strong>Path:</strong> <code>{s.path}</code></span>}\n </div>\n {s.tags && s.tags.length > 0 && (\n <div className=\"skill-detail-tags\">\n {s.tags.map((t) => (\n <span key={t} className=\"tag\">{t}</span>\n ))}\n </div>\n )}\n {s.installCmd && (\n <div>\n <label className=\"field-label\">Install command</label>\n <pre className=\"skill-detail-cmd mono\">{s.installCmd}</pre>\n </div>\n )}\n </div>\n );\n modal.open({\n title: s.name,\n width: 560,\n children: content,\n footer: (\n <div className=\"modal-footer-actions\">\n <Button variant=\"ghost\" onClick={() => modal.close()}>Close</Button>\n {!s.installed && (\n <Button variant=\"primary\" onClick={() => { modal.close(); onInstall(s); }} loading={installing === s.id}>\n <Download size={12} /> Install\n </Button>\n )}\n </div>\n ),\n });\n };\n\n return (\n <div className=\"view view-skills\">\n <header className=\"view-header\">\n <div className=\"view-header-text\">\n <h2 className=\"view-title\">\n <Sparkles size={18} /> Skills\n </h2>\n <p className=\"view-subtitle\">\n Installed skills + browse the registry. Powered by the <code>skills</code> CLI.\n </p>\n </div>\n <div className=\"view-actions\">\n <div className=\"search-input\">\n <Search size={14} />\n <input\n className=\"input\"\n type=\"text\"\n placeholder=\"Browse new skills…\"\n value={searchQ}\n onChange={(e) => setSearchQ(e.target.value)}\n />\n {searchQ && (\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label=\"Clear search\"\n onClick={() => setSearchQ('')}\n title=\"Clear\"\n >\n <XCircle size={12} />\n </button>\n )}\n </div>\n <Button variant=\"secondary\" size=\"sm\" onClick={reload}>\n <RefreshCw size={14} /> Refresh\n </Button>\n </div>\n </header>\n\n {/* v3.3.1 — Search results take priority over category view */}\n {searchQ.trim() && (\n <section className=\"skills-section\">\n <h3 className=\"skills-section-title\">\n <Search size={14} /> Search results\n {searching && <Spinner size=\"sm\" />}\n </h3>\n {searching ? (\n <div className=\"skills-grid\">\n {[0, 1, 2].map((i) => (\n <div key={i} className=\"skill-card skill-card-skeleton\" />\n ))}\n </div>\n ) : searchResults && searchResults.length === 0 ? (\n <EmptyState\n icon={<Search size={28} />}\n title=\"No matches\"\n message={`No skills match \"${searchQ}\".`}\n />\n ) : (\n <div className=\"skills-grid\">\n {(searchResults || []).map((s) => (\n <SkillCard\n key={`search-${s.id}`}\n skill={s}\n onShow={() => onShowDetails(s)}\n onInstall={() => onInstall(s)}\n installing={installing === s.id}\n installed={!!skills.find((x) => x.id === s.id)}\n />\n ))}\n </div>\n )}\n </section>\n )}\n\n {/* v3.3.1 — Collapsible category sections */}\n {!searchQ.trim() && (\n <>\n {/* Quick category pills */}\n <div className=\"skills-categories\">\n {categories.map((c) => {\n const Icon = ICONS[c.id] || Sparkles;\n const count = skills.filter((s) => (s.category || 'tools') === c.id).length;\n return (\n <button\n key={c.id}\n type=\"button\"\n className={cn('skill-category', activeCategory === c.id && 'skill-category-active')}\n onClick={() => setActiveCategory(c.id)}\n >\n <Icon size={14} />\n <span>{c.label}</span>\n {count > 0 && <span className=\"skill-category-count\">{count}</span>}\n </button>\n );\n })}\n </div>\n\n {/* Installed skills grouped by category with <details> */}\n <section className=\"skills-section\">\n <h3 className=\"skills-section-title\">\n <CheckCircle2 size={14} /> Installed\n </h3>\n {loading ? (\n <div className=\"view-loading\"><Spinner size=\"lg\" /></div>\n ) : (\n <div className=\"skills-categories-list\">\n {categories.map((cat) => {\n const catSkills = filteredInstalled.filter((s) => (s.category || 'tools') === cat.id);\n if (catSkills.length === 0) return null;\n const isOpen = expandedCategories.has(cat.id);\n return (\n <details\n key={cat.id}\n className=\"skills-category\"\n open={isOpen}\n onToggle={(e) => {\n const tgt = e.currentTarget as HTMLDetailsElement;\n setExpandedCategories((prev) => {\n const next = new Set(prev);\n if (tgt.open) next.add(cat.id);\n else next.delete(cat.id);\n return next;\n });\n }}\n >\n <summary className=\"skills-category-summary\">\n <span className=\"skills-category-name\">\n {ICONS[cat.id] && (() => { const Icon = ICONS[cat.id]; return <Icon size={14} />; })()}\n {cat.label}\n </span>\n <span className=\"skill-category-count\">{catSkills.length}</span>\n </summary>\n <div className=\"skills-grid\">\n {catSkills.map((s) => (\n <SkillCard\n key={s.id}\n skill={s}\n onShow={() => onShowDetails(s)}\n onToggle={() => onToggle(s)}\n />\n ))}\n </div>\n </details>\n );\n })}\n </div>\n )}\n </section>\n </>\n )}\n </div>\n );\n}\n\nfunction SkillCard({\n skill,\n onShow,\n onInstall,\n onToggle,\n installing,\n installed,\n}: {\n skill: Skill;\n onShow: () => void;\n onInstall?: () => void;\n onToggle?: () => void;\n installing?: boolean;\n installed?: boolean;\n}) {\n const Icon = ICONS[skill.category] || Sparkles;\n const enabled = skill.enabled !== false;\n return (\n <Card variant=\"elevated\" interactive className={cn('skill-card', !enabled && 'skill-card-disabled')}>\n <div className=\"skill-card-head\">\n <div className=\"skill-card-icon\" style={{ background: `color-mix(in srgb, var(--accent) 12%, transparent)` }}>\n <Icon size={18} />\n </div>\n <div className=\"skill-card-title-area\">\n <div className=\"skill-card-title\">{skill.name}</div>\n <div className=\"skill-card-source mono\">{skill.source}</div>\n </div>\n {installed ? (\n <StatusBadge kind={enabled ? 'success' : 'neutral'}>\n {enabled ? 'on' : 'off'}\n </StatusBadge>\n ) : (\n <StatusBadge kind=\"accent\">new</StatusBadge>\n )}\n </div>\n <p className=\"skill-card-desc\">{skill.description || 'No description.'}</p>\n <div className=\"skill-card-meta\">\n <span className=\"mono text-sm\">v{skill.version}</span>\n {skill.category && <span className=\"text-sm muted\">{skill.category}</span>}\n {skill.tags && skill.tags.length > 0 && skill.tags.slice(0, 3).map((t) => (\n <span key={t} className=\"skill-card-tag\">{t}</span>\n ))}\n </div>\n <div className=\"skill-card-actions\">\n <Button variant=\"ghost\" size=\"sm\" onClick={onShow}>\n <ExternalLink size={12} /> Details\n </Button>\n {installed && onToggle && (\n <Button\n variant={enabled ? 'ghost' : 'secondary'}\n size=\"sm\"\n onClick={onToggle}\n title={enabled ? 'Disable' : 'Enable'}\n >\n {enabled ? <PowerOff size={12} /> : <Power size={12} />}\n {enabled ? 'Disable' : 'Enable'}\n </Button>\n )}\n {!installed && onInstall && (\n <Button\n variant=\"primary\"\n size=\"sm\"\n onClick={onInstall}\n loading={installing}\n >\n <Download size={12} /> Install\n </Button>\n )}\n </div>\n </Card>\n );\n}\n","// src/views/History.tsx — v3.4.0: cross-project history view.\n// Shows per-project timelines (task events, plan events, project lifecycle)\n// aggregated from the activity log.\n\nimport { useEffect, useState } from 'react';\nimport {\n History as HistoryIcon,\n RefreshCw,\n Folder,\n CheckSquare,\n Filter,\n ChevronDown,\n ChevronRight,\n Download,\n FileText,\n} from 'lucide-react';\nimport { Card, CardTitle, CardMeta } from '../components/Card';\nimport { Button } from '../components/Button';\nimport { Spinner } from '../components/Spinner';\nimport { useToast } from '../components/Toast';\nimport { api } from '../lib/api';\nimport { cn, formatRelative } from '../lib/utils';\nimport type { Settings, Snapshot } from '../lib/types';\n\ntype Props = {\n snapshot: Snapshot;\n settings: Settings;\n activeTab: string;\n setActiveTab: (id: string) => void;\n refreshSnapshot: () => Promise<void>;\n};\n\ntype HistoryEvent = {\n ts: string;\n kind: string;\n nodeId?: string;\n text?: string;\n author?: string;\n taskId?: string;\n [k: string]: unknown;\n};\n\ntype ProjectHistory = {\n id: string;\n name: string;\n path: string;\n status: string;\n lastAccessed?: string | null;\n tasks: { total: number; done: number; doing: number; blocked: number; queued: number };\n plans: number;\n};\n\ntype HistoryResponse = {\n events: HistoryEvent[];\n projects: ProjectHistory[];\n stats: { file: string; size: number; lines: number; lastTs: string | null; counts: Record<string, number> };\n generatedAt: string;\n};\n\nconst TIME_RANGES = [\n { id: '1h', label: 'Last hour', ms: 60 * 60 * 1000 },\n { id: '1d', label: 'Last day', ms: 24 * 60 * 60 * 1000 },\n { id: '7d', label: 'Last 7 days', ms: 7 * 24 * 60 * 60 * 1000 },\n { id: '30d', label: 'Last 30 days', ms: 30 * 24 * 60 * 60 * 1000 },\n { id: 'all', label: 'All time', ms: 0 },\n];\n\nexport function History({ snapshot }: Props) {\n const toast = useToast();\n const [data, setData] = useState<HistoryResponse | null>(null);\n const [loading, setLoading] = useState(true);\n const [rangeId, setRangeId] = useState<string>('1d');\n const [expanded, setExpanded] = useState<Set<string>>(new Set());\n const [tick, setTick] = useState(0);\n\n const load = async (since?: string) => {\n try {\n const q = since ? `?since=${encodeURIComponent(since)}&limit=1000` : '?limit=1000';\n const r = await api.get<HistoryResponse>(`/history${q}`);\n setData(r);\n setExpanded(\n new Set(\n r.projects\n .filter((project) => r.events.some((ev) => (ev as { projectId?: string }).projectId === project.id))\n .map((project) => project.id),\n ),\n );\n } catch (err) {\n toast.error(`History load failed: ${(err as Error).message}`);\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n setLoading(true);\n const range = TIME_RANGES.find((r) => r.id === rangeId) || TIME_RANGES[1];\n if (range.ms > 0) {\n const since = new Date(Date.now() - range.ms).toISOString();\n load(since);\n } else {\n load();\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [rangeId]);\n\n useEffect(() => {\n const id = setInterval(() => setTick((t) => t + 1), 30_000);\n return () => clearInterval(id);\n }, []);\n\n // Group events by project — use projectId where present, otherwise 'global'\n const eventsByProject = new Map<string, HistoryEvent[]>();\n for (const ev of data?.events || []) {\n const pid = (ev as { projectId?: string }).projectId || 'global';\n if (!eventsByProject.has(pid)) eventsByProject.set(pid, []);\n eventsByProject.get(pid)!.push(ev);\n }\n\n const toggleProject = (id: string) => {\n setExpanded((cur) => {\n const next = new Set(cur);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n return next;\n });\n };\n\n const onExportJson = () => {\n if (!data) return;\n const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = `bizar-history-${new Date().toISOString().replace(/[:.]/g, '-')}.json`;\n a.click();\n URL.revokeObjectURL(url);\n toast.success('History exported.');\n };\n\n return (\n <div className=\"view view-history\" data-tick={tick}>\n <header className=\"view-header\">\n <div className=\"view-header-text\">\n <h2 className=\"view-title\">\n <HistoryIcon size={18} /> History\n </h2>\n <p className=\"view-subtitle\">\n Cross-project history of events, tasks, and plans.\n {data?.stats?.lastTs && (\n <> · last event {formatRelative(data.stats.lastTs)}</>\n )}\n </p>\n </div>\n <div className=\"view-actions\">\n <div className=\"tasks-toolbar-group\">\n <Filter size={14} style={{ color: 'var(--text-dim)' }} />\n <select\n className=\"select select-sm\"\n value={rangeId}\n onChange={(e) => setRangeId(e.target.value)}\n title=\"Time range\"\n >\n {TIME_RANGES.map((r) => (\n <option key={r.id} value={r.id}>{r.label}</option>\n ))}\n </select>\n </div>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => {\n setLoading(true);\n const range = TIME_RANGES.find((r) => r.id === rangeId) || TIME_RANGES[1];\n if (range.ms > 0) {\n load(new Date(Date.now() - range.ms).toISOString());\n } else {\n load();\n }\n }}\n >\n <RefreshCw size={14} /> Refresh\n </Button>\n <Button variant=\"secondary\" size=\"sm\" onClick={onExportJson}>\n <Download size={14} /> Export\n </Button>\n </div>\n </header>\n\n {loading && (\n <div className=\"view-loading\">\n <Spinner size=\"lg\" />\n <p>Loading history…</p>\n </div>\n )}\n\n {!loading && data && (\n <div className=\"history-list\">\n {data.projects.length === 0 && (\n <Card>\n <CardTitle><Folder size={14} /> No projects</CardTitle>\n <CardMeta>Register a project in Overview to start tracking history.</CardMeta>\n </Card>\n )}\n\n {data.projects.map((p) => {\n const events = eventsByProject.get(p.id) || [];\n const isOpen = expanded.has(p.id);\n return (\n <Card key={p.id} className=\"history-project\">\n <div className=\"history-project-head\">\n <div style={{ display: 'flex', flexDirection: 'column', gap: 4, minWidth: 0, flex: 1 }}>\n <div className=\"history-project-name\">\n <Folder size={16} /> {p.name}\n </div>\n <div className=\"history-project-meta\">{p.path}</div>\n </div>\n <div className=\"history-project-stats\">\n <span className=\"history-project-stat\">\n <span className=\"history-project-stat-num\">{p.tasks.done}</span>\n <span className=\"muted\">/ {p.tasks.total} done</span>\n </span>\n {p.tasks.doing > 0 && (\n <span className=\"history-project-stat\">\n <span className=\"history-project-stat-num\">{p.tasks.doing}</span>\n <span className=\"muted\">doing</span>\n </span>\n )}\n {p.tasks.blocked > 0 && (\n <span className=\"history-project-stat\">\n <span className=\"history-project-stat-num\">{p.tasks.blocked}</span>\n <span className=\"muted\">blocked</span>\n </span>\n )}\n <span className=\"history-project-stat\">\n <FileText size={11} /> <span className=\"history-project-stat-num\">{p.plans}</span>\n <span className=\"muted\"> plan{p.plans === 1 ? '' : 's'}</span>\n </span>\n {p.lastAccessed && (\n <span className=\"history-project-stat\">\n <span className=\"muted\">last opened {formatRelative(p.lastAccessed)}</span>\n </span>\n )}\n </div>\n <button\n type=\"button\"\n className=\"icon-btn\"\n onClick={() => toggleProject(p.id)}\n aria-label={isOpen ? 'Collapse' : 'Expand'}\n >\n {isOpen ? <ChevronDown size={14} /> : <ChevronRight size={14} />}\n </button>\n </div>\n\n {isOpen && (\n <div className=\"history-timeline-mini\">\n {events.length === 0 ? (\n <div className=\"muted\" style={{ padding: '12px 8px', fontSize: 12 }}>\n No events in this time range.\n </div>\n ) : (\n events.slice(-100).reverse().map((ev, i) => (\n <div key={i} className=\"history-timeline-row\">\n <span className=\"history-timeline-ts\">\n {new Date(ev.ts).toLocaleTimeString()}\n </span>\n <span className=\"history-timeline-kind\">{ev.kind || 'event'}</span>\n <span className=\"history-timeline-msg\" title={String(ev.text || ev.title || '')}>\n {ev.author ? `@${ev.author} ` : ''}\n {String(ev.text ?? ev.title ?? ev.name ?? '')}\n </span>\n </div>\n ))\n )}\n </div>\n )}\n </Card>\n );\n })}\n\n {/* Global / unassigned events */}\n {eventsByProject.has('global') && (\n <Card className=\"history-project\">\n <div className=\"history-project-head\">\n <div style={{ display: 'flex', flexDirection: 'column', gap: 4, minWidth: 0, flex: 1 }}>\n <div className=\"history-project-name\">\n <HistoryIcon size={16} /> Global events\n </div>\n <div className=\"history-project-meta\">\n Activity not tied to a specific project\n </div>\n </div>\n </div>\n <div className=\"history-timeline-mini\">\n {(eventsByProject.get('global') || []).slice(-100).reverse().map((ev, i) => (\n <div key={i} className=\"history-timeline-row\">\n <span className=\"history-timeline-ts\">\n {new Date(ev.ts).toLocaleTimeString()}\n </span>\n <span className=\"history-timeline-kind\">{ev.kind || 'event'}</span>\n <span className=\"history-timeline-msg\" title={String(ev.text || ev.title || '')}>\n {ev.author ? `@${ev.author} ` : ''}\n {String(ev.text ?? ev.title ?? ev.name ?? '')}\n </span>\n </div>\n ))}\n </div>\n </Card>\n )}\n\n {data.stats?.counts && Object.keys(data.stats.counts).length > 0 && (\n <Card>\n <CardTitle>Event counts by kind</CardTitle>\n <CardMeta>{data.stats.lines} total lines in log</CardMeta>\n <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, marginTop: 8 }}>\n {Object.entries(data.stats.counts)\n .sort((a, b) => b[1] - a[1])\n .slice(0, 30)\n .map(([kind, count]) => (\n <span\n key={kind}\n className={cn('tag', 'tag-neutral')}\n style={{ fontFamily: 'var(--font-mono)' }}\n >\n {kind}: {count}\n </span>\n ))}\n </div>\n </Card>\n )}\n </div>\n )}\n </div>\n );\n}\n","// src/views/MiniMaxUsage.tsx — v4.5.0\n//\n// Token Plan usage tracking dashboard.\n//\n// Renders the user's current 5-hour rolling + weekly remaining quota\n// per model, fetched from https://www.minimax.io/v1/token_plan/remains.\n// The Subscription Key is read from opencode's canonical auth store\n// (`~/.local/share/opencode/auth.json`) — same place opencode's\n// `/connect` command writes to — so the user only enters the key once\n// and both opencode + the Bizar dashboard pick it up.\n//\n// The view has three states:\n// 1. Onboarding wizard (first time, no key configured) — guided flow\n// that takes the user from \"get a key\" → paste → save → dashboard\n// 2. Live dashboard (key configured) — per-model 5h + weekly usage\n// 3. Banner only (key invalid or auth failure) — inline error\n\nimport { useCallback, useEffect, useState } from 'react';\nimport {\n Coins,\n RefreshCw,\n AlertTriangle,\n CheckCircle2,\n KeyRound,\n Send,\n Loader2,\n Calendar,\n Activity,\n Save,\n Eye,\n EyeOff,\n Sparkles,\n X,\n ExternalLink,\n ShieldCheck,\n CircleCheck,\n} from 'lucide-react';\nimport { Card, CardTitle, CardMeta } from '../components/Card';\nimport { Button } from '../components/Button';\nimport { Spinner } from '../components/Spinner';\nimport { useToast } from '../components/Toast';\nimport { api } from '../lib/api';\nimport { cn } from '../lib/utils';\nimport type { Settings, Snapshot } from '../lib/types';\n// Settings is passed for forward-compat with the App's view-props shape\n// even though the read path no longer needs it.\n\ntype Props = {\n snapshot: Snapshot;\n settings: Settings;\n activeTab: string;\n setActiveTab: (id: string) => void;\n refreshSnapshot: () => Promise<void>;\n};\n\n// Suppress unused-var — `settings` is kept in the prop signature so\n// App.tsx can pass a single shape; the read path doesn't need it now\n// that the key comes from opencode's auth.json.\nvoid (null as unknown as Settings | null);\n\ntype RemainsModel = {\n model_name: string;\n current_interval_remaining_percent: number;\n current_weekly_remaining_percent: number;\n current_interval_consumed_percent?: number;\n weekly_consumed_percent?: number;\n current_interval_status: number;\n current_weekly_status: number;\n current_interval_total_count: number;\n current_interval_usage_count: number;\n current_weekly_total_count: number;\n current_weekly_usage_count: number;\n endTimeISO?: string;\n weeklyEndTimeISO?: string;\n intervalResetInMs?: number;\n weeklyResetInMs?: number;\n intervalResetInHuman?: string;\n weeklyResetInHuman?: string;\n intervalUsed?: number;\n intervalTotal?: number;\n weeklyUsed?: number;\n weeklyTotal?: number;\n};\n\ntype RemainsSnapshot = {\n ok: boolean;\n cached?: boolean;\n fetchedAt?: number;\n apiKeyHint?: string;\n keySource?: string;\n groupId?: string;\n baseUrl?: string;\n models?: RemainsModel[];\n baseResp?: { status_code: number; status_msg: string };\n error?: string;\n message?: string;\n};\n\ntype Status = {\n configured: boolean;\n apiKeyHint: string;\n source: string;\n groupId: string;\n tokenBaseUrl: string;\n chatBaseUrl: string;\n knownModels: string[];\n keyPatternValid: boolean | null;\n cache: { fetchedAt: number; apiKeyHint: string; modelCount: number } | null;\n};\n\ntype OnboardingState = {\n dismissedAt: number | null;\n hiddenModels: string[];\n};\n\ntype TestResult = {\n ok: boolean;\n error?: string;\n message?: string;\n model?: string;\n content?: string;\n reasoning?: string;\n finishReason?: string;\n usage?: {\n total_tokens?: number;\n prompt_tokens?: number;\n completion_tokens?: number;\n prompt_tokens_details?: { cached_tokens?: number };\n };\n status?: number;\n raw?: unknown;\n};\n\nexport function MiniMaxUsage({ snapshot, settings, setActiveTab, refreshSnapshot }: Props) {\n const toast = useToast();\n const [status, setStatus] = useState<Status | null>(null);\n const [remains, setRemains] = useState<RemainsSnapshot | null>(null);\n const [onboarding, setOnboarding] = useState<OnboardingState | null>(null);\n const [loading, setLoading] = useState(true);\n const [refreshing, setRefreshing] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [testResult, setTestResult] = useState<TestResult | null>(null);\n const [testing, setTesting] = useState(false);\n // Onboarding wizard state.\n const [wizardStep, setWizardStep] = useState(0); // 0..3 (welcome → key → verify → done)\n const [wizardVerifying, setWizardVerifying] = useState(false);\n const [wizardVerifyResult, setWizardVerifyResult] = useState<TestResult | null>(null);\n // Inline key config — saves a trip to Settings.\n const [keyDraft, setKeyDraft] = useState('');\n const [showKey, setShowKey] = useState(false);\n const [savingKey, setSavingKey] = useState(false);\n\n const load = useCallback(async () => {\n setLoading(true);\n setError(null);\n try {\n const [s, r, o] = await Promise.all([\n api.get<Status>('/minimax/status'),\n api.get<RemainsSnapshot>('/minimax/remains'),\n api.get<OnboardingState>('/minimax/onboarding'),\n ]);\n setStatus(s);\n setRemains(r);\n setOnboarding(o);\n setKeyDraft(''); // never prefill — security\n // If we just configured a key (dismissedAt is set but not configured)\n // or the user already dismissed, do not show the wizard.\n if (s.configured) setWizardStep(4); // skip past wizard\n } catch (err) {\n setError((err as Error).message || 'Failed to load MiniMax data');\n } finally {\n setLoading(false);\n }\n }, []);\n\n // Dismiss the onboarding wizard (so it doesn't show again until the\n // user clears their key).\n const dismissWizard = useCallback(async () => {\n try {\n await api.post('/minimax/onboarding', { dismissedAt: Date.now() });\n setOnboarding((o) => o ? { ...o, dismissedAt: Date.now() } : o);\n } catch { /* best-effort */ }\n }, []);\n\n // Wizard step 2: test the key against the real API before saving.\n const verifyKeyBeforeSave = useCallback(async () => {\n if (!keyDraft.trim()) {\n toast.error('Paste a Subscription Key first.');\n return;\n }\n setWizardVerifying(true);\n setWizardVerifyResult(null);\n try {\n // Temporarily save to the real auth.json, probe, then if the\n // probe fails the user can re-paste. The probe endpoint is the\n // chat completions surface (cheaper than remains + a real-world\n // check that the key actually works for the dashboard's purpose).\n const r = await api.post<TestResult>('/minimax/test', {\n prompt: 'Reply with a single word: pong',\n model: 'MiniMax-M3',\n maxTokens: 16,\n });\n setWizardVerifyResult(r);\n if (r.ok) {\n setWizardStep(3); // success\n toast.success('Key works. Saving…');\n // Auto-save: the user already proved the key works.\n try {\n await api.post('/minimax/onboarding/save-key', {\n key: keyDraft.trim(),\n groupId: 'default',\n });\n clearRemainsCacheClient();\n toast.success('Subscription Key saved.');\n } catch (err) {\n toast.error(`Save failed: ${(err as Error).message}`);\n }\n void load();\n } else {\n toast.error(`Verification failed: ${r.message ?? r.error ?? 'unknown'}`);\n }\n } catch (err) {\n toast.error(`Test request failed: ${(err as Error).message}`);\n } finally {\n setWizardVerifying(false);\n }\n }, [keyDraft, toast, load]);\n\n useEffect(() => { load(); }, [load]);\n\n // Persist the key into opencode's auth.json. The server-side route\n // `POST /api/minimax/onboarding/save-key` writes to\n // `~/.local/share/opencode/auth.json` (the canonical store the\n // opencode `/connect` command writes to). The dashboard reads it\n // back on the next status fetch.\n const saveKey = useCallback(async () => {\n if (!keyDraft.trim()) {\n toast.error('Paste a Subscription Key first.');\n return;\n }\n setSavingKey(true);\n try {\n const r = await api.post<{ ok: boolean; path?: string; apiKeyHint?: string; error?: string; message?: string }>(\n '/minimax/onboarding/save-key',\n { key: keyDraft.trim(), groupId: 'default' },\n );\n if (!r.ok) {\n toast.error(`Save failed: ${r.message ?? r.error ?? 'unknown'}`);\n return;\n }\n setKeyDraft('');\n clearRemainsCacheClient();\n toast.success('Subscription Key saved. Loading quota…');\n void load();\n } catch (err) {\n toast.error(`Save failed: ${(err as Error).message}`);\n } finally {\n setSavingKey(false);\n }\n }, [keyDraft, toast, load]);\n\n // Clears the on-disk + in-memory cache via the dashboard's\n // /api/minimax/cache DELETE endpoint. Wrapped in a helper so the\n // success path can await the round-trip.\n const clearRemainsCacheClient = useCallback(async () => {\n try { await api.del('/minimax/cache'); } catch { /* best-effort */ }\n }, []);\n\n const refresh = useCallback(async () => {\n setRefreshing(true);\n setError(null);\n try {\n await api.post('/minimax/remains/refresh');\n await load();\n toast.success('Refreshed');\n } catch (err) {\n toast.error(`Refresh failed: ${(err as Error).message}`);\n } finally {\n setRefreshing(false);\n }\n }, [load, toast]);\n\n const sendTest = useCallback(async () => {\n setTesting(true);\n setTestResult(null);\n try {\n const r = await api.post<TestResult>('/minimax/test', {\n prompt: 'Reply with a single word: pong',\n model: 'MiniMax-M3',\n maxTokens: 16,\n });\n setTestResult(r);\n if (r.ok) {\n toast.success(`Test ok — used ${r.usage?.total_tokens ?? '?'} tokens`);\n } else {\n toast.error(`Test failed: ${r.message ?? r.error ?? 'unknown'}`);\n }\n } catch (err) {\n toast.error(`Test request failed: ${(err as Error).message}`);\n } finally {\n setTesting(false);\n }\n }, [toast]);\n\n if (loading && !status) {\n return (\n <div className=\"view-container\">\n <Spinner /> Loading MiniMax data…\n </div>\n );\n }\n\n if (!status) {\n return (\n <div className=\"view-container\">\n <div className=\"error-card\">\n <AlertTriangle size={20} />\n <div>\n <strong>Couldn't load MiniMax status</strong>\n <pre>{error ?? 'unknown error'}</pre>\n </div>\n </div>\n </div>\n );\n }\n\n // First-run onboarding: show the wizard when no key is configured and\n // the user hasn't dismissed it. The wizard writes the key to opencode's\n // auth store (same place `/connect` writes), then the dashboard reads\n // it back via /minimax/status and the live dashboard takes over.\n const showWizard = !status.configured\n && (onboarding?.dismissedAt == null)\n && wizardStep < 4;\n if (showWizard) {\n return <OnboardingWizard\n step={wizardStep}\n setStep={setWizardStep}\n keyDraft={keyDraft}\n setKeyDraft={setKeyDraft}\n showKey={showKey}\n setShowKey={setShowKey}\n verifying={wizardVerifying}\n verifyResult={wizardVerifyResult}\n onVerify={verifyKeyBeforeSave}\n onSkip={async () => {\n await dismissWizard();\n toast.success(\"Skipped. You can paste the key anytime from this page.\");\n }}\n onManualKeySave={saveKey}\n savingKey={savingKey}\n status={status}\n />;\n }\n\n return (\n <div className=\"view-container view-minimax-usage\">\n {/* ── Header ─────────────────────────────────────────────────── */}\n <header className=\"view-header\">\n <div className=\"view-header-titles\">\n <h1 className=\"view-title\">\n <Coins size={20} style={{ verticalAlign: 'text-bottom', marginRight: 6 }} />\n MiniMax Token Plan\n </h1>\n <p className=\"view-subtitle\">\n Remaining 5-hour + weekly quota per model. Fetches live from{' '}\n <code>www.minimax.io/v1/token_plan/remains</code>.\n </p>\n </div>\n <div className=\"view-header-actions\">\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={() => setActiveTab('settings')}\n title=\"Configure your Subscription Key\"\n >\n <KeyRound size={14} /> {status.configured ? `Key ${status.apiKeyHint}` : 'Add key'}\n </Button>\n <Button variant=\"secondary\" size=\"sm\" onClick={refresh} disabled={refreshing}>\n {refreshing ? <Loader2 size={14} className=\"spin\" /> : <RefreshCw size={14} />}\n Refresh\n </Button>\n </div>\n </header>\n\n {/* ── Status banners ─────────────────────────────────────────── */}\n {remains && !remains.ok && (\n <div className=\"banner banner-err\">\n <AlertTriangle size={16} />\n <span>\n <strong>Couldn't load quota</strong>: {remains.message ?? remains.error ?? 'unknown error'}\n {status.source && (\n <> · source: <code>{status.source}</code></>\n )}\n </span>\n </div>\n )}\n {status.configured && status.keyPatternValid === false && (\n <div className=\"banner banner-warn\">\n <AlertTriangle size={16} />\n <span>\n The configured Subscription Key has an unexpected format (expected\n <code> sk-cp-</code> / <code>sk-ant-</code> / <code>sk-or-</code> prefix).\n Re-save it from this page.\n </span>\n </div>\n )}\n\n {/* ── Subscription Key config (inline) ──────────────────── */}\n {(\n <Card id=\"minimax-key\">\n <CardTitle>\n <KeyRound size={14} /> Subscription Key\n </CardTitle>\n <CardMeta>\n Get it from{' '}\n <a\n href=\"https://platform.minimax.io/user-center/payment/token-plan\"\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"minimax-link\"\n >\n platform.minimax.io/user-center/payment/token-plan\n </a>\n . Stored in <code>~/.local/share/opencode/auth.json</code>;\n never sent to any other host. Status:{' '}\n {status.configured ? (\n <strong className=\"is-ok\">configured ({status.apiKeyHint})</strong>\n ) : (\n <strong className=\"is-warn\">not configured</strong>\n )}\n .\n </CardMeta>\n <div className=\"minimax-key-row\">\n <div className=\"minimax-key-input-wrap\">\n <KeyRound size={12} className=\"minimax-key-icon\" />\n <input\n type={showKey ? 'text' : 'password'}\n value={keyDraft}\n onChange={(e) => setKeyDraft(e.target.value)}\n placeholder={status.configured ? '•••• paste a new key to replace' : 'eyJhbGciOi...'}\n spellCheck={false}\n autoComplete=\"off\"\n className=\"minimax-key-input\"\n />\n <button\n type=\"button\"\n onClick={() => setShowKey((v) => !v)}\n className=\"minimax-key-toggle\"\n aria-label={showKey ? 'Hide key' : 'Show key'}\n title={showKey ? 'Hide key' : 'Show key'}\n >\n {showKey ? <EyeOff size={13} /> : <Eye size={13} />}\n </button>\n </div>\n <Button onClick={saveKey} disabled={savingKey || !keyDraft.trim()} size=\"sm\">\n {savingKey ? <Loader2 size={14} className=\"spin\" /> : <Save size={14} />}\n Save key\n </Button>\n </div>\n </Card>\n )}\n\n {remains && !remains.ok && (\n <div className=\"banner banner-err\">\n <AlertTriangle size={16} />\n <span>\n <strong>Couldn't load quota</strong>: {remains.message ?? remains.error ?? 'unknown error'}\n </span>\n </div>\n )}\n\n {/* ── Summary stats ─────────────────────────────────────────── */}\n {remains?.ok && remains.models && (\n <>\n <div className=\"minimax-stats-row\">\n <Stat\n label=\"Models tracked\"\n value={String(remains.models.length)}\n hint=\"Distinct model quotas returned by the API\"\n />\n <Stat\n label=\"Last fetched\"\n value={remains.fetchedAt ? relativeTime(remains.fetchedAt) : '—'}\n hint=\"Refreshed on demand + every 60s\"\n />\n <Stat\n label=\"Group\"\n value={remains.groupId ?? '—'}\n hint=\"Usually 'default' for an individual team\"\n />\n <Stat\n label=\"API key\"\n value={remains.apiKeyHint ?? '—'}\n hint=\"Masked; the real key never leaves auth.json\"\n />\n </div>\n\n {/* ── Per-model quota cards ──────────────────────────────── */}\n <div className=\"minimax-models-grid\">\n {remains.models.map((m) => (\n <ModelQuotaCard key={m.model_name} model={m} />\n ))}\n </div>\n </>\n )}\n\n {/* ── Test prompt card ─────────────────────────────────────── */}\n {status.configured && (\n <Card id=\"minimax-test\">\n <CardTitle>\n <Send size={14} /> Test the API key\n </CardTitle>\n <CardMeta>\n Sends a one-shot chat completion to{' '}\n <code>{status.chatBaseUrl}/chat/completions</code> to verify the\n key works and surface live token usage.\n </CardMeta>\n <div className=\"minimax-test-actions\">\n <Button onClick={sendTest} disabled={testing} variant=\"primary\" size=\"sm\">\n {testing ? <Loader2 size={14} className=\"spin\" /> : <Send size={14} />}\n Send test prompt\n </Button>\n <code className=\"minimax-test-prompt\">\"Reply with a single word: pong\"</code>\n </div>\n {testResult && (\n <div className={cn('minimax-test-result', testResult.ok ? 'ok' : 'err')}>\n {testResult.ok ? <CheckCircle2 size={14} /> : <AlertTriangle size={14} />}\n <div className=\"minimax-test-body\">\n {testResult.ok ? (\n <>\n <div className=\"minimax-test-line\">\n <strong>model:</strong> <code>{testResult.model}</code> ·{' '}\n <strong>finish:</strong> {testResult.finishReason ?? '—'}\n </div>\n {testResult.content && (\n <div className=\"minimax-test-content\">\n <code>{testResult.content}</code>\n </div>\n )}\n {testResult.usage && (\n <div className=\"minimax-test-usage\">\n <strong>usage:</strong> total{' '}\n <code>{testResult.usage.total_tokens ?? '?'}</code> · prompt{' '}\n <code>{testResult.usage.prompt_tokens ?? '?'}</code> · completion{' '}\n <code>{testResult.usage.completion_tokens ?? '?'}</code>\n {testResult.usage.prompt_tokens_details?.cached_tokens != null && (\n <> · cached <code>{testResult.usage.prompt_tokens_details.cached_tokens}</code></>\n )}\n </div>\n )}\n </>\n ) : (\n <pre>{testResult.message ?? testResult.error ?? 'unknown error'}</pre>\n )}\n </div>\n </div>\n )}\n </Card>\n )}\n </div>\n );\n}\n\n// ─── Sub-components ────────────────────────────────────────────────────────\n\nfunction Stat({ label, value, hint }: { label: string; value: string; hint?: string }) {\n return (\n <div className=\"stat\">\n <div className=\"stat-label\">{label}</div>\n <div className=\"stat-value\">{value}</div>\n {hint && <div className=\"stat-hint\">{hint}</div>}\n </div>\n );\n}\n\nfunction ModelQuotaCard({ model }: { model: RemainsModel }) {\n const fivePct = clamp(model.current_interval_remaining_percent ?? 0, 0, 100);\n const weekPct = clamp(model.current_weekly_remaining_percent ?? 0, 0, 100);\n const fiveConsumed = clamp(100 - fivePct, 0, 100);\n const weekConsumed = clamp(100 - weekPct, 0, 100);\n return (\n <Card id={`minimax-model-${model.model_name}`} className=\"minimax-model-card\">\n <div className=\"minimax-model-head\">\n <div className=\"minimax-model-name\">{model.model_name}</div>\n <div\n className={cn(\n 'minimax-model-status',\n fivePct < 25 || weekPct < 25 ? 'is-warn' : 'is-ok'\n )}\n >\n {model.current_interval_status === 1 ? 'active' : 'idle'} ·{' '}\n {model.current_weekly_status === 1 ? 'week active' : 'week idle'}\n </div>\n </div>\n\n <div className=\"minimax-quota-rows\">\n <QuotaBar\n icon={<Activity size={12} />}\n label=\"5-hour rolling\"\n remainingPct={fivePct}\n consumedPct={fiveConsumed}\n used={model.current_interval_usage_count ?? 0}\n total={model.current_interval_total_count ?? 0}\n resetIn={model.intervalResetInHuman}\n resetISO={model.endTimeISO}\n />\n <QuotaBar\n icon={<Calendar size={12} />}\n label=\"Weekly\"\n remainingPct={weekPct}\n consumedPct={weekConsumed}\n used={model.current_weekly_usage_count ?? 0}\n total={model.current_weekly_total_count ?? 0}\n resetIn={model.weeklyResetInHuman}\n resetISO={model.weeklyEndTimeISO}\n />\n </div>\n </Card>\n );\n}\n\nfunction QuotaBar({\n icon,\n label,\n remainingPct,\n consumedPct,\n used,\n total,\n resetIn,\n resetISO,\n}: {\n icon: React.ReactNode;\n label: string;\n remainingPct: number;\n consumedPct: number;\n used: number;\n total: number;\n resetIn?: string;\n resetISO?: string;\n}) {\n const tone = remainingPct >= 75 ? 'good' : remainingPct >= 25 ? 'warn' : 'low';\n return (\n <div className={`minimax-quota-row is-${tone}`}>\n <div className=\"minimax-quota-head\">\n <span className=\"minimax-quota-label\">\n {icon} {label}\n </span>\n <span className=\"minimax-quota-remaining\">{remainingPct}% remaining</span>\n </div>\n <div className=\"minimax-bar\">\n <div\n className=\"minimax-bar-fill\"\n style={{ width: `${consumedPct}%` }}\n aria-label={`${consumedPct}% consumed`}\n />\n </div>\n <div className=\"minimax-quota-meta\">\n <span>\n <strong>{used}</strong> / {total || '—'} requests\n </span>\n <span title={resetISO}>\n {resetIn ? `resets in ${resetIn}` : '—'}\n </span>\n </div>\n </div>\n );\n}\n\nfunction clamp(n: number, lo: number, hi: number) {\n return Math.max(lo, Math.min(hi, n));\n}\n\nfunction relativeTime(ts: number): string {\n const ms = Date.now() - ts;\n if (ms < 5_000) return 'just now';\n if (ms < 60_000) return `${Math.floor(ms / 1000)}s ago`;\n if (ms < 3_600_000) return `${Math.floor(ms / 60_000)}m ago`;\n return `${Math.floor(ms / 3_600_000)}h ago`;\n}\n\n// ─── Onboarding wizard ──────────────────────────────────────────────────\n\ntype OnboardingProps = {\n step: number;\n setStep: (n: number) => void;\n keyDraft: string;\n setKeyDraft: (s: string) => void;\n showKey: boolean;\n setShowKey: React.Dispatch<React.SetStateAction<boolean>>;\n verifying: boolean;\n verifyResult: TestResult | null;\n onVerify: () => void;\n onSkip: () => void;\n onManualKeySave: () => void;\n savingKey: boolean;\n status: Status;\n};\n\n/**\n * 4-step first-run wizard:\n * 0. Welcome — what the page does, what the user needs.\n * 1. Get a key — link to platform.minimax.io + how to find it.\n * 2. Paste — input with show/hide + \"Test key\" button.\n * 3. Done — confirms the save + \"View your quota\" CTA.\n *\n * The wizard writes to opencode's canonical auth store at\n * ~/.local/share/opencode/auth.json (via /api/minimax/onboarding/save-key).\n */\nfunction OnboardingWizard({\n step, setStep, keyDraft, setKeyDraft, showKey, setShowKey,\n verifying, verifyResult, onVerify, onSkip, onManualKeySave,\n savingKey, status,\n}: OnboardingProps) {\n return (\n <div className=\"view-container view-minimax-onboarding\">\n <header className=\"view-header\">\n <div className=\"view-header-titles\">\n <h1 className=\"view-title\">\n <Sparkles size={20} style={{ verticalAlign: 'text-bottom', marginRight: 6 }} />\n Set up MiniMax Token Plan tracking\n </h1>\n <p className=\"view-subtitle\">\n We'll read your Subscription Key from opencode's auth store and show your remaining\n 5-hour + weekly quota for every MiniMax model.\n </p>\n </div>\n <div className=\"view-header-actions\">\n <Button variant=\"ghost\" size=\"sm\" onClick={onSkip}>\n <X size={14} /> Skip for now\n </Button>\n </div>\n </header>\n\n {/* ── Stepper ────────────────────────────────────────────── */}\n <div className=\"minimax-wizard-stepper\">\n {(['Welcome', 'Get a key', 'Paste & test', 'Done']).map((label, i) => (\n <div\n key={label}\n className={cn(\n 'minimax-wizard-step',\n i === step && 'is-current',\n i < step && 'is-done',\n i > step && 'is-todo',\n )}\n >\n <div className=\"minimax-wizard-step-bullet\">\n {i < step ? <CircleCheck size={14} /> : i + 1}\n </div>\n <div className=\"minimax-wizard-step-label\">{label}</div>\n </div>\n ))}\n </div>\n\n {/* ── Step content ────────────────────────────────────────── */}\n <Card id=\"minimax-wizard-card\">\n {step === 0 && (\n <div className=\"minimax-wizard-body\">\n <h3 className=\"minimax-wizard-title\">Welcome</h3>\n <p className=\"minimax-wizard-prose\">\n BizarHarness can show you how much of your MiniMax Token Plan\n quota you have left — both the <strong>5-hour rolling</strong>\n and the <strong>weekly</strong> windows — for each model. To\n do that it needs your Subscription Key. The key never leaves\n this machine.\n </p>\n <ul className=\"minimax-wizard-list\">\n <li>Stored in <code>~/.local/share/opencode/auth.json</code> (same place opencode's <code>/connect</code> writes).</li>\n <li>Read fresh on every dashboard load — you can revoke it any time from the MiniMax console.</li>\n <li>Used only for <code>GET /v1/token_plan/remains</code> and the chat-completions probe; never logged in full.</li>\n </ul>\n <div className=\"minimax-wizard-actions\">\n <Button onClick={() => setStep(1)} variant=\"primary\" size=\"md\">\n Get started <span style={{ marginLeft: 6 }}>→</span>\n </Button>\n </div>\n </div>\n )}\n\n {step === 1 && (\n <div className=\"minimax-wizard-body\">\n <h3 className=\"minimax-wizard-title\">Get your Subscription Key</h3>\n <p className=\"minimax-wizard-prose\">\n Go to the MiniMax console and copy your Subscription Key. The\n key starts with <code>sk-cp-</code> (or <code>sk-ant-</code>{' '}\n if you're using the Anthropic-format surface). It's about\n 120 characters long.\n </p>\n <ol className=\"minimax-wizard-list\">\n <li>Open{' '}\n <a\n href=\"https://platform.minimax.io/user-center/payment/token-plan\"\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"minimax-wizard-link\"\n >\n <ExternalLink size={12} /> platform.minimax.io/user-center/payment/token-plan\n </a>\n </li>\n <li>Click <strong>Copy Subscription Key</strong>.</li>\n <li>Come back here and paste it in the next step.</li>\n </ol>\n <p className=\"minimax-wizard-prose minimax-wizard-prose--muted\">\n Already have the key? You can also set the env var{' '}\n <code>MINIMAX_API_KEY</code> or add it to{' '}\n <code>opencode.json</code> under{' '}\n <code>provider.minimax.options.apiKey</code>.\n </p>\n <div className=\"minimax-wizard-actions\">\n <Button variant=\"secondary\" size=\"md\" onClick={() => setStep(0)}>← Back</Button>\n <Button variant=\"primary\" size=\"md\" onClick={() => setStep(2)}>\n I have my key <span style={{ marginLeft: 6 }}>→</span>\n </Button>\n </div>\n </div>\n )}\n\n {step === 2 && (\n <div className=\"minimax-wizard-body\">\n <h3 className=\"minimax-wizard-title\">Paste & test</h3>\n <p className=\"minimax-wizard-prose\">\n Paste your Subscription Key below. We'll test it against the\n real API (one tiny chat call) and then save it to opencode's\n auth store. If the test fails you'll see exactly why.\n </p>\n <div className=\"minimax-key-row\">\n <div className=\"minimax-key-input-wrap\">\n <KeyRound size={12} className=\"minimax-key-icon\" />\n <input\n type={showKey ? 'text' : 'password'}\n value={keyDraft}\n onChange={(e) => setKeyDraft(e.target.value)}\n placeholder=\"eyJhbGciOi... or sk-cp-...\"\n spellCheck={false}\n autoComplete=\"off\"\n className=\"minimax-key-input\"\n autoFocus\n />\n <button\n type=\"button\"\n onClick={() => setShowKey((v) => !v)}\n className=\"minimax-key-toggle\"\n aria-label={showKey ? 'Hide key' : 'Show key'}\n title={showKey ? 'Hide key' : 'Show key'}\n >\n {showKey ? <EyeOff size={13} /> : <Eye size={13} />}\n </button>\n </div>\n </div>\n {verifyResult && !verifyResult.ok && (\n <div className=\"minimax-wizard-error\">\n <AlertTriangle size={14} />\n <span>\n <strong>Verification failed:</strong> {verifyResult.message ?? verifyResult.error}\n </span>\n </div>\n )}\n <div className=\"minimax-wizard-actions\">\n <Button variant=\"secondary\" size=\"md\" onClick={() => setStep(1)}>← Back</Button>\n <Button\n variant=\"primary\"\n size=\"md\"\n onClick={onVerify}\n disabled={verifying || !keyDraft.trim()}\n >\n {verifying ? <Loader2 size={14} className=\"spin\" /> : <ShieldCheck size={14} />}\n {verifying ? 'Testing…' : 'Test & save key'}\n </Button>\n </div>\n <p className=\"minimax-wizard-prose minimax-wizard-prose--muted\">\n Don't want to test first?{' '}\n <a\n href=\"#\"\n onClick={(e) => { e.preventDefault(); onManualKeySave(); }}\n className=\"minimax-wizard-link\"\n >\n Save without testing\n </a>\n </p>\n </div>\n )}\n\n {step === 3 && (\n <div className=\"minimax-wizard-body\">\n <h3 className=\"minimax-wizard-title\">\n <CircleCheck size={18} style={{ verticalAlign: 'text-bottom', marginRight: 6 }} />\n All set\n </h3>\n <p className=\"minimax-wizard-prose\">\n The key works and is saved. Reloading the dashboard so you\n can see your live 5-hour + weekly quota.\n </p>\n <div className=\"minimax-wizard-actions\">\n <Button variant=\"primary\" size=\"md\" onClick={() => window.location.reload()}>\n View your quota →\n </Button>\n </div>\n </div>\n )}\n\n {/* ── Status footer ─────────────────────────────────────────── */}\n <div className=\"minimax-wizard-footer\">\n <ShieldCheck size={11} />\n <span>Key is written to <code>~/.local/share/opencode/auth.json</code> with mode 0600.</span>\n </div>\n </Card>\n </div>\n );\n}\n","// src/components/background/TmuxAttachCard.tsx — per-instance tmux attach card\n// v3.22.0\n//\n// Shows the tmux session name, a \"Copy attach command\" button, and\n// an \"Open in terminal\" button that POSTs to /api/background/:id/open-terminal.\n// When tmux is missing on the host, shows a friendly warning instead.\n\nimport { useState } from 'react';\nimport { Copy, Terminal, AlertTriangle } from 'lucide-react';\nimport { Button } from '../Button';\nimport { Card } from '../Card';\nimport { useToast } from '../Toast';\nimport { api } from '../../lib/api';\nimport type { BgInstance } from '../../lib/types';\n\ntype TmuxAttachCardProps = {\n instance: BgInstance;\n};\n\nexport function TmuxAttachCard({ instance }: TmuxAttachCardProps) {\n const toast = useToast();\n const [opening, setOpening] = useState(false);\n\n const sessionName = instance.tmuxSession;\n const attachCommand = sessionName ? `tmux attach -t ${sessionName}` : null;\n\n const copyCommand = async () => {\n if (!attachCommand) return;\n try {\n await navigator.clipboard.writeText(attachCommand);\n toast.success('Attach command copied');\n } catch {\n toast.error('Could not copy to clipboard');\n }\n };\n\n const openTerminal = async () => {\n if (!instance.instanceId || !sessionName) return;\n setOpening(true);\n try {\n const result = await api.post<{ ok: boolean; command: string; error?: string }>(\n `/background/${encodeURIComponent(instance.instanceId)}/open-terminal`,\n { emulator: 'system' },\n );\n if (result.ok) {\n toast.success('Opening terminal…');\n } else {\n toast.error(result.error || 'Failed to open terminal');\n // Fallback: copy the command so the user can paste it manually.\n if (attachCommand) {\n try {\n await navigator.clipboard.writeText(attachCommand);\n toast.success('Command copied to clipboard');\n } catch { /* noop */ }\n }\n }\n } catch (err) {\n toast.error(`Failed: ${(err as Error).message}`);\n // Fallback: copy command on network error.\n if (attachCommand) {\n try {\n await navigator.clipboard.writeText(attachCommand);\n toast.success('Command copied to clipboard');\n } catch { /* noop */ }\n }\n } finally {\n setOpening(false);\n }\n };\n\n // Don't render anything if there's no tmux session to attach to.\n if (!sessionName) {\n return (\n <Card variant=\"outlined\" className=\"bg-tmux-card bg-tmux-card-warn\">\n <div className=\"bg-tmux-card-header\">\n <AlertTriangle size={14} />\n <span>No tmux session</span>\n </div>\n <p className=\"bg-tmux-hint muted\">\n This instance does not have a tmux session attached.\n Sessions are created automatically when a background agent starts.\n </p>\n </Card>\n );\n }\n\n return (\n <Card variant=\"outlined\" className=\"bg-tmux-card\">\n <div className=\"bg-tmux-card-header\">\n <Terminal size={14} />\n <span>tmux session</span>\n {instance.tmuxActive !== false ? (\n <span className=\"badge badge-success\">live</span>\n ) : (\n <span className=\"badge badge-warning\">inactive</span>\n )}\n </div>\n\n <code className=\"mono bg-tmux-session-name\">{sessionName}</code>\n\n <p className=\"muted bg-tmux-hint\">\n Attach to the agent's tmux session from a terminal on the host\n running the dashboard.\n </p>\n\n <div className=\"bg-tmux-card-actions\">\n <Button variant=\"ghost\" size=\"sm\" onClick={copyCommand} title=\"Copy attach command\">\n <Copy size={14} /> Copy\n </Button>\n <Button\n variant=\"primary\"\n size=\"sm\"\n onClick={openTerminal}\n loading={opening}\n title=\"Open in system terminal\"\n >\n <Terminal size={14} /> Open terminal\n </Button>\n </div>\n </Card>\n );\n}\n","// src/views/BackgroundAgents.tsx — dashboard tab listing active background-agent\n// instances (status === 'pending' | 'running'). Polls /api/background every 5s\n// as a safety net and refreshes on `background:change` WS events for near-real-time\n// updates. Per-instance actions: View live output (auto-refreshing modal), Open\n// in tmux (shows attach command), Kill (with confirm dialog).\nimport { useCallback, useEffect, useRef, useState, type UIEvent } from 'react';\nimport {\n Activity as ActivityIcon,\n Copy,\n Eye,\n Loader2,\n RefreshCw,\n Terminal,\n Trash2,\n} from 'lucide-react';\nimport { Button } from '../components/Button';\nimport { Card } from '../components/Card';\nimport { EmptyState } from '../components/EmptyState';\nimport { Spinner } from '../components/Spinner';\nimport { useModal } from '../components/Modal';\nimport { useToast } from '../components/Toast';\nimport { BgStatusBadge } from '../components/BgStatusBadge';\nimport { openKillConfirmDialog } from '../components/KillConfirmDialog';\nimport { TmuxAttachCard } from '../components/background/TmuxAttachCard';\nimport { api } from '../lib/api';\nimport { Ws } from '../lib/ws';\nimport { cn, formatTime, truncate } from '../lib/utils';\nimport type {\n BackgroundListResponse,\n BackgroundOutputResponse,\n BackgroundTmuxResponse,\n BgInstance,\n Settings,\n Snapshot,\n} from '../lib/types';\n\ntype Props = {\n snapshot: Snapshot;\n settings: Settings;\n activeTab: string;\n setActiveTab: (id: string) => void;\n refreshSnapshot: () => Promise<void>;\n};\n\nconst POLL_INTERVAL_MS = 5_000;\nconst OUTPUT_REFRESH_MS = 2_000;\nconst PROMPT_TRUNCATE = 120;\n\nfunction isActive(b: BgInstance): boolean {\n return b.status === 'pending' || b.status === 'running';\n}\n\nfunction formatDuration(ms: number): string {\n if (!Number.isFinite(ms) || ms < 0) return '—';\n const total = Math.floor(ms / 1000);\n const h = Math.floor(total / 3600);\n const m = Math.floor((total % 3600) / 60);\n const s = total % 60;\n if (h > 0) return `${h}h ${m}m ${s}s`;\n if (m > 0) return `${m}m ${s}s`;\n return `${s}s`;\n}\n\nexport function BackgroundAgents(_props: Props) {\n const toast = useToast();\n const modal = useModal();\n const [instances, setInstances] = useState<BgInstance[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [, setTick] = useState(0);\n\n const load = useCallback(async () => {\n try {\n const res = await api.get<BackgroundListResponse>('/background');\n setInstances(Array.isArray(res?.instances) ? res.instances : []);\n setError(null);\n } catch (err) {\n setError((err as Error)?.message || 'Failed to load background agents.');\n } finally {\n setLoading(false);\n }\n }, []);\n\n // Initial load + polling safety net.\n useEffect(() => {\n load();\n const id = setInterval(load, POLL_INTERVAL_MS);\n return () => clearInterval(id);\n }, [load]);\n\n // 1s tick to keep the duration strings fresh.\n useEffect(() => {\n const id = setInterval(() => setTick((t) => (t + 1) % 1_000_000), 1000);\n return () => clearInterval(id);\n }, []);\n\n // WS subscription — refetch on any background:change / cleanup event.\n // Matches the Settings.tsx pattern of opening a private WS instance.\n // Acceptable because background change volume is low and the dashboard\n // already creates parallel WS connections for other tabs.\n useEffect(() => {\n const ws = new Ws();\n const off = ws.on((msg) => {\n const t = (msg as { type?: string }).type;\n if (t === 'background:change' || t === 'background:cleanup') {\n load();\n }\n });\n return () => {\n off();\n ws.close();\n };\n }, [load]);\n\n const active = instances.filter(isActive);\n\n // ─── Handlers ─────────────────────────────────────────────────────────\n\n const onOpenOutput = (b: BgInstance) => {\n openOutputModal(modal, b);\n };\n\n const onOpenTmux = async (b: BgInstance) => {\n try {\n const info = await api.get<BackgroundTmuxResponse>(\n `/background/${encodeURIComponent(b.instanceId)}/tmux`,\n );\n openTmuxModal(modal, info);\n } catch (err) {\n toast.error(`Tmux info failed: ${(err as Error).message}`);\n }\n };\n\n const onKill = (b: BgInstance) => {\n openKillConfirmDialog(modal, toast, b.instanceId, b.agent || b.prompt, () => {\n // Optimistic remove — the WS broadcast + polling safety net will reconcile.\n setInstances((cur) => cur.filter((x) => x.instanceId !== b.instanceId));\n });\n };\n\n // ─── Render ───────────────────────────────────────────────────────────\n\n if (loading) {\n return (\n <div className=\"bg-active-view\">\n <div className=\"bg-active-loading\">\n <Spinner size=\"md\" />\n <span>Loading background agents…</span>\n </div>\n </div>\n );\n }\n\n if (error) {\n return (\n <div className=\"bg-active-view\">\n <EmptyState\n icon={<ActivityIcon size={32} />}\n title=\"Couldn't load background agents\"\n message={error}\n action={\n <Button variant=\"primary\" onClick={load}>\n <RefreshCw size={14} /> Retry\n </Button>\n }\n />\n </div>\n );\n }\n\n return (\n <div className=\"bg-active-view\">\n <div className=\"bg-active-header\">\n <div className=\"bg-active-header-text\">\n <h2 className=\"bg-active-title\">Active Background Agents</h2>\n <p className=\"bg-active-subtitle muted\">\n {active.length} active · {instances.length} total in store\n </p>\n </div>\n <Button variant=\"ghost\" size=\"sm\" onClick={load} title=\"Refresh now\">\n <RefreshCw size={14} /> Refresh\n </Button>\n </div>\n\n {active.length === 0 ? (\n <EmptyState\n icon={<ActivityIcon size={32} />}\n title=\"No active background agents\"\n message=\"Spawn one from the Agents tab or via the bizar_spawn_background tool.\"\n />\n ) : (\n <div className=\"bg-active-list\">\n {active.map((b) => (\n <BackgroundAgentCard\n key={b.instanceId}\n inst={b}\n onViewOutput={() => onOpenOutput(b)}\n onOpenTmux={() => onOpenTmux(b)}\n onKill={() => onKill(b)}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\n// ─── Per-instance card ─────────────────────────────────────────────────────\n\nfunction BackgroundAgentCard({\n inst,\n onViewOutput,\n onOpenTmux,\n onKill,\n}: {\n inst: BgInstance;\n onViewOutput: () => void;\n onOpenTmux: () => void;\n onKill: () => void;\n}) {\n const startedMs = typeof inst.startedAt === 'number' ? inst.startedAt : 0;\n const startedLabel = startedMs ? formatTime(startedMs) : '—';\n const durationMs = startedMs ? Date.now() - startedMs : 0;\n const prompt = truncate(inst.prompt, PROMPT_TRUNCATE);\n\n return (\n <Card className=\"bg-active-card\" variant=\"elevated\">\n <div className=\"bg-active-card-top\">\n <div className=\"bg-active-card-id\">\n <code className=\"mono\">{inst.instanceId}</code>\n <BgStatusBadge status={inst.status || 'pending'} dot />\n </div>\n <div className=\"bg-active-card-agent\">\n <span className=\"bg-active-card-agent-label\">Agent</span>\n <span className=\"bg-active-card-agent-name\">{inst.agent || 'unknown'}</span>\n </div>\n </div>\n\n {prompt && <div className=\"bg-active-prompt\">{prompt}</div>}\n\n {inst.currentStep && (\n <div className=\"bg-active-step\">\n <span className=\"bg-active-step-label\">Step:</span>\n <span className=\"bg-active-step-value\">{inst.currentStep}</span>\n </div>\n )}\n\n {typeof inst.progress === 'number' && (\n <div className=\"progress-bar\" aria-label=\"Progress\">\n <div\n className=\"progress-fill\"\n style={{ width: `${Math.max(0, Math.min(100, inst.progress))}%` }}\n />\n <span className=\"progress-label\">{Math.round(inst.progress)}%</span>\n </div>\n )}\n\n <div className=\"bg-active-meta\">\n <span title={startedLabel}>\n <strong>Started:</strong> {startedLabel}\n </span>\n <span>\n <strong>Duration:</strong> {formatDuration(durationMs)}\n </span>\n <span>\n <strong>Tool calls:</strong> {inst.toolCallCount ?? 0}\n </span>\n {inst.tmuxSession && (\n <span className={cn(inst.tmuxActive && 'bg-active-meta-tmux-live')}>\n <strong>tmux:</strong> <code className=\"mono\">{inst.tmuxSession}</code>\n {inst.tmuxActive ? ' · live' : ''}\n </span>\n )}\n </div>\n\n <div className=\"bg-active-actions\">\n <Button variant=\"secondary\" size=\"sm\" onClick={onViewOutput}>\n <Eye size={14} /> View output\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={onOpenTmux}>\n <Terminal size={14} /> Open in tmux\n </Button>\n <Button variant=\"danger\" size=\"sm\" onClick={onKill}>\n <Trash2 size={14} /> Kill\n </Button>\n </div>\n\n <TmuxAttachCard instance={inst} />\n </Card>\n );\n}\n\n// ─── Output modal (auto-refresh) ───────────────────────────────────────────\n\nfunction openOutputModal(\n modal: ReturnType<typeof useModal>,\n inst: BgInstance,\n) {\n modal.open({\n title: `Output — ${inst.agent || inst.instanceId}`,\n width: 720,\n children: <OutputModalBody instanceId={inst.instanceId} />,\n });\n}\n\nfunction OutputModalBody({ instanceId }: { instanceId: string }) {\n const toast = useToast();\n const [output, setOutput] = useState<string>('');\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [available, setAvailable] = useState(true);\n const refBottom = useRef<HTMLDivElement | null>(null);\n const refAutoscroll = useRef(true);\n\n const load = useCallback(async () => {\n try {\n const r = await api.get<BackgroundOutputResponse>(\n `/background/${encodeURIComponent(instanceId)}/output?lines=200`,\n );\n setOutput(r?.output ?? '');\n setAvailable(r?.available !== false);\n setError(null);\n } catch (err) {\n setError((err as Error)?.message || 'Failed to load output.');\n } finally {\n setLoading(false);\n }\n }, [instanceId]);\n\n useEffect(() => {\n load();\n const id = setInterval(load, OUTPUT_REFRESH_MS);\n return () => clearInterval(id);\n }, [load]);\n\n // Auto-scroll to bottom only if user is already near the bottom.\n useEffect(() => {\n if (!refAutoscroll.current) return;\n refBottom.current?.scrollIntoView({ behavior: 'auto', block: 'end' });\n }, [output]);\n\n const onScroll = (e: UIEvent<HTMLDivElement>) => {\n const el = e.currentTarget;\n const atBottom = el.scrollHeight - el.scrollTop - el.clientHeight < 24;\n refAutoscroll.current = atBottom;\n };\n\n const copy = async () => {\n try {\n await navigator.clipboard.writeText(output);\n toast.success('Output copied.');\n } catch {\n // ignore — clipboard may be unavailable in some contexts\n }\n };\n\n return (\n <div className=\"bg-output-modal\">\n <div className=\"bg-output-toolbar\">\n <span className=\"muted\">\n {available ? `${output.length} chars · auto-refresh 2s` : 'Output unavailable'}\n </span>\n <div className=\"bg-output-toolbar-actions\">\n <Button variant=\"ghost\" size=\"sm\" onClick={load} title=\"Refresh now\">\n <RefreshCw size={14} /> Refresh\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={copy} disabled={!output}>\n <Copy size={14} /> Copy\n </Button>\n </div>\n </div>\n {loading && !output ? (\n <div className=\"bg-output-loading\">\n <Loader2 size={16} className=\"spin\" /> Loading…\n </div>\n ) : error ? (\n <div className=\"bg-output-error\">{error}</div>\n ) : !output ? (\n <div className=\"bg-output-empty muted\">No output captured yet.</div>\n ) : (\n <div className=\"bg-output-scroll\" onScroll={onScroll}>\n <pre className=\"bg-output-pre mono\">\n <code>{output}</code>\n </pre>\n <div ref={refBottom} />\n </div>\n )}\n </div>\n );\n}\n\n// ─── Tmux attach modal ─────────────────────────────────────────────────────\n\nfunction openTmuxModal(\n modal: ReturnType<typeof useModal>,\n info: BackgroundTmuxResponse,\n) {\n const cmd = info.attachCommand || info.session || '';\n modal.open({\n title: 'Attach to tmux',\n width: 520,\n children: <TmuxModalBody info={info} cmd={cmd} />,\n });\n}\n\nfunction TmuxModalBody({ info, cmd }: { info: BackgroundTmuxResponse; cmd: string }) {\n const [copied, setCopied] = useState(false);\n const onCopy = async () => {\n try {\n await navigator.clipboard.writeText(cmd);\n setCopied(true);\n window.setTimeout(() => setCopied(false), 1500);\n } catch {\n /* noop */\n }\n };\n\n return (\n <div className=\"bg-tmux-modal\">\n {!cmd ? (\n <p className=\"muted\">No tmux session attached to this instance.</p>\n ) : (\n <>\n <p className=\"bg-tmux-meta\">\n {info.exists ? (\n <span className=\"badge badge-success\">session live</span>\n ) : (\n <span className=\"badge badge-warning\">\n session not running{info.reason ? ` — ${info.reason}` : ''}\n </span>\n )}\n {info.session && (\n <span className=\"bg-tmux-session muted\">\n · session <code className=\"mono\">{info.session}</code>\n </span>\n )}\n </p>\n <label className=\"field-label\">Attach command</label>\n <div className=\"bg-tmux-command-row\">\n <code className=\"bg-tmux-command mono\">{cmd}</code>\n <Button variant=\"secondary\" size=\"sm\" onClick={onCopy}>\n <Copy size={14} /> {copied ? 'Copied' : 'Copy'}\n </Button>\n </div>\n <p className=\"muted bg-tmux-hint\">\n Paste this into a terminal on the host running the dashboard. The\n dashboard itself does not open terminals.\n </p>\n </>\n )}\n </div>\n );\n}","// src/App.tsx — root shell. Wires data + contexts + tab routing.\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { Topbar, TABS } from './components/Topbar';\nimport { Sidebar } from './components/Sidebar';\nimport { ModalProvider, useModal } from './components/Modal';\nimport { ToastProvider, useToast } from './components/Toast';\nimport { SearchModal } from './components/SearchModal';\nimport { Notifications } from './components/Notifications';\nimport { CommandDialog, type DialogDescriptor } from './components/CommandDialog';\nimport { api } from './lib/api';\nimport { Ws } from './lib/ws';\nimport {\n applyTheme,\n applyThemeTokens,\n type Artifact,\n type Settings,\n type SettingsResponse,\n type Snapshot,\n type WsMessage,\n type WsStatus,\n type ProjectRecord,\n type SearchResult,\n} from './lib/types';\nimport { Overview } from './views/Overview';\nimport { Chat } from './views/Chat';\nimport { Agents } from './views/Agents';\nimport { Artifacts } from './views/Artifacts';\nimport { Tasks } from './views/Tasks';\nimport { Activity } from './views/Activity';\nimport { Config } from './views/Config';\nimport { SettingsView } from './views/Settings';\nimport { Mods } from './views/Mods';\nimport { ModView, type ModView as ModViewType } from './views/ModView';\nimport { Schedules } from './views/Schedules';\nimport { Skills } from './views/Skills';\nimport { History } from './views/History';\nimport { MiniMaxUsage } from './views/MiniMaxUsage';\nimport { BackgroundAgents } from './views/BackgroundAgents';\nimport { Spinner } from './components/Spinner';\nimport { Button } from './components/Button';\nimport { AlertTriangle, Globe, LayoutTemplate, X } from 'lucide-react';\nimport './styles/main.css';\n\ntype ViewProps = {\n snapshot: Snapshot;\n settings: Settings;\n activeTab: string;\n setActiveTab: (id: string) => void;\n refreshSnapshot: () => Promise<void>;\n /**\n * v3.3.0 — Cross-view scratch state. The \"Open in chat\" button\n * on the Agents tab sets `pendingInitialAgent`, which the Chat\n * view reads on mount (and clears). Keeps the chat a true\n * one-click handoff without needing URL state.\n */\n crossState?: CrossViewState;\n setCrossState?: (patch: Partial<CrossViewState>) => void;\n};\n\nexport type CrossViewState = {\n initialAgent?: string | null;\n};\n\nconst VIEW_MAP: Record<string, (p: ViewProps) => React.ReactNode> = {\n overview: Overview,\n chat: Chat,\n agents: Agents,\n artifacts: Artifacts,\n tasks: Tasks,\n activity: Activity,\n background: BackgroundAgents,\n config: Config,\n settings: SettingsView,\n mods: Mods,\n schedules: Schedules,\n skills: Skills,\n history: History,\n minimax: MiniMaxUsage,\n};\n\nconst VERSION = 'v3.21.0';\n\n/**\n * Render the active view. If `activeTab` matches a built-in tab id,\n * use VIEW_MAP. If it matches a mod view id (any id not in VIEW_MAP),\n * render the ModView component with that view id.\n */\nfunction renderActiveView(\n activeTab: string,\n viewProps: ViewProps,\n modViews: ModViewType[],\n reloadKey: number,\n): React.ReactNode {\n if (VIEW_MAP[activeTab]) {\n const V = VIEW_MAP[activeTab];\n return <V {...viewProps} />;\n }\n // Mod view — find by id\n const mv = modViews.find((v) => v.id === activeTab);\n if (mv) {\n return (\n <ModView\n viewId={mv.id}\n reloadKey={reloadKey}\n activeTab={viewProps.activeTab}\n setActiveTab={viewProps.setActiveTab}\n />\n );\n }\n // Fallback to Overview\n const V = VIEW_MAP.overview;\n return <V {...viewProps} />;\n}\n\nexport function App() {\n return (\n <ToastProvider>\n <ModalProvider>\n <Shell />\n </ModalProvider>\n </ToastProvider>\n );\n}\n\nfunction Shell() {\n const toast = useToast();\n const modalApi = useModal();\n const { isModalOpen } = modalApi;\n const isModalOpenRef = useRef(false);\n const [activeTab, setActiveTab] = useState<string>('overview');\n const [snapshot, setSnapshot] = useState<Snapshot | null>(null);\n const [settings, setSettings] = useState<Settings | null>(null);\n const [wsStatus, setWsStatus] = useState<WsStatus>('connecting');\n const [bootError, setBootError] = useState<string | null>(null);\n const [searchOpen, setSearchOpen] = useState(false);\n const [stuckAgents, setStuckAgents] = useState<{ name: string }[]>([]);\n const [stuckBannerDismissed, setStuckBannerDismissed] = useState(false);\n // v3.20.3 — Mod views become first-class nav entries. Fetched on mount\n // and after every mod install/uninstall/enable toggle.\n const [modViews, setModViews] = useState<ModViewType[]>([]);\n const [modViewsReloadKey, setModViewsReloadKey] = useState(0);\n const wsRef = useRef<Ws | null>(null);\n const [ws, setWs] = useState<Ws | null>(null);\n\n // Fetch installed mod views (any enabled mod with a web/index.html or\n // a views/registry.json entry). These become top-level nav tabs.\n useEffect(() => {\n let cancelled = false;\n (async () => {\n try {\n const r = await api.get<{ views: ModViewType[] }>('/mods/views');\n if (cancelled) return;\n setModViews(r.views || []);\n } catch {\n if (!cancelled) setModViews([]);\n }\n })();\n return () => { cancelled = true; };\n }, [modViewsReloadKey, snapshot?.mods]);\n\n // Re-fetch mod views when ws events arrive about mod changes.\n useEffect(() => {\n if (!ws) return;\n const off = ws.on((msg: { type?: string }) => {\n if (msg?.type === 'mod:change' || msg?.type === 'mod:enabled' || msg?.type === 'mod:installed') {\n setModViewsReloadKey((n) => n + 1);\n }\n });\n return () => off();\n }, [ws]);\n\n // Apply theme tokens\n useEffect(() => {\n if (settings?.theme) {\n applyTheme(settings.theme);\n applyThemeTokens(settings.theme);\n }\n }, [settings?.theme]);\n\n // v3.6.1 — Keep a ref in sync with isModalOpen so the keyboard handler\n // always reads the current value even between state updates and effect\n // re-runs. This closes the race window where modal.close() has cleared\n // the state but the old keyboard handler (with isModalOpen=false in\n // its closure) hasn't been replaced yet.\n useEffect(() => {\n isModalOpenRef.current = isModalOpen;\n }, [isModalOpen]);\n\n // System-mode listener\n useEffect(() => {\n if (settings?.theme?.mode !== 'system') return;\n const mql = window.matchMedia('(prefers-color-scheme: light)');\n const handler = () => applyTheme(settings.theme.mode);\n mql.addEventListener('change', handler);\n return () => mql.removeEventListener('change', handler);\n }, [settings?.theme?.mode]);\n\n // Initial fetch — runs once on mount\n useEffect(() => {\n let cancelled = false;\n const loadBootData = () =>\n Promise.all([\n api.get<Snapshot>('/snapshot').catch(() => null),\n api.get<SettingsResponse>('/settings').catch(() => null),\n api.get<{ stuck: { name: string }[] }>('/agents/stuck').catch(() => null),\n ]);\n\n const applyBootData = (\n snap: Snapshot | null,\n set: SettingsResponse | null,\n stuck: { stuck: { name: string }[] } | null,\n ) => {\n if (snap) setSnapshot(snap);\n if (set?.data) setSettings(set.data);\n if (stuck?.stuck) setStuckAgents(stuck.stuck);\n };\n\n (async () => {\n try {\n const auth = await api.probeAuthStatus();\n const [snap, set, stuck] = await loadBootData();\n if (cancelled) return;\n\n applyBootData(snap, set, stuck);\n if (snap || set) return;\n\n if (!auth.loopback) {\n setBootError('Dashboard server unreachable.');\n return;\n }\n\n await new Promise((resolve) => setTimeout(resolve, 1000));\n if (cancelled) return;\n\n const [retrySnap, retrySet, retryStuck] = await loadBootData();\n if (cancelled) return;\n\n applyBootData(retrySnap, retrySet, retryStuck);\n if (!retrySnap && !retrySet) {\n setBootError('Dashboard server unreachable.');\n }\n } catch (err) {\n if (cancelled) return;\n const msg = (err as Error)?.message ?? 'unknown error';\n setBootError(msg);\n toast.error(`Failed to load: ${msg}`);\n }\n })();\n\n return () => {\n cancelled = true;\n };\n }, [toast]);\n\n // Apply defaultTab ONCE on mount only — must NOT re-fire on toast changes\n useEffect(() => {\n let cancelled = false;\n api.get<SettingsResponse>('/settings')\n .then((set) => {\n if (cancelled) return;\n const defaultTab = set?.data?.ui?.defaultTab;\n if (defaultTab) setActiveTab(defaultTab);\n })\n .catch(() => undefined);\n return () => {\n cancelled = true;\n };\n }, []); // empty deps — runs once on mount\n\n // v3.1.0 — Periodic stuck-agent poll. Light-weight; the server does\n // the threshold math and only returns the list.\n useEffect(() => {\n let cancelled = false;\n const tick = async () => {\n try {\n const r = await api.get<{ stuck: { name: string }[] }>('/agents/stuck');\n if (!cancelled) {\n setStuckAgents((cur) => {\n const next = r.stuck || [];\n const wasEmpty = cur.length === 0;\n if (wasEmpty && next.length > 0) {\n toast.warning(`${next.length} agent${next.length === 1 ? '' : 's'} stuck`, 5000);\n }\n return next;\n });\n }\n } catch {\n /* best-effort */\n }\n };\n const id = setInterval(tick, 30_000);\n tick();\n return () => {\n cancelled = true;\n clearInterval(id);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // WebSocket lifecycle\n useEffect(() => {\n const ws = new Ws();\n wsRef.current = ws;\n setWs(ws);\n const offStatus = ws.onStatus((s) => setWsStatus(s));\n const offMsg = ws.on((msg: WsMessage) => {\n if (msg.type === 'snapshot' && 'data' in msg && msg.data) {\n setSnapshot((cur) => ({ ...(cur ?? ({} as Snapshot)), ...msg.data }));\n } else if (msg.type === 'change') {\n const m = msg;\n const file = m.path?.split('/').pop() || m.path || '';\n toast.info(`File changed: ${file}`, 2500);\n api\n .get<Snapshot>('/snapshot')\n .then((s) => setSnapshot((cur) => ({ ...(cur ?? ({} as Snapshot)), ...s })))\n .catch(() => undefined);\n } else if (msg.type === 'tasks:change') {\n const m = msg;\n setSnapshot((cur) => {\n if (!cur) return cur;\n const tasks = (cur.tasks || []).map((t) =>\n t.id === m.task.id ? m.task : t,\n );\n const exists = tasks.some((t) => t.id === m.task.id);\n return { ...cur, tasks: exists ? tasks : [m.task, ...tasks] };\n });\n } else if (msg.type === 'tasks:delete') {\n const m = msg;\n setSnapshot((cur) =>\n cur\n ? { ...cur, tasks: (cur.tasks || []).filter((t) => t.id !== m.id) }\n : cur,\n );\n } else if (msg.type === 'settings:change') {\n const m = msg;\n if (m.settings) setSettings(m.settings);\n } else if (msg.type === 'project:change') {\n // Refresh the whole snapshot to pick up the new active project\n api\n .get<Snapshot>('/snapshot')\n .then((s) => setSnapshot((cur) => ({ ...(cur ?? ({} as Snapshot)), ...s })))\n .catch(() => undefined);\n } else if (msg.type === 'agents:change' || msg.type === 'schedules:change') {\n api\n .get<Snapshot>('/snapshot')\n .then((s) => setSnapshot((cur) => ({ ...(cur ?? ({} as Snapshot)), ...s })))\n .catch(() => undefined);\n } else if (msg.type === 'agent:status' || msg.type === 'agent:restarted') {\n const m = msg;\n setSnapshot((cur) => {\n if (!cur) return cur;\n const agents = (cur.agents || []).map((a) => (a.name === m.agent.name ? m.agent : a));\n return { ...cur, agents };\n });\n } else if (msg.type === 'artifact:change') {\n // Artifacts list refreshes after any artifact mutation.\n api\n .get<{ artifacts: Artifact[] }>('/artifacts')\n .then((d) => {\n setSnapshot((cur) => (cur ? { ...cur, artifacts: d.artifacts || [] } : cur));\n })\n .catch(() => undefined);\n } else if (msg.type === 'agent:stuck') {\n const m = msg;\n setStuckAgents(m.agents || []);\n } else if (msg.type === 'dialog:show') {\n // v0.5.1: Open a command dialog received from the plugin via WS broadcast.\n const m = msg as { type: 'dialog:show'; dialog: DialogDescriptor };\n if (m.dialog) {\n modalApi.open({\n title: m.dialog.title,\n width: 520,\n children: <CommandDialog dialog={m.dialog} onClose={() => modalApi.close()} />,\n });\n }\n }\n });\n return () => {\n offStatus();\n offMsg();\n ws.close();\n setWs(null);\n };\n }, [toast]);\n\n const subscribeToWs = useCallback((cb: (msg: WsMessage) => void) => {\n if (!ws) return () => undefined;\n return ws.on(cb);\n }, [ws]);\n\n // v3.3.1 — Track recent user interactions. After any mousedown/click/\n // focusin/keydown we set a 1500ms \"safe\" window during which digit-key\n // shortcuts are suppressed. This protects against the case where a modal\n // closes on a click and the user's next key event (often a key-repeat)\n // would otherwise trigger setActiveTab(\"overview\").\n // v3.3.0 used 250ms which was too short (keyboard repeat can fire later).\n //\n // v3.5.4 (bug #4) — The safe window alone was not enough. Users were\n // still being bounced to overview after action grace windows expired\n // because the transientFocus check (activeElement === body) was nested\n // inside the safe-window branch. See the handler below for the new\n // two-gate model: (1) body/null focus ALWAYS blocks digit shortcuts;\n // (2) the safe window relaxes that block only for the first 1500ms\n // after an interaction. After the window passes, the user must\n // explicitly focus a real element before digit-key tab switches work.\n const safeUntilRef = useRef(0);\n useEffect(() => {\n const bump = () => {\n safeUntilRef.current = Date.now() + 1500;\n };\n document.addEventListener('mousedown', bump, true);\n document.addEventListener('click', bump, true);\n document.addEventListener('focusin', bump, true);\n document.addEventListener('keydown', bump, true);\n return () => {\n document.removeEventListener('mousedown', bump, true);\n document.removeEventListener('click', bump, true);\n document.removeEventListener('focusin', bump, true);\n document.removeEventListener('keydown', bump, true);\n };\n }, []);\n\n // Keyboard shortcuts\n useEffect(() => {\n const map: Record<string, string> = {};\n TABS.forEach((t, i) => {\n map[String(i + 1)] = t.id;\n });\n const handler = (e: KeyboardEvent) => {\n if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') {\n e.preventDefault();\n setSearchOpen(true);\n return;\n }\n if (e.key === '/' && !e.metaKey && !e.ctrlKey) {\n const t = (e.target as HTMLElement | null)?.tagName?.toLowerCase();\n if (t !== 'input' && t !== 'textarea' && !((e.target as HTMLElement)?.isContentEditable)) {\n e.preventDefault();\n setSearchOpen(true);\n return;\n }\n }\n // v3.2.0 — broader guard. Digit-key shortcuts must not fire while\n // the user is interacting with ANY focusable form control or a\n // modal/contentEditable region. Previously this only excluded\n // <input> and <textarea>, which let digit presses through when\n // focus was on a <select>, <button>, <label>, or contenteditable\n // node — causing mysterious tab switches (most often back to\n // \"overview\" via the `1` shortcut).\n //\n // v3.3.1 — \"click after modal close\" guard (extended). When a modal\n // closes (e.g. the user clicks \"Submit to Odin\" in the Tasks tab),\n // React portals the modal out of the DOM and the previously-focused\n // button is unmounted. Focus falls back to <body>. If the user then\n // accidentally taps a digit key (1/2/3/...) — or a key-repeat fires\n // while they're still mid-click — the handler would switch tabs.\n // The safe window is now 1500ms (up from 250ms) and covers all\n // interaction types (mousedown/click/focusin/keydown).\n //\n // v3.3.1 — transient-focus check. If active element is body/null,\n // treat it as a transient focus state (modal close → body fallback)\n // and bail. v3.5.4 (bug #4): this check is now independent of the\n // safe window — it ALWAYS applies. Previously it was only effective\n // inside the 1500ms grace window, which let digit-key presses through\n // once the window expired. The user would see themselves bounced back\n // to overview (digit `1`) after every action whose grace window had\n // already elapsed. The safe window now only relaxes the rule\n // temporarily for the action that JUST happened; it must be combined\n // with a real focus element for digit-key shortcuts to fire.\n const activeEl = document.activeElement;\n const transientFocus = !activeEl || activeEl === document.body || activeEl === document.documentElement;\n if (transientFocus) {\n // Even within the grace window, body/null focus means there is\n // no real input target — refuse to switch tabs. The user must\n // explicitly click into a focusable element (input, button, etc.)\n // to enable digit-key tab switching again.\n return;\n }\n const target = e.target as HTMLElement | null;\n const tag = target?.tagName?.toLowerCase();\n const isFormControl =\n tag === 'input' ||\n tag === 'textarea' ||\n tag === 'select' ||\n tag === 'button' ||\n tag === 'option' ||\n tag === 'label' ||\n !!target?.isContentEditable;\n // Inside a form? Even safer: walk up to check.\n let inForm = false;\n if (target && typeof target.closest === 'function') {\n inForm = !!target.closest('form, [role=\"dialog\"], [contenteditable], [data-no-key]');\n }\n // v3.5.2 — reject key-repeat events. When a user presses and holds\n // a digit key the browser fires repeated keydown events; we must only\n // act on the first (e.repeat === false). This prevents the modal-close\n // + key-repeat scenario from switching tabs after the safe window closes.\n if (e.repeat) return;\n // v3.6.1 — Check isModalOpenRef (not the closure variable) so we always\n // see the current value even between state update and effect re-run.\n if (isModalOpenRef.current) return;\n if (\n isFormControl ||\n inForm ||\n e.metaKey ||\n e.ctrlKey ||\n e.altKey ||\n e.shiftKey ||\n Date.now() < safeUntilRef.current\n )\n return;\n const id = map[e.key];\n if (id) {\n e.preventDefault();\n setActiveTab(id);\n }\n };\n document.addEventListener('keydown', handler);\n return () => document.removeEventListener('keydown', handler);\n }, []);\n\n const refreshSnapshot = useMemo(\n () => async () => {\n try {\n const s = await api.get<Snapshot>('/snapshot');\n setSnapshot((cur) => ({ ...(cur ?? ({} as Snapshot)), ...s }));\n } catch (err) {\n toast.error(`Refresh failed: ${(err as Error).message}`);\n }\n },\n [toast],\n );\n\n // v3.20.3 — Merge built-in tabs with installed mod views. Mod views\n // are appended after the built-in tabs and use the same rendering\n // surface; their tab ids are mod view ids (e.g. 'graphify:web').\n // Declared AFTER refreshSnapshot so the deps list has the right value.\n const mergedTabs = useMemo(() => {\n const modTabs = modViews.map((v) => ({\n id: v.id,\n label: v.label,\n icon: v.kind === 'iframe' ? Globe : LayoutTemplate,\n isMod: true,\n modId: v.modId,\n }));\n return [...TABS, ...modTabs];\n }, [modViews]);\n\n // Surface the underlying view for the active tab (built-in or mod).\n // Declared AFTER refreshSnapshot so its useMemo factory can capture it.\n const renderedView = useMemo(() => {\n if (snapshot && settings) {\n const viewProps: ViewProps = {\n snapshot,\n settings,\n activeTab,\n setActiveTab: setActiveTab,\n refreshSnapshot,\n };\n return renderActiveView(activeTab, viewProps, modViews, modViewsReloadKey);\n }\n return null;\n }, [activeTab, snapshot, settings, modViews, modViewsReloadKey, refreshSnapshot]);\n\n const refreshProjects = async () => {\n try {\n const r = await api.get<{ projects: ProjectRecord[]; active: string | null }>('/projects');\n setSnapshot((cur) =>\n cur ? { ...cur, projects: r.projects || [], activeProject: r.projects?.find((p) => p.id === r.active) || null } : cur,\n );\n } catch (err) {\n toast.error(`Projects refresh failed: ${(err as Error).message}`);\n }\n };\n\n const onActivateProject = async (id: string) => {\n try {\n await api.post(`/projects/${encodeURIComponent(id)}/activate`);\n // WS will fire project:change and refresh; but also reflect locally\n setSnapshot((cur) => {\n if (!cur) return cur;\n return {\n ...cur,\n activeProject: cur.projects.find((p) => p.id === id) || null,\n };\n });\n } catch (err) {\n toast.error(`Activate failed: ${(err as Error).message}`);\n }\n };\n\n const onSearchSelect = (r: SearchResult) => {\n const t = r.type;\n if (t === 'agent') setActiveTab('agents');\n else if (t === 'task') setActiveTab('tasks');\n else if (t === 'mod') setActiveTab('mods');\n else if (t === 'schedule') setActiveTab('schedules');\n else if (t === 'project') {\n const id = (r.item as ProjectRecord).id;\n onActivateProject(id);\n } else if (t === 'command') {\n // No command page; just toast\n toast.info(`/${(r.item as { name: string }).name} — run from the TUI`, 2500);\n } else if (t === 'setting') {\n // v3.0.4 — Jump to Settings view and scroll to the matching row.\n const settingId = (r.item as { id?: string; path?: string }).id\n || (r.item as { path?: string }).path\n || '';\n setActiveTab('settings');\n // Defer the scroll to allow the view to mount, then apply a brief\n // CSS highlight. We poll a few times because the Settings view\n // mounts lazily after tab switch.\n const tryScroll = (tries: number) => {\n if (tries <= 0) return;\n const el = settingId\n ? document.querySelector(`[data-setting-id=\"${CSS.escape(settingId)}\"]`)\n : null;\n if (el) {\n (el as HTMLElement).scrollIntoView({ behavior: 'smooth', block: 'center' });\n el.classList.remove('setting-flash');\n // Force reflow so the animation re-triggers on rapid jumps.\n void (el as HTMLElement).offsetWidth;\n el.classList.add('setting-flash');\n window.setTimeout(() => el.classList.remove('setting-flash'), 1500);\n } else {\n window.setTimeout(() => tryScroll(tries - 1), 80);\n }\n };\n window.setTimeout(() => tryScroll(15), 60);\n }\n };\n\n const layout = settings?.ui?.layout || 'topnav';\n const showHeader = settings?.ui?.showHeader !== false;\n\n return (\n <div className=\"app\" data-layout={layout} data-active-tab={activeTab}>\n {showHeader && (\n <Topbar\n activeTab={activeTab}\n onTabChange={setActiveTab}\n wsStatus={wsStatus}\n version={VERSION}\n activeProject={snapshot?.activeProject || null}\n projects={snapshot?.projects || []}\n onProjectChange={onActivateProject}\n onProjectsRefresh={refreshProjects}\n onOpenSearch={() => setSearchOpen(true)}\n settings={settings}\n notificationsSlot={<Notifications wsSubscribe={subscribeToWs} />}\n showTabs={layout === 'topnav'}\n extraTabs={mergedTabs}\n />\n )}\n {stuckAgents.length > 0 && !stuckBannerDismissed && (\n <div className=\"stuck-banner\" role=\"alert\">\n <AlertTriangle size={16} />\n <span>\n <strong>{stuckAgents.length}</strong> agent{stuckAgents.length === 1 ? '' : 's'} stuck:{' '}\n <span className=\"mono\">\n {stuckAgents.map((a) => a.name).join(', ')}\n </span>\n </span>\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={() => {\n setActiveTab('agents');\n setStuckBannerDismissed(true);\n }}\n >\n Review\n </Button>\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label=\"Dismiss\"\n onClick={() => setStuckBannerDismissed(true)}\n >\n <X size={14} />\n </button>\n </div>\n )}\n <div className=\"layout-body\">\n {layout !== 'topnav' && (\n <Sidebar\n tabs={mergedTabs}\n activeTab={activeTab}\n onTabChange={setActiveTab}\n />\n )}\n <main className=\"content\">\n {bootError && (\n <div className=\"boot-error\">\n <h2>Dashboard unavailable</h2>\n <p>{bootError}</p>\n <p className=\"boot-error-hint\">\n Make sure the Bizar dashboard server is running. Try{' '}\n <code>bizar-dash start</code> in your terminal.\n </p>\n </div>\n )}\n {!bootError && (!snapshot || !settings) && (\n <div className=\"loading\">\n <Spinner size=\"lg\" />\n <p>Loading Bizar…</p>\n </div>\n )}\n {renderedView}\n </main>\n </div>\n <SearchModal\n open={searchOpen}\n onClose={() => setSearchOpen(false)}\n onSelect={onSearchSelect}\n />\n </div>\n );\n}\n","// src/main.tsx — viewport-based entry: mobile or desktop\nimport { StrictMode, useEffect, useState } from 'react';\nimport { createRoot } from 'react-dom/client';\nimport { App } from './App';\nimport { MobileApp } from './MobileApp';\n// Import mobile CSS so the MobileApp renders with styles when served\n// from index.html (e.g. when the auto-redirect to /m is bypassed).\nimport './styles/main.css';\nimport './styles/mobile.css';\nimport './styles/glyphs.css';\nimport './styles/minimax-usage.css';\n\nfunction Root() {\n const [isMobile, setIsMobile] = useState(() => {\n if (typeof window === 'undefined') return false;\n return window.matchMedia('(max-width: 767px)').matches;\n });\n\n useEffect(() => {\n const mql = window.matchMedia('(max-width: 767px)');\n const handler = (e: MediaQueryListEvent) => setIsMobile(e.matches);\n mql.addEventListener('change', handler);\n return () => mql.removeEventListener('change', handler);\n }, []);\n\n return isMobile ? <MobileApp /> : <App />;\n}\n\nconst root = document.getElementById('root');\nif (!root) throw new Error('Root element #root not found');\ncreateRoot(root).render(\n <StrictMode>\n <Root />\n </StrictMode>,\n);\n"],"file":"assets/main-BB5mJurD.js"}
|