@bike4mind/cli 0.2.64-worktree-refactor-extract-search-query-builders.21815 → 0.2.64
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/bin/bike4mind-cli.mjs +6 -6
- package/dist/BubblewrapRuntime-BHbtqvLx.mjs +72 -0
- package/dist/ConfigStore-CllM6jOf.mjs +8614 -0
- package/dist/ImageStore-DaKT_Ew8.mjs +202 -0
- package/dist/ProxyManager-Dl2nFk-A.mjs +259 -0
- package/dist/ProxyManager-kiOD1X8-.mjs +3 -0
- package/dist/SandboxOrchestrator-BEW3rqYi.mjs +159 -0
- package/dist/SandboxOrchestrator-CHZgSR3P.mjs +3 -0
- package/dist/SandboxRuntimeAdapter-C1B4t20N.mjs +57 -0
- package/dist/SandboxRuntimeAdapter-D7UAG13n.mjs +3 -0
- package/dist/SeatbeltRuntime-D4m0VOcD.mjs +116 -0
- package/dist/StderrViolationParser-D0afQ3-1.mjs +70 -0
- package/dist/ViolationLogStore-CZl35HcA.mjs +96 -0
- package/dist/bashExecute-BTkdqlSs-5foM20Lb.mjs +466 -0
- package/dist/commands/doctorCommand.mjs +101 -0
- package/dist/commands/headlessCommand.mjs +319 -0
- package/dist/commands/mcpCommand.mjs +218 -0
- package/dist/commands/updateCommand.mjs +40 -0
- package/dist/createFile-yQfh8uvk-I-yM5DxC.mjs +63 -0
- package/dist/deleteFile-DKHfnyny-G3b1Kj2T.mjs +66 -0
- package/dist/globFiles-D1en6joM-8jekiXdX.mjs +100 -0
- package/dist/grepSearch-aMamoBn_-DCJcY8JS.mjs +173 -0
- package/dist/index.mjs +6722 -0
- package/dist/pathValidation-Cgjh5WQO-DiCZTcq6.mjs +63 -0
- package/dist/store-Dw1nZX2Y.mjs +128 -0
- package/dist/store-nZExNOWX.mjs +3 -0
- package/dist/terminalSetup-rmr1P8KF.mjs +254 -0
- package/dist/tools-C6M5aW8W.mjs +20907 -0
- package/dist/treeSitterEngine-DCSXcm_3.mjs +309 -0
- package/dist/types-DBEjF9YS.mjs +59 -0
- package/dist/types-DK3P88Px.mjs +3 -0
- package/dist/updateChecker-Cu9dkHxV.mjs +120 -0
- package/package.json +10 -10
- package/dist/BubblewrapRuntime-PMIOLWKR.js +0 -71
- package/dist/HydrationEngine-YL2HWJ3V.js +0 -9
- package/dist/ImageStore-MMUOUPI2.js +0 -224
- package/dist/ProxyManager-HEB4TLVX.js +0 -7
- package/dist/SandboxOrchestrator-UIJ5GYBB.js +0 -8
- package/dist/SandboxRuntimeAdapter-FQ56MAB2.js +0 -13
- package/dist/SeatbeltRuntime-EE3TTLEP.js +0 -98
- package/dist/StderrViolationParser-7OYPM2DJ.js +0 -59
- package/dist/ViolationLogStore-RIIUVURH.js +0 -104
- package/dist/artifactExtractor-R7DIP2XO.js +0 -180
- package/dist/bashExecute-GLGLD3JD.js +0 -379
- package/dist/chunk-4BIBE3J7.js +0 -48
- package/dist/chunk-5LZS5CVJ.js +0 -161
- package/dist/chunk-BDQBOLYG.js +0 -120
- package/dist/chunk-BPFEGDC7.js +0 -192
- package/dist/chunk-EPIYC3LA.js +0 -13770
- package/dist/chunk-G4ZGEQFT.js +0 -250
- package/dist/chunk-GQGOWACU.js +0 -770
- package/dist/chunk-J6ZBI6TI.js +0 -1079
- package/dist/chunk-JW3JRHH7.js +0 -12433
- package/dist/chunk-KQAMBXAW.js +0 -163
- package/dist/chunk-KUVV2NAB.js +0 -19125
- package/dist/chunk-LTLJRF6I.js +0 -44
- package/dist/chunk-PFBYGCOW.js +0 -449
- package/dist/chunk-QWB6ZYY4.js +0 -48
- package/dist/chunk-SGPRXN4C.js +0 -245
- package/dist/chunk-UZUHPHZC.js +0 -95
- package/dist/chunk-WBE7SQUB.js +0 -241
- package/dist/chunk-Y4WOJJM3.js +0 -147
- package/dist/commands/doctorCommand.js +0 -87
- package/dist/commands/headlessCommand.js +0 -380
- package/dist/commands/mcpCommand.js +0 -203
- package/dist/commands/updateCommand.js +0 -42
- package/dist/create-C4VEEEYR.js +0 -12
- package/dist/createFile-6PSPLW6R.js +0 -71
- package/dist/deleteFile-AUSRLWIK.js +0 -73
- package/dist/formatConverter-5QEJDW24.js +0 -7
- package/dist/globFiles-TSRN64N2.js +0 -120
- package/dist/grepSearch-634XWZOJ.js +0 -216
- package/dist/index.js +0 -6779
- package/dist/llmMarkdownGenerator-Z6NB26TT.js +0 -371
- package/dist/markdownGenerator-SK2ZQQL4.js +0 -269
- package/dist/mementoService-N4IM6QAC.js +0 -12
- package/dist/notificationDeduplicator-HUC53NEW.js +0 -9
- package/dist/src-F4KZCAA2.js +0 -319
- package/dist/src-ISX322I7.js +0 -1101
- package/dist/store-CAB6BV3P.js +0 -11
- package/dist/subtractCredits-D4KEM6VU.js +0 -12
- package/dist/terminalSetup-C5FHMLC3.js +0 -214
- package/dist/treeSitterEngine-4SGFQDY3.js +0 -330
- package/dist/types-KB5NP6T4.js +0 -7
- package/dist/utils-JCHWDM4Z.js +0 -31
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { i as isBinaryAvailable, r as expandPath } from "./SandboxRuntimeAdapter-C1B4t20N.mjs";
|
|
3
|
+
import { mkdtempSync, writeFileSync } from "fs";
|
|
4
|
+
import os from "os";
|
|
5
|
+
import path from "path";
|
|
6
|
+
//#region src/sandbox/runtime/SeatbeltRuntime.ts
|
|
7
|
+
/**
|
|
8
|
+
* macOS Seatbelt (sandbox-exec) runtime implementation.
|
|
9
|
+
*
|
|
10
|
+
* Generates dynamic Seatbelt profiles to restrict filesystem access.
|
|
11
|
+
* Uses Apple's Sandbox framework via the `sandbox-exec` CLI tool.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Escape a path for use in a Seatbelt profile.
|
|
15
|
+
*
|
|
16
|
+
* Seatbelt profiles use S-expression (Scheme-like) syntax where paths are
|
|
17
|
+
* enclosed in quoted strings. Only two characters need escaping:
|
|
18
|
+
* - Backslash (\): Must be doubled to prevent interpreting the next char as special.
|
|
19
|
+
* - Double quote ("): Must be escaped to prevent closing the string prematurely.
|
|
20
|
+
*
|
|
21
|
+
* Scheme syntax characters like (, ), and ; do NOT need escaping because they
|
|
22
|
+
* are only special at the expression parsing level. Inside a quoted string,
|
|
23
|
+
* they are treated as literal characters and cannot inject directives.
|
|
24
|
+
*/
|
|
25
|
+
function escapeSeatbeltPath(p) {
|
|
26
|
+
return p.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
|
|
27
|
+
}
|
|
28
|
+
var SeatbeltRuntime = class {
|
|
29
|
+
constructor() {
|
|
30
|
+
this.platform = "darwin";
|
|
31
|
+
this.name = "seatbelt";
|
|
32
|
+
}
|
|
33
|
+
isAvailable() {
|
|
34
|
+
return isBinaryAvailable("sandbox-exec");
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Generate a Seatbelt profile string from the filesystem config.
|
|
38
|
+
*
|
|
39
|
+
* Strategy:
|
|
40
|
+
* - Start with (allow default) to permit most operations
|
|
41
|
+
* - Deny all file writes globally
|
|
42
|
+
* - Allow file writes only to the working directory
|
|
43
|
+
* - Deny all access to explicitly denied paths
|
|
44
|
+
* - Allow read access to explicitly allowed paths
|
|
45
|
+
*/
|
|
46
|
+
generateProfile(options) {
|
|
47
|
+
const { cwd, filesystemConfig } = options;
|
|
48
|
+
const expandedDenied = filesystemConfig.deniedPaths.map(expandPath);
|
|
49
|
+
const expandedAllowed = filesystemConfig.allowedReadPaths.map(expandPath);
|
|
50
|
+
const lines = [
|
|
51
|
+
"(version 1)",
|
|
52
|
+
"",
|
|
53
|
+
"; Start with permissive defaults (process exec, network, sysctl, etc.)",
|
|
54
|
+
"(allow default)",
|
|
55
|
+
""
|
|
56
|
+
];
|
|
57
|
+
if (filesystemConfig.writeOnlyToWorkingDir) {
|
|
58
|
+
lines.push("; Deny all file writes globally");
|
|
59
|
+
lines.push("(deny file-write*)");
|
|
60
|
+
lines.push("");
|
|
61
|
+
lines.push("; Allow writes to working directory");
|
|
62
|
+
lines.push(`(allow file-write* (subpath "${escapeSeatbeltPath(cwd)}"))`);
|
|
63
|
+
lines.push("");
|
|
64
|
+
lines.push("; Allow writes to temp directories");
|
|
65
|
+
lines.push(`(allow file-write* (subpath "/tmp"))`);
|
|
66
|
+
lines.push(`(allow file-write* (subpath "/private/tmp"))`);
|
|
67
|
+
lines.push(`(allow file-write* (subpath "${escapeSeatbeltPath(os.tmpdir())}"))`);
|
|
68
|
+
lines.push("");
|
|
69
|
+
}
|
|
70
|
+
if (expandedDenied.length > 0) {
|
|
71
|
+
lines.push("; Deny access to sensitive paths");
|
|
72
|
+
for (const deniedPath of expandedDenied) lines.push(`(deny file-read* file-write* (subpath "${escapeSeatbeltPath(deniedPath)}"))`);
|
|
73
|
+
lines.push("");
|
|
74
|
+
}
|
|
75
|
+
if (expandedAllowed.length > 0) {
|
|
76
|
+
lines.push("; Explicitly allowed read paths");
|
|
77
|
+
for (const allowedPath of expandedAllowed) lines.push(`(allow file-read* (subpath "${escapeSeatbeltPath(allowedPath)}"))`);
|
|
78
|
+
lines.push("");
|
|
79
|
+
}
|
|
80
|
+
return lines.join("\n");
|
|
81
|
+
}
|
|
82
|
+
wrapCommand(options) {
|
|
83
|
+
try {
|
|
84
|
+
const profile = this.generateProfile(options);
|
|
85
|
+
const tmpDir = mkdtempSync(path.join(os.tmpdir(), "b4m-sandbox-"));
|
|
86
|
+
const profilePath = path.join(tmpDir, "sandbox.sb");
|
|
87
|
+
writeFileSync(profilePath, profile, "utf-8");
|
|
88
|
+
const args = [
|
|
89
|
+
"-f",
|
|
90
|
+
profilePath,
|
|
91
|
+
"bash",
|
|
92
|
+
"-c",
|
|
93
|
+
options.command
|
|
94
|
+
];
|
|
95
|
+
const envEntries = Object.entries(options.env ?? {});
|
|
96
|
+
const envPrefix = envEntries.length > 0 ? envEntries.map(([k, v]) => `${k}=${shellEscape(v)}`).join(" ") + " " : "";
|
|
97
|
+
return {
|
|
98
|
+
executable: "sandbox-exec",
|
|
99
|
+
args,
|
|
100
|
+
env: options.env ?? {},
|
|
101
|
+
commandString: `${envPrefix}sandbox-exec -f ${profilePath} bash -c ${shellEscape(options.command)}`,
|
|
102
|
+
cleanupPaths: [profilePath, tmpDir]
|
|
103
|
+
};
|
|
104
|
+
} catch (err) {
|
|
105
|
+
throw new Error(`Failed to create sandbox profile: ${err instanceof Error ? err.message : String(err)}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Shell-escape a string for safe embedding in a command.
|
|
111
|
+
*/
|
|
112
|
+
function shellEscape(str) {
|
|
113
|
+
return `'${str.replace(/'/g, "'\\''")}'`;
|
|
114
|
+
}
|
|
115
|
+
//#endregion
|
|
116
|
+
export { SeatbeltRuntime };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
//#region src/sandbox/logging/StderrViolationParser.ts
|
|
3
|
+
/**
|
|
4
|
+
* Parse macOS Seatbelt denial messages from stderr.
|
|
5
|
+
*
|
|
6
|
+
* Format: sandbox-exec: deny(1) file-write-data /path/to/file
|
|
7
|
+
*/
|
|
8
|
+
function parseSeatbeltStderr(stderr) {
|
|
9
|
+
const violations = [];
|
|
10
|
+
const regex = /sandbox-exec:\s*deny\(\d+\)\s+(\S+)\s+(.+)/g;
|
|
11
|
+
let match;
|
|
12
|
+
while ((match = regex.exec(stderr)) !== null) {
|
|
13
|
+
const operation = match[1];
|
|
14
|
+
const targetPath = match[2].trim();
|
|
15
|
+
const type = classifySeatbeltOperation(operation);
|
|
16
|
+
violations.push({
|
|
17
|
+
type,
|
|
18
|
+
operation,
|
|
19
|
+
path: type === "filesystem" ? targetPath : void 0,
|
|
20
|
+
detail: match[0]
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
return violations;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Parse Linux Bubblewrap error messages from stderr.
|
|
27
|
+
*
|
|
28
|
+
* Format: bwrap: Can't open file /path: Permission denied
|
|
29
|
+
*/
|
|
30
|
+
function parseBwrapStderr(stderr) {
|
|
31
|
+
const violations = [];
|
|
32
|
+
const regex = /bwrap:\s+(.+)/g;
|
|
33
|
+
let match;
|
|
34
|
+
while ((match = regex.exec(stderr)) !== null) {
|
|
35
|
+
const extractedPath = match[1].trim().match(/(?:Can't open file |Can't bind mount )(\S+)/)?.[1]?.replace(/:$/, "");
|
|
36
|
+
violations.push({
|
|
37
|
+
type: "filesystem",
|
|
38
|
+
path: extractedPath,
|
|
39
|
+
detail: match[0]
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
return violations;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Parse sandbox stderr (auto-detects platform from content).
|
|
46
|
+
* Runs both parsers since they match only their own patterns.
|
|
47
|
+
*/
|
|
48
|
+
function parseSandboxStderr(stderr) {
|
|
49
|
+
return [...parseSeatbeltStderr(stderr), ...parseBwrapStderr(stderr)];
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Convert parsed violations to SandboxViolation records.
|
|
53
|
+
*/
|
|
54
|
+
function toSandboxViolations(parsed, command) {
|
|
55
|
+
return parsed.map((p) => ({
|
|
56
|
+
type: p.type,
|
|
57
|
+
path: p.path,
|
|
58
|
+
command,
|
|
59
|
+
blockedBy: "sandbox",
|
|
60
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
61
|
+
detail: p.detail
|
|
62
|
+
}));
|
|
63
|
+
}
|
|
64
|
+
/** Map Seatbelt operation to violation type */
|
|
65
|
+
function classifySeatbeltOperation(operation) {
|
|
66
|
+
if (operation.startsWith("network")) return "network";
|
|
67
|
+
return "filesystem";
|
|
68
|
+
}
|
|
69
|
+
//#endregion
|
|
70
|
+
export { parseSandboxStderr, toSandboxViolations };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { promises } from "fs";
|
|
3
|
+
import { homedir } from "os";
|
|
4
|
+
import path from "path";
|
|
5
|
+
//#region src/sandbox/logging/ViolationLogStore.ts
|
|
6
|
+
const MAX_VIOLATIONS = 5e3;
|
|
7
|
+
const DEFAULT_PATH = path.join(homedir(), ".bike4mind", "violations.jsonl");
|
|
8
|
+
/**
|
|
9
|
+
* Persists sandbox violations to a JSONL file.
|
|
10
|
+
* Follows the same pattern as CommandHistoryStore.
|
|
11
|
+
*/
|
|
12
|
+
var ViolationLogStore = class {
|
|
13
|
+
constructor(storePath) {
|
|
14
|
+
this.cache = null;
|
|
15
|
+
this.storePath = storePath ?? DEFAULT_PATH;
|
|
16
|
+
}
|
|
17
|
+
/** Ensure parent directory exists */
|
|
18
|
+
async init() {
|
|
19
|
+
const dir = path.dirname(this.storePath);
|
|
20
|
+
await promises.mkdir(dir, { recursive: true });
|
|
21
|
+
}
|
|
22
|
+
/** Load all entries from disk (newest first) */
|
|
23
|
+
async load() {
|
|
24
|
+
if (this.cache) return this.cache;
|
|
25
|
+
try {
|
|
26
|
+
const entries = (await promises.readFile(this.storePath, "utf-8")).trim().split("\n").filter((line) => line.length > 0).map((line) => {
|
|
27
|
+
try {
|
|
28
|
+
return JSON.parse(line);
|
|
29
|
+
} catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}).filter((entry) => entry !== null);
|
|
33
|
+
entries.sort((a, b) => b.timestamp - a.timestamp);
|
|
34
|
+
this.cache = entries;
|
|
35
|
+
return this.cache;
|
|
36
|
+
} catch (error) {
|
|
37
|
+
if (error.code === "ENOENT") {
|
|
38
|
+
this.cache = [];
|
|
39
|
+
return this.cache;
|
|
40
|
+
}
|
|
41
|
+
throw error;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/** Record a new violation (converts Date → epoch ms, appends JSONL) */
|
|
45
|
+
async record(violation) {
|
|
46
|
+
const entry = {
|
|
47
|
+
type: violation.type,
|
|
48
|
+
command: violation.command,
|
|
49
|
+
blockedBy: violation.blockedBy,
|
|
50
|
+
timestamp: violation.timestamp.getTime(),
|
|
51
|
+
...violation.path && { path: violation.path },
|
|
52
|
+
...violation.domain && { domain: violation.domain },
|
|
53
|
+
...violation.detail && { detail: violation.detail }
|
|
54
|
+
};
|
|
55
|
+
await this.init();
|
|
56
|
+
const line = JSON.stringify(entry) + "\n";
|
|
57
|
+
await promises.appendFile(this.storePath, line, "utf-8");
|
|
58
|
+
this.cache = [entry, ...this.cache ?? []];
|
|
59
|
+
if (this.cache.length > MAX_VIOLATIONS) await this.trim();
|
|
60
|
+
}
|
|
61
|
+
/** Get recent violations (default 50) */
|
|
62
|
+
async getRecent(count = 50) {
|
|
63
|
+
return (await this.load()).slice(0, count);
|
|
64
|
+
}
|
|
65
|
+
/** Count violations by type */
|
|
66
|
+
async countByType() {
|
|
67
|
+
const entries = await this.load();
|
|
68
|
+
let filesystem = 0;
|
|
69
|
+
let network = 0;
|
|
70
|
+
for (const entry of entries) if (entry.type === "filesystem") filesystem++;
|
|
71
|
+
else if (entry.type === "network") network++;
|
|
72
|
+
return {
|
|
73
|
+
filesystem,
|
|
74
|
+
network
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/** Clear all violations */
|
|
78
|
+
async clear() {
|
|
79
|
+
try {
|
|
80
|
+
await promises.unlink(this.storePath);
|
|
81
|
+
} catch (error) {
|
|
82
|
+
if (error.code !== "ENOENT") throw error;
|
|
83
|
+
}
|
|
84
|
+
this.cache = [];
|
|
85
|
+
}
|
|
86
|
+
/** Trim to MAX_VIOLATIONS (rewrite file) */
|
|
87
|
+
async trim() {
|
|
88
|
+
if (!this.cache || this.cache.length <= MAX_VIOLATIONS) return;
|
|
89
|
+
const trimmed = this.cache.slice(0, MAX_VIOLATIONS);
|
|
90
|
+
const lines = [...trimmed].reverse().map((entry) => JSON.stringify(entry)).join("\n");
|
|
91
|
+
await promises.writeFile(this.storePath, lines + "\n", "utf-8");
|
|
92
|
+
this.cache = trimmed;
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
//#endregion
|
|
96
|
+
export { ViolationLogStore };
|