@bitkyc08/opencodex 2.67.0 → 2.68.0-preview.20260927
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/ocx.mjs +3 -0
- package/gui/dist/assets/App-B5-cAEd2.js +51 -0
- package/gui/dist/assets/App-DCBismRi.css +1 -0
- package/gui/dist/assets/Tray-DFnMiyD0.js +1 -0
- package/gui/dist/assets/{index-DtNmX7hW.css → index-BDUBS8PW.css} +1 -1
- package/gui/dist/assets/index-BcXblvem.js +86 -0
- package/gui/dist/assets/quota-summary-i84eOU3o.js +1 -0
- package/gui/dist/index.html +21 -2
- package/package.json +1 -1
- package/src/adapters/anthropic-image-guard.ts +13 -1
- package/src/adapters/anthropic-image-normalize.ts +3 -2
- package/src/adapters/anthropic-output-schema.ts +36 -0
- package/src/adapters/anthropic.ts +10 -2
- package/src/adapters/base.ts +7 -0
- package/src/adapters/codebuddy/live-models.ts +180 -0
- package/src/adapters/coding-agent/protocol.ts +91 -12
- package/src/adapters/coding-agent/turn.ts +32 -27
- package/src/adapters/devin/cloud-direct/index.ts +1 -0
- package/src/adapters/devin/cloud-direct/stated-reset-retry.ts +18 -4
- package/src/adapters/devin.ts +9 -6
- package/src/adapters/google-http.ts +4 -4
- package/src/adapters/google.ts +93 -3
- package/src/adapters/kiro/adapter.ts +6 -2
- package/src/adapters/kiro/stream.ts +12 -2
- package/src/adapters/kiro/usage.ts +3 -1
- package/src/adapters/kiro-errors.ts +11 -1
- package/src/adapters/kiro-events.ts +27 -1
- package/src/adapters/kiro-refusal.ts +30 -0
- package/src/adapters/kiro-retry.ts +71 -31
- package/src/adapters/openai-chat/deepseek-artifact-schema.ts +45 -0
- package/src/adapters/openai-chat/messages.ts +31 -4
- package/src/adapters/openai-chat/serialized-tool-call-content.ts +52 -7
- package/src/adapters/openai-chat/tool-call-id-remint.ts +65 -0
- package/src/adapters/openai-chat/tool-schema.ts +6 -2
- package/src/adapters/openai-chat.ts +2 -2
- package/src/adapters/openai-responses/muse-tool-choice.ts +31 -0
- package/src/adapters/openai-responses/passthrough.ts +9 -3
- package/src/adapters/opencode-go-additional-tools.ts +19 -10
- package/src/adapters/physical-send.ts +10 -3
- package/src/adapters/registry.ts +2 -1
- package/src/adapters/responses-tool-schema.ts +31 -3
- package/src/adapters/run-turn-queue.ts +63 -23
- package/src/adapters/unique-tool-call-ids.ts +63 -0
- package/src/adapters/xai-web-search.ts +32 -2
- package/src/bridge/sse.ts +14 -2
- package/src/chat/inbound.ts +20 -6
- package/src/claude/agents-inject.ts +4 -0
- package/src/claude/desktop-3p.ts +53 -13
- package/src/claude/desktop-profile.ts +41 -4
- package/src/claude/inbound-model-options.ts +14 -2
- package/src/claude/inbound.ts +1 -1
- package/src/claude/intercept/connect-proxy.ts +17 -1
- package/src/claude/intercept/local-ca.ts +7 -1
- package/src/claude/message-threads.ts +28 -0
- package/src/cli/account-api.ts +13 -0
- package/src/cli/account-auth.ts +49 -2
- package/src/cli/account-extended.ts +4 -2
- package/src/cli/account.ts +4 -2
- package/src/cli/capabilities.ts +17 -0
- package/src/cli/claude.ts +3 -1
- package/src/cli/dispatch.ts +62 -5
- package/src/cli/index.ts +84 -79
- package/src/cli/minimax.ts +4 -2
- package/src/cli/opencode.ts +6 -1
- package/src/cli/restart-handoff.ts +110 -0
- package/src/cli/status.ts +51 -0
- package/src/client/connect.ts +34 -15
- package/src/client/link-ingress.ts +102 -0
- package/src/client/link-join.ts +37 -16
- package/src/client/link-relay.ts +228 -45
- package/src/client/link-state.ts +54 -0
- package/src/client/link-status.ts +39 -0
- package/src/client/link-teardown.ts +2 -2
- package/src/client/link-tunnel.ts +615 -86
- package/src/client/machine-api.ts +10 -4
- package/src/client/machine-listener.ts +57 -10
- package/src/client/runtime.ts +210 -35
- package/src/clients/config-export/constants.ts +1 -12
- package/src/clients/config-export/contracts.ts +2 -0
- package/src/clients/config-export/model-metadata.ts +9 -3
- package/src/clients/config-export/omp.ts +1 -1
- package/src/clients/config-export/zcode-store.ts +2 -2
- package/src/clients/config-export.ts +36 -3
- package/src/codex/app-server-processes.ts +32 -0
- package/src/codex/app-server-restart-service.ts +20 -3
- package/src/codex/catalog/access-programs.ts +50 -0
- package/src/codex/catalog/build-entries.ts +13 -0
- package/src/codex/catalog/derive-entry.ts +1 -0
- package/src/codex/catalog/model-hints.ts +11 -0
- package/src/codex/catalog/parsing.ts +6 -2
- package/src/codex/catalog/provider-models.ts +81 -0
- package/src/codex/catalog/retained-sync.ts +3 -0
- package/src/codex/codex-write-lock.ts +2 -2
- package/src/codex/convergence.ts +2 -0
- package/src/codex/desired-state.ts +14 -4
- package/src/codex/home.ts +21 -3
- package/src/codex/inject/restore.ts +17 -0
- package/src/codex/inject/routing-classify.ts +3 -2
- package/src/codex/inject-coordination.ts +4 -1
- package/src/codex/inject.ts +8 -1
- package/src/codex/journal.ts +6 -2
- package/src/codex/management-convergence.ts +9 -0
- package/src/codex/model-entitlements.ts +28 -5
- package/src/codex/routing/idle-window.ts +58 -0
- package/src/codex/routing-drift.ts +134 -0
- package/src/codex/routing-healer.ts +419 -0
- package/src/codex/routing.ts +10 -0
- package/src/codex/runtime.ts +188 -57
- package/src/codex/sibling-handoff.ts +71 -0
- package/src/codex/sibling-start.ts +139 -0
- package/src/codex/sync.ts +5 -3
- package/src/combos/failover.ts +32 -5
- package/src/combos/request.ts +11 -3
- package/src/combos/reset-window.ts +10 -5
- package/src/combos/resolve.ts +36 -6
- package/src/config/diagnostics.ts +2 -1
- package/src/config/load-degrade.ts +2 -0
- package/src/config/paths.ts +7 -1
- package/src/config/process-state.ts +10 -1
- package/src/config/schema/compaction-recovery.ts +15 -0
- package/src/config/schema/config-schema.ts +2 -0
- package/src/config/schema/leaf-validators.ts +9 -3
- package/src/generated/compatibility-version.json +360 -204
- package/src/images/loop.ts +47 -32
- package/src/integrations/catalog-refresh.ts +4 -0
- package/src/integrations/omp-yaml-source.ts +1 -0
- package/src/lib/claude-request-projection.ts +101 -0
- package/src/lib/local-account-switch-capability.ts +48 -0
- package/src/lib/local-upstream.ts +146 -0
- package/src/lib/package-tree-integrity.ts +25 -3
- package/src/lib/package-tree-retarget.ts +130 -0
- package/src/lib/process-control.ts +4 -1
- package/src/lib/system-restart-contract.ts +106 -0
- package/src/lib/upstream-retry.ts +57 -1
- package/src/link/ports.ts +9 -0
- package/src/link/ssh-argv.ts +16 -0
- package/src/link/ssh-runner.ts +70 -2
- package/src/link/tunnel-state.ts +58 -9
- package/src/oauth/account-quota-rank.ts +29 -18
- package/src/oauth/generic-account-failover.ts +179 -22
- package/src/oauth/index.ts +17 -4
- package/src/oauth/kiro-account-load.ts +107 -0
- package/src/oauth/kiro-device-login.ts +312 -0
- package/src/oauth/kiro-terminal-failover.ts +28 -0
- package/src/oauth/login-flow-state.ts +7 -1
- package/src/oauth/pool-settings-capability.ts +23 -14
- package/src/oauth/store.ts +56 -3
- package/src/oauth/types.ts +4 -0
- package/src/plugins/loader.ts +350 -0
- package/src/plugins/upstream-hooks.ts +119 -0
- package/src/protocols/encoders/adapter-events.ts +9 -2
- package/src/providers/account-quota-disk.ts +42 -4
- package/src/providers/codebuddy-models.ts +6 -2
- package/src/providers/command-code-efforts.ts +33 -10
- package/src/providers/kiro-account-state-disk.ts +44 -0
- package/src/providers/kiro-model-catalog.ts +162 -0
- package/src/providers/kiro-models.ts +5 -4
- package/src/providers/kiro-quota-metrics.ts +35 -0
- package/src/providers/kiro-usage.ts +118 -14
- package/src/providers/quota/account-cache.ts +43 -7
- package/src/providers/quota/antigravity.ts +8 -3
- package/src/providers/quota/kiro-account-probe.ts +12 -0
- package/src/providers/quota/vendor-probes-key.ts +31 -26
- package/src/providers/quota/vendor-probes-oauth.ts +16 -7
- package/src/providers/quota-types.ts +14 -0
- package/src/providers/quota.ts +21 -21
- package/src/providers/registry/entries-extended.ts +5 -3
- package/src/providers/request-pacing.ts +410 -12
- package/src/remote-control/workspace-codex-runtime.ts +4 -3
- package/src/responses/citation-markers.ts +132 -65
- package/src/responses/hosted-tool-policy.ts +14 -3
- package/src/responses/parser-content.ts +3 -2
- package/src/responses/parser.ts +4 -1
- package/src/responses/schema.ts +4 -0
- package/src/responses/visualization-directives.ts +182 -0
- package/src/server/chat-native-sse.ts +24 -12
- package/src/server/chat-native.ts +137 -68
- package/src/server/claude-messages.ts +147 -12
- package/src/server/index/link-listener.ts +7 -0
- package/src/server/index/optional-listeners.ts +4 -1
- package/src/server/index/package-tree-guard.ts +35 -16
- package/src/server/index/serve-options.ts +4 -2
- package/src/server/index/startup-warnings.ts +6 -0
- package/src/server/index.ts +7 -7
- package/src/server/inference/client-encoder-delivery.ts +3 -0
- package/src/server/inference/context.ts +30 -2
- package/src/server/local-account-switch-auth.ts +79 -0
- package/src/server/management/agent-settings-routes.ts +11 -3
- package/src/server/management/config-routes.ts +28 -11
- package/src/server/management/context.ts +2 -0
- package/src/server/management/link-routes.ts +123 -39
- package/src/server/management/logs-usage-routes.ts +9 -42
- package/src/server/management/model-rows.ts +1 -0
- package/src/server/management/oauth-account-routes.ts +67 -12
- package/src/server/management/route-registry.ts +5 -5
- package/src/server/management/sibling-guard.ts +60 -0
- package/src/server/management/storage-log-guard-routes.ts +72 -6
- package/src/server/management/system-restart.ts +92 -135
- package/src/server/management/system-routes.ts +1 -1
- package/src/server/management-api.ts +31 -3
- package/src/server/management-auth.ts +3 -0
- package/src/server/port-reclaim.ts +111 -1
- package/src/server/proxy-liveness.ts +16 -0
- package/src/server/relay.ts +16 -15
- package/src/server/request-log-filter.ts +28 -27
- package/src/server/request-log.ts +7 -3
- package/src/server/request-metrics.ts +28 -0
- package/src/server/responses/adapter-continuation.ts +151 -21
- package/src/server/responses/adapter-delivery.ts +21 -7
- package/src/server/responses/adapter-dispatch.ts +239 -51
- package/src/server/responses/codex-ws-pool.ts +5 -4
- package/src/server/responses/codex-ws-request.ts +4 -1
- package/src/server/responses/compact.ts +8 -4
- package/src/server/responses/compaction-recovery-policy.ts +116 -0
- package/src/server/responses/compaction-recovery.ts +330 -0
- package/src/server/responses/core-combo-failure.ts +1 -0
- package/src/server/responses/core-combo.ts +5 -1
- package/src/server/responses/core-lifetime.ts +22 -0
- package/src/server/responses/core-options.ts +16 -1
- package/src/server/responses/core.ts +14 -4
- package/src/server/responses/empty-completion-guard.ts +2 -0
- package/src/server/responses/fetch-helpers.ts +82 -31
- package/src/server/responses/passthrough-delivery.ts +3 -2
- package/src/server/responses/passthrough-dispatch.ts +12 -2
- package/src/server/responses/passthrough-execution.ts +2 -2
- package/src/server/responses/request-send-budget.ts +21 -5
- package/src/server/responses/request-transport.ts +116 -18
- package/src/server/responses/reset-replay.ts +32 -0
- package/src/server/responses/run-turn-execution.ts +136 -19
- package/src/server/responses/sidecar-execution.ts +41 -8
- package/src/server/responses/terminal-guard.ts +2 -0
- package/src/server/responses/ws-upstream.ts +44 -4
- package/src/server/restart-replacement.ts +382 -0
- package/src/server/startup-health-cache.ts +23 -4
- package/src/server/stop-teardown.ts +35 -1
- package/src/server/system-env.ts +3 -0
- package/src/service/windows-taskxml.ts +11 -7
- package/src/service/windows-wrapper-exit.ts +8 -0
- package/src/stall-timeout.ts +35 -10
- package/src/storage/policy-job.ts +4 -0
- package/src/storage/scanner.ts +177 -29
- package/src/storage/storage-mutation-coordinator.ts +17 -0
- package/src/tray/windows-tray.ps1 +50 -23
- package/src/types/config.ts +4 -0
- package/src/types/provider.ts +5 -1
- package/src/types/request.ts +13 -2
- package/src/update/index.ts +3 -1
- package/src/update/job.ts +6 -2
- package/src/update/mise-launcher-target.ts +100 -0
- package/src/update/worker-launch.ts +46 -0
- package/src/usage/log.ts +2 -0
- package/src/web-search/loop.ts +5 -2
- package/gui/dist/assets/App-BJsT8Icc.css +0 -1
- package/gui/dist/assets/App-D3pNGiN4.js +0 -51
- package/gui/dist/assets/Tray-yb05wCjb.js +0 -1
- package/gui/dist/assets/index-CouvvtMV.js +0 -86
- package/gui/dist/assets/tray-data-CYGdjCJ7.js +0 -1
|
@@ -3,8 +3,10 @@ import { getValidAccessTokenForAccount } from "../../oauth";
|
|
|
3
3
|
import { getAccountCredential, getAccountSet } from "../../oauth/store";
|
|
4
4
|
import type { GenerationContext } from "../../lib/state-store-sweeper";
|
|
5
5
|
import { ACCOUNT_QUOTA_TTL_MS, toFiniteNumber } from "../quota-wire";
|
|
6
|
-
import { clearKiroAccountUsageState, reconcileKiroAccountUsageState } from "../kiro-usage";
|
|
7
|
-
import {
|
|
6
|
+
import { clearKiroAccountUsageState, hydrateKiroUsageVerdict, kiroPersistableVerdicts, reconcileKiroAccountUsageState } from "../kiro-usage";
|
|
7
|
+
import { kiroEvidenceIdentity, sanitizeKiroQuota, type KiroPersistedQuota } from "../kiro-account-state-disk";
|
|
8
|
+
import { cancelPendingAccountQuotaPersist, readPersistedAccountQuotas, readPersistedKiroVerdicts, schedulePersistAccountQuotas } from "../account-quota-disk";
|
|
9
|
+
import type { ProviderAccount } from "../../oauth/types";
|
|
8
10
|
import { replaceCachedProviderQuotas } from "../quota-routing-cache";
|
|
9
11
|
import { getProviderRegistryEntry } from "../registry";
|
|
10
12
|
import { getProviderQuotaReportCache, hasQuotaRows, routingEvidence, setProviderQuotaReportCache } from "./report-cache";
|
|
@@ -102,26 +104,51 @@ let diskHydrated = false;
|
|
|
102
104
|
export function hydrateAccountQuotaCache(): void {
|
|
103
105
|
if (diskHydrated) return;
|
|
104
106
|
diskHydrated = true;
|
|
105
|
-
|
|
107
|
+
const now = Date.now();
|
|
108
|
+
const liveKiro = new Map<string, ProviderAccount>(getAccountSet("kiro")?.accounts.map(account =>
|
|
109
|
+
[accountCacheKey("kiro", account.id), account]) ?? []);
|
|
110
|
+
for (const [key, quota] of readPersistedAccountQuotas(now)) {
|
|
111
|
+
if (key.startsWith("kiro\0")) {
|
|
112
|
+
const account = liveKiro.get(key);
|
|
113
|
+
if (!account || (quota as KiroPersistedQuota).identity !== kiroEvidenceIdentity(account)
|
|
114
|
+
|| typeof quota.monthlyPercent !== "number" || !Number.isFinite(quota.monthlyPercent)
|
|
115
|
+
|| quota.monthlyPercent < 0 || quota.monthlyPercent > 100
|
|
116
|
+
|| now - quota.updatedAt >= ACCOUNT_QUOTA_TTL_MS
|
|
117
|
+
|| (quota.monthlyResetAt !== undefined && (typeof quota.monthlyResetAt !== "number"
|
|
118
|
+
|| !Number.isFinite(quota.monthlyResetAt) || quota.monthlyResetAt <= now
|
|
119
|
+
|| !Number.isFinite(new Date(quota.monthlyResetAt).getTime())))) continue;
|
|
120
|
+
}
|
|
106
121
|
// Disk stores observation time, not the Anthropic usage probe's clock.
|
|
107
122
|
if (!accountQuotaCache.has(key)) {
|
|
108
123
|
const anthropic = key.startsWith("anthropic\u0000");
|
|
109
124
|
accountQuotaCache.set(key, {
|
|
110
125
|
ts: anthropic ? 0 : quota.updatedAt,
|
|
111
|
-
quota: anthropic ? normalizeAnthropicQuota(quota,
|
|
126
|
+
quota: anthropic ? normalizeAnthropicQuota(quota, now)
|
|
127
|
+
: key.startsWith("kiro\0") ? sanitizeKiroQuota(quota) : quota,
|
|
128
|
+
...(key.startsWith("kiro\0") ? { identity: (quota as KiroPersistedQuota).identity } : {}),
|
|
112
129
|
});
|
|
113
130
|
}
|
|
114
131
|
}
|
|
132
|
+
for (const [key, verdict] of readPersistedKiroVerdicts(now)) {
|
|
133
|
+
const account = liveKiro.get(key);
|
|
134
|
+
if (account && verdict.identity === kiroEvidenceIdentity(account)) hydrateKiroUsageVerdict(key, verdict, account);
|
|
135
|
+
}
|
|
115
136
|
}
|
|
116
137
|
|
|
117
138
|
export function persistAccountQuotaCache(): void {
|
|
118
139
|
schedulePersistAccountQuotas(function* () {
|
|
119
140
|
const now = Date.now();
|
|
141
|
+
const liveKiro = new Map<string, ProviderAccount>(getAccountSet("kiro")?.accounts.map(account =>
|
|
142
|
+
[accountCacheKey("kiro", account.id), account]) ?? []);
|
|
120
143
|
for (const [key, entry] of accountQuotaCache) {
|
|
121
144
|
const quota = key.startsWith("anthropic\u0000") ? normalizeAnthropicQuota(entry.quota, now) : entry.quota;
|
|
122
|
-
if (quota
|
|
145
|
+
if (quota && key.startsWith("kiro\0")) {
|
|
146
|
+
const account = liveKiro.get(key);
|
|
147
|
+
if (account && entry.identity === kiroEvidenceIdentity(account))
|
|
148
|
+
yield [key, { ...sanitizeKiroQuota(quota), identity: entry.identity } as KiroPersistedQuota] as [string, KiroPersistedQuota];
|
|
149
|
+
} else if (quota) yield [key, quota] as [string, ProviderQuota];
|
|
123
150
|
}
|
|
124
|
-
});
|
|
151
|
+
}, () => kiroPersistableVerdicts());
|
|
125
152
|
}
|
|
126
153
|
export const accountQuotaInflight = new Map<string, Promise<AccountQuotaCacheEntry>>();
|
|
127
154
|
let lastReconciledGeneration = 0;
|
|
@@ -170,6 +197,10 @@ export function accountCacheKey(provider: string, accountId: string): string {
|
|
|
170
197
|
*/
|
|
171
198
|
export function getCachedProviderAccountQuota(provider: string, accountId: string): ProviderQuota | null {
|
|
172
199
|
const entry = accountQuotaCache.get(accountCacheKey(provider, accountId));
|
|
200
|
+
if (provider === "kiro") {
|
|
201
|
+
const account = getAccountSet("kiro")?.accounts.find(row => row.id === accountId);
|
|
202
|
+
if (!account || entry?.identity !== kiroEvidenceIdentity(account)) return null;
|
|
203
|
+
}
|
|
173
204
|
if (entry?.isCurrent && !entry.isCurrent()) return null;
|
|
174
205
|
return provider === "anthropic" ? normalizeAnthropicQuota(entry?.quota, Date.now()) : entry?.quota ?? null;
|
|
175
206
|
}
|
|
@@ -185,7 +216,9 @@ export function setCachedProviderAccountQuotaForTests(
|
|
|
185
216
|
accountQuotaCache.delete(key);
|
|
186
217
|
return;
|
|
187
218
|
}
|
|
188
|
-
|
|
219
|
+
const account = provider === "kiro" ? getAccountSet("kiro")?.accounts.find(row => row.id === accountId) : undefined;
|
|
220
|
+
accountQuotaCache.set(key, { ts: Date.now(), quota,
|
|
221
|
+
...(account ? { identity: kiroEvidenceIdentity(account) } : {}) });
|
|
189
222
|
}
|
|
190
223
|
|
|
191
224
|
/** Unified headers report utilization fractions and epoch-second reset times. */
|
|
@@ -335,6 +368,7 @@ export function sweepExpiredProviderAccountQuotaRows(now = Date.now()): number {
|
|
|
335
368
|
|
|
336
369
|
export function reconcileProviderAccountQuotaRows(context: GenerationContext): number {
|
|
337
370
|
if (context.generation <= lastReconciledGeneration) return 0;
|
|
371
|
+
hydrateAccountQuotaCache();
|
|
338
372
|
let removed = 0;
|
|
339
373
|
for (const key of accountQuotaCache.keys()) {
|
|
340
374
|
if (context.oauthAccountKeys.has(key)) continue;
|
|
@@ -354,6 +388,7 @@ export function reconcileProviderAccountQuotaRows(context: GenerationContext): n
|
|
|
354
388
|
liveAccountQuotaKeys = new Set(context.oauthAccountKeys);
|
|
355
389
|
liveProviderQuotaKeys = new Set(context.providerNames);
|
|
356
390
|
lastReconciledGeneration = context.generation;
|
|
391
|
+
if (removed > 0) persistAccountQuotaCache();
|
|
357
392
|
return removed;
|
|
358
393
|
}
|
|
359
394
|
|
|
@@ -377,6 +412,7 @@ export function clearAccountQuotaCache(provider?: string): void {
|
|
|
377
412
|
cancelPendingAccountQuotaPersist();
|
|
378
413
|
return;
|
|
379
414
|
}
|
|
415
|
+
hydrateAccountQuotaCache();
|
|
380
416
|
const prefix = `${provider}\u0000`;
|
|
381
417
|
for (const key of [...accountQuotaCache.keys()]) {
|
|
382
418
|
if (key.startsWith(prefix)) accountQuotaCache.delete(key);
|
|
@@ -253,16 +253,21 @@ function antigravityUnavailableFailure(
|
|
|
253
253
|
}
|
|
254
254
|
|
|
255
255
|
export async function probeAntigravityUsageQuota(accessToken: string, projectId: string): Promise<AntigravityQuotaProbeResult> {
|
|
256
|
-
const fetchQuota = (url: string) => providerOutboundPost("google-antigravity", { baseUrl: ANTIGRAVITY_ACCOUNT_QUOTA_BASE }, url, {
|
|
256
|
+
const fetchQuota = (url: string, userAgent = antigravityUserAgent()) => providerOutboundPost("google-antigravity", { baseUrl: ANTIGRAVITY_ACCOUNT_QUOTA_BASE }, url, {
|
|
257
257
|
headers: {
|
|
258
258
|
Accept: "application/json", "Content-Type": "application/json",
|
|
259
|
-
"User-Agent":
|
|
259
|
+
"User-Agent": userAgent, Authorization: `Bearer ${accessToken}`,
|
|
260
260
|
},
|
|
261
261
|
body: JSON.stringify({ project: projectId }), signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
|
|
262
262
|
}, antigravityOutboundDependencies);
|
|
263
263
|
let summaryFailure: QuotaFailureCode | undefined;
|
|
264
264
|
try {
|
|
265
|
-
|
|
265
|
+
let response = await fetchQuota(ANTIGRAVITY_QUOTA_SUMMARY_URL);
|
|
266
|
+
if (response.status === 403) {
|
|
267
|
+
// Some valid accounts reject the IDE fingerprint only for quota accounting.
|
|
268
|
+
try { await response.body?.cancel(); } catch { /* Best-effort release before retry. */ }
|
|
269
|
+
response = await fetchQuota(ANTIGRAVITY_QUOTA_SUMMARY_URL, "antigravity/1.0");
|
|
270
|
+
}
|
|
266
271
|
if (await providerRedirectError(response, ANTIGRAVITY_QUOTA_SUMMARY_URL)) return unavailableAntigravityQuota("redirect_blocked");
|
|
267
272
|
if (response.status === 401 || response.status === 403) return unavailableAntigravityQuota("access_denied");
|
|
268
273
|
if (response.ok) {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { getAccountSet } from "../../oauth/store";
|
|
2
|
+
import { kiroEvidenceIdentity } from "../kiro-account-state-disk";
|
|
3
|
+
|
|
4
|
+
/** Capture login identity before an await and recheck it before publishing evidence. */
|
|
5
|
+
export function kiroProbeIdentity(accountId: string): string | undefined {
|
|
6
|
+
const account = getAccountSet("kiro")?.accounts.find(row => row.id === accountId);
|
|
7
|
+
return account ? kiroEvidenceIdentity(account) : undefined;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function kiroProbeCurrent(accountId: string, identity: string | undefined): boolean {
|
|
11
|
+
return identity !== undefined && kiroProbeIdentity(accountId) === identity;
|
|
12
|
+
}
|
|
@@ -40,7 +40,7 @@ const OLLAMA_CLOUD_BASE_URL = "https://ollama.com";
|
|
|
40
40
|
const OLLAMA_CLOUD_USAGE_URL = `${OLLAMA_CLOUD_BASE_URL}/api/usage`;
|
|
41
41
|
const ZAI_BASE_URL = "https://api.z.ai";
|
|
42
42
|
const ZAI_CN_BASE_URL = "https://open.bigmodel.cn";
|
|
43
|
-
const
|
|
43
|
+
const MINIMAX_REMAINS_PATH = "/v1/api/openplatform/coding_plan/remains";
|
|
44
44
|
const MOONSHOT_BASE_URL = "https://api.moonshot.ai/v1";
|
|
45
45
|
const VENICE_BASE_URL = "https://api.venice.ai/api/v1";
|
|
46
46
|
const SYNTHETIC_BASE_URL = "https://api.synthetic.new/v2";
|
|
@@ -652,20 +652,17 @@ async function fetchZaiQuota(provider: string, config: OcxProviderConfig): Promi
|
|
|
652
652
|
}
|
|
653
653
|
|
|
654
654
|
/**
|
|
655
|
-
* MiniMax
|
|
656
|
-
* remaining
|
|
657
|
-
*
|
|
658
|
-
* window: the remaining time is reported as a duration-only window. When the
|
|
659
|
-
* API supplies a total (`total_time` / `plan_duration_ms`), a consumed share
|
|
660
|
-
* is derived from it. Region selects the host: `minimax` → www.minimax.io,
|
|
661
|
-
* `minimax-cn` → api.minimaxi.com.
|
|
655
|
+
* MiniMax Coding Plan `GET /v1/api/openplatform/coding_plan/remains` reports
|
|
656
|
+
* remaining percentages per model/window. Only the `general` model is the
|
|
657
|
+
* Coding Plan quota; video remains are unrelated. Region selects the host.
|
|
662
658
|
*/
|
|
663
659
|
async function fetchMinimaxQuota(provider: string, config: OcxProviderConfig): Promise<ProviderQuotaProbeResult> {
|
|
664
660
|
if (!isCanonicalMinimaxBaseUrl(config.baseUrl)) return null;
|
|
665
661
|
const apiKey = resolveProviderApiKey(config.apiKey)?.trim();
|
|
666
662
|
if (!apiKey) return null;
|
|
667
663
|
const cnHost = normalizedBaseUrl(config.baseUrl)?.startsWith("https://api.minimaxi.com");
|
|
668
|
-
const
|
|
664
|
+
const canonicalHost = cnHost ? "https://api.minimaxi.com" : "https://api.minimax.io";
|
|
665
|
+
const remainsUrl = `${canonicalHost}${MINIMAX_REMAINS_PATH}`;
|
|
669
666
|
const response = await quotaFetch(provider, config, remainsUrl, {
|
|
670
667
|
headers: { Accept: "application/json", Authorization: `Bearer ${apiKey}` },
|
|
671
668
|
redirect: "error",
|
|
@@ -677,24 +674,32 @@ async function fetchMinimaxQuota(provider: string, config: OcxProviderConfig): P
|
|
|
677
674
|
: null;
|
|
678
675
|
}
|
|
679
676
|
const body = asRecord(await readQuotaJson(response));
|
|
680
|
-
if (!body || body.
|
|
681
|
-
const
|
|
682
|
-
const
|
|
683
|
-
if (
|
|
684
|
-
const
|
|
685
|
-
const
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
677
|
+
if (!body || asRecord(body.base_resp)?.status_code !== 0) return null;
|
|
678
|
+
const rows = Array.isArray(body.model_remains) ? body.model_remains : [];
|
|
679
|
+
const general = rows.map(asRecord).find(row => row?.model_name === "general");
|
|
680
|
+
if (!general) return null;
|
|
681
|
+
const customWindows: NonNullable<ProviderQuota["customWindows"]> = [];
|
|
682
|
+
const fiveHourRemaining = toFiniteNumber(general.current_interval_remaining_percent);
|
|
683
|
+
if (fiveHourRemaining !== undefined) {
|
|
684
|
+
const percent = normalizePercent(100 - fiveHourRemaining);
|
|
685
|
+
if (percent !== undefined) {
|
|
686
|
+
const resetAt = normalizeResetAt(general.end_time);
|
|
687
|
+
customWindows.push({ label: "Coding Plan 5-hour", percent, ...(resetAt ? { resetAt } : {}) });
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
if (general.current_weekly_status === 1) {
|
|
691
|
+
const weeklyRemaining = toFiniteNumber(general.current_weekly_remaining_percent);
|
|
692
|
+
if (weeklyRemaining !== undefined) {
|
|
693
|
+
const percent = normalizePercent(100 - weeklyRemaining);
|
|
694
|
+
if (percent !== undefined) {
|
|
695
|
+
const resetAt = normalizeResetAt(general.weekly_end_time);
|
|
696
|
+
customWindows.push({ label: "Coding Plan weekly", percent, ...(resetAt ? { resetAt } : {}) });
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
if (customWindows.length === 0) return null;
|
|
696
701
|
return report(provider, "minimax:token-plan-remains", {
|
|
697
|
-
customWindows
|
|
702
|
+
customWindows,
|
|
698
703
|
updatedAt: Date.now(),
|
|
699
704
|
});
|
|
700
705
|
}
|
|
@@ -2,6 +2,8 @@ import { effectiveCodexAuthAccountId, fetchMainAccountInfoSnapshot, listCodexAut
|
|
|
2
2
|
import { MAIN_CODEX_ACCOUNT_ID } from "../../codex/main-account";
|
|
3
3
|
import { getValidAccessToken } from "../../oauth";
|
|
4
4
|
import { getAccountCredential, getAccountSet } from "../../oauth/store";
|
|
5
|
+
import { hydrateKiroAccountState, persistKiroAccountState } from "../kiro-account-state-disk";
|
|
6
|
+
import { kiroProbeCurrent, kiroProbeIdentity } from "./kiro-account-probe";
|
|
5
7
|
import { fetchMuseKeyQuotaSnapshot } from "../muse-key-quota";
|
|
6
8
|
import { CLAUDE_CLI_USER_AGENT } from "../claude-cli-identity";
|
|
7
9
|
import { XAI_GROK_CLIENT_VERSION, XAI_GROK_COMPATIBILITY } from "../xai-transport";
|
|
@@ -227,7 +229,7 @@ function parseClaudeBucket(value: unknown): { percent?: number; resetAt?: number
|
|
|
227
229
|
|
|
228
230
|
const TERMINAL_CONTROL_CHARACTERS = /[\u0000-\u001f\u007f-\u009f]/gu;
|
|
229
231
|
|
|
230
|
-
function parseClaudeLimit(value: unknown):
|
|
232
|
+
function parseClaudeLimit(value: unknown): ProviderQuotaWindow | null {
|
|
231
233
|
const rec = asRecord(value);
|
|
232
234
|
if (!rec) return null;
|
|
233
235
|
const percent = normalizePercent(rec.percent);
|
|
@@ -247,7 +249,10 @@ function parseClaudeLimit(value: unknown): { label: string; percent: number; res
|
|
|
247
249
|
// control characters still leaves attacker-chosen residue on the quota line.
|
|
248
250
|
if (label === null) return null;
|
|
249
251
|
const resetAt = normalizeResetAt(rec.resets_at);
|
|
250
|
-
|
|
252
|
+
// Model scope is proven structurally here, not guessed from text: the caller admits only
|
|
253
|
+
// `kind: "weekly_scoped"`, and a limit without a recognized `scope.model.display_name` has
|
|
254
|
+
// already returned null above. Routing keys on `scope`, never on `label`.
|
|
255
|
+
return { label, scope: "model", percent, ...(resetAt !== undefined ? { resetAt } : {}) };
|
|
251
256
|
}
|
|
252
257
|
|
|
253
258
|
/** Claude's OAuth usage endpoint, probed with ONE account's own bearer token. */
|
|
@@ -292,9 +297,9 @@ export async function fetchAnthropicUsageQuota(accessToken: string): Promise<Pro
|
|
|
292
297
|
const opus = parseClaudeBucket(body.seven_day_opus);
|
|
293
298
|
const sonnet = parseClaudeBucket(body.seven_day_sonnet);
|
|
294
299
|
const customWindows: ProviderQuotaWindow[] = [];
|
|
295
|
-
if (fable?.percent !== undefined) customWindows.push({ label: "Fable", percent: fable.percent, ...(fable.resetAt !== undefined ? { resetAt: fable.resetAt } : {}) });
|
|
296
|
-
if (opus?.percent !== undefined) customWindows.push({ label: "Opus", percent: opus.percent, ...(opus.resetAt !== undefined ? { resetAt: opus.resetAt } : {}) });
|
|
297
|
-
if (sonnet?.percent !== undefined) customWindows.push({ label: "Sonnet", percent: sonnet.percent, ...(sonnet.resetAt !== undefined ? { resetAt: sonnet.resetAt } : {}) });
|
|
300
|
+
if (fable?.percent !== undefined) customWindows.push({ label: "Fable", scope: "model", percent: fable.percent, ...(fable.resetAt !== undefined ? { resetAt: fable.resetAt } : {}) });
|
|
301
|
+
if (opus?.percent !== undefined) customWindows.push({ label: "Opus", scope: "model", percent: opus.percent, ...(opus.resetAt !== undefined ? { resetAt: opus.resetAt } : {}) });
|
|
302
|
+
if (sonnet?.percent !== undefined) customWindows.push({ label: "Sonnet", scope: "model", percent: sonnet.percent, ...(sonnet.resetAt !== undefined ? { resetAt: sonnet.resetAt } : {}) });
|
|
298
303
|
const knownLabels = new Set(customWindows.map(window => window.label.toLowerCase()));
|
|
299
304
|
const limits = Array.isArray(body.limits) ? body.limits : [];
|
|
300
305
|
for (const rawLimit of limits) {
|
|
@@ -360,8 +365,10 @@ export async function fetchAnthropicQuota(provider: string): Promise<ProviderQuo
|
|
|
360
365
|
* concurrent account switch cannot file this answer under the wrong account.
|
|
361
366
|
*/
|
|
362
367
|
export async function fetchKiroQuota(provider: string): Promise<ProviderQuotaReport | null> {
|
|
368
|
+
hydrateKiroAccountState();
|
|
363
369
|
const probedAccountId = getAccountSet("kiro")?.activeAccountId;
|
|
364
370
|
if (!probedAccountId) return null;
|
|
371
|
+
const identity = kiroProbeIdentity(probedAccountId);
|
|
365
372
|
const probedAccountKey = accountCacheKey("kiro", probedAccountId);
|
|
366
373
|
const writerGeneration = captureConfigGeneration();
|
|
367
374
|
let snapshot: KiroUsageSnapshot | null;
|
|
@@ -371,9 +378,11 @@ export async function fetchKiroQuota(provider: string): Promise<ProviderQuotaRep
|
|
|
371
378
|
return null;
|
|
372
379
|
}
|
|
373
380
|
if (!snapshot) return null;
|
|
381
|
+
if (!kiroProbeCurrent(probedAccountId, identity)) return null;
|
|
374
382
|
if (mayCommitAccountQuotaKey(probedAccountKey, writerGeneration)) {
|
|
375
|
-
accountQuotaCache.set(probedAccountKey, { ts: Date.now(), quota: snapshot.quota });
|
|
376
|
-
commitKiroAccountUsageState(probedAccountKey, snapshot);
|
|
383
|
+
accountQuotaCache.set(probedAccountKey, { ts: Date.now(), quota: snapshot.quota, identity });
|
|
384
|
+
commitKiroAccountUsageState(probedAccountKey, snapshot, identity);
|
|
385
|
+
persistKiroAccountState();
|
|
377
386
|
}
|
|
378
387
|
return report(provider, "kiro:usage-limits", snapshot.quota);
|
|
379
388
|
}
|
|
@@ -19,6 +19,17 @@ export interface ProviderQuotaWindow {
|
|
|
19
19
|
label: string;
|
|
20
20
|
percent: number;
|
|
21
21
|
resetAt?: number;
|
|
22
|
+
/**
|
|
23
|
+
* Set only when the PRODUCER proved this window covers one model family, structurally rather
|
|
24
|
+
* than by reading its label: an Anthropic `seven_day_<family>` body key, or a limit with
|
|
25
|
+
* `kind: "weekly_scoped"` and a recognized `scope.model.display_name`.
|
|
26
|
+
*
|
|
27
|
+
* Absent means provider-wide, which gates every model. That is the fail-closed direction and
|
|
28
|
+
* the behaviour every other producer keeps. Routing must key on THIS, never on the label text:
|
|
29
|
+
* `quota/antigravity.ts` passes an upstream `group.displayName` straight through, so a
|
|
30
|
+
* provider-wide group named "Opus" there would otherwise be mistaken for a per-model window.
|
|
31
|
+
*/
|
|
32
|
+
scope?: "model";
|
|
22
33
|
}
|
|
23
34
|
|
|
24
35
|
export interface ProviderQuotaCreditsUsd {
|
|
@@ -37,6 +48,9 @@ export interface ProviderQuota {
|
|
|
37
48
|
weeklyResetAt?: number;
|
|
38
49
|
monthlyPercent?: number;
|
|
39
50
|
monthlyResetAt?: number;
|
|
51
|
+
/** Observed Kiro plan credits, independent of token and currency estimates. */
|
|
52
|
+
kiroCreditsUsed?: number;
|
|
53
|
+
kiroCreditsLimit?: number;
|
|
40
54
|
customWindows?: ProviderQuotaWindow[];
|
|
41
55
|
creditsUsd?: ProviderQuotaCreditsUsd;
|
|
42
56
|
updatedAt: number;
|
package/src/providers/quota.ts
CHANGED
|
@@ -67,6 +67,8 @@ import {
|
|
|
67
67
|
} from "./quota/vendor-probes-oauth";
|
|
68
68
|
import { fetchCommandCodeQuota, fetchKimiQuota, keyQuotaReaderForProvider } from "./quota/vendor-probes-key";
|
|
69
69
|
import { antigravityQuotaDiagnosticIdentity, fetchAntigravityQuota, probeAntigravityUsageQuota } from "./quota/antigravity";
|
|
70
|
+
import { persistKiroAccountState } from "./kiro-account-state-disk";
|
|
71
|
+
import { kiroProbeCurrent, kiroProbeIdentity } from "./quota/kiro-account-probe";
|
|
70
72
|
|
|
71
73
|
export type { ProviderQuota, ProviderQuotaCreditsUsd, ProviderQuotaWindow } from "./quota-types";
|
|
72
74
|
export { QUOTA_RESPONSE_MAX_BYTES } from "./quota-wire";
|
|
@@ -413,8 +415,6 @@ async function fetchExplicitCurrentQuota(provider: string, config: OcxProviderCo
|
|
|
413
415
|
if (read.result && typeof read.result !== "symbol") accountReportCurrent.set(read.result, isCurrent);
|
|
414
416
|
return read.result;
|
|
415
417
|
}
|
|
416
|
-
|
|
417
|
-
|
|
418
418
|
async function fetchAccountQuota(
|
|
419
419
|
provider: string,
|
|
420
420
|
accountId: string,
|
|
@@ -423,16 +423,22 @@ async function fetchAccountQuota(
|
|
|
423
423
|
): Promise<AccountQuotaCacheEntry> {
|
|
424
424
|
if (!supportsPerAccountQuota(provider)) return { ts: Date.now(), quota: null, unavailable: true };
|
|
425
425
|
if (explicitAccountReader(provider)) return fetchExplicitAccountQuota(provider, accountId, forceRefresh, providerConfig);
|
|
426
|
-
if (provider === "anthropic") hydrateAccountQuotaCache();
|
|
426
|
+
if (provider === "anthropic" || provider === "kiro") hydrateAccountQuotaCache();
|
|
427
427
|
const key = accountCacheKey(provider, accountId);
|
|
428
428
|
const writerGeneration = captureConfigGeneration();
|
|
429
|
-
const
|
|
429
|
+
const kiroIdentity = provider === "kiro" ? kiroProbeIdentity(accountId) : undefined;
|
|
430
|
+
const cachedCandidate = accountQuotaCache.get(key);
|
|
431
|
+
const cached = provider !== "kiro" || cachedCandidate?.identity === kiroIdentity ? cachedCandidate : undefined;
|
|
430
432
|
if (!forceRefresh && cached && Date.now() - cached.ts < ACCOUNT_QUOTA_TTL_MS) {
|
|
431
433
|
if (provider === "google-antigravity" && cached.quotaFailure && cached.quotaFailureIsCurrent?.() !== true) return { ...cached, quotaFailure: undefined };
|
|
432
434
|
return provider === "anthropic" ? { ...cached, quota: normalizeAnthropicQuota(cached.quota, Date.now()) } : cached;
|
|
433
435
|
}
|
|
434
436
|
const joinable = accountQuotaInflight.get(key);
|
|
435
|
-
if (joinable)
|
|
437
|
+
if (joinable) {
|
|
438
|
+
const joined = await joinable;
|
|
439
|
+
return provider !== "kiro" || joined.identity === kiroIdentity
|
|
440
|
+
? joined : fetchAccountQuota(provider, accountId, true, providerConfig);
|
|
441
|
+
}
|
|
436
442
|
|
|
437
443
|
const epoch = explicitAccountEpoch;
|
|
438
444
|
const probe = (async (): Promise<AccountQuotaCacheEntry> => {
|
|
@@ -448,12 +454,6 @@ async function fetchAccountQuota(
|
|
|
448
454
|
let quota: ProviderQuota | null;
|
|
449
455
|
let kiroSnapshot: KiroUsageSnapshot | null = null;
|
|
450
456
|
if (provider === "kiro") {
|
|
451
|
-
// Kiro resolves the bearer and its routing metadata from ONE account-scoped
|
|
452
|
-
// snapshot. It deliberately does not use getTokenForAccountQuotaProbe: that
|
|
453
|
-
// helper refuses to refresh a background `local-cli` slot because Anthropic's
|
|
454
|
-
// lock can adopt a mismatched Claude CLI identity, but Kiro marks every
|
|
455
|
-
// CLI-imported credential `local-cli`, so the same rule would blank the quota of
|
|
456
|
-
// every inactive pool account the moment its token expired.
|
|
457
457
|
kiroSnapshot = await fetchKiroUsageSnapshot(await kiroUsageContextForAccount(accountId));
|
|
458
458
|
quota = kiroSnapshot?.quota ?? null;
|
|
459
459
|
} else {
|
|
@@ -475,31 +475,29 @@ async function fetchAccountQuota(
|
|
|
475
475
|
}
|
|
476
476
|
}
|
|
477
477
|
if (!quota) {
|
|
478
|
-
// Preserve last-good bars
|
|
479
|
-
// negative-cache instead of re-probing on every GUI poll.
|
|
478
|
+
// Preserve last-good bars while negative-caching the failed probe.
|
|
480
479
|
const entry: AccountQuotaCacheEntry = {
|
|
481
480
|
ts: Date.now(),
|
|
482
|
-
// Settle once for all joiners against observations committed during the probe.
|
|
483
481
|
quota: provider === "anthropic"
|
|
484
482
|
? normalizeAnthropicQuota(accountQuotaCache.get(key)?.quota, Date.now()) : cached?.quota ?? null,
|
|
485
483
|
unavailable: true,
|
|
484
|
+
...(provider === "kiro" ? { identity: kiroIdentity } : {}),
|
|
486
485
|
...diagnosticFields(),
|
|
487
486
|
};
|
|
488
|
-
if (mayCommitAccountQuotaKey(key, writerGeneration)) {
|
|
487
|
+
if (mayCommitAccountQuotaKey(key, writerGeneration) && (provider !== "kiro" || kiroProbeCurrent(accountId, kiroIdentity))) {
|
|
489
488
|
accountQuotaCache.set(key, entry);
|
|
490
|
-
if (provider === "kiro")
|
|
489
|
+
if (provider === "kiro") persistKiroAccountState();
|
|
491
490
|
sweepExpiredOnWrite(entry.ts);
|
|
492
491
|
}
|
|
493
492
|
return entry;
|
|
494
493
|
}
|
|
495
494
|
const entry: AccountQuotaCacheEntry = {
|
|
496
495
|
ts: Date.now(), quota: provider === "anthropic" ? normalizeAnthropicQuota(quota, Date.now()) : quota,
|
|
496
|
+
...(provider === "kiro" ? { identity: kiroIdentity } : {}),
|
|
497
497
|
};
|
|
498
|
-
if (mayCommitAccountQuotaKey(key, writerGeneration)) {
|
|
498
|
+
if (mayCommitAccountQuotaKey(key, writerGeneration) && (provider !== "kiro" || kiroProbeCurrent(accountId, kiroIdentity))) {
|
|
499
499
|
accountQuotaCache.set(key, entry);
|
|
500
|
-
|
|
501
|
-
// superseded config generation must not publish either half.
|
|
502
|
-
if (provider === "kiro") commitKiroAccountUsageState(key, kiroSnapshot);
|
|
500
|
+
if (provider === "kiro") { commitKiroAccountUsageState(key, kiroSnapshot, kiroIdentity); persistKiroAccountState(); }
|
|
503
501
|
sweepExpiredOnWrite(entry.ts);
|
|
504
502
|
}
|
|
505
503
|
return entry;
|
|
@@ -510,10 +508,12 @@ async function fetchAccountQuota(
|
|
|
510
508
|
quota: provider === "anthropic"
|
|
511
509
|
? normalizeAnthropicQuota(accountQuotaCache.get(key)?.quota, Date.now()) : cached?.quota ?? null,
|
|
512
510
|
unavailable: true,
|
|
511
|
+
...(provider === "kiro" ? { identity: kiroIdentity } : {}),
|
|
513
512
|
...diagnosticFields(),
|
|
514
513
|
};
|
|
515
|
-
if (mayCommitAccountQuotaKey(key, writerGeneration)) {
|
|
514
|
+
if (mayCommitAccountQuotaKey(key, writerGeneration) && (provider !== "kiro" || kiroProbeCurrent(accountId, kiroIdentity))) {
|
|
516
515
|
accountQuotaCache.set(key, entry);
|
|
516
|
+
if (provider === "kiro") persistKiroAccountState();
|
|
517
517
|
sweepExpiredOnWrite(entry.ts);
|
|
518
518
|
}
|
|
519
519
|
return entry;
|
|
@@ -1402,7 +1402,7 @@ export const PROVIDER_REGISTRY_EXTENDED: readonly ProviderRegistryEntry[] = [
|
|
|
1402
1402
|
dashboardUrl: "https://www.codebuddy.ai/profile/keys",
|
|
1403
1403
|
defaultModel: "default-model",
|
|
1404
1404
|
models: CODEBUDDY_GLOBAL_MODELS,
|
|
1405
|
-
liveModels:
|
|
1405
|
+
liveModels: true,
|
|
1406
1406
|
modelContextWindows: CODEBUDDY_GLOBAL_MODEL_CONTEXT_WINDOWS,
|
|
1407
1407
|
modelMaxOutputTokens: CODEBUDDY_GLOBAL_MODEL_MAX_OUTPUT_TOKENS,
|
|
1408
1408
|
defaultMaxOutputTokens: 32_000,
|
|
@@ -1415,7 +1415,9 @@ export const PROVIDER_REGISTRY_EXTENDED: readonly ProviderRegistryEntry[] = [
|
|
|
1415
1415
|
// Official CodeBuddy Code CLI provider, CHINA / `internal` environment. Identical adapter and
|
|
1416
1416
|
// binary as `codebuddy`; the region is fixed by the profile's CODEBUDDY_INTERNET_ENVIRONMENT
|
|
1417
1417
|
// and this canonical baseUrl. CN key: https://copilot.tencent.com/profile/keys. The CN model
|
|
1418
|
-
// roster differs from Global
|
|
1418
|
+
// roster differs from Global and is discovered live from the key-authenticated product
|
|
1419
|
+
// configuration roster; the seeded list in codebuddy-models.ts is only the degraded
|
|
1420
|
+
// fallback (§八).
|
|
1419
1421
|
id: "codebuddy-cn",
|
|
1420
1422
|
label: "CodeBuddy (CN)",
|
|
1421
1423
|
adapter: "codebuddy",
|
|
@@ -1426,7 +1428,7 @@ export const PROVIDER_REGISTRY_EXTENDED: readonly ProviderRegistryEntry[] = [
|
|
|
1426
1428
|
dashboardUrl: "https://copilot.tencent.com/profile/keys",
|
|
1427
1429
|
defaultModel: "default",
|
|
1428
1430
|
models: CODEBUDDY_CN_MODELS,
|
|
1429
|
-
liveModels:
|
|
1431
|
+
liveModels: true,
|
|
1430
1432
|
modelContextWindows: CODEBUDDY_CN_MODEL_CONTEXT_WINDOWS,
|
|
1431
1433
|
modelMaxOutputTokens: CODEBUDDY_CN_MODEL_MAX_OUTPUT_TOKENS,
|
|
1432
1434
|
defaultMaxOutputTokens: 32_000,
|