From f339a3c4b5a3a4f11bdcfbf7a2a73cc9cd84324f Mon Sep 17 00:00:00 2001 From: pandego <7780875+pandego@users.noreply.github.com> Date: Mon, 20 Apr 2026 13:26:06 +0200 Subject: [PATCH] fix: register conversation event_blobs in fixture bundles Signed-off-by: pandego <7780875+pandego@users.noreply.github.com> --- cxtx/src/conversation_registry_bundle.json | 3 +- fixtures/registry/conversation-bundle.json | 241 +++++++++++++++++++-- scripts/generate-fixtures.sh | 26 +-- server/tests/registry_projection.rs | 88 ++++++++ 4 files changed, 312 insertions(+), 46 deletions(-) diff --git a/cxtx/src/conversation_registry_bundle.json b/cxtx/src/conversation_registry_bundle.json index 0c94543..f4c0ca0 100644 --- a/cxtx/src/conversation_registry_bundle.json +++ b/cxtx/src/conversation_registry_bundle.json @@ -46,7 +46,8 @@ "5": { "name": "agent", "type": "string", "optional": true }, "6": { "name": "turn_number", "type": "int64", "optional": true }, "7": { "name": "max_turns", "type": "int64", "optional": true }, - "8": { "name": "finish_reason", "type": "string", "optional": true } + "8": { "name": "finish_reason", "type": "string", "optional": true }, + "11": { "name": "event_blobs", "type": "map", "optional": true } } } } diff --git a/fixtures/registry/conversation-bundle.json b/fixtures/registry/conversation-bundle.json index 7f224ef..2c87437 100644 --- a/fixtures/registry/conversation-bundle.json +++ b/fixtures/registry/conversation-bundle.json @@ -1,23 +1,224 @@ { - "types": [ - { - "type_id": "cxdb.ConversationItem", - "type_version": 3, - "description": "Canonical conversation turn with role, content, and tool calls", - "fields": [ - {"tag": 1, "name": "role", "type": "string", "semantic": "enum", "required": true}, - {"tag": 2, "name": "content", "type": "string", "required": false}, - {"tag": 3, "name": "tool_calls", "type": "array", "required": false}, - {"tag": 4, "name": "timestamp", "type": "uint64", "semantic": "unix_ms", "required": true} - ] + "registry_version": 1, + "bundle_id": "cxdb.conversation-item.v3.fixture", + "types": { + "cxdb.ConversationItem": { + "versions": { + "3": { + "fields": { + "1": { "name": "item_type", "type": "string" }, + "2": { "name": "status", "type": "string", "optional": true }, + "3": { "name": "timestamp", "type": "timestamp_ms", "optional": true }, + "4": { "name": "id", "type": "string", "optional": true }, + "10": { "name": "user_input", "type": "ref", "ref": "cxdb.UserInput", "optional": true }, + "11": { "name": "turn", "type": "ref", "ref": "cxdb.AssistantTurn", "optional": true }, + "12": { "name": "system", "type": "ref", "ref": "cxdb.SystemMessage", "optional": true }, + "13": { "name": "handoff", "type": "ref", "ref": "cxdb.HandoffInfo", "optional": true }, + "20": { "name": "assistant", "type": "ref", "ref": "cxdb.Assistant", "optional": true }, + "21": { "name": "tool_call", "type": "ref", "ref": "cxdb.ToolCall", "optional": true }, + "22": { "name": "tool_result", "type": "ref", "ref": "cxdb.ToolResult", "optional": true }, + "30": { "name": "context_metadata", "type": "ref", "ref": "cxdb.ContextMetadata", "optional": true } + }, + "renderer": { + "esm_url": "builtin:ConversationRenderer" + } + } + } + }, + "cxdb.UserInput": { + "versions": { + "1": { + "fields": { + "1": { "name": "text", "type": "string" }, + "2": { "name": "files", "type": "array", "items": "string", "optional": true } + } + } + } + }, + "cxdb.AssistantTurn": { + "versions": { + "1": { + "fields": { + "1": { "name": "text", "type": "string" }, + "2": { "name": "tool_calls", "type": "array", "items": { "ref": "cxdb.ToolCallItem" }, "optional": true }, + "3": { "name": "reasoning", "type": "string", "optional": true }, + "4": { "name": "metrics", "type": "ref", "ref": "cxdb.TurnMetrics", "optional": true }, + "5": { "name": "agent", "type": "string", "optional": true }, + "6": { "name": "turn_number", "type": "int64", "optional": true }, + "7": { "name": "max_turns", "type": "int64", "optional": true }, + "8": { "name": "finish_reason", "type": "string", "optional": true }, + "11": { "name": "event_blobs", "type": "map", "optional": true } + } + } + } + }, + "cxdb.ToolCallItem": { + "versions": { + "1": { + "fields": { + "1": { "name": "id", "type": "string" }, + "2": { "name": "name", "type": "string" }, + "3": { "name": "args", "type": "string" }, + "4": { "name": "status", "type": "string" }, + "5": { "name": "description", "type": "string", "optional": true }, + "6": { "name": "streaming_output", "type": "string", "optional": true }, + "7": { "name": "streaming_output_truncated", "type": "bool", "optional": true }, + "8": { "name": "result", "type": "ref", "ref": "cxdb.ToolCallResult", "optional": true }, + "9": { "name": "error", "type": "ref", "ref": "cxdb.ToolCallError", "optional": true }, + "10": { "name": "duration_ms", "type": "int64", "optional": true } + } + } + } + }, + "cxdb.ToolCallResult": { + "versions": { + "1": { + "fields": { + "1": { "name": "content", "type": "string" }, + "2": { "name": "content_truncated", "type": "bool", "optional": true }, + "3": { "name": "success", "type": "bool" }, + "4": { "name": "exit_code", "type": "int64", "optional": true } + } + } + } + }, + "cxdb.ToolCallError": { + "versions": { + "1": { + "fields": { + "1": { "name": "code", "type": "string", "optional": true }, + "2": { "name": "message", "type": "string" }, + "3": { "name": "exit_code", "type": "int64", "optional": true } + } + } + } + }, + "cxdb.TurnMetrics": { + "versions": { + "1": { + "fields": { + "1": { "name": "input_tokens", "type": "int64" }, + "2": { "name": "output_tokens", "type": "int64" }, + "3": { "name": "total_tokens", "type": "int64" }, + "4": { "name": "cached_tokens", "type": "int64", "optional": true }, + "5": { "name": "reasoning_tokens", "type": "int64", "optional": true }, + "6": { "name": "duration_ms", "type": "int64", "optional": true }, + "7": { "name": "model", "type": "string", "optional": true } + } + } + } + }, + "cxdb.SystemMessage": { + "versions": { + "1": { + "fields": { + "1": { "name": "kind", "type": "string" }, + "2": { "name": "title", "type": "string", "optional": true }, + "3": { "name": "content", "type": "string" } + } + } + } + }, + "cxdb.HandoffInfo": { + "versions": { + "1": { + "fields": { + "1": { "name": "from_agent", "type": "string" }, + "2": { "name": "to_agent", "type": "string" }, + "3": { "name": "tool_name", "type": "string", "optional": true }, + "4": { "name": "input", "type": "string", "optional": true }, + "5": { "name": "reason", "type": "string", "optional": true } + } + } + } + }, + "cxdb.Assistant": { + "versions": { + "1": { + "fields": { + "1": { "name": "text", "type": "string" }, + "2": { "name": "reasoning", "type": "string", "optional": true }, + "3": { "name": "model", "type": "string", "optional": true }, + "4": { "name": "input_tokens", "type": "int64", "optional": true }, + "5": { "name": "output_tokens", "type": "int64", "optional": true }, + "6": { "name": "stop_reason", "type": "string", "optional": true } + } + } + } + }, + "cxdb.ToolCall": { + "versions": { + "1": { + "fields": { + "1": { "name": "call_id", "type": "string" }, + "2": { "name": "name", "type": "string" }, + "3": { "name": "args", "type": "string" }, + "4": { "name": "description", "type": "string", "optional": true } + } + } + } + }, + "cxdb.ToolResult": { + "versions": { + "1": { + "fields": { + "1": { "name": "call_id", "type": "string" }, + "2": { "name": "content", "type": "string" }, + "3": { "name": "is_error", "type": "bool" }, + "4": { "name": "exit_code", "type": "int64", "optional": true }, + "5": { "name": "streaming_output", "type": "string", "optional": true }, + "6": { "name": "output_truncated", "type": "bool", "optional": true }, + "7": { "name": "duration_ms", "type": "int64", "optional": true } + } + } + } + }, + "cxdb.ContextMetadata": { + "versions": { + "1": { + "fields": { + "1": { "name": "client_tag", "type": "string", "optional": true }, + "2": { "name": "title", "type": "string", "optional": true }, + "3": { "name": "labels", "type": "array", "items": "string", "optional": true }, + "4": { "name": "custom", "type": "map", "optional": true }, + "10": { "name": "provenance", "type": "ref", "ref": "cxdb.Provenance", "optional": true } + } + } + } + }, + "cxdb.Provenance": { + "versions": { + "1": { + "fields": { + "1": { "name": "parent_context_id", "type": "u64", "optional": true }, + "2": { "name": "spawn_reason", "type": "string", "optional": true }, + "3": { "name": "root_context_id", "type": "u64", "optional": true }, + "10": { "name": "trace_id", "type": "string", "optional": true }, + "11": { "name": "span_id", "type": "string", "optional": true }, + "12": { "name": "correlation_id", "type": "string", "optional": true }, + "20": { "name": "on_behalf_of", "type": "string", "optional": true }, + "21": { "name": "on_behalf_of_source", "type": "string", "optional": true }, + "22": { "name": "on_behalf_of_email", "type": "string", "optional": true }, + "30": { "name": "writer_method", "type": "string", "optional": true }, + "31": { "name": "writer_subject", "type": "string", "optional": true }, + "32": { "name": "writer_issuer", "type": "string", "optional": true }, + "40": { "name": "service_name", "type": "string", "optional": true }, + "41": { "name": "service_version", "type": "string", "optional": true }, + "42": { "name": "service_instance_id", "type": "string", "optional": true }, + "43": { "name": "process_pid", "type": "int64", "optional": true }, + "44": { "name": "process_owner", "type": "string", "optional": true }, + "45": { "name": "host_name", "type": "string", "optional": true }, + "46": { "name": "host_arch", "type": "string", "optional": true }, + "50": { "name": "client_address", "type": "string", "optional": true }, + "51": { "name": "client_port", "type": "int64", "optional": true }, + "60": { "name": "env_vars", "type": "map", "optional": true }, + "70": { "name": "sdk_name", "type": "string", "optional": true }, + "71": { "name": "sdk_version", "type": "string", "optional": true }, + "80": { "name": "captured_at", "type": "timestamp_ms", "optional": true } + } + } + } } - ], - "renderers": [ - { - "type_id": "cxdb.ConversationItem", - "type_version": 3, - "url": "https://your-cdn.com/conversation-renderer.js", - "integrity": "" - } - ] + }, + "enums": {} } diff --git a/scripts/generate-fixtures.sh b/scripts/generate-fixtures.sh index 01387d3..d226802 100755 --- a/scripts/generate-fixtures.sh +++ b/scripts/generate-fixtures.sh @@ -84,31 +84,7 @@ EOF echo " Created: log-entry-bundle.json" # ConversationItem type bundle -cat > "$FIXTURES_DIR/registry/conversation-bundle.json" <<'EOF' -{ - "types": [ - { - "type_id": "cxdb.ConversationItem", - "type_version": 3, - "description": "Canonical conversation turn with role, content, and tool calls", - "fields": [ - {"tag": 1, "name": "role", "type": "string", "semantic": "enum", "required": true}, - {"tag": 2, "name": "content", "type": "string", "required": false}, - {"tag": 3, "name": "tool_calls", "type": "array", "required": false}, - {"tag": 4, "name": "timestamp", "type": "uint64", "semantic": "unix_ms", "required": true} - ] - } - ], - "renderers": [ - { - "type_id": "cxdb.ConversationItem", - "type_version": 3, - "url": "https://your-cdn.com/conversation-renderer.js", - "integrity": "" - } - ] -} -EOF +cp "$ROOT_DIR/cxtx/src/conversation_registry_bundle.json" "$FIXTURES_DIR/registry/conversation-bundle.json" echo " Created: conversation-bundle.json" diff --git a/server/tests/registry_projection.rs b/server/tests/registry_projection.rs index 09843cb..b08baf5 100644 --- a/server/tests/registry_projection.rs +++ b/server/tests/registry_projection.rs @@ -513,6 +513,94 @@ fn array_shorthand_ref_recursively_projects() { ); } +#[test] +fn nested_event_blobs_field_projects_in_typed_view() { + let dir = tempdir().expect("tempdir"); + let mut registry = Registry::open(dir.path()).expect("open registry"); + + let bundle = r#" + { + "registry_version": 1, + "bundle_id": "conversation-event-blobs-test", + "types": { + "cxdb.ConversationItem": { + "versions": { + "3": { + "fields": { + "1": { "name": "item_type", "type": "string" }, + "11": { "name": "turn", "type": "ref", "ref": "cxdb.AssistantTurn", "optional": true } + } + } + } + }, + "cxdb.AssistantTurn": { + "versions": { + "1": { + "fields": { + "1": { "name": "text", "type": "string" }, + "11": { "name": "event_blobs", "type": "map", "optional": true } + } + } + } + } + }, + "enums": {} + } + "#; + + registry + .put_bundle("conversation-event-blobs-test", bundle.as_bytes()) + .expect("put bundle"); + let desc = registry + .get_type_version("cxdb.ConversationItem", 3) + .expect("descriptor"); + + let event_blobs = vec![( + Value::String("request".into()), + Value::Array(vec![ + Value::Binary(vec![0xAA, 0xBB, 0xCC]), + Value::Binary(vec![0x01, 0x02, 0x03]), + ]), + )]; + let turn_map = vec![ + (Value::Integer(1.into()), Value::String("done".into())), + (Value::Integer(11.into()), Value::Map(event_blobs)), + ]; + let root_map = vec![ + ( + Value::Integer(1.into()), + Value::String("assistant_turn".into()), + ), + (Value::Integer(11.into()), Value::Map(turn_map)), + ]; + let value = Value::Map(root_map); + + let mut buf = Vec::new(); + rmpv::encode::write_value(&mut buf, &value).expect("encode msgpack"); + + let projection = project_msgpack(&buf, desc, ®istry, &default_options()).expect("project"); + let data = projection.data.as_object().expect("data object"); + let turn = data + .get("turn") + .expect("turn field present") + .as_object() + .expect("turn is object"); + let event_blobs = turn + .get("event_blobs") + .expect("event_blobs field present") + .as_object() + .expect("event_blobs is object"); + let request = event_blobs + .get("request") + .expect("request key present") + .as_array() + .expect("request is array"); + + assert_eq!(request.len(), 2); + assert_eq!(request[0].as_str().unwrap(), "qrvM"); + assert_eq!(request[1].as_str().unwrap(), "AQID"); +} + // --------------------------------------------------------------------------- // Tests for include_unknown propagation into nested types // ---------------------------------------------------------------------------