Repository navigation
scope client env to sessions so herdr extensions see the right pane #303
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
e2d229c
8349390
7373f99
33c30df
289ff9e
637a0a6
7b577bc
c924141
423de56
3a2b2a2
a39171b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
|
macroscopeapp[bot] marked this conversation as resolved.
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| import { DAEMON_CLIENT_ENV_KEYS } from "./daemon-protocol.js"; | ||
|
|
||
| /** Re-filter client-sent env to the allowlist; the socket peer is untrusted. */ | ||
| export function filterClientEnv(env?: Record<string, string>): Record<string, string> | undefined { | ||
| if (!env) { | ||
| return undefined; | ||
| } | ||
| const filtered: Record<string, string> = {}; | ||
| for (const key of DAEMON_CLIENT_ENV_KEYS) { | ||
| if (env[key] !== undefined) { | ||
| filtered[key] = env[key]; | ||
| } | ||
| } | ||
| return Object.keys(filtered).length > 0 ? filtered : undefined; | ||
| } | ||
|
|
||
| // Serializes env windows so overlapping creates can't cross-restore each | ||
| // other's values. Only env-carrying operations queue here. | ||
| let envWindow: Promise<unknown> = Promise.resolve(); | ||
|
|
||
| /** | ||
| * Run fn with the client's env applied to process.env, restoring afterwards. | ||
| * Extensions capture vars like HERDR_PANE_ID synchronously at module load, so | ||
| * they must be in process.env while the session loads its extensions; after | ||
| * this window the session's exec env covers subprocess reads. | ||
| */ | ||
| export async function withClientEnv<T>(env: Record<string, string> | undefined, fn: () => Promise<T>): Promise<T> { | ||
| if (!env) { | ||
| return fn(); | ||
| } | ||
| const run = envWindow.then(async () => { | ||
| const previous = new Map<string, string | undefined>(); | ||
| for (const [key, value] of Object.entries(env)) { | ||
| previous.set(key, process.env[key]); | ||
| process.env[key] = value; | ||
| } | ||
|
macroscopeapp[bot] marked this conversation as resolved.
cursor[bot] marked this conversation as resolved.
|
||
| try { | ||
| return await fn(); | ||
| } finally { | ||
| for (const [key, value] of previous) { | ||
| if (value === undefined) { | ||
| delete process.env[key]; | ||
| } else { | ||
| process.env[key] = value; | ||
| } | ||
| } | ||
| } | ||
| }); | ||
| envWindow = run.catch(() => undefined); | ||
| return run; | ||
| } | ||
|
macroscopeapp[bot] marked this conversation as resolved.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 Medium
The 🚀 Reply "fix it for me" or copy this AI Prompt for your agent: |
Uh oh!
There was an error while loading. Please reload this page.