feat: migrate repository and workdir domains to ServerApi
This commit is contained in:
@@ -13,6 +13,7 @@ async-trait.workspace = true
|
||||
fs-operation.workspace = true
|
||||
manifest.workspace = true
|
||||
reqwest = { version = "0.13", default-features = false, features = ["json", "rustls"], optional = true }
|
||||
schemars.workspace = true
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json.workspace = true
|
||||
sha2.workspace = true
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
//! optional so Runtime servers can share these DTOs without depending on a
|
||||
//! client stack.
|
||||
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
@@ -16,7 +17,7 @@ use crate::{
|
||||
};
|
||||
|
||||
/// Opaque Runtime-owned identifier for one ephemeral Workdir session.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(transparent)]
|
||||
pub struct WorkdirSessionId(String);
|
||||
|
||||
@@ -37,7 +38,7 @@ impl WorkdirSessionId {
|
||||
}
|
||||
|
||||
/// Open a fresh session for a persisted Workdir identity.
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||
pub struct OpenWorkdirSessionRequest {
|
||||
/// Optional Runtime Worker whose persisted binding establishes workspace
|
||||
/// ownership of the Workdir. Runtime servers reject cross-workspace owners.
|
||||
@@ -45,7 +46,7 @@ pub struct OpenWorkdirSessionRequest {
|
||||
pub owner_worker_id: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||
pub struct OpenWorkdirSessionResponse {
|
||||
pub session_id: WorkdirSessionId,
|
||||
pub workdir_id: WorkdirId,
|
||||
@@ -53,7 +54,7 @@ pub struct OpenWorkdirSessionResponse {
|
||||
}
|
||||
|
||||
/// One provider-side Workdir operation.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(
|
||||
tag = "operation",
|
||||
content = "request",
|
||||
@@ -77,14 +78,14 @@ pub enum WorkdirSessionOperation {
|
||||
}
|
||||
|
||||
/// Wire envelope for one provider operation.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct WorkdirSessionOperationRequest {
|
||||
pub operation: WorkdirSessionOperation,
|
||||
}
|
||||
|
||||
/// Typed result paired with [`WorkdirSessionOperation`].
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(
|
||||
tag = "operation",
|
||||
content = "result",
|
||||
@@ -174,7 +175,7 @@ pub async fn dispatch_workdir_session_operation(
|
||||
}
|
||||
|
||||
/// Stable, host-path-free error code crossing the Runtime boundary.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum WorkdirTransportErrorCode {
|
||||
NotFound,
|
||||
@@ -238,7 +239,7 @@ impl WorkdirTransportErrorCode {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||
pub struct WorkdirTransportError {
|
||||
pub code: WorkdirTransportErrorCode,
|
||||
pub message: String,
|
||||
|
||||
@@ -20,6 +20,7 @@ use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tokio::sync::broadcast;
|
||||
|
||||
@@ -45,7 +46,7 @@ pub use scope::{
|
||||
};
|
||||
|
||||
/// Persistent, opaque identity of one materialized Workdir.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
|
||||
pub struct Workdir {
|
||||
id: WorkdirId,
|
||||
}
|
||||
@@ -63,7 +64,7 @@ impl Workdir {
|
||||
}
|
||||
|
||||
/// Opaque Workdir identifier assigned by the materialization authority.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(transparent)]
|
||||
pub struct WorkdirId(String);
|
||||
|
||||
@@ -79,7 +80,7 @@ impl std::fmt::Display for WorkdirId {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum WorkdirSessionCapability {
|
||||
Read,
|
||||
@@ -90,7 +91,7 @@ pub enum WorkdirSessionCapability {
|
||||
Command,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||
pub struct WorkdirSessionCapabilities {
|
||||
bits: u8,
|
||||
}
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(transparent)]
|
||||
pub struct CommandHandle(pub String);
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||
pub struct CommandRequest {
|
||||
pub command: String,
|
||||
#[schemars(range(min = 0, max = 9_007_199_254_740_991_u64))]
|
||||
pub timeout_secs: u64,
|
||||
#[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))]
|
||||
pub output_limit: usize,
|
||||
/// Workdir-relative command directory. Providers validate it against the
|
||||
/// active session before process start.
|
||||
@@ -25,15 +28,17 @@ pub struct CommandRequest {
|
||||
pub tool_call_id: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||
pub struct CommandOutputRequest {
|
||||
pub handle: CommandHandle,
|
||||
#[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))]
|
||||
pub cursor: usize,
|
||||
#[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))]
|
||||
pub limit: usize,
|
||||
pub wait: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum CommandStatus {
|
||||
Running,
|
||||
@@ -43,35 +48,41 @@ pub enum CommandStatus {
|
||||
Cancelled,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum CommandStream {
|
||||
Stdout,
|
||||
Stderr,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema, Default)]
|
||||
pub struct CommandStreamSlice {
|
||||
#[schemars(range(min = 0, max = 9_007_199_254_740_991_u64))]
|
||||
pub start_offset: u64,
|
||||
#[schemars(range(min = 0, max = 9_007_199_254_740_991_u64))]
|
||||
pub end_offset: u64,
|
||||
pub content: String,
|
||||
pub truncated: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||
pub struct CommandSnapshot {
|
||||
pub command_id: String,
|
||||
pub tool_call_id: Option<String>,
|
||||
pub status: CommandStatus,
|
||||
#[schemars(range(min = 0, max = 9_007_199_254_740_991_u64))]
|
||||
pub started_at_ms: u64,
|
||||
#[schemars(range(min = 0, max = 9_007_199_254_740_991_u64))]
|
||||
pub observed_at_ms: u64,
|
||||
#[schemars(range(min = 0, max = 9_007_199_254_740_991_u64))]
|
||||
pub last_output_at_ms: Option<u64>,
|
||||
pub stdout: CommandStreamSlice,
|
||||
pub stderr: CommandStreamSlice,
|
||||
#[schemars(range(min = -2147483648_i32, max = 2147483647_i32))]
|
||||
pub exit_code: Option<i32>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(tag = "kind", rename_all = "snake_case")]
|
||||
pub enum CommandEvent {
|
||||
Started {
|
||||
@@ -97,12 +108,14 @@ pub enum CommandEvent {
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||
pub struct CommandOutput {
|
||||
pub status: CommandStatus,
|
||||
#[schemars(range(min = -2147483648_i32, max = 2147483647_i32))]
|
||||
pub exit_code: Option<i32>,
|
||||
pub timed_out: bool,
|
||||
pub content: String,
|
||||
#[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))]
|
||||
pub next_cursor: Option<usize>,
|
||||
pub truncated: bool,
|
||||
/// Complete output retained by the provider when `truncated` is true.
|
||||
|
||||
@@ -9,6 +9,7 @@ use fs_operation::{
|
||||
ListResult, ReadRequest, ReadResult, StatRequest, StatResult, WriteRequest, WriteResult,
|
||||
};
|
||||
use manifest::SymlinkPolicy;
|
||||
use schemars::JsonSchema;
|
||||
use tokio::sync::broadcast;
|
||||
|
||||
const MAX_SCOPED_COMMANDS: usize = 16;
|
||||
@@ -19,25 +20,26 @@ use crate::{
|
||||
WorkdirSessionCapabilities, WorkdirSessionCapability, WorkdirSessionHandle,
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, JsonSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum WorkdirToolScopePermission {
|
||||
Read,
|
||||
Write,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, JsonSchema)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct WorkdirToolScopeRule {
|
||||
pub target: FsPath,
|
||||
pub permission: WorkdirToolScopePermission,
|
||||
pub recursive: bool,
|
||||
#[serde(default)]
|
||||
#[schemars(with = "String")]
|
||||
pub symlink_policy: SymlinkPolicy,
|
||||
}
|
||||
|
||||
/// Provider-side check for one operation under an attenuated tool scope.
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, JsonSchema)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct WorkdirScopeAuthorizationRequest {
|
||||
pub rules: Vec<WorkdirToolScopeRule>,
|
||||
@@ -46,14 +48,14 @@ pub struct WorkdirScopeAuthorizationRequest {
|
||||
}
|
||||
|
||||
/// Provider-side overlap comparison that keeps resolved host paths private.
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, JsonSchema)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct WorkdirScopeOverlapRequest {
|
||||
pub left: WorkdirToolScopeRule,
|
||||
pub right: WorkdirToolScopeRule,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, JsonSchema)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct WorkdirToolScope {
|
||||
pub rules: Vec<WorkdirToolScopeRule>,
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
//! transport projections. They intentionally do not expose provider/session
|
||||
//! handles, host paths, Runtime URLs, or credentials.
|
||||
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum WorkingDirectoryMaterializerKind {
|
||||
#[default]
|
||||
@@ -14,7 +15,7 @@ pub enum WorkingDirectoryMaterializerKind {
|
||||
ClientHostedExternal,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum WorkingDirectoryStatusKind {
|
||||
Active,
|
||||
@@ -42,7 +43,7 @@ impl std::fmt::Display for WorkingDirectoryStatusKind {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct WorkingDirectoryCleanupTarget {
|
||||
pub kind: String,
|
||||
@@ -50,7 +51,7 @@ pub struct WorkingDirectoryCleanupTarget {
|
||||
pub repository_key: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct WorkingDirectoryOccupancy {
|
||||
pub runtime_id: String,
|
||||
@@ -59,7 +60,7 @@ pub struct WorkingDirectoryOccupancy {
|
||||
pub linked_at: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct RuntimeWorkingDirectoryCleanupTarget {
|
||||
pub kind: String,
|
||||
@@ -67,7 +68,7 @@ pub struct RuntimeWorkingDirectoryCleanupTarget {
|
||||
pub repository_id: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct RuntimeWorkingDirectorySummary {
|
||||
pub working_directory_id: String,
|
||||
@@ -99,14 +100,14 @@ pub struct RuntimeWorkingDirectorySummary {
|
||||
pub occupied_by: Option<WorkingDirectoryOccupancy>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
||||
#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)]
|
||||
pub enum WorkingDirectorySource {
|
||||
Repository { repository_key: String },
|
||||
ExternalGrant { grant_id: String },
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct WorkingDirectorySummary {
|
||||
pub working_directory_id: String,
|
||||
@@ -146,7 +147,9 @@ impl WorkingDirectorySummary {
|
||||
pub use WorkingDirectoryMaterializerKind as MaterializerKind;
|
||||
|
||||
/// Stable Workspace identity for a Worker hosted by a Runtime.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[derive(
|
||||
Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, JsonSchema,
|
||||
)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct RuntimeWorkerRef {
|
||||
pub runtime_id: String,
|
||||
@@ -164,7 +167,7 @@ impl RuntimeWorkerRef {
|
||||
}
|
||||
|
||||
/// Immutable materialization provenance retained by Workspace inventory.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct WorkingDirectoryProvenance {
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
@@ -179,7 +182,7 @@ pub struct WorkingDirectoryProvenance {
|
||||
}
|
||||
|
||||
/// Latest provider-neutral observation attached to Workspace inventory.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct WorkingDirectoryCurrentObservation {
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
@@ -247,7 +250,7 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct WorkspaceWorkdirSessionOperationRequest {
|
||||
/// Worker-local attachment alias selected by the calling tool router.
|
||||
|
||||
Reference in New Issue
Block a user