@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.
Files changed (85) hide show
  1. package/bin/bike4mind-cli.mjs +6 -6
  2. package/dist/BubblewrapRuntime-BHbtqvLx.mjs +72 -0
  3. package/dist/ConfigStore-CllM6jOf.mjs +8614 -0
  4. package/dist/ImageStore-DaKT_Ew8.mjs +202 -0
  5. package/dist/ProxyManager-Dl2nFk-A.mjs +259 -0
  6. package/dist/ProxyManager-kiOD1X8-.mjs +3 -0
  7. package/dist/SandboxOrchestrator-BEW3rqYi.mjs +159 -0
  8. package/dist/SandboxOrchestrator-CHZgSR3P.mjs +3 -0
  9. package/dist/SandboxRuntimeAdapter-C1B4t20N.mjs +57 -0
  10. package/dist/SandboxRuntimeAdapter-D7UAG13n.mjs +3 -0
  11. package/dist/SeatbeltRuntime-D4m0VOcD.mjs +116 -0
  12. package/dist/StderrViolationParser-D0afQ3-1.mjs +70 -0
  13. package/dist/ViolationLogStore-CZl35HcA.mjs +96 -0
  14. package/dist/bashExecute-BTkdqlSs-5foM20Lb.mjs +466 -0
  15. package/dist/commands/doctorCommand.mjs +101 -0
  16. package/dist/commands/headlessCommand.mjs +319 -0
  17. package/dist/commands/mcpCommand.mjs +218 -0
  18. package/dist/commands/updateCommand.mjs +40 -0
  19. package/dist/createFile-yQfh8uvk-I-yM5DxC.mjs +63 -0
  20. package/dist/deleteFile-DKHfnyny-G3b1Kj2T.mjs +66 -0
  21. package/dist/globFiles-D1en6joM-8jekiXdX.mjs +100 -0
  22. package/dist/grepSearch-aMamoBn_-DCJcY8JS.mjs +173 -0
  23. package/dist/index.mjs +6722 -0
  24. package/dist/pathValidation-Cgjh5WQO-DiCZTcq6.mjs +63 -0
  25. package/dist/store-Dw1nZX2Y.mjs +128 -0
  26. package/dist/store-nZExNOWX.mjs +3 -0
  27. package/dist/terminalSetup-rmr1P8KF.mjs +254 -0
  28. package/dist/tools-C6M5aW8W.mjs +20907 -0
  29. package/dist/treeSitterEngine-DCSXcm_3.mjs +309 -0
  30. package/dist/types-DBEjF9YS.mjs +59 -0
  31. package/dist/types-DK3P88Px.mjs +3 -0
  32. package/dist/updateChecker-Cu9dkHxV.mjs +120 -0
  33. package/package.json +10 -10
  34. package/dist/BubblewrapRuntime-PMIOLWKR.js +0 -71
  35. package/dist/HydrationEngine-YL2HWJ3V.js +0 -9
  36. package/dist/ImageStore-MMUOUPI2.js +0 -224
  37. package/dist/ProxyManager-HEB4TLVX.js +0 -7
  38. package/dist/SandboxOrchestrator-UIJ5GYBB.js +0 -8
  39. package/dist/SandboxRuntimeAdapter-FQ56MAB2.js +0 -13
  40. package/dist/SeatbeltRuntime-EE3TTLEP.js +0 -98
  41. package/dist/StderrViolationParser-7OYPM2DJ.js +0 -59
  42. package/dist/ViolationLogStore-RIIUVURH.js +0 -104
  43. package/dist/artifactExtractor-R7DIP2XO.js +0 -180
  44. package/dist/bashExecute-GLGLD3JD.js +0 -379
  45. package/dist/chunk-4BIBE3J7.js +0 -48
  46. package/dist/chunk-5LZS5CVJ.js +0 -161
  47. package/dist/chunk-BDQBOLYG.js +0 -120
  48. package/dist/chunk-BPFEGDC7.js +0 -192
  49. package/dist/chunk-EPIYC3LA.js +0 -13770
  50. package/dist/chunk-G4ZGEQFT.js +0 -250
  51. package/dist/chunk-GQGOWACU.js +0 -770
  52. package/dist/chunk-J6ZBI6TI.js +0 -1079
  53. package/dist/chunk-JW3JRHH7.js +0 -12433
  54. package/dist/chunk-KQAMBXAW.js +0 -163
  55. package/dist/chunk-KUVV2NAB.js +0 -19125
  56. package/dist/chunk-LTLJRF6I.js +0 -44
  57. package/dist/chunk-PFBYGCOW.js +0 -449
  58. package/dist/chunk-QWB6ZYY4.js +0 -48
  59. package/dist/chunk-SGPRXN4C.js +0 -245
  60. package/dist/chunk-UZUHPHZC.js +0 -95
  61. package/dist/chunk-WBE7SQUB.js +0 -241
  62. package/dist/chunk-Y4WOJJM3.js +0 -147
  63. package/dist/commands/doctorCommand.js +0 -87
  64. package/dist/commands/headlessCommand.js +0 -380
  65. package/dist/commands/mcpCommand.js +0 -203
  66. package/dist/commands/updateCommand.js +0 -42
  67. package/dist/create-C4VEEEYR.js +0 -12
  68. package/dist/createFile-6PSPLW6R.js +0 -71
  69. package/dist/deleteFile-AUSRLWIK.js +0 -73
  70. package/dist/formatConverter-5QEJDW24.js +0 -7
  71. package/dist/globFiles-TSRN64N2.js +0 -120
  72. package/dist/grepSearch-634XWZOJ.js +0 -216
  73. package/dist/index.js +0 -6779
  74. package/dist/llmMarkdownGenerator-Z6NB26TT.js +0 -371
  75. package/dist/markdownGenerator-SK2ZQQL4.js +0 -269
  76. package/dist/mementoService-N4IM6QAC.js +0 -12
  77. package/dist/notificationDeduplicator-HUC53NEW.js +0 -9
  78. package/dist/src-F4KZCAA2.js +0 -319
  79. package/dist/src-ISX322I7.js +0 -1101
  80. package/dist/store-CAB6BV3P.js +0 -11
  81. package/dist/subtractCredits-D4KEM6VU.js +0 -12
  82. package/dist/terminalSetup-C5FHMLC3.js +0 -214
  83. package/dist/treeSitterEngine-4SGFQDY3.js +0 -330
  84. package/dist/types-KB5NP6T4.js +0 -7
  85. package/dist/utils-JCHWDM4Z.js +0 -31
