feat: support pentests with Codex subscription auth (#419)

This commit is contained in:
ezl-keygraph
2026-08-10 15:27:19 +05:30
committed by GitHub
parent 760a140228
commit d4cc2ab974
11 changed files with 136 additions and 10 deletions
+20 -1
View File
@@ -21,8 +21,10 @@
* built over an in-memory credential store primed from the environment.
*/
import { existsSync } from 'node:fs';
import path from 'node:path';
import type { Api, Credential, CredentialInfo, CredentialStore, Model } from '@earendil-works/pi-ai';
import { ModelRuntime } from '@earendil-works/pi-coding-agent';
import { getAgentDir, ModelRuntime } from '@earendil-works/pi-coding-agent';
/**
* Providers Shannon curates with their own credential variables, config sections,
@@ -203,12 +205,29 @@ class RuntimeCredentialStore implements CredentialStore {
}
}
/** The file pi reads credentials from: the agent dir's auth.json. */
function piAuthPath(): string {
return path.join(getAgentDir(), 'auth.json');
}
/** Whether the host's pi credentials are mounted (auth.json present in the agent dir). */
export function piAuthPresent(): boolean {
return existsSync(piAuthPath());
}
/**
* Build a ModelRuntime whose only credential is the one supplied. Model catalogs
* stay offline (`allowModelNetwork` defaults to false) so a scan never blocks on
* a catalog refresh.
*
* When the host's pi auth.json is present, the runtime reads it instead: pi's
* disk-backed store resolves the credential. The mount is writable so OAuth
* refreshes persist to the host for subsequent runs.
*/
export async function createModelRuntime(providerId: string, apiKey: string | undefined): Promise<ModelRuntime> {
if (piAuthPresent()) {
return ModelRuntime.create({ authPath: piAuthPath() });
}
return ModelRuntime.create({ credentials: new RuntimeCredentialStore(providerId, apiKey) });
}
+6 -2
View File
@@ -42,6 +42,7 @@ import {
type ModelSpec,
type OpenAiFormat,
PI_CATALOG_URL,
piAuthPresent,
resolveGatewayFormat,
resolveModel,
resolveModelSpec,
@@ -296,6 +297,7 @@ function credentialHint(providerId: string): string {
/** Human-readable label for which credential path a run is using. */
function describeAuth(providerId: string, baseUrl: string | undefined): string {
if (baseUrl) return `custom endpoint (${baseUrl})`;
if (piAuthPresent()) return `${providerId} credentials from pi auth.json`;
if (providerId === 'amazon-bedrock') return 'Bedrock bearer token';
return `${providerId} API key`;
}
@@ -341,9 +343,11 @@ async function validateCredentials(logger: ActivityLogger): Promise<Result<void,
);
}
// With a mounted pi auth.json the env-var checks don't apply — step 5's probe validates it.
const isBedrock = spec.providerId === 'amazon-bedrock';
const missing = isBedrock ? ['AWS_REGION', 'AWS_BEARER_TOKEN_BEDROCK'].filter((n) => !process.env[n]) : [];
if (missing.length > 0 || (!isBedrock && !credentials.apiKey)) {
const missing =
isBedrock && !piAuthPresent() ? ['AWS_REGION', 'AWS_BEARER_TOKEN_BEDROCK'].filter((n) => !process.env[n]) : [];
if (!piAuthPresent() && (missing.length > 0 || (!isBedrock && !credentials.apiKey))) {
return err(
new PentestError(
`No credentials found for provider "${spec.providerId}". Set ${credentialHint(spec.providerId)} in .env.`,