Skip to content

Commit 95eeac3

Browse files
hyperpolymathclaude
andcommitted
fix(api): include content in octad GET responses
OctadResponse now returns title, body, metadata, and types from the document and semantic modalities — previously only returned boolean has_* flags. Also routes OctadInput.metadata into Document.metadata during create/update so metadata survives roundtrip. This unblocks downstream consumers (stapeln, hypatia) that need to read back stored data. Fields use skip_serializing_if to keep responses clean when modalities are unpopulated. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent ef78c96 commit 95eeac3

2 files changed

Lines changed: 34 additions & 3 deletions

File tree

rust-core/verisim-api/src/lib.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,11 +374,13 @@ pub struct TensorRequest {
374374
pub data: Vec<f64>,
375375
}
376376

377-
/// Octad response
377+
/// Octad response — includes content from document and semantic modalities
378+
/// so consumers can read back what they stored (not just boolean flags).
378379
#[derive(Debug, Serialize, Deserialize)]
379380
pub struct OctadResponse {
380381
pub id: String,
381382
pub status: OctadStatusResponse,
383+
// Modality presence flags
382384
pub has_graph: bool,
383385
pub has_vector: bool,
384386
pub has_tensor: bool,
@@ -388,6 +390,15 @@ pub struct OctadResponse {
388390
pub has_spatial: bool,
389391
pub version_count: u64,
390392
pub provenance_chain_length: u64,
393+
// Content fields — returned when the modality is populated
394+
#[serde(skip_serializing_if = "Option::is_none")]
395+
pub title: Option<String>,
396+
#[serde(skip_serializing_if = "Option::is_none")]
397+
pub body: Option<String>,
398+
#[serde(skip_serializing_if = "Option::is_none")]
399+
pub metadata: Option<std::collections::HashMap<String, String>>,
400+
#[serde(skip_serializing_if = "Option::is_none")]
401+
pub types: Option<Vec<String>>,
391402
}
392403

393404
/// Status response
@@ -400,6 +411,16 @@ pub struct OctadStatusResponse {
400411

401412
impl From<&verisim_octad::Octad> for OctadResponse {
402413
fn from(h: &verisim_octad::Octad) -> Self {
414+
let (title, body, metadata) = match &h.document {
415+
Some(doc) => (
416+
Some(doc.title.clone()),
417+
if doc.body.is_empty() { None } else { Some(doc.body.clone()) },
418+
if doc.metadata.is_empty() { None } else { Some(doc.metadata.clone()) },
419+
),
420+
None => (None, None, None),
421+
};
422+
let types = h.semantic.as_ref().map(|s| s.types.clone());
423+
403424
Self {
404425
id: h.id.to_string(),
405426
status: OctadStatusResponse {
@@ -416,6 +437,10 @@ impl From<&verisim_octad::Octad> for OctadResponse {
416437
has_spatial: h.spatial_data.is_some(),
417438
version_count: h.version_count,
418439
provenance_chain_length: h.provenance_chain_length,
440+
title,
441+
body,
442+
metadata,
443+
types,
419444
}
420445
}
421446
}

rust-core/verisim-octad/src/store.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -430,11 +430,17 @@ where
430430
&self,
431431
id: &OctadId,
432432
input: &OctadDocumentInput,
433+
extra_metadata: &HashMap<String, String>,
433434
) -> Result<Document, OctadError> {
434435
let mut doc = Document::new(id.as_str(), &input.title, &input.body);
435436
for (key, value) in &input.fields {
436437
doc = doc.with_field(key, value);
437438
}
439+
// Store OctadInput.metadata in Document.metadata so it roundtrips
440+
// through GET responses.
441+
for (key, value) in extra_metadata {
442+
doc.metadata.insert(key.clone(), value.clone());
443+
}
438444

439445
self.document.index(&doc).await.map_err(|e| OctadError::ModalityError {
440446
modality: "document".to_string(),
@@ -804,7 +810,7 @@ where
804810

805811
let mut document = None;
806812
if let Some(ref doc_input) = input.document {
807-
match self.process_document(&id, doc_input).await {
813+
match self.process_document(&id, doc_input, &input.metadata).await {
808814
Ok(doc) => {
809815
document = Some(doc);
810816
modality_status.document = true;
@@ -1050,7 +1056,7 @@ where
10501056

10511057
let mut document = None;
10521058
if let Some(ref doc_input) = input.document {
1053-
match self.process_document(id, doc_input).await {
1059+
match self.process_document(id, doc_input, &input.metadata).await {
10541060
Ok(doc) => {
10551061
document = Some(doc);
10561062
modality_status.document = true;

0 commit comments

Comments
 (0)