Files
goodbuddy/src/main/agent/process-environment.ts
T
mesalogo eb53c827c6 fix: apply runtime telemetry settings to web and remote clients
DS Web and remote Agent launch paths omitted shared telemetry opt-out settings. Reuse one environment definition for local launches, remote runtime profiles, and the remote model bridge helper while preserving existing update controls and user-requested networking.

Validation: 16 focused tests passed at commit time. Prior local real-model validation passed; modified Agent real-Host validation and background network monitoring remain outstanding.

Release note: 补齐 DS Web 与远程 Runtime 启动时的遥测关闭配置,保留现有自动更新关闭设置,不影响模型、MCP 和用户主动联网请求。
2026-09-27 13:57:26 +08:00

166 lines
4.1 KiB
TypeScript

import { runtimePrivacyEnvironment } from '../../shared/runtime-privacy-environment'
export { runtimePrivacyEnvironment } from '../../shared/runtime-privacy-environment'
import type { LaunchEnvironmentProvider } from '../local-tool-environment/launch-environment-provider'
export const runtimeProviderEnvironmentNames = [
'ANTHROPIC_API_KEY',
'OPENAI_API_KEY',
'GOOGLE_GENERATIVE_AI_API_KEY',
'GEMINI_API_KEY',
'GROQ_API_KEY',
'AZURE_OPENAI_API_KEY',
'AWS_ACCESS_KEY_ID',
'AWS_SECRET_ACCESS_KEY',
'AWS_SESSION_TOKEN',
'AWS_REGION',
'AWS_PROFILE',
'OPENROUTER_API_KEY',
'XAI_API_KEY',
'MISTRAL_API_KEY',
'COHERE_API_KEY'
] as const
const userProcessCredentialEnvironmentNames = new Set<string>([
...runtimeProviderEnvironmentNames,
'DEEPSEEK_API_KEY',
'DASHSCOPE_API_KEY',
'TOGETHER_API_KEY',
'FIREWORKS_API_KEY',
'PERPLEXITY_API_KEY',
'CEREBRAS_API_KEY',
'CLAUDE_CODE_OAUTH_TOKEN'
])
export function buildCredentialFilteredUserEnvironment(
source: NodeJS.ProcessEnv = process.env
): NodeJS.ProcessEnv {
const environment: NodeJS.ProcessEnv = {}
for (const [name, value] of Object.entries(source)) {
const upperName = name.toUpperCase()
if (
value !== undefined &&
upperName !== 'ELECTRON_RUN_AS_NODE' &&
!upperName.startsWith('GOODBUDDY_') &&
!upperName.startsWith('FACTORY_') &&
!userProcessCredentialEnvironmentNames.has(upperName)
) {
environment[name] = value
}
}
return environment
}
/**
* Applies only the PATH prepared by the local tool environment. In
* particular, arbitrary values from that snapshot must not bypass the
* credential filtering performed by the caller.
*/
export function applyLaunchEnvironmentPath(
environment: NodeJS.ProcessEnv,
provider?: LaunchEnvironmentProvider
): NodeJS.ProcessEnv {
if (!provider) {
return environment
}
const launchEnvironment = provider()
const path =
launchEnvironment.PATH ??
launchEnvironment.Path ??
launchEnvironment.path
if (path === undefined) {
return environment
}
const result = { ...environment }
const existingPathName = Object.keys(environment).find(
(name) => name.toLowerCase() === 'path'
)
for (const name of Object.keys(result)) {
if (name.toLowerCase() === 'path') {
delete result[name]
}
}
result[existingPathName ?? 'PATH'] = path
return result
}
const runtimeEnvironmentAllowlist = [
'PATH',
'Path',
'PATHEXT',
'SystemRoot',
'COMSPEC',
'TEMP',
'TMP',
'TMPDIR',
'HOME',
'USERPROFILE',
'APPDATA',
'LOCALAPPDATA',
'PROGRAMDATA',
'LANG',
'LC_ALL',
'LC_CTYPE',
'SSL_CERT_FILE',
'SSL_CERT_DIR',
'NODE_EXTRA_CA_CERTS',
'HTTP_PROXY',
'HTTPS_PROXY',
'NO_PROXY',
...runtimeProviderEnvironmentNames
] as const
export type RuntimeProfileCredential = {
name: 'ANTHROPIC_API_KEY' | 'OPENAI_API_KEY'
value: string
}
export function buildRuntimeEnvironment(
overrides: NodeJS.ProcessEnv,
source: NodeJS.ProcessEnv = process.env
): NodeJS.ProcessEnv {
const environment: NodeJS.ProcessEnv = {}
for (const name of runtimeEnvironmentAllowlist) {
if (source[name] !== undefined) {
environment[name] = source[name]
}
}
return {
...environment,
...overrides,
NODE_TLS_REJECT_UNAUTHORIZED: '0'
}
}
export function buildExplicitProfileRuntimeEnvironment(
overrides: NodeJS.ProcessEnv,
credential?: RuntimeProfileCredential,
source: NodeJS.ProcessEnv = process.env
): NodeJS.ProcessEnv {
const environment = buildRuntimeEnvironment(overrides, source)
for (const name of runtimeProviderEnvironmentNames) {
delete environment[name]
}
if (credential) {
environment[credential.name] = credential.value
}
return environment
}
export function buildControlledHarnessEnvironment(
dshHome: string,
source: NodeJS.ProcessEnv = process.env
): NodeJS.ProcessEnv {
const environment = buildExplicitProfileRuntimeEnvironment(
{
DSH_HOME: dshHome,
DSH_TELEMETRY_DISABLED: '1',
...runtimePrivacyEnvironment
},
undefined,
source
)
delete environment.NODE_TLS_REJECT_UNAUTHORIZED
return environment
}