chore: merge current develop into T-556

This commit is contained in:
2026-08-30 20:32:20 +09:00
5 changed files with 311 additions and 32 deletions
+84 -5
View File
@@ -107,6 +107,31 @@ pub enum WorkdirTransportErrorCode {
Internal,
}
impl WorkdirTransportErrorCode {
pub const fn as_str(self) -> &'static str {
match self {
Self::NotFound => "not_found",
Self::Conflict => "conflict",
Self::Unsupported => "unsupported",
Self::InvalidRequest => "invalid_request",
Self::UnknownCommand => "unknown_command",
Self::Unavailable => "unavailable",
Self::Internal => "internal",
}
}
/// Shared public HTTP classification for Runtime and Workspace Workdir operation boundaries.
pub const fn http_status(self) -> u16 {
match self {
Self::NotFound | Self::UnknownCommand => 404,
Self::Conflict => 409,
Self::Unsupported | Self::InvalidRequest => 400,
Self::Unavailable => 503,
Self::Internal => 500,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct WorkdirTransportError {
pub code: WorkdirTransportErrorCode,
@@ -126,6 +151,9 @@ impl WorkdirTransportError {
message: format!("Workdir capability {capability:?} is not available"),
};
}
WorkdirError::UnsupportedOperation(_) => {
(Code::Unsupported, "Workdir operation is not supported")
}
WorkdirError::UnknownCommand(_) => {
(Code::UnknownCommand, "Workdir command was not found")
}
@@ -161,7 +189,7 @@ impl WorkdirTransportError {
match self.code {
Code::NotFound => WorkdirError::NotFound("<remote>".into()),
Code::Conflict => WorkdirError::Conflict(self.message),
Code::Unsupported => WorkdirError::Unavailable(self.message),
Code::Unsupported => WorkdirError::UnsupportedOperation(self.message),
Code::UnknownCommand => WorkdirError::UnknownCommand("<remote>".to_string()),
Code::InvalidRequest => WorkdirError::InvalidArgument(self.message),
Code::Unavailable => WorkdirError::Unavailable(self.message),
@@ -517,13 +545,13 @@ mod client {
.json::<WorkdirTransportError>()
.await
.map(WorkdirTransportError::into_workdir_error)
.unwrap_or_else(|error| {
WorkdirError::Unavailable(format!("Runtime HTTP error: {error}"))
.unwrap_or_else(|_| {
WorkdirError::Transport("Runtime Workdir error response was invalid".to_string())
})
}
fn http_unavailable(error: reqwest::Error) -> WorkdirError {
WorkdirError::Unavailable(format!("Runtime Workdir HTTP request failed: {error}"))
fn http_unavailable(_error: reqwest::Error) -> WorkdirError {
WorkdirError::Transport("Runtime Workdir HTTP request failed".to_string())
}
pub use self::RemoteWorkdirSession as ClientSession;
@@ -536,6 +564,57 @@ pub use client::{ClientSession as RemoteWorkdirSession, WorkdirHttpAuthorization
mod tests {
use super::*;
#[test]
fn transport_error_round_trip_keeps_public_classification() {
for (code, expected_status, expected_error) in [
(
WorkdirTransportErrorCode::InvalidRequest,
400,
"invalid argument",
),
(WorkdirTransportErrorCode::NotFound, 404, "file not found"),
(
WorkdirTransportErrorCode::UnknownCommand,
404,
"unknown Workdir session command",
),
(
WorkdirTransportErrorCode::Conflict,
409,
"modified externally",
),
(WorkdirTransportErrorCode::Unsupported, 400, "unsupported"),
(WorkdirTransportErrorCode::Unavailable, 503, "unavailable"),
(WorkdirTransportErrorCode::Internal, 500, "transport failed"),
] {
let transport = WorkdirTransportError {
code,
message: "safe provider message".to_string(),
};
assert_eq!(code.http_status(), expected_status);
let workdir_error = transport.clone().into_workdir_error();
assert!(workdir_error.to_string().contains(expected_error));
assert_eq!(
WorkdirTransportError::from_workdir_error(&workdir_error).code,
code
);
}
}
#[test]
fn local_validation_errors_share_invalid_request_classification() {
for error in [
WorkdirError::InvalidGlob("[".to_string()),
WorkdirError::InvalidRegex("(".to_string()),
WorkdirError::InvalidArgument("limit must be positive".to_string()),
] {
let transport = WorkdirTransportError::from_workdir_error(&error);
assert_eq!(transport.code, WorkdirTransportErrorCode::InvalidRequest);
assert_eq!(transport.code.http_status(), 400);
assert_eq!(transport.message, "Workdir operation request is invalid");
}
}
#[test]
fn transport_failure_remains_distinct_from_session_unavailable() {
let transport = WorkdirTransportError::from_workdir_error(&WorkdirError::Transport(
+3
View File
@@ -225,6 +225,9 @@ pub enum WorkdirError {
#[error("Workdir session does not support {0:?}")]
Unsupported(WorkdirSessionCapability),
#[error("Workdir operation is unsupported: {0}")]
UnsupportedOperation(String),
#[error("invalid Workdir path: {0}")]
InvalidPath(String),