use crate::generated::session_document::{self, SessionDocumentEffect, SessionDocumentError};
use crate::{SessionBuildState, SessionMetadata};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SessionSystemPromptSource {
DirectMutation,
ExplicitBuild,
DefaultBuild,
WasmDefaultBuild,
RuntimeContextAppend,
RuntimeSteerCleanup,
}
impl From<SessionSystemPromptSource> for session_document::SessionSystemPromptSource {
fn from(value: SessionSystemPromptSource) -> Self {
match value {
SessionSystemPromptSource::DirectMutation => Self::DirectMutation,
SessionSystemPromptSource::ExplicitBuild => Self::ExplicitBuild,
SessionSystemPromptSource::DefaultBuild => Self::DefaultBuild,
SessionSystemPromptSource::WasmDefaultBuild => Self::WasmDefaultBuild,
SessionSystemPromptSource::RuntimeContextAppend => Self::RuntimeContextAppend,
SessionSystemPromptSource::RuntimeSteerCleanup => Self::RuntimeSteerCleanup,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SessionDurableConfigAuthorityError {
message: String,
}
impl std::fmt::Display for SessionDurableConfigAuthorityError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.message)
}
}
impl std::error::Error for SessionDurableConfigAuthorityError {}
impl From<SessionDocumentError> for SessionDurableConfigAuthorityError {
fn from(inner: SessionDocumentError) -> Self {
Self {
message: inner.to_string(),
}
}
}
#[derive(Debug, Clone)]
pub struct AuthorizedSessionMetadata {
metadata: SessionMetadata,
}
impl AuthorizedSessionMetadata {
#[must_use]
pub fn into_metadata(self) -> SessionMetadata {
self.metadata
}
}
#[derive(Debug, Clone)]
pub struct AuthorizedSessionBuildState {
state: SessionBuildState,
}
impl AuthorizedSessionBuildState {
#[must_use]
pub fn into_state(self) -> SessionBuildState {
self.state
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AuthorizedSystemPrompt {
prompt: String,
replacing_existing: bool,
source: SessionSystemPromptSource,
}
impl AuthorizedSystemPrompt {
#[must_use]
pub fn into_parts(self) -> (String, bool) {
(self.prompt, self.replacing_existing)
}
#[must_use]
pub fn mutation_kind(&self) -> crate::types::SystemPromptMutationKind {
self.source.into()
}
}
impl From<SessionSystemPromptSource> for crate::types::SystemPromptMutationKind {
fn from(value: SessionSystemPromptSource) -> Self {
match value {
SessionSystemPromptSource::DirectMutation => Self::DirectMutation,
SessionSystemPromptSource::ExplicitBuild => Self::ExplicitBuild,
SessionSystemPromptSource::DefaultBuild => Self::DefaultBuild,
SessionSystemPromptSource::WasmDefaultBuild => Self::WasmDefaultBuild,
SessionSystemPromptSource::RuntimeContextAppend => Self::RuntimeContextAppend,
SessionSystemPromptSource::RuntimeSteerCleanup => Self::RuntimeSteerCleanup,
}
}
}
fn usize_to_u64(value: usize) -> u64 {
u64::try_from(value).unwrap_or(u64::MAX)
}
fn document_authority() -> session_document::SessionDocumentMachineAuthority {
session_document::SessionDocumentMachineAuthority::new()
}
fn drive_metadata_persist(
metadata: &SessionMetadata,
) -> Result<(), SessionDurableConfigAuthorityError> {
let mut authority = document_authority();
let effects = authority.authorize_session_metadata_persist(
u64::from(metadata.schema_version),
!metadata.model.trim().is_empty(),
)?;
expect_effect(&effects, |effect| {
matches!(
effect,
SessionDocumentEffect::SessionMetadataPersistAuthorized
)
})
}
fn drive_build_state_persist(
state: &SessionBuildState,
) -> Result<(), SessionDurableConfigAuthorityError> {
let mob_tool_authority_context_present = state.mob_tool_authority_context.is_some();
let mob_tool_authority_context_generated = state
.mob_tool_authority_context
.as_ref()
.is_some_and(|context| context.is_generated_authority_context());
let mut authority = document_authority();
let effects = authority.authorize_session_build_state_persist(
mob_tool_authority_context_present,
mob_tool_authority_context_generated,
)?;
expect_effect(&effects, |effect| {
matches!(
effect,
SessionDocumentEffect::SessionBuildStatePersistAuthorized
)
})
}
fn drive_build_state_restore() -> Result<(), SessionDurableConfigAuthorityError> {
let mut authority = document_authority();
let effects = authority.restore_session_build_state()?;
expect_effect(&effects, |effect| {
matches!(
effect,
SessionDocumentEffect::SessionBuildStateRestoreAuthorized
)
})
}
fn expect_effect(
effects: &[SessionDocumentEffect],
matches_expected: impl Fn(&SessionDocumentEffect) -> bool,
) -> Result<(), SessionDurableConfigAuthorityError> {
if !effects.is_empty() && effects.iter().all(matches_expected) {
Ok(())
} else {
Err(SessionDurableConfigAuthorityError {
message:
"generated session document authority emitted no durable-config authorization effect"
.to_string(),
})
}
}
pub fn authorize_session_metadata_persist(
mut metadata: SessionMetadata,
) -> Result<AuthorizedSessionMetadata, SessionDurableConfigAuthorityError> {
metadata.schema_version = crate::session_metadata_schema_version();
drive_metadata_persist(&metadata)?;
Ok(AuthorizedSessionMetadata { metadata })
}
pub fn restore_session_metadata(
metadata: SessionMetadata,
) -> Result<SessionMetadata, SessionDurableConfigAuthorityError> {
drive_metadata_persist(&metadata)?;
Ok(metadata)
}
pub fn authorize_session_build_state_persist(
state: SessionBuildState,
) -> Result<AuthorizedSessionBuildState, SessionDurableConfigAuthorityError> {
drive_build_state_persist(&state)?;
Ok(AuthorizedSessionBuildState { state })
}
pub fn restore_session_build_state(
state: SessionBuildState,
) -> Result<SessionBuildState, SessionDurableConfigAuthorityError> {
drive_build_state_restore()?;
Ok(state)
}
pub fn authorize_system_prompt_mutation(
prompt: String,
source: SessionSystemPromptSource,
replacing_existing: bool,
) -> Result<AuthorizedSystemPrompt, SessionDurableConfigAuthorityError> {
let mut authority = document_authority();
let effects = authority.authorize_system_prompt_mutation(
source.into(),
!prompt.is_empty(),
usize_to_u64(prompt.len()),
replacing_existing,
)?;
expect_effect(&effects, |effect| {
matches!(
effect,
SessionDocumentEffect::SystemPromptMutationAuthorized
)
})?;
Ok(AuthorizedSystemPrompt {
prompt,
replacing_existing,
source,
})
}