@bike4mind/cli 0.2.29-feat-cli-sandbox.18842 → 0.2.29-feat-cli-sandbox.18843

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.
@@ -2,11 +2,10 @@
2
2
  import {
3
3
  expandPath,
4
4
  isBinaryAvailable
5
- } from "./chunk-PRJKJWD6.js";
5
+ } from "./chunk-AVAD2PPK.js";
6
6
 
7
7
  // src/sandbox/runtime/BubblewrapRuntime.ts
8
8
  import os from "os";
9
- import { existsSync } from "fs";
10
9
  var SYSTEM_RO_BINDS = ["/usr", "/bin", "/lib", "/lib64", "/sbin", "/etc"];
11
10
  var SPECIAL_MOUNTS = {
12
11
  dev: "/dev",
@@ -27,9 +26,7 @@ var BubblewrapRuntime = class {
27
26
  const expandedAllowed = filesystemConfig.allowedReadPaths.map(expandPath);
28
27
  const args = [];
29
28
  for (const sysPath of SYSTEM_RO_BINDS) {
30
- if (existsSync(sysPath)) {
31
- args.push("--ro-bind", sysPath, sysPath);
32
- }
29
+ args.push("--ro-bind-try", sysPath, sysPath);
33
30
  }
34
31
  args.push("--dev", SPECIAL_MOUNTS.dev);
35
32
  args.push("--proc", SPECIAL_MOUNTS.proc);
@@ -38,7 +35,7 @@ var BubblewrapRuntime = class {
38
35
  const homeDir = os.homedir();
39
36
  args.push("--ro-bind", homeDir, homeDir);
40
37
  for (const allowedPath of expandedAllowed) {
41
- if (!allowedPath.startsWith(homeDir) && existsSync(allowedPath)) {
38
+ if (!allowedPath.startsWith(homeDir)) {
42
39
  args.push("--ro-bind-try", allowedPath, allowedPath);
43
40
  }
44
41
  }
@@ -48,6 +45,9 @@ var BubblewrapRuntime = class {
48
45
  args.push("--unshare-all");
49
46
  args.push("--share-net");
50
47
  args.push("--die-with-parent");
48
+ if (options.seccompProfile) {
49
+ args.push("--seccomp", options.seccompProfile);
50
+ }
51
51
  args.push("--chdir", cwd);
52
52
  args.push("bash", "-c", command);
53
53
  const commandString = ["bwrap", ...args.map(shellEscape)].join(" ");
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  DEFAULT_SANDBOX_CONFIG
4
- } from "./chunk-XPSG72HV.js";
4
+ } from "./chunk-W4TCH4ZT.js";
5
5
 
6
6
  // src/sandbox/SandboxOrchestrator.ts
7
7
  var SandboxOrchestrator = class {
@@ -24,6 +24,12 @@ var SandboxOrchestrator = class {
24
24
  }
25
25
  const baseCommand = this.getBaseCommand(command);
26
26
  if (this.isExcludedCommand(baseCommand)) {
27
+ if (!this.config.allowUnsandboxedCommands) {
28
+ return {
29
+ type: "blocked",
30
+ reason: `Command '${baseCommand}' is excluded from sandboxing and unsandboxed commands are not allowed`
31
+ };
32
+ }
27
33
  return {
28
34
  type: "unsandboxed",
29
35
  requiresPermission: true,
@@ -40,7 +46,10 @@ var SandboxOrchestrator = class {
40
46
  const wrappedCommand = this.runtime.wrapCommand({
41
47
  command,
42
48
  cwd,
43
- filesystemConfig: this.config.filesystem
49
+ filesystemConfig: this.config.filesystem,
50
+ ...this.runtime.platform === "linux" && this.config.platform.linux.seccompProfile && {
51
+ seccompProfile: this.config.platform.linux.seccompProfile
52
+ }
44
53
  });
45
54
  return { type: "sandbox", wrappedCommand };
46
55
  }
@@ -4,7 +4,7 @@ import {
4
4
  detectPlatform,
5
5
  expandPath,
6
6
  isBinaryAvailable
7
- } from "./chunk-PRJKJWD6.js";
7
+ } from "./chunk-AVAD2PPK.js";
8
8
  export {
9
9
  createSandboxRuntime,
10
10
  detectPlatform,
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  expandPath,
4
4
  isBinaryAvailable
5
- } from "./chunk-PRJKJWD6.js";
5
+ } from "./chunk-AVAD2PPK.js";
6
6
 
7
7
  // src/sandbox/runtime/SeatbeltRuntime.ts
8
8
  import { writeFileSync, mkdtempSync } from "fs";
@@ -70,18 +70,22 @@ var SeatbeltRuntime = class {
70
70
  return lines.join("\n");
71
71
  }
72
72
  wrapCommand(options) {
73
- const profile = this.generateProfile(options);
74
- const tmpDir = mkdtempSync(path.join(os.tmpdir(), "b4m-sandbox-"));
75
- const profilePath = path.join(tmpDir, "sandbox.sb");
76
- writeFileSync(profilePath, profile, "utf-8");
77
- const args = ["-f", profilePath, "bash", "-c", options.command];
78
- return {
79
- executable: "sandbox-exec",
80
- args,
81
- env: options.env ?? {},
82
- commandString: `sandbox-exec -f ${profilePath} bash -c ${shellEscape(options.command)}`,
83
- cleanupPaths: [profilePath, tmpDir]
84
- };
73
+ try {
74
+ const profile = this.generateProfile(options);
75
+ const tmpDir = mkdtempSync(path.join(os.tmpdir(), "b4m-sandbox-"));
76
+ const profilePath = path.join(tmpDir, "sandbox.sb");
77
+ writeFileSync(profilePath, profile, "utf-8");
78
+ const args = ["-f", profilePath, "bash", "-c", options.command];
79
+ return {
80
+ executable: "sandbox-exec",
81
+ args,
82
+ env: options.env ?? {},
83
+ commandString: `sandbox-exec -f ${profilePath} bash -c ${shellEscape(options.command)}`,
84
+ cleanupPaths: [profilePath, tmpDir]
85
+ };
86
+ } catch (err) {
87
+ throw new Error(`Failed to create sandbox profile: ${err instanceof Error ? err.message : String(err)}`);
88
+ }
85
89
  }
86
90
  };
87
91
  function shellEscape(str) {
@@ -24,12 +24,12 @@ async function createSandboxRuntime() {
24
24
  const platform = detectPlatform();
25
25
  if (!platform) return null;
26
26
  if (platform === "darwin") {
27
- const { SeatbeltRuntime } = await import("./SeatbeltRuntime-DZMEIRPM.js");
27
+ const { SeatbeltRuntime } = await import("./SeatbeltRuntime-SL7HVS3J.js");
28
28
  const runtime = new SeatbeltRuntime();
29
29
  return runtime.isAvailable() ? runtime : null;
30
30
  }
31
31
  if (platform === "linux") {
32
- const { BubblewrapRuntime } = await import("./BubblewrapRuntime-EJM4QF7U.js");
32
+ const { BubblewrapRuntime } = await import("./BubblewrapRuntime-HXTR3NQG.js");
33
33
  const runtime = new BubblewrapRuntime();
34
34
  return runtime.isAvailable() ? runtime : null;
35
35
  }
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  DEFAULT_SANDBOX_CONFIG
4
- } from "./chunk-XPSG72HV.js";
4
+ } from "./chunk-W4TCH4ZT.js";
5
5
 
6
6
  // src/utils/Logger.ts
7
7
  import fs from "fs/promises";
@@ -285,6 +285,7 @@ var SandboxConfigSchema = z.object({
285
285
  mode: z.enum(["disabled", "auto-allow", "permissions"]).default("disabled"),
286
286
  filesystem: SandboxFilesystemSchema.default(DEFAULT_SANDBOX_CONFIG.filesystem),
287
287
  excludedCommands: z.array(z.string()).default(DEFAULT_SANDBOX_CONFIG.excludedCommands),
288
+ allowUnsandboxedCommands: z.boolean().default(true),
288
289
  platform: SandboxPlatformSchema.default(DEFAULT_SANDBOX_CONFIG.platform)
289
290
  });
290
291
  var PartialSandboxConfigSchema = z.object({
@@ -296,6 +297,7 @@ var PartialSandboxConfigSchema = z.object({
296
297
  writeOnlyToWorkingDir: z.boolean().optional()
297
298
  }).optional(),
298
299
  excludedCommands: z.array(z.string()).optional(),
300
+ allowUnsandboxedCommands: z.boolean().optional(),
299
301
  platform: SandboxPlatformSchema.optional()
300
302
  }).optional();
301
303
  var AuthTokensSchema = z.object({
@@ -546,6 +548,7 @@ function mergeSandboxConfig(base, override) {
546
548
  ...override.filesystem ?? {}
547
549
  },
548
550
  excludedCommands: override.excludedCommands ?? resolved.excludedCommands,
551
+ allowUnsandboxedCommands: override.allowUnsandboxedCommands ?? resolved.allowUnsandboxedCommands,
549
552
  platform: override.platform ?? resolved.platform
550
553
  };
551
554
  }
@@ -10,6 +10,7 @@ var DEFAULT_SANDBOX_CONFIG = {
10
10
  deniedPaths: ["$HOME/.ssh", "$HOME/.aws", "$HOME/.gnupg", "$HOME/.env", "/etc/shadow", "/etc/passwd"]
11
11
  },
12
12
  excludedCommands: ["docker", "watchman", "podman"],
13
+ allowUnsandboxedCommands: true,
13
14
  platform: {
14
15
  linux: {
15
16
  runtime: "bubblewrap"
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ConfigStore
4
- } from "../chunk-JJL2EFHA.js";
5
- import "../chunk-XPSG72HV.js";
4
+ } from "../chunk-JWEG53NG.js";
5
+ import "../chunk-W4TCH4ZT.js";
6
6
 
7
7
  // src/commands/mcpCommand.ts
8
8
  async function handleMcpCommand(subcommand, argv) {
package/dist/index.js CHANGED
@@ -10,12 +10,12 @@ import {
10
10
  import {
11
11
  ConfigStore,
12
12
  logger
13
- } from "./chunk-JJL2EFHA.js";
13
+ } from "./chunk-JWEG53NG.js";
14
14
  import {
15
15
  selectActiveBackgroundAgents,
16
16
  useCliStore
17
17
  } from "./chunk-TVW4ZESU.js";
18
- import "./chunk-XPSG72HV.js";
18
+ import "./chunk-W4TCH4ZT.js";
19
19
  import "./chunk-PKKJ44C5.js";
20
20
  import {
21
21
  BFLImageService,
@@ -11759,15 +11759,33 @@ function wrapToolWithPermission(tool, permissionManager, showPermissionPrompt, a
11759
11759
  }
11760
11760
  const effectiveArgs = isSandboxed ? sandboxedArgs : args;
11761
11761
  if (!permissionManager.needsPermission(toolName, { isSandboxed })) {
11762
- const result2 = await executeTool(toolName, effectiveArgs, apiClient, originalFn);
11762
+ let result2 = await executeTool(toolName, effectiveArgs, apiClient, originalFn);
11763
11763
  cleanupSandboxFiles(effectiveArgs?._sandboxCleanup);
11764
+ result2 = await retrySandboxFailure(
11765
+ isSandboxed,
11766
+ result2,
11767
+ toolName,
11768
+ args,
11769
+ apiClient,
11770
+ originalFn,
11771
+ showPermissionPrompt
11772
+ );
11764
11773
  agentContext.observationQueue.push({ toolName, result: result2 });
11765
11774
  return result2;
11766
11775
  }
11767
11776
  const { useCliStore: useCliStore2 } = await import("./store-FU6NDC2W.js");
11768
11777
  if (useCliStore2.getState().autoAcceptEdits) {
11769
- const result2 = await executeTool(toolName, effectiveArgs, apiClient, originalFn);
11778
+ let result2 = await executeTool(toolName, effectiveArgs, apiClient, originalFn);
11770
11779
  cleanupSandboxFiles(effectiveArgs?._sandboxCleanup);
11780
+ result2 = await retrySandboxFailure(
11781
+ isSandboxed,
11782
+ result2,
11783
+ toolName,
11784
+ args,
11785
+ apiClient,
11786
+ originalFn,
11787
+ showPermissionPrompt
11788
+ );
11771
11789
  agentContext.observationQueue.push({ toolName, result: result2 });
11772
11790
  return result2;
11773
11791
  }
@@ -11830,13 +11848,41 @@ function wrapToolWithPermission(tool, permissionManager, showPermissionPrompt, a
11830
11848
  }
11831
11849
  }
11832
11850
  }
11833
- const result = await executeTool(toolName, effectiveArgs, apiClient, originalFn);
11851
+ let result = await executeTool(toolName, effectiveArgs, apiClient, originalFn);
11834
11852
  cleanupSandboxFiles(effectiveArgs?._sandboxCleanup);
11853
+ result = await retrySandboxFailure(
11854
+ isSandboxed,
11855
+ result,
11856
+ toolName,
11857
+ args,
11858
+ apiClient,
11859
+ originalFn,
11860
+ showPermissionPrompt
11861
+ );
11835
11862
  agentContext.observationQueue.push({ toolName, result });
11836
11863
  return result;
11837
11864
  }
11838
11865
  };
11839
11866
  }
