sqlite_graphrag/extract/llm_embedding/
builder.rs1use super::binary::resolve_real_binary;
4use super::models::{claude_embed_model, codex_embed_model, opencode_embed_model};
5use super::types::EmbeddingFlavour;
6use super::LlmEmbedding;
7use crate::errors::AppError;
8
9#[derive(Clone, Debug)]
16pub struct LlmEmbeddingBuilder {
17 pub(crate) flavour: EmbeddingFlavour,
19 pub(crate) binary_override: Option<std::path::PathBuf>,
21 pub(crate) model_override: Option<String>,
23 pub(crate) timeout_override: Option<std::time::Duration>,
25}
26
27impl LlmEmbeddingBuilder {
28 pub fn claude_default() -> Self {
33 Self {
34 flavour: EmbeddingFlavour::Claude,
35 binary_override: None,
36 model_override: None,
37 timeout_override: None,
38 }
39 }
40
41 pub fn codex_default() -> Self {
44 Self {
45 flavour: EmbeddingFlavour::Codex,
46 binary_override: None,
47 model_override: None,
48 timeout_override: None,
49 }
50 }
51
52 pub fn opencode_default() -> Self {
55 Self {
56 flavour: EmbeddingFlavour::Opencode,
57 binary_override: None,
58 model_override: None,
59 timeout_override: None,
60 }
61 }
62 pub fn override_binary(mut self, binary: std::path::PathBuf) -> Self {
64 self.binary_override = Some(binary);
65 self
66 }
67
68 pub fn override_model(mut self, model: String) -> Self {
70 self.model_override = Some(model);
71 self
72 }
73
74 pub fn override_timeout(mut self, secs: u64) -> Self {
77 let clamped = secs.clamp(1, 3_600);
78 self.timeout_override = Some(std::time::Duration::from_secs(clamped));
79 self
80 }
81
82 pub fn build(self) -> Result<LlmEmbedding, AppError> {
85 LlmEmbedding::oauth_only_enforce()?;
86 let binary = match self.binary_override {
87 Some(path) => resolve_real_binary(&path),
88 None => {
89 let (xdg_bin, which_name) = match self.flavour {
91 EmbeddingFlavour::Codex => (crate::runtime_config::codex_binary(), "codex"),
92 EmbeddingFlavour::Claude => (crate::runtime_config::claude_binary(), "claude"),
93 EmbeddingFlavour::Opencode => {
94 (crate::runtime_config::opencode_binary(), "opencode")
95 }
96 };
97 let path = xdg_bin
98 .map(std::path::PathBuf::from)
99 .or_else(|| which::which(which_name).ok())
100 .ok_or_else(|| {
101 AppError::Embedding(
102 crate::i18n::validation::embedding_binary_not_found_on_path(which_name),
103 )
104 })?;
105 resolve_real_binary(&path)
106 }
107 };
108 let model = match self.model_override {
109 Some(m) => m,
110 None => match self.flavour {
111 EmbeddingFlavour::Codex => codex_embed_model(),
112 EmbeddingFlavour::Claude => claude_embed_model(),
113 EmbeddingFlavour::Opencode => opencode_embed_model(),
114 },
115 };
116 Ok(LlmEmbedding::from_parts(
117 self.flavour,
118 binary,
119 model,
120 self.timeout_override,
121 ))
122 }
123}