blob: 474c432a28a9520d53b17638e534d88bc8b48773 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
use maka_agent_facts::shell_run::ShellObservation;
use maka_agent_facts::terminal::TerminalSize;
use maka_agent_facts::terminal::input::InputAction;
use std::sync::Arc;
use tokio::sync::oneshot;
use tokio_util::sync::CancellationToken;
/// Bytes accepted by the input transport, not a claim of application consumption.
/// Windows accepts into its owned overlapped pipe queue; this is not an I/O
/// completion fence. A later process exit can discard accepted but unread input.
#[derive(Clone, Debug)]
pub struct WriteReceipt {
pub accepted_bytes: usize,
pub resized: bool,
pub resize_changed: bool,
/// The worker's committed parser cut when transport acceptance settles.
pub record: Arc<ShellObservation>,
}
#[derive(Debug, thiserror::Error)]
#[error("{message} (accepted input prefix: {accepted_bytes:?}, resized: {resized:?})")]
pub struct ControlError {
pub kind: ControlErrorKind,
pub message: String,
/// None means the worker disappeared before it could report an exact prefix.
pub accepted_bytes: Option<usize>,
/// None means native resize may have happened before the worker disappeared.
pub resized: Option<bool>,
pub resize_changed: Option<bool>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ControlErrorKind {
Rejected,
Closed,
Unknown,
}
impl ControlError {
pub(super) fn new(message: impl ToString, accepted_bytes: usize) -> Self {
Self {
kind: ControlErrorKind::Closed,
message: message.to_string(),
accepted_bytes: Some(accepted_bytes),
resized: Some(false),
resize_changed: Some(false),
}
}
pub(super) fn unknown(message: &str) -> Self {
Self {
kind: ControlErrorKind::Unknown,
message: message.into(),
accepted_bytes: None,
resized: None,
resize_changed: None,
}
}
pub(super) fn rejected(message: impl ToString) -> Self {
Self {
kind: ControlErrorKind::Rejected,
..Self::new(message, 0)
}
}
pub(super) fn after_resize(mut self, resized: bool, changed: bool) -> Self {
self.resized = Some(resized);
self.resize_changed = Some(changed);
self
}
}
/// Owned complete native terminal payload; the caller supplies authorization before enqueue.
pub enum Input {
Actions(Vec<InputAction>),
Interactive(Vec<InputAction>),
Raw(String),
}
pub(super) struct Control {
pub input: Input,
pub size: Option<TerminalSize>,
pub cancellation: CancellationToken,
pub reply: oneshot::Sender<Result<WriteReceipt, ControlError>>,
}