scv_tools/config.rs
1//! What a session's built-in tools are configured with: limits, the
2//! delegation context, and each delegated agent's adapter settings.
3
4use std::{collections::HashMap, ffi::OsString, path::PathBuf, sync::Arc, time::Duration};
5
6use crate::{
7 builtin::{chat_attach, chat_history},
8 delegate::{
9 adapters::{OutputFormat, Resume, Transport},
10 background,
11 conversation::ConversationLimits,
12 records::DelegationRegistry,
13 },
14};
15
16/// Limits and shared state for one session's tools.
17#[derive(Debug, Clone)]
18pub struct ToolsConfig {
19 /// Default `bash` timeout when a call does not choose one.
20 pub command_timeout: Duration,
21 /// Default native-agent timeout when a call does not choose one.
22 pub agent_timeout: Duration,
23 /// The longest timeout any single call may request.
24 pub max_timeout: Duration,
25 pub output_limit_bytes: usize,
26 pub max_read_bytes: usize,
27 pub max_write_bytes: usize,
28 /// The `agent` tool is offered only below this delegation depth.
29 pub max_delegation_depth: u32,
30 /// Agents the user prefers, in order (`[agent] prefer`); the first one
31 /// offered runs an `agent` call that names none.
32 pub prefer: Vec<String>,
33 /// How many delegated conversations a session remembers, and for how long.
34 pub conversations: ConversationLimits,
35 /// Records delegated runs for listing and cleanup; `None` runs them untracked.
36 pub delegation: Option<DelegationContext>,
37 /// Background jobs `agent` calls may run at once (`background: true`);
38 /// 0 turns background calls and `agent_wait` / `agent_status` /
39 /// `agent_cancel` off.
40 pub max_background: usize,
41 /// The session's background job store, when the server reports finished
42 /// jobs; otherwise the registry makes its own.
43 pub background: Option<Arc<background::BackgroundJobs>>,
44 /// Offers `chat_attach` when the session answers on a chat channel.
45 pub chat_attach: Option<chat_attach::ChatAttachConfig>,
46 /// Offers `chat_history` and `chat_keep` when the session answers a
47 /// conversation that has a chat log.
48 pub chat_history: Option<chat_history::ChatHistoryConfig>,
49}
50
51impl Default for ToolsConfig {
52 fn default() -> Self {
53 Self {
54 command_timeout: Duration::from_secs(600),
55 agent_timeout: Duration::from_secs(3600),
56 max_timeout: Duration::from_secs(14400),
57 output_limit_bytes: 64 * 1024,
58 max_read_bytes: 256 * 1024,
59 max_write_bytes: 1024 * 1024,
60 max_delegation_depth: 2,
61 prefer: Vec::new(),
62 conversations: ConversationLimits {
63 max: 8,
64 idle: Duration::from_secs(86400),
65 },
66 delegation: None,
67 max_background: 2,
68 background: None,
69 chat_attach: None,
70 chat_history: None,
71 }
72 }
73}
74
75/// The registry and parent session that delegated runs are recorded under.
76#[derive(Debug, Clone)]
77pub struct DelegationContext {
78 pub registry: Arc<DelegationRegistry>,
79 pub session: String,
80 /// Delegation depth the session's client declared (0 for a direct
81 /// client). Runs count from the larger of this and the process's own.
82 pub depth: u32,
83}
84
85impl DelegationContext {
86 /// The depth delegated runs of this session start from.
87 pub(crate) fn owner_depth(&self) -> u32 {
88 self.registry.depth().max(self.depth)
89 }
90}
91
92#[derive(Debug, Clone)]
93pub struct AgentAdapterConfig {
94 pub command: String,
95 pub args: Vec<String>,
96 /// Arguments placed immediately before the prompt, for CLIs that take the
97 /// prompt as a flag value.
98 pub prompt_args: Vec<String>,
99 /// The CLI's own full-autonomy arguments, placed after `args`, when the
100 /// user configured `permissions = "full"`; the approval summary says so.
101 pub full_permission_args: Option<Vec<String>>,
102 /// Arguments appended for a per-call model; `{model}` is substituted.
103 /// Empty means the adapter does not offer model selection.
104 pub model_args: Vec<String>,
105 /// Arguments appended for a per-call effort; `{effort}` is substituted.
106 /// Empty means the adapter does not offer effort selection.
107 pub effort_args: Vec<String>,
108 /// Describes the `model` argument for the calling model.
109 pub model_hint: String,
110 /// Environment for the nested process. SCV supplies an instance-private home.
111 pub environment: Vec<(OsString, OsString)>,
112 /// Per-user install directories searched when `command` is not on `PATH`.
113 pub search_dirs: Vec<PathBuf>,
114 /// What the CLI prints, and so how its reply is read.
115 pub output: OutputFormat,
116 /// How a conversation with the CLI is continued, if it can be.
117 pub resume: Resume,
118 /// SCV's private home for this agent, for files SCV hands the CLI.
119 pub home: Option<PathBuf>,
120 /// How SCV talks to the agent.
121 pub transport: Transport,
122 /// The agent's ACP server, when `[agents.<name>] transport` allows it and
123 /// the adapter table has one.
124 pub acp: Option<AcpAgentLaunch>,
125 /// The user's note on when to choose this agent (`[agents.<name>]
126 /// use_for`), added to its line in the `agent` tool's description.
127 pub use_for: Option<String>,
128 /// Default model to pass when the work matches `use_for` (or on every
129 /// call to this agent, when `use_for` is unset).
130 pub model: Option<String>,
131 /// Default effort to pass the same way as `model`.
132 pub effort: Option<String>,
133}
134
135/// An agent's Agent Client Protocol server, resolved from its adapter-table
136/// entry and `[agents.<name>] transport`.
137#[derive(Debug, Clone)]
138pub struct AcpAgentLaunch {
139 pub command: String,
140 /// Arguments with the `permissions = "full"` switches already applied.
141 pub args: Vec<String>,
142 /// The ACP session mode that grants full permissions, selected in every
143 /// new session when `permissions = "full"`.
144 pub full_mode: Option<String>,
145 /// Extra environment for the ACP server, such as permission settings the
146 /// server reads only from its environment.
147 pub environment: Vec<(OsString, OsString)>,
148 /// `transport = "acp"`: never fall back to one CLI process per turn, so
149 /// the agent is not offered while its ACP server is missing.
150 pub required: bool,
151}
152
153pub type SkillMap = HashMap<String, PathBuf>;