feat: complete evidence restructuring worktree
This commit is contained in:
@@ -42,9 +42,14 @@ const PROVIDER_KEY_ENV: Readonly<Record<string, string>> = {
|
||||
const COMPOUND_PROVIDERS = new Set([
|
||||
"amazon-bedrock", "azure-openai-responses", "cloudflare-ai-gateway", "cloudflare-workers-ai",
|
||||
]);
|
||||
const LOCAL_PROVIDERS = new Set([
|
||||
"ollama", "lmstudio", "local", "aritmolab", "local-qwen", "faux",
|
||||
]);
|
||||
|
||||
function configuredCredentialEnv(apiKey: string | undefined): string | null | undefined {
|
||||
if (apiKey === undefined) return undefined;
|
||||
if (!apiKey.startsWith("$")) return null;
|
||||
const matched = /^\$(?:\{([A-Z][A-Z0-9_]*(?:API_KEY|TOKEN))\}|([A-Z][A-Z0-9_]*(?:API_KEY|TOKEN)))$/.exec(apiKey);
|
||||
if (!matched) throw new Error("model provider credential is unavailable");
|
||||
return matched[1] ?? matched[2];
|
||||
}
|
||||
|
||||
export function canonicalPiProvider(provider: string | undefined): string | undefined {
|
||||
const value = provider?.trim().toLowerCase();
|
||||
@@ -106,6 +111,8 @@ export function buildPiChildEnv(opts: {
|
||||
credentialFile?: string;
|
||||
additions?: NodeJS.ProcessEnv;
|
||||
credentialValue?: string;
|
||||
/** Exact apiKey declaration from the selected provider in models.json. */
|
||||
configuredApiKey?: string;
|
||||
fsOps?: CredentialFsOps;
|
||||
/**
|
||||
* Providers pi can authenticate from its own auth store. For these, the single
|
||||
@@ -147,17 +154,22 @@ export function buildPiChildEnv(opts: {
|
||||
delete env.THT_SSL_CA_FILE;
|
||||
for (const name of PI_0803_CREDENTIAL_ENV_NAMES) delete env[name];
|
||||
const provider = canonicalPiProvider(opts.provider);
|
||||
const configuredEnv = configuredCredentialEnv(opts.configuredApiKey);
|
||||
if (configuredEnv) delete env[configuredEnv];
|
||||
if (provider && COMPOUND_PROVIDERS.has(provider)) {
|
||||
throw new Error(
|
||||
"compound credential bundles are unsupported by THT_MODEL_API_KEY_FILE; "
|
||||
+ "dedicated provider configuration is required",
|
||||
);
|
||||
}
|
||||
if (provider && !LOCAL_PROVIDERS.has(provider)) {
|
||||
if (provider) {
|
||||
// pi self-authenticates this provider from its own auth store; injecting the
|
||||
// single managed key here would force one provider's key onto another.
|
||||
if (opts.authProviders?.has(provider)) return env;
|
||||
const envName = PROVIDER_KEY_ENV[provider];
|
||||
// A literal apiKey is entirely owned by models.json (commonly a non-secret
|
||||
// placeholder for a local OpenAI-compatible endpoint) and needs no managed key.
|
||||
if (configuredEnv === null) return env;
|
||||
const envName = configuredEnv ?? PROVIDER_KEY_ENV[provider];
|
||||
if (!envName || (!opts.credentialFile && opts.credentialValue === undefined)) {
|
||||
throw new Error("model provider credential is unavailable");
|
||||
}
|
||||
@@ -169,7 +181,7 @@ export function buildPiChildEnv(opts: {
|
||||
}
|
||||
else if (opts.credentialFile) env[envName] = readCredential(opts.credentialFile, opts.fsOps ?? realFs);
|
||||
else throw new Error("model provider credential is unavailable");
|
||||
} else if (opts.credentialFile && !provider) {
|
||||
} else if (opts.credentialFile) {
|
||||
throw new Error("model provider credential is unavailable");
|
||||
}
|
||||
return env;
|
||||
@@ -181,11 +193,14 @@ export function piProviderCredentialStatus(opts: {
|
||||
credentialFile?: string;
|
||||
resolveCredentialValue?: () => string | undefined;
|
||||
authProviders?: ReadonlySet<string>;
|
||||
configuredApiKey?: string;
|
||||
fsOps?: CredentialFsOps;
|
||||
}): PiCredentialStatus {
|
||||
const provider = canonicalPiProvider(opts.provider);
|
||||
if (!provider || LOCAL_PROVIDERS.has(provider)) return "missing";
|
||||
if (!provider) return "missing";
|
||||
if (opts.authProviders?.has(provider)) return "present";
|
||||
const configuredEnv = configuredCredentialEnv(opts.configuredApiKey);
|
||||
if (configuredEnv === null) return "missing";
|
||||
try {
|
||||
buildPiChildEnv({
|
||||
ambient: {},
|
||||
@@ -193,6 +208,7 @@ export function piProviderCredentialStatus(opts: {
|
||||
credentialFile: opts.credentialFile,
|
||||
credentialValue: opts.resolveCredentialValue?.(),
|
||||
authProviders: opts.authProviders,
|
||||
configuredApiKey: opts.configuredApiKey,
|
||||
fsOps: opts.fsOps,
|
||||
});
|
||||
return "present";
|
||||
|
||||
Reference in New Issue
Block a user