File tree Expand file tree Collapse file tree
first-class-providers/src Expand file tree Collapse file tree Original file line number Diff line number Diff line change 11import { describe , expect , test } from "bun:test" ;
22import {
33 FIRST_CLASS_PROVIDERS ,
4- connectListProviders ,
54 firstClassPathAsProvider ,
65 firstClassProviderById ,
76} from "./providers.js" ;
@@ -21,10 +20,6 @@ describe("FIRST_CLASS_PROVIDERS", () => {
2120 ] ) ;
2221 } ) ;
2322
24- test ( "connectListProviders matches FIRST_CLASS_PROVIDERS" , ( ) => {
25- expect ( connectListProviders ( ) ) . toBe ( FIRST_CLASS_PROVIDERS ) ;
26- } ) ;
27-
2823 test ( "has no separate Codex connect row" , ( ) => {
2924 expect ( FIRST_CLASS_PROVIDERS . some ( ( p ) => p . id === "codex" ) ) . toBe ( false ) ;
3025 expect ( FIRST_CLASS_PROVIDERS . map ( ( p ) => p . label ) ) . not . toContain (
Original file line number Diff line number Diff line change @@ -164,11 +164,6 @@ export const FIRST_CLASS_PROVIDERS: readonly FirstClassProviderDef[] = [
164164 } ,
165165] as const ;
166166
167- /** Connect-list rows (same as FIRST_CLASS_PROVIDERS; explicit export for hosts). */
168- export function connectListProviders ( ) : readonly FirstClassProviderDef [ ] {
169- return FIRST_CLASS_PROVIDERS ;
170- }
171-
172167export function firstClassProviderById (
173168 id : string ,
174169) : FirstClassProviderDef | undefined {
Original file line number Diff line number Diff line change 77import {
88 OPENCODE_GO_DEFAULT_MODEL ,
99 OPENCODE_GO_MODEL_IDS ,
10- OPENCODE_GO_MODELS ,
10+ PROTOCOL_BY_ID ,
1111 type GoProtocol ,
1212} from "./models.js" ;
1313
@@ -23,10 +23,8 @@ interface GoCatalogEntry {
2323}
2424
2525export function buildGoCatalogEntry ( ) : GoCatalogEntry {
26- const protocols : Record < string , GoProtocol > = { } ;
27- for ( const m of OPENCODE_GO_MODELS ) {
28- protocols [ m . id ] = m . protocol ;
29- }
26+ const protocols : Record < string , GoProtocol > =
27+ Object . fromEntries ( PROTOCOL_BY_ID ) ;
3028 return {
3129 name : OPENCODE_GO_PROVIDER_ID ,
3230 displayName : OPENCODE_GO_DISPLAY_NAME ,
Original file line number Diff line number Diff line change @@ -3,6 +3,12 @@ import {
33 OPENCODE_GO_PROVIDER_ID ,
44} from "./constants.js" ;
55
6+ /** True when `host` is opencode.ai or a subdomain of it (case-insensitive). */
7+ export function hostMatchesOpencodeDotAi ( host : string ) : boolean {
8+ const normalized = host . trim ( ) . toLowerCase ( ) ;
9+ return normalized === "opencode.ai" || normalized . endsWith ( ".opencode.ai" ) ;
10+ }
11+
612/**
713 * True when the URL or base is the public OpenCode Go gateway.
814 *
@@ -21,10 +27,7 @@ export function isOpenCodeGoURL(urlOrBase: string | undefined): boolean {
2127 if ( trimmed . length === 0 ) return false ;
2228 try {
2329 const url = new URL ( trimmed ) ;
24- if (
25- url . hostname !== "opencode.ai" &&
26- ! url . hostname . endsWith ( ".opencode.ai" )
27- ) {
30+ if ( ! hostMatchesOpencodeDotAi ( url . hostname ) ) {
2831 return false ;
2932 }
3033 // Strip trailing slashes, then compare path segments case-insensitively.
Original file line number Diff line number Diff line change @@ -19,5 +19,6 @@ export {
1919 isOpenCodeGoProvider ,
2020 isOpenCodeGoProviderId ,
2121 isOpenCodeGoURL ,
22+ hostMatchesOpencodeDotAi ,
2223} from "./identity.js" ;
2324export { parseGoAPIError } from "./errors.js" ;
Original file line number Diff line number Diff line change @@ -63,7 +63,7 @@ export const OPENCODE_GO_MODEL_IDS: readonly string[] = OPENCODE_GO_MODELS.map(
6363
6464export const OPENCODE_GO_DEFAULT_MODEL : GoModelId = "kimi-k2.7-code" ;
6565
66- const PROTOCOL_BY_ID = new Map < string , GoProtocol > (
66+ export const PROTOCOL_BY_ID = new Map < string , GoProtocol > (
6767 OPENCODE_GO_MODELS . map ( ( m ) => [ m . id , m . protocol ] ) ,
6868) ;
6969
Original file line number Diff line number Diff line change @@ -99,6 +99,20 @@ export async function fetchGoUsage(
9999 }
100100}
101101
102+ function formatUsagePercent ( w : GoUsageWindow ) : string {
103+ if ( w . usagePercent !== undefined ) return `${ Math . round ( w . usagePercent ) } %` ;
104+ if ( w . usageDollars !== undefined && w . limitDollars !== undefined ) {
105+ return `$${ w . usageDollars . toFixed ( 2 ) } /$${ w . limitDollars . toFixed ( 0 ) } ` ;
106+ }
107+ return "ok" ;
108+ }
109+
110+ function usageWindowLabel ( usage : GoUsage ) : string {
111+ if ( usage . rolling5h !== undefined ) return "5h" ;
112+ if ( usage . weekly !== undefined ) return "week" ;
113+ return "month" ;
114+ }
115+
102116export function formatGoUsage ( usage : GoUsage ) : string {
103117 if ( usage . status !== "ok" ) {
104118 if ( usage . status === "unavailable" ) return "Go usage unavailable" ;
@@ -109,17 +123,5 @@ export function formatGoUsage(usage: GoUsage): string {
109123 }
110124 const w = usage . rolling5h ?? usage . weekly ?? usage . monthly ;
111125 if ( w === undefined ) return "Go usage ok" ;
112- const pct =
113- w . usagePercent !== undefined
114- ? `${ Math . round ( w . usagePercent ) } %`
115- : w . usageDollars !== undefined && w . limitDollars !== undefined
116- ? `$${ w . usageDollars . toFixed ( 2 ) } /$${ w . limitDollars . toFixed ( 0 ) } `
117- : "ok" ;
118- const window =
119- usage . rolling5h !== undefined
120- ? "5h"
121- : usage . weekly !== undefined
122- ? "week"
123- : "month" ;
124- return `Go ${ window } ${ pct } ` ;
126+ return `Go ${ usageWindowLabel ( usage ) } ${ formatUsagePercent ( w ) } ` ;
125127}
Original file line number Diff line number Diff line change 33// helpers; Go's own URL and id keep matching Go first, never Zen.
44
55import { ZEN_DISPLAY_NAME , ZEN_PROVIDER_ID } from "./constants.js" ;
6-
7- function hostMatchesOpencodeDotAi ( host : string ) : boolean {
8- const normalized = host . trim ( ) . toLowerCase ( ) ;
9- return normalized === "opencode.ai" || normalized . endsWith ( ".opencode.ai" ) ;
10- }
6+ import { hostMatchesOpencodeDotAi } from "../../opencode-go/src/index.js" ;
117
128/**
139 * Match a bare Zen base URL: an opencode.ai URL whose first path segment is
You can’t perform that action at this time.
0 commit comments