Share Paseo Agent env reference helpers

This commit is contained in:
Mohamed Boudra
2026-07-02 08:38:27 +02:00
parent c52482368b
commit c3827466eb
4 changed files with 32 additions and 27 deletions
@@ -18,6 +18,7 @@ import {
} from "./config.js";
import { hasStoredOAuthCredential, storeCodexOAuthCredential } from "./oauth-store.js";
import { isRefreshTokenExpressionConfigured } from "./oauth-credentials.js";
import { findEnvReferences } from "./env-references.js";
interface PaseoAgentConfigServiceOptions {
paseoHome: string;
@@ -46,8 +47,6 @@ interface SetProviderInput {
};
}
const ENV_REFERENCE_PATTERN = /\$\{?([A-Za-z_][A-Za-z0-9_]*)\}?/g;
function resolveEnv(paseoHome: string, env?: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
return env ?? { ...process.env, PASEO_HOME: paseoHome };
}
@@ -71,7 +70,7 @@ function authStateForApiKey(
if (value.startsWith("!")) {
return { kind: "api_key", configured: true, source: "command" };
}
const referencedVars = Array.from(value.matchAll(ENV_REFERENCE_PATTERN), (match) => match[1]);
const referencedVars = findEnvReferences(value);
if (referencedVars.length > 0) {
return {
kind: "api_key",
@@ -6,6 +6,7 @@ import {
resolveRefreshTokenExpression,
} from "./oauth-credentials.js";
import type { PaseoAgentInferenceProvider, PaseoAgentModelReference } from "./pi-services.js";
import { findEnvReferences } from "./env-references.js";
export const PASEO_AGENT_PROVIDER = "paseo";
@@ -212,8 +213,6 @@ function resolveProviderSettings(
};
}
const ENV_REFERENCE_PATTERN = /\$\{?([A-Za-z_][A-Za-z0-9_]*)\}?/g;
/**
* Whether a resolved API-key value is actually configured. Mirrors Pi's config-value
* semantics without importing Pi: literals and `!command` values count as present;
@@ -226,7 +225,7 @@ function isAuthConfigured(value: string | undefined, env: NodeJS.ProcessEnv): bo
if (value.startsWith("!")) {
return true;
}
const referencedVars = Array.from(value.matchAll(ENV_REFERENCE_PATTERN), (match) => match[1]);
const referencedVars = findEnvReferences(value);
if (referencedVars.length === 0) {
return true;
}
@@ -0,0 +1,23 @@
const ENV_REFERENCE_PATTERN = /\$\{?([A-Za-z_][A-Za-z0-9_]*)\}?/g;
const ENV_REFERENCE_DETECT = /\$\{?[A-Za-z_][A-Za-z0-9_]*\}?/;
export function findEnvReferences(value: string): string[] {
return Array.from(value.matchAll(ENV_REFERENCE_PATTERN), (match) => match[1]);
}
export function hasEnvReference(value: string): boolean {
return ENV_REFERENCE_DETECT.test(value);
}
export function substituteEnvReferences(value: string, env: NodeJS.ProcessEnv): string | undefined {
let missing = false;
const result = value.replace(ENV_REFERENCE_PATTERN, (_match, name: string) => {
const resolved = env[name];
if (resolved === undefined) {
missing = true;
return "";
}
return resolved;
});
return missing ? undefined : result;
}
@@ -1,4 +1,5 @@
import { execSync } from "node:child_process";
import { hasEnvReference, substituteEnvReferences } from "./env-references.js";
// Resolution of a *self-supplied* OAuth refresh token expression — a literal, an env
// reference (`$VAR` / `${VAR}`), or a `!command` that prints the token. This is an
@@ -9,23 +10,6 @@ import { execSync } from "node:child_process";
// This module deliberately does NOT read any other tool's auth files (Codex CLI,
// OpenCode, Pi, etc.) and imports no Pi runtime code. Token values are never logged.
const ENV_REFERENCE_PATTERN = /\$\{?([A-Za-z_][A-Za-z0-9_]*)\}?/g;
const ENV_REFERENCE_DETECT = /\$\{?[A-Za-z_][A-Za-z0-9_]*\}?/;
/** Substitute `$VAR` / `${VAR}` references. Returns undefined if any var is unset. */
function substituteEnv(value: string, env: NodeJS.ProcessEnv): string | undefined {
let missing = false;
const result = value.replace(ENV_REFERENCE_PATTERN, (_match, name: string) => {
const resolved = env[name];
if (resolved === undefined) {
missing = true;
return "";
}
return resolved;
});
return missing ? undefined : result;
}
/**
* Resolve a refresh-token expression to its literal value (may run a `!command`).
* Returns undefined when it can't be resolved.
@@ -46,8 +30,8 @@ export function resolveRefreshTokenExpression(
return undefined;
}
}
if (ENV_REFERENCE_DETECT.test(value)) {
const substituted = substituteEnv(value, env);
if (hasEnvReference(value)) {
const substituted = substituteEnvReferences(value, env);
return substituted && substituted.length > 0 ? substituted : undefined;
}
return value.length > 0 ? value : undefined;
@@ -64,8 +48,8 @@ export function isRefreshTokenExpressionConfigured(
if (value.startsWith("!")) {
return true;
}
if (ENV_REFERENCE_DETECT.test(value)) {
return substituteEnv(value, env) !== undefined;
if (hasEnvReference(value)) {
return substituteEnvReferences(value, env) !== undefined;
}
return value.length > 0;
}