protocol: generate workspace TypeScript types
This commit is contained in:
parent
746c51c701
commit
a13fb6933b
23
Cargo.lock
generated
23
Cargo.lock
generated
|
|
@ -3035,6 +3035,7 @@ dependencies = [
|
|||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
"ts-rs",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
|
|
@ -4696,6 +4697,28 @@ dependencies = [
|
|||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ts-rs"
|
||||
version = "12.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "756050066659291d47a554a9f558125db17428b073c5ffce1daf5dcb0f7231d8"
|
||||
dependencies = [
|
||||
"thiserror 2.0.18",
|
||||
"ts-rs-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ts-rs-macros"
|
||||
version = "12.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38d90eea51bc7988ef9e674bf80a85ba6804739e535e9cab48e4bb34a8b652aa"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.117",
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ttf-parser"
|
||||
version = "0.25.1"
|
||||
|
|
|
|||
|
|
@ -4,8 +4,14 @@ version = "0.1.0"
|
|||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[features]
|
||||
default = ["stream"]
|
||||
stream = ["dep:tokio"]
|
||||
typescript = ["dep:ts-rs"]
|
||||
|
||||
[dependencies]
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
tokio = { workspace = true, features = ["io-util"] }
|
||||
tokio = { workspace = true, features = ["io-util"], optional = true }
|
||||
ts-rs = { version = "12.0.1", optional = true }
|
||||
uuid = { workspace = true, features = ["serde"] }
|
||||
|
|
|
|||
16
crates/protocol/examples/generate_typescript.rs
Normal file
16
crates/protocol/examples/generate_typescript.rs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#[cfg(feature = "typescript")]
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let path = protocol::typescript::generated_typescript_path();
|
||||
if let Some(parent) = path.parent() {
|
||||
std::fs::create_dir_all(parent)?;
|
||||
}
|
||||
std::fs::write(&path, protocol::typescript::generated_protocol_types())?;
|
||||
println!("wrote {}", path.display());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "typescript"))]
|
||||
fn main() {
|
||||
eprintln!("enable the `typescript` feature to generate protocol TypeScript bindings");
|
||||
std::process::exit(2);
|
||||
}
|
||||
|
|
@ -1,4 +1,7 @@
|
|||
#[cfg(feature = "stream")]
|
||||
pub mod stream;
|
||||
#[cfg(feature = "typescript")]
|
||||
pub mod typescript;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
|
|
@ -21,6 +24,7 @@ fn is_false(value: &bool) -> bool {
|
|||
// ---------------------------------------------------------------------------
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||
#[serde(tag = "method", content = "params", rename_all = "snake_case")]
|
||||
pub enum Method {
|
||||
Run {
|
||||
|
|
@ -103,6 +107,7 @@ pub enum Method {
|
|||
/// delivery (e.g. `TurnEnded` arriving after `ShutDown` for the same
|
||||
/// child Pod).
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||
#[serde(tag = "kind", rename_all = "snake_case")]
|
||||
pub enum PodEvent {
|
||||
/// Child finished one turn and is back to IDLE.
|
||||
|
|
@ -175,6 +180,7 @@ impl PodEvent {
|
|||
/// placeholder into the LLM context so neither user nor LLM is blind to
|
||||
/// the dropped intent.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||
#[serde(tag = "kind", rename_all = "snake_case")]
|
||||
pub enum Segment {
|
||||
/// Free-form text. The fallback every client can produce.
|
||||
|
|
@ -266,6 +272,7 @@ impl Method {
|
|||
// ---------------------------------------------------------------------------
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||
#[serde(tag = "event", content = "data", rename_all = "snake_case")]
|
||||
pub enum Event {
|
||||
/// A user input message was accepted, persisted as
|
||||
|
|
@ -294,6 +301,7 @@ pub enum Event {
|
|||
/// One event per `LogEntry::SystemItem` commit. Disk-side and
|
||||
/// wire-side are 1:1.
|
||||
SystemItem {
|
||||
#[cfg_attr(feature = "typescript", ts(type = "unknown"))]
|
||||
item: serde_json::Value,
|
||||
},
|
||||
/// A new self-driving cycle has begun (IDLE → active transition).
|
||||
|
|
@ -453,6 +461,7 @@ pub enum Event {
|
|||
/// role-specific entry events (`SegmentRotated` / `SystemItem`) —
|
||||
/// there is no generic "every committed entry" broadcast.
|
||||
Snapshot {
|
||||
#[cfg_attr(feature = "typescript", ts(type = "Array<unknown>"))]
|
||||
entries: Vec<serde_json::Value>,
|
||||
greeting: Greeting,
|
||||
#[serde(default)]
|
||||
|
|
@ -471,6 +480,7 @@ pub enum Event {
|
|||
///
|
||||
/// Payload is the JSON form of `session_store::LogEntry::SegmentStart`.
|
||||
SegmentRotated {
|
||||
#[cfg_attr(feature = "typescript", ts(type = "unknown"))]
|
||||
entry: serde_json::Value,
|
||||
},
|
||||
/// Current Pod controller status. Broadcast on every controller-level
|
||||
|
|
@ -495,6 +505,7 @@ pub enum Event {
|
|||
/// A rewind has truncated the authoritative session. `entries` is the
|
||||
/// retained session-log prefix clients should use to reseed display state.
|
||||
RewindApplied {
|
||||
#[cfg_attr(feature = "typescript", ts(type = "Array<unknown>"))]
|
||||
entries: Vec<serde_json::Value>,
|
||||
input: Vec<Segment>,
|
||||
summary: RewindSummary,
|
||||
|
|
@ -503,14 +514,17 @@ pub enum Event {
|
|||
/// crate can evolve discovery fields without introducing a protocol
|
||||
/// dependency on session-store.
|
||||
PodsListed {
|
||||
#[cfg_attr(feature = "typescript", ts(type = "unknown"))]
|
||||
pods: serde_json::Value,
|
||||
},
|
||||
/// Reply to `Method::RestorePod`.
|
||||
PodRestored {
|
||||
#[cfg_attr(feature = "typescript", ts(type = "unknown"))]
|
||||
result: serde_json::Value,
|
||||
},
|
||||
/// Reply to `Method::RegisterPeer`.
|
||||
PeerRegistered {
|
||||
#[cfg_attr(feature = "typescript", ts(type = "unknown"))]
|
||||
result: serde_json::Value,
|
||||
},
|
||||
Alert(Alert),
|
||||
|
|
@ -530,6 +544,7 @@ pub enum Event {
|
|||
/// `new_segment_id` is the UUID of the freshly created session that
|
||||
/// replaced the old history.
|
||||
CompactDone {
|
||||
#[cfg_attr(feature = "typescript", ts(type = "string"))]
|
||||
new_segment_id: uuid::Uuid,
|
||||
},
|
||||
/// Compaction failed. The session is unchanged.
|
||||
|
|
@ -546,6 +561,7 @@ pub enum Event {
|
|||
/// surfaced to the person driving the client. Keep messages short and
|
||||
/// human-readable.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||
pub struct Alert {
|
||||
pub level: AlertLevel,
|
||||
pub source: AlertSource,
|
||||
|
|
@ -555,6 +571,7 @@ pub struct Alert {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||
pub struct MemoryWorkerEvent {
|
||||
pub worker: String,
|
||||
pub status: String,
|
||||
|
|
@ -568,6 +585,7 @@ pub struct MemoryWorkerEvent {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum AlertLevel {
|
||||
Warn,
|
||||
|
|
@ -575,6 +593,7 @@ pub enum AlertLevel {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum AlertSource {
|
||||
Pod,
|
||||
|
|
@ -591,6 +610,7 @@ pub enum AlertSource {
|
|||
/// nailed down here so the TUI side can ship without waiting for
|
||||
/// the memory / workflow tickets.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum CompletionKind {
|
||||
File,
|
||||
|
|
@ -605,6 +625,7 @@ pub enum CompletionKind {
|
|||
/// keep a trailing `/` after a directory selection so the user can
|
||||
/// drill in without re-typing the prefix.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||
pub struct CompletionEntry {
|
||||
pub value: String,
|
||||
#[serde(default)]
|
||||
|
|
@ -612,12 +633,15 @@ pub struct CompletionEntry {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||
pub struct RewindTargetId {
|
||||
#[cfg_attr(feature = "typescript", ts(type = "string"))]
|
||||
pub segment_id: uuid::Uuid,
|
||||
pub user_input_entry_index: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||
pub struct RewindTarget {
|
||||
pub id: RewindTargetId,
|
||||
pub expected_head_entries: usize,
|
||||
|
|
@ -633,6 +657,7 @@ pub struct RewindTarget {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||
pub struct RewindSummary {
|
||||
pub truncated_to_entries: usize,
|
||||
pub discarded_entries: usize,
|
||||
|
|
@ -647,6 +672,7 @@ pub struct RewindSummary {
|
|||
/// history. Finalized assistant items continue to come from ordinary snapshot
|
||||
/// entries.
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||
pub struct InFlightSnapshot {
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub blocks: Vec<InFlightBlock>,
|
||||
|
|
@ -659,6 +685,7 @@ impl InFlightSnapshot {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||
#[serde(tag = "kind", rename_all = "snake_case")]
|
||||
pub enum InFlightBlock {
|
||||
Text {
|
||||
|
|
@ -681,6 +708,7 @@ pub enum InFlightBlock {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
|
||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum InFlightToolCallState {
|
||||
#[default]
|
||||
|
|
@ -701,6 +729,7 @@ impl InFlightToolCallState {
|
|||
/// transmitted alongside `Event::Snapshot` so clients don't need
|
||||
/// their own view of the manifest.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||
pub struct Greeting {
|
||||
pub pod_name: String,
|
||||
pub cwd: String,
|
||||
|
|
@ -721,6 +750,7 @@ pub struct Greeting {
|
|||
// ---------------------------------------------------------------------------
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
|
||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum PodStatus {
|
||||
#[default]
|
||||
|
|
@ -730,6 +760,7 @@ pub enum PodStatus {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum TurnResult {
|
||||
Finished,
|
||||
|
|
@ -743,6 +774,7 @@ pub enum TurnResult {
|
|||
/// notify message, pod event body) is delivered by the immediately
|
||||
/// following Turn entry, not by the marker itself.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum InvokeKind {
|
||||
/// `Method::Run` — a user submission.
|
||||
|
|
@ -762,6 +794,7 @@ pub enum InvokeKind {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum RunResult {
|
||||
Finished,
|
||||
|
|
@ -775,6 +808,7 @@ pub enum RunResult {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum ErrorCode {
|
||||
AlreadyRunning,
|
||||
|
|
@ -796,6 +830,7 @@ pub enum ErrorCode {
|
|||
|
||||
/// A single allow or deny rule inside a scope configuration.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||
pub struct ScopeRule {
|
||||
/// Target path. Must be absolute by the time a `Scope` is built from
|
||||
/// this rule — relative paths are resolved per-layer against the
|
||||
|
|
@ -822,6 +857,7 @@ fn default_recursive() -> bool {
|
|||
/// everything below); deny rules cap the effective level **strictly
|
||||
/// below** the stated level.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum Permission {
|
||||
Read,
|
||||
|
|
|
|||
97
crates/protocol/src/typescript.rs
Normal file
97
crates/protocol/src/typescript.rs
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use ts_rs::{Config, TS};
|
||||
|
||||
use crate::{
|
||||
Alert, AlertLevel, AlertSource, CompletionEntry, CompletionKind, ErrorCode, Event, Greeting,
|
||||
InFlightBlock, InFlightSnapshot, InFlightToolCallState, InvokeKind, MemoryWorkerEvent, Method,
|
||||
Permission, PodEvent, PodStatus, RewindSummary, RewindTarget, RewindTargetId, RunResult,
|
||||
ScopeRule, Segment, TurnResult,
|
||||
};
|
||||
|
||||
const GENERATED_RELATIVE_PATH: &str = "../../web/workspace/src/lib/generated/protocol.ts";
|
||||
|
||||
/// Repository-relative destination for the Workspace web protocol bindings.
|
||||
pub fn generated_typescript_path() -> PathBuf {
|
||||
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(GENERATED_RELATIVE_PATH)
|
||||
}
|
||||
|
||||
/// Render Workspace web TypeScript bindings for the Pod wire protocol DTOs.
|
||||
///
|
||||
/// Rust DTOs in this crate remain the source of truth; this function is used by
|
||||
/// both the checked-in artifact generator and the stale-output drift test.
|
||||
pub fn generated_protocol_types() -> String {
|
||||
let cfg = Config::new().with_large_int("number");
|
||||
let mut output = String::from(
|
||||
"// @generated by `cargo run -p protocol --example generate_typescript --features typescript`\n\
|
||||
// Do not edit by hand. Rust DTO authority lives in `crates/protocol`.\n\
|
||||
// Large integer fields are JSON numbers on the wire and are emitted as TypeScript `number`.\n\n",
|
||||
);
|
||||
|
||||
push_decl::<AlertLevel>(&cfg, &mut output);
|
||||
push_decl::<AlertSource>(&cfg, &mut output);
|
||||
push_decl::<CompletionKind>(&cfg, &mut output);
|
||||
push_decl::<PodStatus>(&cfg, &mut output);
|
||||
push_decl::<TurnResult>(&cfg, &mut output);
|
||||
push_decl::<InvokeKind>(&cfg, &mut output);
|
||||
push_decl::<RunResult>(&cfg, &mut output);
|
||||
push_decl::<ErrorCode>(&cfg, &mut output);
|
||||
push_decl::<Permission>(&cfg, &mut output);
|
||||
push_decl::<InFlightToolCallState>(&cfg, &mut output);
|
||||
push_decl::<ScopeRule>(&cfg, &mut output);
|
||||
push_decl::<CompletionEntry>(&cfg, &mut output);
|
||||
push_decl::<RewindTargetId>(&cfg, &mut output);
|
||||
push_decl::<RewindTarget>(&cfg, &mut output);
|
||||
push_decl::<RewindSummary>(&cfg, &mut output);
|
||||
push_decl::<InFlightBlock>(&cfg, &mut output);
|
||||
push_decl::<InFlightSnapshot>(&cfg, &mut output);
|
||||
push_decl::<Greeting>(&cfg, &mut output);
|
||||
push_decl::<Alert>(&cfg, &mut output);
|
||||
push_decl::<MemoryWorkerEvent>(&cfg, &mut output);
|
||||
push_decl::<Segment>(&cfg, &mut output);
|
||||
push_decl::<PodEvent>(&cfg, &mut output);
|
||||
push_decl::<Method>(&cfg, &mut output);
|
||||
push_decl::<Event>(&cfg, &mut output);
|
||||
|
||||
normalize_typescript(output)
|
||||
}
|
||||
|
||||
fn normalize_typescript(output: String) -> String {
|
||||
let mut lines = output.lines().map(str::trim_end).collect::<Vec<_>>();
|
||||
while lines.last() == Some(&"") {
|
||||
lines.pop();
|
||||
}
|
||||
lines.join("\n") + "\n"
|
||||
}
|
||||
|
||||
fn push_decl<T: TS>(cfg: &Config, output: &mut String) {
|
||||
let decl = T::decl(cfg);
|
||||
output.push_str(&export_decl(&decl));
|
||||
output.push_str("\n\n");
|
||||
}
|
||||
|
||||
fn export_decl(decl: &str) -> String {
|
||||
for prefix in ["type ", "interface ", "enum "] {
|
||||
if decl.starts_with(prefix) {
|
||||
return format!("export {decl}");
|
||||
}
|
||||
}
|
||||
decl.to_string()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn generated_protocol_types_are_current() {
|
||||
let expected = generated_protocol_types();
|
||||
let path = generated_typescript_path();
|
||||
let actual = std::fs::read_to_string(&path)
|
||||
.unwrap_or_else(|err| panic!("failed to read {}: {err}", path.display()));
|
||||
assert_eq!(
|
||||
actual, expected,
|
||||
"generated TypeScript protocol bindings are stale; run `cargo run -p protocol --example generate_typescript --features typescript`"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -262,11 +262,11 @@ async fn get_workspace(State(api): State<WorkspaceApi>) -> ApiResult<Json<Worksp
|
|||
store: "sqlite".to_string(),
|
||||
event_stream: ExtensionPointState {
|
||||
status: "reserved".to_string(),
|
||||
note: "No event stream is exposed in this bootstrap; route/state seams are reserved.".to_string(),
|
||||
note: "No browser-to-Pod socket path is exposed in this bootstrap; any future stream must be a Workspace server proxy that resolves Worker identity and enforces method allow/block boundaries.".to_string(),
|
||||
},
|
||||
host_worker_bridge: ExtensionPointState {
|
||||
status: "read_only_local".to_string(),
|
||||
note: "Local Hosts and Workers are exposed as a read-only bridge over existing Pod metadata; no scheduling or lifecycle control is implemented.".to_string(),
|
||||
note: "Local Hosts and Workers are exposed as a read-only bridge over existing Pod metadata; no direct Pod socket, scheduling, or lifecycle control is implemented.".to_string(),
|
||||
},
|
||||
},
|
||||
}))
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ rustPlatform.buildRustPackage rec {
|
|||
filter = sourceFilter;
|
||||
};
|
||||
|
||||
cargoHash = "sha256-dKkAFUfTAMxSRHq9iNmwRXjQVSBHQBtb0+v8VHkgAGM=";
|
||||
cargoHash = "sha256-M8cGY+eskFXSRjq3kBbRusflghvVKrWc1Pj50uKAlg8=";
|
||||
|
||||
depsExtraArgs = {
|
||||
# Older fetchCargoVendor utilities used crates.io's API download endpoint,
|
||||
|
|
|
|||
123
web/workspace/src/lib/generated/protocol.ts
Normal file
123
web/workspace/src/lib/generated/protocol.ts
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
// @generated by `cargo run -p protocol --example generate_typescript --features typescript`
|
||||
// Do not edit by hand. Rust DTO authority lives in `crates/protocol`.
|
||||
// Large integer fields are JSON numbers on the wire and are emitted as TypeScript `number`.
|
||||
|
||||
export type AlertLevel = "warn" | "error";
|
||||
|
||||
export type AlertSource = "pod" | "worker" | "compactor" | "agents_md";
|
||||
|
||||
export type CompletionKind = "file" | "knowledge" | "workflow";
|
||||
|
||||
export type PodStatus = "idle" | "running" | "paused";
|
||||
|
||||
export type TurnResult = "finished" | "paused";
|
||||
|
||||
export type InvokeKind = "user_send" | "notify" | "pod_event" | "system_reminder" | "wakeup";
|
||||
|
||||
export type RunResult = "finished" | "paused" | "limit_reached" | "rolled_back";
|
||||
|
||||
export type ErrorCode = "already_running" | "not_running" | "not_paused" | "provider_error" | "tool_error" | "invalid_request" | "internal";
|
||||
|
||||
export type Permission = "read" | "write";
|
||||
|
||||
export type InFlightToolCallState = "pending" | "streaming_args" | "done";
|
||||
|
||||
export type ScopeRule = {
|
||||
/**
|
||||
* Target path. Must be absolute by the time a `Scope` is built from
|
||||
* this rule — relative paths are resolved per-layer against the
|
||||
* manifest file's directory (cwd for overlay layers) before cascade
|
||||
* merge.
|
||||
*/
|
||||
target: string,
|
||||
/**
|
||||
* Permission level this rule grants (allow) or caps strictly below
|
||||
* (deny).
|
||||
*/
|
||||
permission: Permission,
|
||||
/**
|
||||
* When `false`, the rule only matches the target itself and its
|
||||
* direct children. Defaults to `true`.
|
||||
*/
|
||||
recursive: boolean, };
|
||||
|
||||
export type CompletionEntry = { value: string, is_dir: boolean, };
|
||||
|
||||
export type RewindTargetId = { segment_id: string, user_input_entry_index: number, };
|
||||
|
||||
export type RewindTarget = { id: RewindTargetId, expected_head_entries: number, truncate_entries: number, turn_index: number, timestamp_ms: number | null, preview: string, eligible: boolean, disabled_reason: string | null, warning: string | null, };
|
||||
|
||||
export type RewindSummary = { truncated_to_entries: number, discarded_entries: number, tool_side_effect_warning: boolean, };
|
||||
|
||||
export type InFlightBlock = { "kind": "text", text: string, finished?: boolean, } | { "kind": "thinking", text: string, finished?: boolean, } | { "kind": "tool_call", id: string, name: string, args: string, state?: InFlightToolCallState, };
|
||||
|
||||
export type InFlightSnapshot = { blocks?: Array<InFlightBlock>, };
|
||||
|
||||
export type Greeting = { pod_name: string, cwd: string, provider: string, model: string, scope_summary: string, tools: Array<string>,
|
||||
/**
|
||||
* Model context window in tokens. Always filled by the Pod greeting.
|
||||
*/
|
||||
context_window: number,
|
||||
/**
|
||||
* Estimated current session context tokens at connect time.
|
||||
*/
|
||||
context_tokens: number, };
|
||||
|
||||
export type Alert = { level: AlertLevel, source: AlertSource, message: string,
|
||||
/**
|
||||
* Milliseconds since the Unix epoch.
|
||||
*/
|
||||
timestamp_ms: number, };
|
||||
|
||||
export type MemoryWorkerEvent = { worker: string, status: string, run_id: string, trigger: string, reason: string,
|
||||
/**
|
||||
* Human-readable compact form for actionbar rendering.
|
||||
*/
|
||||
message: string,
|
||||
/**
|
||||
* Milliseconds since the Unix epoch.
|
||||
*/
|
||||
timestamp_ms: number, };
|
||||
|
||||
export type Segment = { "kind": "text", content: string, } | { "kind": "paste", id: number, chars: number, lines: number, content: string, } | { "kind": "file_ref", path: string, } | { "kind": "knowledge_ref", slug: string, } | { "kind": "workflow_invoke", slug: string, } | { "kind": "unknown" };
|
||||
|
||||
export type PodEvent = { "kind": "turn_ended", pod_name: string, } | { "kind": "errored", pod_name: string, message: string, } | { "kind": "shut_down", pod_name: string, } | { "kind": "scope_sub_delegated",
|
||||
/**
|
||||
* Sub-delegating Pod (= the sender itself).
|
||||
*/
|
||||
parent_pod: string,
|
||||
/**
|
||||
* Name of the grandchild Pod.
|
||||
*/
|
||||
sub_pod: string,
|
||||
/**
|
||||
* Unix-socket path where the grandchild is reachable.
|
||||
*/
|
||||
sub_socket: string,
|
||||
/**
|
||||
* Scope delegated to the grandchild.
|
||||
*/
|
||||
scope: Array<ScopeRule>, };
|
||||
|
||||
export type Method = { "method": "run", "params": { input: Array<Segment>, } } | { "method": "notify", "params": { message: string, auto_run?: boolean, } } | { "method": "pod_event", "params": PodEvent } | { "method": "resume" } | { "method": "cancel" } | { "method": "pause" } | { "method": "compact" } | { "method": "list_rewind_targets" } | { "method": "rewind_to", "params": { target: RewindTargetId, expected_head_entries: number, } } | { "method": "shutdown" } | { "method": "list_completions", "params": { kind: CompletionKind, prefix: string, } } | { "method": "list_pods" } | { "method": "restore_pod", "params": { name: string, } } | { "method": "register_peer", "params": { name: string, } };
|
||||
|
||||
export type Event = { "event": "user_message", "data": { segments: Array<Segment>, } } | { "event": "system_item", "data": { item: unknown, } } | { "event": "invoke_start", "data": { kind: InvokeKind, } } | { "event": "turn_start", "data": { turn: number, } } | { "event": "turn_end", "data": { turn: number, result: TurnResult, } } | { "event": "llm_call_start", "data": { llm_call: number, } } | { "event": "llm_call_end", "data": { llm_call: number, } } | { "event": "llm_retry", "data": { llm_call: number,
|
||||
/**
|
||||
* The attempt that just failed. 1 origin.
|
||||
*/
|
||||
failed_attempt: number, max_attempts: number, wait_ms: number, elapsed_ms: number, status?: number | null, error: string, } } | { "event": "llm_continuation", "data": { llm_call: number, attempt: number, max_attempts: number, reason: string, } } | { "event": "text_delta", "data": { text: string, } } | { "event": "text_done", "data": { text: string, } } | { "event": "thinking_start" } | { "event": "thinking_delta", "data": { text: string, } } | { "event": "thinking_done", "data": { text: string, } } | { "event": "tool_call_start", "data": { id: string, name: string, } } | { "event": "tool_call_args_delta", "data": { id: string, json: string, } } | { "event": "tool_call_done", "data": { id: string, name: string, arguments: string, } } | { "event": "tool_result", "data": { id: string,
|
||||
/**
|
||||
* Short human-readable summary. Always present; used by clients
|
||||
* that only want a 1-line rendering (e.g. collapsed views).
|
||||
*/
|
||||
summary: string,
|
||||
/**
|
||||
* Full tool output. Absent when the tool chose to return
|
||||
* summary-only, or when the result was pruned.
|
||||
*/
|
||||
output?: string | null, is_error: boolean, } } | { "event": "usage", "data": { input_tokens: number | null, output_tokens: number | null, cache_read_input_tokens?: number | null, } } | { "event": "run_end", "data": { result: RunResult, } } | { "event": "error", "data": { code: ErrorCode, message: string, } } | { "event": "snapshot", "data": { entries: Array<unknown>, greeting: Greeting, status: PodStatus,
|
||||
/**
|
||||
* Unfinished model output that has already streamed in the current
|
||||
* run but is not yet represented by committed snapshot entries.
|
||||
*/
|
||||
in_flight?: InFlightSnapshot, } } | { "event": "segment_rotated", "data": { entry: unknown, } } | { "event": "status", "data": { status: PodStatus, } } | { "event": "completions", "data": { kind: CompletionKind, entries: Array<CompletionEntry>, } } | { "event": "rewind_targets", "data": { head_entries: number, targets: Array<RewindTarget>, } } | { "event": "rewind_applied", "data": { entries: Array<unknown>, input: Array<Segment>, summary: RewindSummary, } } | { "event": "pods_listed", "data": { pods: unknown, } } | { "event": "pod_restored", "data": { result: unknown, } } | { "event": "peer_registered", "data": { result: unknown, } } | { "event": "alert", "data": Alert } | { "event": "memory_worker", "data": MemoryWorkerEvent } | { "event": "compact_start" } | { "event": "compact_done", "data": { new_segment_id: string, } } | { "event": "compact_failed", "data": { error: string, } } | { "event": "shutdown" };
|
||||
|
|
@ -1,3 +1,9 @@
|
|||
export type {
|
||||
Event as PodProtocolEvent,
|
||||
Method as PodProtocolMethod,
|
||||
Segment as PodProtocolSegment,
|
||||
} from '$lib/generated/protocol';
|
||||
|
||||
export type ExtensionPoint = {
|
||||
status: string;
|
||||
note: string;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user