@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,309 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync } from "fs";
|
|
3
|
+
import { createRequire } from "module";
|
|
4
|
+
//#region src/tools/getFileStructure/types.ts
|
|
5
|
+
/**
|
|
6
|
+
* Map file extensions to tree-sitter language identifiers.
|
|
7
|
+
* Language IDs must match WASM file names (e.g. 'typescript' -> tree-sitter-typescript.wasm).
|
|
8
|
+
*/
|
|
9
|
+
const EXTENSION_TO_LANGUAGE = {
|
|
10
|
+
".ts": "typescript",
|
|
11
|
+
".tsx": "tsx",
|
|
12
|
+
".js": "javascript",
|
|
13
|
+
".jsx": "javascript",
|
|
14
|
+
".mjs": "javascript",
|
|
15
|
+
".cjs": "javascript",
|
|
16
|
+
".py": "python"
|
|
17
|
+
};
|
|
18
|
+
//#endregion
|
|
19
|
+
//#region src/tools/getFileStructure/queries/typescript.ts
|
|
20
|
+
/**
|
|
21
|
+
* Tree-sitter S-expression queries for TypeScript/JavaScript/TSX.
|
|
22
|
+
*
|
|
23
|
+
* These queries extract structural elements from the AST. Each query uses
|
|
24
|
+
* @capture names that the engine maps to StructureItem fields.
|
|
25
|
+
*
|
|
26
|
+
* Works for: .ts, .tsx, .js, .jsx, .mjs, .cjs
|
|
27
|
+
*/
|
|
28
|
+
const typescriptQueries = {
|
|
29
|
+
imports: `
|
|
30
|
+
(import_statement
|
|
31
|
+
source: (string) @source
|
|
32
|
+
) @import
|
|
33
|
+
`,
|
|
34
|
+
exports: `
|
|
35
|
+
(export_statement
|
|
36
|
+
declaration: (function_declaration
|
|
37
|
+
name: (identifier) @name)
|
|
38
|
+
) @export
|
|
39
|
+
|
|
40
|
+
(export_statement
|
|
41
|
+
declaration: (class_declaration
|
|
42
|
+
name: (type_identifier) @name)
|
|
43
|
+
) @export
|
|
44
|
+
|
|
45
|
+
(export_statement
|
|
46
|
+
declaration: (interface_declaration
|
|
47
|
+
name: (type_identifier) @name)
|
|
48
|
+
) @export
|
|
49
|
+
|
|
50
|
+
(export_statement
|
|
51
|
+
declaration: (type_alias_declaration
|
|
52
|
+
name: (type_identifier) @name)
|
|
53
|
+
) @export
|
|
54
|
+
|
|
55
|
+
(export_statement
|
|
56
|
+
declaration: (enum_declaration
|
|
57
|
+
name: (identifier) @name)
|
|
58
|
+
) @export
|
|
59
|
+
|
|
60
|
+
(export_statement
|
|
61
|
+
declaration: (lexical_declaration
|
|
62
|
+
(variable_declarator
|
|
63
|
+
name: (identifier) @name))
|
|
64
|
+
) @export
|
|
65
|
+
|
|
66
|
+
(export_statement
|
|
67
|
+
(export_clause
|
|
68
|
+
(export_specifier
|
|
69
|
+
name: (identifier) @name))
|
|
70
|
+
) @export
|
|
71
|
+
`,
|
|
72
|
+
functions: `
|
|
73
|
+
(function_declaration
|
|
74
|
+
name: (identifier) @name
|
|
75
|
+
) @function
|
|
76
|
+
|
|
77
|
+
(lexical_declaration
|
|
78
|
+
(variable_declarator
|
|
79
|
+
name: (identifier) @name
|
|
80
|
+
value: (arrow_function)
|
|
81
|
+
)
|
|
82
|
+
) @function
|
|
83
|
+
`,
|
|
84
|
+
classes: `
|
|
85
|
+
(class_declaration
|
|
86
|
+
name: (type_identifier) @name
|
|
87
|
+
) @class
|
|
88
|
+
`,
|
|
89
|
+
interfaces: `
|
|
90
|
+
(interface_declaration
|
|
91
|
+
name: (type_identifier) @name
|
|
92
|
+
) @interface
|
|
93
|
+
`,
|
|
94
|
+
types: `
|
|
95
|
+
(type_alias_declaration
|
|
96
|
+
name: (type_identifier) @name
|
|
97
|
+
) @type
|
|
98
|
+
|
|
99
|
+
(enum_declaration
|
|
100
|
+
name: (identifier) @name
|
|
101
|
+
) @enum
|
|
102
|
+
`
|
|
103
|
+
};
|
|
104
|
+
//#endregion
|
|
105
|
+
//#region src/tools/getFileStructure/queries/index.ts
|
|
106
|
+
/** Registry mapping tree-sitter language identifiers to their query definitions. */
|
|
107
|
+
const LANGUAGE_QUERIES = {
|
|
108
|
+
typescript: typescriptQueries,
|
|
109
|
+
tsx: typescriptQueries,
|
|
110
|
+
javascript: {
|
|
111
|
+
imports: `
|
|
112
|
+
(import_statement
|
|
113
|
+
source: (string) @source
|
|
114
|
+
) @import
|
|
115
|
+
`,
|
|
116
|
+
exports: `
|
|
117
|
+
(export_statement
|
|
118
|
+
declaration: (function_declaration
|
|
119
|
+
name: (identifier) @name)
|
|
120
|
+
) @export
|
|
121
|
+
|
|
122
|
+
(export_statement
|
|
123
|
+
declaration: (class_declaration
|
|
124
|
+
name: (identifier) @name)
|
|
125
|
+
) @export
|
|
126
|
+
|
|
127
|
+
(export_statement
|
|
128
|
+
declaration: (lexical_declaration
|
|
129
|
+
(variable_declarator
|
|
130
|
+
name: (identifier) @name))
|
|
131
|
+
) @export
|
|
132
|
+
|
|
133
|
+
(export_statement
|
|
134
|
+
(export_clause
|
|
135
|
+
(export_specifier
|
|
136
|
+
name: (identifier) @name))
|
|
137
|
+
) @export
|
|
138
|
+
`,
|
|
139
|
+
functions: `
|
|
140
|
+
(function_declaration
|
|
141
|
+
name: (identifier) @name
|
|
142
|
+
) @function
|
|
143
|
+
|
|
144
|
+
(lexical_declaration
|
|
145
|
+
(variable_declarator
|
|
146
|
+
name: (identifier) @name
|
|
147
|
+
value: (arrow_function)
|
|
148
|
+
)
|
|
149
|
+
) @function
|
|
150
|
+
`,
|
|
151
|
+
classes: `
|
|
152
|
+
(class_declaration
|
|
153
|
+
name: (identifier) @name
|
|
154
|
+
) @class
|
|
155
|
+
`,
|
|
156
|
+
interfaces: "",
|
|
157
|
+
types: ""
|
|
158
|
+
},
|
|
159
|
+
python: {
|
|
160
|
+
imports: `
|
|
161
|
+
(import_statement
|
|
162
|
+
name: (dotted_name) @source
|
|
163
|
+
) @import
|
|
164
|
+
|
|
165
|
+
(import_from_statement
|
|
166
|
+
module_name: (dotted_name) @source
|
|
167
|
+
) @import_from
|
|
168
|
+
`,
|
|
169
|
+
exports: "",
|
|
170
|
+
functions: `
|
|
171
|
+
(function_definition
|
|
172
|
+
name: (identifier) @name
|
|
173
|
+
) @function
|
|
174
|
+
`,
|
|
175
|
+
classes: `
|
|
176
|
+
(class_definition
|
|
177
|
+
name: (identifier) @name
|
|
178
|
+
) @class
|
|
179
|
+
`,
|
|
180
|
+
interfaces: "",
|
|
181
|
+
types: ""
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
//#endregion
|
|
185
|
+
//#region src/tools/getFileStructure/treeSitterEngine.ts
|
|
186
|
+
const require = createRequire(import.meta.url);
|
|
187
|
+
let TreeSitter;
|
|
188
|
+
let parserInitialized = false;
|
|
189
|
+
const languageCache = /* @__PURE__ */ new Map();
|
|
190
|
+
function locateTreeSitterWasm() {
|
|
191
|
+
return require.resolve("web-tree-sitter/tree-sitter.wasm");
|
|
192
|
+
}
|
|
193
|
+
function locateLanguageWasm(language) {
|
|
194
|
+
return require.resolve(`tree-sitter-wasms/out/tree-sitter-${language}.wasm`);
|
|
195
|
+
}
|
|
196
|
+
/** Initialize the tree-sitter parser (lazy, one-time). */
|
|
197
|
+
async function ensureInitialized() {
|
|
198
|
+
if (parserInitialized) return;
|
|
199
|
+
try {
|
|
200
|
+
TreeSitter = await import("web-tree-sitter");
|
|
201
|
+
} catch {
|
|
202
|
+
throw new Error("web-tree-sitter is not available. Install it with: pnpm add web-tree-sitter tree-sitter-wasms --filter @bike4mind/cli");
|
|
203
|
+
}
|
|
204
|
+
const wasmPath = locateTreeSitterWasm();
|
|
205
|
+
const wasmBinary = readFileSync(wasmPath);
|
|
206
|
+
await TreeSitter.Parser.init({
|
|
207
|
+
locateFile: (scriptName) => {
|
|
208
|
+
if (scriptName === "tree-sitter.wasm") return wasmPath;
|
|
209
|
+
return scriptName;
|
|
210
|
+
},
|
|
211
|
+
wasmBinary
|
|
212
|
+
});
|
|
213
|
+
parserInitialized = true;
|
|
214
|
+
}
|
|
215
|
+
/** Load and cache a language grammar. */
|
|
216
|
+
async function loadLanguage(languageId) {
|
|
217
|
+
const cached = languageCache.get(languageId);
|
|
218
|
+
if (cached) return cached;
|
|
219
|
+
const wasmPath = locateLanguageWasm(languageId);
|
|
220
|
+
const language = await TreeSitter.Language.load(wasmPath);
|
|
221
|
+
languageCache.set(languageId, language);
|
|
222
|
+
return language;
|
|
223
|
+
}
|
|
224
|
+
/** Run a single query category and extract structure items. */
|
|
225
|
+
function runQuery(language, rootNode, querySource, kind) {
|
|
226
|
+
if (!querySource.trim()) return [];
|
|
227
|
+
const items = [];
|
|
228
|
+
const query = new TreeSitter.Query(language, querySource);
|
|
229
|
+
try {
|
|
230
|
+
const matches = query.matches(rootNode);
|
|
231
|
+
for (const match of matches) {
|
|
232
|
+
const nameCapture = match.captures.find((c) => c.name === "name");
|
|
233
|
+
const sourceCapture = match.captures.find((c) => c.name === "source");
|
|
234
|
+
if (kind === "import") {
|
|
235
|
+
const node = match.captures.find((c) => c.name === "import" || c.name === "import_from")?.node || sourceCapture?.node;
|
|
236
|
+
if (node) items.push({
|
|
237
|
+
kind: "import",
|
|
238
|
+
name: sourceCapture?.node.text.replace(/['"]/g, "") || "",
|
|
239
|
+
line: node.startPosition.row + 1,
|
|
240
|
+
details: node.text
|
|
241
|
+
});
|
|
242
|
+
} else if (nameCapture) items.push({
|
|
243
|
+
kind,
|
|
244
|
+
name: nameCapture.node.text,
|
|
245
|
+
line: nameCapture.node.startPosition.row + 1,
|
|
246
|
+
...kind === "export" && { exported: true }
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
} finally {
|
|
250
|
+
query.delete();
|
|
251
|
+
}
|
|
252
|
+
return items;
|
|
253
|
+
}
|
|
254
|
+
/** Query category keys mapped to their StructureItem kind (singular of plural). */
|
|
255
|
+
const QUERY_CATEGORIES = [
|
|
256
|
+
["imports", "import"],
|
|
257
|
+
["exports", "export"],
|
|
258
|
+
["functions", "function"],
|
|
259
|
+
["classes", "class"],
|
|
260
|
+
["interfaces", "interface"],
|
|
261
|
+
["types", "type"]
|
|
262
|
+
];
|
|
263
|
+
/**
|
|
264
|
+
* Parse a source file and extract its structural elements.
|
|
265
|
+
*/
|
|
266
|
+
async function parseFileStructure(sourceCode, languageId) {
|
|
267
|
+
await ensureInitialized();
|
|
268
|
+
const queries = LANGUAGE_QUERIES[languageId];
|
|
269
|
+
if (!queries) throw new Error(`No query definitions for language: ${languageId}. Supported: ${getSupportedLanguages().join(", ")}`);
|
|
270
|
+
const language = await loadLanguage(languageId);
|
|
271
|
+
const parser = new TreeSitter.Parser();
|
|
272
|
+
let tree = null;
|
|
273
|
+
try {
|
|
274
|
+
parser.setLanguage(language);
|
|
275
|
+
tree = parser.parse(sourceCode);
|
|
276
|
+
if (!tree) throw new Error("Failed to parse source code");
|
|
277
|
+
const allItems = [];
|
|
278
|
+
for (const [queryKey, kind] of QUERY_CATEGORIES) allItems.push(...runQuery(language, tree.rootNode, queries[queryKey], kind));
|
|
279
|
+
return deduplicateItems(allItems);
|
|
280
|
+
} finally {
|
|
281
|
+
tree?.delete();
|
|
282
|
+
parser.delete();
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Deduplicate structure items. When an item appears as both an export and a
|
|
287
|
+
* function/class/type, mark the definition as exported and drop the separate export entry.
|
|
288
|
+
*/
|
|
289
|
+
function deduplicateItems(items) {
|
|
290
|
+
const exportNames = /* @__PURE__ */ new Set();
|
|
291
|
+
const definitionNames = /* @__PURE__ */ new Set();
|
|
292
|
+
for (const item of items) if (item.kind === "export") exportNames.add(item.name);
|
|
293
|
+
else if (item.kind !== "import") definitionNames.add(item.name);
|
|
294
|
+
const result = [];
|
|
295
|
+
for (const item of items) {
|
|
296
|
+
if (item.kind === "export" && definitionNames.has(item.name)) continue;
|
|
297
|
+
if (item.kind !== "export" && item.kind !== "import" && exportNames.has(item.name)) item.exported = true;
|
|
298
|
+
result.push(item);
|
|
299
|
+
}
|
|
300
|
+
return result;
|
|
301
|
+
}
|
|
302
|
+
function getSupportedLanguages() {
|
|
303
|
+
return Object.keys(LANGUAGE_QUERIES);
|
|
304
|
+
}
|
|
305
|
+
function getLanguageForExtension(ext) {
|
|
306
|
+
return EXTENSION_TO_LANGUAGE[ext] || null;
|
|
307
|
+
}
|
|
308
|
+
//#endregion
|
|
309
|
+
export { getLanguageForExtension, getSupportedLanguages, parseFileStructure };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
//#region src/sandbox/types.ts
|
|
3
|
+
/** Default sandbox configuration */
|
|
4
|
+
const DEFAULT_SANDBOX_CONFIG = {
|
|
5
|
+
enabled: false,
|
|
6
|
+
mode: "disabled",
|
|
7
|
+
filesystem: {
|
|
8
|
+
writeOnlyToWorkingDir: true,
|
|
9
|
+
allowedReadPaths: [
|
|
10
|
+
"$HOME/.gitconfig",
|
|
11
|
+
"$HOME/.npmrc",
|
|
12
|
+
"$HOME/.node_modules"
|
|
13
|
+
],
|
|
14
|
+
deniedPaths: [
|
|
15
|
+
"$HOME/.ssh",
|
|
16
|
+
"$HOME/.aws",
|
|
17
|
+
"$HOME/.gnupg",
|
|
18
|
+
"$HOME/.env",
|
|
19
|
+
"/etc/shadow",
|
|
20
|
+
"/etc/passwd"
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
network: {
|
|
24
|
+
enabled: false,
|
|
25
|
+
allowedDomains: [
|
|
26
|
+
"registry.npmjs.org",
|
|
27
|
+
"*.npmjs.org",
|
|
28
|
+
"pypi.org",
|
|
29
|
+
"*.pypi.org",
|
|
30
|
+
"files.pythonhosted.org",
|
|
31
|
+
"crates.io",
|
|
32
|
+
"*.crates.io",
|
|
33
|
+
"rubygems.org",
|
|
34
|
+
"github.com",
|
|
35
|
+
"*.github.com",
|
|
36
|
+
"gitlab.com",
|
|
37
|
+
"*.gitlab.com",
|
|
38
|
+
"bitbucket.org",
|
|
39
|
+
"*.bitbucket.org",
|
|
40
|
+
"*.githubusercontent.com",
|
|
41
|
+
"*.cloudflare.com"
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
excludedCommands: [
|
|
45
|
+
"docker",
|
|
46
|
+
"watchman",
|
|
47
|
+
"podman"
|
|
48
|
+
],
|
|
49
|
+
allowUnsandboxedCommands: true,
|
|
50
|
+
platform: {
|
|
51
|
+
linux: { runtime: "bubblewrap" },
|
|
52
|
+
macos: {
|
|
53
|
+
runtime: "seatbelt",
|
|
54
|
+
profileTemplate: "default"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
//#endregion
|
|
59
|
+
export { DEFAULT_SANDBOX_CONFIG as t };
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { promises } from "fs";
|
|
3
|
+
import { homedir } from "os";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import axios from "axios";
|
|
6
|
+
//#region package.json
|
|
7
|
+
var version = "0.2.64";
|
|
8
|
+
//#endregion
|
|
9
|
+
//#region src/utils/updateChecker.ts
|
|
10
|
+
/**
|
|
11
|
+
* Update checker utility for B4M CLI
|
|
12
|
+
* Checks the NPM registry for newer versions and caches results.
|
|
13
|
+
* Used by the startup banner, `b4m update`, and `b4m doctor` commands.
|
|
14
|
+
*/
|
|
15
|
+
const CACHE_FILE = path.join(homedir(), ".bike4mind", "update-check.json");
|
|
16
|
+
const CACHE_TTL_MS = 1440 * 60 * 1e3;
|
|
17
|
+
const NPM_REGISTRY_URL = "https://registry.npmjs.org/@bike4mind/cli/latest";
|
|
18
|
+
const FETCH_TIMEOUT_MS = 5e3;
|
|
19
|
+
/**
|
|
20
|
+
* Compare two semver strings (MAJOR.MINOR.PATCH).
|
|
21
|
+
* Returns -1 if a < b, 0 if equal, 1 if a > b.
|
|
22
|
+
*/
|
|
23
|
+
function compareSemver(a, b) {
|
|
24
|
+
const partsA = a.split(".").map(Number);
|
|
25
|
+
const partsB = b.split(".").map(Number);
|
|
26
|
+
for (let i = 0; i < 3; i++) {
|
|
27
|
+
const segA = partsA[i] ?? 0;
|
|
28
|
+
const segB = partsB[i] ?? 0;
|
|
29
|
+
if (segA < segB) return -1;
|
|
30
|
+
if (segA > segB) return 1;
|
|
31
|
+
}
|
|
32
|
+
return 0;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Fetch the latest published version from the NPM registry.
|
|
36
|
+
* Returns the version string or null on any error.
|
|
37
|
+
*/
|
|
38
|
+
async function fetchLatestVersion() {
|
|
39
|
+
try {
|
|
40
|
+
const version = (await axios.get(NPM_REGISTRY_URL, {
|
|
41
|
+
timeout: FETCH_TIMEOUT_MS,
|
|
42
|
+
headers: { Accept: "application/json" }
|
|
43
|
+
})).data?.version;
|
|
44
|
+
return typeof version === "string" ? version : null;
|
|
45
|
+
} catch {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Read the cached update check result.
|
|
51
|
+
*/
|
|
52
|
+
async function readCache() {
|
|
53
|
+
try {
|
|
54
|
+
const data = await promises.readFile(CACHE_FILE, "utf-8");
|
|
55
|
+
const parsed = JSON.parse(data);
|
|
56
|
+
if (parsed && typeof parsed.lastChecked === "string" && typeof parsed.latestVersion === "string") return parsed;
|
|
57
|
+
return null;
|
|
58
|
+
} catch {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Write the update check result to cache.
|
|
64
|
+
*/
|
|
65
|
+
async function writeCache(cache) {
|
|
66
|
+
try {
|
|
67
|
+
await promises.mkdir(path.dirname(CACHE_FILE), { recursive: true });
|
|
68
|
+
await promises.writeFile(CACHE_FILE, JSON.stringify(cache, null, 2), "utf-8");
|
|
69
|
+
} catch {}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Check for updates using cache when fresh.
|
|
73
|
+
* Non-throwing — returns null on any error.
|
|
74
|
+
*/
|
|
75
|
+
async function checkForUpdate(currentVersion) {
|
|
76
|
+
try {
|
|
77
|
+
const cache = await readCache();
|
|
78
|
+
if (cache && cache.currentVersion === currentVersion) {
|
|
79
|
+
if (Date.now() - new Date(cache.lastChecked).getTime() < CACHE_TTL_MS) return {
|
|
80
|
+
currentVersion,
|
|
81
|
+
latestVersion: cache.latestVersion,
|
|
82
|
+
updateAvailable: compareSemver(cache.latestVersion, currentVersion) > 0
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
const latestVersion = await fetchLatestVersion();
|
|
86
|
+
if (!latestVersion) return null;
|
|
87
|
+
await writeCache({
|
|
88
|
+
lastChecked: (/* @__PURE__ */ new Date()).toISOString(),
|
|
89
|
+
latestVersion,
|
|
90
|
+
currentVersion
|
|
91
|
+
});
|
|
92
|
+
return {
|
|
93
|
+
currentVersion,
|
|
94
|
+
latestVersion,
|
|
95
|
+
updateAvailable: compareSemver(latestVersion, currentVersion) > 0
|
|
96
|
+
};
|
|
97
|
+
} catch {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Force-check for updates (ignores cache).
|
|
103
|
+
* Used by `b4m update` and `b4m doctor`.
|
|
104
|
+
*/
|
|
105
|
+
async function forceCheckForUpdate(currentVersion) {
|
|
106
|
+
const latestVersion = await fetchLatestVersion();
|
|
107
|
+
if (!latestVersion) return null;
|
|
108
|
+
await writeCache({
|
|
109
|
+
lastChecked: (/* @__PURE__ */ new Date()).toISOString(),
|
|
110
|
+
latestVersion,
|
|
111
|
+
currentVersion
|
|
112
|
+
});
|
|
113
|
+
return {
|
|
114
|
+
currentVersion,
|
|
115
|
+
latestVersion,
|
|
116
|
+
updateAvailable: compareSemver(latestVersion, currentVersion) > 0
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
//#endregion
|
|
120
|
+
export { version as i, fetchLatestVersion as n, forceCheckForUpdate as r, checkForUpdate as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bike4mind/cli",
|
|
3
|
-
"version": "0.2.64
|
|
3
|
+
"version": "0.2.64",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Interactive CLI tool for Bike4Mind with ReAct agents",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -32,11 +32,11 @@
|
|
|
32
32
|
],
|
|
33
33
|
"scripts": {
|
|
34
34
|
"dev": "tsx src/index.tsx",
|
|
35
|
-
"build": "
|
|
35
|
+
"build": "tsdown",
|
|
36
36
|
"typecheck": "tsc --noEmit",
|
|
37
37
|
"test": "vitest run",
|
|
38
38
|
"test:watch": "vitest",
|
|
39
|
-
"start": "node dist/index.
|
|
39
|
+
"start": "node dist/index.mjs",
|
|
40
40
|
"prepublishOnly": "pnpm build",
|
|
41
41
|
"postinstall": "node -e \"try { require('better-sqlite3') } catch(e) { if(e.message.includes('bindings')) { console.log('\\n⚠️ Rebuilding better-sqlite3 native bindings...'); require('child_process').execSync('pnpm rebuild better-sqlite3', {stdio:'inherit'}) } }\""
|
|
42
42
|
},
|
|
@@ -115,11 +115,11 @@
|
|
|
115
115
|
"zustand": "^4.5.4"
|
|
116
116
|
},
|
|
117
117
|
"devDependencies": {
|
|
118
|
-
"@bike4mind/agents": "0.4.2
|
|
119
|
-
"@bike4mind/common": "2.75.1
|
|
120
|
-
"@bike4mind/mcp": "1.33.21
|
|
121
|
-
"@bike4mind/services": "2.69.1
|
|
122
|
-
"@bike4mind/utils": "2.16.3
|
|
118
|
+
"@bike4mind/agents": "0.4.2",
|
|
119
|
+
"@bike4mind/common": "2.75.1",
|
|
120
|
+
"@bike4mind/mcp": "1.33.21",
|
|
121
|
+
"@bike4mind/services": "2.69.1",
|
|
122
|
+
"@bike4mind/utils": "2.16.3",
|
|
123
123
|
"@types/better-sqlite3": "^7.6.13",
|
|
124
124
|
"@types/jsonwebtoken": "^9.0.4",
|
|
125
125
|
"@types/node": "^22.9.0",
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
"@types/ws": "^8.18.1",
|
|
129
129
|
"@types/yargs": "^17.0.35",
|
|
130
130
|
"ink-testing-library": "^4.0.0",
|
|
131
|
-
"
|
|
131
|
+
"tsdown": "^0.21.4",
|
|
132
132
|
"tsx": "^4.21.0",
|
|
133
133
|
"typescript": "^5.9.3",
|
|
134
134
|
"vitest": "^4.1.0"
|
|
@@ -136,5 +136,5 @@
|
|
|
136
136
|
"optionalDependencies": {
|
|
137
137
|
"@vscode/ripgrep": "^1.17.1"
|
|
138
138
|
},
|
|
139
|
-
"gitHead": "
|
|
139
|
+
"gitHead": "bab047b7f53654baafcbb873a9b5e6a8f16cffb7"
|
|
140
140
|
}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
expandPath,
|
|
4
|
-
isBinaryAvailable
|
|
5
|
-
} from "./chunk-QWB6ZYY4.js";
|
|
6
|
-
|
|
7
|
-
// src/sandbox/runtime/BubblewrapRuntime.ts
|
|
8
|
-
import os from "os";
|
|
9
|
-
var SYSTEM_RO_BINDS = ["/usr", "/bin", "/lib", "/lib64", "/sbin", "/etc"];
|
|
10
|
-
var SPECIAL_MOUNTS = {
|
|
11
|
-
dev: "/dev",
|
|
12
|
-
proc: "/proc",
|
|
13
|
-
tmp: "/tmp"
|
|
14
|
-
};
|
|
15
|
-
var BubblewrapRuntime = class {
|
|
16
|
-
constructor() {
|
|
17
|
-
this.platform = "linux";
|
|
18
|
-
this.name = "bubblewrap";
|
|
19
|
-
}
|
|
20
|
-
isAvailable() {
|
|
21
|
-
return isBinaryAvailable("bwrap");
|
|
22
|
-
}
|
|
23
|
-
wrapCommand(options) {
|
|
24
|
-
const { command, cwd, filesystemConfig, env } = options;
|
|
25
|
-
const expandedDenied = filesystemConfig.deniedPaths.map(expandPath);
|
|
26
|
-
const expandedAllowed = filesystemConfig.allowedReadPaths.map(expandPath);
|
|
27
|
-
const args = [];
|
|
28
|
-
for (const sysPath of SYSTEM_RO_BINDS) {
|
|
29
|
-
args.push("--ro-bind-try", sysPath, sysPath);
|
|
30
|
-
}
|
|
31
|
-
args.push("--dev", SPECIAL_MOUNTS.dev);
|
|
32
|
-
args.push("--proc", SPECIAL_MOUNTS.proc);
|
|
33
|
-
args.push("--tmpfs", SPECIAL_MOUNTS.tmp);
|
|
34
|
-
args.push("--bind", cwd, cwd);
|
|
35
|
-
const homeDir = os.homedir();
|
|
36
|
-
args.push("--ro-bind", homeDir, homeDir);
|
|
37
|
-
for (const allowedPath of expandedAllowed) {
|
|
38
|
-
if (!allowedPath.startsWith(homeDir)) {
|
|
39
|
-
args.push("--ro-bind-try", allowedPath, allowedPath);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
for (const deniedPath of expandedDenied) {
|
|
43
|
-
args.push("--tmpfs", deniedPath);
|
|
44
|
-
}
|
|
45
|
-
args.push("--unshare-all");
|
|
46
|
-
args.push("--share-net");
|
|
47
|
-
args.push("--die-with-parent");
|
|
48
|
-
if (options.seccompProfile) {
|
|
49
|
-
args.push("--seccomp", options.seccompProfile);
|
|
50
|
-
}
|
|
51
|
-
for (const [key, value] of Object.entries(env ?? {})) {
|
|
52
|
-
args.push("--setenv", key, value);
|
|
53
|
-
}
|
|
54
|
-
args.push("--chdir", cwd);
|
|
55
|
-
args.push("bash", "-c", command);
|
|
56
|
-
const commandString = ["bwrap", ...args.map(shellEscape)].join(" ");
|
|
57
|
-
return {
|
|
58
|
-
executable: "bwrap",
|
|
59
|
-
args,
|
|
60
|
-
env: env ?? {},
|
|
61
|
-
commandString
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
function shellEscape(str) {
|
|
66
|
-
if (/^[a-zA-Z0-9._/=:-]+$/.test(str)) return str;
|
|
67
|
-
return `'${str.replace(/'/g, "'\\''")}'`;
|
|
68
|
-
}
|
|
69
|
-
export {
|
|
70
|
-
BubblewrapRuntime
|
|
71
|
-
};
|