Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
17d5e87
Add the Synthetic provider
Finesssee Oct 11, 2026
b358acd
Add the ClawRouter provider
Finesssee Oct 11, 2026
5ce549d
Add the IBM Bob provider
Finesssee Oct 11, 2026
0a14898
Add the Langdock provider
Finesssee Oct 11, 2026
58eea49
Add the LithosAI provider
Finesssee Oct 11, 2026
e200608
Expose the LithosAI cookie source picker
Finesssee Oct 11, 2026
d722ffe
Expose the Langdock cookie source picker
Finesssee Oct 11, 2026
dea953c
Describe the Langdock picker against upstream accurately
Finesssee Oct 11, 2026
749b296
Merge remote-tracking branch 'origin/main' into feat/provider-synthetic
Finesssee Oct 11, 2026
3070281
Merge branch 'feat/provider-synthetic' into feat/provider-clawrouter
Finesssee Oct 11, 2026
f5dab54
Merge branch 'feat/provider-clawrouter' into feat/provider-ibmbob
Finesssee Oct 11, 2026
b801479
Merge branch 'feat/provider-ibmbob' into feat/provider-langdock
Finesssee Oct 11, 2026
0b556a6
Merge branch 'feat/provider-langdock' into feat/provider-lithosai
Finesssee Oct 11, 2026
3011182
Merge branch 'feat/provider-ibmbob' into feat/provider-langdock
Finesssee Oct 11, 2026
2fb5592
Merge branch 'feat/provider-clawrouter' into feat/provider-ibmbob
Finesssee Oct 11, 2026
b27bef0
Merge branch 'feat/provider-synthetic' into feat/provider-clawrouter
Finesssee Oct 11, 2026
7ae0c8d
Merge branch 'feat/provider-langdock' into feat/provider-lithosai
Finesssee Oct 11, 2026
fab0fde
Merge remote-tracking branch 'origin/main' into feat/provider-synthetic
Finesssee Oct 11, 2026
8c8f398
Langdock: pick the browser that holds auth_token
Finesssee Oct 11, 2026
ff82741
IBM Bob: show the upstream message when no API key is set
Finesssee Oct 11, 2026
5ad2913
ClawRouter: classify rejected keys as needs-auth
Finesssee Oct 11, 2026
d814f9d
LithosAI: keep debts visible and try every browser session
Finesssee Oct 11, 2026
ad8e802
Synthetic: hide weekly cost like the Mac card
Finesssee Oct 11, 2026
b375963
Merge branch 'feat/provider-synthetic' into feat/provider-clawrouter
Finesssee Oct 11, 2026
876d6a6
Merge branch 'feat/provider-clawrouter' into feat/provider-ibmbob
Finesssee Oct 11, 2026
fa1d21a
Merge branch 'feat/provider-ibmbob' into feat/provider-langdock
Finesssee Oct 11, 2026
46c99e8
Merge branch 'feat/provider-langdock' into feat/provider-lithosai
Finesssee Oct 11, 2026
e121931
Merge remote-tracking branch 'origin/main' into feat/provider-synthetic
Finesssee Oct 11, 2026
fd471ad
Merge branch 'feat/provider-synthetic' into feat/provider-clawrouter
Finesssee Oct 11, 2026
dccba63
Merge branch 'feat/provider-clawrouter' into feat/provider-ibmbob
Finesssee Oct 11, 2026
c0875a6
Merge branch 'feat/provider-ibmbob' into feat/provider-langdock
Finesssee Oct 11, 2026
42b7ded
Merge branch 'feat/provider-langdock' into feat/provider-lithosai
Finesssee Oct 11, 2026
5fef9b1
Merge origin/main into feat/provider-synthetic
Finesssee Oct 11, 2026
97ac168
Merge feat/provider-synthetic into feat/provider-clawrouter
Finesssee Oct 11, 2026
b90e275
Merge feat/provider-clawrouter into feat/provider-ibmbob
Finesssee Oct 11, 2026
0188e55
Merge feat/provider-ibmbob into feat/provider-langdock
Finesssee Oct 11, 2026
88c9cb8
Merge feat/provider-langdock into feat/provider-lithosai
Finesssee Oct 11, 2026
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: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,18 @@ See the full history in [CHANGELOG.md](CHANGELOG.md).
| Raycast | Cookies (Chrome auto or manual) | Monthly AI credits, plan, renewal |
| Replicate | Cookies / token accounts | Monthly spend, credit balance |
| Aixy | API Key / token accounts | Applicable budget balances, 7-day key usage |
| ClawRouter | API Key | Monthly budget, requests, tokens, routed-provider spend |
| ElevenLabs | API Key | Subscription Credits, Voice Slots |
| Deepgram | API Key | Project Usage |
| Groq | API Key | Enterprise Metrics |
| LLM Proxy | API Key | Quota Stats |
| llmman | Local daemon / optional API Key | Memory in use, loaded and stored models |
| DevPass | API Key | Plan credits, Premium weekly, API-key spend |
| IBM Bob | API Key / token accounts | Monthly Bobcoins, per-team budgets |
| xKiro | API Key | Daily free tokens |
| Synthetic | API Key | Five-hour quota, Weekly tokens, Hourly search, Plan |
| Langdock | Browser cookies / manual Cookie header | Session (5h), Weekly |
| LithosAI | Browser cookies / manual Cookie header | Prepaid balance, UTC spend today and this month |

