feat: migrate workspace configuration domains to ServerApi

This commit is contained in:
2026-09-23 04:27:52 +09:00
parent c8766e9fb9
commit 6cbc3a6988
34 changed files with 10679 additions and 454 deletions
+39
View File
@@ -128,6 +128,45 @@ fn server_api_client(
.map_err(|error| BackendWorkspaceClientError::InvalidTarget(error.to_string()))
}
pub(crate) fn memory_document_blocking(
backend: &BackendApiClient,
workspace_id: &str,
) -> Result<server_api::MemoryDocumentResponse, BackendWorkspaceClientError> {
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.map_err(|error| BackendWorkspaceClientError::InvalidTarget(error.to_string()))?;
runtime.block_on(async {
server_api_client(backend)?
.memory_document(workspace_id.to_owned())
.await
.map_err(|error| server_client_error(backend, error))
})
}
pub(crate) fn memory_staging_list_blocking(
backend: &BackendApiClient,
workspace_id: &str,
limit: usize,
) -> Result<server_api::MemoryStagingListResponse, BackendWorkspaceClientError> {
let limit = u32::try_from(limit).map_err(|_| {
BackendWorkspaceClientError::InvalidTarget("Memory staging limit exceeds u32".to_string())
})?;
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.map_err(|error| BackendWorkspaceClientError::InvalidTarget(error.to_string()))?;
runtime.block_on(async {
server_api_client(backend)?
.memory_staging_list(
workspace_id.to_owned(),
server_api::MemoryStagingQuery { limit: Some(limit) },
)
.await
.map_err(|error| server_client_error(backend, error))
})
}
pub fn list_backend_workspaces_blocking(
target: &BackendWorkspaceCatalogTarget,
) -> Result<Vec<BackendWorkspace>, BackendWorkspaceClientError> {
+12 -3
View File
@@ -310,14 +310,14 @@ impl BackendWorkspaceProductClient {
}
pub fn memory_document(&self) -> Result<MemoryDocumentResponse, BackendWorkspaceClientError> {
self.get_json("/memory")
crate::backend_workspace::memory_document_blocking(&self.api, &self.workspace_id)
}
pub fn list_memory_staging(
&self,
limit: usize,
) -> Result<MemoryStagingListResponse, BackendWorkspaceClientError> {
self.get_json(&format!("/memory/staging?limit={limit}"))
crate::backend_workspace::memory_staging_list_blocking(&self.api, &self.workspace_id, limit)
}
pub fn launch_ticket_intake(
@@ -813,7 +813,16 @@ mod tests {
let error = client.list_memory_staging(10).unwrap_err();
assert!(matches!(error, BackendWorkspaceClientError::Http(_)));
assert!(matches!(
error,
BackendWorkspaceClientError::ServerApi(
server_api::client_support::ClientError::Failure(
server_api::client_support::ClientFailure::Decode {
kind: server_api::client_support::DecodeKind::Success,
},
),
)
));
assert!(
request
.recv()
+38 -15
View File
@@ -4,6 +4,7 @@
//! backend operation boundary. Repository-local audit logs are not an authority.
use chrono::{DateTime, Utc};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
@@ -11,7 +12,7 @@ fn is_zero_usize(value: &usize) -> bool {
*value == 0
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum AuditWorker {
MemoryExtract,
@@ -27,7 +28,7 @@ impl AuditWorker {
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum WorkerLifecycleStatus {
Started,
@@ -49,7 +50,7 @@ impl WorkerLifecycleStatus {
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum AuditTrigger {
SessionEnd,
@@ -77,7 +78,7 @@ impl AuditTrigger {
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum AuditStatus {
Success,
@@ -85,7 +86,7 @@ pub enum AuditStatus {
Skipped,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct ModelAudit {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub ref_: Option<String>,
@@ -95,31 +96,39 @@ pub struct ModelAudit {
pub model_id: Option<String>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct UsageAudit {
#[serde(default, skip_serializing_if = "Option::is_none")]
#[schemars(range(min = 0, max = 9_007_199_254_740_991_u64))]
pub input_tokens: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[schemars(range(min = 0, max = 9_007_199_254_740_991_u64))]
pub output_tokens: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[schemars(range(min = 0, max = 9_007_199_254_740_991_u64))]
pub total_tokens: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[schemars(range(min = 0, max = 9_007_199_254_740_991_u64))]
pub cache_read_input_tokens: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[schemars(range(min = 0, max = 9_007_199_254_740_991_u64))]
pub cache_creation_input_tokens: Option<u64>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct ExtractAudit {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub session_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub segment_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[schemars(with = "Option<crate::schema::JsonSafeU64Pair>")]
pub entry_range: Option<[u64; 2]>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[schemars(with = "Option<crate::schema::JsonSafeU64Pair>")]
pub history_range: Option<[u64; 2]>,
#[serde(default)]
#[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))]
pub staging_count: usize,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub staging_ids: Vec<String>,
@@ -127,13 +136,16 @@ pub struct ExtractAudit {
pub staging_paths: Vec<String>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct ConsolidationAudit {
#[serde(default)]
#[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))]
pub staging_count: usize,
#[serde(default, skip_serializing_if = "is_zero_usize")]
#[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))]
pub invalid_staging_count: usize,
#[serde(default)]
#[schemars(range(min = 0, max = 9_007_199_254_740_991_u64))]
pub staging_bytes: u64,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub consumed_staging_ids: Vec<String>,
@@ -141,19 +153,25 @@ pub struct ConsolidationAudit {
pub operations: OperationCounts,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct OperationCounts {
#[serde(default)]
#[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))]
pub write: usize,
#[serde(default)]
#[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))]
pub edit: usize,
#[serde(default)]
#[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))]
pub delete: usize,
#[serde(default)]
#[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))]
pub drop: usize,
#[serde(default)]
#[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))]
pub merge: usize,
#[serde(default)]
#[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))]
pub trim: usize,
}
@@ -163,15 +181,17 @@ impl OperationCounts {
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct MemorySettingsAudit {
pub workspace_id: String,
#[schemars(range(min = 0, max = 9_007_199_254_740_991_u64))]
pub settings_revision: u64,
pub language: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct WorkerLifecycleAudit {
#[schemars(with = "String")]
pub run_id: Uuid,
pub worker: AuditWorker,
pub status: WorkerLifecycleStatus,
@@ -189,7 +209,7 @@ pub struct WorkerLifecycleAudit {
pub consolidation: Option<ConsolidationAudit>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct RecordOperationAudit {
pub op: String,
pub status: AuditStatus,
@@ -204,7 +224,7 @@ pub struct RecordOperationAudit {
pub reason: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct RecordUsageAudit {
pub op: String,
pub status: AuditStatus,
@@ -216,12 +236,13 @@ pub struct RecordUsageAudit {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub query: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))]
pub result_count: Option<usize>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub reason: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "event", rename_all = "snake_case")]
pub enum AuditPayload {
WorkerLifecycle(WorkerLifecycleAudit),
@@ -229,9 +250,11 @@ pub enum AuditPayload {
RecordUsage(RecordUsageAudit),
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct AuditEvent {
#[schemars(with = "String")]
pub id: Uuid,
#[schemars(with = "String")]
pub occurred_at: DateTime<Utc>,
#[serde(flatten)]
pub payload: AuditPayload,
+19 -13
View File
@@ -11,7 +11,7 @@ use crate::audit::AuditEvent;
use crate::extract::{ExtractedCandidate, ExtractedPayload, StagingEvidence};
use crate::schema::{SourceEvidenceRef, SourceRef};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "operation", rename_all = "snake_case")]
pub enum MemoryBackendOperation {
Query(MemoryQueryOperation),
@@ -26,7 +26,7 @@ pub enum MemoryBackendOperation {
StagingClose(MemoryStagingCloseOperation),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "status", rename_all = "snake_case")]
pub enum MemoryBackendHttpResponse {
Ok {
@@ -37,7 +37,7 @@ pub enum MemoryBackendHttpResponse {
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum MemoryBackendOperationResult {
ToolOutput(MemoryToolOutput),
@@ -45,14 +45,14 @@ pub enum MemoryBackendOperationResult {
StagingWritten(MemoryStagingWriteOutput),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct MemoryToolOutput {
pub summary: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub content: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct MemoryQueryOperation {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub query: Option<String>,
@@ -61,8 +61,10 @@ pub struct MemoryQueryOperation {
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct MemoryDocumentReadOperation {
#[serde(default, skip_serializing_if = "Option::is_none")]
#[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))]
pub offset: Option<usize>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))]
pub limit: Option<usize>,
}
@@ -74,15 +76,15 @@ pub struct MemoryDocumentUpdateOperation {
pub replace_all: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
pub struct MemoryResidentSummaryOperation {}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct MemoryAppendAuditOperation {
pub event: AuditEvent,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct MemoryStageCandidateOperation {
pub source: SourceRef,
pub extract_run_id: String,
@@ -93,7 +95,7 @@ pub struct MemoryStageCandidateOperation {
pub source_refs: Vec<SourceEvidenceRef>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct MemoryStageExtractedOperation {
pub source: SourceRef,
pub payload: ExtractedPayload,
@@ -102,6 +104,7 @@ pub struct MemoryStageExtractedOperation {
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct MemoryStagingListOperation {
#[serde(default, skip_serializing_if = "Option::is_none")]
#[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))]
pub limit: Option<usize>,
}
@@ -140,28 +143,31 @@ pub enum MemoryStagingAffectedMemoryOperation {
Edit,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct MemoryConsolidateStagingOperation {
#[serde(default)]
pub force: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct MemoryConsolidationOutput {
pub status: String,
pub summary: String,
#[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))]
pub candidate_count: usize,
#[schemars(range(min = 0, max = 9_007_199_254_740_991_u64))]
pub total_bytes: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct MemoryBackendAckOutput {
pub summary: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct MemoryStagingWriteOutput {
#[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))]
pub staging_count: usize,
pub staging_ids: Vec<String>,
}
+2 -1
View File
@@ -73,12 +73,13 @@ impl ExtractedPayload {
}
/// Bounded evidence snippet copied into a flat staging record.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct StagingEvidence {
pub id: String,
pub kind: EvidenceKind,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[schemars(with = "Option<crate::schema::JsonSafeU64Pair>")]
pub entry_range: Option<[u64; 2]>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub origin: Option<EvidenceOrigin>,
+12 -1
View File
@@ -4,14 +4,23 @@ use lint_common::RecordLintError;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
/// Schema-only representation for JSON integers that must remain exactly
/// representable by JavaScript consumers.
#[allow(dead_code)]
#[derive(JsonSchema)]
pub struct MemoryJsonSafeU64(#[schemars(range(min = 0, max = 9_007_199_254_740_991_u64))] u64);
pub type JsonSafeU64Pair = [MemoryJsonSafeU64; 2];
pub use lint_common::Frontmatter;
/// Reference to a session-store entry range. Stored in `sources` /
/// `last_sources` arrays for traceability back to raw session logs.
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, JsonSchema)]
pub struct SourceRef {
pub segment_id: String,
/// `[start_entry, end_entry]` inclusive range of session-store entry indices.
#[schemars(with = "crate::schema::JsonSafeU64Pair")]
pub range: [u64; 2],
}
@@ -99,6 +108,7 @@ pub struct EvidenceOrigin {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub flow_definition_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[schemars(range(min = 0, max = 9_007_199_254_740_991_u64))]
pub flow_definition_revision: Option<u64>,
}
@@ -118,6 +128,7 @@ pub struct SourceEvidenceRef {
pub segment_id: Option<String>,
/// `[start_entry, end_entry]` inclusive range of session-store entry indices.
#[serde(default, skip_serializing_if = "Option::is_none")]
#[schemars(with = "Option<crate::schema::JsonSafeU64Pair>")]
pub entry_range: Option<[u64; 2]>,
/// Host-assigned evidence id within the referenced evidence set.
#[serde(default, skip_serializing_if = "Option::is_none")]
+1
View File
@@ -8,6 +8,7 @@ mod decision;
mod request;
mod summary;
pub(crate) use common::JsonSafeU64Pair;
pub use common::{
EvidenceKind, EvidenceOrigin, EvidenceOriginKind, Frontmatter, SourceEvidenceRef, SourceRef,
split_frontmatter,
+1
View File
@@ -11,6 +11,7 @@ typescript = ["dep:ts-rs", "protocol/typescript"]
[dependencies]
api-macros = { workspace = true, features = ["reqwest", "axum", "openapi"] }
memory.workspace = true
protocol.workspace = true
runtime-api.workspace = true
schemars.workspace = true
File diff suppressed because it is too large Load Diff
+14 -3
View File
@@ -532,18 +532,29 @@ impl WorkspaceClient for RuntimeOwnedWorkspaceClient {
response.status, response.body
)));
}
let projection: WorkspacePromptProjection =
let wire_projection: server_api::WorkspacePromptProjection =
serde_json::from_str(&response.body).map_err(|error| {
WorkspaceClientError::Request(format!(
"invalid active Workspace Prompt projection response: {error}"
))
})?;
if projection.workspace_id != self.workspace_id {
if wire_projection.workspace_id != self.workspace_id {
return Err(WorkspaceClientError::Request(format!(
"active Workspace Prompt projection scope mismatch: expected {}, got {}",
self.workspace_id, projection.workspace_id
self.workspace_id, wire_projection.workspace_id
)));
}
let projection: WorkspacePromptProjection =
serde_json::from_value(serde_json::to_value(wire_projection).map_err(|error| {
WorkspaceClientError::Request(format!(
"project active Workspace Prompt projection response: {error}"
))
})?)
.map_err(|error| {
WorkspaceClientError::Request(format!(
"convert active Workspace Prompt projection response: {error}"
))
})?;
let resolution = cache
.observe(projection)
.map_err(WorkspaceClientError::Request)?;
+12 -4
View File
@@ -104,7 +104,7 @@ async fn execute_memory_backend(
let response = client.execute(WorkspaceRequest::json(
WorkspaceRequestMethod::Post,
format!("/api/w/{workspace_id}/memory/backend"),
serde_json::to_string(&operation)?,
serde_json::to_string(&server_api::MemoryBackendRequest(operation))?,
))?;
let status = reqwest::StatusCode::from_u16(response.status)
.unwrap_or(reqwest::StatusCode::INTERNAL_SERVER_ERROR);
@@ -114,7 +114,7 @@ async fn execute_memory_backend(
body: response.body,
});
}
match serde_json::from_str::<MemoryBackendHttpResponse>(&response.body)? {
match serde_json::from_str::<server_api::MemoryBackendResponse>(&response.body)?.0 {
MemoryBackendHttpResponse::Ok { result } => Ok(result),
MemoryBackendHttpResponse::Error { message } => {
Err(WorkspaceMemoryBackendError::Backend(message))
@@ -138,7 +138,9 @@ async fn execute_memory_consolidation(
let response = client.execute(WorkspaceRequest::json(
WorkspaceRequestMethod::Post,
format!("/api/w/{workspace_id}/memory/consolidation"),
serde_json::to_string(&operation)?,
serde_json::to_string(&server_api::MemoryConsolidateStagingRequest {
force: operation.force,
})?,
))?;
let status = reqwest::StatusCode::from_u16(response.status)
.unwrap_or(reqwest::StatusCode::INTERNAL_SERVER_ERROR);
@@ -148,7 +150,13 @@ async fn execute_memory_consolidation(
body: response.body,
});
}
serde_json::from_str::<MemoryConsolidationOutput>(&response.body).map_err(Into::into)
let response = serde_json::from_str::<server_api::MemoryConsolidationResponse>(&response.body)?;
Ok(MemoryConsolidationOutput {
status: response.status,
summary: response.summary,
candidate_count: response.candidate_count,
total_bytes: response.total_bytes,
})
}
pub fn workspace_http_memory_tools(client: Arc<dyn WorkspaceClient>) -> Vec<ToolDefinition> {
+4 -14
View File
@@ -1,23 +1,13 @@
use serde::{Deserialize, Serialize};
use serde::Deserialize;
use crate::worker::WorkspaceClient;
pub use server_api::{
SkillActivationStatus, SkillCatalogEntry, SkillCatalogResponse, SkillDetailResponse,
SkillDiagnostic, SkillDiagnosticSeverity, SkillProjectionIdentity, SkillProjectionStatus,
SkillProvenance, SkillResourceRef, SkillSourceKind,
SkillActivationResponse, SkillActivationStatus, SkillCatalogEntry, SkillCatalogResponse,
SkillDetailResponse, SkillDiagnostic, SkillDiagnosticSeverity, SkillProjectionIdentity,
SkillProjectionStatus, SkillProvenance, SkillResourceRef, SkillSourceKind,
};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct SkillActivationResponse {
pub name: String,
pub provenance: SkillProvenance,
#[serde(default)]
pub diagnostics: Vec<SkillDiagnostic>,
/// Imported Markdown content to append to Worker history on explicit activation.
pub body: String,
}
#[derive(Debug, thiserror::Error)]
pub enum SkillClientError {
#[error("workspace client is unavailable: {0}")]
+10 -4
View File
@@ -3889,8 +3889,8 @@ impl<C: LlmClient + 'static, St: Store> Worker<C, St> {
.ok_or_else(|| {
WorkerError::FlowInput("Workspace client has no Workspace scope".to_string())
})?;
let request = flow::FlowSourceResolveRequest {
selector: selector.clone(),
let request = server_api::FlowSourceResolveRequest {
selector: selector.to_string(),
};
let response = workspace
.execute(WorkspaceRequest {
@@ -3915,13 +3915,19 @@ impl<C: LlmClient + 'static, St: Store> Worker<C, St> {
response.status
)));
}
let source: flow::ResolvedFlowSource = serde_json::from_str(&response.body)
let wire_source: server_api::ResolvedFlowSource = serde_json::from_str(&response.body)
.map_err(|error| WorkerError::FlowInput(format!("decode Flow source: {error}")))?;
if source.workspace_id != workspace_id || source.selector != selector {
if wire_source.workspace_id != workspace_id || wire_source.selector != selector.to_string()
{
return Err(WorkerError::FlowInput(
"Workspace returned a Flow source outside the requested scope".to_string(),
));
}
let source: flow::ResolvedFlowSource =
serde_json::from_value(serde_json::to_value(wire_source).map_err(|error| {
WorkerError::FlowInput(format!("project Flow source transport: {error}"))
})?)
.map_err(|error| WorkerError::FlowInput(format!("convert Flow source: {error}")))?;
let (state, initial_instructions) =
flow::FlowRuntimeState::start(&source, uuid::Uuid::now_v7().to_string())
.map_err(|error| WorkerError::FlowInput(error.to_string()))?;
File diff suppressed because it is too large Load Diff