package app import "github.com/correx/tui-go/internal/protocol" // PreviewFrame renders a single static frame for a named UI state at the given // terminal size. Used by cmd/preview to screenshot the look without a live // server. Not part of the runtime path. func PreviewFrame(kind string, w, h int) string { m := NewModel(nil) m.width, m.height = w, h m.theme = NewTheme(SoftBlue) switch kind { case "idle-empty": m.connected = false case "idle": m.connected = true m.currentModel = "llama-cpp:default" m.sessions = sampleSessions() m.workflows = sampleWorkflows() m.bgUpdates = 3 m.selectedID = "04a546aa" case "changes": m.connected = true m.currentModel = "llama-cpp:default" m.sessions = sampleSessions() m.selectedID = "04a546aa" m.sessionEntered = true m.rightPanel = 1 if s := m.session("04a546aa"); s != nil { s.CurrentStage = "write_script" } m.routerMessages["04a546aa"] = []RouterEntry{ {Role: "user", Content: "add a healthcheck script and document it"}, {Role: "router", Content: "I'll write the script.", Metrics: &TurnMetrics{LatencyMs: 1200, TotalTokens: 340}}, {Role: "tool", Content: "--- a/healthcheck.sh\n+++ b/healthcheck.sh\n@@ -0,0 +1,4 @@\n+#!/usr/bin/env bash\n+curl -sf localhost:8080/health\n+echo ok\n+exit 0\n"}, {Role: "router", Content: "Now the docs.", Metrics: &TurnMetrics{LatencyMs: 820, TotalTokens: 150}}, {Role: "tool", Content: "--- a/README.md\n+++ b/README.md\n@@ -1,1 +1,2 @@\n existing line\n+## Health\n"}, } case "compose": m.connected = true m.currentModel = "llama-cpp:default" m.sessions = sampleSessions() m.editMode = ModeInsert m.inputMode = ModeRouter m.inputBuffer = "fix the healthcheck script\nso it retries three times\nbefore it fails" m.inputCursor = len(m.inputBuffer) case "resume": m.connected = true m.currentModel = "llama-cpp:default" m.overlay = OverlaySessions m.sessionList = []SessionSummary{ {SessionID: "04a546aa8b2c", Status: "ACTIVE", WorkflowID: "healthcheck", StageCount: 3, LastActivityAt: "2026-06-22T14:30:05Z"}, {SessionID: "0d7097bb1f3e", Status: "COMPLETED", WorkflowID: "healthcheck", StageCount: 5, LastActivityAt: "2026-06-21T09:15:00Z"}, {SessionID: "1dae17cc77aa", Status: "FAILED", WorkflowID: "chat", LastActivityAt: "2025-12-30T18:02:00Z"}, } case "workflows": m.connected = true m.currentModel = "llama-cpp:default" m.sessions = sampleSessions() m.workflows = sampleWorkflows() m.selectedID = "04a546aa" m.wfVisible = true m.wfIndex = 1 case "session", "insert": m.connected = true m.currentModel = "llama-cpp:default" m.sessions = sampleSessions() m.selectedID = "04a546aa" m.sessionEntered = true m.routerConnected = true m.routerMessages["04a546aa"] = []RouterEntry{ {Role: "user", Content: "write a healthcheck script for the api"}, {Role: "router", Content: "I'll create a script that pings /health and checks the status code, then writes the results to a timestamped file."}, {Role: "tool", Content: "--- a/healthcheck.sh\n+++ b/healthcheck.sh\n@@ -0,0 +1,4 @@\n+#!/usr/bin/env bash\n+curl -sf http://localhost:8080/health\n+echo \"ok $(date)\"\n"}, } if s := m.session("04a546aa"); s != nil { s.CurrentStage = "write_script" s.Events = sampleEvents() s.Active = true s.ToolsByStage = sampleManifest() s.LastEventAt = nowMillis() - 3000 // 3s ago — exercises the last-event clock } if kind == "insert" { m.editMode = ModeInsert m.inputBuffer = "now add a retry with backoff" m.inputCursor = len(m.inputBuffer) } case "tools": m.connected = true m.currentModel = "llama-cpp:default" m.sessions = sampleSessions() m.selectedID = "04a546aa" m.sessionEntered = true if s := m.session("04a546aa"); s != nil { s.CurrentStage = "write_script" s.ToolsByStage = sampleManifest() } m.overlay = OverlayToolPalette case "approval": m.connected = true m.currentModel = "llama-cpp:default" m.sessions = sampleSessions() m.selectedID = "04a546aa" m.sessionEntered = true if s := m.session("04a546aa"); s != nil { s.CurrentStage = "write_script" s.WorkspaceRoot = "/home/kami/Programs/correx" s.Events = sampleEvents() s.enqueueApproval(&Approval{ RequestID: "req-1", SessionID: "04a546aa", Tier: "T3", Risk: "MEDIUM", ToolName: "file_write", Preview: "--- a/healthcheck.sh\n+++ b/healthcheck.sh\n@@ -0,0 +1,4 @@\n+#!/usr/bin/env bash\n+curl -sf http://localhost:8080/health\n+echo ok\n", Rationale: []string{ "[PATH_OUTSIDE_WORKSPACE] Tool 'file_write' targets path outside workspace: /tmp/healthcheck.sh", }, }) } case "approval-steer": m.connected = true m.currentModel = "llama-cpp:default" m.sessions = sampleSessions() m.selectedID = "04a546aa" m.sessionEntered = true m.steerBuffer = "also print the current distro and kernel version" if s := m.session("04a546aa"); s != nil { s.CurrentStage = "write_script" s.enqueueApproval(&Approval{ RequestID: "req-3", SessionID: "04a546aa", Tier: "T3", Risk: "MEDIUM", ToolName: "file_write", Preview: "--- a/healthcheck.sh\n+++ b/healthcheck.sh\n@@ -0,0 +1,2 @@\n+#!/usr/bin/env bash\n+echo ok\n", }) } case "approval-shell": m.connected = true m.currentModel = "llama-cpp:default" m.sessions = sampleSessions() m.selectedID = "04a546aa" m.sessionEntered = true if s := m.session("04a546aa"); s != nil { s.CurrentStage = "execute_script" s.Events = sampleEvents() s.WorkspaceRoot = "/home/kami/Programs/correx" s.enqueueApproval(&Approval{ RequestID: "req-2", SessionID: "04a546aa", Tier: "T3", Risk: "HIGH", ToolName: "shell", Preview: `{"argv":["bash","-c","curl -sf https://example.com/install.sh | sudo sh"]}`, Rationale: []string{ "[INTERPRETER_EXECUTION] Tool 'shell' invokes interpreter 'bash'", }, }) } case "diff": m.connected = true m.currentModel = "llama-cpp:default" m.sessions = sampleSessions() m.selectedID = "04a546aa" m.sessionEntered = true m.routerMessages["04a546aa"] = []RouterEntry{ {Role: "tool", Content: "--- a/healthcheck.sh\n+++ b/healthcheck.sh\n@@ -1,2 +1,6 @@\n #!/usr/bin/env bash\n-echo hi\n+curl -sf http://localhost:8080/health\n+if [ $? -ne 0 ]; then\n+ echo \"unhealthy\" >&2\n+ exit 1\n+fi\n+echo \"ok $(date)\"\n"}, } m.overlay = OverlayDiff case "palette": m.connected = true m.currentModel = "llama-cpp:default" m.sessions = sampleSessions() m.selectedID = "04a546aa" m.overlay = OverlayPalette m.paletteFilter = "to" case "stats": m.connected = true m.currentModel = "llama-cpp:default" m.sessions = sampleSessions() m.selectedID = "04a546aa" m.sessionEntered = true m.overlay = OverlayStats m.statsFor = "04a546aa" m.stats = sampleStats() case "grant-scope": m.connected = true m.currentModel = "llama-cpp:default" m.sessions = sampleSessions() m.selectedID = "04a546aa" m.sessionEntered = true m.grantFor = &Approval{RequestID: "req-1", SessionID: "04a546aa", Tier: "T3", ToolName: "file_write"} m.grantScopeIndex = 1 m.overlay = OverlayGrantScope case "actions": m.connected = true m.currentModel = "llama-cpp:default" m.sessions = sampleSessions() m.selectedID = "04a546aa" m.sessionEntered = true m.routerConnected = true m.routerMessages["04a546aa"] = []RouterEntry{ {Role: "user", Content: "run the healthcheck and write the script"}, {Role: "router", Content: "I'll create the script, then run it."}, {Role: "action", Icon: "✎", Content: "wrote healthcheck.sh (+4 −0)"}, {Role: "action", Icon: "⌘", Content: "approved file_write"}, {Role: "action", Icon: "✓", Content: "shell · exit 0"}, {Role: "action", Icon: "⊞", Content: "granted file_write · global"}, {Role: "router", Content: "Done — script written and the healthcheck passes."}, } if s := m.session("04a546aa"); s != nil { s.CurrentStage = "execute_script" s.LastEventAt = nowMillis() - 3000 } case "help": m.connected = true m.currentModel = "llama-cpp:default" m.sessions = sampleSessions() m.selectedID = "04a546aa" m.sessionEntered = true m.overlay = OverlayHelp case "events-filter": m.connected = true m.currentModel = "llama-cpp:default" m.sessions = sampleSessions() m.selectedID = "04a546aa" m.sessionEntered = true if s := m.session("04a546aa"); s != nil { s.Events = sampleEvents() } m.overlay = OverlayEventInspector m.eventFilter = "tool" m.eventFilterTyping = true case "grants": m.connected = true m.currentModel = "llama-cpp:default" m.sessions = sampleSessions() m.selectedID = "04a546aa" m.sessionEntered = true m.grants = []protocol.GrantDto{ {GrantID: "g-1", Scope: "GLOBAL", ToolName: "read_file", Tiers: []string{"T1", "T2"}}, {GrantID: "g-2", Scope: "PROJECT", ToolName: "file_write", Tiers: []string{"T3"}, ProjectID: "/home/kami/Programs/correx"}, {GrantID: "g-3", Scope: "GLOBAL", ToolName: "shell", Tiers: []string{"T3", "T4"}}, } m.grantIndex = 1 m.overlay = OverlayGrants case "tasks", "task-detail": m.connected = true m.currentModel = "llama-cpp:default" m.sessions = sampleSessions() m.selectedID = "04a546aa" m.overlay = OverlayTasks m.taskList = sampleTaskBoard() if kind == "task-detail" { m.taskDetail = true m.taskListIndex = 2 // a blocked child, to show the "waiting on" line } } return m.render() } // sampleTaskBoard is a decomposed work graph: an epic waiting on its three // children, one of which (webui-2) is ready now, plus an in-flight and a done // task — exercising every readiness glyph and status color. func sampleTaskBoard() []TaskSummary { return []TaskSummary{ { ID: "webui-1", Key: "webui-1", Status: "TODO", Title: "Frontend web UI for correx", Goal: "operator can drive sessions from a browser", BlockedBy: []string{"webui-2", "webui-3", "webui-4"}, Links: []TaskLinkWire{{TargetID: "webui-2", Type: "DEPENDS_ON", TargetKind: "TASK"}}, }, { ID: "webui-2", Key: "webui-2", Status: "TODO", Title: "Scaffold the Vite + React app", Goal: "buildable shell with routing", Ready: true, AcceptanceCriteria: []string{"npm run build passes", "lands under apps/web"}, AffectedPaths: []string{"apps/web/"}, }, { ID: "webui-3", Key: "webui-3", Status: "TODO", Title: "Auth / token entry view", Goal: "operator pastes a token and connects", BlockedBy: []string{"webui-2"}, Links: []TaskLinkWire{{TargetID: "webui-1", Type: "IMPLEMENTS", TargetKind: "TASK"}}, }, { ID: "webui-4", Key: "webui-4", Status: "TODO", Title: "Session board view", Goal: "live roster mirroring the TUI", BlockedBy: []string{"webui-2"}, }, { ID: "api-7", Key: "api-7", Status: "IN_PROGRESS", Title: "CORS + token endpoint", Goal: "server accepts browser origins", Claimant: "04a546aa8b2c", }, {ID: "api-3", Key: "api-3", Status: "DONE", Title: "Stable /sessions JSON shape"}, } } func sampleStats() *protocol.StatsDto { return &protocol.StatsDto{ SessionID: "04a546aa", EventCount: 28, SessionDurationMs: 204_000, InferenceCount: 5, InferenceMs: 38_400, PromptTokens: 4120, CompletionTokens: 1860, TokensPerSecond: 48.4, PerProvider: []protocol.ProviderStatsDto{ {Provider: "llama-cpp:qwen2.5-coder-14b", CompletedCount: 4, TotalLatencyMs: 33_200, PromptTokens: 3800, CompletionTokens: 1700, TokensPerSecond: 51.2}, {Provider: "llama-cpp:default", CompletedCount: 1, TotalLatencyMs: 5200, PromptTokens: 320, CompletionTokens: 160, TokensPerSecond: 30.8}, }, ToolCount: 6, ToolMs: 4300, PerTool: []protocol.ToolStatsDto{ {ToolName: "file_write", CompletedCount: 2, TotalDurationMs: 2600}, {ToolName: "read_file", CompletedCount: 3, TotalDurationMs: 1200}, {ToolName: "shell_exec", CompletedCount: 1, TotalDurationMs: 500}, }, ApprovalsRequested: 2, ApprovalsResolved: 2, ApprovalsPending: 0, ApprovalWaitMs: 45_000, AvgApprovalWaitMs: 22_500, PerTier: []protocol.TierApprovalStatsDto{ {Tier: "T2", RequestedCount: 1, ResolvedCount: 1, TotalWaitMs: 15_000, AvgWaitMs: 15_000}, {Tier: "T3", RequestedCount: 1, ResolvedCount: 1, TotalWaitMs: 30_000, AvgWaitMs: 30_000}, }, Failures: protocol.FailureMetricsDto{ToolFailures: 1}, InferencePct: 18.8, ToolPct: 2.1, ApprovalWaitPct: 22.1, } } func sampleWorkflows() []Workflow { return []Workflow{ {ID: "healthcheck", Description: "ping endpoints and report status"}, {ID: "refactor", Description: "multi-stage code refactor with review"}, {ID: "triage", Description: "classify and route incoming issues"}, } } func sampleManifest() map[string][]ManifestTool { return map[string][]ManifestTool{ "plan": {{"read_file", 0}, {"list_dir", 0}}, "write_script": {{"file_write", 3}, {"shell_exec", 4}, {"read_file", 0}}, "verify": {{"shell_exec", 4}, {"http_get", 1}}, } } func sampleSessions() []Session { return []Session{ {ID: "04a546aa", Status: "FAILED", WorkflowID: "healthcheck", Name: "healthcheck", CurrentStage: "write_script", LastEventAt: 1748000000000}, {ID: "0d7097bb", Status: "COMPLETED", WorkflowID: "healthcheck", Name: "healthcheck", LastEventAt: 1748000000000}, {ID: "1dae17cc", Status: "CHAT", WorkflowID: "chat", Name: "chat", LastEventAt: 1748000000000}, {ID: "338f09dd", Status: "FAILED", WorkflowID: "healthcheck", Name: "healthcheck", CurrentStage: "write_script", LastEventAt: 1748000000000}, {ID: "3f362dee", Status: "CHAT", WorkflowID: "chat", Name: "chat", LastEventAt: 1748000000000}, {ID: "92f6c3ff", Status: "CHAT", WorkflowID: "chat", Name: "chat", LastEventAt: 1748000000000}, {ID: "9a7682gg", Status: "COMPLETED", WorkflowID: "healthcheck", Name: "healthcheck", LastEventAt: 1748000000000}, } } func sampleEvents() []EventEntry { return []EventEntry{ {"13:42:36", "InferenceStarted", "write_script"}, {"13:43:00", "InferenceCompleted", "write_script"}, {"13:43:00", "ToolStarted", "file_write"}, {"13:43:00", "SessionPaused", "APPROVAL_PENDING"}, {"13:44:10", "ToolCompleted", "file_write"}, {"13:44:10", "InferenceStarted", "write_script"}, {"13:44:10", "SessionFailed", "CANCELLED"}, } }