</details>

Expand Down
23 changes: 23 additions & 0 deletions apps/desktop-tauri/src-tauri/src/commands/provider_settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,8 @@ fn cookie_source_provider(provider_id: &str) -> Option<codexbar::core::ProviderI
"typesafe" => ProviderId::TypeSafe,
"hyper" => ProviderId::Hyper,
"groq" => ProviderId::Groq,
"lithosai" => ProviderId::LithosAI,
"langdock" => ProviderId::Langdock,
_ => return None,
})
}
Expand Down Expand Up @@ -453,6 +455,7 @@ mod tests {
(ProviderId::Wayfinder, "http://localhost:8787"),
(ProviderId::Bifrost, "https://bifrost.example.com"),
(ProviderId::Aixy, "https://aixy.example.com/prefix"),
(ProviderId::ClawRouter, "https://router.example.com/v1"),
] {
settings.set_gateway_url(id, url);
let ctx = super::super::providers::build_fetch_context(
Expand Down Expand Up @@ -485,6 +488,7 @@ mod tests {
assert_eq!(gateway_provider("wayfinder"), Some(ProviderId::Wayfinder));
assert_eq!(gateway_provider("bifrost"), Some(ProviderId::Bifrost));
assert_eq!(gateway_provider("aixy"), Some(ProviderId::Aixy));
assert_eq!(gateway_provider("clawrouter"), Some(ProviderId::ClawRouter));
assert_eq!(gateway_provider("codex"), None);
}

Expand Down Expand Up @@ -548,6 +552,7 @@ fn gateway_provider(provider_id: &str) -> Option<codexbar::core::ProviderId> {
"wayfinder" => Some(codexbar::core::ProviderId::Wayfinder),
"bifrost" => Some(codexbar::core::ProviderId::Bifrost),
"aixy" => Some(codexbar::core::ProviderId::Aixy),
"clawrouter" => Some(codexbar::core::ProviderId::ClawRouter),
_ => None,
}
}
Expand Down Expand Up @@ -577,6 +582,10 @@ pub fn set_provider_gateway_url(provider_id: String, gateway_url: String) -> Res
codexbar::providers::aixy::validate_gateway_url(gateway_url)
.map_err(|error| error.to_string())?;
}
codexbar::core::ProviderId::ClawRouter => {
codexbar::providers::clawrouter::validate_gateway_url(gateway_url)
.map_err(|error| error.to_string())?;
}
_ => unreachable!("gateway_provider only returns gateway providers"),
}

