Real-time index of opencode sessions
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Introduce canonical key and stage contract types

Add shared key types (SessionKey, MessageKey, PartKey, EntityKey) and shared stage/report envelope types (StageName, StageIssue, StageReport, StageResult). These are the foundation for recomb-based API convergence across index, flow, and planned CDC layers.

Also restore src/index.rs after earlier intermediate deletion so the crate continues to compile while we iterate toward papaya-backed registries and zero-copy reference trees.

rektide 53cb8fef 9e37815e

+142
+1
Cargo.toml
··· 21 21 watchman_client = { version = "0.1", optional = true } 22 22 notify = { version = "8", optional = true } 23 23 bon = "3.9.0" 24 + papaya = "0.2.3" 24 25 25 26 [features] 26 27 default = []
+54
src/key.rs
··· 1 + use crate::id::{MessageId, PartId, SessionId}; 2 + 3 + #[derive(Debug, Clone, PartialEq, Eq, Hash)] 4 + pub struct SessionKey { 5 + pub project_id: String, 6 + pub session_id: SessionId, 7 + } 8 + 9 + impl SessionKey { 10 + pub fn new(project_id: impl Into<String>, session_id: SessionId) -> Self { 11 + Self { 12 + project_id: project_id.into(), 13 + session_id, 14 + } 15 + } 16 + } 17 + 18 + #[derive(Debug, Clone, PartialEq, Eq, Hash)] 19 + pub struct MessageKey { 20 + pub session_id: SessionId, 21 + pub message_id: MessageId, 22 + } 23 + 24 + impl MessageKey { 25 + pub fn new(session_id: SessionId, message_id: MessageId) -> Self { 26 + Self { 27 + session_id, 28 + message_id, 29 + } 30 + } 31 + } 32 + 33 + #[derive(Debug, Clone, PartialEq, Eq, Hash)] 34 + pub struct PartKey { 35 + pub message_id: MessageId, 36 + pub part_id: PartId, 37 + } 38 + 39 + impl PartKey { 40 + pub fn new(message_id: MessageId, part_id: PartId) -> Self { 41 + Self { 42 + message_id, 43 + part_id, 44 + } 45 + } 46 + } 47 + 48 + #[derive(Debug, Clone, PartialEq, Eq, Hash)] 49 + pub enum EntityKey { 50 + Session(SessionKey), 51 + Message(MessageKey), 52 + Part(PartKey), 53 + SessionDiff { session_id: SessionId }, 54 + }
+4
src/lib.rs
··· 1 1 pub mod error; 2 2 pub mod id; 3 3 pub mod index; 4 + pub mod key; 4 5 pub mod loader; 5 6 pub mod materializer; 7 + pub mod stage; 6 8 pub mod storage; 7 9 pub mod types; 8 10 ··· 14 16 pub use index::{ 15 17 MessageMeta, MessageRole, PartKind, PartRef, SessionIndex, SessionIndexBuilder, SessionMeta, 16 18 }; 19 + pub use key::{EntityKey, MessageKey, PartKey, SessionKey}; 17 20 pub use loader::{LoadedSession, MessageWithParts, SessionLoader, SessionTree}; 18 21 pub use materializer::{ 19 22 MessageFlowScope, SessionFlowOptions, SessionFlowResult, SessionFlowScope, SessionMaterializer, 20 23 Stats as MaterializerStats, 21 24 }; 25 + pub use stage::{IssueKind, StageIssue, StageName, StageReport, StageResult}; 22 26 pub use storage::{FileReader, MappedFile, MappedFileCache, StoragePaths}; 23 27 pub use types::{ 24 28 message::{AssistantMessage, FileDiff, Message, UserMessage},
+83
src/stage.rs
··· 1 + use crate::key::EntityKey; 2 + use std::path::PathBuf; 3 + 4 + #[derive(Debug, Clone, Copy, PartialEq, Eq)] 5 + pub enum StageName { 6 + Plan, 7 + Resolve, 8 + Hydrate, 9 + } 10 + 11 + #[derive(Debug, Clone, Copy, PartialEq, Eq)] 12 + pub enum IssueKind { 13 + NotFound, 14 + InvalidReference, 15 + ParseError, 16 + Io, 17 + } 18 + 19 + #[derive(Debug, Clone)] 20 + pub struct StageIssue { 21 + pub stage: StageName, 22 + pub key: Option<EntityKey>, 23 + pub path: Option<PathBuf>, 24 + pub kind: IssueKind, 25 + pub message: String, 26 + } 27 + 28 + #[derive(Debug, Clone)] 29 + pub struct StageReport { 30 + pub stage: StageName, 31 + pub attempted: usize, 32 + pub succeeded: usize, 33 + pub issues: Vec<StageIssue>, 34 + } 35 + 36 + impl StageReport { 37 + pub fn new(stage: StageName) -> Self { 38 + Self { 39 + stage, 40 + attempted: 0, 41 + succeeded: 0, 42 + issues: Vec::new(), 43 + } 44 + } 45 + 46 + pub fn push_issue( 47 + &mut self, 48 + key: Option<EntityKey>, 49 + path: Option<PathBuf>, 50 + kind: IssueKind, 51 + message: impl Into<String>, 52 + ) { 53 + self.issues.push(StageIssue { 54 + stage: self.stage, 55 + key, 56 + path, 57 + kind, 58 + message: message.into(), 59 + }); 60 + } 61 + } 62 + 63 + #[derive(Debug, Clone)] 64 + pub struct StageResult<T> { 65 + pub value: T, 66 + pub report: StageReport, 67 + pub generation: Option<u64>, 68 + } 69 + 70 + impl<T> StageResult<T> { 71 + pub fn new(value: T, report: StageReport) -> Self { 72 + Self { 73 + value, 74 + report, 75 + generation: None, 76 + } 77 + } 78 + 79 + pub fn with_generation(mut self, generation: u64) -> Self { 80 + self.generation = Some(generation); 81 + self 82 + } 83 + }