Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions bt-daemon/src/agents/antigravity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub(crate) struct Antigravity;
pub(crate) const IDENTITY: Identity = Identity {
id: "antigravity",
source: "antigravity",
aliases: &["agy"],
aliases: &[],
display_name: "Google Antigravity",
};

Expand All @@ -18,6 +18,7 @@ impl Agent for Antigravity {

impl Register for Antigravity {
fn register(self: Arc<Self>, registrar: &mut Registrar) {
registrar.setup.insert(self);
registrar.setup.insert(self.clone());
registrar.translate.insert(self);
}
}
3 changes: 2 additions & 1 deletion bt-daemon/src/agents/claude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ impl Agent for Claude {
impl Register for Claude {
fn register(self: Arc<Self>, registrar: &mut Registrar) {
registrar.setup.insert(self.clone());
registrar.run.insert(self);
registrar.run.insert(self.clone());
registrar.translate.insert(self);
}
}
3 changes: 2 additions & 1 deletion bt-daemon/src/agents/codex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ impl Agent for Codex {
impl Register for Codex {
fn register(self: Arc<Self>, registrar: &mut Registrar) {
registrar.setup.insert(self.clone());
registrar.run.insert(self);
registrar.run.insert(self.clone());
registrar.translate.insert(self);
}
}
3 changes: 2 additions & 1 deletion bt-daemon/src/agents/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ impl Agent for Cursor {
impl Register for Cursor {
fn register(self: Arc<Self>, registrar: &mut Registrar) {
registrar.setup.insert(self.clone());
registrar.run.insert(self);
registrar.run.insert(self.clone());
registrar.translate.insert(self);
}
}
3 changes: 2 additions & 1 deletion bt-daemon/src/agents/grok.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ impl Agent for Grok {

impl Register for Grok {
fn register(self: Arc<Self>, registrar: &mut Registrar) {
registrar.setup.insert(self);
registrar.setup.insert(self.clone());
registrar.translate.insert(self);
}
}
6 changes: 6 additions & 0 deletions bt-daemon/src/agents/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub(crate) use pi::Pi;

use crate::managed_run::ManagedRun;
use crate::setup::Setup;
use crate::translate::TranslatorFactory;
use std::sync::{Arc, OnceLock};

/// The names an agent is known by.
Expand Down Expand Up @@ -72,13 +73,18 @@ impl<T: ?Sized + Agent> Agents<T> {
.find(|agent| agent.identity().matches(name))
.map(|agent| &**agent)
}

pub fn shared(&self) -> impl Iterator<Item = &Arc<T>> {
self.agents.iter()
}
}

/// Every capability registry. Agents add themselves in [`Register::register`].
#[derive(Default)]
pub(crate) struct Registrar {
pub setup: Agents<dyn Setup>,
pub run: Agents<dyn ManagedRun>,
pub translate: Agents<dyn TranslatorFactory>,
}

pub(crate) trait Register {
Expand Down
3 changes: 2 additions & 1 deletion bt-daemon/src/agents/opencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ impl Agent for OpenCode {
impl Register for OpenCode {
fn register(self: Arc<Self>, registrar: &mut Registrar) {
registrar.setup.insert(self.clone());
registrar.run.insert(self);
registrar.run.insert(self.clone());
registrar.translate.insert(self);
}
}
3 changes: 2 additions & 1 deletion bt-daemon/src/agents/pi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ impl Agent for Pi {
impl Register for Pi {
fn register(self: Arc<Self>, registrar: &mut Registrar) {
registrar.setup.insert(self.clone());
registrar.run.insert(self);
registrar.run.insert(self.clone());
registrar.translate.insert(self);
}
}
4 changes: 1 addition & 3 deletions bt-daemon/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,4 @@ pub use trace_runtime::{
run_trace, HostRouteSelection, RouteRequirements, TraceHostContext, TraceHostServices,
};
pub use transcript_import::{import_transcript, import_transcripts, run_import};
pub use translate::{
AgentTranslator, Registry, SessionCtx, SpanOp, SpanRow, SpanType, TranslatorFactory,
};
pub use translate::{AgentTranslator, Registry, SessionCtx, SpanOp, SpanRow, SpanType};
21 changes: 5 additions & 16 deletions bt-daemon/src/translate/antigravity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,12 @@ use std::io::{BufRead, Seek, SeekFrom};
use std::path::Path;
use std::sync::Arc;

pub struct AntigravityTranslatorFactory {
git: Arc<GitMetadataCache>,
}

impl AntigravityTranslatorFactory {
pub(super) fn new(git: Arc<GitMetadataCache>) -> Self {
Self { git }
}
}

impl TranslatorFactory for AntigravityTranslatorFactory {
fn source(&self) -> &str {
"antigravity"
}

impl TranslatorFactory for crate::agents::Antigravity {
fn create(&self, session_id: &str) -> Box<dyn AgentTranslator> {
Box::new(AntigravityTranslator::new(session_id, self.git.clone()))
Box::new(AntigravityTranslator::new(
session_id,
GitMetadataCache::shared(),
))
}
}

Expand Down
21 changes: 5 additions & 16 deletions bt-daemon/src/translate/claude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,23 +119,12 @@ fn value_as_nonempty_string(value: &Value) -> Option<String> {
}
}

pub struct ClaudeTranslatorFactory {
git: Arc<GitMetadataCache>,
}

impl ClaudeTranslatorFactory {
pub(super) fn new(git: Arc<GitMetadataCache>) -> Self {
Self { git }
}
}

impl TranslatorFactory for ClaudeTranslatorFactory {
fn source(&self) -> &str {
"claude-code"
}

impl TranslatorFactory for crate::agents::Claude {
fn create(&self, session_id: &str) -> Box<dyn AgentTranslator> {
Box::new(ClaudeTranslator::new(session_id, self.git.clone()))
Box::new(ClaudeTranslator::new(
session_id,
GitMetadataCache::shared(),
))
}
}

Expand Down
17 changes: 2 additions & 15 deletions bt-daemon/src/translate/codex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,20 +108,7 @@ fn decode<T: DeserializeOwned>(value: &Value) -> Option<T> {
serde_json::from_value(value.clone()).ok()
}

pub struct CodexTranslatorFactory {
git: Arc<GitMetadataCache>,
}

impl CodexTranslatorFactory {
pub(super) fn new(git: Arc<GitMetadataCache>) -> Self {
Self { git }
}
}

impl TranslatorFactory for CodexTranslatorFactory {
fn source(&self) -> &str {
"codex"
}
impl TranslatorFactory for crate::agents::Codex {
fn create(&self, session_id: &str) -> Box<dyn AgentTranslator> {
let root_span_id = ids::span_id(session_id, "root");
Box::new(CodexTranslator {
Expand All @@ -144,7 +131,7 @@ impl TranslatorFactory for CodexTranslatorFactory {
compaction_trigger_by_turn: RecentMap::default(),
compaction_spans: RecentSet::default(),
pending: None,
git: self.git.clone(),
git: GitMetadataCache::shared(),
})
}
}
Expand Down
18 changes: 5 additions & 13 deletions bt-daemon/src/translate/cursor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,20 +62,12 @@ const CURSOR_METADATA_FIELDS: &[&str] = &[
"replacement_context_available",
];

pub struct CursorTranslatorFactory {
git: Arc<GitMetadataCache>,
}
impl CursorTranslatorFactory {
pub(super) fn new(git: Arc<GitMetadataCache>) -> Self {
Self { git }
}
}
impl TranslatorFactory for CursorTranslatorFactory {
fn source(&self) -> &str {
"cursor"
}
impl TranslatorFactory for crate::agents::Cursor {
fn create(&self, session_id: &str) -> Box<dyn AgentTranslator> {
Box::new(CursorTranslator::new(session_id, self.git.clone()))
Box::new(CursorTranslator::new(
session_id,
GitMetadataCache::shared(),
))
}
}

Expand Down
21 changes: 17 additions & 4 deletions bt-daemon/src/translate/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,28 @@
//! exists.

use super::{AgentTranslator, SessionCtx, SpanOp, SpanRow, SpanType, TranslatorFactory};
use crate::agents::{Agent, Identity};
use crate::ids;
use crate::wire::Envelope;

pub struct DebugTranslatorFactory;
/// Not a coding agent, so it is never registered in [`crate::agents`]; the
/// translator registry adds it directly.
pub(crate) struct DebugTranslatorFactory;

impl TranslatorFactory for DebugTranslatorFactory {
fn source(&self) -> &str {
"debug"
const IDENTITY: Identity = Identity {
id: "debug",
source: "debug",
aliases: &[],
display_name: "Debug",
};

impl Agent for DebugTranslatorFactory {
fn identity(&self) -> &'static Identity {
&IDENTITY
}
}

impl TranslatorFactory for DebugTranslatorFactory {
fn create(&self, session_id: &str) -> Box<dyn AgentTranslator> {
Box::new(DebugTranslator {
root_span_id: ids::span_id(session_id, "root"),
Expand Down
10 changes: 9 additions & 1 deletion bt-daemon/src/translate/git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::{SpanOp, SpanRow};
use serde_json::{Map, Value};
use std::collections::{HashMap, VecDeque};
use std::path::{Path, PathBuf};
use std::sync::Mutex;
use std::sync::{Arc, Mutex, OnceLock};
use std::time::{Duration, Instant, SystemTime};

const CACHE_CAPACITY: usize = 256;
Expand Down Expand Up @@ -89,6 +89,14 @@ impl Default for GitMetadataCache {
}

impl GitMetadataCache {
/// The process-wide cache shared by every translator. Repository entries
/// are revalidated against the git directory before reuse and "not a
/// repository" results expire, so sharing them across registries is safe.
pub(super) fn shared() -> Arc<Self> {
static SHARED: OnceLock<Arc<GitMetadataCache>> = OnceLock::new();
SHARED.get_or_init(Arc::default).clone()
}

pub(super) fn metadata(&self, cwd: &str) -> Map<String, Value> {
if cwd.is_empty() {
return Map::new();
Expand Down
18 changes: 2 additions & 16 deletions bt-daemon/src/translate/grok.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,9 @@ const MAX_OUTPUT_CHUNKS: usize = 2_048;
const MAX_OUTPUT_BYTES: usize = 2 * 1024 * 1024;
const MAX_SYSTEM_PROMPT_BYTES: u64 = 2 * 1024 * 1024;

pub struct GrokTranslatorFactory {
git: Arc<GitMetadataCache>,
}

impl GrokTranslatorFactory {
pub(super) fn new(git: Arc<GitMetadataCache>) -> Self {
Self { git }
}
}

impl TranslatorFactory for GrokTranslatorFactory {
fn source(&self) -> &str {
"grok"
}

impl TranslatorFactory for crate::agents::Grok {
fn create(&self, session_id: &str) -> Box<dyn AgentTranslator> {
Box::new(GrokTranslator::new(session_id, self.git.clone()))
Box::new(GrokTranslator::new(session_id, GitMetadataCache::shared()))
}
}

Expand Down
Loading
Loading