From 06e90a5bac98e115997d5e89e6b11e4b7aa73662 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Kova=C4=BE?= Date: Sun, 14 Jun 2026 09:15:46 +0200 Subject: [PATCH 1/2] feat(cli): --debug-egress opt-in surfaces L7 egress headers via openlock logs --- src/cli/sandbox.ts | 2 ++ src/sandbox/container.test.ts | 12 ++++++++++++ src/sandbox/container.ts | 4 ++++ src/sandbox/session.ts | 16 +++++++++++++++- 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/cli/sandbox.ts b/src/cli/sandbox.ts index 68d841c..377afad 100644 --- a/src/cli/sandbox.ts +++ b/src/cli/sandbox.ts @@ -8,6 +8,7 @@ export const flagSchema = { provider: { type: "string" }, branch: { type: "string", short: "b" }, "no-attach": { type: "boolean" }, + "debug-egress": { type: "boolean" }, help: { type: "boolean", short: "h" }, } as const satisfies ParseArgsOptionsConfig; @@ -31,6 +32,7 @@ export function sandboxCmd(args: string[]): void { provider: values.provider, branch: values.branch, noAttach: values["no-attach"] === true, + debugEgress: values["debug-egress"] === true, }), ); } diff --git a/src/sandbox/container.test.ts b/src/sandbox/container.test.ts index 391ae56..039c000 100644 --- a/src/sandbox/container.test.ts +++ b/src/sandbox/container.test.ts @@ -394,6 +394,18 @@ describe("buildOpenshellCreateArgv", () => { expect(argv).not.toContain("--volume"); }); + it("appends --log-level debug when debugEgress is set", () => { + const argv = buildOpenshellCreateArgv({ ...base, debugEgress: true }); + const idx = argv.indexOf("--log-level"); + expect(idx).toBeGreaterThan(-1); + expect(argv[idx + 1]).toBe("debug"); + }); + + it("omits --log-level by default", () => { + const argv = buildOpenshellCreateArgv(base); + expect(argv).not.toContain("--log-level"); + }); + it("passes providerId verbatim as --provider", () => { const argv = buildOpenshellCreateArgv({ ...base, providerId: "openrouter" }); const idx = argv.indexOf("--provider"); diff --git a/src/sandbox/container.ts b/src/sandbox/container.ts index cdb00e9..ce990db 100644 --- a/src/sandbox/container.ts +++ b/src/sandbox/container.ts @@ -130,6 +130,9 @@ export interface OpenshellCreateArgs { providerId: ProviderId; command: string[]; volumeArgs?: readonly string[]; + /** Opt-in: run the in-container supervisor at debug so the L7 egress + * request/response header lines surface via `openlock logs`. Off by default. */ + debugEgress?: boolean; } export interface OpenshellHandle { @@ -153,6 +156,7 @@ export function buildOpenshellCreateArgv(args: OpenshellCreateArgs): string[] { args.policy, "--provider", args.providerId, + ...(args.debugEgress === true ? ["--log-level", "debug"] : []), "--no-tty", ...(args.volumeArgs ?? []), "--", diff --git a/src/sandbox/session.ts b/src/sandbox/session.ts index 384aedd..6b731e6 100644 --- a/src/sandbox/session.ts +++ b/src/sandbox/session.ts @@ -73,6 +73,9 @@ export interface SandboxOpts { /** Detached create: create/resolve the session but do NOT attach the harness, * so a scripted/CI caller can drive it via `openlock exec`. */ noAttach?: boolean; + /** Opt-in supervisor debug for L7 egress header capture (see container.ts). + * Applies only at container creation; ignored when reattaching an existing one. */ + debugEgress?: boolean; } async function buildSandboxImage(openlockFolderPath: string): Promise { @@ -144,6 +147,7 @@ async function createSession( harness: Harness, providerId: ProviderId, branch: string | undefined, + debugEgress: boolean, ): Promise { const { policy, mounts } = resolved; @@ -232,6 +236,7 @@ async function createSession( providerId, command: ["/bin/bash", "-c", setupCmd], volumeArgs: bindMountArgs(mounts), + debugEgress, }); // Don't await handle.exited — it blocks until the container stops. @@ -556,11 +561,19 @@ async function resolveOrCreateSession( harness: Harness, providerId: ProviderId, branch: string | undefined, + debugEgress: boolean, ): Promise { const matches = findSessionsByPath(sessionsDir(), projectPath); exitOnAmbiguousSessions(projectPath, matches); if (matches.length === 0) { - const created = await createSession(projectPath, resolved, harness, providerId, branch); + const created = await createSession( + projectPath, + resolved, + harness, + providerId, + branch, + debugEgress, + ); updateSessionMeta(sessionsDir(), created.id, { attachedPid: process.pid, lastAttachedAt: new Date().toISOString(), @@ -696,6 +709,7 @@ export async function runSandbox(opts: SandboxOpts): Promise { harness, providerId, opts.branch, + opts.debugEgress === true, ); if (opts.noAttach === true) { From 6fec97fa5d18588fcac5a9b2c13e733a2c868e3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Kova=C4=BE?= Date: Wed, 17 Jun 2026 06:17:26 +0200 Subject: [PATCH 2/2] chore(sandbox): bump OPENSHELL_FORK_TAG to v0.6.6 (L7 egress debug logging) --- src/sandbox/fork-binaries.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sandbox/fork-binaries.ts b/src/sandbox/fork-binaries.ts index 7dfdfad..192c5a9 100644 --- a/src/sandbox/fork-binaries.ts +++ b/src/sandbox/fork-binaries.ts @@ -7,7 +7,7 @@ import { forkDir } from "../paths"; // release ships, alongside any matching changes in openlock that depend // on fork-side behavior. const OPENSHELL_FORK_REPO = "vessux/OpenShell"; -export const OPENSHELL_FORK_TAG = "v0.6.5"; +export const OPENSHELL_FORK_TAG = "v0.6.6"; type ForkBinary = "openshell-gateway" | "openshell-sandbox" | "openshell";