From c3827466eb5f19bbcff42c07ac16bf656027039c Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Fri, 19 Jun 2026 10:47:16 +0700 Subject: [PATCH] Share Paseo Agent env reference helpers --- .../providers/paseo-agent/config-service.ts | 5 ++-- .../agent/providers/paseo-agent/config.ts | 5 ++-- .../providers/paseo-agent/env-references.ts | 23 ++++++++++++++++ .../paseo-agent/oauth-credentials.ts | 26 ++++--------------- 4 files changed, 32 insertions(+), 27 deletions(-) create mode 100644 packages/server/src/server/agent/providers/paseo-agent/env-references.ts diff --git a/packages/server/src/server/agent/providers/paseo-agent/config-service.ts b/packages/server/src/server/agent/providers/paseo-agent/config-service.ts index 4c12c1b84f..0ed8d5469a 100644 --- a/packages/server/src/server/agent/providers/paseo-agent/config-service.ts +++ b/packages/server/src/server/agent/providers/paseo-agent/config-service.ts @@ -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", diff --git a/packages/server/src/server/agent/providers/paseo-agent/config.ts b/packages/server/src/server/agent/providers/paseo-agent/config.ts index 42ba6f6bda..e8952e41f2 100644 --- a/packages/server/src/server/agent/providers/paseo-agent/config.ts +++ b/packages/server/src/server/agent/providers/paseo-agent/config.ts @@ -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; } diff --git a/packages/server/src/server/agent/providers/paseo-agent/env-references.ts b/packages/server/src/server/agent/providers/paseo-agent/env-references.ts new file mode 100644 index 0000000000..f88b3a62ff --- /dev/null +++ b/packages/server/src/server/agent/providers/paseo-agent/env-references.ts @@ -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; +} diff --git a/packages/server/src/server/agent/providers/paseo-agent/oauth-credentials.ts b/packages/server/src/server/agent/providers/paseo-agent/oauth-credentials.ts index e4d310389b..5613efbb36 100644 --- a/packages/server/src/server/agent/providers/paseo-agent/oauth-credentials.ts +++ b/packages/server/src/server/agent/providers/paseo-agent/oauth-credentials.ts @@ -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; }