Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ fn cookie_source_provider(provider_id: &str) -> Option<codexbar::core::ProviderI
"ollama" => ProviderId::Ollama,
"mistral" => ProviderId::Mistral,
"qoder" => ProviderId::Qoder,
"codebuddy" => ProviderId::CodeBuddy,
"sakana" => ProviderId::Sakana,
"notion" => ProviderId::Notion,
_ => return None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ export const PROVIDER_ICON_REGISTRY: Record<string, ProviderIcon> = {
crof: { id: "crof", brandColor: "#7c3aed", fallbackLetter: "C", svgPath: RAW.crof },
crossmodel: { id: "crossmodel", brandColor: "#c084fc", fallbackLetter: "X", svgPath: RAW.crossmodel },
qoder: { id: "qoder", brandColor: "#2563eb", fallbackLetter: "Q", svgPath: RAW.qoder },
codebuddy: { id: "codebuddy", brandColor: "#0052d9", fallbackLetter: "C" },
sakana: { id: "sakana", brandColor: "#0ea5e9", fallbackLetter: "S", svgPath: RAW.sakana },
stepfun: { id: "stepfun", brandColor: "#999999", fallbackLetter: "S", svgPath: RAW.stepfun },
sub2api: { id: "sub2api", brandColor: "#2dc6d8", fallbackLetter: "S", svgPath: RAW.sub2api },
Expand Down
9 changes: 9 additions & 0 deletions apps/desktop-tauri/src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -4228,19 +4228,28 @@ html:has(.menu-surface--tray) {
align-items: baseline;
justify-content: space-between;
gap: 8px;
min-width: 0; /* allow children to shrink/ellipsis inside flex */
}

.menu-metric__pct {
/* upstream: .font(.footnote) ≈ 11px primary */
font-size: 11px;
color: var(--text-primary);
font-variant-numeric: tabular-nums;
flex: 0 0 auto;
}

.menu-metric__reset {
font-size: 11px;
color: var(--text-secondary);
white-space: nowrap;
/* Long provider descriptions (credits remaining, etc.) used to overflow
the tray card because nowrap had no max-width/ellipsis. */
min-width: 0;
max-width: 62%;
overflow: hidden;
text-overflow: ellipsis;
text-align: right;
}

.menu-metric__exhausted {
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop-tauri/src/surfaces/TrayPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const HAS_DASHBOARD = new Set([
"doubao", "elevenlabs", "factory", "gemini", "grok", "groq",
"infini", "jetbrains", "kilo", "kimi", "kimik2", "kiro", "manus",
"mimo", "minimax", "mistral", "nanogpt", "notion", "ollama", "openaiapi",
"opencode", "opencodego", "openrouter", "perplexity", "qoder", "sakana", "stepfun",
"opencode", "opencodego", "openrouter", "perplexity", "qoder", "codebuddy", "sakana", "stepfun",
"t3chat", "venice", "vertexai", "warp", "windsurf",
"xai", "zai",
]);
Expand Down
1 change: 1 addition & 0 deletions apps/desktop-tauri/src/test/providerCatalog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export const TEST_PROVIDER_CATALOG: Array<[string, string]> = [
["zed", "Zed"],
["crossmodel", "CrossModel (removed)"],
["qoder", "Qoder"],
["codebuddy", "CodeBuddy"],
["sakana", "Sakana AI"],
["sub2api", "sub2api"],
["qwencloud", "Qwen Cloud"],
Expand Down
11 changes: 10 additions & 1 deletion rust/src/core/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ pub enum ProviderId {
Zed,
CrossModel,
Qoder,
CodeBuddy,
Sakana,
Sub2Api,
Wayfinder,
Expand Down Expand Up @@ -142,6 +143,7 @@ impl ProviderId {
ProviderId::Zed,
ProviderId::CrossModel,
ProviderId::Qoder,
ProviderId::CodeBuddy,
ProviderId::Sakana,
ProviderId::Sub2Api,
ProviderId::Wayfinder,
Expand Down Expand Up @@ -216,6 +218,7 @@ impl ProviderId {
ProviderId::Zed => "zed",
ProviderId::CrossModel => "crossmodel",
ProviderId::Qoder => "qoder",
ProviderId::CodeBuddy => "codebuddy",
ProviderId::Sakana => "sakana",
ProviderId::Sub2Api => "sub2api",
ProviderId::Wayfinder => "wayfinder",
Expand Down Expand Up @@ -292,6 +295,7 @@ impl ProviderId {
// Soft-removed (upstream #2254); still resolvable via CLI for legacy configs.
ProviderId::CrossModel => "CrossModel (removed)",
ProviderId::Qoder => "Qoder",
ProviderId::CodeBuddy => "CodeBuddy",
ProviderId::Sakana => "Sakana AI",
ProviderId::Sub2Api => "sub2api",
ProviderId::Wayfinder => "Wayfinder",
Expand Down Expand Up @@ -339,6 +343,7 @@ impl ProviderId {
ProviderId::CommandCode => Some("commandcode.ai"),
ProviderId::Grok => Some("grok.com"),
ProviderId::Qoder => Some("qoder.com"),
ProviderId::CodeBuddy => Some("codebuddy.cn"),
ProviderId::Sakana => Some("console.sakana.ai"),
ProviderId::LongCat => Some("longcat.chat"),
// Token-based providers (don't use cookies)
Expand Down Expand Up @@ -457,6 +462,9 @@ impl ProviderId {
Some(ProviderId::CrossModel)
}
"qoder" => Some(ProviderId::Qoder),
"codebuddy" | "code-buddy" | "codebuddy-cn" | "codebuddycn" | "腾讯codebuddy" => {
Some(ProviderId::CodeBuddy)
}
"sakana" | "sakana-ai" | "sakana ai" => Some(ProviderId::Sakana),
"sub2api" | "sub-2-api" | "sub 2 api" => Some(ProviderId::Sub2Api),
"wayfinder" => Some(ProviderId::Wayfinder),
Expand Down Expand Up @@ -724,7 +732,7 @@ mod tests {
#[test]
fn test_provider_id_all() {
let all = ProviderId::all();
assert_eq!(all.len(), 68);
assert_eq!(all.len(), 69);
assert!(all.contains(&ProviderId::Claude));
assert!(all.contains(&ProviderId::Codex));
assert!(all.contains(&ProviderId::Kimi));
Expand Down Expand Up @@ -762,6 +770,7 @@ mod tests {
assert!(all.contains(&ProviderId::Zed));
assert!(all.contains(&ProviderId::CrossModel));
assert!(all.contains(&ProviderId::Qoder));
assert!(all.contains(&ProviderId::CodeBuddy));
assert!(all.contains(&ProviderId::Sakana));
assert!(all.contains(&ProviderId::Sub2Api));
assert!(all.contains(&ProviderId::Wayfinder));
Expand Down
4 changes: 3 additions & 1 deletion rust/src/core/provider_factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ use crate::providers::{
LongCatProvider, ManusProvider, MiMoProvider, MiniMaxProvider, MistralProvider,
NanoGPTProvider, NeuralwattProvider, NotionProvider, OllamaProvider, OpenAIApiProvider,
OpenCodeGoProvider, OpenCodeProvider, OpenRouterProvider, PerplexityProvider, PoeProvider,
QoderProvider, QwenCloudProvider, SakanaProvider, StepFunProvider, Sub2ApiProvider,
CodeBuddyProvider, QoderProvider, QwenCloudProvider, SakanaProvider, StepFunProvider,
Sub2ApiProvider,
T3ChatProvider, VeniceProvider, VertexAIProvider, WarpProvider, WayfinderProvider,
WindsurfProvider, XaiProvider, ZaiProvider, ZedProvider, ZenMuxProvider, ZoomMateProvider,
};
Expand Down Expand Up @@ -85,6 +86,7 @@ pub fn instantiate(id: ProviderId) -> Box<dyn Provider> {
ProviderId::Zed => Box::new(ZedProvider::new()),
ProviderId::CrossModel => Box::new(CrossModelProvider::new()),
ProviderId::Qoder => Box::new(QoderProvider::new()),
ProviderId::CodeBuddy => Box::new(CodeBuddyProvider::new()),
ProviderId::Sakana => Box::new(SakanaProvider::new()),
ProviderId::Sub2Api => Box::new(Sub2ApiProvider::new()),
ProviderId::Wayfinder => Box::new(WayfinderProvider::new()),
Expand Down
8 changes: 8 additions & 0 deletions rust/src/core/token_accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,14 @@ impl TokenAccountSupport {
requires_manual_cookie_source: true,
cookie_name: None,
}),
ProviderId::CodeBuddy => Some(TokenAccountSupport {
title: "Session tokens",
subtitle: "Store CodeBuddy CN Cookie headers (from plans-usage DevTools cURL).",
placeholder: "Cookie: session=...; ... (or paste full Cookie header)",
injection: TokenInjection::CookieHeader,
requires_manual_cookie_source: true,
cookie_name: None,
}),
ProviderId::Sakana => Some(TokenAccountSupport {
title: "Session tokens",
subtitle: "Store multiple Sakana Console Cookie headers.",
Expand Down
83 changes: 83 additions & 0 deletions rust/src/providers/codebuddy/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# CodeBuddy (soft-fork)

Tencent **CodeBuddy CN** credit usage for Win-CodexBar.

## What it shows

- Primary meter: **Credits** used % across all returned resource packages
- Description: `remaining/total` plus package count
- Reset time: earliest package expire time when present

## Setup

1. Settings → Providers → enable **CodeBuddy**
2. Prefer **manual Cookie** (Chrome 127+ App-Bound Encryption often blocks auto-import):

- Open <https://www.codebuddy.cn/profile/plans-usage>
- DevTools → Network → `get-user-resource` → Copy as cURL
- Paste the `Cookie:` value into CodeBuddy settings / token account

3. Or put the cookie on one line in:

```
%USERPROFILE%\.codebuddy\cb_cookie.txt
```

(compatible with `D:\workspace\codebuddy-statusline`)

## API

```http
POST https://www.codebuddy.cn/billing/meter/get-user-resource
Origin: https://www.codebuddy.cn
Referer: https://www.codebuddy.cn/profile/plans-usage
User-Agent: Chrome/* (must NOT contain Edg/)
Cookie: …
Content-Type: application/json

{
"PageNumber": 1,
"PageSize": 200,
"ProductCode": "p_tcaca",
"Status": [0, 3],
"OnlyValidPeriod": true,
"PackageCodes": [ "TCACA_code_007_…", … ]
}
```

Sums `CapacitySize* / CapacityUsed* / CapacityRemain*` over `data.Response.Data.Accounts`.

### EdgeOne 401

Tencent EdgeOne rejects Microsoft Edge user-agents on this path. The provider always sends a Chrome UA without `Edg/`.

Expired cookies also surface as 401 — refresh `cb_cookie.txt` / manual cookie.

### Empty Accounts

If `Accounts` is `[]`, your package codes differ. Copy `PackageCodes` from the browser request body and set:

```powershell
$env:CB_PACKAGE_CODES = '["TCACA_code_007_...","TCACA_code_029_..."]'
```

## Local cache fallback

Source mode **Auto** / **CLI** can read:

```
%USERPROFILE%\.codebuddy\cb_credits.json
```

produced by `codebuddy-statusline`’s `parse_credits.js` pipeline.

## CLI

```text
codexbar-cli usage -p codebuddy --verbose
```

## Not covered yet

- International `codebuddy.ai` (different host / product codes)
- OAuth device flow (cookie session only)
Loading