# kcode-kennedy-sessions 0.1.2
`kcode-kennedy-sessions` runs one Kennedy logical session. It owns session policy, context recovery, Kweb write staging, tool dispatch, provider-loop hosting, checkpoints, and final write-session commit.
## Public API
```rust
pub use kcode_telegram_session_coordinator::validate_file_name
as validate_delivery_file_name;
#[derive(Clone)]
pub struct Service { /* private shared capability handles */ }
pub struct Capabilities {
pub kmap: kcode_kweb_manager::KwebManager,
pub intelligence: kcode_intelligence_router::Intelligence,
pub history: kcode_session_history::SessionHistory,
pub speech_classifier: Arc<kcode_speech_classification::SpeechClassifier>,
pub dev_tools: kcode_dev_tools::Service,
pub agents: kcode_agent_runtime::AgentRuntime,
pub telegram: kcode_telegram_session_coordinator::Service,
}
impl Service {
pub fn new(capabilities: Capabilities) -> Self;
}
pub struct RuntimeModel {
pub model: String,
pub reasoning_effort: String,
pub context_window_tokens: u64,
}
impl RuntimeModel {
pub fn from_intelligence(
runtime: kcode_intelligence_router::RuntimeModel,
) -> Self;
}
pub enum AgentMode {
Conversation,
FreeTime,
Wakeup,
Ingress { record_id: Option<String> },
}
pub struct SessionOptions {
pub session_type: String,
pub root_node_ids: Vec<String>,
pub reference_root_node_ids: Vec<String>,
pub channel: serde_json::Value,
pub free_time: serde_json::Value,
pub orchestration: serde_json::Value,
pub provenance_id: Option<String>,
pub mode: AgentMode,
pub source_session_type: Option<String>,
pub group_context: serde_json::Value,
pub rust_lib_session_id: Option<String>,
}
impl SessionOptions {
pub fn conversation(
session_type: impl Into<String>,
roots: Vec<String>,
) -> Self;
}
pub struct ResolvedObject {
pub object_id: String,
pub bytes: Vec<u8>,
pub file_name: String,
pub media_type: String,
pub transport_kind: Option<String>,
}
pub struct Session {
pub session_type: String,
pub channel: serde_json::Value,
pub free_time: serde_json::Value,
pub orchestration: serde_json::Value,
pub provenance_id: Option<String>,
pub rust_lib_session_id: String,
pub root_node_ids: Vec<String>,
pub reference_root_node_ids: Vec<String>,
pub started_at: String,
pub transcript: Vec<serde_json::Value>,
pub pending_turn: bool,
pub pending_external_event_id: Option<String>,
pub completed: bool,
pub rounds_used: u64,
// remaining runtime, journal, Kweb-plan, mode, context, and commit state is private
}
impl Session {
pub async fn new(
service: Service,
system_prompt: String,
runtime: RuntimeModel,
options: SessionOptions,
restored: Option<&serde_json::Value>,
) -> anyhow::Result<Self>;
pub fn append_final_user_message(
&mut self,
text: &str,
metadata: &serde_json::Value,
) -> bool;
pub fn stage_source_message(
&mut self,
kennedy: bool,
text: &str,
metadata: serde_json::Value,
) -> anyhow::Result<()>;
pub fn answer_for_external_event(
&self,
id: &str,
) -> Option<&serde_json::Value>;
pub fn responses_for_external_event(
&self,
id: &str,
) -> Vec<&serde_json::Value>;
pub fn resolve_object(
&mut self,
object_id: &str,
) -> anyhow::Result<ResolvedObject>;
pub fn requires_history_ingress(&self) -> bool;
pub fn stage_free_time_opening(&mut self) -> bool;
pub fn stage_wakeup_opening(&mut self) -> anyhow::Result<bool>;
pub fn begin_user_turn(
&mut self,
text: &str,
metadata: &serde_json::Value,
) -> bool;
pub fn reset_exhausted_turn_rounds_for_retry(&mut self);
pub fn interrupt_current_turn(&mut self) -> anyhow::Result<()>;
pub async fn run_pending_turn<C, F>(
&mut self,
operation_id: uuid::Uuid,
checkpoint: C,
) -> anyhow::Result<Option<String>>
where
C: FnMut(serde_json::Value) -> F + Send,
F: Future<Output = anyhow::Result<()>> + Send;
pub fn refresh_telegram_group_context(
&mut self,
group_context: &serde_json::Value,
current_message_id: Option<&str>,
) -> anyhow::Result<()>;
pub fn finalize_free_time(
&mut self,
reason: &str,
) -> anyhow::Result<()>;
pub fn commit_current_write_session(&mut self) -> anyhow::Result<()>;
pub fn snapshot(&self) -> anyhow::Result<serde_json::Value>;
pub async fn release_managed_sources(&self);
}
```
## Construction and lifecycle
`SessionOptions::conversation` creates an idle conversation with ordered writable roots. Reference roots are sorted, deduplicated, and removed when also writable. Callers may edit the other option fields before construction. `system_prompt` must already be fully composed, and `RuntimeModel` must contain the selected model, reasoning effort, and verified context window.
`Session::new` creates or reopens the durable Session History journal, restores compatible state, loads the Kweb roots, and prepares history ingress when requested. `AgentMode` controls completion: conversations may remain open; free-time, wakeup, and ingress sessions finalize their staged Kweb transaction when their run ends.
`begin_user_turn` rejects empty input or an already-pending turn. It durably stages text and attachments, records an optional `externalEventId`, resets round accounting, and opens a turn. `append_final_user_message` stages a final source message without opening a turn. `stage_source_message` stages an explicitly user- or Kennedy-owned message. These operations apply normal context recovery.
`stage_free_time_opening` and `stage_wakeup_opening` run at most once while a turn is pending. Wakeup requires an RFC 3339 `channel.wakeupMarker`. `interrupt_current_turn` repairs unfinished tool records, records a user-stop notice, and returns the session to idle. `reset_exhausted_turn_rounds_for_retry` affects only an exhausted conversation.
`run_pending_turn` returns `Ok(None)` without work when no turn is pending. Otherwise it runs the provider loop and invokes `checkpoint` with a complete snapshot after each durable semantic transition; callback failure aborts the run. A conversation returns `Ok(Some(answer))` for a new terminal text answer. `Ok(None)` means an object/tool already responded, the source terminated, or a non-conversation mode completed. The supplied operation ID owns cancellation lineage for provider and descendant work.
## Objects, events, and completion
`resolve_object` accepts a session-pending object ID or canonical Kweb object ID and returns exact bytes plus authoritative delivery metadata. Resolving canonical objects does not stage or commit them. `validate_delivery_file_name` validates bounded, path-free recipient-visible filenames.
`answer_for_external_event` returns the newest terminal response for an exact event ID. `responses_for_external_event` returns all Kennedy/system responses for that event in transcript order. `refresh_telegram_group_context` is a no-op outside Telegram-group sessions; in a group it replaces channel context, adds a controller update, and applies context recovery.
`requires_history_ingress` is true only for a conversation whose source has terminated. `finalize_free_time` accepts exactly `tool`, `deadline`, `hard-stop`, or `user-stop`. `commit_current_write_session` is valid only for free-time, wakeup, or ingress and atomically finalizes staged Kweb writes. `release_managed_sources` releases this session's managed-development leases.
`snapshot` is the complete opaque recovery checkpoint. Persist it as a unit and pass it back to `Session::new`; do not independently edit its journal, Kweb plan, boxes, or events.
## Authority and persistence
Session History owns the durable journal, staged objects, and archive. Kweb Manager owns database reads and writes; durable read projection and legacy node decoding are delegated to the read-only Kweb loader. Agent runtime owns provider execution, and the Telegram coordinator owns delivery and Telegram context. The application retains prompt composition, roots and runtime selection, transport scheduling, retry policy, and persistence of checkpoint values. This crate retains session policy, Kweb write staging, tool authorization and dispatch, context recovery, and final commit.