@stixxert/pi-docker-sandbox 1.1.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -184,6 +184,11 @@ persistent name (e.g. a shared sandbox reused across restarts), pin
184
184
  - `DOCKER_SANDBOX_TEMPLATE=<name>` — use a pre-baked `sbx template` for
185
185
  auto-created sandboxes (avoids re-pulling common images every session;
186
186
  create with `sbx template save <name>` from a prepared sandbox).
187
+ - `DOCKER_SANDBOX_DEBUG=1` — emit the extension's lifecycle/GC diagnostics
188
+ (watchdog armed, teardown, startup sweep) to stderr. **Off by default**: the
189
+ extension runs inside the pi process, so stray console output would land on
190
+ the same terminal the TUI is drawing and corrupt the chat. Turn it on when
191
+ running `pi -p`, in a plain shell, or when diagnosing lifecycle issues.
187
192
 
188
193
  ## Ports (verified rules)
189
194
 
package/index.ts CHANGED
@@ -124,9 +124,9 @@ async function teardownSandbox(reason: string): Promise<void> {
124
124
  ].join("\n");
125
125
  const child = spawn("/bin/sh", ["-c", script], { detached: true, stdio: "ignore", env: scrubbedEnv() });
126
126
  child.unref();
127
- console.error(`[docker-sandbox] session ${reason}: ${action} sandbox "${name}" (detached, retrying)`);
127
+ note(`session ${reason}: ${action} sandbox "${name}" (detached, retrying)`);
128
128
  } catch (e) {
129
- console.error(`[docker-sandbox] session ${reason}: teardown of "${name}" failed: ${(e as Error).message}`);
129
+ note(`session ${reason}: teardown of "${name}" failed: ${(e as Error).message}`);
130
130
  }
131
131
  }
132
132
 
@@ -141,6 +141,22 @@ function findSbxCli(): string {
141
141
  return "sbx";
142
142
  }
143
143
 
144
+ /**
145
+ * Diagnostics are OFF by default on purpose: the extension runs inside the pi
146
+ * process, so a raw console write lands on the terminal the TUI is drawing and
147
+ * corrupts the chat transcript. Set DOCKER_SANDBOX_DEBUG=1 (or SBX_PI_DEBUG=1 /
148
+ * SBX_DEBUG=1) to get the lifecycle/GC lines on stderr — useful in `pi -p`, a
149
+ * plain shell or when diagnosing, harmless in the TUI because it is opt-in.
150
+ */
151
+ function debugEnabled(): boolean {
152
+ return /^(1|true|yes|on)$/i.test((env.DOCKER_SANDBOX_DEBUG ?? env.SBX_PI_DEBUG ?? env.SBX_DEBUG ?? "").trim());
153
+ }
154
+
155
+ /** Diagnostic line — silent unless debug logging is enabled (see debugEnabled). */
156
+ function note(message: string): void {
157
+ if (debugEnabled()) console.error(`[docker-sandbox] ${message}`);
158
+ }
159
+
144
160
  /**
145
161
  * Non-secret vars always forwarded to children (the sbx CLI and shells need
146
162
  * them to function; they are not credentials).
@@ -1486,9 +1502,9 @@ function spawnWatchdog(): void {
1486
1502
  try {
1487
1503
  const child = spawn("/bin/sh", ["-c", script], { detached: true, stdio: "ignore", env: scrubbedEnv() });
1488
1504
  child.unref();
1489
- console.error(`[docker-sandbox] watchdog armed for sandbox "${name}" (pid ${pid}, teardown=${mode}, keepalive=${keep})`);
1505
+ note(`watchdog armed for sandbox "${name}" (pid ${pid}, teardown=${mode}, keepalive=${keep})`);
1490
1506
  } catch (e) {
1491
- console.error(`[docker-sandbox] failed to arm watchdog: ${(e as Error).message}`);
1507
+ note(`failed to arm watchdog: ${(e as Error).message}`);
1492
1508
  }
1493
1509
  }
1494
1510
 
@@ -1670,8 +1686,8 @@ async function armSessionLifecycle(): Promise<void> {
1670
1686
  // sandboxes from crashed sessions, and session start must not wait on
1671
1687
  // `sbx ls` (and any sandboxd round trip) to get there.
1672
1688
  void gcSweep(raw)
1673
- .then((summary) => console.error(`[docker-sandbox] ${summary}`))
1674
- .catch((e) => console.error(`[docker-sandbox] gc at startup failed: ${(e as Error).message}`));
1689
+ .then((summary) => note(summary))
1690
+ .catch((e) => note(`gc at startup failed: ${(e as Error).message}`));
1675
1691
  }
1676
1692
 
1677
1693
  export default function (pi: ExtensionAPI) {
@@ -1973,4 +1989,5 @@ export {
1973
1989
  ensureSandbox,
1974
1990
  teardownSandbox,
1975
1991
  armSessionLifecycle,
1992
+ debugEnabled,
1976
1993
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stixxert/pi-docker-sandbox",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "pi extension: a private docker sandbox (sbx microVM with its own daemon) as the agent's deploy target — the host's docker is never exposed.",
5
5
  "license": "Apache-2.0",
6
6
  "publishConfig": {
package/sandbox/e2e.mjs CHANGED
@@ -375,6 +375,7 @@ try {
375
375
  process.env.DOCKER_SANDBOX_KEEPALIVE = "1";
376
376
  process.env.DOCKER_SANDBOX_TEARDOWN = "none"; // no stray teardown attempt
377
377
  process.env.DOCKER_SANDBOX_GC_HOURS = "0"; // skip the startup sweep
378
+ process.env.DOCKER_SANDBOX_DEBUG = "1"; // lifecycle notes are debug-gated (silent in the TUI by default)
378
379
  const { armSessionLifecycle } = await loadTs("index.ts");
379
380
  const lifecycleLog = [];
380
381
  const realError = console.error;
@@ -389,6 +390,7 @@ try {
389
390
  );
390
391
  delete process.env.DOCKER_SANDBOX_TEARDOWN;
391
392
  delete process.env.DOCKER_SANDBOX_GC_HOURS;
393
+ delete process.env.DOCKER_SANDBOX_DEBUG;
392
394
 
393
395
  /* --- lightweight template handshake -------------------------------- */
394
396
  console.log("\nlightweight template handshake");
package/sandbox/index.ts CHANGED
@@ -40,7 +40,7 @@ import {
40
40
  createReadToolDefinition,
41
41
  createWriteToolDefinition,
42
42
  } from "@earendil-works/pi-coding-agent";
43
- import { armSessionLifecycle, envAllowlist, teardownSandbox } from "../index.ts";
43
+ import { armSessionLifecycle, debugEnabled, envAllowlist, teardownSandbox } from "../index.ts";
44
44
  import {
45
45
  createBashOps,
46
46
  createEditOps,
@@ -157,7 +157,10 @@ export default function (pi: ExtensionAPI) {
157
157
  void ensureTransport(ctx)
158
158
  .then((active) => (active?.kind === "sbx" ? armSessionLifecycle() : undefined))
159
159
  .catch((err) => {
160
- console.error(`[sbx] session start failed: ${err instanceof Error ? err.message : String(err)}`);
160
+ // Raw console writes land on the terminal the TUI is drawing, so cap
161
+ // the failure note behind the debug flag — the backend degrades to
162
+ // local tools either way (the `sbx` command reports live status).
163
+ if (debugEnabled()) console.error(`[sbx] session start failed: ${err instanceof Error ? err.message : String(err)}`);
161
164
  });
162
165
  });
163
166