5721ed21bb
SessionWorkspaceBoundEvent already recorded the bound workspace root but it was never surfaced. Map it to a new session.workspace_bound frame (sealed ServerMessage variant, auto-registered; re-emitted on reconnect via the snapshot replay), carry it on Session.WorkspaceRoot, and show it home-abbreviated in the status bar (⌂ ~/Programs/correx). Golden test pins the decode.
184 lines
6.3 KiB
Go
184 lines
6.3 KiB
Go
package app
|
|
|
|
// 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 "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{
|
|
{"user", "write a healthcheck script for the api"},
|
|
{"router", "I'll create a script that pings /health and checks the status code, then writes the results to a timestamped file."},
|
|
{"tool", "--- 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()
|
|
}
|
|
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.Pending = &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.Pending = &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.Pending = &Approval{
|
|
RequestID: "req-2", SessionID: "04a546aa", Tier: "T2", Risk: "MEDIUM",
|
|
ToolName: "shell",
|
|
Preview: `{"argv":["bash","scripts/healthcheck.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{
|
|
{"tool", "--- 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"
|
|
}
|
|
return m.View()
|
|
}
|
|
|
|
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"},
|
|
}
|
|
}
|