fix(subprocess): consumers with one mixed env map split DSH_* onto the managed channel
Codex review of the acp-only fix found lsp-local carries the identical defect: its server config's unrestricted env merges into the connection's ordinary spawn channel, so a configured DSH_* fact crashed the spawn with the reserved-namespace rejection. The partition now lives on the seam as splitEnvChannels() beside the scrub it complements; the ACP run and the LSP connection both use it, and each proves child delivery end-to-end (MOCK_ECHO_ENV / LSP_FAKE_ECHO_ENV fixture knobs). Seam + consumer README rows updated (en+zh, re-recorded). bash-local is already two-channel; mcp/pty/sdk bypass the seam and only share the scrub.
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
|
||||
import { Context, Service } from 'cordis'
|
||||
import { DSH_ENV_PREFIX } from './types.ts'
|
||||
import type { DshEnvironment, DshEnvironmentKey } from './types.ts'
|
||||
import type { SubprocessHandle, SubprocessSpawnSpec } from './types.ts'
|
||||
|
||||
export { DSH_ENV_PREFIX } from './types.ts'
|
||||
@@ -61,6 +62,27 @@ export function scrubbedParentEnv(): Record<string, string> {
|
||||
return env
|
||||
}
|
||||
|
||||
/**
|
||||
* Partition one mixed explicit-env map onto the spec's two channels: `DSH_*`
|
||||
* names are deployment-owned facts for the child and take the managed
|
||||
* {@link SubprocessSpawnSpec.dshEnv} channel (the ordinary channel rejects the
|
||||
* reserved namespace), everything else stays ordinary `env`. For consumers
|
||||
* whose configs expose a single env map (lsp-local servers, the ACP backend)
|
||||
* rather than two channel-shaped fields.
|
||||
* @param env - explicit entries from a consumer's config, both namespaces mixed.
|
||||
* @returns the two spec channels, each safe for its validator.
|
||||
*/
|
||||
export function splitEnvChannels(env: Readonly<Record<string, string>>): { env: Record<string, string>; dshEnv: DshEnvironment } {
|
||||
const ordinary: Record<string, string> = {}
|
||||
const managed: Record<DshEnvironmentKey, string> = {}
|
||||
const isDshKey = (key: string): key is DshEnvironmentKey => key.startsWith(DSH_ENV_PREFIX)
|
||||
for (const [key, value] of Object.entries(env)) {
|
||||
if (isDshKey(key)) managed[key] = value
|
||||
else ordinary[key] = value
|
||||
}
|
||||
return { env: ordinary, dshEnv: managed }
|
||||
}
|
||||
|
||||
declare module 'cordis' {
|
||||
interface Context {
|
||||
subprocess: SubprocessService
|
||||
|
||||
Reference in New Issue
Block a user