Просмотр исходного кода

refactor(e2b): share environment scrubbing

Tianyi Cui 2 месяцев назад
Родитель
Сommit
62df6d0c09

+ 21 - 0
packages/e2b/subprocess-e2b/src/environment.ts

@@ -0,0 +1,21 @@
+/** Shared remote-environment scrubbing for E2B process and terminal launchers. */
+
+import { SENSITIVE_ENV_PATTERN } from '@deepseek-ai/dsh-subprocess'
+
+/**
+ * Parse an E2B NUL-delimited environment while removing harness-private and credential-shaped names.
+ * @param raw - The complete NUL-delimited remote environment.
+ * @returns Mutable retained entries for the caller to overlay and serialize.
+ */
+export function scrubRemoteEnvironment(raw: string): Map<string, string> {
+  const environment = new Map<string, string>()
+  for (const entry of raw.split('\0')) {
+    if (entry.length === 0) continue
+    const separator = entry.indexOf('=')
+    if (separator <= 0) continue
+    const name = entry.slice(0, separator)
+    if (name.startsWith('DSH_') || SENSITIVE_ENV_PATTERN.test(name)) continue
+    environment.set(name, entry.slice(separator + 1))
+  }
+  return environment
+}

+ 2 - 10
packages/e2b/subprocess-e2b/src/process.ts

@@ -8,7 +8,6 @@ import {
   quoteE2BShellArg,
 } from '@deepseek-ai/dsh-e2b'
 import type { CommandHandle, CommandResult, Sandbox } from '@deepseek-ai/dsh-e2b'
-import { SENSITIVE_ENV_PATTERN } from '@deepseek-ai/dsh-subprocess'
 import type {
   SubprocessCollect,
   SubprocessHandle,
@@ -17,6 +16,7 @@ import type {
   SubprocessSpawnSpec,
 } from '@deepseek-ai/dsh-subprocess'
 import type E2BSandboxService from '@deepseek-ai/dsh-e2b'
+import { scrubRemoteEnvironment } from './environment.ts'
 import { E2BBase64Decoder, E2B_OUTPUT_COMPLETE_FRAME, E2BOutputReader } from './output.ts'
 
 const GROUP_POLL_MS = 20
@@ -74,15 +74,7 @@ interface RemotePaths {
 }
 
 function remoteEnvironment(raw: string, explicit: Readonly<Record<string, string>> | undefined): string {
-  const environment = new Map<string, string>()
-  for (const entry of raw.split('\0')) {
-    if (entry.length === 0) continue
-    const separator = entry.indexOf('=')
-    if (separator <= 0) continue
-    const name = entry.slice(0, separator)
-    if (name.startsWith('DSH_') || SENSITIVE_ENV_PATTERN.test(name)) continue
-    environment.set(name, entry.slice(separator + 1))
-  }
+  const environment = scrubRemoteEnvironment(raw)
   for (const [name, value] of Object.entries(explicit ?? {})) environment.set(name, value)
   return [...environment].map(([name, value]) => `${name}=${value}\0`).join('')
 }

+ 3 - 10
packages/e2b/subprocess-e2b/src/terminal.ts

@@ -9,7 +9,7 @@ import {
   quoteE2BShellArg,
 } from '@deepseek-ai/dsh-e2b'
 import type { CommandHandle, CommandResult, Sandbox } from '@deepseek-ai/dsh-e2b'
-import { SENSITIVE_ENV_PATTERN, SubprocessTerminalLifecycle } from '@deepseek-ai/dsh-subprocess'
+import { SubprocessTerminalLifecycle } from '@deepseek-ai/dsh-subprocess'
 import type {
   SubprocessOutcome,
   SubprocessTerminalForeground,
@@ -18,6 +18,7 @@ import type {
   SubprocessTerminalSpawnSpec,
 } from '@deepseek-ai/dsh-subprocess'
 import type E2BSandboxService from '@deepseek-ai/dsh-e2b'
+import { scrubRemoteEnvironment } from './environment.ts'
 
 const POLL_MS = 20
 
@@ -71,15 +72,7 @@ function serializeValues(values: readonly string[], kind: string): string {
 }
 
 function remoteEnvironment(raw: string, explicit: Readonly<Record<string, string>> | undefined): string {
-  const environment = new Map<string, string>()
-  for (const entry of raw.split('\0')) {
-    if (entry.length === 0) continue
-    const separator = entry.indexOf('=')
-    if (separator <= 0) continue
-    const name = entry.slice(0, separator)
-    if (name.startsWith('DSH_') || SENSITIVE_ENV_PATTERN.test(name)) continue
-    environment.set(name, entry.slice(separator + 1))
-  }
+  const environment = scrubRemoteEnvironment(raw)
   for (const [name, value] of Object.entries(explicit ?? {})) {
     if (name.length === 0 || name.includes('=') || name.includes('\0') || value.includes('\0')) {
       throw new Error('subprocess-e2b: terminal environment entries require non-empty NUL-free names without = and NUL-free values')