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
12 changes: 2 additions & 10 deletions src/accounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,14 +311,9 @@ export class CommandCodeAccountPool {

const disabled = latest.filter((account) => account.state?.kind === 'disabled')
if (disabled.length === latest.length) {
// Bilingual: the harness UI renders this message verbatim inside its
// (already localized) retry/turn-error chrome, so both languages ride
// in one string — English first, then the Chinese reading.
throw new LlmError(
`llm-commandcode: every configured Command Code account (${latest.length}) was rejected with 401`
+ ' — check the stored API keys (Models page / settings) or the auth file'
+ `;已配置的 ${latest.length} 个 Command Code 账户密钥均被拒绝(401)`
+ '——请在设置页检查存储的 API 密钥,或重新运行 command-code login',
+ ' — check the stored API keys (Models page / settings) or re-run command-code login',
'INVALID_CREDENTIAL',
)
}
Expand All @@ -338,10 +333,7 @@ export class CommandCodeAccountPool {
throw new LlmError(
`llm-commandcode: all ${latest.length} Command Code account(s) have exhausted their usage window`
+ (earliest > 0 ? `; the earliest window resets at ${clockLabel(earliest)}` : '')
+ ' — requests will succeed again after the reset (or add another account)'
+ `;已用尽全部 ${latest.length} 个 Command Code 账户的用量窗口`
+ (earliest > 0 ? `,最早的重置时间为 ${clockLabel(earliest)}` : '')
+ '——窗口重置后请求会自动恢复(也可以添加更多账户)',
+ ' — requests succeed again after the reset (or add another account)',
'RATE_LIMIT',
wait > 0 && wait <= RETRY_MAX_DELAY_MS ? { providerRetryAfterMs: wait } : undefined,
)
Expand Down
258 changes: 38 additions & 220 deletions src/adapter.ts

Large diffs are not rendered by default.

36 changes: 27 additions & 9 deletions src/capabilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
* subscriptionPlanInfo, isFreeModel) live here too — they exist only to read
* the tables, so a sync never has to touch src/adapter.ts.
*
* Ported from pi-commandcode-provider (MIT); originally part of src/adapter.ts
* and split out so upstream syncs stay reviewable.
* This snapshot lives in its own module so the frequent CLI/doc sync diffs stay
* reviewable: src/adapter.ts holds only the stable wire/runtime logic.
*/
// ---------------------------------------------------------------------------
// Static capability snapshot (from the official command-code@1.53.0 bundled
Expand Down Expand Up @@ -610,12 +610,35 @@ export const KNOWN_PEAK_PRICING: ReadonlySet<string> = new Set([
/**
* Peak hours (UTC, hour-of-day range end-exclusive): 01–03 and 06–09.
* Weekday-only — see `peakPricingState()`; weekends are fully off-peak.
*
* Exported because the vendored price table (`./model-prices.ts`) ships these
* windows to the browser with the table itself: the composer prices a session
* against the very schedule this snapshot knows rather than restating it, so
* there is one place to update when the windows move.
*/
const PEAK_HOUR_RANGES: ReadonlyArray<readonly [number, number]> = [
export const PEAK_HOUR_RANGES: ReadonlyArray<readonly [number, number]> = [
[1, 4],
[6, 10],
]

/**
* Whether `now` (defaults to `Date.now()`) falls inside a peak-pricing window,
* ignoring which model is asking. Peak rates apply Monday–Friday (UTC) only,
* so a weekend timestamp is off-peak even inside {@link PEAK_HOUR_RANGES}.
*
* Model-independent on purpose: `peakPricingState()` adds the membership test
* on top for the picker's label, while the price table selects peak rates from
* a row's own `peak` block — so a model whose catalog id spelling differs from
* the one in {@link KNOWN_PEAK_PRICING} still gets the right half of the day.
*/
export function isPeakPricingHour(now: number = Date.now()): boolean {
const at = new Date(now)
const day = at.getUTCDay()
if (day === 0 || day === 6) return false
const hour = at.getUTCHours()
return PEAK_HOUR_RANGES.some(([start, end]) => hour >= start && hour < end)
}

/**
* Whether `now` (defaults to `Date.now()`) falls in a peak-pricing window for
* time-of-day-priced models. Peak rates apply Monday–Friday (UTC) only: the
Expand All @@ -628,12 +651,7 @@ export function peakPricingState(
now: number = Date.now(),
): 'peak' | 'off-peak' | undefined {
if (!KNOWN_PEAK_PRICING.has(modelId)) return undefined
const at = new Date(now)
const day = at.getUTCDay()
if (day === 0 || day === 6) return 'off-peak'
const hour = at.getUTCHours()
const inPeak = PEAK_HOUR_RANGES.some(([start, end]) => hour >= start && hour < end)
return inPeak ? 'peak' : 'off-peak'
return isPeakPricingHour(now) ? 'peak' : 'off-peak'
}

/**
Expand Down
6 changes: 3 additions & 3 deletions src/client/card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* Models page dispatches for every Command Code provider row).
*
* The official Models page opens one editor card per provider row through its
* own 编辑 button. For a namespace the page does not curate a layout for
* own Edit button. For a namespace the page does not curate a layout for
* (`llm-commandcode`), that editor is a bare shell — a pointer to
* `settings.yaml` above a permanently disabled apply button. This panel takes
* its place: the slot outlet renders right beside the official editor inside
Expand Down Expand Up @@ -105,7 +105,7 @@ export interface SlotWrapperSiblings {
* Find the official editor card among the slot outlet's siblings, or null
* while it is closed. The Models page renders the editor as an immediate
* sibling of the outlet wrapper — after it in a provider row (the target of
* the row's 编辑 toggle), before it in the first-run setup card and the
* the row's Edit toggle), before it in the first-run setup card and the
* add-provider card, where it is always open. The editor is the only such
* sibling whose CSS module class carries the `editor` stem
* (`<hash>_editor`); the row header and the add card's provider select
Expand Down Expand Up @@ -207,7 +207,7 @@ function CardKeyField({ state, disabled, t, onEdit }: {
* the Models page (saved row, first-run setup posture, and add-provider
* draft).
*
* Closed (the official 编辑 toggle off) the panel renders nothing: the row
* Closed (the official Edit toggle off) the panel renders nothing: the row
* head the Models page owns already names the provider and shows the
* credential dot, so a page full of providers stays compact. Opening the
* official editor mounts the editor shell as the outlet's sibling; the panel
Expand Down
Loading
Loading