fix(code-runtime): separate model environment from native startup paths
This commit is contained in:
1 parent
a6f7eeadc6
commit
98d3af0683
12 files changed
+46
-14
No files matched your search
@@ -0,0 +1,4 @@
|
||||
/** Startup variables required by native executables before model evaluation. */
|
||||
|
||||
/** Native executable search and Windows system paths retained in the OS environment. */
|
||||
export const STARTUP_ENVIRONMENT_NAMES: ReadonlySet<string> = new Set(['PATH', 'PATHEXT', 'SYSTEMROOT', 'WINDIR'])
|
||||
@@ -18,6 +18,7 @@ import { bootstrapArgs } from './launch.ts'
|
||||
import type { LaunchConfig } from './launch.ts'
|
||||
import { OutputLedger } from './output-ledger.ts'
|
||||
import { drainOutput } from './output-stream.ts'
|
||||
import { STARTUP_ENVIRONMENT_NAMES } from './environment.ts'
|
||||
import { decodeCodeJsonWire, encodeCodeJsonWire } from './json-wire.ts'
|
||||
import type { ProgramBootData } from './protocol.ts'
|
||||
|
||||
@@ -43,7 +44,6 @@ type ResolvedConfig = Required<Omit<Config, 'bootstrapPath'>> & Pick<Config, 'bo
|
||||
interface LiveRun { controller: AbortController; finished: Promise<void> }
|
||||
const STRIP_PREFIX = 'async function __dsh_program__() {\n'
|
||||
const STRIP_SUFFIX = '\n}'
|
||||
const STARTUP_ENVIRONMENT = new Set(['PATH', 'PATHEXT', 'SYSTEMROOT', 'WINDIR'])
|
||||
|
||||
function messageOf(error: unknown): string { return error instanceof Error ? error.message : String(error) }
|
||||
function record(value: unknown): value is Record<string, unknown> { return typeof value === 'object' && value !== null && !Array.isArray(value) }
|
||||
@@ -213,9 +213,9 @@ export class NodeCodeRuntime extends CodeRuntime {
|
||||
const argv = [executable, `--max-old-space-size=${this.config.maxOldGenerationSizeMb}`, ...bootstrapArgs(this.ctx.fs, this.config, this.config.maxMessageBytes)]
|
||||
confined = policy.mode === 'danger-full-access' ? undefined : this.ctx.sandbox.confine(argv, { ...policy, mode: policy.mode })
|
||||
if (confined !== undefined) sandbox.enforcement = confined.enforcement
|
||||
// Native launchers need executable search and Windows system paths until the child clears its environment.
|
||||
// Native launchers need executable search and Windows system paths before the child installs its model environment.
|
||||
const env: NodeJS.ProcessEnv = Object.fromEntries(Object.keys(process.env)
|
||||
.filter(key => !STARTUP_ENVIRONMENT.has(key.toUpperCase()))
|
||||
.filter(key => !STARTUP_ENVIRONMENT_NAMES.has(key.toUpperCase()))
|
||||
.map(key => [key, undefined]))
|
||||
if ('pkg' in process && this.config.bootstrapPath === undefined) env.DSH_CODE_RUNTIME_NODE = '1'
|
||||
handle = this.ctx.subprocess.spawn({ argv: confined?.argv ?? argv, cwd: spec.cwd, env, stdio: { stdin: 'ignore', stdout: 'pipe', stderr: 'pipe', control: 'pipe' }, graceMs: this.config.graceMs, signal })
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import type { Duplex } from 'node:stream'
|
||||
import { JsonChannel } from './channel.ts'
|
||||
import { runProgram } from './bootstrap.ts'
|
||||
import { STARTUP_ENVIRONMENT_NAMES } from './environment.ts'
|
||||
import type { PatchableStream } from './bootstrap.ts'
|
||||
import type { ReplyMessage, ProgramBootData, ProgramToHost } from './protocol.ts'
|
||||
|
||||
@@ -22,7 +23,11 @@ export interface ProgramProcess {
|
||||
*/
|
||||
export async function runNodeMain(stream: Duplex, maxMessageBytes: number, processState: ProgramProcess): Promise<void> {
|
||||
if (!Number.isSafeInteger(maxMessageBytes) || maxMessageBytes <= 0 || maxMessageBytes > 0xffff_ffff) throw new Error('invalid control message limit')
|
||||
for (const key of Object.keys(processState.env)) Reflect.deleteProperty(processState.env, key)
|
||||
for (const key of Object.keys(processState.env)) {
|
||||
if (!STARTUP_ENVIRONMENT_NAMES.has(key.toUpperCase())) Reflect.deleteProperty(processState.env, key)
|
||||
}
|
||||
// Windows native process creation still needs SystemRoot in the OS environment.
|
||||
processState.env = Object.create(null) as NodeJS.ProcessEnv
|
||||
const boot = Promise.withResolvers<ProgramBootData>()
|
||||
const listeners: Array<(message: ReplyMessage) => void> = []
|
||||
let started = false
|
||||
|
||||
Reference in new issue
Block a user