Implement PTY-native session terminal control

This commit is contained in:
ms2k 2026-08-02 17:36:40 +09:00
commit 8cef037fa3
3 changed files with 1488 additions and 382 deletions

View file

@ -230,6 +230,7 @@ pub enum ControlRequest {
Register(SessionRegistrationRequest),
Execute(NonInteractiveSessionRequest),
ExecuteInteractive(super::InteractiveSessionRequest),
ExecuteInteractiveV2(super::InteractiveSessionRequestV2),
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]

View file

@ -4,25 +4,28 @@ use super::{
DefaultAction, DerivedNetworkPolicy, DeveloperDecision, DeveloperDecisionKind, Domain,
DomainStore, DomainStoreMetadata, EnvironmentReference, EscalationOutcome, Generation,
GenerationIdentity, GitRoutingOwnership, GuestProcessIdentity, HelperOwnership,
HostProcessIdentity, HostProcessOwnershipSlot, InteractiveSessionBatch,
InteractiveSessionEvent, InteractiveSessionMessage, InteractiveSessionRequest, Mailbox,
MailboxCancellation, MailboxRequest, MailboxResult, MailboxResultAck, MailboxResultChunk,
MountIdentity, NamespaceIdentity, NetworkCanaryObservation, NetworkObservation,
NetworkOwnership, NetworkReadinessAttestation, NetworkReadinessEvidence,
NetworkReadinessIdentity, NonInteractiveOutput, NonInteractiveSessionMessage,
NonInteractiveSessionRequest, Participant, ParticipantOwnership, ParticipantState,
PersistedHostProcessOwnership, PidfsProcessAuthorityV1, PidfsProcessIdentityV1, PolicyAction,
PolicyDelivery, PrefixRule, PrepareOperation, PrepareStageState, PreparedArtifact,
PreparedLowerOwnership, ProcessOwnershipCommitAck, ProcessOwnershipMessageVersion,
ProtocolCredential, ProtocolCredentialRole, ProtocolPublicationIdentity, PtyIdentity,
PublicationOwnership, ResolvedAutoApprovalRule, ResolvedVolume, Resolver, ResultStream,
RunscProcessOwnership, SandboxCredentialBundle, SandboxOwnership, Session, SessionBinding,
SessionClose, SessionExit, SessionExitOutcome, SessionRegistrationRequest,
SessionRegistrationResponse, SessionRequestCapability, SessionTerminal, SessionTerminalEvent,
SessionTerminalMessage, SessionTerminalState, SignedProtocolRecord, StagedProcessOwnership,
StateAnchorOwnership, StateAnchorReleaseEvidence, StorageCatalog, StorageCatalogMetadata,
StoreMetadata, TerminalInput, TerminalOutput, TerminalPrompt, TerminalResize, TerminalSignal,
TerminalSignalKind, TlsCredential, TlsRole, TrustManifest, TrustedHostConfigurationV1,
HostProcessIdentity, HostProcessOwnershipSlot, InteractiveProtocolVersion,
InteractiveSessionBatch, InteractiveSessionBatchV2, InteractiveSessionEvent,
InteractiveSessionEventV2, InteractiveSessionMessage, InteractiveSessionRequest,
InteractiveSessionRequestV2, Mailbox, MailboxCancellation, MailboxRequest, MailboxResult,
MailboxResultAck, MailboxResultChunk, MountIdentity, NamespaceIdentity,
NetworkCanaryObservation, NetworkObservation, NetworkOwnership, NetworkReadinessAttestation,
NetworkReadinessEvidence, NetworkReadinessIdentity, NonInteractiveOutput,
NonInteractiveSessionMessage, NonInteractiveSessionRequest, Participant, ParticipantOwnership,
ParticipantState, PersistedHostProcessOwnership, PidfsProcessAuthorityV1,
PidfsProcessIdentityV1, PolicyAction, PolicyDelivery, PrefixRule, PrepareOperation,
PrepareStageState, PreparedArtifact, PreparedLowerOwnership, ProcessOwnershipCommitAck,
ProcessOwnershipMessageVersion, ProtocolCredential, ProtocolCredentialRole,
ProtocolPublicationIdentity, PtyIdentity, PublicationOwnership, ResolvedAutoApprovalRule,
ResolvedVolume, Resolver, ResultStream, RunscProcessOwnership, SandboxCredentialBundle,
SandboxOwnership, Session, SessionBinding, SessionClose, SessionExit, SessionExitOutcome,
SessionRegistrationRequest, SessionRegistrationResponse, SessionRequestCapability,
SessionTerminal, SessionTerminalEvent, SessionTerminalEventV2, SessionTerminalMessage,
SessionTerminalState, SignedProtocolRecord, StagedProcessOwnership, StateAnchorOwnership,
StateAnchorReleaseEvidence, StorageCatalog, StorageCatalogMetadata, StoreMetadata,
TerminalBreak, TerminalInput, TerminalModesV2, TerminalOutput, TerminalPrompt, TerminalResize,
TerminalSignal, TerminalSignalKind, TlsCredential, TlsRole, TrustManifest,
TrustedHostConfigurationV1,
};
use crate::protocol::{BootstrapWaitOutcome, BootstrapWaitRequest};
@ -67,16 +70,23 @@ schema_types!(
"ProcessOwnershipCommitAck" => ProcessOwnershipCommitAck,
"GuestProcessIdentity" => GuestProcessIdentity,
"SessionTerminalEvent" => SessionTerminalEvent,
"SessionTerminalEventV2" => SessionTerminalEventV2,
"TerminalInput" => TerminalInput,
"TerminalResize" => TerminalResize,
"TerminalModesV2" => TerminalModesV2,
"TerminalBreak" => TerminalBreak,
"TerminalSignal" => TerminalSignal,
"TerminalSignalKind" => TerminalSignalKind,
"SessionClose" => SessionClose,
"SessionTerminalMessage" => SessionTerminalMessage,
"InteractiveSessionRequest" => InteractiveSessionRequest,
"InteractiveProtocolVersion" => InteractiveProtocolVersion,
"InteractiveSessionRequestV2" => InteractiveSessionRequestV2,
"InteractiveSessionEvent" => InteractiveSessionEvent,
"InteractiveSessionEventV2" => InteractiveSessionEventV2,
"InteractiveSessionMessage" => InteractiveSessionMessage,
"InteractiveSessionBatch" => InteractiveSessionBatch,
"InteractiveSessionBatchV2" => InteractiveSessionBatchV2,
"TerminalPrompt" => TerminalPrompt,
"NonInteractiveSessionRequest" => NonInteractiveSessionRequest,
"NonInteractiveOutput" => NonInteractiveOutput,

View file

@ -2,6 +2,11 @@ use crate::identity::{RequestDigest, RequestId};
use super::{Deserialize, NonZeroU16, ProtocolVersion, Serialize, SessionId};
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub enum InteractiveProtocolVersion {
V2,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct TerminalInput {
pub session_id: SessionId,
@ -17,6 +22,34 @@ pub struct TerminalResize {
pub pixel_height: u16,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct TerminalModesV2 {
pub input_modes: u32,
pub output_modes: u32,
pub control_modes: u32,
pub local_modes: u32,
pub line_discipline: u8,
pub input_speed: u32,
pub output_speed: u32,
pub interrupt: u8,
pub quit: u8,
pub erase: u8,
pub kill: u8,
pub eof: u8,
pub time: u8,
pub minimum: u8,
pub switch: u8,
pub start: u8,
pub stop: u8,
pub suspend: u8,
pub end_of_line: u8,
pub reprint: u8,
pub discard: u8,
pub word_erase: u8,
pub literal_next: u8,
pub end_of_line_2: u8,
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub enum TerminalSignalKind {
Interrupt,
@ -35,6 +68,11 @@ pub struct SessionClose {
pub session_id: SessionId,
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct TerminalBreak {
pub session_id: SessionId,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub enum SessionTerminalEvent {
Input(TerminalInput),
@ -43,6 +81,14 @@ pub enum SessionTerminalEvent {
Close(SessionClose),
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub enum SessionTerminalEventV2 {
Input(TerminalInput),
Resize(TerminalResize),
Break(TerminalBreak),
Close(SessionClose),
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct TerminalOutput {
pub session_id: SessionId,
@ -147,6 +193,15 @@ pub struct InteractiveSessionRequest {
pub initial_size: TerminalResize,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct InteractiveSessionRequestV2 {
pub protocol_version: InteractiveProtocolVersion,
pub session_id: SessionId,
pub argv: Vec<Vec<u8>>,
pub initial_size: TerminalResize,
pub initial_modes: TerminalModesV2,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct TerminalPrompt {
pub session_id: SessionId,
@ -169,6 +224,18 @@ pub enum InteractiveSessionEvent {
},
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub enum InteractiveSessionEventV2 {
Terminal(SessionTerminalEventV2),
PromptDecision {
session_id: SessionId,
signed_decision: Vec<u8>,
},
Poll {
session_id: SessionId,
},
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub enum InteractiveSessionMessage {
Terminal(SessionTerminalMessage),
@ -181,6 +248,12 @@ pub struct InteractiveSessionBatch {
pub messages: Vec<InteractiveSessionMessage>,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct InteractiveSessionBatchV2 {
pub session_id: SessionId,
pub messages: Vec<InteractiveSessionMessage>,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct NonInteractiveSessionRequest {
pub protocol_version: super::ProtocolVersion,