docs: describe the runtime public API surface

This adds crate-level and type-level Rustdoc to the runtime crate's core exported types so downstream crates and contributors can understand the session, prompt, permission, OAuth, usage, and tool I/O primitives without spelunking every implementation file.

Constraint: The docs pass needed to stay focused on public runtime types without changing behavior
Rejected: Add blanket docs to every public item in one sweep | larger churn than needed for a targeted docs pass
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: When exporting new runtime primitives from lib.rs, add a short Rustdoc summary in the defining module at the same time
Tested: cargo build --workspace; cargo test --workspace
Not-tested: rustdoc HTML rendering beyond  doc-test coverage
This commit is contained in:
Yeachan-Heo
2026-04-04 15:23:29 +00:00
parent 953513f12d
commit 22ad54c08e
11 changed files with 106 additions and 6 deletions

View File

@@ -14,6 +14,7 @@ use crate::sandbox::{
};
use crate::ConfigLoader;
/// Input schema for the built-in bash execution tool.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct BashCommandInput {
pub command: String,
@@ -33,6 +34,7 @@ pub struct BashCommandInput {
pub allowed_mounts: Option<Vec<String>>,
}
/// Output returned from a bash tool invocation.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct BashCommandOutput {
pub stdout: String,
@@ -64,6 +66,7 @@ pub struct BashCommandOutput {
pub sandbox_status: Option<SandboxStatus>,
}
/// Executes a shell command with the requested sandbox settings.
pub fn execute_bash(input: BashCommandInput) -> io::Result<BashCommandOutput> {
let cwd = env::current_dir()?;
let sandbox_status = sandbox_status_for_input(&input, &cwd);

View File

@@ -5,6 +5,7 @@ const COMPACT_CONTINUATION_PREAMBLE: &str =
const COMPACT_RECENT_MESSAGES_NOTE: &str = "Recent messages are preserved verbatim.";
const COMPACT_DIRECT_RESUME_INSTRUCTION: &str = "Continue the conversation from where it left off without asking the user any further questions. Resume directly — do not acknowledge the summary, do not recap what was happening, and do not preface with continuation text.";
/// Thresholds controlling when and how a session is compacted.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct CompactionConfig {
pub preserve_recent_messages: usize,
@@ -20,6 +21,7 @@ impl Default for CompactionConfig {
}
}
/// Result of compacting a session into a summary plus preserved tail messages.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CompactionResult {
pub summary: String,
@@ -28,11 +30,13 @@ pub struct CompactionResult {
pub removed_message_count: usize,
}
/// Roughly estimates the token footprint of the current session transcript.
#[must_use]
pub fn estimate_session_tokens(session: &Session) -> usize {
session.messages.iter().map(estimate_message_tokens).sum()
}
/// Returns `true` when the session exceeds the configured compaction budget.
#[must_use]
pub fn should_compact(session: &Session, config: CompactionConfig) -> bool {
let start = compacted_summary_prefix_len(session);
@@ -46,6 +50,7 @@ pub fn should_compact(session: &Session, config: CompactionConfig) -> bool {
>= config.max_estimated_tokens
}
/// Normalizes a compaction summary into user-facing continuation text.
#[must_use]
pub fn format_compact_summary(summary: &str) -> String {
let without_analysis = strip_tag_block(summary, "analysis");
@@ -61,6 +66,7 @@ pub fn format_compact_summary(summary: &str) -> String {
collapse_blank_lines(&formatted).trim().to_string()
}
/// Builds the synthetic system message used after session compaction.
#[must_use]
pub fn get_compact_continuation_message(
summary: &str,
@@ -85,6 +91,7 @@ pub fn get_compact_continuation_message(
base
}
/// Compacts a session by summarizing older messages and preserving the recent tail.
#[must_use]
pub fn compact_session(session: &Session, config: CompactionConfig) -> CompactionResult {
if !should_compact(session, config) {

View File

@@ -6,8 +6,10 @@ use std::path::{Path, PathBuf};
use crate::json::JsonValue;
use crate::sandbox::{FilesystemIsolationMode, SandboxConfig};
/// Schema name advertised by generated settings files.
pub const CLAW_SETTINGS_SCHEMA_NAME: &str = "SettingsSchema";
/// Origin of a loaded settings file in the configuration precedence chain.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum ConfigSource {
User,
@@ -15,6 +17,7 @@ pub enum ConfigSource {
Local,
}
/// Effective permission mode after decoding config values.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ResolvedPermissionMode {
ReadOnly,
@@ -22,12 +25,14 @@ pub enum ResolvedPermissionMode {
DangerFullAccess,
}
/// A discovered config file and the scope it contributes to.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ConfigEntry {
pub source: ConfigSource,
pub path: PathBuf,
}
/// Fully merged runtime configuration plus parsed feature-specific views.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RuntimeConfig {
merged: BTreeMap<String, JsonValue>,
@@ -35,6 +40,7 @@ pub struct RuntimeConfig {
feature_config: RuntimeFeatureConfig,
}
/// Parsed plugin-related settings extracted from runtime config.
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct RuntimePluginConfig {
enabled_plugins: BTreeMap<String, bool>,
@@ -44,6 +50,7 @@ pub struct RuntimePluginConfig {
bundled_root: Option<String>,
}
/// Structured feature configuration consumed by runtime subsystems.
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct RuntimeFeatureConfig {
hooks: RuntimeHookConfig,
@@ -56,6 +63,7 @@ pub struct RuntimeFeatureConfig {
sandbox: SandboxConfig,
}
/// Hook command lists grouped by lifecycle stage.
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct RuntimeHookConfig {
pre_tool_use: Vec<String>,
@@ -63,6 +71,7 @@ pub struct RuntimeHookConfig {
post_tool_use_failure: Vec<String>,
}
/// Raw permission rule lists grouped by allow, deny, and ask behavior.
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct RuntimePermissionRuleConfig {
allow: Vec<String>,
@@ -70,17 +79,20 @@ pub struct RuntimePermissionRuleConfig {
ask: Vec<String>,
}
/// Collection of configured MCP servers after scope-aware merging.
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct McpConfigCollection {
servers: BTreeMap<String, ScopedMcpServerConfig>,
}
/// MCP server config paired with the scope that defined it.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ScopedMcpServerConfig {
pub scope: ConfigSource,
pub config: McpServerConfig,
}
/// Transport families supported by configured MCP servers.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum McpTransport {
Stdio,
@@ -91,6 +103,7 @@ pub enum McpTransport {
ManagedProxy,
}
/// Scope-normalized MCP server configuration variants.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum McpServerConfig {
Stdio(McpStdioServerConfig),
@@ -101,6 +114,7 @@ pub enum McpServerConfig {
ManagedProxy(McpManagedProxyServerConfig),
}
/// Configuration for an MCP server launched as a local stdio process.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct McpStdioServerConfig {
pub command: String,
@@ -109,6 +123,7 @@ pub struct McpStdioServerConfig {
pub tool_call_timeout_ms: Option<u64>,
}
/// Configuration for an MCP server reached over HTTP or SSE.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct McpRemoteServerConfig {
pub url: String,
@@ -117,6 +132,7 @@ pub struct McpRemoteServerConfig {
pub oauth: Option<McpOAuthConfig>,
}
/// Configuration for an MCP server reached over WebSocket.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct McpWebSocketServerConfig {
pub url: String,
@@ -124,17 +140,20 @@ pub struct McpWebSocketServerConfig {
pub headers_helper: Option<String>,
}
/// Configuration for an MCP server addressed through an SDK name.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct McpSdkServerConfig {
pub name: String,
}
/// Configuration for an MCP managed-proxy endpoint.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct McpManagedProxyServerConfig {
pub url: String,
pub id: String,
}
/// OAuth overrides associated with a remote MCP server.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct McpOAuthConfig {
pub client_id: Option<String>,
@@ -143,6 +162,7 @@ pub struct McpOAuthConfig {
pub xaa: Option<bool>,
}
/// OAuth client configuration used by the main Claw runtime.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OAuthConfig {
pub client_id: String,
@@ -153,6 +173,7 @@ pub struct OAuthConfig {
pub scopes: Vec<String>,
}
/// Errors raised while reading or parsing runtime configuration files.
#[derive(Debug)]
pub enum ConfigError {
Io(std::io::Error),
@@ -176,6 +197,7 @@ impl From<std::io::Error> for ConfigError {
}
}
/// Discovers config files and merges them into a [`RuntimeConfig`].
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ConfigLoader {
cwd: PathBuf,
@@ -441,6 +463,7 @@ impl RuntimePluginConfig {
}
#[must_use]
/// Returns the default per-user config directory used by the runtime.
pub fn default_config_home() -> PathBuf {
std::env::var_os("CLAW_CONFIG_HOME")
.map(PathBuf::from)
@@ -1338,7 +1361,10 @@ mod tests {
.load()
.expect("config should load");
let remote_server = loaded.mcp().get("remote").expect("remote server should exist");
let remote_server = loaded
.mcp()
.get("remote")
.expect("remote server should exist");
assert_eq!(remote_server.transport(), McpTransport::Http);
match &remote_server.config {
McpServerConfig::Http(config) => {

View File

@@ -18,12 +18,14 @@ use crate::usage::{TokenUsage, UsageTracker};
const DEFAULT_AUTO_COMPACTION_INPUT_TOKENS_THRESHOLD: u32 = 100_000;
const AUTO_COMPACTION_THRESHOLD_ENV_VAR: &str = "CLAUDE_CODE_AUTO_COMPACT_INPUT_TOKENS";
/// Fully assembled request payload sent to the upstream model client.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ApiRequest {
pub system_prompt: Vec<String>,
pub messages: Vec<ConversationMessage>,
}
/// Streamed events emitted while processing a single assistant turn.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum AssistantEvent {
TextDelta(String),
@@ -37,6 +39,7 @@ pub enum AssistantEvent {
MessageStop,
}
/// Prompt-cache telemetry captured from the provider response stream.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PromptCacheEvent {
pub unexpected: bool,
@@ -46,14 +49,17 @@ pub struct PromptCacheEvent {
pub token_drop: u32,
}
/// Minimal streaming API contract required by [`ConversationRuntime`].
pub trait ApiClient {
fn stream(&mut self, request: ApiRequest) -> Result<Vec<AssistantEvent>, RuntimeError>;
}
/// Trait implemented by tool dispatchers that execute model-requested tools.
pub trait ToolExecutor {
fn execute(&mut self, tool_name: &str, input: &str) -> Result<String, ToolError>;
}
/// Error returned when a tool invocation fails locally.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ToolError {
message: String,
@@ -76,6 +82,7 @@ impl Display for ToolError {
impl std::error::Error for ToolError {}
/// Error returned when a conversation turn cannot be completed.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RuntimeError {
message: String,
@@ -98,6 +105,7 @@ impl Display for RuntimeError {
impl std::error::Error for RuntimeError {}
/// Summary of one completed runtime turn, including tool results and usage.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TurnSummary {
pub assistant_messages: Vec<ConversationMessage>,
@@ -108,11 +116,13 @@ pub struct TurnSummary {
pub auto_compaction: Option<AutoCompactionEvent>,
}
/// Details about automatic session compaction applied during a turn.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct AutoCompactionEvent {
pub removed_message_count: usize,
}
/// Coordinates the model loop, tool execution, hooks, and session updates.
pub struct ConversationRuntime<C, T> {
session: Session,
api_client: C,
@@ -637,6 +647,7 @@ where
}
}
/// Reads the automatic compaction threshold from the environment.
#[must_use]
pub fn auto_compaction_threshold_from_env() -> u32 {
parse_auto_compaction_threshold(
@@ -739,6 +750,7 @@ fn merge_hook_feedback(messages: &[String], output: String, is_error: bool) -> S
type ToolHandler = Box<dyn FnMut(&str) -> Result<String, ToolError>>;
/// Simple in-memory tool executor for tests and lightweight integrations.
#[derive(Default)]
pub struct StaticToolExecutor {
handlers: BTreeMap<String, ToolHandler>,

View File

@@ -42,6 +42,7 @@ fn validate_workspace_boundary(resolved: &Path, workspace_root: &Path) -> io::Re
Ok(())
}
/// Text payload returned by file-reading operations.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct TextFilePayload {
#[serde(rename = "filePath")]
@@ -55,6 +56,7 @@ pub struct TextFilePayload {
pub total_lines: usize,
}
/// Output envelope for the `read_file` tool.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct ReadFileOutput {
#[serde(rename = "type")]
@@ -62,6 +64,7 @@ pub struct ReadFileOutput {
pub file: TextFilePayload,
}
/// Structured patch hunk emitted by write and edit operations.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct StructuredPatchHunk {
#[serde(rename = "oldStart")]
@@ -75,6 +78,7 @@ pub struct StructuredPatchHunk {
pub lines: Vec<String>,
}
/// Output envelope for full-file write operations.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct WriteFileOutput {
#[serde(rename = "type")]
@@ -90,6 +94,7 @@ pub struct WriteFileOutput {
pub git_diff: Option<serde_json::Value>,
}
/// Output envelope for targeted string-replacement edits.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct EditFileOutput {
#[serde(rename = "filePath")]
@@ -110,6 +115,7 @@ pub struct EditFileOutput {
pub git_diff: Option<serde_json::Value>,
}
/// Result of a glob-based filename search.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct GlobSearchOutput {
#[serde(rename = "durationMs")]
@@ -120,6 +126,7 @@ pub struct GlobSearchOutput {
pub truncated: bool,
}
/// Parameters accepted by the grep-style search tool.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct GrepSearchInput {
pub pattern: String,
@@ -145,6 +152,7 @@ pub struct GrepSearchInput {
pub multiline: Option<bool>,
}
/// Result payload returned by the grep-style search tool.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct GrepSearchOutput {
pub mode: Option<String>,
@@ -162,6 +170,7 @@ pub struct GrepSearchOutput {
pub applied_offset: Option<usize>,
}
/// Reads a text file and returns a line-windowed payload.
pub fn read_file(
path: &str,
offset: Option<usize>,
@@ -210,6 +219,7 @@ pub fn read_file(
})
}
/// Replaces a file's contents and returns patch metadata.
pub fn write_file(path: &str, content: &str) -> io::Result<WriteFileOutput> {
if content.len() > MAX_WRITE_SIZE {
return Err(io::Error::new(
@@ -243,6 +253,7 @@ pub fn write_file(path: &str, content: &str) -> io::Result<WriteFileOutput> {
})
}
/// Performs an in-file string replacement and returns patch metadata.
pub fn edit_file(
path: &str,
old_string: &str,
@@ -283,6 +294,7 @@ pub fn edit_file(
})
}
/// Expands a glob pattern and returns matching filenames.
pub fn glob_search(pattern: &str, path: Option<&str>) -> io::Result<GlobSearchOutput> {
let started = Instant::now();
let base_dir = path
@@ -326,6 +338,7 @@ pub fn glob_search(pattern: &str, path: Option<&str>) -> io::Result<GlobSearchOu
})
}
/// Runs a regex search over workspace files with optional context lines.
pub fn grep_search(input: &GrepSearchInput) -> io::Result<GrepSearchOutput> {
let base_path = input
.path

View File

@@ -1,3 +1,9 @@
//! Core runtime primitives for the `claw` CLI and supporting crates.
//!
//! This crate owns session persistence, permission evaluation, prompt assembly,
//! MCP plumbing, tool-facing file operations, and the core conversation loop
//! that drives interactive and one-shot turns.
mod bash;
pub mod bash_validation;
mod bootstrap;
@@ -134,17 +140,14 @@ pub use stale_branch::{
apply_policy, check_freshness, BranchFreshness, StaleBranchAction, StaleBranchEvent,
StaleBranchPolicy,
};
pub use task_packet::{
validate_packet, TaskPacket, TaskPacketValidationError, ValidatedPacket,
};
pub use task_packet::{validate_packet, TaskPacket, TaskPacketValidationError, ValidatedPacket};
pub use trust_resolver::{TrustConfig, TrustDecision, TrustEvent, TrustPolicy, TrustResolver};
pub use usage::{
format_usd, pricing_for_model, ModelPricing, TokenUsage, UsageCostEstimate, UsageTracker,
};
pub use worker_boot::{
Worker, WorkerEvent, WorkerEventKind, WorkerEventPayload, WorkerFailure, WorkerFailureKind,
WorkerPromptTarget, WorkerReadySnapshot, WorkerRegistry, WorkerStatus,
WorkerTrustResolution,
WorkerPromptTarget, WorkerReadySnapshot, WorkerRegistry, WorkerStatus, WorkerTrustResolution,
};
#[cfg(test)]

View File

@@ -9,6 +9,7 @@ use sha2::{Digest, Sha256};
use crate::config::OAuthConfig;
/// Persisted OAuth access token bundle used by the CLI.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct OAuthTokenSet {
pub access_token: String,
@@ -17,6 +18,7 @@ pub struct OAuthTokenSet {
pub scopes: Vec<String>,
}
/// PKCE verifier/challenge pair generated for an OAuth authorization flow.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PkceCodePair {
pub verifier: String,
@@ -24,6 +26,7 @@ pub struct PkceCodePair {
pub challenge_method: PkceChallengeMethod,
}
/// Challenge algorithms supported by the local PKCE helpers.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PkceChallengeMethod {
S256,
@@ -38,6 +41,7 @@ impl PkceChallengeMethod {
}
}
/// Parameters needed to build an authorization URL for browser-based login.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OAuthAuthorizationRequest {
pub authorize_url: String,
@@ -50,6 +54,7 @@ pub struct OAuthAuthorizationRequest {
pub extra_params: BTreeMap<String, String>,
}
/// Request body for exchanging an OAuth authorization code for tokens.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OAuthTokenExchangeRequest {
pub grant_type: &'static str,
@@ -60,6 +65,7 @@ pub struct OAuthTokenExchangeRequest {
pub state: String,
}
/// Request body for refreshing an existing OAuth token set.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OAuthRefreshRequest {
pub grant_type: &'static str,
@@ -68,6 +74,7 @@ pub struct OAuthRefreshRequest {
pub scopes: Vec<String>,
}
/// Parsed query parameters returned to the local OAuth callback endpoint.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OAuthCallbackParams {
pub code: Option<String>,

View File

@@ -4,6 +4,7 @@ use serde_json::Value;
use crate::config::RuntimePermissionRuleConfig;
/// Permission level assigned to a tool invocation or runtime session.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum PermissionMode {
ReadOnly,
@@ -26,6 +27,7 @@ impl PermissionMode {
}
}
/// Hook-provided override applied before standard permission evaluation.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PermissionOverride {
Allow,
@@ -33,6 +35,7 @@ pub enum PermissionOverride {
Ask,
}
/// Additional permission context supplied by hooks or higher-level orchestration.
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct PermissionContext {
override_decision: Option<PermissionOverride>,
@@ -62,6 +65,7 @@ impl PermissionContext {
}
}
/// Full authorization request presented to a permission prompt.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PermissionRequest {
pub tool_name: String,
@@ -71,22 +75,26 @@ pub struct PermissionRequest {
pub reason: Option<String>,
}
/// User-facing decision returned by a [`PermissionPrompter`].
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PermissionPromptDecision {
Allow,
Deny { reason: String },
}
/// Prompting interface used when policy requires interactive approval.
pub trait PermissionPrompter {
fn decide(&mut self, request: &PermissionRequest) -> PermissionPromptDecision;
}
/// Final authorization result after evaluating static rules and prompts.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PermissionOutcome {
Allow,
Deny { reason: String },
}
/// Evaluates permission mode requirements plus allow/deny/ask rules.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PermissionPolicy {
active_mode: PermissionMode,

View File

@@ -5,6 +5,7 @@ use std::process::Command;
use crate::config::{ConfigError, ConfigLoader, RuntimeConfig};
/// Errors raised while assembling the final system prompt.
#[derive(Debug)]
pub enum PromptBuildError {
Io(std::io::Error),
@@ -34,17 +35,21 @@ impl From<ConfigError> for PromptBuildError {
}
}
/// Marker separating static prompt scaffolding from dynamic runtime context.
pub const SYSTEM_PROMPT_DYNAMIC_BOUNDARY: &str = "__SYSTEM_PROMPT_DYNAMIC_BOUNDARY__";
/// Human-readable default frontier model name embedded into generated prompts.
pub const FRONTIER_MODEL_NAME: &str = "Claude Opus 4.6";
const MAX_INSTRUCTION_FILE_CHARS: usize = 4_000;
const MAX_TOTAL_INSTRUCTION_CHARS: usize = 12_000;
/// Contents of an instruction file included in prompt construction.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ContextFile {
pub path: PathBuf,
pub content: String,
}
/// Project-local context injected into the rendered system prompt.
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct ProjectContext {
pub cwd: PathBuf,
@@ -81,6 +86,7 @@ impl ProjectContext {
}
}
/// Builder for the runtime system prompt and dynamic environment sections.
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct SystemPromptBuilder {
output_style_name: Option<String>,
@@ -184,6 +190,7 @@ impl SystemPromptBuilder {
}
}
/// Formats each item as an indented bullet for prompt sections.
#[must_use]
pub fn prepend_bullets(items: Vec<String>) -> Vec<String> {
items.into_iter().map(|item| format!(" - {item}")).collect()
@@ -401,6 +408,7 @@ fn collapse_blank_lines(content: &str) -> String {
result
}
/// Loads config and project context, then renders the system prompt text.
pub fn load_system_prompt(
cwd: impl Into<PathBuf>,
current_date: impl Into<String>,

View File

@@ -14,6 +14,7 @@ const ROTATE_AFTER_BYTES: u64 = 256 * 1024;
const MAX_ROTATED_FILES: usize = 3;
static SESSION_ID_COUNTER: AtomicU64 = AtomicU64::new(0);
/// Speaker role associated with a persisted conversation message.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MessageRole {
System,
@@ -22,6 +23,7 @@ pub enum MessageRole {
Tool,
}
/// Structured message content stored inside a [`Session`].
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ContentBlock {
Text {
@@ -40,6 +42,7 @@ pub enum ContentBlock {
},
}
/// One conversation message with optional token-usage metadata.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ConversationMessage {
pub role: MessageRole,
@@ -47,6 +50,7 @@ pub struct ConversationMessage {
pub usage: Option<TokenUsage>,
}
/// Metadata describing the latest compaction that summarized a session.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SessionCompaction {
pub count: u32,
@@ -54,6 +58,7 @@ pub struct SessionCompaction {
pub summary: String,
}
/// Provenance recorded when a session is forked from another session.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SessionFork {
pub parent_session_id: String,
@@ -65,6 +70,7 @@ struct SessionPersistence {
path: PathBuf,
}
/// Persisted conversational state for the runtime and CLI session manager.
#[derive(Debug, Clone)]
pub struct Session {
pub version: u32,
@@ -91,6 +97,7 @@ impl PartialEq for Session {
impl Eq for Session {}
/// Errors raised while loading, parsing, or saving sessions.
#[derive(Debug)]
pub enum SessionError {
Io(std::io::Error),

View File

@@ -5,6 +5,7 @@ const DEFAULT_OUTPUT_COST_PER_MILLION: f64 = 75.0;
const DEFAULT_CACHE_CREATION_COST_PER_MILLION: f64 = 18.75;
const DEFAULT_CACHE_READ_COST_PER_MILLION: f64 = 1.5;
/// Per-million-token pricing used for cost estimation.
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct ModelPricing {
pub input_cost_per_million: f64,
@@ -25,6 +26,7 @@ impl ModelPricing {
}
}
/// Token counters accumulated for a conversation turn or session.
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct TokenUsage {
pub input_tokens: u32,
@@ -33,6 +35,7 @@ pub struct TokenUsage {
pub cache_read_input_tokens: u32,
}
/// Estimated dollar cost derived from a [`TokenUsage`] sample.
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct UsageCostEstimate {
pub input_cost_usd: f64,
@@ -51,6 +54,7 @@ impl UsageCostEstimate {
}
}
/// Returns pricing metadata for a known model alias or family.
#[must_use]
pub fn pricing_for_model(model: &str) -> Option<ModelPricing> {
let normalized = model.to_ascii_lowercase();
@@ -155,10 +159,12 @@ fn cost_for_tokens(tokens: u32, usd_per_million_tokens: f64) -> f64 {
}
#[must_use]
/// Formats a dollar-denominated value for CLI display.
pub fn format_usd(amount: f64) -> String {
format!("${amount:.4}")
}
/// Aggregates token usage across a running session.
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct UsageTracker {
latest_turn: TokenUsage,