1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
use std::collections::HashSet;
use std::path::PathBuf;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use std::sync::mpsc;
use crate::daemon::DaemonCommand;
/// Session-level context passed through tool execution.
///
/// Carries the session ID, database handle, a channel to the daemon
/// command loop, and parent session config so tools (especially
/// spawn_subsession) can create child sessions with inherited settings.
#[derive(Clone)]
pub struct ToolContext {
/// The session that initiated this tool call.
pub session_id: u64,
/// Handle to the daemon's shared redb database.
pub db: Arc<redb::Database>,
/// Channel to the daemon command loop for daemon-level operations.
pub daemon_tx: mpsc::Sender<DaemonCommand>,
/// Tool groups active in the parent session (inherited by sub-sessions).
pub active_tool_groups: HashSet<String>,
/// Reasoning effort configured for the parent session.
pub reasoning_effort: Option<String>,
/// Model selected for the parent session (inherited by sub-sessions).
pub selected_model: Option<String>,
/// Working directory for the parent session (used as fallback working_dir).
pub working_dir: Option<PathBuf>,
/// Cancellation flag: set to `true` when the parent session is cancelled.
/// Tools that block indefinitely (e.g. `spawn_subsession`) should poll this
/// and abort when it becomes `true`.
///
/// This is the one sanctioned shared-mutable-state exception to the repo's
/// channel-only thread-communication rule (see AGENTS.md): a channel
/// message cannot interrupt a blocking tool call, so the flag is a
/// best-effort, data-free stop hint. All control flow — results,
/// cancellation events, kills, streaming — still travels over channels.
pub cancelled: Arc<AtomicBool>,
/// Account name used by the parent session (inherited by sub-sessions so
/// they can resolve the provider for model inference).
pub account_name: Option<String>,
}
impl ToolContext {
/// Convenience constructor for tests and simple usage where only the
/// session ID, database, and daemon channel are needed.
/// New config fields (`active_tool_groups`, `reasoning_effort`, `selected_model`, `working_dir`, `account_name`)
/// default to empty/None.
pub fn new(
session_id: u64,
db: Arc<redb::Database>,
daemon_tx: mpsc::Sender<DaemonCommand>,
) -> Self {
Self {
session_id,
db,
daemon_tx,
active_tool_groups: HashSet::new(),
reasoning_effort: None,
selected_model: None,
working_dir: None,
cancelled: Arc::new(AtomicBool::new(false)),
account_name: None,
}
}
}