feat(tui): show session workspace (cwd) in the status bar

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.
This commit is contained in:
2026-06-03 01:56:46 +04:00
parent 00b08660bd
commit 5721ed21bb
8 changed files with 82 additions and 33 deletions
+22 -20
View File
@@ -32,6 +32,7 @@ const (
TypeToolRejected = "tool.rejected"
TypeApprovalRequired = "approval.required"
TypeApprovalResolved = "approval.resolved"
TypeWorkspaceBound = "session.workspace_bound"
TypeStageManifest = "stage.tool_manifest"
TypeProviderStatus = "provider.status_changed"
TypeProtocolError = "protocol_error"
@@ -52,25 +53,26 @@ const (
type ServerMessage struct {
Type string `json:"type"`
SessionID string `json:"sessionId"`
WorkflowID string `json:"workflowId"`
StageID string `json:"stageId"`
ToolName string `json:"toolName"`
Role string `json:"role"`
TurnID string `json:"turnId"`
Reason string `json:"reason"`
Summary string `json:"outputSummary"`
Response string `json:"responseText"`
Content string `json:"content"`
Diff *string `json:"diff"`
Tier string `json:"tier"`
Message string `json:"message"`
RequestID string `json:"requestId"`
ArtifactID string `json:"artifactId"`
ProviderID string `json:"providerId"`
Preview *string `json:"preview"`
Disposition string `json:"disposition"`
Outcome string `json:"outcome"` // approval.resolved: APPROVED | REJECTED | AUTO_APPROVED
SessionID string `json:"sessionId"`
WorkflowID string `json:"workflowId"`
StageID string `json:"stageId"`
ToolName string `json:"toolName"`
Role string `json:"role"`
TurnID string `json:"turnId"`
Reason string `json:"reason"`
Summary string `json:"outputSummary"`
Response string `json:"responseText"`
Content string `json:"content"`
Diff *string `json:"diff"`
Tier string `json:"tier"`
Message string `json:"message"`
RequestID string `json:"requestId"`
ArtifactID string `json:"artifactId"`
ProviderID string `json:"providerId"`
Preview *string `json:"preview"`
Disposition string `json:"disposition"`
Outcome string `json:"outcome"` // approval.resolved: APPROVED | REJECTED | AUTO_APPROVED
WorkspaceRoot string `json:"workspaceRoot"` // session.workspace_bound: the bound cwd
SteeringEmitted bool `json:"steeringEmitted"`
OccurredAt int64 `json:"occurredAt"`
@@ -180,7 +182,7 @@ func (m ServerMessage) IsEventBearing() bool {
TypeInferenceStarted, TypeInferenceDone, TypeInferenceTimeout,
TypeToolStarted, TypeToolCompleted, TypeToolFailed, TypeToolRejected,
TypeToolAssessed,
TypeApprovalRequired, TypeApprovalResolved, TypeArtifactCreated:
TypeApprovalRequired, TypeApprovalResolved, TypeWorkspaceBound, TypeArtifactCreated:
return true
default:
return false