Expand Down Expand Up @@ -853,6 +862,20 @@ pub fn cookie_source_options_for(provider_id: &str, lang: Language) -> Vec<Cooki
cookie_option(lang, "manual", None),
cookie_option(lang, "off", None),
],
// Upstream picks one Edge profile instead; Windows uses the shared
// cookie-source choices: automatic browser import, a pasted header, or off.
"langdock" => vec![
cookie_option(lang, "auto", None),
cookie_option(lang, "manual", None),
cookie_option(lang, "off", None),
],
// Upstream's LithosAI cookie source: automatic browser import,
// a pasted header, or off.
"lithosai" => vec![
cookie_option(lang, "auto", None),
cookie_option(lang, "manual", None),
cookie_option(lang, "off", None),
],
_ => Vec::new(),
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,85 @@ fn groq_exposes_a_cookie_source_picker_defaulting_to_auto() {
.collect();
assert_eq!(values, vec!["auto", "manual", "off"]);
}

/// Langdock is web-only: the picker chooses the session, a stored header
/// always wins, an empty manual source fails closed without reading a browser,
/// and off reaches the provider as Cli (its "cookies are disabled" error).
#[test]
fn langdock_exposes_a_cookie_source_picker_and_routes_each_choice() {
let settings = Settings::default();
assert_eq!(
super::provider_cookie_source_lookup(&settings, "langdock").as_deref(),
Some("auto")
);
let values: Vec<_> = super::cookie_source_options_for("langdock", Language::English)
.into_iter()
.map(|option| option.value)
.collect();
assert_eq!(values, vec!["auto", "manual", "off"]);

let cookie = "auth_token=fixture";
for source in ["auto", "manual"] {
let ctx = session_context(ProviderId::Langdock, Some(source), "auto", Some(cookie));
assert!(
matches!(ctx.source_mode, SourceMode::Auto | SourceMode::Web),
"{source}"
);
assert_eq!(
ctx.manual_cookie_header.as_deref(),
Some(cookie),
"{source}"
);
assert!(!ctx.manual_cookie_missing, "{source}");
}

let ctx = session_context(ProviderId::Langdock, Some("manual"), "auto", None);
assert_eq!(ctx.source_mode, SourceMode::Web);
assert!(ctx.manual_cookie_header.is_none());
assert!(ctx.manual_cookie_missing);

let ctx = session_context(ProviderId::Langdock, Some("off"), "auto", Some(cookie));
assert_eq!(ctx.source_mode, SourceMode::Cli);
assert!(ctx.manual_cookie_header.is_none());
}

/// LithosAI is web-only: the picker chooses the session, a stored header
/// always wins, an empty manual source fails closed without reading a browser,
/// and off reaches the provider as Cli (its "cookies are disabled" error).
#[test]
fn lithosai_exposes_a_cookie_source_picker_and_routes_each_choice() {
let settings = Settings::default();
assert_eq!(
super::provider_cookie_source_lookup(&settings, "lithosai").as_deref(),
Some("auto")
);
let values: Vec<_> = super::cookie_source_options_for("lithosai", Language::English)
.into_iter()
.map(|option| option.value)
.collect();
assert_eq!(values, vec!["auto", "manual", "off"]);

let cookie = "__Host-console_session=fixture; __Host-console_csrf=fixture";
for source in ["auto", "manual"] {
let ctx = session_context(ProviderId::LithosAI, Some(source), "auto", Some(cookie));
assert!(
matches!(ctx.source_mode, SourceMode::Auto | SourceMode::Web),
"{source}"
);
assert_eq!(
ctx.manual_cookie_header.as_deref(),
Some(cookie),
"{source}"
);
assert!(!ctx.manual_cookie_missing, "{source}");
}

let ctx = session_context(ProviderId::LithosAI, Some("manual"), "auto", None);
assert_eq!(ctx.source_mode, SourceMode::Web);
assert!(ctx.manual_cookie_header.is_none());
assert!(ctx.manual_cookie_missing);

let ctx = session_context(ProviderId::LithosAI, Some("off"), "auto", Some(cookie));
assert_eq!(ctx.source_mode, SourceMode::Cli);
assert!(ctx.manual_cookie_header.is_none());
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading