fix(opencode-go): don't fall back to OPENCODE_API_KEY when the credential database is unreadable (#24605)

* fix(opencode-go): stop before OPENCODE_API_KEY when the credential database is unreadable

An unreadable OpenCode credential database read as 'no key', so the Go key
resolver fell through to OPENCODE_API_KEY, which OpenCode shares with its
Zen provider and can show usage for the wrong key. The database read now
reports unreadable separately; with an env key set the resolver stops, and
the usage fetch uses a configured cookie or shows a readable error.

* fix(opencode-go): treat a denied credential-database listing as unreadable, not missing
This commit is contained in:
Jinwoo Hong
2026-10-02 19:00:27 -04:00
committed by GitHub
parent 13ce9a77d0
commit a1da632eb9
5 changed files with 175 additions and 19 deletions
@@ -30,7 +30,9 @@ function getOpenCodeDatabaseOverride(dataDirectory: string): OpenCodeDatabaseOve
export async function listOpenCodeDatabases(
/** Lets a caller report the refusal; an empty list otherwise reads as
* "OpenCode not used" rather than "we could not look". */
onRefusal?: (path: string, error: WslTranscriptFsError) => void
onRefusal?: (path: string, error: WslTranscriptFsError) => void,
/** Every other stat/readdir failure, including ENOENT; also read as an empty list. */
onFsError?: (path: string, error: unknown) => void
): Promise<string[]> {
const dataDirectory = resolveOpenCodeDataDirectory()
const databaseOverride = getOpenCodeDatabaseOverride(dataDirectory)
@@ -43,7 +45,7 @@ export async function listOpenCodeDatabases(
? [databaseOverride.path]
: []
} catch (error) {
reportRefusal(databaseOverride.path, error, onRefusal)
reportFailure(databaseOverride.path, error, onRefusal, onFsError)
return []
}
}
@@ -55,18 +57,21 @@ export async function listOpenCodeDatabases(
.map((entry) => join(dataDirectory, entry.name))
.sort()
} catch (error) {
reportRefusal(dataDirectory, error, onRefusal)
reportFailure(dataDirectory, error, onRefusal, onFsError)
return []
}
}
function reportRefusal(
function reportFailure(
path: string,
error: unknown,
onRefusal?: (path: string, error: WslTranscriptFsError) => void
onRefusal?: (path: string, error: WslTranscriptFsError) => void,
onFsError?: (path: string, error: unknown) => void
): void {
if (error instanceof WslTranscriptFsError) {
onRefusal?.(path, error)
} else {
onFsError?.(path, error)
}
}