@@ -1,1079 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- ChatModels
4
- } from "./chunk-JW3JRHH7.js";
5
- import {
6
- DEFAULT_SANDBOX_CONFIG
7
- } from "./chunk-4BIBE3J7.js";
8
-
9
- // src/utils/Logger.ts
10
- import fs from "fs/promises";
11
- import path from "path";
12
- import os from "os";
13
- var Logger = class _Logger {
14
- constructor() {
15
- this.logFilePath = null;
16
- this.sessionId = null;
17
- this.fileLoggingEnabled = true;
18
- this.consoleVerbose = false;
19
- }
20
- static {
21
- this.instance = null;
22
- }
23
- static getInstance() {
24
- if (!_Logger.instance) {
25
- _Logger.instance = new _Logger();
26
- }
27
- return _Logger.instance;
28
- }
29
- /**
30
- * Initialize the logger with a session ID
31
- */
32
- async initialize(sessionId) {
33
- this.sessionId = sessionId;
34
- const debugDir = path.join(os.homedir(), ".bike4mind", "debug");
35
- await fs.mkdir(debugDir, { recursive: true });
36
- this.logFilePath = path.join(debugDir, `${sessionId}.txt`);
37
- await this.writeToFile("INFO", "=== CLI SESSION START ===");
38
- }
39
- /**
40
- * Set whether verbose console logging is enabled
41
- */
42
- setVerbose(enabled) {
43
- this.consoleVerbose = enabled;
44
- }
45
- /**
46
- * Set whether file logging is enabled
47
- */
48
- setFileLoggingEnabled(enabled) {
49
- this.fileLoggingEnabled = enabled;
50
- }
51
- /**
52
- * DEBUG level - verbose-only console, always file
53
- */
54
- debug(message) {
55
- this.writeToFile("DEBUG", message).catch(() => {
56
- });
57
- if (this.consoleVerbose) {
58
- console.log(message);
59
- }
60
- }
61
- /**
62
- * INFO level - always shown to user
63
- */
64
- info(message) {
65
- this.writeToFile("INFO", message).catch(() => {
66
- });
67
- console.log(message);
68
- }
69
- /**
70
- * WARN level - always shown to user
71
- */
72
- warn(message) {
73
- this.writeToFile("WARN", message).catch(() => {
74
- });
75
- console.warn(message);
76
- }
77
- /**
78
- * ERROR level - always shown to user
79
- */
80
- error(message, err) {
81
- this.writeToFile("ERROR", message).catch(() => {
82
- });
83
- if (err) {
84
- this.logErrorDetailsToFile(err).catch(() => {
85
- });
86
- }
87
- console.error(message);
88
- }
89
- /**
90
- * Write log entry to file
91
- */
92
- async writeToFile(level, message) {
93
- if (!this.fileLoggingEnabled || !this.logFilePath) {
94
- return;
95
- }
96
- try {
97
- const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").substring(0, 19);
98
- const logEntry = `[${timestamp}] [${level}] ${message}
99
- `;
100
- await fs.appendFile(this.logFilePath, logEntry, "utf-8");
101
- } catch (error) {
102
- console.error("File logging failed:", error);
103
- }
104
- }
105
- /**
106
- * Log error details to file
107
- */
108
- async logErrorDetailsToFile(err) {
109
- if (!this.fileLoggingEnabled || !this.logFilePath) {
110
- return;
111
- }
112
- try {
113
- if (err && typeof err === "object" && "response" in err && err.response) {
114
- const response = err.response;
115
- const config = err && typeof err === "object" && "config" in err ? err.config : void 0;
116
- await this.writeToFile("ERROR", ` Status: ${response.status} ${response.statusText || ""}`);
117
- await this.writeToFile("ERROR", ` URL: ${config?.url || "unknown"}`);
118
- await this.writeToFile("ERROR", ` Headers: ${this.safeStringify(response.headers)}`);
119
- if (response.data) {
120
- const errorText = this.extractErrorMessage(response.data);
121
- if (errorText.trim().startsWith("<!DOCTYPE") || errorText.trim().startsWith("<html")) {
122
- await this.writeToFile("ERROR", ` Response Type: HTML Error Page`);
123
- const parsedError = this.parseHtmlError(errorText);
124
- if (parsedError) {
125
- await this.writeToFile("ERROR", ` Error Message: ${parsedError}`);
126
- }
127
- await this.writeToFile("ERROR", ` Raw HTML: ${this.truncate(errorText, 1e3)}`);
128
- } else {
129
- const preview = this.truncate(errorText, 500);
130
- await this.writeToFile("ERROR", ` Response: ${preview}`);
131
- }
132
- } else {
133
- await this.writeToFile("ERROR", ` Response: (no data)`);
134
- }
135
- }
136
- if (err && typeof err === "object" && "stack" in err && typeof err.stack === "string") {
137
- const stackLines = err.stack.split("\n").slice(0, 5).join("\n ");
138
- await this.writeToFile("ERROR", ` Stack: ${stackLines}`);
139
- } else if (err && typeof err === "object" && "message" in err && typeof err.message === "string") {
140
- await this.writeToFile("ERROR", ` Message: ${err.message}`);
141
- }
142
- } catch (error) {
143
- }
144
- }
145
- /**
146
- * Safely stringify object, handling circular references
147
- */
148
- safeStringify(obj) {
149
- try {
150
- return JSON.stringify(obj);
151
- } catch (error) {
152
- if (error instanceof Error && error.message.includes("circular")) {
153
- try {
154
- const seen = /* @__PURE__ */ new WeakSet();
155
- return JSON.stringify(obj, (key, value) => {
156
- if (typeof value === "object" && value !== null) {
157
- if (seen.has(value)) {
158
- return "[Circular]";
159
- }
160
- seen.add(value);
161
- }
162
- return value;
163
- });
164
- } catch {
165
- return "[Unable to stringify]";
166
- }
167
- }
168
- return "[Stringify error]";
169
- }
170
- }
171
- /**
172
- * Extract readable text from error response data
173
- */
174
- extractErrorMessage(data) {
175
- if (Buffer.isBuffer(data)) {
176
- return data.toString("utf-8");
177
- }
178
- if (typeof data === "string") {
179
- return data;
180
- }
181
- if (data && typeof data === "object" && "_readableState" in data && data._readableState && typeof data._readableState === "object" && "buffer" in data._readableState && Array.isArray(data._readableState.buffer) && data._readableState.buffer.length > 0) {
182
- const chunks = [];
183
- for (const chunk of data._readableState.buffer) {
184
- if (chunk && typeof chunk === "object" && "type" in chunk && chunk.type === "Buffer" && "data" in chunk && Array.isArray(chunk.data)) {
185
- chunks.push(Buffer.from(chunk.data));
186
- } else if (Buffer.isBuffer(chunk)) {
187
- chunks.push(chunk);
188
- } else if (chunk && typeof chunk === "object" && "data" in chunk) {
189
- if (Buffer.isBuffer(chunk.data)) {
190
- chunks.push(chunk.data);
191
- } else if (Array.isArray(chunk.data)) {
192
- chunks.push(Buffer.from(chunk.data));
193
- }
194
- }
195
- }
196
- if (chunks.length > 0) {
197
- return Buffer.concat(chunks).toString("utf-8");
198
- }
199
- }
200
- return this.safeStringify(data);
201
- }
202
- /**
203
- * Parse HTML error page to extract error message
204
- */
205
- parseHtmlError(html) {
206
- const titleMatch = html.match(/<title>(.*?)<\/title>/i);
207
- const h1Match = html.match(/<h1>(.*?)<\/h1>/i);
208
- const bodyMatch = html.match(/<body[^>]*>(.*?)<\/body>/is);
209
- if (titleMatch && titleMatch[1] !== "Error") {
210
- return titleMatch[1].trim();
211
- }
212
- if (h1Match) {
213
- return h1Match[1].trim();
214
- }
215
- if (bodyMatch) {
216
- const text = bodyMatch[1].replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
217
- return text.substring(0, 200);
218
- }
219
- return null;
220
- }
221
- /**
222
- * Truncate string to max length with ellipsis
223
- */
224
- truncate(str, maxLength) {
225
- if (str.length <= maxLength) {
226
- return str;
227
- }
228
- return str.substring(0, maxLength) + "... [truncated]";
229
- }
230
- /**
231
- * Format bytes to human-readable size
232
- */
233
- formatBytes(bytes) {
234
- if (bytes === 0) return "0 B";
235
- const k = 1024;
236
- const sizes = ["B", "KB", "MB", "GB"];
237
- const i = Math.floor(Math.log(bytes) / Math.log(k));
238
- return Math.round(bytes / Math.pow(k, i) * 100) / 100 + " " + sizes[i];
239
- }
240
- /**
241
- * Clean up old debug logs (older than 30 days)
242
- */
243
- async cleanupOldLogs() {
244
- if (!this.fileLoggingEnabled) return;
245
- try {
246
- const debugDir = path.join(os.homedir(), ".bike4mind", "debug");
247
- const files = await fs.readdir(debugDir);
248
- const now = Date.now();
249
- const thirtyDaysAgo = now - 30 * 24 * 60 * 60 * 1e3;
250
- for (const file of files) {
251
- const filePath = path.join(debugDir, file);
252
- const stats = await fs.stat(filePath);
253
- if (stats.mtime.getTime() < thirtyDaysAgo) {
254
- await fs.unlink(filePath);
255
- }
256
- }
257
- } catch (error) {
258
- console.error("Failed to cleanup old logs:", error);
259
- }
260
- }
261
- };
262
- var logger = Logger.getInstance();
263
- logger.setVerbose(process.env.B4M_VERBOSE === "1");
264
-
265
- // src/storage/ConfigStore.ts
266
- import { promises as fs2, existsSync } from "fs";
267
- import path2 from "path";
268
- import { homedir } from "os";
269
- import { v4 as uuidv4 } from "uuid";
270
- import { z } from "zod";
271
- var SandboxFilesystemSchema = z.object({
272
- allowedReadPaths: z.array(z.string()).default(DEFAULT_SANDBOX_CONFIG.filesystem.allowedReadPaths),
273
- deniedPaths: z.array(z.string()).default(DEFAULT_SANDBOX_CONFIG.filesystem.deniedPaths),
274
- writeOnlyToWorkingDir: z.boolean().default(true)
275
- });
276
- var SandboxNetworkSchema = z.object({
277
- enabled: z.boolean().default(false),
278
- allowedDomains: z.array(z.string()).default(DEFAULT_SANDBOX_CONFIG.network.allowedDomains)
279
- });
280
- var SandboxPlatformSchema = z.object({
281
- linux: z.object({
282
- runtime: z.literal("bubblewrap").default("bubblewrap"),
283
- seccompProfile: z.string().optional()
284
- }).default({ runtime: "bubblewrap" }),
285
- macos: z.object({
286
- runtime: z.literal("seatbelt").default("seatbelt"),
287
- profileTemplate: z.string().default("default")
288
- }).default({ runtime: "seatbelt", profileTemplate: "default" })
289
- });
290
- var SandboxConfigSchema = z.object({
291
- enabled: z.boolean().default(false),
292
- mode: z.enum(["disabled", "auto-allow", "permissions"]).default("disabled"),
293
- filesystem: SandboxFilesystemSchema.default(DEFAULT_SANDBOX_CONFIG.filesystem),
294
- network: SandboxNetworkSchema.default(DEFAULT_SANDBOX_CONFIG.network),
295
- excludedCommands: z.array(z.string()).default(DEFAULT_SANDBOX_CONFIG.excludedCommands),
296
- allowUnsandboxedCommands: z.boolean().default(true),
297
- platform: SandboxPlatformSchema.default(DEFAULT_SANDBOX_CONFIG.platform)
298
- }).refine(
299
- (config) => {
300
- if (config.enabled && config.mode === "disabled") return false;
301
- if (!config.enabled && config.mode !== "disabled") return false;
302
- return true;
303
- },
304
- {
305
- message: 'Sandbox config inconsistency: enabled and mode must agree. If enabled=true, mode must be "auto-allow" or "permissions". If mode="disabled", enabled must be false.'
306
- }
307
- );
308
- var PartialSandboxConfigSchema = z.object({
309
- enabled: z.boolean().optional(),
310
- mode: z.enum(["disabled", "auto-allow", "permissions"]).optional(),
311
- filesystem: z.object({
312
- allowedReadPaths: z.array(z.string()).optional(),
313
- deniedPaths: z.array(z.string()).optional(),
314
- writeOnlyToWorkingDir: z.boolean().optional()
315
- }).optional(),
316
- network: z.object({
317
- enabled: z.boolean().optional(),
318
- allowedDomains: z.array(z.string()).optional()
319
- }).optional(),
320
- excludedCommands: z.array(z.string()).optional(),
321
- allowUnsandboxedCommands: z.boolean().optional(),
322
- platform: SandboxPlatformSchema.optional()
323
- }).optional();
324
- var AuthTokensSchema = z.object({
325
- accessToken: z.string(),
326
- refreshToken: z.string(),
327
- expiresAt: z.string(),
328
- userId: z.string()
329
- });
330
- var ApiConfigSchema = z.object({
331
- customUrl: z.url().optional()
332
- });
333
- var McpServerSchema = z.object({
334
- name: z.string(),
335
- command: z.string().optional(),
336
- args: z.array(z.string()).optional(),
337
- env: z.record(z.string(), z.string()).prefault({}),
338
- enabled: z.boolean().prefault(true)
339
- });
340
- var McpServersSchema = z.union([
341
- // Array format (B4M native)
342
- z.array(McpServerSchema),
343
- // Object format (portable - compatible with Claude Code)
344
- z.record(
345
- z.string(),
346
- z.object({
347
- command: z.string().optional(),
348
- args: z.array(z.string()).optional(),
349
- env: z.record(z.string(), z.string()).optional(),
350
- enabled: z.boolean().optional()
351
- })
352
- )
353
- ]);
354
- function normalizeMcpServers(servers) {
355
- if (Array.isArray(servers)) {
356
- return servers.map((server) => ({
357
- name: server.name,
358
- command: server.command,
359
- args: server.args,
360
- env: server.env || {},
361
- enabled: server.enabled ?? true
362
- }));
363
- } else {
364
- return Object.entries(servers).map(([name, config]) => ({
365
- name,
366
- command: config.command,
367
- args: config.args,
368
- env: config.env || {},
369
- enabled: config.enabled ?? true
370
- }));
371
- }
372
- }
373
- var CliConfigSchema = z.object({
374
- version: z.string(),
375
- userId: z.string(),
376
- auth: AuthTokensSchema.optional(),
377
- defaultModel: z.string(),
378
- apiConfig: ApiConfigSchema.optional(),
379
- toolApiKeys: z.object({
380
- openweather: z.string().optional(),
381
- serper: z.string().optional()
382
- }).optional(),
383
- mcpServers: McpServersSchema,
384
- preferences: z.object({
385
- maxTokens: z.number(),
386
- temperature: z.number(),
387
- autoSave: z.boolean(),
388
- autoCompact: z.boolean().optional().prefault(true),
389
- theme: z.enum(["light", "dark"]),
390
- exportFormat: z.enum(["markdown", "json"]),
391
- maxIterations: z.number().nullable().prefault(10),
392
- enableSkillTool: z.boolean().optional().prefault(true),
393
- enableDynamicAgentCreation: z.boolean().optional().prefault(false)
394
- }),
395
- tools: z.object({
396
- enabled: z.array(z.string()),
397
- disabled: z.array(z.string()),
398
- config: z.record(z.string(), z.any())
399
- }),
400
- features: z.object({
401
- tavern: z.boolean().optional()
402
- }).optional().prefault({}),
403
- trustedTools: z.array(z.string()).optional().prefault([]),
404
- sandbox: SandboxConfigSchema.optional(),
405
- additionalDirectories: z.array(z.string()).optional().prefault([])
406
- });
407
- var ProjectConfigSchema = z.object({
408
- tools: z.object({
409
- enabled: z.array(z.string()).optional(),
410
- denied: z.array(z.string()).optional(),
411
- config: z.record(z.string(), z.any()).optional()
412
- }).optional(),
413
- defaultModel: z.string().optional(),
414
- mcpServers: McpServersSchema.optional(),
415
- preferences: z.object({
416
- maxTokens: z.number().optional(),
417
- temperature: z.number().optional(),
418
- autoSave: z.boolean().optional(),
419
- autoCompact: z.boolean().optional(),
420
- theme: z.enum(["light", "dark"]).optional(),
421
- exportFormat: z.enum(["markdown", "json"]).optional(),
422
- enableSkillTool: z.boolean().optional(),
423
- enableDynamicAgentCreation: z.boolean().optional()
424
- }).optional(),
425
- sandbox: PartialSandboxConfigSchema,
426
- additionalDirectories: z.array(z.string()).optional()
427
- });
428
- var ProjectLocalConfigSchema = z.object({
429
- trustedTools: z.array(z.string()).optional(),
430
- toolApiKeys: z.object({
431
- openweather: z.string().optional(),
432
- serper: z.string().optional()
433
- }).optional(),
434
- preferences: z.object({
435
- maxTokens: z.number().optional(),
436
- temperature: z.number().optional(),
437
- autoSave: z.boolean().optional(),
438
- autoCompact: z.boolean().optional(),
439
- theme: z.enum(["light", "dark"]).optional(),
440
- exportFormat: z.enum(["markdown", "json"]).optional(),
441
- enableSkillTool: z.boolean().optional(),
442
- enableDynamicAgentCreation: z.boolean().optional()
443
- }).optional(),
444
- mcpServers: McpServersSchema.optional(),
445
- sandbox: PartialSandboxConfigSchema
446
- });
447
- var DEFAULT_CONFIG = {
448
- version: "0.1.0",
449
- userId: uuidv4(),
450
- defaultModel: ChatModels.CLAUDE_4_5_SONNET,
451
- toolApiKeys: {
452
- openweather: void 0,
453
- serper: void 0
454
- },
455
- mcpServers: [],
456
- preferences: {
457
- maxTokens: 4096,
458
- temperature: 0.7,
459
- autoSave: true,
460
- autoCompact: true,
461
- theme: "dark",
462
- exportFormat: "markdown",
463
- maxIterations: 10,
464
- enableSkillTool: true,
465
- enableDynamicAgentCreation: false
466
- },
467
- tools: {
468
- enabled: [],
469
- disabled: ["blog_publish", "blog_edit", "blog_draft"],
470
- // Web-only tools
471
- config: {}
472
- },
473
- trustedTools: [],
474
- // No tools trusted by default
475
- additionalDirectories: []
476
- // No additional directories by default
477
- };
478
- function findProjectConfigDir(startDir = process.cwd()) {
479
- let currentDir = startDir;
480
- const { root } = path2.parse(currentDir);
481
- while (currentDir !== root) {
482
- const gitPath = path2.join(currentDir, ".git");
483
- try {
484
- if (existsSync(gitPath)) {
485
- return currentDir;
486
- }
487
- } catch {
488
- }
489
- currentDir = path2.dirname(currentDir);
490
- }
491
- return process.cwd();
492
- }
493
- async function loadProjectConfig(projectDir) {
494
- const configPath = path2.join(projectDir, ".bike4mind", "config.json");
495
- try {
496
- const data = await fs2.readFile(configPath, "utf-8");
497
- const rawConfig = JSON.parse(data);
498
- const validated = ProjectConfigSchema.parse(rawConfig);
499
- const result = {
500
- ...validated,
501
- mcpServers: validated.mcpServers ? normalizeMcpServers(validated.mcpServers) : void 0
502
- };
503
- return result;
504
- } catch (error) {
505
- if (error.code === "ENOENT") {
506
- return null;
507
- }
508
- if (error instanceof z.ZodError) {
509
- console.error("Project config validation error:", error.issues);
510
- return null;
511
- }
512
- console.error("Failed to load project config:", error);
513
- return null;
514
- }
515
- }
516
- async function loadProjectLocalConfig(projectDir) {
517
- const configPath = path2.join(projectDir, ".bike4mind", "local.json");
518
- try {
519
- const data = await fs2.readFile(configPath, "utf-8");
520
- const rawConfig = JSON.parse(data);
521
- const validated = ProjectLocalConfigSchema.parse(rawConfig);
522
- const result = {
523
- ...validated,
524
- mcpServers: validated.mcpServers ? normalizeMcpServers(validated.mcpServers) : void 0
525
- };
526
- return result;
527
- } catch (error) {
528
- if (error.code === "ENOENT") {
529
- return null;
530
- }
531
- if (error instanceof z.ZodError) {
532
- console.error("Project local config validation error:", error.issues);
533
- return null;
534
- }
535
- console.error("Failed to load project local config:", error);
536
- return null;
537
- }
538
- }
539
- var McpJsonConfigSchema = z.object({
540
- mcpServers: McpServersSchema
541
- });
542
- async function loadMcpJsonConfig(projectDir) {
543
- const mcpConfigPath = path2.join(projectDir, ".mcp.json");
544
- try {
545
- const data = await fs2.readFile(mcpConfigPath, "utf-8");
546
- const rawConfig = JSON.parse(data);
547
- const validated = McpJsonConfigSchema.parse(rawConfig);
548
- const servers = normalizeMcpServers(validated.mcpServers);
549
- return servers;
550
- } catch (error) {
551
- if (error.code === "ENOENT") {
552
- return null;
553
- }
554
- if (error instanceof z.ZodError) {
555
- console.error(".mcp.json validation error:", error.issues);
556
- return null;
557
- }
558
- console.error("Failed to load .mcp.json:", error);
559
- return null;
560
- }
561
- }
562
- function mergeMcpServers(...serverArrays) {
563
- const serverMap = /* @__PURE__ */ new Map();
564
- for (const servers of serverArrays) {
565
- if (servers) {
566
- for (const server of servers) {
567
- serverMap.set(server.name, server);
568
- }
569
- }
570
- }
571
- return Array.from(serverMap.values());
572
- }
573
- function mergeSandboxConfig(base, override) {
574
- const resolved = base ?? DEFAULT_SANDBOX_CONFIG;
575
- if (!override) return resolved;
576
- return {
577
- enabled: override.enabled ?? resolved.enabled,
578
- mode: override.mode ?? resolved.mode,
579
- filesystem: {
580
- ...resolved.filesystem,
581
- ...override.filesystem ?? {}
582
- },
583
- network: {
584
- ...resolved.network,
585
- ...override.network ?? {}
586
- },
587
- excludedCommands: override.excludedCommands ?? resolved.excludedCommands,
588
- allowUnsandboxedCommands: override.allowUnsandboxedCommands ?? resolved.allowUnsandboxedCommands,
589
- platform: override.platform ?? resolved.platform
590
- };
591
- }
592
- function mergeConfigs(global, project, local) {
593
- const merged = { ...global };
594
- if (project) {
595
- if (project.defaultModel) {
596
- merged.defaultModel = project.defaultModel;
597
- }
598
- if (project.preferences) {
599
- merged.preferences = {
600
- ...merged.preferences,
601
- ...project.preferences
602
- };
603
- }
604
- if (project.tools) {
605
- merged.tools = {
606
- ...merged.tools,
607
- enabled: [...merged.tools.enabled || [], ...project.tools.enabled || []],
608
- disabled: [...merged.tools.disabled, ...project.tools.denied || []],
609
- config: {
610
- ...merged.tools.config,
611
- ...project.tools.config
612
- }
613
- };
614
- }
615
- if (project.mcpServers) {
616
- merged.mcpServers = mergeMcpServers(merged.mcpServers, project.mcpServers);
617
- }
618
- if (project.sandbox) {
619
- merged.sandbox = mergeSandboxConfig(merged.sandbox, project.sandbox);
620
- }
621
- }
622
- if (local) {
623
- if (local.trustedTools) {
624
- const trustedSet = /* @__PURE__ */ new Set([...merged.trustedTools || [], ...local.trustedTools]);
625
- merged.trustedTools = Array.from(trustedSet);
626
- }
627
- if (local.toolApiKeys) {
628
- merged.toolApiKeys = {
629
- ...merged.toolApiKeys,
630
- ...local.toolApiKeys
631
- };
632
- }
633
- if (local.preferences) {
634
- merged.preferences = {
635
- ...merged.preferences,
636
- ...local.preferences
637
- };
638
- }
639
- if (local.mcpServers) {
640
- merged.mcpServers = mergeMcpServers(merged.mcpServers, local.mcpServers);
641
- }
642
- if (local.sandbox) {
643
- merged.sandbox = mergeSandboxConfig(merged.sandbox, local.sandbox);
644
- }
645
- }
646
- return merged;
647
- }
648
- var ConfigStore = class {
649
- constructor(configPath) {
650
- this.config = null;
651
- this.projectConfigDir = null;
652
- this.configPath = configPath || path2.join(homedir(), ".bike4mind", "config.json");
653
- }
654
- /**
655
- * Initialize config directory
656
- */
657
- async init() {
658
- const dir = path2.dirname(this.configPath);
659
- try {
660
- await fs2.mkdir(dir, { recursive: true });
661
- } catch (error) {
662
- console.error("Failed to initialize config directory:", error);
663
- throw error;
664
- }
665
- }
666
- /**
667
- * Load configuration from disk with Zod validation
668
- * Merges global → project → local configs
669
- */
670
- async load() {
671
- if (this.config) {
672
- return this.config;
673
- }
674
- try {
675
- let globalConfig;
676
- try {
677
- try {
678
- const stats = await fs2.stat(this.configPath);
679
- const mode = stats.mode & 511;
680
- if (mode !== 384) {
681
- console.warn(`\u26A0\uFE0F Config file has insecure permissions (${mode.toString(8)}). Setting to 0600...`);
682
- await fs2.chmod(this.configPath, 384);
683
- }
684
- } catch (statError) {
685
- }
686
- const data = await fs2.readFile(this.configPath, "utf-8");
687
- const rawConfig = JSON.parse(data);
688
- if (rawConfig.apiConfig && "environment" in rawConfig.apiConfig) {
689
- const oldApiConfig = rawConfig.apiConfig;
690
- if (oldApiConfig.environment === "custom" && oldApiConfig.customUrl) {
691
- rawConfig.apiConfig = { customUrl: oldApiConfig.customUrl };
692
- } else {
693
- rawConfig.apiConfig = {};
694
- }
695
- }
696
- const validated = CliConfigSchema.parse(rawConfig);
697
- const normalizedMcpServers = normalizeMcpServers(validated.mcpServers);
698
- globalConfig = {
699
- ...DEFAULT_CONFIG,
700
- ...validated,
701
- auth: validated.auth,
702
- // Explicitly preserve auth field
703
- mcpServers: normalizedMcpServers,
704
- preferences: {
705
- ...DEFAULT_CONFIG.preferences,
706
- ...validated.preferences
707
- },
708
- tools: {
709
- ...DEFAULT_CONFIG.tools,
710
- ...validated.tools
711
- },
712
- toolApiKeys: {
713
- ...DEFAULT_CONFIG.toolApiKeys,
714
- ...validated.toolApiKeys || {}
715
- },
716
- trustedTools: validated.trustedTools || []
717
- };
718
- } catch (error) {
719
- if (error.code === "ENOENT") {
720
- globalConfig = { ...DEFAULT_CONFIG };
721
- } else if (error instanceof z.ZodError) {
722
- console.error("Global config validation error:", error.issues);
723
- console.error("Using default configuration");
724
- globalConfig = { ...DEFAULT_CONFIG };
725
- } else {
726
- throw error;
727
- }
728
- }
729
- let projectConfig = null;
730
- let projectLocalConfig = null;
731
- let mcpJsonServers = null;
732
- if (process.env.B4M_NO_PROJECT_CONFIG !== "1") {
733
- this.projectConfigDir = findProjectConfigDir();
734
- if (this.projectConfigDir) {
735
- projectConfig = await loadProjectConfig(this.projectConfigDir);
736
- projectLocalConfig = await loadProjectLocalConfig(this.projectConfigDir);
737
- mcpJsonServers = await loadMcpJsonConfig(this.projectConfigDir);
738
- if (projectConfig) {
739
- logger.debug(`\u{1F4C1} Project config loaded from: ${this.projectConfigDir}/.bike4mind/`);
740
- }
741
- if (mcpJsonServers && mcpJsonServers.length > 0) {
742
- logger.debug(`\u{1F4C1} Project MCP config loaded from: ${this.projectConfigDir}/.mcp.json`);
743
- }
744
- }
745
- } else {
746
- this.projectConfigDir = null;
747
- }
748
- const mergedConfig = mergeConfigs(globalConfig, projectConfig, projectLocalConfig);
749
- if (mcpJsonServers && mcpJsonServers.length > 0) {
750
- mergedConfig.mcpServers = mergeMcpServers(mcpJsonServers, mergedConfig.mcpServers);
751
- }
752
- this.config = mergedConfig;
753
- return this.config;
754
- } catch (error) {
755
- if (error.code === "ENOENT") {
756
- return this.reset();
757
- }
758
- if (error instanceof z.ZodError) {
759
- console.error("Config validation error:", error.issues);
760
- console.error("Resetting to default configuration");
761
- return this.reset();
762
- }
763
- console.error("Failed to load config:", error);
764
- throw error;
765
- }
766
- }
767
- /**
768
- * Save configuration to disk
769
- */
770
- async save(config) {
771
- await this.init();
772
- if (config) {
773
- const existingConfig = await this.load();
774
- this.config = {
775
- ...existingConfig,
776
- ...config,
777
- auth: config.auth !== void 0 ? config.auth : existingConfig.auth,
778
- preferences: {
779
- ...existingConfig.preferences,
780
- ...config.preferences || {}
781
- },
782
- tools: {
783
- ...existingConfig.tools,
784
- ...config.tools || {}
785
- },
786
- toolApiKeys: {
787
- ...existingConfig.toolApiKeys,
788
- ...config.toolApiKeys || {}
789
- }
790
- };
791
- }
792
- if (!this.config) {
793
- throw new Error("No configuration to save");
794
- }
795
- try {
796
- await fs2.writeFile(this.configPath, JSON.stringify(this.config, null, 2), "utf-8");
797
- await fs2.chmod(this.configPath, 384);
798
- } catch (error) {
799
- console.error("Failed to save config:", error);
800
- throw error;
801
- }
802
- }
803
- /**
804
- * Reset configuration to defaults
805
- */
806
- async reset() {
807
- this.config = { ...DEFAULT_CONFIG, userId: uuidv4() };
808
- await this.save();
809
- return this.config;
810
- }
811
- /**
812
- * Get current configuration
813
- */
814
- async get() {
815
- return this.load();
816
- }
817
- /**
818
- * Update a specific configuration value
819
- */
820
- async update(updates) {
821
- await this.save(updates);
822
- }
823
- /**
824
- * Add MCP server configuration
825
- */
826
- async addMcpServer(server) {
827
- const config = await this.load();
828
- config.mcpServers = config.mcpServers.filter((s) => s.name !== server.name);
829
- config.mcpServers.push(server);
830
- await this.save(config);
831
- }
832
- /**
833
- * Remove MCP server configuration
834
- */
835
- async removeMcpServer(name) {
836
- const config = await this.load();
837
- config.mcpServers = config.mcpServers.filter((s) => s.name !== name);
838
- await this.save(config);
839
- }
840
- /**
841
- * Enable/disable MCP server
842
- */
843
- async toggleMcpServer(name, enabled) {
844
- const config = await this.load();
845
- const server = config.mcpServers.find((s) => s.name === name);
846
- if (server) {
847
- server.enabled = enabled;
848
- await this.save(config);
849
- }
850
- }
851
- /**
852
- * Add a tool to trusted tools list
853
- */
854
- async trustTool(toolName) {
855
- const config = await this.load();
856
- if (!config.trustedTools) {
857
- config.trustedTools = [];
858
- }
859
- if (!config.trustedTools.includes(toolName)) {
860
- config.trustedTools.push(toolName);
861
- await this.save(config);
862
- }
863
- }
864
- /**
865
- * Remove a tool from trusted tools list
866
- */
867
- async untrustTool(toolName) {
868
- const config = await this.load();
869
- if (config.trustedTools) {
870
- config.trustedTools = config.trustedTools.filter((t) => t !== toolName);
871
- await this.save(config);
872
- }
873
- }
874
- /**
875
- * Get list of trusted tools
876
- */
877
- async getTrustedTools() {
878
- const config = await this.load();
879
- return config.trustedTools || [];
880
- }
881
- /**
882
- * Clear all trusted tools
883
- */
884
- async clearTrustedTools() {
885
- const config = await this.load();
886
- config.trustedTools = [];
887
- await this.save(config);
888
- }
889
- /**
890
- * Get authentication tokens
891
- */
892
- async getAuthTokens() {
893
- const config = await this.load();
894
- return config.auth || null;
895
- }
896
- /**
897
- * Set authentication tokens
898
- */
899
- async setAuthTokens(tokens) {
900
- const config = await this.load();
901
- config.auth = tokens;
902
- await this.save(config);
903
- }
904
- /**
905
- * Clear authentication tokens (logout)
906
- */
907
- async clearAuthTokens() {
908
- const config = await this.load();
909
- config.auth = void 0;
910
- await this.save(config);
911
- }
912
- /**
913
- * Check if user is authenticated
914
- */
915
- async isAuthenticated() {
916
- const tokens = await this.getAuthTokens();
917
- if (!tokens) return false;
918
- const expiresAt = new Date(tokens.expiresAt);
919
- return expiresAt > /* @__PURE__ */ new Date();
920
- }
921
- /**
922
- * Get API configuration
923
- */
924
- async getApiConfig() {
925
- const config = await this.load();
926
- return config.apiConfig;
927
- }
928
- /**
929
- * Set custom API URL for self-hosted Bike4Mind instance
930
- * Pass null to reset to Bike4Mind main service
931
- */
932
- async setCustomApiUrl(url) {
933
- const config = await this.load();
934
- if (url === null) {
935
- config.apiConfig = void 0;
936
- } else {
937
- config.apiConfig = { customUrl: url };
938
- }
939
- await this.save(config);
940
- }
941
- /**
942
- * Get project config directory (if any)
943
- */
944
- getProjectConfigDir() {
945
- return this.projectConfigDir;
946
- }
947
- /**
948
- * Initialize project config directory
949
- * Creates .bike4mind/ directory and ensures local.json is gitignored
950
- * Does NOT auto-create config.json (user creates that manually)
951
- */
952
- async initProjectConfig() {
953
- const projectDir = this.projectConfigDir || findProjectConfigDir();
954
- if (!projectDir) {
955
- return;
956
- }
957
- const configDir = path2.join(projectDir, ".bike4mind");
958
- await fs2.mkdir(configDir, { recursive: true });
959
- await this.ensureGitignore(projectDir);
960
- }
961
- /**
962
- * Ensure .gitignore includes .bike4mind/local.json
963
- */
964
- async ensureGitignore(projectDir) {
965
- const gitignorePath = path2.join(projectDir, ".gitignore");
966
- const entryToAdd = ".bike4mind/local.json";
967
- try {
968
- let gitignoreContent = "";
969
- try {
970
- gitignoreContent = await fs2.readFile(gitignorePath, "utf-8");
971
- } catch {
972
- }
973
- if (gitignoreContent.includes(entryToAdd)) {
974
- return;
975
- }
976
- const newContent = gitignoreContent.trim() + (gitignoreContent ? "\n" : "") + `
977
- # Bike4Mind local config (developer-specific)
978
- ${entryToAdd}
979
- `;
980
- await fs2.writeFile(gitignorePath, newContent, "utf-8");
981
- console.log(`\u2705 Added ${entryToAdd} to .gitignore`);
982
- } catch (error) {
983
- console.warn(`\u26A0\uFE0F Failed to update .gitignore:`, error);
984
- }
985
- }
986
- /**
987
- * Save project config to .bike4mind/config.json
988
- */
989
- async saveProjectConfig(config, projectDir) {
990
- const targetDir = projectDir || this.projectConfigDir || process.cwd();
991
- const configPath = path2.join(targetDir, ".bike4mind", "config.json");
992
- await fs2.mkdir(path2.dirname(configPath), { recursive: true });
993
- const validated = ProjectConfigSchema.parse(config);
994
- await fs2.writeFile(configPath, JSON.stringify(validated, null, 2), "utf-8");
995
- console.log(`\u2705 Saved project config to: ${configPath}`);
996
- }
997
- /**
998
- * Save project-local config to .bike4mind/local.json
999
- */
1000
- async saveProjectLocalConfig(config, projectDir) {
1001
- const targetDir = projectDir || this.projectConfigDir || process.cwd();
1002
- const configPath = path2.join(targetDir, ".bike4mind", "local.json");
1003
- await fs2.mkdir(path2.dirname(configPath), { recursive: true });
1004
- const validated = ProjectLocalConfigSchema.parse(config);
1005
- await fs2.writeFile(configPath, JSON.stringify(validated, null, 2), "utf-8");
1006
- await fs2.chmod(configPath, 384);
1007
- console.log(`\u2705 Saved project-local config to: ${configPath}`);
1008
- }
1009
- /**
1010
- * Load raw project config (without merging)
1011
- */
1012
- async loadRawProjectConfig() {
1013
- if (!this.projectConfigDir) {
1014
- return null;
1015
- }
1016
- return loadProjectConfig(this.projectConfigDir);
1017
- }
1018
- /**
1019
- * Load raw project-local config (without merging)
1020
- */
1021
- async loadRawProjectLocalConfig() {
1022
- if (!this.projectConfigDir) {
1023
- return null;
1024
- }
1025
- return loadProjectLocalConfig(this.projectConfigDir);
1026
- }
1027
- /**
1028
- * Add a directory to the allowed directories list
1029
- * Persists to global config
1030
- */
1031
- async addDirectory(dirPath) {
1032
- const config = await this.load();
1033
- if (!config.additionalDirectories) {
1034
- config.additionalDirectories = [];
1035
- }
1036
- const resolvedPath = path2.resolve(dirPath);
1037
- if (!config.additionalDirectories.includes(resolvedPath)) {
1038
- config.additionalDirectories.push(resolvedPath);
1039
- await this.save(config);
1040
- }
1041
- }
1042
- /**
1043
- * Remove a directory from the allowed directories list
1044
- */
1045
- async removeDirectory(dirPath) {
1046
- const config = await this.load();
1047
- if (config.additionalDirectories) {
1048
- const resolvedPath = path2.resolve(dirPath);
1049
- config.additionalDirectories = config.additionalDirectories.filter((d) => path2.resolve(d) !== resolvedPath);
1050
- await this.save(config);
1051
- }
1052
- }
1053
- /**
1054
- * Get all additional directories (merged from global + project configs)
1055
- * Returns resolved absolute paths
1056
- */
1057
- async getAdditionalDirectories() {
1058
- const config = await this.load();
1059
- const dirs = /* @__PURE__ */ new Set();
1060
- if (config.additionalDirectories) {
1061
- for (const dir of config.additionalDirectories) {
1062
- dirs.add(path2.resolve(dir));
1063
- }
1064
- }
1065
- const projectConfig = await this.loadRawProjectConfig();
1066
- if (projectConfig?.additionalDirectories) {
1067
- const projectRoot = this.projectConfigDir || process.cwd();
1068
- for (const dir of projectConfig.additionalDirectories) {
1069
- dirs.add(path2.resolve(projectRoot, dir));
1070
- }
1071
- }
1072
- return Array.from(dirs);
1073
- }
1074
- };
1075
-
1076
- export {
1077
- logger,
1078
- ConfigStore
1079
- };