mirror of
https://github.com/instructkr/claw-code.git
synced 2026-04-05 23:54:50 +08:00
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:
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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>,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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>,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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>,
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user