11867
+ function isSandboxFailure(isSandboxed, result) {
11868
+ if (!isSandboxed) return false;
11869
+ return result.includes("sandbox-exec:") || result.includes("bwrap:") || result.includes("Operation not permitted");
11870
+ }
11871
+ async function retrySandboxFailure(isSandboxed, result, toolName, originalArgs, apiClient, originalFn, showPermissionPrompt) {
11872
+ if (!isSandboxFailure(isSandboxed, result)) return result;
11873
+ const errorSnippet = result.slice(0, 200);
11874
+ const retryResponse = await showPermissionPrompt(
11875
+ toolName,
11876
+ originalArgs,
11877
+ `Sandbox execution failed. Retry without sandbox?
11878
+
11879
+ Error: ${errorSnippet}`
11880
+ );
11881
+ if (retryResponse.action !== "deny") {
11882
+ return executeTool(toolName, originalArgs, apiClient, originalFn);
11883
+ }
11884
+ return result;
11885
+ }
11840
11886
  function cleanupSandboxFiles(paths) {
11841
11887
  if (!paths || paths.length === 0) return;
11842
11888
  for (const p of paths) {
@@ -13643,7 +13689,7 @@ import { isAxiosError as isAxiosError2 } from "axios";
13643
13689
  // package.json
13644
13690
  var package_default = {
13645
13691
  name: "@bike4mind/cli",
13646
- version: "0.2.29-feat-cli-sandbox.18842+fc55c56fc",
13692
+ version: "0.2.29-feat-cli-sandbox.18843+467f137bc",
13647
13693
  type: "module",
13648
13694
  description: "Interactive CLI tool for Bike4Mind with ReAct agents",
13649
13695
  license: "UNLICENSED",
@@ -13753,10 +13799,10 @@ var package_default = {
13753
13799
  },
13754
13800
  devDependencies: {
13755
13801
  "@bike4mind/agents": "0.1.0",
13756
- "@bike4mind/common": "2.50.1-feat-cli-sandbox.18842+fc55c56fc",
13757
- "@bike4mind/mcp": "1.29.1-feat-cli-sandbox.18842+fc55c56fc",
13758
- "@bike4mind/services": "2.48.1-feat-cli-sandbox.18842+fc55c56fc",
13759
- "@bike4mind/utils": "2.5.1-feat-cli-sandbox.18842+fc55c56fc",
13802
+ "@bike4mind/common": "2.50.1-feat-cli-sandbox.18843+467f137bc",
13803
+ "@bike4mind/mcp": "1.29.1-feat-cli-sandbox.18843+467f137bc",
13804
+ "@bike4mind/services": "2.48.1-feat-cli-sandbox.18843+467f137bc",
13805
+ "@bike4mind/utils": "2.5.1-feat-cli-sandbox.18843+467f137bc",
13760
13806
  "@types/better-sqlite3": "^7.6.13",
13761
13807
  "@types/diff": "^5.0.9",
13762
13808
  "@types/jsonwebtoken": "^9.0.4",
@@ -13773,7 +13819,7 @@ var package_default = {
13773
13819
  optionalDependencies: {
13774
13820
  "@vscode/ripgrep": "^1.17.0"
13775
13821
  },
13776
- gitHead: "fc55c56fc0acb53d861d98b5b5e902a3e38a4c37"
13822
+ gitHead: "467f137bcb738020d1665b78bc7d34de7d846df5"
13777
13823
  };
13778
13824
 
13779
13825
  // src/config/constants.ts
@@ -15779,9 +15825,9 @@ function CliApp() {
15779
15825
  config.tools.disabled || []
15780
15826
  // denied tools from project config
15781
15827
  );
15782
- const { createSandboxRuntime } = await import("./SandboxRuntimeAdapter-SRX3IM2Q.js");
15783
- const { SandboxOrchestrator } = await import("./SandboxOrchestrator-AEOHC2BL.js");
15784
- const { DEFAULT_SANDBOX_CONFIG } = await import("./types-2T7ALTCA.js");
15828
+ const { createSandboxRuntime } = await import("./SandboxRuntimeAdapter-5ZMU25Q3.js");
15829
+ const { SandboxOrchestrator } = await import("./SandboxOrchestrator-Z36SFJ7X.js");
15830
+ const { DEFAULT_SANDBOX_CONFIG } = await import("./types-SMQKWHQK.js");
15785
15831
  const sandboxRuntime = await createSandboxRuntime();
15786
15832
  const sandboxConfig = config.sandbox ?? DEFAULT_SANDBOX_CONFIG;
15787
15833
  const sandboxOrchestrator = new SandboxOrchestrator(sandboxConfig, sandboxRuntime);
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  DEFAULT_SANDBOX_CONFIG
4
- } from "./chunk-XPSG72HV.js";
4
+ } from "./chunk-W4TCH4ZT.js";
5
5
  export {
6
6
  DEFAULT_SANDBOX_CONFIG
7
7
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bike4mind/cli",
3
- "version": "0.2.29-feat-cli-sandbox.18842+fc55c56fc",
3
+ "version": "0.2.29-feat-cli-sandbox.18843+467f137bc",
4
4
  "type": "module",
5
5
  "description": "Interactive CLI tool for Bike4Mind with ReAct agents",
6
6
  "license": "UNLICENSED",
@@ -110,10 +110,10 @@
110
110
  },
111
111
  "devDependencies": {
112
112
  "@bike4mind/agents": "0.1.0",
113
- "@bike4mind/common": "2.50.1-feat-cli-sandbox.18842+fc55c56fc",
114
- "@bike4mind/mcp": "1.29.1-feat-cli-sandbox.18842+fc55c56fc",
115
- "@bike4mind/services": "2.48.1-feat-cli-sandbox.18842+fc55c56fc",
116
- "@bike4mind/utils": "2.5.1-feat-cli-sandbox.18842+fc55c56fc",
113
+ "@bike4mind/common": "2.50.1-feat-cli-sandbox.18843+467f137bc",
114
+ "@bike4mind/mcp": "1.29.1-feat-cli-sandbox.18843+467f137bc",
115
+ "@bike4mind/services": "2.48.1-feat-cli-sandbox.18843+467f137bc",
116
+ "@bike4mind/utils": "2.5.1-feat-cli-sandbox.18843+467f137bc",
117
117
  "@types/better-sqlite3": "^7.6.13",
118
118
  "@types/diff": "^5.0.9",
119
119
  "@types/jsonwebtoken": "^9.0.4",
@@ -130,5 +130,5 @@
130
130
  "optionalDependencies": {
131
131
  "@vscode/ripgrep": "^1.17.0"
132
132
  },
133
- "gitHead": "fc55c56fc0acb53d861d98b5b5e902a3e38a4c37"
133
+ "gitHead": "467f137bcb738020d1665b78bc7d34de7d846df5"
134
134
  }