Documentation
¶
Overview ¶
Package msg contains all typed message structs used for inter-actor communication via NATS. Messages are plain Go structs (no protobuf). They are serialized into NATSEnvelope for transport.
Autonomous agent messages.
Humanoid messages, including contact pairing and the allowlist.
Lane and pane-group messages: the two middle levels of the tree. Kept together because a pane group only ever exists inside a lane, and the operations on them mirror each other.
The `##llm select` picker payload: WorkspaceActor → attached front-ends, pushed on pane.<paneID>.llm.picker.
The daemon does not drive the picker. It answers a bare `##llm select` with everything a front-end needs to run the interaction itself — the activatable models, why the rest are not activatable, the scopes a selection can bind at, and whether each model's provider already has a key — and then goes back to its mailbox. Whatever the user picks comes back as an ordinary `##` command (`##<scope> model <ref>`, `##secret new <NAME> <value>`), so every existing guard applies unchanged and nothing new can bind a model behind their back.
This is what keeps an arrow-key picker compatible with the constraint that forced the numbered menu in the first place (see actors.cmdLLMSelect): a `##` command runs on the WorkspaceActor's mailbox goroutine and cannot block waiting for an answer. Here it never waits — it publishes and returns.
A front-end that ignores this push loses nothing: the numbered menu is still printed, and `##llm select <n>` still works.
Pane-level messages: input and lifecycle for a single pane, its LLM actor, cross-pane listening, pipeline mode, attention and replay.
Sharing messages: raw PTY relay for remote observers, upstream pane sharing, the shared-pane protocol, per-pane share restrictions, and WebSocket connection reliability.
Snapshot request/reply messages. Every level of the tree answers one of these; they are grouped here rather than split across the four level-specific files because they are a single request/reply protocol.
Tab-level messages: what the workspace and the CLI send to a TabActor, plus the tab's active-pane query and its layout operations.
Workspace-level messages: what the TUI and the CLI send to the WorkspaceActor, and the workspace-level layout operations.
Package msg proxy_audit_aliases.go — re-exports rysh-shared/msg governance proxy audit types (design 001 §4.5) so rysh-cli references them as msg.MsgProxyRequestAudit etc. The codec is registered in rysh-shared's DefaultCodecRegistry, which the CLI registry is built from, so no CLI-side codec registration is needed (mirrors usage_aliases.go).
Package msg shared_aliases.go — re-exports rysh-shared/msg types as type aliases. Type aliases (=) are NOT new types — they are the same underlying Go type. This is required so that messages sent from rysh-cli actors to rysh-shared/agentic actors match the type switches in the shared actors' Receive() methods.
Package msg usage_aliases.go — re-exports rysh-shared/msg usage-ledger types (design 003) so rysh-cli actors reference them as msg.MsgUsageRecord etc. The codecs are registered in rysh-shared's DefaultCodecRegistry, which the CLI registry is built from, so no CLI-side codec registration is needed.
Index ¶
- Constants
- Variables
- func AnsaInboxSubject() string
- func BoardAlivePattern() string
- func BoardAliveSubject(board string) string
- func BoardIDFromMeta(id string) string
- func BoardIDFromSubject(subject, leaf string) (string, bool)
- func BoardPersona(givenName, title, paneID string) string
- func BoardPostPattern() string
- func BoardPostSubject(board string) string
- func BoardQueryPattern() string
- func BoardQuerySubject(board string) string
- func BoardRegisterPattern() string
- func BoardRegisterSubject(board string) string
- func FleetQuerySubject() string
- func FleetUpdateSubject() string
- func IsDefaultBoard(id string) bool
- func MintThreadID(paneID string, n int) string
- func NormalizeBoardID(id string) string
- func SendBoardPost(p *NATSPublisher, board string, post *MsgBoardPost) error
- func SendBoardRegister(p *NATSPublisher, board string, reg *MsgBoardRegister) error
- func SendMirrorPaneVTFrame(p *NATSPublisher, mirrorID string, f *MsgMirrorPaneVTFrame) error
- func SendPaneRawDirty(p *NATSPublisher, paneID string) error
- func SendRawOutput(p *NATSPublisher, paneID string, data []byte) error
- func SendShareModeChange(p *NATSPublisher, paneID string, interactive bool, rows, cols int) error
- func ValidateBoardID(id string) error
- type AgentInfo
- type ApprovalDecision
- type ApprovalType
- type AttachmentInfo
- type AttentionCategory
- type AttentionPriority
- type BoardIDError
- type ChannelConfig
- type ChannelStatus
- type Choice
- type CodecRegistry
- type ConversationMessage
- type ConversationTurnInfo
- type ConversationType
- type DiffPayload
- type Direction
- type EmailChannelConfig
- type EmailDetail
- type EmailSummary
- type ForgedInvokeRequest
- type ForgedInvokeResult
- type ForgedOpSpec
- type GroundingReportInfo
- type HumanoidInfo
- type ImportCookie
- type InputType
- type LLMPickerModel
- type LLMPickerScope
- type MemoryEntry
- type MemoryState
- type MessageLogger
- type MessageOrigin
- type MessageSource
- type MsgActivePaneReply
- type MsgAgentActivate
- type MsgAgentContinue
- type MsgAgentCreate
- type MsgAgentDeactivate
- type MsgAgentDelete
- type MsgAgentList
- type MsgAgentListReply
- type MsgAgentPrompt
- type MsgAgentRegisterPane
- type MsgAgentStop
- type MsgAgentUnregisterPane
- type MsgAgenticCancel
- type MsgAgenticContinue
- type MsgAgenticOutput
- type MsgAgenticPrompt
- type MsgAgenticStatus
- type MsgAgenticStep
- type MsgAnsaRoute
- type MsgAnsaRouteResult
- type MsgApprovalRequest
- type MsgApprovalResponse
- type MsgAttentionAck
- type MsgAttentionDisable
- type MsgAttentionEnable
- type MsgAttentionEvent
- type MsgBoardAgentPrompt
- type MsgBoardPost
- type MsgBoardRegister
- type MsgBrowserActionRequest
- type MsgBrowserActionResponse
- type MsgCLIAnsaSend
- type MsgCLIBoardPost
- type MsgCLICreateLane
- type MsgCLICreatePane
- type MsgCLICreatePaneGroup
- type MsgCLICreateStackedPane
- type MsgCLICreateTab
- type MsgCLIDeleteLane
- type MsgCLIDeletePane
- type MsgCLIDeletePaneGroup
- type MsgCLIDeleteTab
- type MsgCLIPipelineDisable
- type MsgCLIPipelineEnable
- type MsgCLIResponse
- type MsgCLIRyshCommand
- type MsgCancelPrompt
- type MsgChannelAllow
- type MsgChannelPairApprove
- type MsgChannelPairLink
- type MsgChannelPairList
- type MsgChannelPairListReply
- type MsgChannelPairQR
- type MsgChannelPairRequest
- type MsgChannelPairStatus
- type MsgClosePane
- type MsgConversationAppend
- type MsgConversationHistoryAppend
- type MsgConversationHistoryReply
- type MsgCreateApprovalPane
- type MsgCreatePane
- type MsgCreatePaneDown
- type MsgCreateStackedPane
- type MsgCreateTab
- type MsgDestroyApprovalPane
- type MsgDiscoverCodexSession
- type MsgEqualizeAll
- type MsgEqualizeHorizontal
- type MsgEqualizePanes
- type MsgEqualizeVertical
- type MsgExecPrompt
- type MsgExecRyshOnPane
- type MsgFocusNextTab
- type MsgFocusPane
- type MsgFocusPaneByID
- type MsgFocusPrevTab
- type MsgFocusTabIndex
- type MsgGetActivePane
- type MsgGetConversationHistory
- type MsgGetGroundingState
- type MsgGetLaneActivePane
- type MsgGetLaneSnapshot
- type MsgGetMirrorPaneVT
- type MsgGetMirrorScrollback
- type MsgGetPaneGroupActivePane
- type MsgGetPaneGroupSnapshot
- type MsgGetPaneScrollback
- type MsgGetPaneScrollbackDelta
- type MsgGetPaneSnapshot
- type MsgGetPaneVT
- type MsgGetRunStatus
- type MsgGetSessionMemory
- type MsgGetTabSnapshot
- type MsgGetWorkspaceSnapshot
- type MsgGroundingStateReply
- type MsgHumanoidActivate
- type MsgHumanoidChannelStart
- type MsgHumanoidChannelStatus
- type MsgHumanoidChannelStop
- type MsgHumanoidContinue
- type MsgHumanoidCreate
- type MsgHumanoidDeactivate
- type MsgHumanoidDelete
- type MsgHumanoidEmailChanged
- type MsgHumanoidEmailCompose
- type MsgHumanoidEmailComposeReply
- type MsgHumanoidEmailList
- type MsgHumanoidEmailListReply
- type MsgHumanoidEmailRead
- type MsgHumanoidEmailReadReply
- type MsgHumanoidGovernanceChanged
- type MsgHumanoidInboundMessage
- type MsgHumanoidList
- type MsgHumanoidListReply
- type MsgHumanoidOutboundMessage
- type MsgHumanoidPrompt
- type MsgHumanoidRegisterPane
- type MsgHumanoidReplyModeChanged
- type MsgHumanoidSetFocus
- type MsgHumanoidSetGovernance
- type MsgHumanoidSetProvider
- type MsgHumanoidSetReplyMode
- type MsgHumanoidStop
- type MsgHumanoidUnregisterPane
- type MsgHumanoidWhatsAppChanged
- type MsgHumanoidWhatsAppList
- type MsgHumanoidWhatsAppListReply
- type MsgHumanoidWhatsAppRead
- type MsgHumanoidWhatsAppReadReply
- type MsgLLMPickerOpen
- type MsgLaneActivePaneReply
- type MsgLaneCloseActivePane
- type MsgLaneClosePaneGroup
- type MsgLaneCreatePaneGroup
- type MsgLaneCreateStackedPane
- type MsgLaneCreateStackedPaneInGroup
- type MsgLaneDeletePaneGroup
- type MsgLaneEqualizeGroups
- type MsgLaneFocusGroup
- type MsgLaneFocusPaneByID
- type MsgLaneResizeGroupHeight
- type MsgLaneSetPaneHidden
- type MsgLaneSnapshotReply
- type MsgLaneStackedPane
- type MsgLaneStackedPaneMove
- type MsgLaneStackedPaneSelect
- type MsgLaunchClaudeInPane
- type MsgLayoutDirty
- type MsgMCPStatus
- type MsgMemoryAppend
- type MsgMemoryGet
- type MsgMemoryGetReply
- type MsgMemoryStateUpdate
- type MsgMemorySummarize
- type MsgMemorySummarizeDone
- type MsgMirrorDirty
- type MsgMirrorMaximizePane
- type MsgMirrorPaneVTFrame
- type MsgMirrorPaneVTReply
- type MsgMirrorScrollbackReply
- type MsgMirrorTabOp
- type MsgMoveTab
- type MsgOrchestratorDone
- type MsgPaneAIHistoryAppend
- type MsgPaneAIOutputAppend
- type MsgPaneActivateMode
- type MsgPaneChatHistoryAppend
- type MsgPaneChatOutputAppend
- type MsgPaneClearOutput
- type MsgPaneDisableMode
- type MsgPaneEnableMode
- type MsgPaneExecChat
- type MsgPaneExecPrompt
- type MsgPaneExecRysh
- type MsgPaneExecShell
- type MsgPaneExternalHistoryAppend
- type MsgPaneExternalOutputAppend
- type MsgPaneGroupActivePaneReply
- type MsgPaneGroupCreateStackedPane
- type MsgPaneGroupDeletePane
- type MsgPaneGroupFocusPaneByID
- type MsgPaneGroupSetPaneHidden
- type MsgPaneGroupSnapshotReply
- type MsgPaneGroupStackedPane
- type MsgPaneGroupStackedPaneMove
- type MsgPaneGroupStackedPaneSelect
- type MsgPaneHistoryAppend
- type MsgPaneHopClear
- type MsgPaneHopContent
- type MsgPaneHopResume
- type MsgPaneImportCookies
- type MsgPaneKillForeground
- type MsgPaneNativeMode
- type MsgPaneOutputAppend
- type MsgPaneProcess
- type MsgPaneRawDirty
- type MsgPaneRawOutputAppend
- type MsgPaneRegisterForgedProxies
- type MsgPaneReleaseSize
- type MsgPaneReplayShareState
- type MsgPaneResize
- type MsgPaneResized
- type MsgPaneRyshHistoryAppend
- type MsgPaneRyshOutputAppend
- type MsgPaneScrollbackDeltaReply
- type MsgPaneScrollbackReply
- type MsgPaneSetApprovalPaneGroups
- type MsgPaneSetGivenName
- type MsgPaneSetHidden
- type MsgPaneSetHumanoid
- type MsgPaneSetMeta
- type MsgPaneSetProvider
- type MsgPaneSetRemoteSubscriber
- type MsgPaneSetShareRestrictions
- type MsgPaneSetSharingState
- type MsgPaneSetTitle
- type MsgPaneShareModeChange
- type MsgPaneShareStart
- type MsgPaneShareStatus
- type MsgPaneShareStatusReply
- type MsgPaneShareStop
- type MsgPaneShellHistoryAppend
- type MsgPaneShellOutputAppend
- type MsgPaneSnapshotReply
- type MsgPaneStatusUpdate
- type MsgPaneStop
- type MsgPaneStopped
- type MsgPaneSubmitInput
- type MsgPaneTerminated
- type MsgPaneVTReply
- type MsgPaneWebHeadless
- type MsgPipelineCommand
- type MsgPipelineOutputAppend
- type MsgProxyAuditSnapshotReply
- type MsgProxyAuditSnapshotRequest
- type MsgProxyRequestAudit
- type MsgRawKeyInput
- type MsgReconcileWorkspaces
- type MsgRelayActivate
- type MsgRelayDeactivate
- type MsgReloadPrompts
- type MsgReloadPromptsRequest
- type MsgRemoteForwardCommand
- type MsgRemoteInteractiveModeChange
- type MsgRemotePaneFullscreen
- type MsgRemoteScrollbackAppend
- type MsgRemoteUpstreamConnect
- type MsgRemoteUpstreamDisconnect
- type MsgRemoteUpstreamStatus
- type MsgRemoteVTScreenUpdate
- type MsgRenameLane
- type MsgRenamePane
- type MsgRenameTab
- type MsgReplayControl
- type MsgResizePane
- type MsgResizePaneHeight
- type MsgResizePaneWidth
- type MsgRestoreConversation
- type MsgResumeNativeAgents
- type MsgRunStatusReply
- type MsgSessionMemoryReplace
- type MsgSessionMemoryReply
- type MsgSetChatOutputPane
- type MsgSetConnectedPane
- type MsgSetControllerMode
- type MsgSetGroundingMode
- type MsgSetRunBudget
- type MsgSetTabBarOrientation
- type MsgSetWorkingDir
- type MsgShareDisableMode
- type MsgShareEnableMode
- type MsgShareEntity
- type MsgShareForgedAPI
- type MsgShareList
- type MsgShareListReply
- type MsgShareOutput
- type MsgShareRegisterAck
- type MsgShareRestrictionsUpdated
- type MsgShareSetFileBrowse
- type MsgShareShellAllow
- type MsgShareShellClear
- type MsgShareShellForbid
- type MsgShareShowRestrictions
- type MsgShareStatus
- type MsgShareStatusReply
- type MsgShutdown
- type MsgSpawnSubOrchestrator
- type MsgStackedPaneMove
- type MsgStackedPaneRotate
- type MsgStackedPaneSelect
- type MsgStartPaneListener
- type MsgStopPaneListener
- type MsgSubOrchestratorResult
- type MsgSubmitInput
- type MsgSwapPane
- type MsgSwitchWorkspace
- type MsgTabClosePane
- type MsgTabCreateGrid
- type MsgTabCreateGroupsInLane
- type MsgTabCreatePane
- type MsgTabCreatePaneDown
- type MsgTabCreatePaneGroupInLane
- type MsgTabCreateStackedPane
- type MsgTabCreateStackedPaneInLane
- type MsgTabDeleteLane
- type MsgTabEqualizeAll
- type MsgTabEqualizeHorizontal
- type MsgTabEqualizePanes
- type MsgTabEqualizeVertical
- type MsgTabFocus
- type MsgTabFocusPaneByID
- type MsgTabPipelineDisable
- type MsgTabPipelineEnable
- type MsgTabResizePane
- type MsgTabResizePaneHeight
- type MsgTabResizePaneWidth
- type MsgTabSetActive
- type MsgTabSetInactive
- type MsgTabSetPaneHidden
- type MsgTabSnapshotReply
- type MsgTabStackedPane
- type MsgTabStackedPaneMove
- type MsgTabStackedPaneSelect
- type MsgTabSubmitInput
- type MsgTabSwapPane
- type MsgTabTerminated
- type MsgTogglePipelineMode
- type MsgToolCall
- type MsgToolResult
- type MsgUnshareEntity
- type MsgUpstreamCommand
- type MsgUpstreamCommandAck
- type MsgUpstreamConnectionClosed
- type MsgUpstreamReconnected
- type MsgUpstreamSendCommand
- type MsgUpstreamSharesList
- type MsgUpstreamSubscribe
- type MsgUpstreamUnsubscribe
- type MsgUsageBudgetSet
- type MsgUsageCheck
- type MsgUsageCheckReply
- type MsgUsageRecord
- type MsgUsageSnapshotReply
- type MsgUsageSnapshotRequest
- type MsgWebActivate
- type MsgWebDeactivate
- type MsgWebPromptDispatched
- type MsgWorkspaceSnapshotReply
- type NATSEnvelope
- type NATSPublisher
- type PendingPair
- type RequestEnvelope
- type ShareInfo
- type ShareRestrictions
- type ToolCallInfo
- type TurnType
- type UsageAgg
- type UsageCeiling
- type VTLineDelta
- type WhatsAppMsgDetail
- type WhatsAppMsgSummary
Constants ¶
const ( // TUI → WorkspaceActor TagCreateTab = "MsgCreateTab" TagCreatePane = "MsgCreatePane" TagCreatePaneDown = "MsgCreatePaneDown" TagClosePane = "MsgClosePane" TagFocusNextTab = "MsgFocusNextTab" TagFocusPrevTab = "MsgFocusPrevTab" TagFocusTabIndex = "MsgFocusTabIndex" TagMoveTab = "MsgMoveTab" TagSetTabBarOrient = "MsgSetTabBarOrientation" TagFocusPane = "MsgFocusPane" TagFocusPaneByID = "MsgFocusPaneByID" TagResizePane = "MsgResizePane" TagResizePaneHeight = "MsgResizePaneHeight" TagSubmitInput = "MsgSubmitInput" TagWebPromptDispatched = "MsgWebPromptDispatched" TagWebActivate = "MsgWebActivate" TagWebDeactivate = "MsgWebDeactivate" TagRenamePane = "MsgRenamePane" TagRenameTab = "MsgRenameTab" TagRenameLane = "MsgRenameLane" TagShutdown = "MsgShutdown" TagSwitchWorkspace = "MsgSwitchWorkspace" TagReconcileWorkspaces = "MsgReconcileWorkspaces" // MCP restart-state (follow-up 6b). Published session-globally to // T("mcp","status"); rendered by the TUI footer. TagMCPStatus = "MsgMCPStatus" // Prompt auto-reload trigger (follow-up 2b). Published to ws.inbox by // the fsnotify watcher; the active WorkspaceActor runs the same reload + // broadcast path as ##agent reload-prompts. TagReloadPromptsRequest = "MsgReloadPromptsRequest" // Broadcast down Workspace → Tab → Lane → PaneGroup to update pane cwd. TagSetWorkingDir = "MsgSetWorkingDir" // WorkspaceActor → TabActor TagTabCreatePane = "MsgTabCreatePane" TagTabCreatePaneDown = "MsgTabCreatePaneDown" TagTabClosePane = "MsgTabClosePane" TagTabFocus = "MsgTabFocus" TagTabFocusPaneByID = "MsgTabFocusPaneByID" TagTabSetPaneHidden = "MsgTabSetPaneHidden" TagTabResizePane = "MsgTabResizePane" TagTabResizePaneHeight = "MsgTabResizePaneHeight" TagTabSubmitInput = "MsgTabSubmitInput" TagTabSetActive = "MsgTabSetActive" TagTabSetInactive = "MsgTabSetInactive" // TabActor → LaneActor TagLaneCreatePaneGroup = "MsgLaneCreatePaneGroup" TagLaneClosePaneGroup = "MsgLaneClosePaneGroup" TagLaneCloseActivePane = "MsgLaneCloseActivePane" TagLaneFocusGroup = "MsgLaneFocusGroup" TagLaneFocusPaneByID = "MsgLaneFocusPaneByID" TagLaneSetPaneHidden = "MsgLaneSetPaneHidden" TagLaneCreateStackedPane = "MsgLaneCreateStackedPane" TagLaneStackedPane = "MsgLaneStackedPane" TagLaneStackedPaneSelect = "MsgLaneStackedPaneSelect" TagLaneStackedPaneMove = "MsgLaneStackedPaneMove" TagLaneResizeGroupHeight = "MsgLaneResizeGroupHeight" TagGetLaneSnapshot = "MsgGetLaneSnapshot" TagLaneSnapshotReply = "MsgLaneSnapshotReply" TagGetLaneActivePane = "MsgGetLaneActivePane" TagLaneActivePaneReply = "MsgLaneActivePaneReply" // LaneActor → PaneGroupActor TagGetPaneGroupSnapshot = "MsgGetPaneGroupSnapshot" TagPaneGroupSnapshotReply = "MsgPaneGroupSnapshotReply" TagGetPaneGroupActivePane = "MsgGetPaneGroupActivePane" TagPaneGroupActivePaneReply = "MsgPaneGroupActivePaneReply" // Stacked panes: TUI → Workspace TagCreateStackedPane = "MsgCreateStackedPane" TagStackedPaneRotate = "MsgStackedPaneRotate" TagStackedPaneSelect = "MsgStackedPaneSelect" TagStackedPaneMove = "MsgStackedPaneMove" // Stacked panes: Workspace → Tab TagTabCreateStackedPane = "MsgTabCreateStackedPane" TagTabStackedPane = "MsgTabStackedPane" TagTabStackedPaneSelect = "MsgTabStackedPaneSelect" TagTabStackedPaneMove = "MsgTabStackedPaneMove" // Stacked panes: Tab/Lane → PaneGroup TagPaneGroupCreateStackedPane = "MsgPaneGroupCreateStackedPane" TagPaneGroupStackedPane = "MsgPaneGroupStackedPane" TagPaneGroupStackedPaneSelect = "MsgPaneGroupStackedPaneSelect" TagPaneGroupFocusPaneByID = "MsgPaneGroupFocusPaneByID" TagPaneGroupSetPaneHidden = "MsgPaneGroupSetPaneHidden" TagPaneGroupStackedPaneMove = "MsgPaneGroupStackedPaneMove" // Given-name messages (Workspace → Pane, direct) TagPaneSetGivenName = "MsgPaneSetGivenName" // Off-screen toggle for a live pane (Workspace → Pane, direct). TagPaneSetHidden = "MsgPaneSetHidden" // Per-pane metadata for whoever is driving the pane (Workspace → Pane, // direct), and the foreground-program announcement (Pane → anyone). TagPaneSetMeta = "MsgPaneSetMeta" TagLaunchClaudeInPane = "MsgLaunchClaudeInPane" TagPaneProcess = "MsgPaneProcess" // Native agent panes — `##claude` / `##codex` (design 029). TagDiscoverCodexSession = "MsgDiscoverCodexSession" TagResumeNativeAgents = "MsgResumeNativeAgents" // Per-pane provider override (Workspace → Pane, direct; design 002 §3.4) TagPaneSetProvider = "MsgPaneSetProvider" // Interactive `##llm select` picker (Workspace → front-end push) TagLLMPickerOpen = "MsgLLMPickerOpen" // Per-pane mode enable/disable (Workspace → Pane, direct) TagPaneEnableMode = "MsgPaneEnableMode" TagPaneDisableMode = "MsgPaneDisableMode" TagPaneActivateMode = "MsgPaneActivateMode" TagPaneWebHeadless = "MsgPaneWebHeadless" TagPaneImportCookies = "MsgPaneImportCookies" // PaneGroupActor → PaneActor TagPaneSubmitInput = "MsgPaneSubmitInput" TagPaneExecShell = "MsgPaneExecShell" TagPaneExecPrompt = "MsgPaneExecPrompt" TagPaneExecRysh = "MsgPaneExecRysh" TagPaneExecChat = "MsgPaneExecChat" TagPaneSetTitle = "MsgPaneSetTitle" TagPaneStop = "MsgPaneStop" // PaneActor → LLMActor TagExecPrompt = "MsgExecPrompt" TagCancelPrompt = "MsgCancelPrompt" // Snapshot request/reply TagGetWorkspaceSnapshot = "MsgGetWorkspaceSnapshot" TagWorkspaceSnapshotReply = "MsgWorkspaceSnapshotReply" TagGetTabSnapshot = "MsgGetTabSnapshot" TagTabSnapshotReply = "MsgTabSnapshotReply" TagGetPaneSnapshot = "MsgGetPaneSnapshot" TagPaneSnapshotReply = "MsgPaneSnapshotReply" TagGetPaneVT = "MsgGetPaneVT" TagPaneVTReply = "MsgPaneVTReply" TagGetPaneScrollback = "MsgGetPaneScrollback" TagPaneScrollbackReply = "MsgPaneScrollbackReply" TagGetPaneScrollbackDelta = "MsgGetPaneScrollbackDelta" TagPaneScrollbackDeltaReply = "MsgPaneScrollbackDeltaReply" TagGetMirrorScrollback = "MsgGetMirrorScrollback" TagMirrorScrollbackReply = "MsgMirrorScrollbackReply" TagGetMirrorPaneVT = "MsgGetMirrorPaneVT" TagMirrorPaneVTReply = "MsgMirrorPaneVTReply" TagMirrorPaneVTFrame = "MsgMirrorPaneVTFrame" // Supervision notifications TagPaneTerminated = "MsgPaneTerminated" TagPaneKillForeground = "MsgPaneKillForeground" TagTabTerminated = "MsgTabTerminated" // TabActor active-pane query TagGetActivePane = "MsgGetActivePane" TagActivePaneReply = "MsgActivePaneReply" // Pane listener (cross-pane output listening) TagStartPaneListener = "MsgStartPaneListener" TagStopPaneListener = "MsgStopPaneListener" // Hop commands TagPaneHopContent = "MsgPaneHopContent" TagPaneHopResume = "MsgPaneHopResume" TagPaneHopClear = "MsgPaneHopClear" // Pipeline mode TagTogglePipelineMode = "MsgTogglePipelineMode" TagPipelineCommand = "MsgPipelineCommand" TagTabPipelineEnable = "MsgTabPipelineEnable" TagTabPipelineDisable = "MsgTabPipelineDisable" // Layout management: TUI → Workspace TagEqualizeHorizontal = "MsgEqualizeHorizontal" TagEqualizeVertical = "MsgEqualizeVertical" TagEqualizeAll = "MsgEqualizeAll" TagEqualizePanes = "MsgEqualizePanes" TagResizePaneWidth = "MsgResizePaneWidth" TagSwapPane = "MsgSwapPane" // Layout management: Workspace → Tab TagTabEqualizeHorizontal = "MsgTabEqualizeHorizontal" TagTabEqualizeVertical = "MsgTabEqualizeVertical" TagTabEqualizeAll = "MsgTabEqualizeAll" TagTabEqualizePanes = "MsgTabEqualizePanes" TagTabResizePaneWidth = "MsgTabResizePaneWidth" TagTabSwapPane = "MsgTabSwapPane" // Layout management: Tab → Lane TagLaneEqualizeGroups = "MsgLaneEqualizeGroups" // CLI messages TagCLICreateTab = "MsgCLICreateTab" TagCLIDeleteTab = "MsgCLIDeleteTab" TagCLICreateLane = "MsgCLICreateLane" TagCLIDeleteLane = "MsgCLIDeleteLane" TagCLICreatePaneGroup = "MsgCLICreatePaneGroup" TagCLIDeletePaneGroup = "MsgCLIDeletePaneGroup" TagCLICreatePane = "MsgCLICreatePane" TagCLIDeletePane = "MsgCLIDeletePane" TagCLICreateStackedPane = "MsgCLICreateStackedPane" TagCLIPipelineEnable = "MsgCLIPipelineEnable" TagCLIPipelineDisable = "MsgCLIPipelineDisable" TagCLIResponse = "MsgCLIResponse" TagCLIRyshCommand = "MsgCLIRyshCommand" TagTabDeleteLane = "MsgTabDeleteLane" TagTabCreatePaneGroupInLane = "MsgTabCreatePaneGroupInLane" TagTabCreateGrid = "MsgTabCreateGrid" TagTabCreateGroupsInLane = "MsgTabCreateGroupsInLane" TagTabCreateStackedPaneInLane = "MsgTabCreateStackedPaneInLane" TagLaneDeletePaneGroup = "MsgLaneDeletePaneGroup" TagLaneCreateStackedPaneInGroup = "MsgLaneCreateStackedPaneInGroup" TagPaneGroupDeletePane = "MsgPaneGroupDeletePane" // Remote upstream / pane sharing TagPaneSetSharingState = "MsgPaneSetSharingState" TagRemoteUpstreamConnect = "MsgRemoteUpstreamConnect" TagRemoteUpstreamDisconnect = "MsgRemoteUpstreamDisconnect" TagRemoteUpstreamStatus = "MsgRemoteUpstreamStatus" // Shared-panes-via-upstream TagPaneRegisterForgedProxies = "MsgPaneRegisterForgedProxies" TagUpstreamCommand = "MsgUpstreamCommand" TagUpstreamCommandAck = "MsgUpstreamCommandAck" TagUpstreamSubscribe = "MsgUpstreamSubscribe" TagUpstreamUnsubscribe = "MsgUpstreamUnsubscribe" TagUpstreamSendCommand = "MsgUpstreamSendCommand" // Controller mode (remote upstream) TagSetControllerMode = "MsgSetControllerMode" TagSetConnectedPane = "MsgSetConnectedPane" TagRemoteForwardCommand = "MsgRemoteForwardCommand" TagExecRyshOnPane = "MsgExecRyshOnPane" TagMirrorTabOp = "MsgMirrorTabOp" TagMirrorMaximizePane = "MsgMirrorMaximizePane" TagRemotePaneFullscreen = "MsgRemotePaneFullscreen" // Share restrictions // WebSocket connection reliability TagUpstreamReconnected = "MsgUpstreamReconnected" TagUpstreamConnectionClosed = "MsgUpstreamConnectionClosed" // Autonomous agents TagAgentCreate = "MsgAgentCreate" TagAgentDelete = "MsgAgentDelete" TagAgentStop = "MsgAgentStop" TagAgentContinue = "MsgAgentContinue" TagAgentActivate = "MsgAgentActivate" TagAgentDeactivate = "MsgAgentDeactivate" TagAgentList = "MsgAgentList" TagAgentListReply = "MsgAgentListReply" TagAgentPrompt = "MsgAgentPrompt" TagAgentRegisterPane = "MsgAgentRegisterPane" TagAgentUnregisterPane = "MsgAgentUnregisterPane" // Humanoids (agents with external communication channels) TagHumanoidCreate = "MsgHumanoidCreate" TagHumanoidDelete = "MsgHumanoidDelete" TagHumanoidStop = "MsgHumanoidStop" TagHumanoidContinue = "MsgHumanoidContinue" TagHumanoidActivate = "MsgHumanoidActivate" TagHumanoidDeactivate = "MsgHumanoidDeactivate" TagHumanoidList = "MsgHumanoidList" TagHumanoidListReply = "MsgHumanoidListReply" TagHumanoidPrompt = "MsgHumanoidPrompt" TagHumanoidRegisterPane = "MsgHumanoidRegisterPane" TagHumanoidUnregisterPane = "MsgHumanoidUnregisterPane" TagHumanoidChannelStart = "MsgHumanoidChannelStart" TagHumanoidChannelStop = "MsgHumanoidChannelStop" TagHumanoidChannelStatus = "MsgHumanoidChannelStatus" TagHumanoidSetReplyMode = "MsgHumanoidSetReplyMode" TagHumanoidSetGovernance = "MsgHumanoidSetGovernance" TagHumanoidGovernanceChanged = "MsgHumanoidGovernanceChanged" TagHumanoidReplyModeChanged = "MsgHumanoidReplyModeChanged" TagHumanoidSetProvider = "MsgHumanoidSetProvider" TagHumanoidInboundMessage = "MsgHumanoidInboundMessage" TagHumanoidOutboundMessage = "MsgHumanoidOutboundMessage" TagHumanoidEmailList = "MsgHumanoidEmailList" TagHumanoidEmailRead = "MsgHumanoidEmailRead" TagHumanoidEmailListReply = "MsgHumanoidEmailListReply" TagHumanoidEmailReadReply = "MsgHumanoidEmailReadReply" TagHumanoidEmailChanged = "MsgHumanoidEmailChanged" TagHumanoidSetFocus = "MsgHumanoidSetFocus" TagHumanoidEmailCompose = "MsgHumanoidEmailCompose" TagHumanoidEmailComposeReply = "MsgHumanoidEmailComposeReply" TagHumanoidWhatsAppList = "MsgHumanoidWhatsAppList" TagHumanoidWhatsAppRead = "MsgHumanoidWhatsAppRead" TagHumanoidWhatsAppListReply = "MsgHumanoidWhatsAppListReply" TagHumanoidWhatsAppReadReply = "MsgHumanoidWhatsAppReadReply" TagHumanoidWhatsAppChanged = "MsgHumanoidWhatsAppChanged" // Pane ← Humanoid TagPaneSetHumanoid = "MsgPaneSetHumanoid" // Contact pairing & allowlists (WS3, design 003) — humanoid.{name}.pairing TagChannelPairRequest = "MsgChannelPairRequest" TagChannelPairApprove = "MsgChannelPairApprove" TagChannelAllow = "MsgChannelAllow" TagChannelPairList = "MsgChannelPairList" TagChannelPairListReply = "MsgChannelPairListReply" TagChannelPairQR = "MsgChannelPairQR" TagChannelPairStatus = "MsgChannelPairStatus" TagChannelPairLink = "MsgChannelPairLink" // Attention mechanism TagAttentionEvent = "MsgAttentionEvent" TagAttentionAck = "MsgAttentionAck" TagAttentionEnable = "MsgAttentionEnable" TagAttentionDisable = "MsgAttentionDisable" // Raw/interactive terminal mode TagPaneResize = "MsgPaneResize" TagPaneReleaseSize = "MsgPaneReleaseSize" TagPaneResized = "MsgPaneResized" TagRawKeyInput = "MsgRawKeyInput" TagPaneClearOutput = "MsgPaneClearOutput" TagPaneNativeMode = "MsgPaneNativeMode" TagRelayActivate = "MsgRelayActivate" TagRelayDeactivate = "MsgRelayDeactivate" // Interactive sharing TagPaneRawOutputAppend = "MsgPaneRawOutputAppend" TagPaneRawDirty = "MsgPaneRawDirty" TagBoardPost = "MsgBoardPost" TagBoardRegister = "MsgBoardRegister" TagCLIBoardPost = "MsgCLIBoardPost" TagBoardAgentPrompt = "MsgBoardAgentPrompt" TagAnsaRoute = "MsgAnsaRoute" TagAnsaRouteResult = "MsgAnsaRouteResult" TagCLIAnsaSend = "MsgCLIAnsaSend" TagRemoteInteractiveModeChange = "MsgRemoteInteractiveModeChange" TagPaneSetRemoteSubscriber = "MsgPaneSetRemoteSubscriber" TagRemoteVTScreenUpdate = "MsgRemoteVTScreenUpdate" TagRemoteScrollbackAppend = "MsgRemoteScrollbackAppend" TagMirrorDirty = "MsgMirrorDirty" TagLayoutDirty = "MsgLayoutDirty" // Session replay v2 (design 006) — dedicated replay pane TagReplayControl = "MsgReplayControl" TagPaneStopped = "MsgPaneStopped" )
const ( AnsaModeShell = "shell" AnsaModePrompt = "prompt" )
Delivery modes. These are the pane inbox's own vocabulary, not ANSA's invention — see MsgPaneExecShell / MsgPaneExecPrompt.
const ( // AnsaErrNoTarget — the caller named nobody. AnsaErrNoTarget = "no_target" // AnsaErrNoText — the caller sent nothing to deliver. AnsaErrNoText = "no_text" // AnsaErrUnknownTarget — the name/id matched no pane in the session. AnsaErrUnknownTarget = "unknown_target" // AnsaErrAmbiguousTarget — the name matched MORE THAN ONE pane. ANSA // refuses rather than picking one. See the note on given-names below. AnsaErrAmbiguousTarget = "ambiguous_target" // AnsaErrUnreachable — the target pane exists in the layout but did not // answer a liveness probe, so publishing to its inbox would be a write into // a subject nobody is reading. AnsaErrUnreachable = "unreachable" // AnsaErrBadMode — an unrecognised delivery mode. NOT defaulted silently: // a typo'd mode that quietly became a shell command is a message delivered // as something other than what the sender meant. AnsaErrBadMode = "bad_mode" // AnsaErrPublishFailed — the transport itself refused. AnsaErrPublishFailed = "publish_failed" // AnsaErrNotAnID — the router was handed a NAME where an id belongs. The // caller skipped edge resolution. Its own code because it is a caller bug // with a specific fix ("resolve the @name first"), not a missing pane. AnsaErrNotAnID = "not_an_id" // AnsaErrDirectory — ANSA could not enumerate the session's panes, so it // cannot know whether the target exists. Distinct from unknown_target on // purpose: "I looked and it is not there" and "I could not look" are // different facts, and only one of them means the caller should give up. AnsaErrDirectory = "directory_unavailable" )
Refusal codes. Every one of these is a message that did NOT get delivered and a caller that WAS told so.
They are exhaustive by construction: the router's only success path returns OK, and every other branch sets one of these. A new failure mode must add a code here, which is a visible edit rather than a silent `return nil`.
const ( BoardKindMilestone = "milestone" BoardKindTaskDone = "task-done" BoardKindBlocked = "blocked" BoardKindReply = "reply" )
Board message kinds. Kind is deliberately a free-form string rather than an enum: fleetctl's --kind is already free-form (it carries WORK ORDER, REPORT, PROGRESS, BLOCKED, NUDGE and whatever an agent invents next), and the board must render an unknown kind rather than drop the message. These are the well-known values, not the permitted set.
const ( TagProxyRequestAudit = sharedmsg.TagProxyRequestAudit TagProxyAuditSnapshotRequest = sharedmsg.TagProxyAuditSnapshotRequest TagProxyAuditSnapshotReply = sharedmsg.TagProxyAuditSnapshotReply ProxyBudgetOK = sharedmsg.ProxyBudgetOK ProxyBudgetExceeded = sharedmsg.ProxyBudgetExceeded ProxyBudgetRateLimited = sharedmsg.ProxyBudgetRateLimited ProxyBlocked = sharedmsg.ProxyBlocked )
const ( ConvShell = sharedmsg.ConvShell ConvAI = sharedmsg.ConvAI ConvRysh = sharedmsg.ConvRysh ConvChat = sharedmsg.ConvChat ConvEmail = sharedmsg.ConvEmail ConvSlack = sharedmsg.ConvSlack ConvChatbot = sharedmsg.ConvChatbot )
Conversation type constants
const ( TurnQuestion = sharedmsg.TurnQuestion TurnAnswer = sharedmsg.TurnAnswer )
Turn type constants
const ( InputShell = sharedmsg.InputShell InputPrompt = sharedmsg.InputPrompt InputCommand = sharedmsg.InputCommand InputApproval = sharedmsg.InputApproval InputMessage = sharedmsg.InputMessage )
Input type constants
const ( SourceHuman = sharedmsg.SourceHuman SourceAI = sharedmsg.SourceAI SourceExternal = sharedmsg.SourceExternal SourceAgent = sharedmsg.SourceAgent SourceSubagent = sharedmsg.SourceSubagent SourceHumanoid = sharedmsg.SourceHumanoid SourceSystem = sharedmsg.SourceSystem )
Message source constants
const ( // Output tags TagPaneOutputAppend = sharedmsg.TagPaneOutputAppend TagPaneShellOutputAppend = sharedmsg.TagPaneShellOutputAppend TagPaneAIOutputAppend = sharedmsg.TagPaneAIOutputAppend TagPaneChatOutputAppend = sharedmsg.TagPaneChatOutputAppend TagPaneRyshOutputAppend = sharedmsg.TagPaneRyshOutputAppend TagPaneExternalOutputAppend = sharedmsg.TagPaneExternalOutputAppend TagPaneStatusUpdate = sharedmsg.TagPaneStatusUpdate TagPipelineOutputAppend = sharedmsg.TagPipelineOutputAppend // History tags TagPaneHistoryAppend = sharedmsg.TagPaneHistoryAppend TagPaneShellHistoryAppend = sharedmsg.TagPaneShellHistoryAppend TagPaneAIHistoryAppend = sharedmsg.TagPaneAIHistoryAppend TagPaneChatHistoryAppend = sharedmsg.TagPaneChatHistoryAppend TagPaneRyshHistoryAppend = sharedmsg.TagPaneRyshHistoryAppend TagPaneExternalHistoryAppend = sharedmsg.TagPaneExternalHistoryAppend // Unified conversation tags (new) TagConversationAppend = sharedmsg.TagConversationAppend TagConversationHistoryAppend = sharedmsg.TagConversationHistoryAppend // Agentic tags TagAgenticPrompt = sharedmsg.TagAgenticPrompt TagAgenticCancel = sharedmsg.TagAgenticCancel TagOrchestratorDone = sharedmsg.TagOrchestratorDone TagToolCall = sharedmsg.TagToolCall TagToolResult = sharedmsg.TagToolResult TagAgenticOutput = sharedmsg.TagAgenticOutput TagAgenticStatus = sharedmsg.TagAgenticStatus TagApprovalRequest = sharedmsg.TagApprovalRequest TagApprovalResponse = sharedmsg.TagApprovalResponse TagSpawnSubOrchestrator = sharedmsg.TagSpawnSubOrchestrator TagSubOrchestratorResult = sharedmsg.TagSubOrchestratorResult TagGetConversationHistory = sharedmsg.TagGetConversationHistory TagConversationHistoryReply = sharedmsg.TagConversationHistoryReply TagRestoreConversation = sharedmsg.TagRestoreConversation TagSetChatOutputPane = sharedmsg.TagSetChatOutputPane TagCreateApprovalPane = sharedmsg.TagCreateApprovalPane TagDestroyApprovalPane = sharedmsg.TagDestroyApprovalPane TagPaneSetApprovalPaneGroups = sharedmsg.TagPaneSetApprovalPaneGroups TagMemoryStateUpdate = sharedmsg.TagMemoryStateUpdate // Memory tags TagMemoryAppend = sharedmsg.TagMemoryAppend TagMemoryGet = sharedmsg.TagMemoryGet TagMemoryGetReply = sharedmsg.TagMemoryGetReply TagMemorySummarize = sharedmsg.TagMemorySummarize TagMemorySummarizeDone = sharedmsg.TagMemorySummarizeDone // Approval decision constants ApprovalTypeDiff = sharedmsg.ApprovalTypeDiff ApprovalTypeDestructive = sharedmsg.ApprovalTypeDestructive ApprovalTypeChoice = sharedmsg.ApprovalTypeChoice ApprovalTypeQuestion = sharedmsg.ApprovalTypeQuestion DecisionYes = sharedmsg.DecisionYes DecisionYesAlways = sharedmsg.DecisionYesAlways DecisionNo = sharedmsg.DecisionNo DecisionNoWithExplanation = sharedmsg.DecisionNoWithExplanation DecisionChoiceSelected = sharedmsg.DecisionChoiceSelected )
const ( TagUsageRecord = sharedmsg.TagUsageRecord TagUsageCheck = sharedmsg.TagUsageCheck TagUsageCheckReply = sharedmsg.TagUsageCheckReply TagUsageSnapshotRequest = sharedmsg.TagUsageSnapshotRequest TagUsageSnapshotReply = sharedmsg.TagUsageSnapshotReply TagUsageBudgetSet = sharedmsg.TagUsageBudgetSet UsageSourceAgent = sharedmsg.UsageSourceAgent UsageSourceProxy = sharedmsg.UsageSourceProxy UsageSourceEval = sharedmsg.UsageSourceEval UsageSourceCI = sharedmsg.UsageSourceCI UsageScopePane = sharedmsg.UsageScopePane UsageScopeTenant = sharedmsg.UsageScopeTenant )
const AnsaSchemaVersion = 1
AnsaSchemaVersion is stamped on every route request, from the first release, for the same reason the board's is: a router that cannot tell v1 from v2 cannot be changed later without breaking every live agent.
const BoardAliveReply = "recording"
BoardAliveReply is what a live recorder answers. The content is deliberately trivial: the fact that a reply arrived at all is the signal.
const BoardSchemaVersion = 1
BoardSchemaVersion is stamped on every board message from the first release. A board that cannot tell v1 from v2 cannot be changed later without breaking every live agent, so this ships before there is anything to be compatible with.
const DefaultBoardID = "session"
DefaultBoardID names the session board: the one every claude can post to and the one a pane with no board of its own belongs to.
It is a NAME, not a subject token. IsDefaultBoard is what decides the wire shape, and for this id the wire shape is the legacy three-token subject.
const MaxBoardIDLen = 32
MaxBoardIDLen bounds a board id. A board id becomes a SUBJECT TOKEN and, through internal/board, a KV key prefix; both are cheaper to keep short than to explain later.
Variables ¶
var ( ProxyAuditSubject = sharedmsg.ProxyAuditSubject ProxyAuditWildcardSubject = sharedmsg.ProxyAuditWildcardSubject ProxyAuditInboxSubject = sharedmsg.ProxyAuditInboxSubject )
var ( NewTurnID = sharedmsg.NewTurnID NowMs = sharedmsg.NowMs NewShellQuestion = sharedmsg.NewShellQuestion NewShellAnswer = sharedmsg.NewShellAnswer NewAIQuestion = sharedmsg.NewAIQuestion NewAIAnswer = sharedmsg.NewAIAnswer NewRyshQuestion = sharedmsg.NewRyshQuestion NewRyshAnswer = sharedmsg.NewRyshAnswer NewChatMessage = sharedmsg.NewChatMessage NewChannelMessage = sharedmsg.NewChannelMessage )
Constructor aliases
var ( NewMemoryEntry = sharedmsg.NewMemoryEntry FormatMemoryForPrompt = sharedmsg.FormatMemoryForPrompt MemorySummarizationPrompt = sharedmsg.MemorySummarizationPrompt )
Memory constructor and helper aliases
var ( UsageSubject = sharedmsg.UsageSubject UsageWildcardSubject = sharedmsg.UsageWildcardSubject UsageCheckSubject = sharedmsg.UsageCheckSubject UsageInboxSubject = sharedmsg.UsageInboxSubject )
var InitMsgLog = sharedmsg.InitMsgLog
var MsgLog = sharedmsg.MsgLog
var NewCodecRegistry = sharedmsg.NewCodecRegistry
var NewNATSPublisher = sharedmsg.NewNATSPublisher
var SessionPrefix = sharedmsg.SessionPrefix
SessionPrefix returns the current NATS subject prefix.
var SetSessionPrefix = sharedmsg.SetSessionPrefix
SetSessionPrefix sets the NATS subject prefix for this session. All subjects constructed by T() and by rysh-shared publishers will use this prefix.
var T = sharedmsg.T
T constructs a NATS subject by joining the session prefix with the given parts. Delegates to rysh-shared/msg so that the session prefix is consistent across all publishers (CLI actors and shared agentic actors).
Functions ¶
func AnsaInboxSubject ¶ added in v0.2.4
func AnsaInboxSubject() string
AnsaInboxSubject is where the router listens. Session-scoped like every other subject: msg.T renders the session prefix, so this is never a literal.
func BoardAlivePattern ¶ added in v0.2.6
func BoardAlivePattern() string
BoardAlivePattern is the wildcard a recorder subscribes to in order to answer for every named board. Like the post pattern, it does not match the default board's shorter subject.
func BoardAliveSubject ¶ added in v0.2.4
BoardAliveSubject is where the recorder answers "are you recording?".
A REQUEST, not a heartbeat. Every failure on this track came from inferring state from a proxy — a pane's idle flag, send.ok, os.path.isfile, a persisted roster entry, a KV revision. A heartbeat is one more proxy: it reports that something wrote a key recently, which is not the same as a recorder being alive now, and it needs a staleness threshold that can be wrong under load.
Asking the recorder directly has no threshold to tune, and a timeout tests the ACTUAL path rather than an artifact's freshness. It also keeps liveness out of the board's KV bucket, where a second writer to that bucket would falsify the single-writer detector in internal/actors/abla_test.go — that bucket's precondition is "nothing else writes here", and liveness has no business breaking it. Per board since design 028: a caller asks whether the recorder for a NAMED board is listening. One recorder serves every board in a session today (internal/actors/abla.go), so every board's alive subject is answered by the same actor — but the subject is per board so that stays an implementation detail rather than something callers encode.
func BoardIDFromMeta ¶ added in v0.2.6
BoardIDFromMeta resolves which board a PANE reads and posts to, from the value of its `board.id` meta.
ONE PREDICATE, TWO SURFACES. The TUI renders board panes itself (tui.Model.boardIDForPane) and the web server answers the app's board_get with the same question; before this existed the TUI owned the only copy, and the second surface would have had to restate it. That restatement is the F-18 shape design 025 §8b puts a rule in one predicate to avoid — and here it would be invisible, because both copies return a VALID board id. They would simply return different ones, and the app would confidently render a board the TUI does not show for the same pane.
An empty or INVALID id is the session board rather than an error, matching boardSubject's fallback: a pane whose meta was hand-edited to something unusable still belongs somewhere, and the session board is where an unattributed pane belongs. Callers that took an id from a human — the CLI's --board, ##board open — must keep REFUSING instead; this is the pane-meta edge, where there is nobody to tell.
func BoardIDFromSubject ¶ added in v0.2.6
BoardIDFromSubject extracts the board a delivered message was addressed to.
It parses from the END, never by counting from the front: T's prefix is the session name (rysh-shared/msg/topics.go), and a session name is free-form enough to contain a dot. Counting tokens from the left would then read part of the session name as a board id — the sort of failure that shows up as an empty board rather than as an error.
<session>.board.post → ("session", true)
<session>.board.epic-07.post → ("epic-07", true)
<session>.pane.x.output → ("", false)
func BoardPersona ¶ added in v0.2.4
BoardPersona resolves a display name for a pane, in the order the board renders it: given-name, then the auto-generated title, then "pane-<8>".
It never returns an empty string and never returns the literal "no-name" that ##pane info prints for an unnamed pane — an unnamed agent still needs a stable label to be followed by.
The approval-pane guard is not hypothetical: approval panes OVERLOAD GivenName to carry "requestID\x1FresponseSubject" for the TUI (internal/actors/approval_pane.go). Rendering that blindly would one day print a NATS subject as somebody's name, so a name carrying the unit separator is rejected and falls through to the next candidate.
func BoardPostPattern ¶ added in v0.2.6
func BoardPostPattern() string
BoardPostPattern / BoardRegisterPattern are the wildcard subjects a subscriber uses to hear EVERY named board at once.
They deliberately do NOT match the default board: its subject has one token fewer, so a subscriber that wants everything takes the pattern AND the legacy subject. That is board.Subscribe's job, and it is why these are exported next to the builders rather than assembled at the call site.
func BoardPostSubject ¶ added in v0.2.4
BoardPostSubject is the subject agents post to and a board view subscribes to, for ONE board (design 028; board ids in board_id.go).
The empty string and DefaultBoardID both mean the session board, whose subject is unchanged from before board ids existed — see the wire-shape note in board_id.go.
func BoardQueryPattern ¶ added in v0.2.6
func BoardQueryPattern() string
BoardQueryPattern is the wildcard the recorder serves every named board on.
func BoardQuerySubject ¶ added in v0.2.6
BoardQuerySubject is where the recorder answers "what is ON the board?".
A SECOND REQUEST SUBJECT IN THE SHAPE OF BoardAliveSubject, deliberately, and served by the same actor for the same two reasons.
ASK THE RECORDER, DO NOT READ THE TRACE IT LEFT (design 026 §5.4). ABLA holds the authoritative in-memory board — restored from the KV at start and fed by the live subscription since. Its answer is what the session actually heard. The KV is a durable copy of that, one restore behind, and reading it would be inferring the board's state from an artifact instead of asking the thing that owns it.
F-23 IS WHAT HAPPENS WHEN A SECOND CALL SITE DERIVES THE BUCKET NAME. runAttachUI built a bus.Config with no SessionName, so an attaching TUI opened rysh-board-default while the daemon wrote rysh-board-<session>. Subjects were fine; only the restore was dead, and it failed LOOKING HEALTHY — an empty board renders identically to a quiet one. A read path that goes through this subject cannot reintroduce that: it has no bucket name to get wrong, and a recorder that does not answer is an ERROR rather than an empty result (board.ErrNoRecorder).
func BoardRegisterPattern ¶ added in v0.2.6
func BoardRegisterPattern() string
func BoardRegisterSubject ¶ added in v0.2.4
BoardRegisterSubject carries persona announcements for one board.
func FleetQuerySubject ¶ added in v0.2.6
func FleetQuerySubject() string
FleetQuerySubject is where the fleet actor answers "what fleets exist?".
SAME SHAPE AND SAME REASON AS BoardQuerySubject: a reader ASKS THE ACTOR that owns the registry rather than opening the KV bucket at a second call site. F-23 is what happens when a second call site derives a bucket name — the read failed while LOOKING HEALTHY, because an empty answer and a wrong bucket are indistinguishable.
func FleetUpdateSubject ¶ added in v0.2.6
func FleetUpdateSubject() string
FleetUpdateSubject is where the fleet actor accepts registrations, membership changes and state transitions.
func IsDefaultBoard ¶ added in v0.2.6
IsDefaultBoard reports whether id addresses the session board.
func MintThreadID ¶ added in v0.2.4
MintThreadID builds a thread id the poster owns outright: "<pane-uuid>/<n>".
It is derived from the FULL pane uuid, not the persona and not the envelope's 8-char truncation, so two agents can never mint colliding ids even when they share a given-name across lanes. No round trip to the board is involved, which is what lets an agent open a thread while blind to the board — and what makes a retried post idempotent instead of minting a second root.
func NormalizeBoardID ¶ added in v0.2.6
NormalizeBoardID maps the several spellings of "the session board" onto one. An empty id, the default id itself, and any case variant of it are the same board. Everything else is returned lower-cased and otherwise untouched — this does NOT sanitise; ValidateBoardID is what rejects.
func SendBoardPost ¶ added in v0.2.4
func SendBoardPost(p *NATSPublisher, board string, post *MsgBoardPost) error
SendBoardPost publishes one board message.
Package-level, not a method, for the reason given at the top of this file: NATSPublisher is a type alias for a rysh-shared type and Go does not allow methods on aliased external types.
The caller stamps V and TS via NewBoardPost rather than having them filled in here, so that a post relayed from elsewhere keeps its original clock. The board is named by the CALLER and is not carried in the post: passing "" posts to the session board, which is what every non-fleet claude does.
func SendBoardRegister ¶ added in v0.2.4
func SendBoardRegister(p *NATSPublisher, board string, reg *MsgBoardRegister) error
SendBoardRegister publishes a persona announcement. Advisory: the board renders posts from unregistered panes too.
func SendMirrorPaneVTFrame ¶
func SendMirrorPaneVTFrame(p *NATSPublisher, mirrorID string, f *MsgMirrorPaneVTFrame) error
SendMirrorPaneVTFrame PUSHES a keyframe/delta VT frame directly on the per-pane topic rysh.pane.{mirrorID}.vtframe — no request/reply, no WorkspaceActor mailbox hop. It is the steady-state path for an interactive mirror pane's live screen: the WorkspaceActor marshals once at update time and the TUI subscriber applies it against its last-applied seq (keyframe + delta, sequence-numbered). Fire-and-forget; a dropped frame becomes a seq gap healed by the TUI's resync pull (MsgGetMirrorPaneVT).
func SendPaneRawDirty ¶
func SendPaneRawDirty(p *NATSPublisher, paneID string) error
SendPaneRawDirty publishes a tiny notification that a pane's raw VT screen has changed. The TUI subscribes via wildcard and uses it to drive a push-based, per-change fetch of raw panes instead of the legacy 50ms poll of every visible raw pane. Fire-and-forget; dropped messages are healed by the longer-interval reconcile tick. Best-effort error semantics match the other sharing helpers above.
func SendRawOutput ¶
func SendRawOutput(p *NATSPublisher, paneID string, data []byte) error
SendRawOutput publishes raw PTY bytes (base64-encoded) for interactive sharing. This is a package-level function because NATSPublisher is a type alias from rysh-shared/msg and Go does not allow adding methods to aliased external types.
func SendShareModeChange ¶
func SendShareModeChange(p *NATSPublisher, paneID string, interactive bool, rows, cols int) error
SendShareModeChange publishes an interactive mode transition for sharing.
func ValidateBoardID ¶ added in v0.2.6
ValidateBoardID rejects anything that cannot safely be a subject token.
THIS IS A SUBJECT-INJECTION GUARD, not a style preference. A board id ends up between "board" and "post" in a NATS subject, so an id containing "." would silently publish into a subject nobody subscribes to, and an id of "*" or ">" would publish into (or subscribe to) EVERY board. Both failures are silent at the publisher and invisible at the board that should have received the post, which is why this is checked at every edge that accepts an id from a human, a flag, or pane meta.
Types ¶
type AgentInfo ¶
type AgentInfo struct {
Name string `json:"name"`
Active bool `json:"active"`
SystemPrompt string `json:"system_prompt"`
RegisteredPanes []string `json:"registered_panes,omitempty"`
// WorktreePath is the agent's isolation worktree (design 008), "" when the
// agent runs on the shared checkout. Surfaced so the worktree lifecycle can
// refuse to auto-remove a worktree a live agent still claims.
WorktreePath string `json:"worktree_path,omitempty"`
}
AgentInfo describes an agent's state.
type ApprovalDecision ¶
type ApprovalDecision = sharedmsg.ApprovalDecision
type ApprovalType ¶
type ApprovalType = sharedmsg.ApprovalType
type AttachmentInfo ¶
type AttachmentInfo struct {
Filename string `json:"filename"`
ContentType string `json:"content_type"`
Size int `json:"size"`
}
AttachmentInfo describes an email attachment without the full data.
type AttentionCategory ¶
type AttentionCategory string
AttentionCategory identifies the source of an attention event.
const ( AttentionApproval AttentionCategory = "approval" AttentionSlack AttentionCategory = "slack" AttentionEmail AttentionCategory = "email" AttentionChatbot AttentionCategory = "chatbot" AttentionWhatsApp AttentionCategory = "whatsapp" AttentionPhone AttentionCategory = "phone" )
type AttentionPriority ¶
type AttentionPriority int
AttentionPriority defines urgency levels.
const ( AttentionPriorityLow AttentionPriority = 0 AttentionPriorityNormal AttentionPriority = 1 AttentionPriorityHigh AttentionPriority = 2 AttentionPriorityCritical AttentionPriority = 3 )
type BoardIDError ¶ added in v0.2.6
BoardIDError is a rejected board id, carrying what was wrong so the surface that took the id can say it back to whoever typed it.
func (*BoardIDError) Error ¶ added in v0.2.6
func (e *BoardIDError) Error() string
type ChannelConfig ¶
type ChannelConfig struct {
// Common
Enabled bool `json:"enabled" yaml:"enabled"`
ReplyMode string `json:"reply_mode,omitempty" yaml:"reply_mode"` // "messages" (default) or "mentions"
// WhatsApp (Meta Cloud API). Phone is the numeric phone_number_id (NOT the
// display number); APIKey is the Graph API access token. Inbound arrives via
// a local webhook server the adapter runs on WebhookPort: VerifyToken answers
// Meta's GET verification handshake (hub.verify_token) and AppSecret, when
// set, validates the X-Hub-Signature-256 HMAC on inbound POSTs. GraphVersion
// overrides the default Graph API version. (AppSecret is also the Teams bot
// client secret — see the Teams block below.)
Phone string `json:"phone,omitempty" yaml:"phone"`
APIKey string `json:"api_key,omitempty" yaml:"api_key"`
BusinessID string `json:"business_id,omitempty" yaml:"business_id"`
VerifyToken string `json:"verify_token,omitempty" yaml:"verify_token"`
AppSecret string `json:"app_secret,omitempty" yaml:"app_secret"`
WebhookPort string `json:"webhook_port,omitempty" yaml:"webhook_port"` // string so it can hold a ${SECRET}; parsed to int by the adapter
GraphVersion string `json:"graph_version,omitempty" yaml:"graph_version"`
// Governance controls inbound handling: "ai" (default, auto-reply) or "human"
// (inbound is displayed only; the human drives list/read/draft/approve/send via
// the whatsapp_* tools). Mirrors EmailChannelConfig.Governance.
Governance string `json:"governance,omitempty" yaml:"governance"`
// Relay mode. When true the adapter does NOT run a local webhook listener or
// hold platform credentials; inbound arrives over the upstream rysh-server on
// ws.{RelayWorkspaceID}.{type}.{RelayConnectionID}.inbound and outbound is
// published to the sibling .outbound subject, where the server delivers it
// using the credentials it already stores.
//
// This is what lets a humanoid run on a laptop behind NAT: the session dials
// out to the server rather than needing to be reachable by the platform.
Relay bool `json:"relay,omitempty" yaml:"relay"`
RelayURL string `json:"relay_url,omitempty" yaml:"relay_url"`
RelayAPIKey string `json:"relay_api_key,omitempty" yaml:"relay_api_key"`
RelayWorkspace string `json:"relay_workspace,omitempty" yaml:"relay_workspace"`
RelayWorkspaceID string `json:"relay_workspace_id,omitempty" yaml:"relay_workspace_id"`
RelayConnectionID string `json:"relay_connection_id,omitempty" yaml:"relay_connection_id"`
// Slack
BotToken string `json:"bot_token,omitempty" yaml:"bot_token"`
AppToken string `json:"app_token,omitempty" yaml:"app_token"`
Channels []string `json:"channels,omitempty" yaml:"channels"`
// Email — type selects the provider (e.g. "gmail"), config holds all
// connection details (IMAP/SMTP hosts, ports, credentials).
EmailType string `json:"type,omitempty" yaml:"type"`
EmailConfig *EmailChannelConfig `json:"config,omitempty" yaml:"config"`
// Phone / SMS (Twilio). Number is the sending number in E.164 ("+15550100")
// — it is also the Signal account id, so the two channels share the field.
// AccountSID/AuthToken are the Twilio REST credentials. Inbound arrives via
// a loopback webhook server on WebhookPort, which the operator exposes with
// a tunnel; WebhookURL is that public URL and is what makes inbound
// signature validation possible (Twilio signs the URL it requested, so the
// adapter cannot reconstruct it from the loopback request alone).
//
// SMS/MMS only: voice calls are not handled. A voice webhook reaching this
// endpoint is logged and rejected rather than answered.
Number string `json:"number,omitempty" yaml:"number"`
Provider string `json:"provider,omitempty" yaml:"provider"`
AccountSID string `json:"account_sid,omitempty" yaml:"account_sid"`
AuthToken string `json:"auth_token,omitempty" yaml:"auth_token"`
// Microsoft Teams (Azure Bot Service / Bot Framework). AppID is the bot's
// Microsoft App (client) ID and AppSecret its client secret — the same
// AppSecret field WhatsApp uses for HMAC validation, since a channel only
// ever means one of the two. TenantID selects the Entra tenant for a
// single-tenant bot; empty uses the multi-tenant "botframework.com"
// authority. Inbound arrives via a loopback webhook on WebhookPort (the
// Azure Bot's Messaging Endpoint points at the operator's tunnel), and
// every inbound activity's Bot Framework JWT is verified — there is no
// switch to turn that off.
AppID string `json:"app_id,omitempty" yaml:"app_id"`
TenantID string `json:"tenant_id,omitempty" yaml:"tenant_id"`
// Chatbot (local HTTP server mode)
WebhookURL string `json:"webhook_url,omitempty" yaml:"webhook_url"`
CORSOrigins []string `json:"cors_origins,omitempty" yaml:"cors_origins"`
ListenPort int `json:"listen_port,omitempty" yaml:"listen_port"`
// Chatbot (remote server mode — CLI connects to rysh-server chatbot panes).
// WorkspaceID is required: every operator-side chatbot route on rysh-server
// is nested under /api/workspaces/:wsID/chatbots/:id/... (X2).
ServerURL string `json:"server_url,omitempty" yaml:"server_url"`
WorkspaceID string `json:"workspace_id,omitempty" yaml:"workspace_id"`
ConfigID string `json:"config_id,omitempty" yaml:"config_id"`
AutoTakeover bool `json:"auto_takeover,omitempty" yaml:"auto_takeover"`
TakeoverKeywords []string `json:"takeover_keywords,omitempty" yaml:"takeover_keywords"`
// Mode is a channel-polysemous transport selector.
// Telegram: "poll" (default, getUpdates long-poll — needs no public
// endpoint) or "webhook" (reuses WebhookPort/WebhookURL). BotToken and
// Channels are shared with Slack/Discord.
// WhatsApp: "direct" (default) runs the local webhook server + direct Graph
// API sends using the WhatsApp fields above; "relay" routes inbound and
// outbound through rysh-server's channel relay over the upstream NATS bus
// (ws.{workspace}.whatsapp.{connection}.inbound/outbound), so the platform
// access token stays server-side, no local webhook port is bound, and the
// connection id is resolved from the workspace's enabled WhatsApp External
// Connection. Relay mode requires an enabled [upstream] connection
// (URL + api_key + workspace).
// The canonical relay spelling is `relay: true` (the Relay field above);
// `mode: relay` is an accepted alias that the humanoid skill-file parser
// folds into Relay at load. Any other value than "relay"/"direct" — or a
// conflict between the two spellings — fails the skill-file load loudly
// (see actors.normalizeWhatsAppRelayMode). The adapter itself reads only
// Relay, never Mode.
Mode string `json:"mode,omitempty" yaml:"mode"`
// WhatsApp GA (out-of-window re-engagement). DefaultTemplate names a
// pre-approved Meta template used when the 24h customer-service window has
// closed; TemplateLang is its language code (e.g. "en_US").
DefaultTemplate string `json:"default_template,omitempty" yaml:"default_template"`
TemplateLang string `json:"template_lang,omitempty" yaml:"template_lang"`
// Signal (signal-cli sidecar). SidecarAddr is the JSON-RPC endpoint of a
// signal-cli daemon (UNIX socket path or host:port); SidecarCmd optionally
// names a command rysh spawns to launch the daemon itself.
SidecarAddr string `json:"sidecar_addr,omitempty" yaml:"sidecar_addr"`
SidecarCmd string `json:"sidecar_cmd,omitempty" yaml:"sidecar_cmd"`
// Link, when true, runs the signal-cli device-link flow on Start
// (startLink → QR → finishLink) via the PairingChannel path (X4, design
// 009). It is a first-run/onboarding switch: leaving it set re-links on
// every start (signal-cli provisions a fresh linked device each time), so
// it is meant to be turned on once. Requires an account-less daemon.
Link bool `json:"link,omitempty" yaml:"link"`
// iMessage (macOS host bridge). DBPath overrides the default
// ~/Library/Messages/chat.db location (mainly for testing).
DBPath string `json:"db_path,omitempty" yaml:"db_path"`
// Contact pairing & allowlists (WS3, design 003). Allowlist is the declared
// seed of pre-approved SenderIDs, merged into the runtime PairingStore at
// spawn (${ENV} references are expanded like other channel fields).
// PairingPolicy selects how a non-allowlisted sender is handled: "request"
// (default — a pending pairing request a human approves) or "drop"
// (discarded with a log line), or "open" (an EXPLICIT opt-out: ungated on
// purpose, which `rysh doctor` accepts silently).
//
// A channel with NO allowlist and NO pairing_policy follows the session
// default `humanoid_defaults.pairing_default` (RYSH_PAIRING_DEFAULT):
// "open" (the shipped default, pre-WS3 behaviour) admits every sender;
// "closed" gates it with policy "request" per design 003 G5. Until the
// default is set to closed, `rysh doctor` WARNs for each such channel.
Allowlist []string `json:"allowlist,omitempty" yaml:"allowlist"`
PairingPolicy string `json:"pairing_policy,omitempty" yaml:"pairing_policy"`
}
ChannelConfig describes the configuration for a single communication channel.
type ChannelStatus ¶
type ChannelStatus struct {
Type string `json:"type"` // "whatsapp", "slack", "email", "phone", "chatbot"
Connected bool `json:"connected"`
Error string `json:"error,omitempty"`
Details string `json:"details,omitempty"` // e.g. "listening on #support, #engineering"
}
ChannelStatus reports the state of one communication channel.
type CodecRegistry ¶
type CodecRegistry = sharedmsg.CodecRegistry
func DefaultCodecRegistry ¶
func DefaultCodecRegistry() *CodecRegistry
DefaultCodecRegistry returns a CodecRegistry pre-registered with all message types: shared agentic/output types (from rysh-shared) plus CLI-specific workspace routing, snapshot, and sharing messages.
type ConversationMessage ¶
type ConversationMessage = sharedmsg.ConversationMessage
type ConversationTurnInfo ¶
type ConversationTurnInfo = sharedmsg.ConversationTurnInfo
type ConversationType ¶
type ConversationType = sharedmsg.ConversationType
type DiffPayload ¶
type DiffPayload = sharedmsg.DiffPayload
type Direction ¶
type Direction string
Direction represents a navigation direction for consolidated focus messages.
type EmailChannelConfig ¶
type EmailChannelConfig struct {
Governance string `json:"governance,omitempty" yaml:"governance"` // "ai" (default) or "human"
Address string `json:"address,omitempty" yaml:"address"`
IMAPHost string `json:"imap_host,omitempty" yaml:"imap_host"`
IMAPPort int `json:"imap_port,omitempty" yaml:"imap_port"`
SMTPHost string `json:"smtp_host,omitempty" yaml:"smtp_host"`
SMTPPort int `json:"smtp_port,omitempty" yaml:"smtp_port"`
Username string `json:"username,omitempty" yaml:"username"`
Password string `json:"password,omitempty" yaml:"password"`
}
EmailChannelConfig holds all connection details for an email channel: IMAP/SMTP hosts, ports, and credentials.
type EmailDetail ¶
type EmailDetail struct {
ID string `json:"id"` // short 4-char handle for prompts
UID int `json:"uid"`
From string `json:"from"`
To string `json:"to"`
Subject string `json:"subject"`
Date string `json:"date"`
Body string `json:"body"`
MessageID string `json:"message_id"`
InReplyTo string `json:"in_reply_to"`
Attachments []AttachmentInfo `json:"attachments,omitempty"`
}
EmailDetail holds the full content of a single email.
type EmailSummary ¶
type EmailSummary struct {
ID string `json:"id"` // short 4-char handle for prompts (stable per session)
UID int `json:"uid"`
From string `json:"from"`
Subject string `json:"subject"`
Date string `json:"date"`
Snippet string `json:"snippet"`
MessageID string `json:"message_id"`
InReplyTo string `json:"in_reply_to"`
}
EmailSummary holds a brief overview of an email for listing. MessageID and InReplyTo are carried so a UI can thread messages and identify which email to act on (e.g. set reply In-Reply-To) without a full ReadEmail.
type ForgedInvokeRequest ¶
type ForgedInvokeRequest struct {
Op string `json:"op"`
Args json.RawMessage `json:"args,omitempty"`
// Auth, when non-empty, is the SUBSCRIBER's current access token (forged-API
// auth plan, Model B / delegated identity). The owner injects it as the bearer
// for this one call so the backend enforces the subscriber's authorization,
// then discards it — it is never cached, persisted, or logged. It is carried
// out-of-band from Args (so it is excluded from arg-schema validation) and is
// honored ONLY when the owner's share opted into delegated auth.
Auth string `json:"auth,omitempty"`
}
ForgedInvokeRequest is the payload a subscriber sends to invoke a shared forge-origin operation (Task 2, phase 2b). It travels inside a MsgUpstreamCommand of CommandType "invoke_op" (Payload = JSON of this struct) and, on the subscriber side, as the body of the local invoke request to the RemoteShareListenerActor. Op is the forge tool name (e.g. "weather_getWeather"); Args is the tool's input JSON.
type ForgedInvokeResult ¶
type ForgedInvokeResult struct {
Content string `json:"content,omitempty"`
Error string `json:"error,omitempty"`
ErrorKind string `json:"error_kind,omitempty"`
}
ForgedInvokeResult is the owner's reply to a ForgedInvokeRequest. It mirrors tools.ToolOutput's user-facing fields so the subscriber proxy can reconstruct a ToolOutput. Content is redacted on the owner side when the share's --redact is on (the default). ErrorKind uses the tools.ErrKind* taxonomy.
type ForgedOpSpec ¶
type ForgedOpSpec struct {
Name string `json:"name"`
Description string `json:"description"`
Schema string `json:"schema"`
Mutating bool `json:"mutating"`
}
ForgedOpSpec describes one shareable forged-API operation (Task 2 phase 2a). Name is the forge operation/tool name (e.g. "weather_getWeather"); Schema is the operation's JSON-schema text; Mutating is true for non-GET/HEAD operations.
type GroundingReportInfo ¶
type GroundingReportInfo = sharedmsg.GroundingReportInfo
type HumanoidInfo ¶
type HumanoidInfo struct {
Name string `json:"name"`
Active bool `json:"active"`
SystemPrompt string `json:"system_prompt"`
RegisteredPanes []string `json:"registered_panes,omitempty"`
Channels []ChannelStatus `json:"channels,omitempty"`
}
HumanoidInfo describes a humanoid's state.
type ImportCookie ¶
type ImportCookie struct {
Name string `json:"name"`
Value string `json:"value"`
Domain string `json:"domain"`
Path string `json:"path"`
Expires float64 `json:"expires"` // unix seconds; <=0 means a session cookie
HTTPOnly bool `json:"httpOnly"`
Secure bool `json:"secure"`
SameSite string `json:"sameSite"` // "Strict" | "Lax" | "None" | ""
}
ImportCookie is one browser cookie transferred from a real-Chrome login jar into the desktop app's Electron session partition. Fields/JSON tags mirror cdp.Cookie (from Storage.getCookies) so the wire payload is identical.
type LLMPickerModel ¶ added in v0.2.3
type LLMPickerModel struct {
Ref string `json:"ref"` // "<provider>/<name>" as declared in .rysh/llms
Model string `json:"model"` // provider API model id
Provider string `json:"provider"` // rysh provider family serving it
Current bool `json:"current"` // is the session default right now
// KeyMissing reports that this model's provider family has no API key in
// reach — neither ##secret nor the daemon environment — so a selection would
// fail to authenticate on the next prompt. KeyName is the variable to set
// (empty when the family needs no key, e.g. ollama).
KeyMissing bool `json:"key_missing,omitempty"`
KeyName string `json:"key_name,omitempty"`
}
LLMPickerModel is one activatable row of the picker.
type LLMPickerScope ¶ added in v0.2.3
type LLMPickerScope struct {
Name string `json:"name"` // "session", "workspace", "tab", "lane", "stack", "pane"
// Hint is the one-line explanation shown beside the name — how far the
// binding reaches, in the user's terms.
Hint string `json:"hint"`
// Command is the `##` command that binds the chosen model at this scope,
// missing only the model ref. The front-end appends the ref and submits it,
// so the scope hierarchy stays defined in one place: the daemon.
Command string `json:"command"`
}
LLMPickerScope is one binding level offered in step two of the picker.
type MemoryEntry ¶
type MemoryEntry = sharedmsg.MemoryEntry
type MemoryState ¶
type MemoryState = sharedmsg.MemoryState
type MessageLogger ¶
type MessageLogger = sharedmsg.MessageLogger
type MessageOrigin ¶
type MessageOrigin = sharedmsg.MessageOrigin
type MessageSource ¶
type MessageSource = sharedmsg.MessageSource
type MsgActivePaneReply ¶
MsgActivePaneReply carries the TabActor's active pane ID and pane count.
type MsgAgentActivate ¶
type MsgAgentActivate struct {
Name string `json:"name"`
}
MsgAgentActivate activates a deactivated agent.
type MsgAgentContinue ¶
type MsgAgentContinue struct {
Name string `json:"name"`
}
MsgAgentContinue resumes an agent's paused LLM run by name (used by @@agent-name continue). No-op with a notice when nothing is paused.
type MsgAgentCreate ¶
type MsgAgentCreate struct {
Name string `json:"name"`
SystemPrompt string `json:"system_prompt"`
WorktreeBranch string `json:"worktree_branch,omitempty"`
WorktreePath string `json:"worktree_path,omitempty"`
// AutoApprove carries the skill-file `auto_approve:` field. Nil = absent =
// the default, TRUE: an agent runs autonomously with no terminal, so a
// gated tool call would block on a dialog nobody can answer.
AutoApprove *bool `json:"auto_approve,omitempty"`
}
MsgAgentCreate creates a new autonomous agent. WorktreeBranch/WorktreePath record the agent's isolation worktree when one was provisioned at spawn (`isolation: worktree` frontmatter or `##agent spawn --worktree`, design 008); empty means the agent works on the shared checkout.
type MsgAgentDeactivate ¶
type MsgAgentDeactivate struct {
Name string `json:"name"`
}
MsgAgentDeactivate deactivates an agent (keeps state, stops processing).
type MsgAgentDelete ¶
type MsgAgentDelete struct {
Name string `json:"name"`
}
MsgAgentDelete deletes an agent by name.
type MsgAgentListReply ¶
type MsgAgentListReply struct {
Agents []AgentInfo `json:"agents"`
}
MsgAgentListReply carries the list of agents.
type MsgAgentPrompt ¶
type MsgAgentPrompt struct {
AgentName string `json:"agent_name"`
Prompt string `json:"prompt"`
SourcePaneID string `json:"source_pane_id"`
ScopeHint string `json:"scope_hint,omitempty"` // invoking pane's scope chain (resolved by the workspace)
}
MsgAgentPrompt sends a prompt to a named agent.
type MsgAgentRegisterPane ¶
type MsgAgentRegisterPane struct {
AgentName string `json:"agent_name"`
PaneID string `json:"pane_id"`
PaneName string `json:"pane_name"`
}
MsgAgentRegisterPane registers an agent to output to a specific pane.
type MsgAgentStop ¶
type MsgAgentStop struct {
Name string `json:"name"`
}
MsgAgentStop interrupts an agent's in-flight LLM run by name (used by @@agent-name stop). PAUSE semantics: the agent stays alive and its conversation state / session memory are preserved — MsgAgentContinue (or a new prompt) resumes from the checkpoint. Deleting an agent is a separate operation (MsgAgentDelete / ##agent delete).
type MsgAgentUnregisterPane ¶
type MsgAgentUnregisterPane struct {
AgentName string `json:"agent_name"`
PaneID string `json:"pane_id"`
}
MsgAgentUnregisterPane removes an agent's pane registration.
type MsgAgenticCancel ¶
type MsgAgenticCancel = sharedmsg.MsgAgenticCancel
type MsgAgenticContinue ¶
type MsgAgenticContinue = sharedmsg.MsgAgenticContinue
type MsgAgenticOutput ¶
type MsgAgenticOutput = sharedmsg.MsgAgenticOutput
type MsgAgenticPrompt ¶
type MsgAgenticPrompt = sharedmsg.MsgAgenticPrompt
type MsgAgenticStatus ¶
type MsgAgenticStatus = sharedmsg.MsgAgenticStatus
type MsgAgenticStep ¶
type MsgAgenticStep = sharedmsg.MsgAgenticStep
type MsgAnsaRoute ¶ added in v0.2.4
type MsgAnsaRoute struct {
V int `json:"v"` // AnsaSchemaVersion
// From is the sender's pane id, for attribution and for the audit line the
// target sees. Optional: a route from something that is not a pane (cron, a
// humanoid, a test) is legitimate and must not be refused for it.
From string `json:"from,omitempty"`
// To is the target's FULL PANE UUID. Always. A name never travels as an
// address.
//
// @name is resolved to an id at the EDGE — in the command that accepted the
// @ — never in the router. The reason is one layer below the board's:
// given-names are unique per LANE, not per session
// (TabActor.IsGivenNameTakenInLane), so a name is a label for humans and an
// id is an address. A name arriving here is AnsaErrNotAnID, because
// resolving it late would re-open the ambiguity the edge already closed.
//
// Ambiguity is therefore HANDLED rather than assumed away, which is why
// session-unique given-names are an improvement to this design and not a
// safety gate on it.
To string `json:"to"`
// Mode is AnsaModeShell or AnsaModePrompt. Empty means shell, which is the
// pane inbox's own default; anything else is AnsaErrBadMode.
Mode string `json:"mode,omitempty"`
Text string `json:"text"`
}
MsgAnsaRoute is a routing request: deliver Text to the pane named by To.
Published to T("ansa", "inbox") as a REQUEST — the reply is MsgAnsaRouteResult and is the whole point. Fire-and-forget would reintroduce exactly the silent drop this actor exists to prevent.
func NewAnsaRoute ¶ added in v0.2.4
func NewAnsaRoute(from, to, mode, text string) *MsgAnsaRoute
NewAnsaRoute stamps the schema version so V is never forgotten at a new call site — the same reason NewBoardPost exists.
type MsgAnsaRouteResult ¶ added in v0.2.4
type MsgAnsaRouteResult struct {
OK bool `json:"ok"`
// TargetPaneID is the FULL pane uuid the message was delivered to —
// resolved, never echoed back from the request. A caller that addressed by
// name learns which pane it actually reached.
TargetPaneID string `json:"target_pane_id,omitempty"`
// TargetPersona is that pane's display name, for the caller's own logs.
TargetPersona string `json:"target_persona,omitempty"`
// Code is one of the AnsaErr* constants when OK is false, and empty when
// OK is true.
Code string `json:"code,omitempty"`
Error string `json:"error,omitempty"`
// Candidates lists the panes an ambiguous name matched, so the caller can
// re-address by id without having to go and look. Only set for
// AnsaErrAmbiguousTarget — a refusal that tells you how to succeed.
Candidates []string `json:"candidates,omitempty"`
}
MsgAnsaRouteResult is the answer. OK is the only success; every false carries both a Code (to branch on) and an Error (to show a human).
func AnsaRefusal ¶ added in v0.2.4
func AnsaRefusal(code, format string, a ...any) *MsgAnsaRouteResult
AnsaRefusal builds a failed result. Constructing refusals through one function is what keeps "a code was set" from being a thing anyone has to remember at eight separate return statements.
type MsgApprovalRequest ¶
type MsgApprovalRequest = sharedmsg.MsgApprovalRequest
type MsgApprovalResponse ¶
type MsgApprovalResponse = sharedmsg.MsgApprovalResponse
type MsgAttentionAck ¶
type MsgAttentionAck struct {
PaneID string `json:"pane_id"`
}
MsgAttentionAck is published when the user acknowledges a pane's attention.
type MsgAttentionDisable ¶
type MsgAttentionDisable struct {
PaneID string `json:"pane_id,omitempty"`
HumanoidName string `json:"humanoid_name,omitempty"`
}
MsgAttentionDisable disables attention for a humanoid or approval pane.
type MsgAttentionEnable ¶
type MsgAttentionEnable struct {
PaneID string `json:"pane_id,omitempty"`
HumanoidName string `json:"humanoid_name,omitempty"`
}
MsgAttentionEnable enables attention for a humanoid or approval pane.
type MsgAttentionEvent ¶
type MsgAttentionEvent struct {
PaneID string `json:"pane_id"`
HumanoidName string `json:"humanoid_name,omitempty"`
Category AttentionCategory `json:"category"`
Priority AttentionPriority `json:"priority"`
Title string `json:"title"`
Summary string `json:"summary"`
Timestamp int64 `json:"timestamp"`
}
MsgAttentionEvent is published when a pane/humanoid needs user attention.
type MsgBoardAgentPrompt ¶ added in v0.2.6
type MsgBoardAgentPrompt struct {
Text string `json:"text"`
// Board names WHICH board's claude to reach (design 028, `D-13` ruled
// per-fleet on 2026-08-11). Empty means the session board.
//
// It does not weaken ruling 2: every prompt still goes to a board claude
// and there is still no bypass. What it fixes is that with one mind per
// fleet, "the board claude" stopped being a single pane — and a prompt
// typed into fleet epic-07's board must not be acted on by epic-08's.
Board string `json:"board,omitempty"`
}
MsgBoardAgentPrompt is one line typed into the agents-board input field (design 027 §5.2).
It carries NO target. Every prompt goes to the board claude — that is the founder's ruling 2, and there is deliberately no verbatim `@tag` bypass — so naming a target here would create a second way to route that the board claude is not in the path of. Resolving which pane is the board claude belongs to the workspace, which is also where the refusal lives when two panes share the name.
type MsgBoardPost ¶ added in v0.2.4
type MsgBoardPost struct {
V int `json:"v"` // BoardSchemaVersion
// PaneID is the FULL pane uuid of the poster and is the identity key.
// Never the 8-char truncation the fleet envelope carries.
PaneID string `json:"pane_id"`
// Persona is the poster's display name — its pane given-name, falling back
// to the auto-title and then to "pane-<first 8 of uuid>". Display only; not
// unique (see the file header).
Persona string `json:"persona"`
Kind string `json:"kind"` // free-form; see BoardKind* for the well-known ones
Text string `json:"text"`
// ThreadID is empty when this post IS a root. Otherwise it is the root's
// id, minted by whichever agent opened the thread as "<pane-uuid>/<n>".
// A reply whose root has not arrived yet is rendered as a provisional root
// and re-parented when the root lands — that is expected, not an error.
ThreadID string `json:"thread_id,omitempty"`
TS int64 `json:"ts"` // unix millis, the POSTER's clock: arrival order, not causal order
// ToPersona / ToPaneID — the recipient of a DIRECTED message.
//
// GATE 4 WAS REOPENED (founder, 2026-08-09) and this reverses the earlier
// ruling that removed these. The original argument for asking before v1 was
// that adding them later is a breaking change; the schema is still V=1, so
// it is still cheap.
//
// A directed message is still CHAT, not routing: this says who was spoken
// TO, exactly as a chat app shows an @mention. It carries no chain, no
// msg id and no delivery semantics, and ANSA — not this field — is what
// actually delivers anything.
//
// Both are empty for a broadcast, which stays the default. Gate 3 is
// unaffected: a non-fleet claude directs a message exactly as a fleet one
// does, because neither field mentions a fleet.
ToPersona string `json:"to_persona,omitempty"`
ToPaneID string `json:"to_pane_id,omitempty"`
}
MsgBoardPost is one message on the agents board: a root, or a reply under a root. Published on T("board", "post"); the board view subscribes.
func NewBoardPost ¶ added in v0.2.4
func NewBoardPost(paneID, persona, kind, text string, nowMillis int64) *MsgBoardPost
NewBoardPost stamps the schema version and the poster's clock. Every producer goes through here so that V is never forgotten on a new call site.
type MsgBoardRegister ¶ added in v0.2.4
type MsgBoardRegister struct {
V int `json:"v"`
PaneID string `json:"pane_id"`
Persona string `json:"persona"`
TS int64 `json:"ts"`
}
MsgBoardRegister is a persona announcement: an agent telling the board who it is, so the board can show a roster without waiting for a first post. Published on T("board", "register"). Registration is advisory — a post from an unregistered pane is still rendered, because a board that drops messages from agents that forgot to introduce themselves is worse than one with a thin roster.
func NewBoardRegister ¶ added in v0.2.4
func NewBoardRegister(paneID, persona string, nowMillis int64) *MsgBoardRegister
NewBoardRegister stamps the schema version and the announcer's clock, for the same reason NewBoardPost does: every producer goes through a constructor so V is never forgotten on a new call site.
type MsgBrowserActionRequest ¶
type MsgBrowserActionRequest = sharedmsg.MsgBrowserActionRequest
Browser-action messages (server-side AI ↔ web-pane executor).
type MsgBrowserActionResponse ¶
type MsgBrowserActionResponse = sharedmsg.MsgBrowserActionResponse
type MsgCLIAnsaSend ¶ added in v0.2.4
type MsgCLIAnsaSend struct {
// AsPaneID is the SENDER, and unlike the board's it is optional: routing
// from outside a pane is legitimate. It is never inferred from the active
// pane, because a wrong "from" is a lie about who is talking.
AsPaneID string `json:"as_pane_id,omitempty"`
// To is required — the whole operation is "deliver to this target".
To string `json:"to"`
Mode string `json:"mode,omitempty"`
Text string `json:"text"`
}
MsgCLIAnsaSend is the AGENT door, reached by `rysh ansa send`.
It is its own CLI message rather than a ##ansa run through MsgCLIRyshCommand, for the three reasons the board's agent door exists (see internal/actors/workspace_board.go): that path attributes to the workspace's ambient active pane when none is named, FOCUSES the pane that is named, and ECHOES the command line into that pane's output buffers. A control channel used by dozens of agents must do none of the three — an agent routing a message must not yank the human's cursor to its own pane.
type MsgCLIBoardPost ¶ added in v0.2.4
type MsgCLIBoardPost struct {
// AsPaneID is the poster, and is REQUIRED. An empty value is an error, not
// a fallback to the active pane — silently attributing a post to a
// bystander is the exact defect this message exists to avoid.
AsPaneID string `json:"as_pane_id"`
Kind string `json:"kind,omitempty"` // default: BoardKindMilestone
Text string `json:"text"`
ThreadID string `json:"thread_id,omitempty"` // empty = start a new root
// Board names which board to post to (design 028). Empty means "resolve it
// from the poster", which the workspace does: the pane's own board.id meta,
// then the session board.
//
// It rides the CLI message and NOT MsgBoardPost, and the difference is the
// whole of D-12: this is a request that says where to deliver, while the
// post itself stays free of any board or fleet identity. Adding it here
// costs nothing to gate 4, which is about the schema on the wire between
// agents.
Board string `json:"board,omitempty"`
}
MsgCLIBoardPost is the agent-facing door: `rysh --board-post --as <pane-id>`.
It exists as its OWN CLI message rather than riding MsgCLIRyshCommand because that path has three properties a board post must not have, each verified against the running code in wave 1:
- with no --pane-id it runs as the workspace's ACTIVE pane, so a post would be attributed to a bystander (WorkspaceActor.handleCLIRyshCommand);
- naming a pane calls focusPaneByID, which switches the active tab and moves the human's focus — unusable when dozens of agents post;
- runRyshCommand echoes the command line into the pane's output buffers, so a post would pollute whichever pane it was attributed to.
So this message carries its poster EXPLICITLY in AsPaneID, never inherits the ambient pane, and its handler neither focuses nor echoes.
type MsgCLICreateLane ¶
type MsgCLICreateLane struct {
TabID string `json:"tab_id"` // empty = active tab
}
MsgCLICreateLane creates a new lane in the specified tab.
type MsgCLICreatePane ¶
type MsgCLICreatePane struct {
TabID string `json:"tab_id"` // empty = active tab
}
MsgCLICreatePane creates a new pane (lane split right) in the specified tab.
type MsgCLICreatePaneGroup ¶
type MsgCLICreatePaneGroup struct {
TabID string `json:"tab_id"` // empty = active tab
LaneID string `json:"lane_id"` // empty = active lane
}
MsgCLICreatePaneGroup creates a new pane group (split down) in the specified lane.
type MsgCLICreateStackedPane ¶
type MsgCLICreateStackedPane struct {
TabID string `json:"tab_id"` // empty = active tab
LaneID string `json:"lane_id"` // empty = active lane
PaneGroupID string `json:"pane_group_id"` // empty = active group
}
MsgCLICreateStackedPane creates a stacked pane in the specified pane group.
type MsgCLIDeleteLane ¶
MsgCLIDeleteLane deletes a lane by ID within a tab.
type MsgCLIDeletePane ¶
type MsgCLIDeletePane struct {
PaneID string `json:"pane_id"`
}
MsgCLIDeletePane deletes a specific pane by ID.
type MsgCLIDeletePaneGroup ¶
type MsgCLIDeletePaneGroup struct {
TabID string `json:"tab_id"`
LaneID string `json:"lane_id"`
PaneGroupID string `json:"pane_group_id"`
}
MsgCLIDeletePaneGroup deletes a pane group by ID.
type MsgCLIDeleteTab ¶
type MsgCLIDeleteTab struct {
TabID string `json:"tab_id"`
}
MsgCLIDeleteTab deletes a tab by ID.
type MsgCLIPipelineDisable ¶
type MsgCLIPipelineDisable struct {
TabID string `json:"tab_id"` // empty = active tab
}
MsgCLIPipelineDisable disables pipeline mode for a tab.
type MsgCLIPipelineEnable ¶
type MsgCLIPipelineEnable struct {
TabID string `json:"tab_id"` // empty = active tab
}
MsgCLIPipelineEnable enables pipeline mode for a tab.
type MsgCLIResponse ¶
type MsgCLIResponse struct {
OK bool `json:"ok"`
Error string `json:"error,omitempty"`
ID string `json:"id,omitempty"` // newly created entity ID, if applicable
Output string `json:"output,omitempty"` // captured textual output (e.g. ## command result)
}
MsgCLIResponse is the response to all CLI commands.
type MsgCLIRyshCommand ¶
type MsgCLIRyshCommand struct {
TabID string `json:"tab_id"` // empty = active tab
PaneID string `json:"pane_id"` // empty = active (or TabID's active) pane
Command string `json:"command"` // rysh command body WITHOUT leading "##"
}
MsgCLIRyshCommand asks the WorkspaceActor to run a "##" system command on behalf of the CLI, targeting a specific pane (and tab) and replying with the captured command output. It is the command-line equivalent of typing a "##" command in a pane: e.g. `rysh --cmd --tab-id <t> --pane-id <p> "echo hi"` maps to Command="cmd echo hi" run on pane <p>.
Command is the rysh command body WITHOUT the leading "##" (e.g. "cmd echo hi", "pane info", "tab list"). PaneID and TabID select the target pane; an empty PaneID falls back to TabID's active pane, and an empty TabID falls back to the workspace's currently active pane. PaneID/TabID may be an id, alias, title, or given-name (resolved the same way as interactive ## commands).
type MsgCancelPrompt ¶
type MsgCancelPrompt struct{}
MsgCancelPrompt cancels any in-flight LLM completion.
type MsgChannelAllow ¶
type MsgChannelAllow struct {
HumanoidName string `json:"humanoid_name"`
Channel string `json:"channel,omitempty"`
SenderID string `json:"sender_id"`
}
MsgChannelAllow adds a sender directly to the allowlist, skipping the code flow (approver → humanoid). An empty Channel applies to every configured channel.
type MsgChannelPairApprove ¶
type MsgChannelPairApprove struct {
HumanoidName string `json:"humanoid_name"`
Channel string `json:"channel,omitempty"`
Code string `json:"code"`
}
MsgChannelPairApprove consumes a pending code, promoting its sender to the allowlist (approver → humanoid). An empty Channel means "search every configured channel for the code" — the terminal command omits the channel.
type MsgChannelPairLink ¶
type MsgChannelPairLink struct {
HumanoidName string `json:"humanoid_name"`
Channel string `json:"channel"`
Force bool `json:"force,omitempty"`
}
MsgChannelPairLink asks a humanoid to run a channel's device-link flow on demand (approver → humanoid; `##humanoid pair link`, X4 design 009 §3.4). Force overrides the re-link guard, which otherwise refuses when the daemon already holds a linked account — re-provisioning a live number is the §6 re-link hazard.
type MsgChannelPairList ¶
type MsgChannelPairList struct {
HumanoidName string `json:"humanoid_name"`
Channel string `json:"channel,omitempty"`
}
MsgChannelPairList requests the pending + allowlist state (approver → humanoid, request/reply). An empty Channel aggregates every configured channel.
type MsgChannelPairListReply ¶
type MsgChannelPairListReply struct {
Pending []PendingPair `json:"pending,omitempty"`
Allowlist []string `json:"allowlist,omitempty"`
}
MsgChannelPairListReply carries the swept pending set and the allowlist (humanoid → approver). When the request aggregated several channels, the allowlist entries are rendered as "channel:sender" so they stay attributable.
type MsgChannelPairQR ¶
type MsgChannelPairQR struct {
HumanoidName string `json:"humanoid_name"`
Channel string `json:"channel"`
QR string `json:"qr"`
// QRImage is a "data:image/png;base64,…" rendering of QR the web dashboard can
// show in an <img> (X4, design 009). Empty when encoding failed; the pane
// renders its own half-block QR from QR, so this is dashboard-only.
QRImage string `json:"qr_image,omitempty"`
}
MsgChannelPairQR carries a QR-channel device-link payload for rendering (humanoid → pane/dashboard). QR is the raw link payload; the dashboard renders it as a scannable image (design 005 DB2).
type MsgChannelPairRequest ¶
type MsgChannelPairRequest struct {
HumanoidName string `json:"humanoid_name"`
Channel string `json:"channel"`
SenderID string `json:"sender_id"`
SenderName string `json:"sender_name"`
Code string `json:"code"`
FirstMsg string `json:"first_msg,omitempty"`
ExpiresAt int64 `json:"expires_at"`
}
MsgChannelPairRequest announces that a non-allowlisted sender messaged a gated channel and is waiting for approval (humanoid → approvers/dashboard). The code is shown only to the operator, never sent back to the requester.
type MsgChannelPairStatus ¶
type MsgChannelPairStatus struct {
HumanoidName string `json:"humanoid_name"`
Channel string `json:"channel"`
Connected bool `json:"connected"`
Detail string `json:"detail,omitempty"`
}
MsgChannelPairStatus reports a QR channel's device-link state transitions (humanoid → pane/dashboard): linked (Connected=true) or a link error (Connected=false with Detail).
type MsgClosePane ¶
type MsgClosePane struct{}
MsgClosePane closes the active pane group (or entire lane/tab if last).
type MsgConversationAppend ¶
type MsgConversationAppend = sharedmsg.MsgConversationAppend
type MsgConversationHistoryAppend ¶
type MsgConversationHistoryAppend = sharedmsg.MsgConversationHistoryAppend
type MsgConversationHistoryReply ¶
type MsgConversationHistoryReply = sharedmsg.MsgConversationHistoryReply
type MsgCreateApprovalPane ¶
type MsgCreateApprovalPane = sharedmsg.MsgCreateApprovalPane
type MsgCreatePane ¶
type MsgCreatePane struct{}
MsgCreatePane creates a new lane to the right of the active lane.
type MsgCreatePaneDown ¶
type MsgCreatePaneDown struct{}
MsgCreatePaneDown creates a new pane group in the active lane.
type MsgCreateStackedPane ¶
type MsgCreateStackedPane struct{}
MsgCreateStackedPane creates a new pane stacked in the active group.
type MsgDestroyApprovalPane ¶
type MsgDestroyApprovalPane = sharedmsg.MsgDestroyApprovalPane
type MsgDiscoverCodexSession ¶ added in v0.2.6
type MsgDiscoverCodexSession struct {
PaneID string `json:"pane_id"`
// Cwd is the directory the agent was launched in, and the field discovery
// matches on — codex records it in the rollout's first line.
Cwd string `json:"cwd"`
// NotBefore is the launch time as a unix timestamp. A rollout older than
// this belongs to an earlier session.
NotBefore int64 `json:"not_before"`
Retries int `json:"retries"`
}
MsgDiscoverCodexSession is the workspace's note to itself to find out which session a just-launched codex opened (design 029).
It exists because codex, unlike claude, has no launch-time session-id flag: it issues its own id and the only place it publishes it is the rollout file it writes under $CODEX_HOME/sessions. That file appears a moment AFTER the launch command is delivered, so the lookup has to be retried rather than done inline — hence a self-addressed message with a countdown, the same shape MsgLaunchClaudeInPane uses for the same class of problem.
type MsgEqualizeAll ¶
type MsgEqualizeAll struct{}
MsgEqualizeAll resets both lane widths and every lane's group heights to equal, restoring a fully balanced layout in one shot (ctrl+l e).
type MsgEqualizeHorizontal ¶
type MsgEqualizeHorizontal struct{}
MsgEqualizeHorizontal sets all lanes to equal width.
type MsgEqualizePanes ¶
type MsgEqualizePanes struct{}
MsgEqualizePanes resets all lane flex weights to equal.
type MsgEqualizeVertical ¶
type MsgEqualizeVertical struct{}
MsgEqualizeVertical resets all group rowFlex weights in the active lane to equal.
type MsgExecPrompt ¶
type MsgExecPrompt struct {
Prompt string `json:"prompt"`
}
MsgExecPrompt runs an LLM completion. If a completion is already in flight, it is cancelled first (last-prompt-wins semantics).
type MsgExecRyshOnPane ¶
MsgExecRyshOnPane asks the WorkspaceActor to run a ## system command on a specific pane. It is used to relay a #### command from a remote subscriber to the shared source pane: the source's UpstreamShareActor publishes this to the workspace inbox so the command runs as "##<Command>" on the target pane. Command is the rysh command body WITHOUT the leading "##".
type MsgFocusPane ¶
type MsgFocusPane struct {
Direction Direction `json:"direction"`
}
MsgFocusPane moves focus in the specified direction. Replaces MsgFocusNextPane, MsgFocusPrevPane, MsgFocusPaneLeft/Right/Up/Down.
type MsgFocusPaneByID ¶
type MsgFocusPaneByID struct {
ID string `json:"id"`
}
MsgFocusPaneByID focuses a specific pane by its UUID.
type MsgFocusPrevTab ¶
type MsgFocusPrevTab struct{}
MsgFocusPrevTab cycles focus to the previous tab.
type MsgFocusTabIndex ¶
type MsgFocusTabIndex struct {
Index int `json:"index"`
}
MsgFocusTabIndex jumps to a tab by 0-based index.
type MsgGetActivePane ¶
type MsgGetActivePane struct{}
MsgGetActivePane requests the active pane ID and pane count from a TabActor.
type MsgGetConversationHistory ¶
type MsgGetConversationHistory = sharedmsg.MsgGetConversationHistory
type MsgGetGroundingState ¶
type MsgGetGroundingState = sharedmsg.MsgGetGroundingState
type MsgGetLaneActivePane ¶
type MsgGetLaneActivePane struct{}
MsgGetLaneActivePane requests the active pane ID and pane count from a LaneActor.
type MsgGetLaneSnapshot ¶
type MsgGetLaneSnapshot struct {
LayoutOnly bool `json:"layout_only,omitempty"`
NoHistories bool `json:"no_histories,omitempty"`
}
MsgGetLaneSnapshot requests a lane snapshot. When LayoutOnly is set, the reply omits heavy per-pane content (output/history/VT) so only structural layout fields are carried up the cascade.
type MsgGetMirrorPaneVT ¶
type MsgGetMirrorPaneVT struct {
PaneID string `json:"pane_id"`
}
MsgGetMirrorPaneVT requests the live VT frame (screen + cursor) of a single mirror pane (id "mirror:<shareID>:<srcPaneID>"). Answered by the subscriber's WorkspaceActor straight from its mirror-tab state — O(one pane), no Tab→Lane→Group cascade — so the TUI can refresh one interactive mirror pane per rawDirty signal instead of re-reading the whole workspace snapshot.
type MsgGetMirrorScrollback ¶
type MsgGetMirrorScrollback struct {
PaneID string `json:"pane_id"`
}
MsgGetMirrorScrollback requests the accumulated scrollback + current screen of a mirror pane (id prefixed "mirror:"). Answered by the subscriber's WorkspaceActor, which holds the mirror-tab state (mirror panes are synthetic and have no PaneActor of their own).
type MsgGetPaneGroupActivePane ¶
type MsgGetPaneGroupActivePane struct{}
MsgGetPaneGroupActivePane requests the active pane ID and pane count from a PaneGroupActor.
type MsgGetPaneGroupSnapshot ¶
type MsgGetPaneGroupSnapshot struct {
LayoutOnly bool `json:"layout_only,omitempty"`
NoHistories bool `json:"no_histories,omitempty"`
}
MsgGetPaneGroupSnapshot requests a pane group snapshot. When LayoutOnly is set, the reply omits heavy per-pane content so only layout fields are carried.
type MsgGetPaneScrollback ¶
type MsgGetPaneScrollback struct{}
MsgGetPaneScrollback requests an interactive pane's scrollback history plus its current screen, rendered as ANSI rows (oldest line first). Used by the TUI to populate raw-pane scroll mode for inline programs (e.g. claude).
type MsgGetPaneScrollbackDelta ¶
type MsgGetPaneScrollbackDelta struct {
Since int64 `json:"since"`
}
MsgGetPaneScrollbackDelta requests scrollback rows (rendered ANSI, oldest first) evicted since the given monotonic count, plus the current evicted total. A tab share's layout loop uses this to forward incremental interactive history to subscribers without re-sending the whole buffer each tick.
type MsgGetPaneSnapshot ¶
type MsgGetPaneSnapshot struct {
LayoutOnly bool `json:"layout_only,omitempty"`
NoHistories bool `json:"no_histories,omitempty"`
}
MsgGetPaneSnapshot requests a pane snapshot. When LayoutOnly is set the pane builds a content-free snapshot (no output/VT) — used by the layout cascade. The TUI's direct per-pane backfill/reconcile leaves it false to pull the full content in a single hop. NoHistories additionally drops the command histories, which LayoutOnly keeps (see MsgGetWorkspaceSnapshot.NoHistories — they are 97% of a layout-only pane snapshot).
type MsgGetPaneVT ¶
type MsgGetPaneVT struct{}
MsgGetPaneVT requests ONLY the live interactive VT frame (screen + cursor) of a local raw pane — the lightweight per-frame refresh for inline TUIs (claude, vim) running in a multi-pane / stacked layout. It is served from the same .snapshot request subject as MsgGetPaneSnapshot (the PaneActor dispatches by type) but skips building and marshalling the heavy output/history buffers, so a redraw-heavy app refreshes one pane's screen cheaply instead of pulling the whole pane snapshot on every rawDirty signal.
type MsgGetRunStatus ¶
type MsgGetRunStatus = sharedmsg.MsgGetRunStatus
type MsgGetSessionMemory ¶
type MsgGetSessionMemory = sharedmsg.MsgGetSessionMemory
type MsgGetTabSnapshot ¶
type MsgGetTabSnapshot struct {
LayoutOnly bool `json:"layout_only,omitempty"`
NoHistories bool `json:"no_histories,omitempty"`
}
MsgGetTabSnapshot requests a tab snapshot. LayoutOnly and NoHistories are propagated down the cascade so per-pane content (and optionally command history) is omitted.
type MsgGetWorkspaceSnapshot ¶
type MsgGetWorkspaceSnapshot struct {
LayoutOnly bool `json:"layout_only,omitempty"`
// Fresh forces a cache-bypassing rebuild of the snapshot. Set when the request
// is triggered by an explicit ws.layoutDirty signal (something just changed) —
// in particular pane-mode/web-binding changes, which mutate PaneActor state
// without going through the WorkspaceActor's persistToKV cache-invalidation.
// Without this, a layoutDirty-driven fetch can be served from the ~100ms
// memoized snapshot built BEFORE the change, so a stream client with no
// fallback poll (the desktop app) sticks on stale state until the next dirty
// signal. The blind poll and overlapping internal pollers leave it false and
// keep sharing the cache.
Fresh bool `json:"fresh,omitempty"`
// NoHistories additionally drops the per-pane command histories, which
// LayoutOnly keeps. They are not incidental: measured live, shell_history was
// 28.9 KB of a 29.9 KB layout-only pane snapshot — 97.5% of it — because
// every pane seeds the SAME session history file (pane.go, loadHistoryFile)
// and the file had grown to ~29 KB. Fifty panes therefore carried fifty
// identical copies, re-serialized on every cascade (F-7c).
//
// Only set this when the caller reads no history at all. The TUI's
// activeHistory() reads ShellHistory/PromptHistory straight out of its layout
// snapshot for arrow-key recall, so the TUI must leave this false; the web
// server's streamPaneVT reads only ids and the RawMode/RemoteInteractive
// flags, so it sets it.
NoHistories bool `json:"no_histories,omitempty"`
}
MsgGetWorkspaceSnapshot requests a workspace snapshot. When LayoutOnly is set (the TUI's event-driven layout fetch), the whole Tab→Lane→Group→Pane cascade builds content-free pane snapshots: heavy output/VT buffers are omitted because the TUI streams that content directly per-pane. Internal callers (sharing, CLI, KV) leave it false to get the full snapshot.
LayoutOnly does NOT drop command history — see NoHistories.
type MsgGroundingStateReply ¶
type MsgGroundingStateReply = sharedmsg.MsgGroundingStateReply
type MsgHumanoidActivate ¶
type MsgHumanoidActivate struct {
Name string `json:"name"`
}
MsgHumanoidActivate activates a deactivated humanoid.
type MsgHumanoidChannelStart ¶
type MsgHumanoidChannelStart struct {
ChannelType string `json:"channel_type"`
}
MsgHumanoidChannelStart starts a specific channel on a humanoid.
type MsgHumanoidChannelStatus ¶
type MsgHumanoidChannelStatus struct {
Name string `json:"name"`
ChannelType string `json:"channel_type"`
Connected bool `json:"connected"`
Error string `json:"error,omitempty"`
}
MsgHumanoidChannelStatus reports a channel's connection state.
type MsgHumanoidChannelStop ¶
type MsgHumanoidChannelStop struct {
ChannelType string `json:"channel_type"`
}
MsgHumanoidChannelStop stops a specific channel on a humanoid.
type MsgHumanoidContinue ¶
type MsgHumanoidContinue struct {
Name string `json:"name"`
}
MsgHumanoidContinue resumes a humanoid's paused LLM run by name (used by @@humanoid-name continue). No-op with a notice when nothing is paused.
type MsgHumanoidCreate ¶
type MsgHumanoidCreate struct {
Name string `json:"name"`
SystemPrompt string `json:"system_prompt"`
Contacts map[string]ChannelConfig `json:"contacts,omitempty"`
Provider string `json:"provider,omitempty" yaml:"provider,omitempty"`
// Model pins the model for the selected provider. Parsed from skill-file
// frontmatter since MP2 but never threaded through until R4 — it was dead
// config, and `rysh assistant` writes it into every generated SKILL.md.
Model string `json:"model,omitempty" yaml:"model,omitempty"`
Profile string `json:"profile,omitempty" yaml:"profile,omitempty"`
// AutoApprove carries the skill-file `auto_approve:` field. Nil means the
// field was absent, which resolves to the DEFAULT (true) — a humanoid runs
// its tool calls without an approval dialog. Set it to false in the skill
// file to gate every consequential tool call on an owner "yes". A pointer
// rather than a bool so "absent" and "explicitly false" stay
// distinguishable across the wire and the KV round trip.
AutoApprove *bool `json:"auto_approve,omitempty" yaml:"auto_approve,omitempty"`
}
MsgHumanoidCreate creates a new humanoid with optional channel configs. Provider carries the skill-file `provider:` selection (design 006 MP2) so a humanoid can run on a non-default model provider; empty = config default. Profile carries the skill-file `profile:` marker (design 007 PM1/PM3); "assistant" selects the fail-closed personal-assistant defaults.
type MsgHumanoidDeactivate ¶
type MsgHumanoidDeactivate struct {
Name string `json:"name"`
}
MsgHumanoidDeactivate deactivates a humanoid (keeps state, stops processing).
type MsgHumanoidDelete ¶
type MsgHumanoidDelete struct {
Name string `json:"name"`
}
MsgHumanoidDelete tears a humanoid down by name and drops it from the registry — the inverse of MsgHumanoidCreate, driven by `##humanoid stop` (and the dashboard's humanoid_delete command). The skill file on disk is untouched, so the humanoid re-spawns by name.
type MsgHumanoidEmailChanged ¶
type MsgHumanoidEmailChanged struct {
HumanoidName string `json:"humanoid_name"`
}
MsgHumanoidEmailChanged signals that a humanoid's inbox changed (new mail arrived via IMAP IDLE), so the UI can refresh its listing.
type MsgHumanoidEmailCompose ¶
type MsgHumanoidEmailCompose struct {
To string `json:"to"`
Subject string `json:"subject"`
Body string `json:"body"`
InReplyTo string `json:"in_reply_to,omitempty"` // MessageID being replied to, for threading
}
MsgHumanoidEmailCompose asks a humanoid to send an email the human wrote themselves (the manual-compose path of the email client, distinct from the AI-draft path). The human authored and sent it, so it needs no separate approval gate: the humanoid stages it as an approved draft and sends it over SMTP. Published to humanoid.<name>.inbox; the humanoid replies on humanoid.<name>.email.compose.
type MsgHumanoidEmailComposeReply ¶
type MsgHumanoidEmailComposeReply struct {
HumanoidName string `json:"humanoid_name"`
Ok bool `json:"ok"`
Err string `json:"err,omitempty"`
}
MsgHumanoidEmailComposeReply reports the outcome of a MsgHumanoidEmailCompose send back toward the UI.
type MsgHumanoidEmailList ¶
type MsgHumanoidEmailList struct {
Count int `json:"count"` // 0 ⇒ default (10), capped at 50 by the adapter
Search string `json:"search"` // optional SUBJECT substring filter
}
MsgHumanoidEmailList asks a humanoid to fetch its inbox listing. The humanoid serves it from its EmailAdapter and replies on humanoid.<name>.email.list.
type MsgHumanoidEmailListReply ¶
type MsgHumanoidEmailListReply struct {
HumanoidName string `json:"humanoid_name"`
Emails []EmailSummary `json:"emails"`
Err string `json:"err,omitempty"`
}
MsgHumanoidEmailListReply carries an inbox listing back toward the UI.
type MsgHumanoidEmailRead ¶
type MsgHumanoidEmailRead struct {
UID int `json:"uid"`
}
MsgHumanoidEmailRead asks a humanoid to fetch one email's full detail. The reply is published on humanoid.<name>.email.detail.
type MsgHumanoidEmailReadReply ¶
type MsgHumanoidEmailReadReply struct {
HumanoidName string `json:"humanoid_name"`
Email *EmailDetail `json:"email"`
Err string `json:"err,omitempty"`
}
MsgHumanoidEmailReadReply carries a single email's detail back toward the UI.
type MsgHumanoidGovernanceChanged ¶ added in v0.2.3
type MsgHumanoidGovernanceChanged struct {
Name string `json:"name"`
Mode string `json:"mode"` // "ai" or "human"
}
MsgHumanoidGovernanceChanged is published by a HumanoidActor to the registry inbox after a runtime governance flip was applied, so the registry can record the new mode in the contacts it persists to KV. Without it the flip silently reverts to the skill-file value on the next restart.
type MsgHumanoidInboundMessage ¶
type MsgHumanoidInboundMessage struct {
ChannelType string `json:"channel_type"`
SenderID string `json:"sender_id"`
SenderName string `json:"sender_name"`
Content string `json:"content"`
ThreadID string `json:"thread_id,omitempty"`
Timestamp int64 `json:"timestamp"`
Metadata map[string]string `json:"metadata,omitempty"`
}
MsgHumanoidInboundMessage arrives from an external channel.
type MsgHumanoidList ¶
type MsgHumanoidList struct{}
MsgHumanoidList requests a list of all humanoids.
type MsgHumanoidListReply ¶
type MsgHumanoidListReply struct {
Humanoids []HumanoidInfo `json:"humanoids"`
}
MsgHumanoidListReply carries the list of humanoids.
type MsgHumanoidOutboundMessage ¶
type MsgHumanoidOutboundMessage struct {
ChannelType string `json:"channel_type"`
RecipientID string `json:"recipient_id"`
Content string `json:"content"`
ThreadID string `json:"thread_id,omitempty"`
}
MsgHumanoidOutboundMessage is sent back to an external channel.
type MsgHumanoidPrompt ¶
type MsgHumanoidPrompt struct {
HumanoidName string `json:"humanoid_name"`
Prompt string `json:"prompt"`
SourcePaneID string `json:"source_pane_id"`
ScopeHint string `json:"scope_hint,omitempty"` // invoking pane's scope chain (resolved by the workspace)
}
MsgHumanoidPrompt sends a prompt to a named humanoid.
type MsgHumanoidRegisterPane ¶
type MsgHumanoidRegisterPane struct {
HumanoidName string `json:"humanoid_name"`
PaneID string `json:"pane_id"`
PaneName string `json:"pane_name"`
PaneGroupID string `json:"pane_group_id,omitempty"` // for ephemeral approval panes
}
MsgHumanoidRegisterPane registers a humanoid to output to a specific pane.
type MsgHumanoidReplyModeChanged ¶ added in v0.2.3
type MsgHumanoidReplyModeChanged struct {
Name string `json:"name"`
ChannelType string `json:"channel_type"`
Mode string `json:"mode"` // "messages" or "mentions"
}
MsgHumanoidReplyModeChanged is the reply-mode analogue of MsgHumanoidGovernanceChanged: it persists a runtime `##humanoid reply-to` flip so a restart rebuilds the channel adapter with the flipped mode.
type MsgHumanoidSetFocus ¶
type MsgHumanoidSetFocus struct {
Listing bool `json:"listing"`
UID int `json:"uid"`
MessageID string `json:"message_id"`
ThreadID string `json:"thread_id"`
From string `json:"from"`
Subject string `json:"subject"`
Body string `json:"body,omitempty"`
}
MsgHumanoidSetFocus tells a humanoid which email the desktop UI currently has open (Listing=false), or that the user is browsing the inbox list with no email open (Listing=true). The humanoid prefers this over lastInbound when enriching the LLM prompt, so "reply to this" acts on the email the user is actually looking at — even an older one. Body is included so the LLM need not re-read the message; MessageID is used as the reply In-Reply-To.
type MsgHumanoidSetGovernance ¶
type MsgHumanoidSetGovernance struct {
Mode string `json:"mode"` // "ai" or "human"
}
MsgHumanoidSetGovernance changes a humanoid's ai|human governance mode at runtime — it applies to EVERY configured channel (see applyGovernanceMode), not only email.
type MsgHumanoidSetProvider ¶
type MsgHumanoidSetProvider struct {
Provider string `json:"provider"` // anthropic | openai | ollama
Model string `json:"model,omitempty"` // optional; empty keeps the provider default
}
MsgHumanoidSetProvider overrides a humanoid's model provider at runtime (design 006 §4.3 precedence step 2, openclaw_roadmap R4). Applied on the next executor spawn, matching how MsgHumanoidSetGovernance documents its effect.
type MsgHumanoidSetReplyMode ¶
type MsgHumanoidSetReplyMode struct {
ChannelType string `json:"channel_type"`
Mode string `json:"mode"` // "messages" or "mentions"
}
MsgHumanoidSetReplyMode changes a channel's reply mode at runtime. Mode is "messages" (reply to all channel messages) or "mentions" (reply only when the bot is @mentioned).
type MsgHumanoidStop ¶
type MsgHumanoidStop struct {
Name string `json:"name"`
}
MsgHumanoidStop interrupts a humanoid's in-flight LLM run by name (used by @@humanoid-name stop). PAUSE semantics: the humanoid stays alive (channel adapters keep running) and its conversation state is preserved — MsgHumanoidContinue (or a new prompt) resumes from the checkpoint. Tearing the humanoid down is a separate operation (MsgHumanoidDelete / ##humanoid stop) — note the two "stop"s differ: @@name stop pauses a run, ##humanoid stop ends the humanoid.
type MsgHumanoidUnregisterPane ¶
type MsgHumanoidUnregisterPane struct {
HumanoidName string `json:"humanoid_name"`
PaneID string `json:"pane_id"`
}
MsgHumanoidUnregisterPane removes a humanoid's pane registration.
type MsgHumanoidWhatsAppChanged ¶
type MsgHumanoidWhatsAppChanged struct {
HumanoidName string `json:"humanoid_name"`
}
MsgHumanoidWhatsAppChanged signals that a humanoid received a new WhatsApp message, so the UI can refresh its listing.
type MsgHumanoidWhatsAppList ¶
type MsgHumanoidWhatsAppList struct {
Count int `json:"count"` // 0 ⇒ default (50), capped by the adapter store
}
MsgHumanoidWhatsAppList asks a humanoid to return its recent received messages. The humanoid serves it from its WhatsAppAdapter store and replies on humanoid.<name>.whatsapp.list.
type MsgHumanoidWhatsAppListReply ¶
type MsgHumanoidWhatsAppListReply struct {
HumanoidName string `json:"humanoid_name"`
Messages []WhatsAppMsgSummary `json:"messages"`
Err string `json:"err,omitempty"`
}
MsgHumanoidWhatsAppListReply carries the recent-message listing back to the UI.
type MsgHumanoidWhatsAppRead ¶
type MsgHumanoidWhatsAppRead struct {
ID string `json:"id"`
}
MsgHumanoidWhatsAppRead asks a humanoid for one message's full detail by its short ID. The reply is published on humanoid.<name>.whatsapp.detail.
type MsgHumanoidWhatsAppReadReply ¶
type MsgHumanoidWhatsAppReadReply struct {
HumanoidName string `json:"humanoid_name"`
Message *WhatsAppMsgDetail `json:"message"`
Err string `json:"err,omitempty"`
}
MsgHumanoidWhatsAppReadReply carries one message's detail back to the UI.
type MsgLLMPickerOpen ¶ added in v0.2.3
type MsgLLMPickerOpen struct {
PaneID string `json:"pane_id"`
// Models are the activatable rows, in the same order the numbered menu
// prints them, so a user reading either sees one list.
Models []LLMPickerModel `json:"models"`
// Blocked are the registry entries that cannot be activated, each already
// rendered with its reason. Shown but never selectable.
Blocked []string `json:"blocked,omitempty"`
// Scopes are the binding levels offered in step two, broadest first. The
// daemon sends them rather than the front-end hard-coding the hierarchy.
Scopes []LLMPickerScope `json:"scopes"`
// InEffect labels the model serving this pane right now, for the header.
InEffect string `json:"in_effect,omitempty"`
}
MsgLLMPickerOpen asks the front-end to open the interactive model picker.
type MsgLaneActivePaneReply ¶
type MsgLaneActivePaneReply struct {
PaneID string `json:"pane_id"`
PaneCount int `json:"pane_count"`
}
MsgLaneActivePaneReply carries the LaneActor's active pane info.
type MsgLaneCloseActivePane ¶
type MsgLaneCloseActivePane struct{}
MsgLaneCloseActivePane closes the active (top) pane in the active pane group. If the group has only one pane, this is a no-op (use MsgLaneClosePaneGroup instead).
type MsgLaneClosePaneGroup ¶
type MsgLaneClosePaneGroup struct{}
MsgLaneClosePaneGroup closes the active pane group in the lane.
type MsgLaneCreatePaneGroup ¶
type MsgLaneCreatePaneGroup struct {
PaneID string `json:"pane_id"`
Title string `json:"title"`
GroupID string `json:"group_id,omitempty"`
WorkingDir string `json:"working_dir,omitempty"`
// PaneType marks the initial pane as a special variant ("replay" panes
// never start a shell/PTY). Empty = normal pane. See
// MsgTabCreatePaneGroupInLane.
PaneType string `json:"pane_type,omitempty"`
// Meta is metadata the initial pane is born with. See
// MsgTabCreatePaneGroupInLane.Meta for why birth rather than a follow-up
// message.
Meta map[string]string `json:"meta,omitempty"`
}
MsgLaneCreatePaneGroup creates a new pane group in the lane.
GroupID, when set, pre-assigns the new group's ID (normally generated by the lane) so the sender can reference the group it asked for — the worktree lifecycle (design 008) records which group runs in which worktree at create time. WorkingDir, when set, is the directory the group's panes start their shells in, overriding the lane's inherited config. Both are carried at birth rather than sent as a follow-up MsgSetWorkingDir, which would race the group's initial pane creation.
type MsgLaneCreateStackedPane ¶
MsgLaneCreateStackedPane creates a new stacked pane in the active group.
type MsgLaneCreateStackedPaneInGroup ¶
type MsgLaneCreateStackedPaneInGroup struct {
PaneGroupID string `json:"pane_group_id"`
PaneID string `json:"pane_id"`
Title string `json:"title"`
}
MsgLaneCreateStackedPaneInGroup creates a stacked pane in a specific group.
type MsgLaneDeletePaneGroup ¶
type MsgLaneDeletePaneGroup struct {
PaneGroupID string `json:"pane_group_id"`
}
MsgLaneDeletePaneGroup deletes a specific pane group by ID within a lane.
type MsgLaneEqualizeGroups ¶
type MsgLaneEqualizeGroups struct{}
MsgLaneEqualizeGroups resets all group rowFlex weights in the lane to equal.
type MsgLaneFocusGroup ¶
type MsgLaneFocusGroup struct {
Direction Direction `json:"direction"`
}
MsgLaneFocusGroup moves focus up or down within the lane. Replaces MsgLaneFocusGroupUp and MsgLaneFocusGroupDown.
type MsgLaneFocusPaneByID ¶
type MsgLaneFocusPaneByID struct {
ID string `json:"id"`
}
MsgLaneFocusPaneByID makes the pane group containing the given pane the active group within the lane, so the lane snapshot reports it as active.
type MsgLaneResizeGroupHeight ¶
type MsgLaneResizeGroupHeight struct {
Delta int `json:"delta"`
}
MsgLaneResizeGroupHeight adjusts the height of the active pane group within the lane. Delta > 0 grows the group; Delta < 0 shrinks it.
type MsgLaneSetPaneHidden ¶ added in v0.2.6
MsgLaneSetPaneHidden forwards a hide/reveal to the group holding the pane.
type MsgLaneSnapshotReply ¶
type MsgLaneSnapshotReply struct {
Snapshot domain.LaneSnapshot `json:"snapshot"`
}
MsgLaneSnapshotReply carries the lane snapshot reply.
type MsgLaneStackedPane ¶
type MsgLaneStackedPane struct {
Direction Direction `json:"direction"`
}
MsgLaneStackedPane cycles the stack in the specified direction in the active group. Replaces MsgLaneStackedPaneNext and MsgLaneStackedPanePrev.
type MsgLaneStackedPaneMove ¶
type MsgLaneStackedPaneMove struct {
Direction Direction `json:"direction"`
}
MsgLaneStackedPaneMove reorders the active pane within the active group's stack.
type MsgLaneStackedPaneSelect ¶
type MsgLaneStackedPaneSelect struct {
Index int `json:"index"`
}
MsgLaneStackedPaneSelect activates the stacked pane at the given 0-based index in the active group.
type MsgLaunchClaudeInPane ¶ added in v0.2.3
type MsgLaunchClaudeInPane struct {
Alias string `json:"alias"`
SessionID string `json:"session_id"`
PromptFile string `json:"prompt_file,omitempty"`
Retries int `json:"retries"`
// GivenName and Hidden are applied once the pane resolves, by the same
// retry loop that starts claude (design 027 §5.5). They ride along rather
// than getting a loop of their own because they have the identical problem:
// the pane is created by a message travelling down the actor hierarchy, so
// its id does not exist when the command returns. A second timer would be a
// second thing to get wrong, and the board claude needs BOTH — a pane that
// comes up named but visible puts an agent on everyone's screen, and one
// that comes up hidden but unnamed cannot be found again.
GivenName string `json:"given_name,omitempty"`
Hidden bool `json:"hidden,omitempty"`
// ExtraArgs are appended to the claude invocation verbatim. Empty for
// `##pane new --claude`, where a human is watching the pane and manual
// approval is the safe default. The BOARD CLAUDE sets it, because an agent
// whose entire job is to act on the fleet cannot do that job while it is
// asking a human to approve each action — and its pane is hidden, so there
// is nobody there to ask.
ExtraArgs string `json:"extra_args,omitempty"`
}
MsgLaunchClaudeInPane is the workspace's note to itself to finish a `##pane new --claude`: the pane is created by a message that travels down the actor hierarchy, so its id does not exist yet when the command returns — only the alias does. Retries counts down; each hop is one more chance for the pane to have appeared.
type MsgLayoutDirty ¶
type MsgLayoutDirty struct{}
MsgLayoutDirty is a lightweight notification published by the WorkspaceActor to rysh.ws.layoutDirty whenever the workspace structure/layout changes (tab/pane create/close, focus, resize, stack rotate, rename — anything that calls persistToKV). The TUI subscribes to it and triggers a coalesced (~16 ms) layout-only snapshot refresh instead of polling on a blind timer. It carries no payload; the TUI re-reads the layout tree on receipt.
type MsgMCPStatus ¶
type MsgMCPStatus struct {
Server string `json:"server"`
Phase string `json:"phase"` // connected|reconnecting|given_up|disconnected|removed
Attempt int `json:"attempt,omitempty"` // 1-based reconnect attempt when reconnecting/given_up
Max int `json:"max,omitempty"` // MaxRestartAttemptsPerSession at emit time
Detail string `json:"detail,omitempty"` // tool count / last error / retry delay
}
MsgMCPStatus reports a live state transition for one MCP server. It is published session-globally to T("mcp","status") on every transition (connected / reconnecting / given_up / disconnected / removed) by the MCP manager's StatusEmitter, so the TUI footer can surface restart progress without polling the manager. Follow-up 6b.
type MsgMemoryAppend ¶
type MsgMemoryAppend = sharedmsg.MsgMemoryAppend
type MsgMemoryGet ¶
type MsgMemoryGet = sharedmsg.MsgMemoryGet
type MsgMemoryGetReply ¶
type MsgMemoryGetReply = sharedmsg.MsgMemoryGetReply
type MsgMemoryStateUpdate ¶
type MsgMemoryStateUpdate = sharedmsg.MsgMemoryStateUpdate
type MsgMemorySummarize ¶
type MsgMemorySummarize = sharedmsg.MsgMemorySummarize
type MsgMemorySummarizeDone ¶
type MsgMemorySummarizeDone = sharedmsg.MsgMemorySummarizeDone
type MsgMirrorDirty ¶
type MsgMirrorDirty struct {
}
MsgMirrorDirty is a lightweight notification published by the WorkspaceActor to rysh.ws.mirrorDirty whenever a mirror tab's structure or per-pane VT content changes (a layout doc or a raw VT frame was applied). The TUI subscribes to it and triggers a coalesced (~16 ms) snapshot refresh so a mirrored (shared) tab repaints on arrival instead of waiting for the 250 ms render tick. It carries no payload beyond the share id (used only for logging / future filtering); the TUI re-reads the full snapshot regardless.
type MsgMirrorMaximizePane ¶
type MsgMirrorMaximizePane struct {
On bool `json:"on"`
Rows int `json:"rows,omitempty"`
Cols int `json:"cols,omitempty"`
}
MsgMirrorMaximizePane is sent by the subscriber TUI to the WorkspaceActor when the user (un)fullscreens a pane while viewing a shared (mirror) tab. The WorkspaceActor forwards it to the source as a "maximize" control command on the subscriber's focused source pane, so the source maximizes that pane too and its PTY-backed app re-renders at full size. On=false restores the source layout.
Rows/Cols carry the SUBSCRIBER's own fullscreen content dimensions (the PTY size its maximized pane occupies). The source sizes the shared pane's PTY to these dims rather than its own full body, so a subscriber with a larger terminal than the source gets a true full-resolution render at its own screen size instead of one capped at the source's screen. Zero when On=false (restore).
type MsgMirrorPaneVTFrame ¶
type MsgMirrorPaneVTFrame struct {
PaneID string `json:"pane_id"`
Seq uint64 `json:"seq"` // monotonic per pane
BaseSeq uint64 `json:"base_seq,omitempty"` // delta applies onto this seq; 0 for keyframe
Interactive bool `json:"interactive"` // false = pane left interactive mode
Rows int `json:"rows"` // total screen rows (authoritative size)
Full []string `json:"full,omitempty"` // keyframe: entire screen
Changed []VTLineDelta `json:"changed,omitempty"` // delta: only changed rows
CursorRow int `json:"cursor_row"`
CursorCol int `json:"cursor_col"`
}
MsgMirrorPaneVTFrame is PUSHED on rysh.pane.{mirrorID}.vtframe on every VT change of an interactive mirror pane — no request/reply, no WorkspaceActor mailbox hop. It is keyframe+delta and sequence-numbered for loss recovery:
- keyframe: Full carries the entire screen, BaseSeq == 0.
- delta: Changed carries only the changed rows, BaseSeq == the seq the delta applies onto (the receiver's last applied seq must match).
A receiver tracks the last applied Seq per pane; a gap (BaseSeq != lastSeq) is healed by a resync pull (MsgGetMirrorPaneVT, served as a keyframe). A non-interactive frame (Interactive == false) tells the receiver to drop its delta state — the source pane left interactive mode.
type MsgMirrorPaneVTReply ¶
type MsgMirrorPaneVTReply struct {
PaneID string `json:"pane_id"`
Interactive bool `json:"interactive"`
Screen []string `json:"screen,omitempty"`
CursorRow int `json:"cursor_row"`
CursorCol int `json:"cursor_col"`
Seq uint64 `json:"seq"`
}
MsgMirrorPaneVTReply carries one mirror pane's live VT frame. Interactive is false when the pane has no VT state (left interactive mode or unknown id). Seq is the current sequence the push stream (rysh.pane.{mirrorID}.vtframe) is at, so a backfill/resync reply (treated as a keyframe) carries the seq the subsequent deltas will build onto — deltas with BaseSeq == this Seq apply.
type MsgMirrorScrollbackReply ¶
type MsgMirrorScrollbackReply struct {
Rows []string `json:"rows,omitempty"`
}
MsgMirrorScrollbackReply carries the mirror pane's scrollback + screen rows.
type MsgMirrorTabOp ¶
type MsgMirrorTabOp struct {
TabID string `json:"tab_id"`
PaneID string `json:"pane_id"`
Op string `json:"op"`
Dir string `json:"dir,omitempty"`
Delta int `json:"delta,omitempty"`
Name string `json:"name,omitempty"`
}
MsgMirrorTabOp applies a structural operation relayed from a mirror-tab subscriber to a specific source tab + pane. The source's UpstreamShareActor publishes this to the workspace inbox so the WorkspaceActor can generate a unique alias (for create ops) and target the shared tab by ID. Op is one of create_pane | create_pane_down | create_stacked | close_pane | stack_rotate | stack_move | resize | resize_height | rename_pane. For rename_pane, Name holds the new given-name to assign to the target pane.
type MsgMoveTab ¶
type MsgMoveTab struct {
Direction Direction `json:"direction"`
}
MsgMoveTab reorders the active tab. DirLeft moves it one position toward the start of the tab list; DirRight moves it one position toward the end. The moved tab stays active; it is a no-op at the edges.
type MsgOrchestratorDone ¶
type MsgOrchestratorDone = sharedmsg.MsgOrchestratorDone
type MsgPaneAIHistoryAppend ¶
type MsgPaneAIHistoryAppend = sharedmsg.MsgPaneAIHistoryAppend
type MsgPaneAIOutputAppend ¶
type MsgPaneAIOutputAppend = sharedmsg.MsgPaneAIOutputAppend
type MsgPaneActivateMode ¶
MsgPaneActivateMode tells stream clients (the TUI, the desktop app) to switch a pane's VISIBLE input mode now — the deterministic backend→frontend "show this mode" push that the frontend's local mode cycle otherwise never receives. Used when a humanoid registers its output pane (##humanoid register-output) so the pane flips to the humanoid's surface (the "email" client, or "external") instead of silently filling a buffer the user must cycle to by hand. Published on pane.<id>.activateMode. Mode must be one of the pane's enabled modes.
type MsgPaneChatHistoryAppend ¶
type MsgPaneChatHistoryAppend = sharedmsg.MsgPaneChatHistoryAppend
type MsgPaneChatOutputAppend ¶
type MsgPaneChatOutputAppend = sharedmsg.MsgPaneChatOutputAppend
type MsgPaneClearOutput ¶
type MsgPaneClearOutput struct {
PaneID string `json:"pane_id"`
}
MsgPaneClearOutput clears a pane's display output buffers without recording anything in command history — the readline Ctrl+L gesture in shell mode (typing `clear` still goes through the shell and IS recorded, like bash). Published directly to rysh.pane.{paneID}.inbox.
type MsgPaneDisableMode ¶
type MsgPaneDisableMode struct {
PaneID string `json:"pane_id"`
// Humanoid marks the removal of a dynamic per-humanoid mode.
Humanoid bool `json:"humanoid,omitempty"`
Mode string `json:"mode"`
}
MsgPaneDisableMode disables (removes) an input mode from a pane's cycle. "shell" cannot be disabled. Routed: WorkspaceActor → PaneActor (direct, pass-through).
type MsgPaneEnableMode ¶
type MsgPaneEnableMode struct {
PaneID string `json:"pane_id"`
Mode string `json:"mode"` // canonical: shell|prompt|rysh|chat|external|web
WebProfile string `json:"web_profile,omitempty"`
WebURL string `json:"web_url,omitempty"`
// Humanoid marks a dynamic per-humanoid mode registration (Mode is the
// humanoid name). Only then is a non-fixed mode name accepted; ##mode keeps
// the strict fixed-mode set.
Humanoid bool `json:"humanoid,omitempty"`
}
MsgPaneEnableMode enables (adds) an input mode to a pane's cycle. Idempotent. For Mode=="web", WebProfile/WebURL carry the browser binding and are refreshed on re-enable. Routed: WorkspaceActor → PaneActor (direct, pass-through).
type MsgPaneExecChat ¶
type MsgPaneExecChat struct {
Message string `json:"message"`
SenderName string `json:"sender_name,omitempty"`
}
MsgPaneExecChat sends a chat message to the pane's agentic actor. SenderName, when non-empty, overrides the receiving pane's own profile name so that remote-originated chat messages show the sender's identity rather than the host pane's profile.
type MsgPaneExecPrompt ¶
type MsgPaneExecPrompt struct {
Prompt string `json:"prompt"`
}
MsgPaneExecPrompt sends a prompt to the LLMActor. PaneActor forwards this to rysh.pane.{paneID}.llm.inbox as MsgExecPrompt.
type MsgPaneExecRysh ¶
type MsgPaneExecRysh struct {
Command string `json:"command"`
}
MsgPaneExecRysh records a rysh system command in the pane's rysh history.
type MsgPaneExecShell ¶
type MsgPaneExecShell struct {
Command string `json:"command"`
}
MsgPaneExecShell executes a shell command in the pane's PTY.
type MsgPaneExternalHistoryAppend ¶
type MsgPaneExternalHistoryAppend = sharedmsg.MsgPaneExternalHistoryAppend
type MsgPaneExternalOutputAppend ¶
type MsgPaneExternalOutputAppend = sharedmsg.MsgPaneExternalOutputAppend
type MsgPaneGroupActivePaneReply ¶
type MsgPaneGroupActivePaneReply struct {
PaneID string `json:"pane_id"`
PaneCount int `json:"pane_count"`
}
MsgPaneGroupActivePaneReply carries the PaneGroupActor's active pane info.
type MsgPaneGroupCreateStackedPane ¶
type MsgPaneGroupCreateStackedPane struct {
PaneID string `json:"pane_id"`
Title string `json:"title"`
}
MsgPaneGroupCreateStackedPane creates a new stacked pane in this group.
type MsgPaneGroupDeletePane ¶
type MsgPaneGroupDeletePane struct {
PaneID string `json:"pane_id"`
}
MsgPaneGroupDeletePane deletes a specific pane by ID within a group.
type MsgPaneGroupFocusPaneByID ¶
type MsgPaneGroupFocusPaneByID struct {
PaneID string `json:"pane_id"`
}
MsgPaneGroupFocusPaneByID makes the identified member pane this group's active (expanded) stack pane. Sent by the lane's focus-by-id path so the GROUP's notion of its active pane follows workspace focus: without it, focusing a background stacked pane (mouse click on its title bar, focus restore) updated tab/lane bookkeeping only — the group kept the old pane expanded while input routed to the newly-"active" invisible one.
type MsgPaneGroupSetPaneHidden ¶ added in v0.2.6
type MsgPaneGroupSetPaneHidden struct {
PaneID string `json:"pane_id"`
Hidden bool `json:"hidden"`
}
MsgPaneGroupSetPaneHidden hides or reveals one pane of this group, moving focus off it first when it is the active one (design 027 §5.1).
type MsgPaneGroupSnapshotReply ¶
type MsgPaneGroupSnapshotReply struct {
Snapshot domain.PaneGroupSnapshot `json:"snapshot"`
}
MsgPaneGroupSnapshotReply carries the pane group snapshot reply.
type MsgPaneGroupStackedPane ¶
type MsgPaneGroupStackedPane struct {
Direction Direction `json:"direction"`
}
MsgPaneGroupStackedPane cycles the stack in the specified direction. Replaces MsgPaneGroupStackedPaneNext and MsgPaneGroupStackedPanePrev.
type MsgPaneGroupStackedPaneMove ¶
type MsgPaneGroupStackedPaneMove struct {
Direction Direction `json:"direction"`
}
MsgPaneGroupStackedPaneMove reorders the active pane within this group's stack. DirUp moves it toward the front (index 0); DirDown moves it toward the back.
type MsgPaneGroupStackedPaneSelect ¶
type MsgPaneGroupStackedPaneSelect struct {
Index int `json:"index"`
}
MsgPaneGroupStackedPaneSelect activates the stacked pane at the given 0-based index within this group. Out-of-range indices are ignored.
type MsgPaneHistoryAppend ¶
type MsgPaneHistoryAppend = sharedmsg.MsgPaneHistoryAppend
type MsgPaneHopClear ¶
type MsgPaneHopClear struct{}
MsgPaneHopClear clears the stored hopped content from a pane.
type MsgPaneHopContent ¶
type MsgPaneHopContent struct {
SourcePaneID string `json:"source_pane_id"`
SourceAlias string `json:"source_alias"`
Content string `json:"content"`
ChatContent string `json:"chat_content,omitempty"`
// MemoryTurns is the number of LLM conversation turns forked into the
// target's session memory alongside this content (0 = terminal text
// only, no memory fork). The fork itself travels separately as
// MsgSessionMemoryReplace to the target's LLM-execution actor; this
// count lets the pane render status and pick the native resume prompt.
MemoryTurns int `json:"memory_turns,omitempty"`
}
MsgPaneHopContent delivers hopped content from a source pane to a target pane.
type MsgPaneHopResume ¶
type MsgPaneHopResume struct{}
MsgPaneHopResume triggers the AI prompt with the stored hopped content. When the hop also forked session memory, the prompt continues the forked conversation natively instead of dumping the copied text.
type MsgPaneImportCookies ¶
type MsgPaneImportCookies struct {
Profile string `json:"profile"`
Cookies []ImportCookie `json:"cookies"`
}
MsgPaneImportCookies carries cookies pulled from a profile's real-Chrome login jar (`##web import-google-session`) to the desktop app, which writes them into persist:<profile> so web panes on that profile become authenticated — e.g. a Google session so third-party "Sign in with Google" completes without Google's embedded-browser block. Routed: WorkspaceActor → web server → app. Profile-global (not pane-scoped).
type MsgPaneKillForeground ¶ added in v0.2.6
type MsgPaneKillForeground struct {
PaneID string `json:"pane_id"`
Hard bool `json:"hard,omitempty"`
}
MsgPaneKillForeground asks a pane to SIGNAL its foreground process group — the hard stop, founder ruling 2026-08-11 reversing 027 ruling 3 for the fleet-stop verb. ESC ends a turn but cannot cancel a pending task-notification, so an interrupted agent with a background task wakes itself (F-41); a dead process cannot be woken, and its absence is verifiable by process state rather than by reading a screen. The claude session is resumable afterwards: the session id is pinned at launch, so `claude --resume <id>` restores the conversation.
Hard=false sends SIGTERM to the group; Hard=true sends SIGKILL. The caller escalates only after verifying the group survived — policy lives in the router, where it is testable.
type MsgPaneNativeMode ¶
MsgPaneNativeMode switches a pane's native pass-through shell mode (##native): the pane renders its VT screen permanently and every keystroke goes straight to the PTY — bash owns readline, completion, history and PS1. Action is "on", "off", or "toggle". Sent to rysh.pane.{paneID}.inbox by the ##native command (workspace) and by the TUI's double-Esc exit gesture.
type MsgPaneOutputAppend ¶
type MsgPaneOutputAppend = sharedmsg.MsgPaneOutputAppend
type MsgPaneProcess ¶ added in v0.2.3
type MsgPaneProcess struct {
PaneID string `json:"pane_id"`
// Event is "start" (a program took the terminal) or "exit" (it gave it
// back). There is no exit status: the foreground process group is gone by
// the time we notice, and inventing a status would be worse than omitting
// one.
Event string `json:"event"`
Program string `json:"program,omitempty"`
PGID int `json:"pgid,omitempty"`
// UnixMilli rather than time.Time: this crosses the wire as JSON and is
// consumed by non-Go readers (the fan-out helper is Python).
At int64 `json:"at"`
}
MsgPaneProcess announces a change in a pane's FOREGROUND program: a command started, or the pane fell back to its shell. Published to rysh.pane.{paneID}.process.
It exists so a supervisor can wait for an event instead of polling a pane's rendered screen. Screen-scraping is how you end up matching on a TUI's footer text ("esc to interrupt") and calling a program finished because it redrew.
Program is the executable name (Linux; empty where it cannot be resolved) and is empty for the shell — "back to the prompt" is the end of a run, and naming the shell would make every exit look like a new program starting.
type MsgPaneRawDirty ¶
type MsgPaneRawDirty struct {
PaneID string `json:"pane_id"`
}
MsgPaneRawDirty is a fire-and-forget notification that a pane's raw VT state (local p.VTScreen or remote p.RemoteVTScreen) has changed and the TUI should refresh that pane's full content snapshot. Published to rysh.pane.{paneID}.rawDirty at the source-side raw-publish coalesce cadence (~16ms for local raw panes) and at the remote-share listener's render cadence (~33ms for remote raw panes). Replaces the TUI's fixed 50ms wholesale poll of every visible raw pane with push-driven, per-change fetches — idle raw panes incur zero TUI work, and busy panes are still bounded by the listener throttle. The payload is intentionally just the pane id so the message is tiny and cheap to flood.
type MsgPaneRawOutputAppend ¶
type MsgPaneRawOutputAppend struct {
PaneID string `json:"pane_id"`
Data string `json:"data"` // base64-encoded raw PTY bytes
}
MsgPaneRawOutputAppend carries raw PTY bytes (with ANSI sequences intact) for the sharing pipeline during interactive mode. Data is base64-encoded. Published to rysh.pane.{paneID}.rawOutput by rawReadLoop.
type MsgPaneRegisterForgedProxies ¶
type MsgPaneRegisterForgedProxies struct {
Ops []ForgedOpSpec `json:"ops"`
}
MsgPaneRegisterForgedProxies tells a subscriber pane to (re)register inert forged-API proxies for a remote share's operations (phase 2a — the proxies are visible to the pane's agent but return "not yet enabled" when called).
type MsgPaneReleaseSize ¶ added in v0.2.3
type MsgPaneReleaseSize struct {
ClientID string `json:"client_id"`
}
MsgPaneReleaseSize withdraws a viewport's size claim: the pane drops it and re-sizes to the smallest of whatever remains (or leaves the PTY alone when nothing is left).
Only clients whose liveness the pane cannot check for itself need to send this. A "tui:<pid>" claim is pruned by a process-liveness check, so a terminal UI never has to; the web hub does send it, because a closed WebSocket leaves no trace the PaneActor could test.
type MsgPaneReplayShareState ¶
type MsgPaneReplayShareState struct {
}
MsgPaneReplayShareState asks a PaneActor to re-publish its current interactive share state — a MsgPaneShareModeChange followed by a full-screen repaint — so a newly (re)joined share subscriber resumes rendering the live interactive app instead of seeing stale scrollback/history. Share output over NATS is ephemeral pub/sub, so a subscriber that joins after the app entered interactive mode never received the original mode/raw messages; this re-sends them on demand. Sent by UpstreamShareActor on a subscriber-join notification. It is a no-op when the pane is not currently interactive.
type MsgPaneResize ¶
type MsgPaneResize struct {
Rows int `json:"rows"`
Cols int `json:"cols"`
// ClientID names the viewport this claim belongs to, so one viewport's
// later claim replaces its own earlier one rather than adding to the set.
// Terminal UIs use "tui:<pid>" — the pane prunes those by checking whether
// the process is still alive, which covers a clean exit and a crash alike.
// Web/desktop-app clients use "web:<n>" and are released explicitly by the
// hub on disconnect. Empty is a legacy/anonymous client and behaves as a
// single shared claim.
ClientID string `json:"client_id,omitempty"`
// Override applies these dimensions to the PTY directly, bypassing
// arbitration and leaving the claim set untouched. It is for deliberate
// one-off sizing that is not a viewport measurement — a remote share
// subscriber asking the source to render at ITS resolution, which is a
// choice the source honours rather than a constraint to intersect.
Override bool `json:"override,omitempty"`
}
MsgPaneResize tells the PaneActor how much room a viewport gives this pane.
A pane has ONE PTY but can be on screen in several places at once — a terminal UI and a desktop-app window attached to the same daemon, or two of either. Each renders the pane at its own size, and each used to send this message as a command that won last-writer-wins, so two attached front-ends fought over pty.Setsize and an interactive app reflowed on every frame.
So this is a CLAIM, not a command: the pane records each viewport's size and sizes its PTY to the smallest one (see PaneActor.applyEffectivePaneSize), so the rendered grid fits inside every viewport showing it. A larger viewport letterboxes; a smaller one would otherwise have to truncate or wrap, which corrupts the display of a full-screen app.
type MsgPaneResized ¶
type MsgPaneResized struct {
PaneID string `json:"pane_id"`
Rows int `json:"rows"`
Cols int `json:"cols"`
}
MsgPaneResized is published by PaneActor after a resize to notify interested local subscribers (e.g. RemoteShareListenerActor) of the new dimensions. Published to rysh.pane.{paneID}.resized.
type MsgPaneRyshHistoryAppend ¶
type MsgPaneRyshHistoryAppend = sharedmsg.MsgPaneRyshHistoryAppend
type MsgPaneRyshOutputAppend ¶
type MsgPaneRyshOutputAppend = sharedmsg.MsgPaneRyshOutputAppend
type MsgPaneScrollbackDeltaReply ¶
type MsgPaneScrollbackDeltaReply struct {
Evicted int64 `json:"evicted"`
Rows []string `json:"rows,omitempty"`
}
MsgPaneScrollbackDeltaReply carries the incremental scrollback rows and the pane's current monotonic evicted total (use as the next Since).
type MsgPaneScrollbackReply ¶
type MsgPaneScrollbackReply struct {
Rows []string `json:"rows,omitempty"`
}
MsgPaneScrollbackReply carries the rendered scrollback + current-screen rows.
type MsgPaneSetApprovalPaneGroups ¶
type MsgPaneSetApprovalPaneGroups = sharedmsg.MsgPaneSetApprovalPaneGroups
type MsgPaneSetGivenName ¶
type MsgPaneSetGivenName struct {
Name string `json:"name"`
}
MsgPaneSetGivenName sets the user-assigned given-name for a pane.
type MsgPaneSetHidden ¶ added in v0.2.6
type MsgPaneSetHidden struct {
Hidden bool `json:"hidden"`
}
MsgPaneSetHidden takes a pane off screen, or puts it back (design 027 §5.1).
Rendering only. The pane keeps its PTY and its program, and stays addressable by ANSA and by every `##pane` command — this is not a way to stop a pane, and anything that treats it as one is a bug.
type MsgPaneSetHumanoid ¶
type MsgPaneSetHumanoid struct {
HumanoidName string `json:"humanoid_name"`
}
MsgPaneSetHumanoid notifies a pane that it is registered to a humanoid.
type MsgPaneSetMeta ¶ added in v0.2.3
MsgPaneSetMeta writes one entry of a pane's metadata map (`##pane meta`). An empty Value deletes the key — the same convention as an env var, and it keeps deletion from needing a second message type.
Metadata is for whoever is DRIVING the pane: a supervisor recording the session id of the claude it launched, the task a pane was opened for, which process spawned it. rysh itself never interprets it. It rides the pane's KV snapshot, so it survives a daemon restart and is readable by any tool that can ask for a snapshot — which is the point. A sidecar file in one tool's private directory is invisible to every other tool and to the pane list.
type MsgPaneSetProvider ¶
type MsgPaneSetProvider struct {
Provider string `json:"provider"`
Model string `json:"model,omitempty"`
// Scope names the level of the model hierarchy this selection came from
// (session > workspace > tab > lane > stack > pane). "" or "pane" is the
// pane's OWN choice: it is persisted in the pane's KV record and outranks
// everything above. Any broader value is INHERITED — applied live but
// never persisted, because the workspace recomputes it from the binding of
// the nearest enclosing scope. Keeping the two in separate slots is what
// stops a lane-wide re-bind from clobbering a pane that chose for itself.
Scope string `json:"scope,omitempty"`
}
MsgPaneSetProvider sets or clears the pane's runtime provider override (`##pane provider` — design 002 §3.4). Empty Provider clears the override. Applied to the pane's next agentic prompt.
type MsgPaneSetRemoteSubscriber ¶
type MsgPaneSetRemoteSubscriber struct {
Subscriber bool `json:"subscriber"`
}
MsgPaneSetRemoteSubscriber marks (or unmarks) a pane as the local owner pane of a remote-share subscription (##upstream subscribe). Sent from RemoteShareListenerActor on start/stop. While set, the pane folds non-shell remote modes (chat/rysh/external) into its merged display buffer as well, so a passively-viewing subscriber sees that output in the default view without having to manually switch the pane's input mode. shell/ai already merge.
type MsgPaneSetShareRestrictions ¶
type MsgPaneSetShareRestrictions struct {
}
MsgPaneSetShareRestrictions propagates restrictions from a remote share owner to a local pane in controller mode (via RemoteShareListenerActor).
type MsgPaneSetSharingState ¶
type MsgPaneSetSharingState struct {
Sharing bool `json:"sharing"`
URL string `json:"url,omitempty"`
}
MsgPaneSetSharingState tells a PaneActor to update its upstream sharing state. Sent by UpstreamShareActor when it connects or disconnects from the upstream server, so PaneActor.sharing correctly reflects the ShareRegistry-based sharing mechanism (##share pane) in addition to the legacy MsgPaneShareStart path.
type MsgPaneSetTitle ¶
type MsgPaneSetTitle struct {
Title string `json:"title"`
}
MsgPaneSetTitle renames the pane.
type MsgPaneShareModeChange ¶
type MsgPaneShareModeChange struct {
}
MsgPaneShareModeChange signals an interactive mode transition for sharing. Published to rysh.pane.{paneID}.shareMode on interactive enter/exit and PTY resize.
type MsgPaneShareStart ¶
type MsgPaneShareStart struct{}
MsgPaneShareStart tells a PaneActor to start sharing to the remote upstream.
type MsgPaneShareStatus ¶
type MsgPaneShareStatus struct{}
MsgPaneShareStatus requests the sharing status of a PaneActor.
type MsgPaneShareStatusReply ¶
type MsgPaneShareStatusReply struct {
}
MsgPaneShareStatusReply carries the sharing status of a PaneActor.
type MsgPaneShareStop ¶
type MsgPaneShareStop struct{}
MsgPaneShareStop tells a PaneActor to stop sharing to the remote upstream.
type MsgPaneShellHistoryAppend ¶
type MsgPaneShellHistoryAppend = sharedmsg.MsgPaneShellHistoryAppend
type MsgPaneShellOutputAppend ¶
type MsgPaneShellOutputAppend = sharedmsg.MsgPaneShellOutputAppend
type MsgPaneSnapshotReply ¶
type MsgPaneSnapshotReply struct {
Snapshot domain.PaneSnapshot `json:"snapshot"`
}
MsgPaneSnapshotReply carries the pane snapshot reply.
type MsgPaneStatusUpdate ¶
type MsgPaneStatusUpdate = sharedmsg.MsgPaneStatusUpdate
type MsgPaneStopped ¶
type MsgPaneStopped struct {
PaneID string `json:"pane_id"`
}
MsgPaneStopped announces that a pane actor has fully stopped (any close path: keyboard close, group/lane/tab cascade, CLI delete). Published to ws.inbox from the PaneActor's Stopping hook so the workspace can release per-pane resources it holds — today: stopping an in-flight replay playback when its dedicated replay pane closes (design 006 v2).
type MsgPaneSubmitInput ¶
type MsgPaneSubmitInput struct {
Text string `json:"text"`
Mode string `json:"mode"`
ContentBlocks []provider.ContentBlock `json:"content_blocks,omitempty"`
}
MsgPaneSubmitInput sends raw user input to a PaneActor for mode routing. The PaneActor performs the mode switch internally (shell/prompt/rysh/chat).
ContentBlocks (follow-up 1b) carries optional structured content blocks — e.g. an image attached via `##image <path>` — that the PaneActor forwards to MsgAgenticPrompt.ContentBlocks for prompt mode.
type MsgPaneTerminated ¶
MsgPaneTerminated is published when a PaneActor stops.
type MsgPaneVTReply ¶
type MsgPaneVTReply struct {
PaneID string `json:"pane_id"`
Interactive bool `json:"interactive"`
Screen []string `json:"screen,omitempty"`
CursorRow int `json:"cursor_row"`
CursorCol int `json:"cursor_col"`
}
MsgPaneVTReply carries one local pane's live interactive VT frame. Interactive is false when the pane is not currently showing an interactive program (the TUI then leaves its last frame in place and lets the slower full-content reconcile path catch the transition).
type MsgPaneWebHeadless ¶
type MsgPaneWebHeadless struct {
PaneID string `json:"pane_id"`
Op string `json:"op"` // "on" | "off" | "status"
Profile string `json:"profile,omitempty"`
URL string `json:"url,omitempty"`
}
MsgPaneWebHeadless controls the pane's CLI-owned headless browser executor (Phase 4 web automation — runs browser_action requests in a headless Chromium without the desktop app). Routed: WorkspaceActor → PaneActor.
Op "on" — spawn the headless executor (Profile/URL default to the
pane's web binding); enables web mode state and unbinds any
desktop-app view so exactly ONE executor answers
browser.request.
Op "off" — stop the executor; rebinds the app view when web mode is
still enabled.
Op "status" — print the executor state to the pane's rysh output.
type MsgPipelineCommand ¶
type MsgPipelineCommand struct {
PaneID string `json:"pane_id"` // pane that issued the command (for output routing)
Cmd string `json:"cmd"` // "run"
Args string `json:"args"` // remaining arguments
}
MsgPipelineCommand is sent from WorkspaceActor to TabActor for ##pipe commands that require actor.Context (e.g. "run" which may need to spawn the pipeline actor).
type MsgPipelineOutputAppend ¶
type MsgPipelineOutputAppend = sharedmsg.MsgPipelineOutputAppend
type MsgProxyAuditSnapshotReply ¶
type MsgProxyAuditSnapshotReply = sharedmsg.MsgProxyAuditSnapshotReply
type MsgProxyAuditSnapshotRequest ¶
type MsgProxyAuditSnapshotRequest = sharedmsg.MsgProxyAuditSnapshotRequest
type MsgProxyRequestAudit ¶
type MsgProxyRequestAudit = sharedmsg.MsgProxyRequestAudit
type MsgRawKeyInput ¶
MsgRawKeyInput sends raw keystroke bytes to the PaneActor's PTY in raw mode. Published to rysh.pane.{paneID}.rawinput as a data-plane bypass for minimal latency.
type MsgReconcileWorkspaces ¶
type MsgReconcileWorkspaces struct{}
MsgReconcileWorkspaces asks the session to reconcile its live workspace set against the on-disk config file. It is published fire-and-forget by the TUI to ws.inbox on attach/startup. The active WorkspaceActor forwards it to the WorkspaceFarmActor, which re-reads the daemon's OWN config file and spawns any workspace that was added since the daemon started (add-only — existing workspaces are never removed or restarted). It carries no payload: the daemon is authoritative for which config file to read.
type MsgRelayActivate ¶
type MsgRelayActivate struct {
PaneID string `json:"pane_id"`
Cols int `json:"cols"`
Rows int `json:"rows"`
}
MsgRelayActivate tells the PaneActor to enter relay mode: rawReadLoop starts publishing raw PTY bytes to rysh.pane.{id}.relay.data (no envelope, raw binary). The TUI sends this after subscribing to the relay subjects and entering alt screen.
type MsgRelayDeactivate ¶
type MsgRelayDeactivate struct {
PaneID string `json:"pane_id"`
}
MsgRelayDeactivate tells the PaneActor to exit relay mode. rawReadLoop stops publishing to the relay subject.
type MsgReloadPrompts ¶
type MsgReloadPrompts = sharedmsg.MsgReloadPrompts
Follow-up 2b: prompt hot-reload broadcast.
type MsgReloadPromptsRequest ¶
type MsgReloadPromptsRequest struct {
Reason string `json:"reason,omitempty"`
}
MsgReloadPromptsRequest asks the active WorkspaceActor to re-read the layered prompt store and rebroadcast MsgReloadPrompts to its panes — the same path as the ##agent reload-prompts command. Published to ws.inbox by the fsnotify auto-reload watcher (follow-up 2b). Reason is for logging only.
type MsgRemoteForwardCommand ¶
type MsgRemoteForwardCommand struct {
CommandType string `json:"command_type"` // "exec_shell", "exec_prompt", "exec_chat"
Payload string `json:"payload"`
// TargetPaneID names the source pane the keystroke/command was aimed at,
// captured at press time on the subscriber. Empty for older clients.
TargetPaneID string `json:"target_pane_id,omitempty"`
}
MsgRemoteForwardCommand is published by a PaneActor in controller mode to ask the WorkspaceActor to forward a command to the active remote share listener.
type MsgRemoteInteractiveModeChange ¶
type MsgRemoteInteractiveModeChange struct {
Interactive bool `json:"interactive"`
Rows int `json:"rows"`
Cols int `json:"cols"`
}
MsgRemoteInteractiveModeChange notifies a pane that a remote share has entered or exited interactive mode. Sent from RemoteShareListenerActor or PaneSharedOutputListenerActor to the owning PaneActor.
type MsgRemotePaneFullscreen ¶
type MsgRemotePaneFullscreen struct {
TabID string `json:"tab_id"`
PaneID string `json:"pane_id"`
On bool `json:"on"`
Rows int `json:"rows,omitempty"`
Cols int `json:"cols,omitempty"`
}
MsgRemotePaneFullscreen is published by the source UpstreamShareActor to the ws.remoteFullscreen topic when a controlling subscriber maximizes (or restores) a shared pane. The source TUI subscribes and (un)fullscreens that pane locally — reusing the same path as Alt+P f — so the source pane's PTY is resized and the interactive app reflows. The enlarged screen is then mirrored back to subscribers via the existing per-pane VT stream.
Rows/Cols, when > 0, are the subscriber's requested fullscreen PTY dimensions: the source sizes the pane's PTY to these so the subscriber sees a full-resolution render at its own screen size. When 0 the source falls back to its own full body.
type MsgRemoteScrollbackAppend ¶
type MsgRemoteScrollbackAppend struct {
Reset bool `json:"reset,omitempty"`
Rows []string `json:"rows,omitempty"`
}
MsgRemoteScrollbackAppend forwards newly-evicted scrollback lines (rendered ANSI rows, oldest first) from a remote share's reconstructed VTerm to the owning PaneActor, so subscriber-side copy mode can scroll the remote program's history. Reset=true tells the pane to discard any prior remote scrollback first (sent when the listener (re)creates its VTerm).
type MsgRemoteUpstreamConnect ¶
type MsgRemoteUpstreamConnect struct{}
MsgRemoteUpstreamConnect tells a RemoteUpstreamActor to connect.
type MsgRemoteUpstreamDisconnect ¶
type MsgRemoteUpstreamDisconnect struct{}
MsgRemoteUpstreamDisconnect tells a RemoteUpstreamActor to disconnect.
type MsgRemoteUpstreamStatus ¶
type MsgRemoteUpstreamStatus struct {
Connected bool `json:"connected"`
Error string `json:"error,omitempty"`
PaneID string `json:"pane_id"`
URL string `json:"url"`
}
MsgRemoteUpstreamStatus carries the remote upstream connection status.
type MsgRemoteVTScreenUpdate ¶
type MsgRemoteVTScreenUpdate struct {
Screen []string `json:"screen"`
CursorRow int `json:"cursor_row"`
CursorCol int `json:"cursor_col"`
}
MsgRemoteVTScreenUpdate pushes a rendered VTerm screen from a remote share to the owning PaneActor. The screen lines replace the pane's display when RemoteInteractive is true.
type MsgRenameLane ¶
type MsgRenameLane struct {
Name string `json:"name"`
}
MsgRenameLane sets the name of the currently active lane.
type MsgRenamePane ¶
type MsgRenamePane struct {
Title string `json:"title"`
}
MsgRenamePane renames the currently active pane.
type MsgRenameTab ¶
type MsgRenameTab struct {
Title string `json:"title"`
}
MsgRenameTab renames the currently active tab.
type MsgReplayControl ¶
type MsgReplayControl struct {
PaneID string `json:"pane_id"`
// Action: "pause" (toggle), "seek" (by DeltaMs), "faster", "slower", "stop".
Action string `json:"action"`
DeltaMs int64 `json:"delta_ms,omitempty"` // seek delta, negative = backward
}
MsgReplayControl is a playback control for the active replay pane, published to ws.inbox by the TUI while the replay pane is focused (space pause, ←/→ seek, +/- speed). PaneID names the replay pane the key was pressed in; the workspace ignores controls that do not match its active replay pane.
type MsgResizePane ¶
type MsgResizePane struct {
Delta int `json:"delta"`
}
MsgResizePane adjusts the width of the active lane. Delta > 0 grows the lane; Delta < 0 shrinks it.
type MsgResizePaneHeight ¶
type MsgResizePaneHeight struct {
Delta int `json:"delta"`
}
MsgResizePaneHeight adjusts the height of the active pane group within the lane. Delta > 0 grows the group; Delta < 0 shrinks it.
type MsgResizePaneWidth ¶
type MsgResizePaneWidth struct {
Delta int `json:"delta"`
}
MsgResizePaneWidth adjusts the width flex of the active lane.
type MsgRestoreConversation ¶
type MsgRestoreConversation = sharedmsg.MsgRestoreConversation
type MsgResumeNativeAgents ¶ added in v0.2.6
type MsgResumeNativeAgents struct {
Retries int `json:"retries"`
}
MsgResumeNativeAgents asks the workspace to bring back the agents it had launched itself, after a stop/start has rebuilt the session from KV (design 029).
Scheduled once the layout is restored, and retried while panes are still coming up: a restored pane's shell is spawned by its own actor's Started hook, so "the pane exists" and "the pane can run a command" are separated by a few hundred milliseconds.
type MsgRunStatusReply ¶
type MsgRunStatusReply = sharedmsg.MsgRunStatusReply
type MsgSessionMemoryReplace ¶
type MsgSessionMemoryReplace = sharedmsg.MsgSessionMemoryReplace
type MsgSessionMemoryReply ¶
type MsgSessionMemoryReply = sharedmsg.MsgSessionMemoryReply
type MsgSetChatOutputPane ¶
type MsgSetChatOutputPane = sharedmsg.MsgSetChatOutputPane
type MsgSetConnectedPane ¶
type MsgSetConnectedPane struct {
PaneID string `json:"pane_id"` // remote pane ID (empty = disconnected)
}
MsgSetConnectedPane tells a PaneActor that it is connected to (or disconnected from) a remote shared pane via upstream subscription.
type MsgSetControllerMode ¶
type MsgSetControllerMode struct {
PaneAlias string `json:"pane_alias"`
Active bool `json:"active"`
}
MsgSetControllerMode tells a PaneActor to enter or exit controller mode for a remote upstream share. When Active is true, shell/prompt/chat input will be forwarded to the remote pane instead of executing locally.
type MsgSetGroundingMode ¶
type MsgSetGroundingMode = sharedmsg.MsgSetGroundingMode
type MsgSetRunBudget ¶
type MsgSetRunBudget = sharedmsg.MsgSetRunBudget
type MsgSetTabBarOrientation ¶ added in v0.2.6
type MsgSetTabBarOrientation struct {
Vertical bool `json:"vertical"`
Toggle bool `json:"toggle,omitempty"`
}
MsgSetTabBarOrientation switches the tab bar between a horizontal strip under the workspace row and a vertical column down the left edge of the body. Orientation is per-workspace state and survives a restart.
Vertical selects the orientation directly; Toggle flips whatever is current and takes precedence over Vertical when set.
type MsgSetWorkingDir ¶
type MsgSetWorkingDir struct {
Dir string `json:"dir"`
}
MsgSetWorkingDir updates the working directory that newly created panes start in. It is broadcast down the hierarchy (Workspace → Tab → Lane → PaneGroup) so that every pane-creating actor's config copy is updated; existing panes keep their already-started shells. Backs `##session cwd <path>`.
type MsgShareDisableMode ¶
type MsgShareDisableMode struct {
}
MsgShareDisableMode disables a mode for remote users on the active pane. Routed: WorkspaceActor → PaneActor (direct, pass-through).
type MsgShareEnableMode ¶
type MsgShareEnableMode struct {
}
MsgShareEnableMode re-enables a previously disabled mode. Routed: WorkspaceActor → PaneActor (direct, pass-through).
type MsgShareEntity ¶
type MsgShareEntity struct {
// viewers (e.g. the mobile shares list) can identify the entity. For panes it
// packs the user-given name and the auto-assigned title as "<given> · <auto>"
// (or just "<auto>" when there is no distinct given name). Empty falls back to
// the entity id in the registry.
EntityAlias string `json:"entity_alias,omitempty"`
// the root the rysh-mobile file browser starts from for this share. For a tab
// share it applies to every pane in the tab. Empty means "resolve the browse
// root live per request" (the target pane's current working directory).
SharedRootFolder string `json:"shared_root_folder,omitempty"`
// Forged-API sharing (Task 2 phase 2a). ShareAPI opts the share's forge-origin
// operations in; Redact governs result redaction (the caller resolves its
// default of true); ForgedOps carries the operation specs the workspace
// computed at share time (forge-origin ∩ the shared entity's scope).
}
MsgShareEntity starts sharing an entity to the upstream server.
type MsgShareForgedAPI ¶
type MsgShareForgedAPI struct {
}
MsgShareForgedAPI carries the owner's shareable forged-API operation specs to subscribers (published last-value on ws.{workspace}.share.{shareID}.api).
type MsgShareListReply ¶
type MsgShareListReply struct {
}
MsgShareListReply carries the list of active shares.
type MsgShareOutput ¶
type MsgShareOutput struct {
}
MsgShareOutput carries share output from upstream to local listener.
type MsgShareRegisterAck ¶
type MsgShareRegisterAck struct {
}
MsgShareRegisterAck is the server's acknowledgment of a share registration.
type MsgShareRestrictionsUpdated ¶
type MsgShareRestrictionsUpdated struct {
}
MsgShareRestrictionsUpdated notifies UpstreamShareActor of restriction changes. Published by PaneActor to rysh.pane.{paneID}.restrictions on every change.
type MsgShareSetFileBrowse ¶
type MsgShareSetFileBrowse struct {
}
MsgShareSetFileBrowse sets the file-browse allow-absolute flag for remote subscribers of the pane's share. File browsing itself is always enabled; this only controls whether browsing may escape the pane's working-directory subtree. Routed: WorkspaceActor → PaneActor (direct, pass-through).
type MsgShareShellAllow ¶
type MsgShareShellAllow struct {
}
MsgShareShellAllow sets the shell command allow-list (clears forbid-list). Routed: WorkspaceActor → PaneActor (direct, pass-through).
type MsgShareShellClear ¶
type MsgShareShellClear struct {
}
MsgShareShellClear removes all shell command restrictions. Routed: WorkspaceActor → PaneActor (direct, pass-through).
type MsgShareShellForbid ¶
type MsgShareShellForbid struct {
}
MsgShareShellForbid sets the shell command forbid-list (clears allow-list). Routed: WorkspaceActor → PaneActor (direct, pass-through).
type MsgShareShowRestrictions ¶
type MsgShareShowRestrictions struct {
}
MsgShareShowRestrictions requests current restrictions for display. Routed: WorkspaceActor → PaneActor (direct, pass-through). Reply via rysh output.
type MsgShareStatus ¶
type MsgShareStatus struct {
}
MsgShareStatus requests the sharing status of an entity.
type MsgShareStatusReply ¶
type MsgShareStatusReply struct {
}
MsgShareStatusReply carries sharing status.
type MsgShutdown ¶
type MsgShutdown struct{}
MsgShutdown triggers a graceful shutdown of the workspace.
type MsgSpawnSubOrchestrator ¶
type MsgSpawnSubOrchestrator = sharedmsg.MsgSpawnSubOrchestrator
type MsgStackedPaneMove ¶
type MsgStackedPaneMove struct {
Direction Direction `json:"direction"`
}
MsgStackedPaneMove reorders the active pane within its stack by one slot. DirUp moves it toward the front (index 0); DirDown moves it toward the back. The moved pane stays active.
type MsgStackedPaneRotate ¶
type MsgStackedPaneRotate struct {
Direction Direction `json:"direction"`
}
MsgStackedPaneRotate cycles the stacked pane stack in the specified direction. Replaces MsgStackedPaneNext and MsgStackedPanePrev.
type MsgStackedPaneSelect ¶
type MsgStackedPaneSelect struct {
Index int `json:"index"`
}
MsgStackedPaneSelect activates the stacked pane at the given 0-based index within the active group (the position shown as n/N in the title bars, minus one). Out-of-range indices are ignored.
type MsgStartPaneListener ¶
type MsgStartPaneListener struct {
TargetPaneID string `json:"target_pane_id"`
TargetAlias string `json:"target_alias"` // for display purposes
}
MsgStartPaneListener tells a PaneActor to start listening to another pane's shared output.
type MsgStopPaneListener ¶
type MsgStopPaneListener struct{}
MsgStopPaneListener tells a PaneActor to stop listening.
type MsgSubOrchestratorResult ¶
type MsgSubOrchestratorResult = sharedmsg.MsgSubOrchestratorResult
type MsgSubmitInput ¶
type MsgSubmitInput struct {
Text string `json:"text"`
Mode string `json:"mode"`
// PaneID, when set, targets the input at that pane instead of the
// workspace's current active pane. Sent by the desktop app, whose input
// boxes are per-pane: routing by "active pane" raced daemon-side focus —
// under PTY churn a starved focus command made Enter execute in the
// PREVIOUS pane (e.g. straight into a running claude CLI). The workspace
// aligns focus to this pane before routing, healing any drift.
PaneID string `json:"pane_id,omitempty"`
// Programmatic marks input that NOBODY TYPED: an agent's rysh tool, a
// script, `rysh run`. It routes to PaneID exactly like typed input but must
// not move the human's focus there — a human typing is the strongest focus
// signal there is, and a machine submitting on a pane's behalf is no signal
// at all. Without it, every agent that ran a ## command dragged the cursor
// (and, across tabs, the whole visible tab) to itself.
Programmatic bool `json:"programmatic,omitempty"`
}
MsgSubmitInput submits user input (shell command or AI prompt). Mode is "shell" or "prompt"; empty falls back to the "!" prefix check.
type MsgSwapPane ¶
type MsgSwapPane struct{}
MsgSwapPane swaps the active lane position with the next one.
type MsgSwitchWorkspace ¶
type MsgSwitchWorkspace struct {
Index int `json:"index"`
Direction Direction `json:"direction,omitempty"`
}
MsgSwitchWorkspace switches the active workspace within the session. It is published by the TUI to the active workspace's ws.inbox as a request, so the reply carries the newly activated workspace's snapshot (race-free switch). The active WorkspaceActor resolves the target and forwards the handoff to its parent WorkspaceFarmActor. If Direction is DirNext/DirPrev it takes precedence; otherwise Index selects a 0-based workspace.
type MsgTabClosePane ¶
type MsgTabClosePane struct{}
MsgTabClosePane closes the active pane group in the active lane.
type MsgTabCreateGrid ¶
type MsgTabCreateGrid struct {
LaneTitles [][]string `json:"lane_titles"`
}
MsgTabCreateGrid seeds a grid of lanes into an existing tab. Each entry in LaneTitles is one new lane appended to the tab; the inner titles are the pane groups (one pane each) within that lane. Existing lanes are preserved. Used by `##new grid <lanes>x<panes> --here`.
type MsgTabCreateGroupsInLane ¶
type MsgTabCreateGroupsInLane struct {
LaneID string `json:"lane_id"`
Titles []string `json:"titles"`
}
MsgTabCreateGroupsInLane appends one pane group (a single pane) per title to the given lane, stacking them vertically, then equalizes the lane's group heights. Used by `##new grid <n>` to stack n panes in the active lane.
type MsgTabCreatePane ¶
type MsgTabCreatePane struct {
Title string `json:"title,omitempty"` // pre-generated unique alias
}
MsgTabCreatePane creates a new lane in the tab.
type MsgTabCreatePaneDown ¶
type MsgTabCreatePaneDown struct {
Title string `json:"title,omitempty"` // pre-generated unique alias
}
MsgTabCreatePaneDown creates a new pane group in the active lane.
type MsgTabCreatePaneGroupInLane ¶
type MsgTabCreatePaneGroupInLane struct {
LaneID string `json:"lane_id"`
Title string `json:"title,omitempty"`
GroupID string `json:"group_id,omitempty"`
WorkingDir string `json:"working_dir,omitempty"`
PaneID string `json:"pane_id,omitempty"`
PaneType string `json:"pane_type,omitempty"`
// Meta is metadata the pane is BORN with (design 028). It exists because
// the alternative — create the pane, then publish MsgPaneSetMeta at it —
// races the pane actor's own subscription: the id is known, but the inbox
// may not be listening yet, and a lost fire-and-forget meta write shows up
// much later as a board pane that has forgotten which board it renders.
Meta map[string]string `json:"meta,omitempty"`
}
MsgTabCreatePaneGroupInLane creates a new pane group in a specific lane. GroupID / WorkingDir semantics are those of MsgLaneCreatePaneGroup, which this message forwards to (worktree lifecycle, design 008).
PaneID, when set, pre-assigns the initial pane's ID (normally minted by the tab) so the sender can address the pane it asked for — the replay pane (design 006 v2) publishes recorded output to that ID at creation time. PaneType, when set, marks the initial pane as a special variant: "replay" panes never start a shell/PTY (read-only by construction).
type MsgTabCreateStackedPane ¶
type MsgTabCreateStackedPane struct {
Title string `json:"title,omitempty"` // pre-generated unique alias
}
MsgTabCreateStackedPane creates a new stacked pane in the active group.
type MsgTabCreateStackedPaneInLane ¶
type MsgTabCreateStackedPaneInLane struct {
LaneID string `json:"lane_id"`
PaneGroupID string `json:"pane_group_id"`
Title string `json:"title,omitempty"`
}
MsgTabCreateStackedPaneInLane creates a stacked pane in a specific lane's active group.
type MsgTabDeleteLane ¶
type MsgTabDeleteLane struct {
LaneID string `json:"lane_id"`
}
MsgTabDeleteLane deletes a specific lane by ID within a tab.
type MsgTabEqualizeAll ¶
type MsgTabEqualizeAll struct{}
MsgTabEqualizeAll equalizes lane widths and every lane's group heights.
type MsgTabEqualizeHorizontal ¶
type MsgTabEqualizeHorizontal struct{}
MsgTabEqualizeHorizontal sets all lanes to equal width.
type MsgTabEqualizePanes ¶
type MsgTabEqualizePanes struct{}
MsgTabEqualizePanes resets all lane flex weights to equal.
type MsgTabEqualizeVertical ¶
type MsgTabEqualizeVertical struct{}
MsgTabEqualizeVertical resets all group rowFlex in the active lane to equal.
type MsgTabFocus ¶
type MsgTabFocus struct {
Direction Direction `json:"direction"`
}
MsgTabFocus moves focus in the specified direction within the tab. Replaces MsgTabFocusNextPane, MsgTabFocusPrevPane, MsgTabFocusPaneLeft/Right/Up/Down.
type MsgTabFocusPaneByID ¶
type MsgTabFocusPaneByID struct {
ID string `json:"id"`
}
MsgTabFocusPaneByID focuses a pane by UUID within the tab.
type MsgTabPipelineDisable ¶
type MsgTabPipelineDisable struct{}
MsgTabPipelineDisable disables pipeline mode for a tab.
type MsgTabPipelineEnable ¶
type MsgTabPipelineEnable struct{}
MsgTabPipelineEnable enables pipeline mode for a tab.
type MsgTabResizePane ¶
type MsgTabResizePane struct {
Delta int `json:"delta"`
}
MsgTabResizePane adjusts the width of the active lane within the tab.
type MsgTabResizePaneHeight ¶
type MsgTabResizePaneHeight struct {
Delta int `json:"delta"`
}
MsgTabResizePaneHeight adjusts the height of the active pane group within the active lane.
type MsgTabResizePaneWidth ¶
type MsgTabResizePaneWidth struct {
Delta int `json:"delta"`
}
MsgTabResizePaneWidth adjusts the width flex of the active lane.
type MsgTabSetActive ¶
type MsgTabSetActive struct{}
MsgTabSetActive notifies a tab that it became the active tab.
type MsgTabSetInactive ¶
type MsgTabSetInactive struct{}
MsgTabSetInactive notifies a tab that it became inactive.
type MsgTabSetPaneHidden ¶ added in v0.2.6
MsgTabSetPaneHidden takes one pane in this tab off screen, or puts it back (design 027 §5.1). Routed tab → lane → group by pane id, the same traversal MsgTabFocusPaneByID uses, because the GROUP is what has to act: it owns the stack's active index, and hiding the focused pane has to move focus off it first or focus is stranded in a pane nothing draws.
type MsgTabSnapshotReply ¶
type MsgTabSnapshotReply struct {
Snapshot domain.TabSnapshot `json:"snapshot"`
}
MsgTabSnapshotReply carries the tab snapshot reply.
type MsgTabStackedPane ¶
type MsgTabStackedPane struct {
Direction Direction `json:"direction"`
}
MsgTabStackedPane cycles the stack in the specified direction in the active group. Replaces MsgTabStackedPaneNext and MsgTabStackedPanePrev.
type MsgTabStackedPaneMove ¶
type MsgTabStackedPaneMove struct {
Direction Direction `json:"direction"`
}
MsgTabStackedPaneMove reorders the active pane within the active group's stack.
type MsgTabStackedPaneSelect ¶
type MsgTabStackedPaneSelect struct {
Index int `json:"index"`
}
MsgTabStackedPaneSelect activates the stacked pane at the given 0-based index in the active group.
type MsgTabSubmitInput ¶
type MsgTabSubmitInput struct {
PaneID string `json:"pane_id"`
Text string `json:"text"`
Mode string `json:"mode"`
}
MsgTabSubmitInput forwards user input to a specific pane within the tab.
type MsgTabSwapPane ¶
type MsgTabSwapPane struct{}
MsgTabSwapPane swaps the active lane with the next one.
type MsgTabTerminated ¶
type MsgTabTerminated struct {
TabID string `json:"tab_id"`
}
MsgTabTerminated is published when a TabActor stops.
type MsgTogglePipelineMode ¶
type MsgTogglePipelineMode struct{}
MsgTogglePipelineMode toggles pipeline mode for the active tab.
type MsgToolCall ¶
type MsgToolCall = sharedmsg.MsgToolCall
type MsgToolResult ¶
type MsgToolResult = sharedmsg.MsgToolResult
type MsgUpstreamCommand ¶
type MsgUpstreamCommand struct {
CommandID string `json:"command_id"`
CommandType string `json:"command_type"` // "submit_input" | "exec_shell" | "exec_prompt"
Payload string `json:"payload"`
SenderID string `json:"sender_id"`
SenderName string `json:"sender_name"`
// TargetPaneID names the specific source pane this command should run on.
// Used by multi-pane (tab/lane/pane_group) control shares so a subscriber can
// drive a chosen pane. Empty for single-pane shares (routes to that pane).
TargetPaneID string `json:"target_pane_id,omitempty"`
}
MsgUpstreamCommand carries a command received from a remote session.
type MsgUpstreamCommandAck ¶
type MsgUpstreamCommandAck struct {
CommandID string `json:"command_id"`
Success bool `json:"success"`
Error string `json:"error,omitempty"`
}
MsgUpstreamCommandAck acknowledges a remote command.
type MsgUpstreamConnectionClosed ¶
type MsgUpstreamConnectionClosed struct {
Reason string `json:"reason,omitempty"`
}
MsgUpstreamConnectionClosed signals that the remote NATS connection was permanently closed (all reconnect attempts exhausted, or auth error).
type MsgUpstreamReconnected ¶
type MsgUpstreamReconnected struct{}
MsgUpstreamReconnected signals that a remote NATS connection was restored. Published by nats.go reconnect handlers (in goroutines) to the actor's own mailbox so that re-registration and re-subscription happen on the actor thread.
type MsgUpstreamSendCommand ¶
type MsgUpstreamSendCommand struct {
CommandType string `json:"command_type"`
Payload string `json:"payload"`
// TargetPaneID names the specific source pane to run the command on (for
// multi-pane mirror tabs). Empty for single-pane control shares.
TargetPaneID string `json:"target_pane_id,omitempty"`
}
MsgUpstreamSendCommand sends a command to a remote share (control mode).
type MsgUpstreamSharesList ¶
type MsgUpstreamSharesList struct {
}
MsgUpstreamSharesList is the reply listing available shares on the upstream.
type MsgUpstreamSubscribe ¶
type MsgUpstreamSubscribe struct {
}
MsgUpstreamSubscribe subscribes to a remote share's output.
type MsgUpstreamUnsubscribe ¶
type MsgUpstreamUnsubscribe struct {
}
MsgUpstreamUnsubscribe stops subscribing to a remote share.
type MsgUsageBudgetSet ¶
type MsgUsageBudgetSet = sharedmsg.MsgUsageBudgetSet
type MsgUsageCheck ¶
type MsgUsageCheck = sharedmsg.MsgUsageCheck
type MsgUsageCheckReply ¶
type MsgUsageCheckReply = sharedmsg.MsgUsageCheckReply
type MsgUsageRecord ¶
type MsgUsageRecord = sharedmsg.MsgUsageRecord
type MsgUsageSnapshotReply ¶
type MsgUsageSnapshotReply = sharedmsg.MsgUsageSnapshotReply
type MsgUsageSnapshotRequest ¶
type MsgUsageSnapshotRequest = sharedmsg.MsgUsageSnapshotRequest
type MsgWebActivate ¶
type MsgWebActivate struct {
PaneID string `json:"pane_id"`
// Profile and URL carry the pane's web binding so the desktop app can create
// and navigate the embedded browser directly from this push — without waiting
// for a snapshot to carry web_profile/web_url (which is timing-fragile: the
// layout-only snapshot that follows a web-enable can lag and arrive stale,
// leaving the app with no URL → blank browser).
Profile string `json:"profile,omitempty"`
URL string `json:"url,omitempty"`
}
MsgWebActivate tells the desktop app to switch a pane's display to web mode now (published when `##mode new web` enables/re-binds web on the pane). It is a deterministic signal that doesn't depend on the app noticing the snapshot's web_activate_seq bump — which is timing-fragile, so the pane only flipped to web after an unrelated click forced a fresh snapshot. Relayed by the web server to the app as a "web_activate" message.
type MsgWebDeactivate ¶
type MsgWebDeactivate struct {
PaneID string `json:"pane_id"`
}
MsgWebDeactivate tells the desktop app to switch a pane's display OFF web mode now (published when `##mode delete web` disables web on the pane). It mirrors MsgWebActivate: a deterministic, push-driven signal so the app drops the pane back to shell display immediately instead of relying on a snapshot's cleared web binding (which is timing-fragile). Relayed by the web server to the app as a "web_deactivate" message.
type MsgWebPromptDispatched ¶
MsgWebPromptDispatched announces that a prompt was sent to a web pane's AI assistant from outside the in-pane "Ask Rysh" chat box (e.g. via the `##mode web ai <prompt>` system command typed in shell mode). The web server relays it to the desktop app so the prompt renders as a human bubble in the Ask Rysh panel — exactly like a prompt typed into the chat box. Published on the pane's `web.prompt` subject; the actual AI execution goes through the normal prompt-submission path (MsgPaneSubmitInput).
type MsgWorkspaceSnapshotReply ¶
type MsgWorkspaceSnapshotReply struct {
Snapshot domain.WorkspaceSnapshot `json:"snapshot"`
}
MsgWorkspaceSnapshotReply carries the workspace snapshot reply.
type NATSEnvelope ¶
type NATSEnvelope = sharedmsg.NATSEnvelope
type NATSPublisher ¶
type NATSPublisher = sharedmsg.NATSPublisher
type PendingPair ¶
type PendingPair struct {
Code string `json:"code"`
SenderID string `json:"sender_id"`
SenderName string `json:"sender_name"`
Channel string `json:"channel"`
FirstMsg string `json:"first_msg,omitempty"`
CreatedAt int64 `json:"created_at"`
ExpiresAt int64 `json:"expires_at"`
}
PendingPair is the wire form of one pending pairing request. It mirrors channels.PendingReq field-for-field (with Unix-second times) so the msg package does not import internal/channels.
type RequestEnvelope ¶
type RequestEnvelope = sharedmsg.RequestEnvelope
type ShareRestrictions ¶
type ShareRestrictions struct {
// ws.{ws}.share.{shareID}.fs request/reply subject). It is ALWAYS true for an
// active share — file browsing is always available — but kept as an explicit
// flag for clarity and forward-compatibility. By default browsing is confined
// to the target pane's working-directory subtree.
AllowFileBrowse bool `json:"allow_file_browse"`
// request paths and browse outside the resolved root subtree. Defaults false:
// absolute paths are rejected and browsing is confined to the root subtree
// ("denied" on any escape). Opt-in via "##share pane ... --allow-absolute".
AllowAbsolute bool `json:"allow_absolute,omitempty"`
}
ShareRestrictions holds per-pane access restrictions for remote users. Stored in PaneActor state, persisted to KV, propagated to UpstreamShareActor and remote subscribers.
type ToolCallInfo ¶
type ToolCallInfo = sharedmsg.ToolCallInfo
type UsageCeiling ¶
type UsageCeiling = sharedmsg.UsageCeiling
type VTLineDelta ¶
VTLineDelta is one changed VT row in a delta frame: Y is the row index, S is the new (ANSI-styled) row content.
type WhatsAppMsgDetail ¶
type WhatsAppMsgDetail struct {
ID string `json:"id"`
MessageID string `json:"message_id"`
From string `json:"from"`
Name string `json:"name"`
Text string `json:"text"`
Time string `json:"time"`
}
WhatsAppMsgDetail is the full content of a single received WhatsApp message.
type WhatsAppMsgSummary ¶
type WhatsAppMsgSummary struct {
ID string `json:"id"`
MessageID string `json:"message_id"`
From string `json:"from"`
Name string `json:"name"`
Snippet string `json:"snippet"`
Time string `json:"time"`
}
WhatsAppMsgSummary is a brief overview of a received WhatsApp message for the list pane. ID is the short handle ("wa-3") used by whatsapp_read.
Source Files
¶
- board_id.go
- codec.go
- email_messages.go
- forged_api.go
- messages.go
- messages_agent.go
- messages_ansa.go
- messages_board.go
- messages_fleet.go
- messages_humanoid.go
- messages_lane.go
- messages_llm_picker.go
- messages_pane.go
- messages_share.go
- messages_snapshot.go
- messages_tab.go
- messages_workspace.go
- msglog.go
- proxy_audit_aliases.go
- publisher.go
- shared_aliases.go
- topics.go
- usage_aliases.go
- whatsapp_messages.go