types/behaviours
Behaviour record types — structural contracts for dependency injection. Gleam has no traits/protocols, so we use records of function fields. Each service/plugin module exports a constructor that returns its behaviour.
Core modules depend on these behaviours, never on concrete service/plugin modules. This keeps core as a pure wireframe.
Pattern: fn service_or_plugin_constructor(deps) -> BehaviourRecord { … } fn consumer(behaviour: BehaviourRecord, …) -> Result(…) { … }
Types
pub type CompressorHook {
CompressorHook(
should_compress: fn(Int, Int, Int) -> Bool,
split_history: fn(List(message.Message), Int, Int) -> hooks.CompressionPlan,
build_summary_prompt: fn(List(message.Message)) -> String,
apply_compression: fn(List(message.Message), Int, Int, String) -> List(
message.Message,
),
is_cooling_down: fn(hooks.CooldownState, Int) -> Bool,
record_success: fn(hooks.CooldownState) -> hooks.CooldownState,
record_failure: fn(hooks.CooldownState, Int) -> hooks.CooldownState,
)
}
Constructors
-
CompressorHook( should_compress: fn(Int, Int, Int) -> Bool, split_history: fn(List(message.Message), Int, Int) -> hooks.CompressionPlan, build_summary_prompt: fn(List(message.Message)) -> String, apply_compression: fn(List(message.Message), Int, Int, String) -> List( message.Message, ), is_cooling_down: fn(hooks.CooldownState, Int) -> Bool, record_success: fn(hooks.CooldownState) -> hooks.CooldownState, record_failure: fn(hooks.CooldownState, Int) -> hooks.CooldownState, )
pub type ContextBuilder {
ContextBuilder(
build_tool_continuation: fn(
String,
List(message.Message),
List(message.Message),
sqlight.Connection,
String,
) -> List(message.Message),
system_prompt: fn(String, sqlight.Connection, String) -> String,
)
}
Constructors
-
ContextBuilder( build_tool_continuation: fn( String, List(message.Message), List(message.Message), sqlight.Connection, String, ) -> List(message.Message), system_prompt: fn(String, sqlight.Connection, String) -> String, )
pub type CronStore {
CronStore(
list_enabled: fn(sqlight.Connection) -> Result(
List(session.CronJobRow),
String,
),
list_all: fn(sqlight.Connection) -> Result(
List(session.CronJobRow),
String,
),
upsert: fn(
sqlight.Connection,
String,
String,
String,
String,
String,
Bool,
) -> Result(Nil, String),
delete: fn(sqlight.Connection, String) -> Result(Nil, String),
touch: fn(sqlight.Connection, String) -> Result(Nil, String),
)
}
Constructors
-
CronStore( list_enabled: fn(sqlight.Connection) -> Result( List(session.CronJobRow), String, ), list_all: fn(sqlight.Connection) -> Result( List(session.CronJobRow), String, ), upsert: fn( sqlight.Connection, String, String, String, String, String, Bool, ) -> Result(Nil, String), delete: fn(sqlight.Connection, String) -> Result(Nil, String), touch: fn(sqlight.Connection, String) -> Result(Nil, String), )
pub type DbConnector {
DbConnector(
open: fn(String) -> Result(sqlight.Connection, String),
close: fn(sqlight.Connection) -> Result(Nil, String),
checkpoint: fn(sqlight.Connection) -> Result(Nil, String),
integrity_check: fn(sqlight.Connection) -> Result(
String,
String,
),
migrate: fn(sqlight.Connection) -> Result(Nil, String),
)
}
Constructors
-
DbConnector( open: fn(String) -> Result(sqlight.Connection, String), close: fn(sqlight.Connection) -> Result(Nil, String), checkpoint: fn(sqlight.Connection) -> Result(Nil, String), integrity_check: fn(sqlight.Connection) -> Result( String, String, ), migrate: fn(sqlight.Connection) -> Result(Nil, String), )
pub type DndChecker {
DndChecker(
is_quiet_now: fn(sqlight.Connection, String) -> Bool,
list_active: fn(sqlight.Connection) -> Result(
List(DndRule),
String,
),
add_rule: fn(sqlight.Connection, String, String, String) -> Result(
String,
String,
),
toggle_indefinite: fn(sqlight.Connection) -> Result(
String,
String,
),
remove_all: fn(sqlight.Connection) -> Result(Int, String),
)
}
Constructors
-
DndChecker( is_quiet_now: fn(sqlight.Connection, String) -> Bool, list_active: fn(sqlight.Connection) -> Result( List(DndRule), String, ), add_rule: fn(sqlight.Connection, String, String, String) -> Result( String, String, ), toggle_indefinite: fn(sqlight.Connection) -> Result( String, String, ), remove_all: fn(sqlight.Connection) -> Result(Int, String), )
pub type DndRule {
DndRule(
id: Int,
rule_type: String,
start_time: String,
end_time: String,
enabled: Bool,
created_at: String,
)
}
Constructors
-
DndRule( id: Int, rule_type: String, start_time: String, end_time: String, enabled: Bool, created_at: String, )
pub type Guardrail {
Guardrail(
check: fn(String) -> guardrails.GuardrailResult,
classify_risk: fn(guardrails.GuardrailResult) -> guardrails.Risk,
strip_ansi: fn(String) -> String,
check_cache: fn(
List(#(String, String, guardrails.ApprovalScope)),
String,
String,
) -> Bool,
store_cache: fn(
List(#(String, String, guardrails.ApprovalScope)),
String,
String,
guardrails.ApprovalScope,
) -> List(#(String, String, guardrails.ApprovalScope)),
consume_cache: fn(
List(#(String, String, guardrails.ApprovalScope)),
String,
String,
) -> #(
List(#(String, String, guardrails.ApprovalScope)),
Bool,
),
)
}
Constructors
-
Guardrail( check: fn(String) -> guardrails.GuardrailResult, classify_risk: fn(guardrails.GuardrailResult) -> guardrails.Risk, strip_ansi: fn(String) -> String, check_cache: fn( List(#(String, String, guardrails.ApprovalScope)), String, String, ) -> Bool, store_cache: fn( List(#(String, String, guardrails.ApprovalScope)), String, String, guardrails.ApprovalScope, ) -> List(#(String, String, guardrails.ApprovalScope)), consume_cache: fn( List(#(String, String, guardrails.ApprovalScope)), String, String, ) -> #(List(#(String, String, guardrails.ApprovalScope)), Bool), )
pub type GuardrailHook {
GuardrailHook(
fresh: fn() -> hooks.LoopState,
record_success: fn(hooks.LoopState, String, String, String) -> hooks.LoopState,
record_failure: fn(hooks.LoopState, String, String) -> hooks.LoopState,
escalation: fn(hooks.LoopState, Int, Int, Int, Int, Int, Int) -> hooks.Escalation,
block_tool: fn(hooks.LoopState, String) -> hooks.LoopState,
halt: fn(hooks.LoopState) -> hooks.LoopState,
)
}
Constructors
-
GuardrailHook( fresh: fn() -> hooks.LoopState, record_success: fn(hooks.LoopState, String, String, String) -> hooks.LoopState, record_failure: fn(hooks.LoopState, String, String) -> hooks.LoopState, escalation: fn(hooks.LoopState, Int, Int, Int, Int, Int, Int) -> hooks.Escalation, block_tool: fn(hooks.LoopState, String) -> hooks.LoopState, halt: fn(hooks.LoopState) -> hooks.LoopState, )
pub type LLMClient {
LLMClient(
chat: fn(
client.Client,
List(message.Message),
List(tool_def.ToolDefinition),
) -> Result(response.ChatResponse, client.ClientError),
chat_with_retry: fn(
client.Client,
List(message.Message),
List(tool_def.ToolDefinition),
Int,
) -> Result(response.ChatResponse, client.ClientError),
is_retryable: fn(client.ClientError) -> Bool,
should_compress: fn(client.ClientError) -> Bool,
)
}
Constructors
-
LLMClient( chat: fn( client.Client, List(message.Message), List(tool_def.ToolDefinition), ) -> Result(response.ChatResponse, client.ClientError), chat_with_retry: fn( client.Client, List(message.Message), List(tool_def.ToolDefinition), Int, ) -> Result(response.ChatResponse, client.ClientError), is_retryable: fn(client.ClientError) -> Bool, should_compress: fn(client.ClientError) -> Bool, )
pub type Logger {
Logger(
debug: fn(logging.LogCategory, String, String) -> Nil,
info: fn(logging.LogCategory, String, String) -> Nil,
warn: fn(logging.LogCategory, String, String) -> Nil,
error: fn(logging.LogCategory, String, String) -> Nil,
)
}
Constructors
-
Logger( debug: fn(logging.LogCategory, String, String) -> Nil, info: fn(logging.LogCategory, String, String) -> Nil, warn: fn(logging.LogCategory, String, String) -> Nil, error: fn(logging.LogCategory, String, String) -> Nil, )
pub type MemoryStore {
MemoryStore(
format_for_system_prompt: fn(
sqlight.Connection,
String,
String,
) -> Result(String, String),
add_entry: fn(sqlight.Connection, String, String, String) -> Result(
Nil,
String,
),
get_entries: fn(sqlight.Connection, String, String) -> Result(
List(String),
String,
),
replace_entry: fn(
sqlight.Connection,
String,
String,
String,
String,
) -> Result(Nil, String),
remove_entry: fn(sqlight.Connection, String, String, String) -> Result(
Nil,
String,
),
usage_string: fn(sqlight.Connection, String, String) -> Result(
String,
String,
),
)
}
Constructors
-
MemoryStore( format_for_system_prompt: fn(sqlight.Connection, String, String) -> Result( String, String, ), add_entry: fn(sqlight.Connection, String, String, String) -> Result( Nil, String, ), get_entries: fn(sqlight.Connection, String, String) -> Result( List(String), String, ), replace_entry: fn( sqlight.Connection, String, String, String, String, ) -> Result(Nil, String), remove_entry: fn(sqlight.Connection, String, String, String) -> Result( Nil, String, ), usage_string: fn(sqlight.Connection, String, String) -> Result( String, String, ), )
pub type PruneResult {
PruneResult(deleted_count: Int, orphaned_count: Int)
}
Constructors
-
PruneResult(deleted_count: Int, orphaned_count: Int)
pub type ReflectionHook {
ReflectionHook(
should_reflect: fn(Int, Int) -> Bool,
spawn_review: fn(
client.Client,
String,
List(message.Message),
String,
fn(sqlight.Connection, String) -> tool.Tool,
) -> Nil,
)
}
Constructors
-
ReflectionHook( should_reflect: fn(Int, Int) -> Bool, spawn_review: fn( client.Client, String, List(message.Message), String, fn(sqlight.Connection, String) -> tool.Tool, ) -> Nil, )
pub type SessionStore {
SessionStore(
load_session: fn(sqlight.Connection, String) -> Result(
option.Option(#(session.SessionRow, List(message.Message))),
String,
),
create_session: fn(sqlight.Connection, String, String, String) -> Result(
String,
String,
),
append_message: fn(
sqlight.Connection,
String,
message.Message,
) -> Result(Nil, String),
touch_session: fn(sqlight.Connection, String) -> Result(
Nil,
String,
),
end_session: fn(sqlight.Connection, String, String) -> Result(
Nil,
String,
),
generate_id: fn() -> String,
load_session_row: fn(sqlight.Connection, String) -> Result(
option.Option(session.SessionRow),
String,
),
set_session_title: fn(sqlight.Connection, String, String) -> Result(
Nil,
String,
),
list_sessions: fn(sqlight.Connection) -> Result(
List(session.SessionSummary),
String,
),
search_messages: fn(sqlight.Connection, String, Int, Int) -> Result(
List(session.FtsSearchResult),
String,
),
find_session_for_message: fn(sqlight.Connection, Int) -> Result(
option.Option(String),
String,
),
resolve_root_session: fn(sqlight.Connection, String) -> Result(
String,
String,
),
load_messages_range: fn(sqlight.Connection, String, Int, Int) -> Result(
List(message.Message),
String,
),
list_sessions_rich: fn(sqlight.Connection) -> Result(
List(session.RichSessionSummary),
String,
),
delete_session: fn(sqlight.Connection, String) -> Result(
Nil,
String,
),
export_session_json: fn(sqlight.Connection, String) -> Result(
option.Option(String),
String,
),
find_session_by_title: fn(sqlight.Connection, String) -> Result(
option.Option(#(session.SessionRow, List(message.Message))),
String,
),
list_recently_active: fn(
sqlight.Connection,
Int,
option.Option(String),
) -> Result(List(session.SessionSummary), String),
prune_sessions: fn(
sqlight.Connection,
Int,
option.Option(String),
) -> Result(PruneResult, String),
)
}
Constructors
-
SessionStore( load_session: fn(sqlight.Connection, String) -> Result( option.Option(#(session.SessionRow, List(message.Message))), String, ), create_session: fn(sqlight.Connection, String, String, String) -> Result( String, String, ), append_message: fn(sqlight.Connection, String, message.Message) -> Result( Nil, String, ), touch_session: fn(sqlight.Connection, String) -> Result( Nil, String, ), end_session: fn(sqlight.Connection, String, String) -> Result( Nil, String, ), generate_id: fn() -> String, load_session_row: fn(sqlight.Connection, String) -> Result( option.Option(session.SessionRow), String, ), set_session_title: fn(sqlight.Connection, String, String) -> Result( Nil, String, ), list_sessions: fn(sqlight.Connection) -> Result( List(session.SessionSummary), String, ), search_messages: fn(sqlight.Connection, String, Int, Int) -> Result( List(session.FtsSearchResult), String, ), find_session_for_message: fn(sqlight.Connection, Int) -> Result( option.Option(String), String, ), resolve_root_session: fn(sqlight.Connection, String) -> Result( String, String, ), load_messages_range: fn(sqlight.Connection, String, Int, Int) -> Result( List(message.Message), String, ), list_sessions_rich: fn(sqlight.Connection) -> Result( List(session.RichSessionSummary), String, ), delete_session: fn(sqlight.Connection, String) -> Result( Nil, String, ), export_session_json: fn(sqlight.Connection, String) -> Result( option.Option(String), String, ), find_session_by_title: fn(sqlight.Connection, String) -> Result( option.Option(#(session.SessionRow, List(message.Message))), String, ), list_recently_active: fn( sqlight.Connection, Int, option.Option(String), ) -> Result(List(session.SessionSummary), String), prune_sessions: fn( sqlight.Connection, Int, option.Option(String), ) -> Result(PruneResult, String), )
pub type TokenEstimator {
TokenEstimator(
estimate_request: fn(
String,
List(message.Message),
List(tool_def.ToolDefinition),
) -> Int,
context_usage_percent: fn(Int, Int) -> Int,
context_window_warning: fn(Int, Int, Int) -> String,
)
}
Constructors
-
TokenEstimator( estimate_request: fn( String, List(message.Message), List(tool_def.ToolDefinition), ) -> Int, context_usage_percent: fn(Int, Int) -> Int, context_window_warning: fn(Int, Int, Int) -> String, )