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 和用户主动联网请求。
166 lines
4.1 KiB
TypeScript
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
|
|
}
|