1pub mod attachments;
2pub mod chronological;
3pub mod direct;
4pub mod lashlang_bridge;
5pub mod llm;
6mod model;
7pub mod plugin;
8mod plugin_stack;
9mod protocol_build;
10pub mod provider;
11pub mod runtime;
12pub mod search;
13pub mod session;
14pub mod session_graph;
15pub mod session_model;
16mod stable_hash;
17pub mod store;
18#[cfg(any(test, feature = "testing"))]
19pub mod testing;
20pub mod tool_dispatch;
21mod tool_provider;
22pub mod tool_registry;
23mod tool_result;
24mod trace;
25pub mod triggers;
26
27pub use lash_sansio::sansio;
28
29pub const VERSION: &str = env!("CARGO_PKG_VERSION");
30pub const SANSIO_VERSION: &str = lash_sansio::VERSION;
31
32pub use attachments::{
34 AttachmentStore, AttachmentStoreError, AttachmentStorePersistence, FileAttachmentStore,
35 InMemoryAttachmentStore, SessionScopedAttachmentStore, StoredAttachment,
36};
37pub use chronological::{
41 BorrowedChronologicalEntry, BorrowedChronologicalMessage, BorrowedChronologicalPayload,
42 ChronologicalEntry, ChronologicalPayload, ChronologicalProjection, visit_turn_view,
43};
44pub use direct::{
45 DirectJsonSchema, DirectLlmClient, DirectLlmError, DirectMessage, DirectOutputSpec, DirectPart,
46 DirectRequest, DirectRole,
47};
48pub use lash_sansio::llm::types::{
49 GenerationOptions, LlmOutputPart, LlmRequest, LlmResponse, LlmTerminalReason,
50};
51pub use lash_sansio::{
52 AcceptedInjectedTurnInput, AttachmentCreateMeta, AttachmentId, AttachmentMeta, AttachmentRef,
53 BaseRenderCache, CheckpointDelivery, CheckpointKind, CompactToolContract, EffectId,
54 ErrorEnvelope, ExecImage, ExecResponse, ImageMediaType, LashSchema, LashlangToolBinding,
55 LlmCallError, MediaType, Message, MessageOrigin, MessageRole, MessageSequence, ModelToolReturn,
56 ModelToolReturnPart, Part, PartKind, PluginMessage, PluginRuntimeEvent, PreparedPrompt,
57 PromptBuildInput, PromptBuiltin, PromptContext, PromptContribution, PromptContributionGate,
58 PromptContributionSet, PromptFingerprint, PromptLayer, PromptSlot, PromptSlotLayer,
59 PromptTemplate, PromptTemplateEntry, PromptTemplateSection, PruneState, RenderedPrompt,
60 ResolvedLashlangToolBinding, ResolvedPromptLayer, Response, SchemaProjectionOverride,
61 SessionEvent, TextProjectionMetadata, TokenUsage, ToolActivation, ToolArgumentProjectionPolicy,
62 ToolAvailability, ToolAvailabilityConfig, ToolCallOutcome, ToolCallOutput, ToolCallRecord,
63 ToolCallStatus, ToolCancellation, ToolCatalog, ToolCatalogBuildInput, ToolCatalogEntry,
64 ToolCatalogOverride, ToolContract, ToolControl, ToolDefinition, ToolFailure, ToolFailureClass,
65 ToolFailureSource, ToolId, ToolManifest, ToolOutputContract, ToolRetryDisposition,
66 ToolRetryPolicy, ToolScheduling, ToolValue, TurnCause, TurnFinish, TurnLimitFinalMessage,
67 TurnOutcome, TurnStop, append_assistant_text_part, build_prompt, build_tool_catalog,
68 build_turn, default_prompt_template, head_tail_truncate, messages_are_prompt_resume_safe,
69 normalized_response_parts, prompt_template_fingerprint, prompt_text_fingerprint,
70 prompt_tool_names_fingerprint, reasoning_part, render_turn_causes_prompt,
71 resolve_prompt_layers, shared_parts, validate_tool_input,
72};
73pub use lashlang::{DurabilityTier, InMemoryLashlangArtifactStore, LashlangArtifactStore};
74pub use protocol_build::ProtocolBuildInput;
75pub use tool_registry::{
76 ReconfigureError, ToolRegistry, ToolRestoreReport, ToolSourceHandle, ToolState, ToolStateEntry,
77};
78pub use tool_result::{CancelHint, PendingCompletion, TimeoutBehavior, ToolResult};
79pub use triggers::{
80 InMemoryTriggerStore, TriggerDeliveryReservation, TriggerEmitReport, TriggerEvent,
81 TriggerEventCatalog, TriggerEventKey, TriggerEventType, TriggerOccurrenceRecord,
82 TriggerOccurrenceRequest, TriggerRegistration, TriggerRouter, TriggerStore,
83 TriggerSubscriptionDraft, TriggerSubscriptionFilter, TriggerSubscriptionRecord,
84 TriggerTargetSummary, default_trigger_source_key, deterministic_delivery_process_id,
85 deterministic_occurrence_id, empty_trigger_source_key, trigger_event_type,
86 trigger_occurrence_request_hash, validate_payload, validate_trigger_occurrence_request,
87};
88#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
89pub struct ProtocolTurnOptions {
90 #[serde(default = "empty_protocol_turn_payload")]
91 pub payload: serde_json::Value,
92}
93
94fn empty_protocol_turn_payload() -> serde_json::Value {
95 serde_json::Value::Object(serde_json::Map::new())
96}
97
98impl Default for ProtocolTurnOptions {
99 fn default() -> Self {
100 Self::empty()
101 }
102}
103
104impl ProtocolTurnOptions {
105 pub fn empty() -> Self {
106 Self {
107 payload: serde_json::Value::Object(serde_json::Map::new()),
108 }
109 }
110
111 pub fn is_empty(&self) -> bool {
112 match &self.payload {
113 serde_json::Value::Object(map) => map.is_empty(),
114 _ => false,
115 }
116 }
117
118 pub fn merged_with_override(&self, override_options: &Self) -> Self {
119 match (&self.payload, &override_options.payload) {
120 (serde_json::Value::Object(base), serde_json::Value::Object(overrides)) => {
121 let mut payload = base.clone();
122 payload.extend(overrides.clone());
123 Self {
124 payload: serde_json::Value::Object(payload),
125 }
126 }
127 _ => override_options.clone(),
128 }
129 }
130
131 pub fn typed<T>(value: T) -> Result<Self, serde_json::Error>
132 where
133 T: serde::Serialize,
134 {
135 Ok(Self {
136 payload: serde_json::to_value(value)?,
137 })
138 }
139
140 pub fn decode<T>(&self) -> Result<T, serde_json::Error>
141 where
142 T: serde::de::DeserializeOwned,
143 {
144 serde_json::from_value(self.payload.clone())
145 }
146}
147
148#[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
149pub struct ProtocolDriverState {
150 pub plugin_id: String,
151 pub payload: serde_json::Value,
152}
153
154impl ProtocolDriverState {
155 pub fn new(plugin_id: impl Into<String>, payload: serde_json::Value) -> Self {
156 Self {
157 plugin_id: plugin_id.into(),
158 payload,
159 }
160 }
161}
162
163#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
164pub struct HostTurnProtocol;
165
166impl lash_sansio::TurnProtocol for HostTurnProtocol {
167 type Event = crate::session_model::ProtocolEvent;
168 type Termination = ProtocolTurnOptions;
169 type DriverState = ProtocolDriverState;
170}
171
172pub type Effect = lash_sansio::Effect<HostTurnProtocol>;
173pub type DriverAction = lash_sansio::DriverAction<HostTurnProtocol>;
174pub type DriverContextView<'a> = lash_sansio::DriverContextView<'a, HostTurnProtocol>;
175pub type TurnDriverConfig = lash_sansio::TurnDriverConfig<HostTurnProtocol>;
176pub type TurnDriverPreamble = lash_sansio::TurnDriverPreamble<HostTurnProtocol>;
177pub type ProjectorContext<'a> = lash_sansio::ProjectorContext<'a, HostTurnProtocol>;
178pub type PreparedTurnMachine = lash_sansio::PreparedTurnMachine<HostTurnProtocol>;
179pub type SansIoTurnInput = lash_sansio::SansIoTurnInput<HostTurnProtocol>;
180pub type TurnMachine = lash_sansio::TurnMachine<HostTurnProtocol>;
181pub type TurnMachineConfig = lash_sansio::TurnMachineConfig<HostTurnProtocol>;
182#[cfg(feature = "otel-trace")]
183pub use lash_trace::otel::{OtelTraceOptions, OtelTraceSink};
184pub use lash_trace::{
185 JsonlTraceSink, TraceAttachment, TraceBranchSelection, TraceContentBlock, TraceContext,
186 TraceError, TraceEvent, TraceLabelMetadata, TraceLashlangChildExecution,
187 TraceLashlangEdgeSelection, TraceLashlangExecutionEvent, TraceLashlangExecutionIdentity,
188 TraceLashlangGraph, TraceLashlangGraphChildLink, TraceLashlangGraphEdge,
189 TraceLashlangGraphNode, TraceLashlangGraphStore, TraceLashlangMap, TraceLashlangMapEdge,
190 TraceLashlangMapNode, TraceLashlangNodeStatus, TraceLashlangStatus, TraceLevel,
191 TraceLlmMessage, TraceLlmRequest, TraceLlmResponse, TracePromptComponent,
192 TraceProviderStreamEvent, TraceRecord, TraceRuntimeScope, TraceRuntimeStreamEvent,
193 TraceRuntimeSubject, TraceSink, TraceSinkError, TraceTokenUsage, TraceToolSpec,
194};
195pub use llm::transport::{LlmTransportError, ProviderFailure, ProviderFailureKind};
196pub use model::{ModelLimits, ModelSpec};
197pub use plugin::{
198 AgentFrameAssignment, AgentFrameId, AgentFrameReason, AgentFrameRecord, AgentFrameStatus,
199 AppendSessionNodesRequest, AppendSessionNodesResult, AssistantResponseHookContext,
200 AssistantResponseTransform, AssistantStreamHookContext, AssistantStreamTransform,
201 CheckpointHookContext, CompactionContext, ContextCompaction, ContextCompactor, ContextError,
202 ContextRegistrations, DirectCompletion, DirectLlmCompletion, OpenAgentFrameRequest,
203 OpenAgentFrameResult, PersistentRuntimeServices, PluginAction, PluginActionContext,
204 PluginActionDef, PluginActionFailure, PluginActionInvokeError, PluginActionKind,
205 PluginDirective, PluginError, PluginFactory, PluginHost, PluginLifecycleEvent,
206 PluginLifecycleEventHook, PluginOptions, PluginOwned, PluginRegistrar, PluginSession,
207 PluginSessionContext, PluginSessionSnapshot, PluginSnapshotArtifact, PluginSnapshotEntry,
208 PluginSnapshotMeta, PluginSpec, PluginSpecFactory, PromptHookContext,
209 ProtocolBeforeLlmCallContext, ProtocolLlmCallAction, RuntimeServices, SessionAppendNode,
210 SessionConfigChangedContext, SessionContextOverlay, SessionCreateRequest, SessionGraphService,
211 SessionHandle, SessionLifecycleService, SessionParam, SessionPlugin, SessionPluginSource,
212 SessionReadView, SessionRelation, SessionSnapshot, SessionStartPoint,
213 SessionStateChangedContext, SessionStateService, SessionToolAccess, SessionTurnInput,
214 SessionTurnRequest, SnapshotReader, SnapshotWriter, SubagentSessionContext,
215 ToolCatalogContribution, ToolDiscoveryContext, ToolDiscoveryContribution,
216 ToolDiscoveryContributor, ToolDiscoveryToolContribution, ToolResultProjectionContext,
217 ToolResultProjector, TriggerEventRegistrations, TurnContextTransform, TurnHookContext,
218 TurnResultHookContext, TurnResultSummary, TurnTransformContext, plugin_action_def,
219};
220pub use plugin_stack::PluginStack;
221pub use provider::{
222 CacheRetention, EmptyProviderResolver, LlmTimeouts, MapProviderResolver, Provider,
223 ProviderBinding, ProviderComponents, ProviderFactory, ProviderHandle, ProviderModelPolicy,
224 ProviderOptions, ProviderResolutionError, ProviderSpec, RequestTimeout,
225 RuntimeProviderResolver, SingleProviderResolver, StaticModelPolicy,
226};
227#[cfg(any(test, feature = "testing"))]
228pub use runtime::TestLocalProcessRegistry;
229pub use runtime::{
230 AgentFrameRun, AssembledTurn, AssistantOutput, AwaitEventKey, AwaitEventWaitIdentity,
231 CausalRef, CodeOutputRecord, DefaultProcessCancelAbility, DeliveryPolicy,
232 DirectCompletionClient, DurableProcessWorker, DurableProcessWorkerConfig, DurableStoreFacet,
233 EffectHost, EmbeddedRuntimeBuilder, EmbeddedRuntimeHost, EventSink, ExecutionScope,
234 ExecutionSummary, ExternalCompletionError, InMemoryLiveReplayStore,
235 InMemoryLiveReplayStoreConfig, InMemorySessionStore, InMemorySessionStoreFactory,
236 InlineEffectHost, InlineProcessRunHandle, InlineRuntimeEffectController, InputItem,
237 LashRuntime, LiveReplayGap, LiveReplayGapReason, LiveReplayResult, LiveReplayStore,
238 LiveReplayStoreError, LiveReplaySubscribeResult, LiveReplaySubscription, MergeKey,
239 NoopEventSink, NoopTurnActivitySink, ObservedProcess, ObservedProcessEvent, ObservedWorkItem,
240 OutputState, PROCESS_LEASE_SCHEMA_VERSION, ParkedSession, ProcessAwaitOutput,
241 ProcessCancelAbility, ProcessCancelAllRequest, ProcessCancelRequest, ProcessCancelSource,
242 ProcessCancelSummary, ProcessDefinitionSelector, ProcessDefinitionSummary, ProcessEvent,
243 ProcessEventAppendRequest, ProcessEventAppendResult, ProcessEventType, ProcessExecutionContext,
244 ProcessExecutionEnvRef, ProcessExecutionEnvSpec, ProcessExternalRef, ProcessHandleDescriptor,
245 ProcessHandleGrant, ProcessHandleSummary, ProcessId, ProcessInput, ProcessLease,
246 ProcessLeaseCompletion, ProcessLifecycleStatus, ProcessListFilter, ProcessListMode,
247 ProcessOpScope, ProcessOriginator, ProcessProvenance, ProcessRecord, ProcessRegistration,
248 ProcessRegistry, ProcessRunHandle, ProcessRuntimeHost, ProcessService,
249 ProcessSessionDeleteReport, ProcessSpawnProvenance, ProcessStartGrant, ProcessStartOptions,
250 ProcessStartRequest, ProcessStatus, ProcessStatusFilter, ProcessTerminalSemantics,
251 ProcessTerminalSpec, ProcessTerminalState, ProcessValueSelector, ProcessWake,
252 ProcessWakeDedupeKey, ProcessWakeDelivery, ProcessWakeSpec, ProcessWorkDriver,
253 ProcessWorkObserver, ProcessWorkPoke, ProcessWorkRunner, ProcessWorkSnapshot, PromptUsage,
254 ProtocolSessionExtension, ProtocolSessionExtensionHandle, ProtocolTurnExtension,
255 ProtocolTurnExtensionHandle, QueuedWorkPoke, QueuedWorkRunHandle, QueuedWorkRunOutcome,
256 QueuedWorkRunRequest, QueuedWorkRunner, Residency, Resolution, ResolveOutcome,
257 RuntimeEnvironment, RuntimeEnvironmentBuilder, RuntimeError, RuntimeErrorCode, RuntimeHandle,
258 RuntimeHostConfig, RuntimeObservation, ScopedEffectController, SessionCommand,
259 SessionCommandReceipt, SessionCursor, SessionCursorError, SessionObservation,
260 SessionObservationEvent, SessionObservationEventPayload, SessionObservationSubscription,
261 SessionProcessEventKind, SessionQueueEventKind, SessionResume, SessionRevision, SessionScope,
262 SessionScopeId, SessionStoreCreateRequest, SessionStoreFactory, SessionUsageReport, SlotPolicy,
263 TerminationPolicy, TokenLedgerEntry, ToolCallLaunch, TurnActivity, TurnActivityId,
264 TurnActivitySink, TurnContext, TurnEvent, TurnInput, TurnIssue, TurnOptions,
265 UnavailableProcessService, UsageReportRow, UsageTotals, WaitKind, WaitState, current_epoch_ms,
266 diff_token_ledger, diff_usage_reports, ensure_durable_effect_input, epoch_ms_from_system_time,
267 lashlang_process_event_types, lashlang_process_signal_event_types, process_signal_event_type,
268 process_signal_name_from_event_type, process_signal_wait_key, system_time_from_epoch_ms,
269 validate_process_signal_name,
270};
271#[allow(unused_imports)]
272pub(crate) use runtime::{
273 LlmAttachmentSpec, PreparedProcessEventAppend, ProcessEventSemantics, QUEUED_WORK_CLAIM_TTL_MS,
274 QueuedCheckpointWork, QueuedTurnWork, QueuedWorkBatch, QueuedWorkBatchDraft, QueuedWorkClaim,
275 QueuedWorkClaimBoundary, QueuedWorkCompletion, QueuedWorkItem, QueuedWorkPayload,
276 RuntimeReplay, RuntimeScope, RuntimeSubject, load_process_execution_env,
277 materialize_process_event_semantics, persist_process_execution_env,
278 prepare_process_event_append, prepare_process_registration, process_event_invocation,
279 process_event_payload_hash, process_wake_batch_draft, process_wake_delivery,
280 process_wake_input_from_event_payload, process_wake_turn_cause, process_wake_turn_text,
281 require_event_replay,
282};
283pub use runtime::{
287 LlmRequestSpec, ProcessCommand, ProcessEffectOutcome, ProcessEventSemanticsSpec,
288 RuntimeEffectCommand, RuntimeEffectController, RuntimeEffectControllerError,
289 RuntimeEffectEnvelope, RuntimeEffectKind, RuntimeEffectLocalExecutor, RuntimeEffectOutcome,
290 RuntimeInvocation, RuntimeSessionState,
291};
292pub use schemars::JsonSchema;
293pub use session::{
294 ExecRequest, InjectedTurnInput, RuntimeExecutionContext, Session, SessionError, ToolInvocation,
295 ToolInvocationReply,
296};
297pub use session_graph::{
298 PersistedSessionConfig, PersistedTurnState, SessionGraph, SessionMessageTreeNode,
299 SessionNodePayload, SessionNodeRecord,
300};
301pub use session_model::context::PreparedContext;
302pub use session_model::{ConversationRecord, ProtocolEvent, SessionEventRecord};
303pub use session_model::{RuntimeSessionPolicy, SessionPolicy, SessionSpec};
304pub use store::{
305 AttachmentIntent, AttachmentManifest, AttachmentManifestEntry, BlobRef, GcReport,
306 RuntimePersistence, SessionMeta, SessionPickerInfo, SessionReadScope, StoreError, VacuumReport,
307};
308#[allow(unused_imports)]
309pub(crate) use store::{
310 GraphCommitDelta, PersistedSessionRead, RuntimeCommitResult, SessionCheckpoint,
311 SessionHeadMeta, ensure_supported_schema_version, load_persisted_session_state,
312 load_persisted_session_state_active_path,
313};
314pub use store::{
315 HydratedSessionCheckpoint, RuntimeCommit, RuntimeTurnCommitStamp, SessionHead,
316 refresh_persisted_session_state,
317};
318pub use tool_provider::{
319 PreparedToolCall, ProgressSender, SandboxMessage, ToolCall, ToolContext, ToolDurableEffects,
320 ToolLashlangExecutionCallSite, ToolPrepareCall, ToolPrepareContext, ToolProvider,
321 ToolSessionAdmin, ToolSessionModel, ToolTriggerClient,
322};
323
324#[cfg(test)]
325mod tests {
326 use super::*;
327
328 #[test]
329 fn protocol_turn_options_missing_payload_deserializes_to_empty_object() {
330 let options: ProtocolTurnOptions =
331 serde_json::from_value(serde_json::json!({})).expect("deserialize options");
332
333 assert!(options.is_empty());
334 assert_eq!(options.payload, serde_json::json!({}));
335 }
336
337 #[test]
338 fn protocol_turn_options_explicit_null_is_not_empty() {
339 let options: ProtocolTurnOptions =
340 serde_json::from_value(serde_json::json!({ "payload": null }))
341 .expect("deserialize options");
342
343 assert!(!options.is_empty());
344 assert_eq!(options.payload, serde_json::Value::Null);
345 }
346
347 #[test]
348 fn root_exports_do_not_reintroduce_removed_session_state_shapes() {
349 let source = include_str!("lib.rs");
350 let removed_envelope = ["SessionState", "Envelope"].concat();
351 let removed_persisted = ["PersistedSession", "Snapshot"].concat();
352 let removed_history_rewriter = ["History", "Rewriter"].concat();
353 let removed_rewrite_trigger = ["Rewrite", "Trigger"].concat();
354 let removed_rewrite_context = ["Rewrite", "Context"].concat();
355 let removed_history_state = ["History", "State"].concat();
356 let removed_history_metadata = ["History", "Rewrite", "Metadata"].concat();
357
358 assert!(!source.contains(&removed_envelope));
359 assert!(!source.contains(&removed_persisted));
360 assert!(!source.contains(&removed_history_rewriter));
361 assert!(!source.contains(&removed_rewrite_trigger));
362 assert!(!source.contains(&removed_rewrite_context));
363 assert!(!source.contains(&removed_history_state));
364 assert!(!source.contains(&removed_history_metadata));
365 }
366
367 fn public_reexport_block(source: &str, module: &str) -> String {
368 let start = format!("pub use {module}::{{");
369 let mut block = String::new();
370 let mut collecting = false;
371 for line in source.lines() {
372 if line.trim_start().starts_with(&start) {
373 collecting = true;
374 }
375 if collecting {
376 block.push_str(line);
377 block.push('\n');
378 if line.trim_end() == "};" {
379 break;
380 }
381 }
382 }
383 assert!(!block.is_empty(), "missing public {module} re-export block");
384 block
385 }
386
387 #[test]
388 fn root_runtime_exports_exclude_internal_runtime_records() {
389 let runtime_exports = public_reexport_block(include_str!("lib.rs"), "runtime");
390 for removed in [
391 "RuntimeEffectCommand",
392 "RuntimeEffectEnvelope",
393 "RuntimeEffectKind",
394 "RuntimeEffectOutcome",
395 "RuntimeInvocation",
396 "RuntimeScope",
397 "RuntimeSessionState",
398 "QueuedWorkBatch",
399 "QueuedWorkBatchDraft",
400 "QueuedWorkPayload",
401 "prepare_process_registration",
402 "process_wake_batch_draft",
403 "require_event_replay",
404 ] {
405 assert!(
406 !runtime_exports.contains(removed),
407 "runtime root export leaked {removed}"
408 );
409 }
410 }
411
412 #[test]
413 fn root_store_exports_exclude_wire_records() {
414 let store_exports = public_reexport_block(include_str!("lib.rs"), "store");
415 for removed in [
416 "SessionHead",
417 "SessionCheckpoint",
418 "RuntimeCommit",
419 "HydratedSessionCheckpoint",
420 "PersistedSessionRead",
421 "GraphCommitDelta",
422 ] {
423 assert!(
424 !store_exports.contains(removed),
425 "store root export leaked {removed}"
426 );
427 }
428 }
429
430 #[test]
431 fn removed_manager_and_host_trait_names_stay_removed() {
432 let removed_manager = ["Runtime", "Session", "Manager"].concat();
433 let removed_host = ["Runtime", "Session", "Host"].concat();
434 let sources = [
435 include_str!("runtime/session_manager/mod.rs"),
436 include_str!("plugin/runtime_host.rs"),
437 include_str!("tool_dispatch/context.rs"),
438 include_str!("tool_provider.rs"),
439 ];
440
441 for source in sources {
442 assert!(!source.contains(&removed_manager));
443 assert!(!source.contains(&removed_host));
444 }
445 }
446}