Sign in

    tun-poc-proto

    Download zip
    Version
    0.3.3
    License
    Apache-2.0
    Last updated
    2 months ago
    Downloads
    200

    #tun-poc-proto

    Shared wire protocol types for tun-poc. Imported by the browser client, the relay, and the server agent so all three stay in sync.

    Covers:

    • Relay ↔ client and relay ↔ server messages (task lifecycle, terminal I/O, render viewports, replay, reconnection).
    • REST API payloads (auth, user status, task list, machines, groups, and administration).
    • Codex JSON-RPC envelopes and filesystem event types.
    • Task UUIDs, machine/group/user payloads, and typed JSON codecs for each message variant.

    See docs/protocol.md for the message flow.

    AddMemberRequest

    pub(all) struct AddMemberRequest {
    login : String
    }

    Capability

    pub(all) enum Capability {
    RenderFrameVt
    RenderFrameState
    ViewportResize
    ServerScrollback
    ClientAttachAck
    MoonIdeHover
    FilesystemWatch
    Unknown(String)
    } derive(Eq,
    Debug
    )

    Capability::from_wire

    fn Capability::from_wire(value : String) -> Capability

    Capability::to_wire

    fn Capability::to_wire(self : Capability) -> String

    CapabilitySet

    pub struct CapabilitySet(Array[Capability]) derive(Eq,
    Debug
    )

    CapabilitySet::empty

    CapabilitySet::from_wire

    fn CapabilitySet::from_wire(values : Array[String]) -> CapabilitySet

    CapabilitySet::length

    fn CapabilitySet::length(self : CapabilitySet) -> Int

    CapabilitySet::new

    CapabilitySet::supports

    fn CapabilitySet::supports(self : CapabilitySet, capability : Capability) -> Bool

    CapabilitySet::supports_client_attach_ack

    fn CapabilitySet::supports_client_attach_ack(self : CapabilitySet) -> Bool

    CapabilitySet::supports_filesystem_watch

    fn CapabilitySet::supports_filesystem_watch(self : CapabilitySet) -> Bool

    CapabilitySet::supports_moon_ide_hover

    fn CapabilitySet::supports_moon_ide_hover(self : CapabilitySet) -> Bool

    CapabilitySet::supports_render_frame_state

    fn CapabilitySet::supports_render_frame_state(self : CapabilitySet) -> Bool

    CapabilitySet::supports_render_frame_vt

    fn CapabilitySet::supports_render_frame_vt(self : CapabilitySet) -> Bool

    CapabilitySet::supports_server_scrollback

    fn CapabilitySet::supports_server_scrollback(self : CapabilitySet) -> Bool

    CapabilitySet::supports_viewport_resize

    fn CapabilitySet::supports_viewport_resize(self : CapabilitySet) -> Bool

    CapabilitySet::to_log_string

    fn CapabilitySet::to_log_string(self : CapabilitySet) -> String

    CapabilitySet::to_wire

    fn CapabilitySet::to_wire(self : CapabilitySet) -> Array[String]

    CodexActiveFlag

    pub(all) enum CodexActiveFlag {
    WaitingOnApproval
    WaitingOnUserInput
    } derive(Eq,
    Debug
    )

    CodexActivityStatus

    pub(all) enum CodexActivityStatus {
    NotLoaded
    Idle
    Active(Array[CodexActiveFlag])
    SystemError
    } derive(Eq,
    Debug
    )

    CodexApproval

    pub(all) enum CodexApproval {
    Command(command~ : String)
    FileChange(reason~ : String)
    }

    CodexApprovalDecision

    pub(all) enum CodexApprovalDecision {
    Accept
    Decline
    }

    CodexClientInfo

    pub(all) struct CodexClientInfo {
    name : String
    title : String
    version : String
    }

    CodexIncoming

    pub(all) enum CodexIncoming {
    ThreadResult(thread~ : CodexThreadResult)
    ThreadListResult(threads~ : Array[CodexThreadResult])
    ThreadReadResult(thread~ : CodexThreadResult, turns~ : Array[CodexReadTurn])
    OtherResponse(id~ : Json)
    TurnStarted(turn_id~ : CodexTurnId)
    TurnCompleted(turn_id~ : CodexTurnId, status~ : CodexStatus)
    ItemStarted(turn_id~ : CodexTurnId, item_id~ : CodexItemId, kind~ : CodexItemKind, text~ : String, command~ : String)
    ItemCompleted(turn_id~ : CodexTurnId, item_id~ : CodexItemId, status~ : CodexStatus)
    Delta(turn_id~ : CodexTurnId, item_id~ : CodexItemId, delta~ : String, kind~ : CodexItemKind)
    ThreadStatusChanged(thread_id~ : CodexThreadId, activity~ : CodexActivityStatus)
    Approval(id~ : CodexRequestId, thread_id~ : CodexThreadId, turn_id~ : CodexTurnId, item_id~ : CodexItemId, approval~ : CodexApproval)
    }

    CodexItemId

    pub(all) struct CodexItemId(String) derive(Eq,
    Debug
    )

    CodexItemKind

    pub(all) enum CodexItemKind {
    AgentMessage
    UserMessage
    CommandExecution
    FileChange
    Reasoning
    } derive(Eq,
    Debug
    )

    CodexOutgoing

    pub(all) enum CodexOutgoing {
    Initialize(id~ : Int, client_info~ : CodexClientInfo)
    ThreadStart(id~ : Int, cwd~ : String)
    ThreadList(id~ : Int, cwd~ : String)
    ThreadRead(id~ : Int, thread_id~ : CodexThreadId, include_turns~ : Bool)
    ThreadResume(id~ : Int, thread_id~ : CodexThreadId)
    TurnStart(id~ : Int, thread_id~ : CodexThreadId, input~ : String)
    TurnInterrupt(id~ : Int, thread_id~ : CodexThreadId, turn_id~ : CodexTurnId)
    Initialized
    Approval(id~ : CodexRequestId, decision~ : CodexApprovalDecision)
    }

    CodexReadItem

    pub(all) struct CodexReadItem {
    id : CodexItemId
    kind : CodexItemKind
    text : String
    command : String
    output : String
    }

    CodexReadTurn

    pub(all) struct CodexReadTurn {
    id : CodexTurnId
    items : Array[CodexReadItem]
    status : CodexStatus
    }

    CodexRequestId

    pub(all) struct CodexRequestId(Json)

    CodexStatus

    pub(all) enum CodexStatus {
    InProgress
    Completed
    Failed
    } derive(Eq,
    Debug
    )

    CodexThreadResult

    pub(all) struct CodexThreadResult {
    id : CodexThreadId
    preview : String
    status : CodexThreadStatus
    activity : CodexActivityStatus
    } derive(Eq,
    Debug
    )

    CodexThreadStatus

    pub(all) enum CodexThreadStatus {
    Open
    Archived
    Closed
    } derive(Eq,
    Debug
    )

    CodexTurnId

    pub(all) struct CodexTurnId(String) derive(Eq,
    Debug
    )

    CreateGroupRequest

    pub(all) struct CreateGroupRequest {
    name : String
    }

    CreateMachineRequest

    pub(all) struct CreateMachineRequest {
    name : String
    }

    CreateMachineResponse

    pub(all) struct CreateMachineResponse {
    token : String
    machine_id : Int
    }

    CreatedGroupResponse

    pub(all) struct CreatedGroupResponse {
    id : Int
    }

    Cursor

    pub(all) struct Cursor {
    x : Int
    y : Int
    shape : CursorShape
    blink : Bool
    color : String?
    } derive(Eq,
    Debug
    )

    The visible cursor. Coordinates are zero-based viewport cells; a cursor on a wide glyph's trailing cell is already snapped to the glyph head. color is set only when the child application overrides the cursor color, so the client theme keeps the default. The glyph under a block cursor, its cell span, and its inverted color are not on the wire: the client derives them from the run grid it already holds.
    impl ToJson for Cursor

    CursorShape

    pub(all) enum CursorShape {
    Block
    Bar
    Underline
    } derive(Eq,
    Debug
    )

    DeviceApproveRequest

    pub(all) struct DeviceApproveRequest {
    code : String
    }

    Request body of POST /device/approve. Sent by the SPA when the user clicks Approve on the pairing page.

    DeviceAuthorizationRequest

    pub(all) struct DeviceAuthorizationRequest {
    hostname : String
    }

    DeviceAuthorizationResponse

    pub(all) struct DeviceAuthorizationResponse {
    device_code : String
    user_code : String
    verification_uri : String
    verification_uri_complete : String?
    expires_in : Int
    interval : Int
    }

    DeviceDenyRequest

    pub(all) struct DeviceDenyRequest {
    code : String
    }

    Request body of POST /device/deny. Sent by the SPA when the user clicks Deny on the pairing page.

    DevicePendingResponse

    pub(all) struct DevicePendingResponse {
    hostname : String
    }

    Response body of GET /device/pending?code=<user_code>. Returned to the SPA approval page so it can render the hostname the agent reported.

    DeviceTokenError

    pub(all) enum DeviceTokenError {
    AuthorizationPending
    SlowDown
    ExpiredToken
    AccessDenied
    InvalidRequest
    UnsupportedGrantType
    Unknown(String)
    }

    RFC 8628 §3.5 token-endpoint error codes, plus Unknown(String) as a forward-compatibility hatch for codes added by a future relay against an older server. Wire format is a bare JSON string (see DeviceTokenResponse::Error).

    DeviceTokenRequest

    pub(all) struct DeviceTokenRequest {
    grant_type : String
    device_code : String
    }

    DeviceTokenResponse

    pub(all) enum DeviceTokenResponse {
    Success(access_token~ : String, token_type~ : String)
    Error(error~ : DeviceTokenError)
    }

    RFC 8628 §3.5 token-endpoint response. Discriminated on the wire by which field is present: access_token → Success, error → Error.

    ErrorCode

    pub(all) enum ErrorCode {
    TaskNotFound
    TaskOffline
    InternalError
    ProtoVersionTooOld(min_version~ : Int)
    } derive(Eq,
    Debug
    )

    ErrorCode::to_wire

    fn ErrorCode::to_wire(self : ErrorCode) -> String

    FileStat

    pub(all) struct FileStat {
    file_type : Int
    size : Int64
    mtime : Int64
    ctime : Int64
    } derive(
    Debug
    )

    impl ToJson for FileStat

    FileStat::to_log_string

    fn FileStat::to_log_string(self : FileStat) -> String

    Frame

    pub(all) struct Frame {
    full : Bool
    styles : Array[RunStyle]
    lines : Array[Line]
    cursor : Cursor?
    } derive(Eq,
    Debug
    )

    Structured render payload for render_frame_state clients. The server diffs terminal state against what each client already holds, so lines carries only the rows to repaint unless full is set. Runs keep explicit col and width so the client can map text back to grid cells for selection without replaying a terminal emulator.

    FsMessage

    pub(all) enum FsMessage {
    WatchFile(req_id~ : String, client_id~ : String, path~ : String)
    UnwatchFile(req_id~ : String, client_id~ : String)
    WatchFileReady(req_id~ : String, client_id~ : String, path~ : String, resolved_path~ : String)
    FileChanged(req_id~ : String, client_id~ : String, path~ : String, resolved_path~ : String)
    Stat(req_id~ : String, client_id~ : String, path~ : String)
    StatResult(req_id~ : String, client_id~ : String, stat~ : FileStat)
    Readdir(req_id~ : String, client_id~ : String, path~ : String)
    ReaddirResult(req_id~ : String, client_id~ : String, entries~ : Array[(String, Int)])
    ReadFile(req_id~ : String, client_id~ : String, path~ : String)
    ReadFileResult(req_id~ : String, client_id~ : String, data~ : String)
    WriteFile(req_id~ : String, client_id~ : String, path~ : String, data~ : String, create~ : Bool, overwrite~ : Bool)
    Mkdir(req_id~ : String, client_id~ : String, path~ : String)
    FsDelete(req_id~ : String, client_id~ : String, path~ : String, recursive~ : Bool)
    FsRename(req_id~ : String, client_id~ : String, from~ : String, to~ : String, overwrite~ : Bool)
    FsOk(req_id~ : String, client_id~ : String)
    FsError(req_id~ : String, client_id~ : String, code~ : String, message~ : String)
    } derive(
    Debug
    )

    impl ToJson for FsMessage

    FsMessage::client_id

    fn FsMessage::client_id(self : FsMessage) -> String

    FsMessage::to_log_string

    fn FsMessage::to_log_string(self : FsMessage) -> String

    GrantAccessRequest

    pub(all) struct GrantAccessRequest {
    group_id : Int
    }

    GroupInfo

    pub(all) struct GroupInfo {
    id : Int
    name : String
    owner_id : Int64
    }

    GroupMember

    pub(all) struct GroupMember {
    github_id : Int64
    login : String
    avatar_url : String
    }

    IdeErrorCode

    pub(all) enum IdeErrorCode {
    InvalidRequest
    MoonUnavailable
    MoonIdeFailed
    IdeTimeout
    } derive(Eq,
    Debug
    )

    Fixed error classifications for the Moon IDE hover channel.

    IdeErrorCode::from_wire

    fn IdeErrorCode::from_wire(value : String) -> IdeErrorCode?

    IdeErrorCode::to_wire

    fn IdeErrorCode::to_wire(self : IdeErrorCode) -> String

    IdeMessage

    pub(all) enum IdeMessage {
    Hover(req_id~ : String, client_id~ : String, path~ : String, line~ : Int, column~ : Int)
    CancelHover(req_id~ : String, client_id~ : String)
    HoverResult(req_id~ : String, client_id~ : String, path~ : String, range~ : String?, contents~ : Array[String])
    IdeError(req_id~ : String, client_id~ : String, path~ : String, code~ : IdeErrorCode, message~ : String)
    } derive(
    Debug
    )

    Moon IDE hover messages. Positions and compact ranges use one-based Unicode code-point coordinates, matching moon ide hover.

    IdeMessage::client_id

    fn IdeMessage::client_id(self : IdeMessage) -> String

    IdeMessage::to_log_string

    fn IdeMessage::to_log_string(self : IdeMessage) -> String

    Line

    pub(all) struct Line {
    y : Int
    runs : Array[Run]
    } derive(Eq,
    Debug
    )

    MachineAccessGroup

    pub(all) struct MachineAccessGroup {
    group_id : Int
    name : String
    }

    Message

    pub(all) enum Message {
    Sys(SysMessage)
    Fs(FsMessage)
    Ide(IdeMessage)
    Term(TermMessage)
    Codex(client_id~ : String, data~ : String)
    } derive(
    Debug
    )

    impl ToJson for Message

    Message::client_id

    fn Message::client_id(self : Message) -> String

    Message::to_log_string

    fn Message::to_log_string(self : Message) -> String

    RegisterRejectReason

    pub(all) enum RegisterRejectReason {
    UuidAlreadyClaimedThisSession
    InvalidUuid
    ProtoVersionTooOld(min_version~ : Int)
    } derive(Eq,
    Debug
    )

    RegisterRejectReason::to_wire

    fn RegisterRejectReason::to_wire(self : RegisterRejectReason) -> String

    Run

    pub(all) struct Run {
    col : Int
    width : Int
    text : String
    style : Int?
    } derive(Eq,
    Debug
    )

    One styled run of cells. An ASCII run holds one cell per character, so width equals the character count. A non-ASCII glyph always forms its own run whose width (1 or 2) is its grid-cell span; the client renders it as a fixed-width centered span so glyph advances cannot push later columns off the grid.
    impl ToJson for Run

    RunStyle

    pub(all) struct RunStyle {
    fg : String?
    bg : String?
    underline_color : String?
    flags : Int
    } derive(Eq,
    Debug
    )

    Colors are #rrggbb; None means the client's default foreground or background. The server resolves palette indices (including bold promotion) but never substitutes its own default colors, so client themes keep owning the defaults — including under inverse, which the client applies by swapping resolved colors with its theme defaults.
    impl ToJson for RunStyle
    fn RunStyle::blink(self : RunStyle) -> Bool

    RunStyle::bold

    fn RunStyle::bold(self : RunStyle) -> Bool

    RunStyle::conceal

    fn RunStyle::conceal(self : RunStyle) -> Bool

    RunStyle::faint

    fn RunStyle::faint(self : RunStyle) -> Bool

    RunStyle::inverse

    fn RunStyle::inverse(self : RunStyle) -> Bool

    RunStyle::is_default

    fn RunStyle::is_default(self : RunStyle) -> Bool

    Whether this is the default style a Run encodes as style : None.

    RunStyle::italic

    fn RunStyle::italic(self : RunStyle) -> Bool

    RunStyle::new

    fn RunStyle::new(fg? : String, bg? : String, underline_color? : String, bold? : Bool, faint? : Bool, italic? : Bool, strikethrough? : Bool, overline? : Bool, blink? : Bool, inverse? : Bool, conceal? : Bool, underline? : Underline) -> RunStyle

    RunStyle::overline

    fn RunStyle::overline(self : RunStyle) -> Bool

    RunStyle::strikethrough

    fn RunStyle::strikethrough(self : RunStyle) -> Bool

    RunStyle::underline

    fn RunStyle::underline(self : RunStyle) -> Underline

    SysMessage

    pub(all) enum SysMessage {
    Register(task_uuid~ :
    UUID
    , hostname~ : String, cwd~ : String, proto_version~ : Int, server_capabilities~ : CapabilitySet)
    Registered(task_uuid~ :
    UUID
    )
    RegisterRejected(reason~ : RegisterRejectReason)
    TaskExited(exit_code~ : Int)
    Title(title~ : String?)
    Connect(task_uuid~ :
    UUID
    , last_seen_id~ : Int64?, proto_version~ : Int, client_capabilities~ : CapabilitySet)
    Connected(server_proto_version~ : Int, server_capabilities~ : CapabilitySet)
    TaskOnline(server_proto_version~ : Int, server_capabilities~ : CapabilitySet)
    NewClient(client_id~ : String, last_seen_id~ : Int64?, client_proto_version~ : Int, client_capabilities~ : CapabilitySet)
    ClientDisconnected(client_id~ : String)
    Error(ErrorCode)
    AuthError(message~ : String)
    }

    impl Debug for SysMessage

    SysMessage::client_id

    fn SysMessage::client_id(self : SysMessage) -> String

    SysMessage::to_log_string

    fn SysMessage::to_log_string(self : SysMessage) -> String

    TaskEntry

    pub(all) struct TaskEntry {
    task_uuid :
    UUID

    machine_id : Int
    hostname : String
    cwd : String
    title : String?
    owner : String
    online : Bool
    last_seen_at : Int64
    } derive(Eq)

    Flat row for the GET /api/tasks listing. One row per running task instance (keyed by task_uuid), joined with its parent machine's display info. machine_id groups tasks that belong to the same long-lived machine; task_uuid is the identity used everywhere else on the wire.
    impl ToJson for TaskEntry

    TermMessage

    pub(all) enum TermMessage {
    ClientReplayCursor(client_id~ : String, last_seen_id~ : Int64?)
    Viewport(client_id~ : String, cols~ : Int, rows~ : Int, active~ : Bool)
    RenderFrame(client_id~ : String, seq~ : Int64, cols~ : Int, rows~ : Int, scroll_offset~ : Int64, scrollback_rows~ : Int64, title~ : String?, mouse~ : Bool?, data~ : String)
    RenderState(client_id~ : String, seq~ : Int64, cols~ : Int, rows~ : Int, scroll_offset~ : Int64, scrollback_rows~ : Int64, title~ : String?, mouse~ : Bool?, frame~ : Frame)
    InputText(client_id~ : String, text~ : String)
    InputKey(client_id~ : String, key~ : String, mods~ : Array[String], text~ : String?)
    InputPaste(client_id~ : String, text~ : String)
    InputMouse(client_id~ : String, x~ : Int, y~ : Int, button~ : String?, action~ : String, mods~ : Array[String])
    InputScroll(client_id~ : String, x~ : Int, y~ : Int, delta_rows~ : Int, mods~ : Array[String])
    ScrollToLive(client_id~ : String)
    Theme(client_id~ : String, background~ : String, foreground~ : String)
    Data(client_id~ : String, id~ : Int64, created~ : Int64?, replay~ : Bool?, data~ : String)
    Exited(client_id~ : String, id~ : Int64)
    } derive(
    Debug
    )

    TermMessage::client_id

    fn TermMessage::client_id(self : TermMessage) -> String

    TermMessage::to_log_string

    fn TermMessage::to_log_string(self : TermMessage) -> String

    TransferGroupRequest

    pub(all) struct TransferGroupRequest {
    new_owner_id : Int64
    }

    Underline

    pub(all) enum Underline {
    None
    Single
    Double
    Curly
    Dotted
    Dashed
    } derive(Eq,
    Debug
    )

    UserInfo

    pub(all) struct UserInfo {
    github_id : Int64
    login : String
    avatar_url : String
    status : UserStatus
    is_admin : Bool
    } derive(Eq)

    UserStatus

    pub(all) enum UserStatus {
    Pending
    Approved
    Rejected
    } derive(Eq,
    Debug
    )

    UserStatus::from_string

    fn UserStatus::from_string(s : String) -> UserStatus

    UserStatus::to_string

    fn UserStatus::to_string(self : UserStatus) -> String

    ProtoMinVersion

    let ProtoMinVersion : Int

    Lowest proto_version the relay accepts on Register/Connect. Bump to match ProtoVersion when dropping support for a prior version.

    ProtoVersion

    let ProtoVersion : Int

    Wire protocol version this build speaks. Bumped when peers need to reason about a new protocol capability or when a breaking Register/Connect/sys-channel handshake change lands. Optional version fields default to 0 so peers built before versioning was introduced decode as version 0 — fully backwards compatible.